summaryrefslogtreecommitdiff
path: root/test/rdoc/test_rdoc_token_stream.rb
blob: c946d0f1ef628cbbe9e76d45adb1a47fd7407fd5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# frozen_string_literal: true
require 'minitest_helper'

class TestRDocTokenStream < RDoc::TestCase

  def test_class_to_html
    tokens = [
      { :line_no => 0, :char_no => 0, :kind => :on_const, :text => 'CONSTANT' },
      { :line_no => 0, :char_no => 0, :kind => :on_kw, :text => 'KW' },
      { :line_no => 0, :char_no => 0, :kind => :on_ivar, :text => 'IVAR' },
      { :line_no => 0, :char_no => 0, :kind => :on_op, :text => 'Op' },
      { :line_no => 0, :char_no => 0, :kind => :on_ident, :text => 'Id' },
      { :line_no => 0, :char_no => 0, :kind => :on_backref, :text => 'Node' },
      { :line_no => 0, :char_no => 0, :kind => :on_comment, :text => 'COMMENT' },
      { :line_no => 0, :char_no => 0, :kind => :on_regexp, :text => 'REGEXP' },
      { :line_no => 0, :char_no => 0, :kind => :on_tstring, :text => 'STRING' },
      { :line_no => 0, :char_no => 0, :kind => :on_int, :text => 'Val' },
      { :line_no => 0, :char_no => 0, :kind => :on_unknown, :text => '\\' }
    ]

    expected = [
      '<span class="ruby-constant">CONSTANT</span>',
      '<span class="ruby-keyword">KW</span>',
      '<span class="ruby-ivar">IVAR</span>',
      '<span class="ruby-operator">Op</span>',
      '<span class="ruby-identifier">Id</span>',
      '<span class="ruby-node">Node</span>',
      '<span class="ruby-comment">COMMENT</span>',
      '<span class="ruby-regexp">REGEXP</span>',
      '<span class="ruby-string">STRING</span>',
      '<span class="ruby-value">Val</span>',
      '\\'
    ].join

    assert_equal expected, RDoc::TokenStream.to_html(tokens)
  end

  def test_class_to_html_empty
    assert_equal '', RDoc::TokenStream.to_html([])
  end

  def test_tokens_to_s
    foo = Class.new do
      include RDoc::TokenStream

      def initialize
        @token_stream = [
          { line_no: 0, char_no: 0, kind: :on_ident,   text: "foo" },
          { line_no: 0, char_no: 0, kind: :on_sp,      text: " " },
          { line_no: 0, char_no: 0, kind: :on_tstring, text: "'bar'" },
        ]
      end
    end.new

    assert_equal "foo 'bar'", foo.tokens_to_s
  end
end

s='add' style='width: 16.7%;'/> -rw-r--r--bcc32/Makefile.sub89
-rwxr-xr-xbcc32/configure.bat92
-rwxr-xr-x[-rw-r--r--]bcc32/mkexports.rb2
-rw-r--r--bcc32/setup.mak80
-rw-r--r--bignum.c568
-rw-r--r--bin/irb4
-rw-r--r--bin/rdoc2
-rw-r--r--class.c57
-rw-r--r--common.mk261
-rw-r--r--compar.c4
-rw-r--r--configure.in440
-rw-r--r--defines.h53
-rw-r--r--dir.c1346
-rw-r--r--dln.c119
-rw-r--r--dln.h4
-rw-r--r--doc/NEWS-1.8.0 (renamed from doc/NEWS)0
-rw-r--r--doc/forwardable.rd4
-rw-r--r--doc/forwardable.rd.ja4
-rw-r--r--doc/irb/irb-tools.rd.ja4
-rw-r--r--doc/irb/irb.rd4
-rw-r--r--doc/irb/irb.rd.ja4
-rw-r--r--doc/shell.rd4
-rw-r--r--doc/shell.rd.ja4
-rw-r--r--enum.c1250
-rw-r--r--enumerator.c450
-rw-r--r--env.h4
-rw-r--r--error.c47
-rw-r--r--eval.c1499
-rw-r--r--ext/Setup1
-rw-r--r--ext/Setup.atheos1
-rw-r--r--ext/Setup.dj1
-rw-r--r--ext/Setup.emx1
-rw-r--r--ext/Setup.nt1
-rw-r--r--ext/Setup.x681
-rw-r--r--ext/Win32API/Win32API.c2
-rw-r--r--ext/Win32API/lib/win32/registry.rb2
-rw-r--r--ext/Win32API/lib/win32/resolv.rb2
-rw-r--r--ext/bigdecimal/bigdecimal.c177
-rw-r--r--ext/bigdecimal/bigdecimal.h12
-rw-r--r--ext/bigdecimal/bigdecimal_en.html9
-rw-r--r--ext/bigdecimal/bigdecimal_ja.html7
-rw-r--r--ext/bigdecimal/extconf.rb8
-rw-r--r--ext/curses/curses.c3
-rw-r--r--ext/curses/extconf.rb2
-rw-r--r--ext/dbm/dbm.c6
-rw-r--r--ext/dbm/extconf.rb60
-rw-r--r--ext/digest/bubblebabble/.cvsignore (renamed from ext/enumerator/.cvsignore)1
-rw-r--r--ext/digest/bubblebabble/bubblebabble.c142
-rw-r--r--ext/digest/bubblebabble/depend3
-rw-r--r--ext/digest/bubblebabble/extconf.rb6
-rw-r--r--ext/digest/defs.h10
-rw-r--r--ext/digest/digest.c698
-rw-r--r--ext/digest/digest.h30
-rw-r--r--ext/digest/digest.txt113
-rw-r--r--ext/digest/digest.txt.ja111
-rw-r--r--ext/digest/extconf.rb6
-rw-r--r--ext/digest/lib/digest.rb50
-rw-r--r--ext/digest/lib/md5.rb19
-rw-r--r--ext/digest/lib/sha1.rb19
-rw-r--r--ext/digest/md5/extconf.rb4
-rw-r--r--ext/digest/md5/md5.c28
-rw-r--r--ext/digest/md5/md5.h11
-rw-r--r--ext/digest/md5/md5init.c25
-rw-r--r--ext/digest/md5/md5ossl.c25
-rw-r--r--ext/digest/md5/md5ossl.h7
-rw-r--r--ext/digest/rmd160/depend2
-rw-r--r--ext/digest/rmd160/extconf.rb6
-rw-r--r--ext/digest/rmd160/rmd160.c11
-rw-r--r--ext/digest/rmd160/rmd160.h18
-rw-r--r--ext/digest/rmd160/rmd160hl.c96
-rw-r--r--ext/digest/rmd160/rmd160init.c28
-rw-r--r--ext/digest/rmd160/rmd160ossl.c43
-rw-r--r--ext/digest/rmd160/rmd160ossl.h6
-rw-r--r--ext/digest/sha1/depend2
-rw-r--r--ext/digest/sha1/extconf.rb6
-rw-r--r--ext/digest/sha1/sha1.c24
-rw-r--r--ext/digest/sha1/sha1.h19
-rw-r--r--ext/digest/sha1/sha1hl.c102
-rw-r--r--ext/digest/sha1/sha1init.c32
-rw-r--r--ext/digest/sha1/sha1ossl.c43
-rw-r--r--ext/digest/sha1/sha1ossl.h9
-rw-r--r--ext/digest/sha2/depend2
-rw-r--r--ext/digest/sha2/extconf.rb5
-rw-r--r--ext/digest/sha2/lib/sha2.rb73
-rw-r--r--ext/digest/sha2/sha2.c26
-rw-r--r--ext/digest/sha2/sha2.h38
-rw-r--r--ext/digest/sha2/sha2hl.c252
-rw-r--r--ext/digest/sha2/sha2init.c25
-rw-r--r--ext/digest/test.sh7
-rw-r--r--ext/dl/dl.c18
-rw-r--r--ext/dl/dl.h2
-rw-r--r--ext/dl/h2rb2
-rw-r--r--ext/dl/handle.c6
-rw-r--r--ext/dl/lib/dl/import.rb4
-rw-r--r--ext/dl/ptr.c45
-rw-r--r--ext/dl/sym.c5
-rw-r--r--ext/enumerator/enumerator.c298
-rw-r--r--ext/enumerator/enumerator.txt102
-rw-r--r--ext/enumerator/extconf.rb2
-rw-r--r--ext/etc/etc.c6
-rw-r--r--ext/extmk.rb165
-rw-r--r--ext/fcntl/fcntl.c2
-rw-r--r--ext/gdbm/gdbm.c418
-rw-r--r--ext/iconv/iconv.c65
-rw-r--r--ext/io/wait/extconf.rb2
-rw-r--r--ext/io/wait/wait.c8
-rw-r--r--ext/nkf/lib/kconv.rb10
-rw-r--r--ext/nkf/nkf-utf8/nkf.c1103
-rw-r--r--ext/nkf/nkf-utf8/utf8tbl.c2
-rw-r--r--ext/nkf/nkf.c14
-rw-r--r--ext/openssl/extconf.rb11
-rw-r--r--ext/openssl/lib/net/ftptls.rb14
-rw-r--r--ext/openssl/lib/net/telnets.rb7
-rw-r--r--ext/openssl/lib/openssl.rb5
-rw-r--r--ext/openssl/lib/openssl/bn.rb4
-rw-r--r--ext/openssl/lib/openssl/buffering.rb4
-rw-r--r--ext/openssl/lib/openssl/cipher.rb37
-rw-r--r--ext/openssl/lib/openssl/digest.rb18
-rw-r--r--ext/openssl/lib/openssl/pkcs7.rb25
-rw-r--r--ext/openssl/lib/openssl/ssl.rb94
-rw-r--r--ext/openssl/lib/openssl/x509.rb4
-rw-r--r--ext/openssl/openssl_missing.c14
-rw-r--r--ext/openssl/openssl_missing.h62
-rw-r--r--ext/openssl/ossl.c34
-rw-r--r--ext/openssl/ossl.h44
-rw-r--r--ext/openssl/ossl_asn1.c66
-rw-r--r--ext/openssl/ossl_asn1.h2
-rw-r--r--ext/openssl/ossl_bio.c25
-rw-r--r--ext/openssl/ossl_bio.h2
-rw-r--r--ext/openssl/ossl_bn.c169
-rw-r--r--ext/openssl/ossl_bn.h7
-rw-r--r--ext/openssl/ossl_cipher.c251
-rw-r--r--ext/openssl/ossl_cipher.h3
-rw-r--r--ext/openssl/ossl_config.c19
-rw-r--r--ext/openssl/ossl_config.h2
-rw-r--r--ext/openssl/ossl_digest.c201
-rw-r--r--ext/openssl/ossl_digest.h3
-rw-r--r--ext/openssl/ossl_engine.c12
-rw-r--r--ext/openssl/ossl_engine.h2
-rw-r--r--ext/openssl/ossl_hmac.c74
-rw-r--r--ext/openssl/ossl_hmac.h2
-rw-r--r--ext/openssl/ossl_ns_spki.c15
-rw-r--r--ext/openssl/ossl_ns_spki.h2
-rw-r--r--ext/openssl/ossl_ocsp.c28
-rw-r--r--ext/openssl/ossl_ocsp.h2
-rw-r--r--ext/openssl/ossl_pkcs12.c78
-rw-r--r--ext/openssl/ossl_pkcs12.h3
-rw-r--r--ext/openssl/ossl_pkcs5.c96
-rw-r--r--ext/openssl/ossl_pkcs5.h6
-rw-r--r--ext/openssl/ossl_pkcs7.c66
-rw-r--r--ext/openssl/ossl_pkcs7.h3
-rw-r--r--ext/openssl/ossl_pkey.c30
-rw-r--r--ext/openssl/ossl_pkey.h23
-rw-r--r--ext/openssl/ossl_pkey_dh.c108
-rw-r--r--ext/openssl/ossl_pkey_dsa.c99
-rw-r--r--ext/openssl/ossl_pkey_ec.c1582
-rw-r--r--ext/openssl/ossl_pkey_rsa.c126
-rw-r--r--ext/openssl/ossl_rand.c94
-rw-r--r--ext/openssl/ossl_rand.h2
-rw-r--r--ext/openssl/ossl_ssl.c651
-rw-r--r--ext/openssl/ossl_ssl.h17
-rw-r--r--ext/openssl/ossl_ssl_session.c298
-rw-r--r--ext/openssl/ossl_version.h2
-rw-r--r--ext/openssl/ossl_x509.c2
-rw-r--r--ext/openssl/ossl_x509.h2
-rw-r--r--ext/openssl/ossl_x509attr.c38
-rw-r--r--ext/openssl/ossl_x509cert.c111
-rw-r--r--ext/openssl/ossl_x509crl.c18
-rw-r--r--ext/openssl/ossl_x509ext.c26
-rw-r--r--ext/openssl/ossl_x509name.c48
-rw-r--r--ext/openssl/ossl_x509req.c12
-rw-r--r--ext/openssl/ossl_x509revoked.c10
-rw-r--r--ext/openssl/ossl_x509store.c19
-rw-r--r--ext/openssl/ruby_missing.h29
-rw-r--r--ext/pty/expect_sample.rb15
-rw-r--r--ext/pty/lib/expect.rb2
-rw-r--r--ext/pty/pty.c103
-rw-r--r--ext/purelib.rb10
-rw-r--r--ext/racc/cparse/cparse.c4
-rw-r--r--ext/racc/cparse/extconf.rb2
-rw-r--r--ext/readline/extconf.rb5
-rw-r--r--ext/readline/readline.c25
-rw-r--r--ext/sdbm/_sdbm.c6
-rw-r--r--ext/sdbm/init.c4
-rw-r--r--ext/socket/addrinfo.h5
-rw-r--r--ext/socket/extconf.rb8
-rw-r--r--ext/socket/getnameinfo.c5
-rw-r--r--ext/socket/socket.c190
-rw-r--r--ext/socket/sockport.h4
-rw-r--r--ext/stringio/README4
-rw-r--r--ext/stringio/stringio.c87
-rw-r--r--ext/strscan/strscan.c6
-rw-r--r--ext/syck/bytecode.c4
-rw-r--r--ext/syck/emitter.c4
-rw-r--r--ext/syck/handler.c4
-rw-r--r--ext/syck/implicit.c4
-rw-r--r--ext/syck/node.c4
-rw-r--r--ext/syck/rubyext.c20
-rw-r--r--ext/syck/syck.c4
-rw-r--r--ext/syck/syck.h6
-rw-r--r--ext/syck/token.c4
-rw-r--r--ext/syck/yaml2byte.c4
-rw-r--r--ext/syslog/extconf.rb2
-rw-r--r--ext/syslog/syslog.c5
-rw-r--r--ext/syslog/syslog.txt7
-rw-r--r--ext/syslog/test.rb2
-rw-r--r--ext/thread/extconf.rb9
-rw-r--r--ext/thread/lib/thread.rb5
-rw-r--r--ext/thread/thread.c1182
-rw-r--r--ext/tk/ChangeLog.tkextlib66
-rw-r--r--ext/tk/MANUAL_tcltklib.eng24
-rw-r--r--ext/tk/MANUAL_tcltklib.eucj22
-rw-r--r--ext/tk/README.1st13
-rw-r--r--ext/tk/README.tcltklib25
-rw-r--r--ext/tk/extconf.rb167
-rw-r--r--ext/tk/lib/multi-tk.rb200
-rw-r--r--ext/tk/lib/tcltk.rb2
-rw-r--r--ext/tk/lib/tk.rb1230
-rw-r--r--ext/tk/lib/tk/after.rb2
-rw-r--r--ext/tk/lib/tk/autoload.rb358
-rw-r--r--ext/tk/lib/tk/bindtag.rb83
-rw-r--r--ext/tk/lib/tk/button.rb5
-rw-r--r--ext/tk/lib/tk/canvas.rb60
-rw-r--r--ext/tk/lib/tk/canvastag.rb117
-rw-r--r--ext/tk/lib/tk/checkbutton.rb9
-rw-r--r--ext/tk/lib/tk/composite.rb70
-rw-r--r--ext/tk/lib/tk/encodedstr.rb84
-rw-r--r--ext/tk/lib/tk/entry.rb6
-rw-r--r--ext/tk/lib/tk/event.rb62
-rw-r--r--ext/tk/lib/tk/font.rb742
-rw-r--r--ext/tk/lib/tk/frame.rb5
-rw-r--r--ext/tk/lib/tk/grid.rb49
-rw-r--r--ext/tk/lib/tk/image.rb62
-rw-r--r--ext/tk/lib/tk/itemconfig.rb177
-rw-r--r--ext/tk/lib/tk/itemfont.rb33
-rw-r--r--ext/tk/lib/tk/label.rb5
-rw-r--r--ext/tk/lib/tk/labelframe.rb8
-rw-r--r--ext/tk/lib/tk/listbox.rb5
-rw-r--r--ext/tk/lib/tk/macpkg.rb9
-rw-r--r--ext/tk/lib/tk/menu.rb91
-rw-r--r--ext/tk/lib/tk/menubar.rb2
-rw-r--r--ext/tk/lib/tk/menuspec.rb26
-rw-r--r--ext/tk/lib/tk/message.rb5
-rw-r--r--ext/tk/lib/tk/msgcat.rb6
-rw-r--r--ext/tk/lib/tk/namespace.rb149
-rw-r--r--ext/tk/lib/tk/optiondb.rb16
-rw-r--r--ext/tk/lib/tk/pack.rb17
-rw-r--r--ext/tk/lib/tk/package.rb4
-rw-r--r--ext/tk/lib/tk/palette.rb2
-rw-r--r--ext/tk/lib/tk/panedwindow.rb32
-rw-r--r--ext/tk/lib/tk/radiobutton.rb9
-rw-r--r--ext/tk/lib/tk/root.rb37
-rw-r--r--ext/tk/lib/tk/scale.rb33
-rw-r--r--ext/tk/lib/tk/scrollable.rb11
-rw-r--r--ext/tk/lib/tk/scrollbar.rb65
-rw-r--r--ext/tk/lib/tk/scrollbox.rb7
-rw-r--r--ext/tk/lib/tk/spinbox.rb24
-rw-r--r--ext/tk/lib/tk/text.rb178
-rw-r--r--ext/tk/lib/tk/textimage.rb14
-rw-r--r--ext/tk/lib/tk/textmark.rb102
-rw-r--r--ext/tk/lib/tk/texttag.rb113
-rw-r--r--ext/tk/lib/tk/textwindow.rb13
-rw-r--r--ext/tk/lib/tk/timer.rb57
-rw-r--r--ext/tk/lib/tk/toplevel.rb13
-rw-r--r--ext/tk/lib/tk/ttk_selector.rb76
-rw-r--r--ext/tk/lib/tk/txtwin_abst.rb2
-rw-r--r--ext/tk/lib/tk/validation.rb25
-rw-r--r--ext/tk/lib/tk/variable.rb488
-rw-r--r--ext/tk/lib/tk/virtevent.rb77
-rw-r--r--ext/tk/lib/tk/winpkg.rb18
-rw-r--r--ext/tk/lib/tk/wm.rb476
-rw-r--r--ext/tk/lib/tkclass.rb2
-rw-r--r--ext/tk/lib/tkextlib/SUPPORT_STATUS42
-rw-r--r--ext/tk/lib/tkextlib/blt.rb4
-rw-r--r--ext/tk/lib/tkextlib/blt/bitmap.rb21
-rw-r--r--ext/tk/lib/tkextlib/blt/busy.rb2
-rw-r--r--ext/tk/lib/tkextlib/blt/component.rb452
-rw-r--r--ext/tk/lib/tkextlib/blt/container.rb20
-rw-r--r--ext/tk/lib/tkextlib/blt/dragdrop.rb54
-rw-r--r--ext/tk/lib/tkextlib/blt/eps.rb2
-rw-r--r--ext/tk/lib/tkextlib/blt/htext.rb1
-rw-r--r--ext/tk/lib/tkextlib/blt/table.rb119
-rw-r--r--ext/tk/lib/tkextlib/blt/tabset.rb81
-rw-r--r--ext/tk/lib/tkextlib/blt/ted.rb9
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/button.rb2
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/checkbutton.rb4
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/frame.rb2
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/label.rb2
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/radiobutton.rb4
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/scrollbar.rb2
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/toplevel.rb2
-rw-r--r--ext/tk/lib/tkextlib/blt/tree.rb341
-rw-r--r--ext/tk/lib/tkextlib/blt/treeview.rb228
-rw-r--r--ext/tk/lib/tkextlib/blt/unix_dnd.rb16
-rw-r--r--ext/tk/lib/tkextlib/blt/vector.rb37
-rw-r--r--ext/tk/lib/tkextlib/blt/watch.rb47
-rw-r--r--ext/tk/lib/tkextlib/bwidget/button.rb2
-rw-r--r--ext/tk/lib/tkextlib/bwidget/buttonbox.rb20
-rw-r--r--ext/tk/lib/tkextlib/bwidget/combobox.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/dialog.rb33
-rw-r--r--ext/tk/lib/tkextlib/bwidget/dynamichelp.rb7
-rw-r--r--ext/tk/lib/tkextlib/bwidget/entry.rb2
-rw-r--r--ext/tk/lib/tkextlib/bwidget/label.rb2
-rw-r--r--ext/tk/lib/tkextlib/bwidget/labelentry.rb2
-rw-r--r--ext/tk/lib/tkextlib/bwidget/labelframe.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/listbox.rb37
-rw-r--r--ext/tk/lib/tkextlib/bwidget/mainframe.rb48
-rw-r--r--ext/tk/lib/tkextlib/bwidget/messagedlg.rb16
-rw-r--r--ext/tk/lib/tkextlib/bwidget/notebook.rb24
-rw-r--r--ext/tk/lib/tkextlib/bwidget/pagesmanager.rb16
-rw-r--r--ext/tk/lib/tkextlib/bwidget/panedwindow.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/panelframe.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/progressdlg.rb4
-rw-r--r--ext/tk/lib/tkextlib/bwidget/scrollableframe.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/selectcolor.rb28
-rw-r--r--ext/tk/lib/tkextlib/bwidget/selectfont.rb7
-rw-r--r--ext/tk/lib/tkextlib/bwidget/spinbox.rb2
-rw-r--r--ext/tk/lib/tkextlib/bwidget/statusbar.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/titleframe.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/tree.rb37
-rw-r--r--ext/tk/lib/tkextlib/bwidget/widget.rb20
-rw-r--r--ext/tk/lib/tkextlib/itcl/incr_tcl.rb12
-rw-r--r--ext/tk/lib/tkextlib/itk/incr_tk.rb44
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/buttonbox.rb5
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/calendar.rb19
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/checkbox.rb23
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/dialogshell.rb5
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/entryfield.rb19
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/hierarchy.rb58
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/menubar.rb5
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/messagebox.rb5
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/notebook.rb16
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/panedwindow.rb5
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/radiobox.rb16
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb12
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb2
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb30
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/selectionbox.rb2
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb2
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/spinner.rb19
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb21
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/tabset.rb49
-rw-r--r--ext/tk/lib/tkextlib/tcllib/autoscroll.rb2
-rw-r--r--ext/tk/lib/tkextlib/tcllib/ctext.rb2
-rw-r--r--ext/tk/lib/tkextlib/tcllib/datefield.rb2
-rw-r--r--ext/tk/lib/tkextlib/tcllib/getstring.rb5
-rw-r--r--ext/tk/lib/tkextlib/tcllib/ico.rb6
-rw-r--r--ext/tk/lib/tkextlib/tcllib/ip_entry.rb2
-rw-r--r--ext/tk/lib/tkextlib/tcllib/plotchart.rb77
-rw-r--r--ext/tk/lib/tkextlib/tcllib/swaplist.rb5
-rw-r--r--ext/tk/lib/tkextlib/tcllib/tablelist.rb2
-rw-r--r--ext/tk/lib/tkextlib/tcllib/tablelist_core.rb16
-rw-r--r--ext/tk/lib/tkextlib/tcllib/tkpiechart.rb14
-rw-r--r--ext/tk/lib/tkextlib/tile.rb260
-rw-r--r--ext/tk/lib/tkextlib/tile/dialog.rb16
-rw-r--r--ext/tk/lib/tkextlib/tile/sizegrip.rb29
-rw-r--r--ext/tk/lib/tkextlib/tile/style.rb241
-rw-r--r--ext/tk/lib/tkextlib/tile/tbutton.rb7
-rw-r--r--ext/tk/lib/tkextlib/tile/tcheckbutton.rb8
-rw-r--r--ext/tk/lib/tkextlib/tile/tcombobox.rb9
-rw-r--r--ext/tk/lib/tkextlib/tile/tentry.rb12
-rw-r--r--ext/tk/lib/tkextlib/tile/tframe.rb7
-rw-r--r--ext/tk/lib/tkextlib/tile/tlabel.rb7
-rw-r--r--ext/tk/lib/tkextlib/tile/tlabelframe.rb8
-rw-r--r--ext/tk/lib/tkextlib/tile/tmenubutton.rb12
-rw-r--r--ext/tk/lib/tkextlib/tile/tnotebook.rb41
-rw-r--r--ext/tk/lib/tkextlib/tile/tpaned.rb55
-rw-r--r--ext/tk/lib/tkextlib/tile/tprogressbar.rb3
-rw-r--r--ext/tk/lib/tkextlib/tile/tradiobutton.rb8
-rw-r--r--ext/tk/lib/tkextlib/tile/treeview.rb1212
-rw-r--r--ext/tk/lib/tkextlib/tile/tscale.rb7
-rw-r--r--ext/tk/lib/tkextlib/tile/tscrollbar.rb28
-rw-r--r--ext/tk/lib/tkextlib/tile/tseparator.rb3
-rw-r--r--ext/tk/lib/tkextlib/tkDND/shape.rb32
-rw-r--r--ext/tk/lib/tkextlib/tkDND/tkdnd.rb18
-rw-r--r--ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb17
-rw-r--r--ext/tk/lib/tkextlib/tktable/tktable.rb188
-rw-r--r--ext/tk/lib/tkextlib/tktrans/tktrans.rb4
-rw-r--r--ext/tk/lib/tkextlib/treectrl/tktreectrl.rb300
-rw-r--r--ext/tk/lib/tkextlib/version.rb6
-rw-r--r--ext/tk/lib/tkextlib/vu/pie.rb77
-rw-r--r--ext/tk/lib/tkextlib/vu/spinbox.rb2
-rw-r--r--ext/tk/lib/tkextlib/winico/winico.rb57
-rw-r--r--ext/tk/sample/binstr_usage.rb12
-rw-r--r--ext/tk/sample/demos-en/anilabel.rb10
-rw-r--r--ext/tk/sample/demos-en/aniwave.rb9
-rw-r--r--ext/tk/sample/demos-en/arrow.rb26
-rw-r--r--ext/tk/sample/demos-en/bind.rb33
-rw-r--r--ext/tk/sample/demos-en/bitmap.rb10
-rw-r--r--ext/tk/sample/demos-en/button.rb2
-rw-r--r--ext/tk/sample/demos-en/check.rb14
-rw-r--r--ext/tk/sample/demos-en/check2.rb14
-rw-r--r--ext/tk/sample/demos-en/clrpick.rb22
-rw-r--r--ext/tk/sample/demos-en/colors.rb18
-rw-r--r--ext/tk/sample/demos-en/combo.rb96
-rw-r--r--ext/tk/sample/demos-en/cscroll.rb14
-rw-r--r--ext/tk/sample/demos-en/ctext.rb53
-rw-r--r--ext/tk/sample/demos-en/entry1.rb12
-rw-r--r--ext/tk/sample/demos-en/entry2.rb8
-rw-r--r--ext/tk/sample/demos-en/entry3.rb50
-rw-r--r--ext/tk/sample/demos-en/filebox.rb17
-rw-r--r--ext/tk/sample/demos-en/floor.rb14
-rw-r--r--ext/tk/sample/demos-en/floor2.rb14
-rw-r--r--ext/tk/sample/demos-en/form.rb8
-rw-r--r--ext/tk/sample/demos-en/goldberg.rb23
-rw-r--r--ext/tk/sample/demos-en/hello6
-rw-r--r--ext/tk/sample/demos-en/hscale.rb29
-rw-r--r--ext/tk/sample/demos-en/icon.rb20
-rw-r--r--ext/tk/sample/demos-en/image1.rb13
-rw-r--r--ext/tk/sample/demos-en/image2.rb22
-rw-r--r--ext/tk/sample/demos-en/image3.rb29
-rw-r--r--ext/tk/sample/demos-en/items.rb17
-rw-r--r--ext/tk/sample/demos-en/knightstour.rb271
-rw-r--r--ext/tk/sample/demos-en/label.rb13
-rw-r--r--ext/tk/sample/demos-en/labelframe.rb8
-rw-r--r--ext/tk/sample/demos-en/mclist.rb117
-rw-r--r--ext/tk/sample/demos-en/menu.rb12
-rw-r--r--ext/tk/sample/demos-en/menu84.rb8
-rw-r--r--ext/tk/sample/demos-en/menubu.rb10
-rw-r--r--ext/tk/sample/demos-en/msgbox.rb10
-rw-r--r--ext/tk/sample/demos-en/msgbox2.rb91
-rw-r--r--ext/tk/sample/demos-en/paned1.rb14
-rw-r--r--ext/tk/sample/demos-en/paned2.rb8
-rw-r--r--ext/tk/sample/demos-en/patch_1.1c193
-rw-r--r--ext/tk/sample/demos-en/pendulum.rb43
-rw-r--r--ext/tk/sample/demos-en/plot.rb8
-rw-r--r--ext/tk/sample/demos-en/puzzle.rb32
-rw-r--r--ext/tk/sample/demos-en/radio.rb12
-rw-r--r--ext/tk/sample/demos-en/radio2.rb17
-rw-r--r--ext/tk/sample/demos-en/radio3.rb19
-rw-r--r--ext/tk/sample/demos-en/rolodex-j323
-rw-r--r--ext/tk/sample/demos-en/ruler.rb8
-rw-r--r--ext/tk/sample/demos-en/sayings.rb8
-rw-r--r--ext/tk/sample/demos-en/search.rb19
-rw-r--r--ext/tk/sample/demos-en/spin.rb12
-rw-r--r--ext/tk/sample/demos-en/states.rb8
-rw-r--r--ext/tk/sample/demos-en/style.rb42
-rw-r--r--ext/tk/sample/demos-en/text.rb8
-rw-r--r--ext/tk/sample/demos-en/textpeer.rb76
-rw-r--r--ext/tk/sample/demos-en/toolbar.rb130
-rw-r--r--ext/tk/sample/demos-en/tree.rb119
-rw-r--r--ext/tk/sample/demos-en/ttkbut.rb139
-rw-r--r--ext/tk/sample/demos-en/ttkmenu.rb85
-rw-r--r--ext/tk/sample/demos-en/ttknote.rb89
-rw-r--r--ext/tk/sample/demos-en/ttkpane.rb213
-rw-r--r--ext/tk/sample/demos-en/ttkprogress.rb66
-rw-r--r--ext/tk/sample/demos-en/twind.rb14
-rw-r--r--ext/tk/sample/demos-en/twind2.rb6
-rw-r--r--ext/tk/sample/demos-en/unicodeout.rb14
-rw-r--r--ext/tk/sample/demos-en/vscale.rb29
-rw-r--r--ext/tk/sample/demos-en/widget232
-rw-r--r--ext/tk/sample/demos-jp/anilabel.rb11
-rw-r--r--ext/tk/sample/demos-jp/aniwave.rb10
-rw-r--r--ext/tk/sample/demos-jp/arrow.rb27
-rw-r--r--ext/tk/sample/demos-jp/bind.rb34
-rw-r--r--ext/tk/sample/demos-jp/bitmap.rb11
-rw-r--r--ext/tk/sample/demos-jp/button.rb4
-rw-r--r--ext/tk/sample/demos-jp/check.rb15
-rw-r--r--ext/tk/sample/demos-jp/check2.rb15
-rw-r--r--ext/tk/sample/demos-jp/clrpick.rb21
-rw-r--r--ext/tk/sample/demos-jp/colors.rb19
-rw-r--r--ext/tk/sample/demos-jp/combo.rb98
-rw-r--r--ext/tk/sample/demos-jp/cscroll.rb15
-rw-r--r--ext/tk/sample/demos-jp/ctext.rb54
-rw-r--r--ext/tk/sample/demos-jp/dialog1.rb1
-rw-r--r--ext/tk/sample/demos-jp/dialog2.rb1
-rw-r--r--ext/tk/sample/demos-jp/entry1.rb13
-rw-r--r--ext/tk/sample/demos-jp/entry2.rb9
-rw-r--r--ext/tk/sample/demos-jp/entry3.rb49
-rw-r--r--ext/tk/sample/demos-jp/filebox.rb18
-rw-r--r--ext/tk/sample/demos-jp/floor.rb15
-rw-r--r--ext/tk/sample/demos-jp/floor2.rb15
-rw-r--r--ext/tk/sample/demos-jp/form.rb9
-rw-r--r--ext/tk/sample/demos-jp/goldberg.rb24
-rw-r--r--ext/tk/sample/demos-jp/hello1
-rw-r--r--ext/tk/sample/demos-jp/hscale.rb29
-rw-r--r--ext/tk/sample/demos-jp/icon.rb21
-rw-r--r--ext/tk/sample/demos-jp/image1.rb14
-rw-r--r--ext/tk/sample/demos-jp/image2.rb24
-rw-r--r--ext/tk/sample/demos-jp/image3.rb18
-rw-r--r--ext/tk/sample/demos-jp/items.rb18
-rw-r--r--ext/tk/sample/demos-jp/ixset21
-rw-r--r--ext/tk/sample/demos-jp/knightstour.rb273
-rw-r--r--ext/tk/sample/demos-jp/label.rb14
-rw-r--r--ext/tk/sample/demos-jp/labelframe.rb10
-rw-r--r--ext/tk/sample/demos-jp/mclist.rb121
-rw-r--r--ext/tk/sample/demos-jp/menu.rb15
-rw-r--r--ext/tk/sample/demos-jp/menu84.rb9
-rw-r--r--ext/tk/sample/demos-jp/menu8x.rb13
-rw-r--r--ext/tk/sample/demos-jp/menubu.rb11
-rw-r--r--ext/tk/sample/demos-jp/msgbox.rb15
-rw-r--r--ext/tk/sample/demos-jp/msgbox2.rb90
-rw-r--r--ext/tk/sample/demos-jp/paned1.rb16
-rw-r--r--ext/tk/sample/demos-jp/paned2.rb10
-rw-r--r--ext/tk/sample/demos-jp/pendulum.rb44
-rw-r--r--ext/tk/sample/demos-jp/plot.rb15
-rw-r--r--ext/tk/sample/demos-jp/puzzle.rb33
-rw-r--r--ext/tk/sample/demos-jp/radio.rb13
-rw-r--r--ext/tk/sample/demos-jp/radio2.rb19
-rw-r--r--ext/tk/sample/demos-jp/radio3.rb21
-rw-r--r--ext/tk/sample/demos-jp/rolodex-j1
-rw-r--r--ext/tk/sample/demos-jp/ruler.rb9
-rw-r--r--ext/tk/sample/demos-jp/sayings.rb9
-rw-r--r--ext/tk/sample/demos-jp/search.rb20
-rw-r--r--ext/tk/sample/demos-jp/spin.rb16
-rw-r--r--ext/tk/sample/demos-jp/states.rb9
-rw-r--r--ext/tk/sample/demos-jp/style.rb42
-rw-r--r--ext/tk/sample/demos-jp/tcolor1
-rw-r--r--ext/tk/sample/demos-jp/text.rb9
-rw-r--r--ext/tk/sample/demos-jp/textpeer.rb82
-rw-r--r--ext/tk/sample/demos-jp/toolbar.rb136
-rw-r--r--ext/tk/sample/demos-jp/tree.rb120
-rw-r--r--ext/tk/sample/demos-jp/ttkbut.rb145
-rw-r--r--ext/tk/sample/demos-jp/ttkmenu.rb91
-rw-r--r--ext/tk/sample/demos-jp/ttknote.rb97
-rw-r--r--ext/tk/sample/demos-jp/ttkpane.rb216
-rw-r--r--ext/tk/sample/demos-jp/ttkprogress.rb71
-rw-r--r--ext/tk/sample/demos-jp/twind.rb13
-rw-r--r--ext/tk/sample/demos-jp/twind2.rb7
-rw-r--r--ext/tk/sample/demos-jp/unicodeout.rb16
-rw-r--r--ext/tk/sample/demos-jp/vscale.rb30
-rw-r--r--ext/tk/sample/demos-jp/widget278
-rw-r--r--ext/tk/sample/editable_listbox.rb69
-rw-r--r--ext/tk/sample/encstr_usage.rb5
-rw-r--r--ext/tk/sample/figmemo_sample.rb456
-rw-r--r--ext/tk/sample/images/teapot.ppm49
-rw-r--r--ext/tk/sample/irbtkw.rbw146
-rw-r--r--ext/tk/sample/tcltklib/sample2.rb2
-rw-r--r--ext/tk/sample/tkextlib/tile/demo.rb39
-rw-r--r--ext/tk/sample/tkextlib/tile/repeater.tcl2
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/pkgIndex.tcl2
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/keramik.tcl2
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/keramik/pkgIndex.tcl2
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc.rb30
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc/pkgIndex.tcl2
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/pkgIndex.tcl2
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/plastik/plastik.tcl2
-rw-r--r--ext/tk/sample/tkextlib/tile/toolbutton.tcl2
-rw-r--r--ext/tk/sample/tkextlib/tkHTML/page3/index.html2
-rw-r--r--ext/tk/sample/tkextlib/treectrl/demo.rb7
-rw-r--r--ext/tk/sample/tkextlib/vu/canvSticker2.rb12
-rw-r--r--ext/tk/sample/tkrttimer.rb13
-rw-r--r--ext/tk/sample/tksleep_sample.rb29
-rw-r--r--ext/tk/sample/tktextio.rb557
-rw-r--r--ext/tk/sample/ttk_wrapper.rb154
-rw-r--r--ext/tk/stubs.c78
-rw-r--r--ext/tk/tcltklib.c2703
-rw-r--r--ext/tk/tkutil/extconf.rb11
-rw-r--r--ext/tk/tkutil/tkutil.c710
-rw-r--r--ext/win32ole/extconf.rb4
-rw-r--r--ext/win32ole/sample/olegen.rb4
-rw-r--r--ext/win32ole/tests/testOLEEVENT.rb91
-rw-r--r--ext/win32ole/tests/testWIN32OLE.rb3
-rw-r--r--ext/win32ole/tests/test_win32ole_event.rb133
-rw-r--r--ext/win32ole/tests/testall.rb1
-rw-r--r--ext/win32ole/win32ole.c229
-rw-r--r--ext/zlib/doc/zlib.rd2
-rw-r--r--ext/zlib/extconf.rb6
-rw-r--r--ext/zlib/zlib.c17
-rw-r--r--file.c429
-rw-r--r--gc.c433
-rw-r--r--hash.c605
-rw-r--r--ia64.s33
-rw-r--r--inits.c6
-rwxr-xr-x[-rw-r--r--]instruby.rb373
-rw-r--r--intern.h46
-rw-r--r--io.c427
-rw-r--r--keywords2
-rw-r--r--lex.c2
-rw-r--r--lib/.document3
-rw-r--r--lib/README6
-rw-r--r--lib/abbrev.rb2
-rw-r--r--lib/base64.rb4
-rw-r--r--lib/benchmark.rb11
-rw-r--r--lib/cgi.rb47
-rw-r--r--lib/cgi/session.rb44
-rw-r--r--lib/cgi/session/pstore.rb2
-rw-r--r--lib/complex.rb32
-rw-r--r--lib/csv.rb2
-rw-r--r--lib/date.rb996
-rw-r--r--lib/date/format.rb1595
-rw-r--r--lib/delegate.rb49
-rw-r--r--lib/drb/acl.rb2
-rw-r--r--lib/drb/drb.rb25
-rw-r--r--lib/drb/extservm.rb41
-rw-r--r--lib/drb/unix.rb2
-rw-r--r--lib/erb.rb306
-rw-r--r--lib/fileutils.rb133
-rw-r--r--lib/forwardable.rb6
-rw-r--r--lib/generator.rb40
-rw-r--r--lib/getopts.rb6
-rw-r--r--lib/ipaddr.rb148
-rw-r--r--lib/irb.rb24
-rw-r--r--lib/irb/cmd/chws.rb4
-rw-r--r--lib/irb/cmd/fork.rb6
-rw-r--r--lib/irb/cmd/help.rb4
-rw-r--r--lib/irb/cmd/load.rb4
-rw-r--r--lib/irb/cmd/nop.rb6
-rw-r--r--lib/irb/cmd/pushws.rb4
-rw-r--r--lib/irb/cmd/subirb.rb4
-rw-r--r--lib/irb/completion.rb6
-rw-r--r--lib/irb/context.rb4
-rw-r--r--lib/irb/ext/change-ws.rb4
-rw-r--r--lib/irb/ext/history.rb6
-rw-r--r--lib/irb/ext/loader.rb6
-rw-r--r--lib/irb/ext/math-mode.rb4
-rw-r--r--lib/irb/ext/multi-irb.rb6
-rw-r--r--lib/irb/ext/save-history.rb6
-rw-r--r--lib/irb/ext/tracer.rb4
-rw-r--r--lib/irb/ext/use-loader.rb4
-rw-r--r--lib/irb/ext/workspaces.rb4
-rw-r--r--lib/irb/extend-command.rb6
-rw-r--r--lib/irb/frame.rb4
-rw-r--r--lib/irb/help.rb6
-rw-r--r--lib/irb/init.rb4
-rw-r--r--lib/irb/input-method.rb6
-rw-r--r--lib/irb/lc/error.rb4
-rw-r--r--lib/irb/lc/help-message4
-rw-r--r--lib/irb/lc/ja/error.rb4
-rw-r--r--lib/irb/lc/ja/help-message4
-rw-r--r--lib/irb/locale.rb12
-rw-r--r--lib/irb/notifier.rb6
-rw-r--r--lib/irb/output-method.rb6
-rw-r--r--lib/irb/ruby-lex.rb8
-rw-r--r--lib/irb/ruby-token.rb4
-rw-r--r--lib/irb/slex.rb8
-rw-r--r--lib/irb/version.rb4
-rw-r--r--lib/irb/workspace.rb4
-rw-r--r--lib/irb/ws-for-case-2.rb4
-rw-r--r--lib/irb/xmp.rb6
-rw-r--r--lib/jcode.rb2
-rw-r--r--lib/logger.rb6
-rw-r--r--lib/matrix.rb20
-rw-r--r--lib/mkmf.rb458
-rw-r--r--lib/net/ftp.rb19
-rw-r--r--lib/net/http.rb7
-rw-r--r--lib/net/https.rb8
-rw-r--r--lib/net/imap.rb42
-rw-r--r--lib/net/pop.rb236
-rw-r--r--lib/net/protocol.rb6
-rw-r--r--lib/net/smtp.rb639
-rw-r--r--lib/net/telnet.rb24
-rw-r--r--lib/open-uri.rb12
-rw-r--r--lib/open3.rb45
-rw-r--r--lib/optparse.rb166
-rw-r--r--lib/parsearg.rb6
-rw-r--r--lib/parsedate.rb44
-rw-r--r--lib/ping.rb49
-rw-r--r--lib/pp.rb13
-rw-r--r--lib/prettyprint.rb12
-rw-r--r--lib/pstore.rb25
-rw-r--r--lib/rational.rb78
-rw-r--r--lib/rdoc/generators/ri_generator.rb2
-rw-r--r--lib/rdoc/options.rb17
-rw-r--r--lib/rdoc/parsers/parse_c.rb272
-rw-r--r--lib/rdoc/parsers/parse_f95.rb8
-rw-r--r--lib/rdoc/parsers/parse_rb.rb10
-rw-r--r--lib/rdoc/rdoc.rb54
-rw-r--r--lib/rdoc/ri/ri_formatter.rb4
-rw-r--r--lib/rdoc/ri/ri_options.rb34
-rw-r--r--lib/rdoc/ri/ri_paths.rb27
-rw-r--r--lib/resolv-replace.rb3
-rw-r--r--lib/resolv.rb1244
-rw-r--r--lib/rexml/attlistdecl.rb2
-rw-r--r--lib/rexml/attribute.rb38
-rw-r--r--lib/rexml/cdata.rb21
-rw-r--r--lib/rexml/comment.rb28
-rw-r--r--lib/rexml/doctype.rb27
-rw-r--r--lib/rexml/document.rb113
-rw-r--r--lib/rexml/element.rb2258
-rw-r--r--lib/rexml/encoding.rb31
-rw-r--r--lib/rexml/encodings/CP-1252.rb123
-rw-r--r--lib/rexml/encodings/ISO-8859-15.rb59
-rw-r--r--lib/rexml/encodings/SHIFT-JIS.rb4
-rw-r--r--lib/rexml/encodings/UNILE.rb2
-rw-r--r--lib/rexml/encodings/UTF-16.rb3
-rw-r--r--lib/rexml/entity.rb7
-rw-r--r--lib/rexml/formatters/default.rb109
-rw-r--r--lib/rexml/formatters/pretty.rb138
-rw-r--r--lib/rexml/formatters/transitive.rb56
-rw-r--r--lib/rexml/functions.rb29
-rw-r--r--lib/rexml/instruction.rb4
-rw-r--r--lib/rexml/node.rb25
-rw-r--r--lib/rexml/parsers/baseparser.rb87
-rw-r--r--lib/rexml/parsers/sax2parser.rb8
-rw-r--r--lib/rexml/parsers/treeparser.rb9
-rw-r--r--lib/rexml/parsers/xpathparser.rb10
-rw-r--r--lib/rexml/rexml.rb13
-rw-r--r--lib/rexml/sax2listener.rb2
-rw-r--r--lib/rexml/source.rb380
-rw-r--r--lib/rexml/text.rb64
-rw-r--r--lib/rexml/undefinednamespaceexception.rb8
-rw-r--r--lib/rexml/xmldecl.rb11
-rw-r--r--lib/rexml/xpath.rb16
-rw-r--r--lib/rexml/xpath_parser.rb103
-rw-r--r--lib/rinda/ring.rb4
-rw-r--r--lib/rinda/tuplespace.rb111
-rw-r--r--lib/rss.rb7
-rw-r--r--lib/rss/0.9.rb23
-rw-r--r--lib/rss/1.0.rb13
-rw-r--r--lib/rss/2.0.rb2
-rw-r--r--lib/rss/atom.rb749
-rw-r--r--lib/rss/content.rb25
-rw-r--r--lib/rss/content/1.0.rb10
-rw-r--r--lib/rss/content/2.0.rb12
-rw-r--r--lib/rss/converter.rb8
-rw-r--r--lib/rss/dublincore.rb39
-rw-r--r--lib/rss/dublincore/1.0.rb13
-rw-r--r--lib/rss/dublincore/2.0.rb13
-rw-r--r--lib/rss/dublincore/atom.rb17
-rw-r--r--lib/rss/image.rb10
-rw-r--r--lib/rss/itunes.rb410
-rw-r--r--lib/rss/maker.rb25
-rw-r--r--lib/rss/maker/0.9.rb375
-rw-r--r--lib/rss/maker/1.0.rb332
-rw-r--r--lib/rss/maker/2.0.rb147
-rw-r--r--lib/rss/maker/atom.rb172
-rw-r--r--lib/rss/maker/base.rb844
-rw-r--r--lib/rss/maker/content.rb14
-rw-r--r--lib/rss/maker/dublincore.rb145
-rw-r--r--lib/rss/maker/entry.rb163
-rw-r--r--lib/rss/maker/feed.rb429
-rw-r--r--lib/rss/maker/image.rb116
-rw-r--r--lib/rss/maker/itunes.rb242
-rw-r--r--lib/rss/maker/slash.rb33
-rw-r--r--lib/rss/maker/syndication.rb13
-rw-r--r--lib/rss/maker/taxonomy.rb118
-rw-r--r--lib/rss/maker/trackback.rb115
-rw-r--r--lib/rss/parser.rb167
-rw-r--r--lib/rss/rss.rb735
-rw-r--r--lib/rss/slash.rb49
-rw-r--r--lib/rss/syndication.rb9
-rw-r--r--lib/rss/taxonomy.rb2
-rw-r--r--lib/rss/utils.rb78
-rw-r--r--lib/rss/xml-stylesheet.rb4
-rw-r--r--lib/rss/xml.rb71
-rw-r--r--lib/scanf.rb10
-rw-r--r--lib/securerandom.rb137
-rw-r--r--lib/set.rb65
-rw-r--r--lib/shell/builtin-command.rb4
-rw-r--r--lib/shell/command-processor.rb4
-rw-r--r--lib/shell/error.rb4
-rw-r--r--lib/shell/filter.rb4
-rw-r--r--lib/shell/process-controller.rb4
-rw-r--r--lib/shell/system-command.rb4
-rw-r--r--lib/shell/version.rb4
-rw-r--r--lib/shellwords.rb146
-rw-r--r--lib/singleton.rb61
-rw-r--r--lib/sync.rb6
-rw-r--r--lib/tempfile.rb28
-rw-r--r--lib/test/unit/autorunner.rb24
-rw-r--r--lib/test/unit/collector/dir.rb25
-rw-r--r--lib/test/unit/testcase.rb14
-rw-r--r--lib/thread.rb15
-rw-r--r--lib/time.rb28
-rw-r--r--lib/timeout.rb23
-rw-r--r--lib/tmpdir.rb108
-rw-r--r--lib/uri.rb3
-rw-r--r--lib/uri/common.rb12
-rw-r--r--lib/uri/ftp.rb88
-rw-r--r--lib/uri/generic.rb124
-rw-r--r--lib/uri/http.rb51
-rw-r--r--lib/uri/https.rb6
-rw-r--r--lib/uri/ldap.rb2
-rw-r--r--lib/uri/ldaps.rb12
-rw-r--r--lib/uri/mailto.rb47
-rw-r--r--lib/weakref.rb30
-rw-r--r--lib/webrick/cgi.rb2
-rw-r--r--lib/webrick/cookie.rb6
-rw-r--r--lib/webrick/httpproxy.rb2
-rw-r--r--lib/webrick/httpresponse.rb2
-rw-r--r--lib/webrick/httpservlet/abstract.rb2
-rw-r--r--lib/webrick/httpservlet/cgi_runner.rb4
-rw-r--r--lib/webrick/httpservlet/cgihandler.rb4
-rw-r--r--lib/webrick/httpservlet/filehandler.rb71
-rw-r--r--lib/webrick/httputils.rb16
-rw-r--r--lib/webrick/ssl.rb2
-rw-r--r--lib/xmlrpc/base64.rb2
-rw-r--r--lib/xmlrpc/client.rb21
-rw-r--r--lib/xmlrpc/config.rb2
-rw-r--r--lib/xmlrpc/create.rb4
-rw-r--r--lib/xmlrpc/datetime.rb2
-rw-r--r--lib/xmlrpc/httpserver.rb2
-rw-r--r--lib/xmlrpc/marshal.rb2
-rw-r--r--lib/xmlrpc/parser.rb6
-rw-r--r--lib/xmlrpc/server.rb8
-rw-r--r--lib/xmlrpc/utils.rb4
-rw-r--r--lib/yaml.rb6
-rw-r--r--lib/yaml/baseemitter.rb2
-rw-r--r--lib/yaml/basenode.rb2
-rw-r--r--lib/yaml/encoding.rb6
-rw-r--r--lib/yaml/rubytypes.rb20
-rw-r--r--lib/yaml/store.rb20
-rw-r--r--lib/yaml/tag.rb2
-rw-r--r--lib/yaml/types.rb8
-rw-r--r--main.c13
-rw-r--r--marshal.c134
-rw-r--r--math.c8
-rwxr-xr-xmdoc2man.rb2
-rw-r--r--misc/README3
-rw-r--r--misc/inf-ruby.el10
-rw-r--r--misc/rdebug.el136
-rw-r--r--misc/ruby-mode.el47
-rw-r--r--misc/ruby-style.el66
-rw-r--r--missing.h6
-rw-r--r--missing/acosh.c4
-rw-r--r--missing/crypt.c34
-rw-r--r--missing/flock.c5
-rw-r--r--missing/isinf.c7
-rw-r--r--missing/strftime.c58
-rw-r--r--missing/strtod.c2
-rw-r--r--missing/vsnprintf.c2
-rwxr-xr-x[-rw-r--r--]mkconfig.rb43
-rw-r--r--node.h120
-rw-r--r--numeric.c617
-rw-r--r--object.c242
-rw-r--r--pack.c39
-rw-r--r--parse.y285
-rw-r--r--prec.c4
-rw-r--r--process.c158
-rw-r--r--random.c32
-rw-r--r--range.c105
-rw-r--r--re.c183
-rw-r--r--re.h4
-rw-r--r--regex.c115
-rw-r--r--regex.h4
-rw-r--r--ruby.c302
-rw-r--r--ruby.h64
-rw-r--r--rubyio.h29
-rw-r--r--rubysig.h12
-rwxr-xr-x[-rw-r--r--]rubytest.rb0
-rwxr-xr-xrunruby.rb22
-rw-r--r--sample/README3
-rw-r--r--sample/biorhythm.rb4
-rw-r--r--sample/cal.rb84
-rw-r--r--sample/cbreak.rb4
-rw-r--r--sample/dualstack-httpd.rb2
-rw-r--r--sample/erb/erb4html.rb60
-rw-r--r--sample/eval.rb2
-rw-r--r--sample/from.rb2
-rw-r--r--sample/goodfriday.rb48
-rw-r--r--sample/openssl/c_rehash.rb4
-rw-r--r--sample/philos.rb2
-rw-r--r--sample/regx.rb2
-rwxr-xr-xsample/rss/blend.rb6
-rwxr-xr-xsample/rss/convert.rb2
-rwxr-xr-x[-rw-r--r--]sample/rss/list_description.rb13
-rwxr-xr-xsample/rss/re_read.rb10
-rwxr-xr-x[-rw-r--r--]sample/rss/rss_recent.rb20
-rw-r--r--sample/test.rb69
-rw-r--r--sample/time.rb16
-rw-r--r--signal.c167
-rw-r--r--sprintf.c112
-rw-r--r--string.c494
-rw-r--r--struct.c39
-rw-r--r--test/dbm/test_dbm.rb4
-rw-r--r--test/digest/test_digest.rb30
-rw-r--r--test/drb/drbtest.rb2
-rw-r--r--test/erb/hello.erb4
-rw-r--r--test/erb/test_erb.rb386
-rw-r--r--test/fileutils/fileasserts.rb8
-rw-r--r--test/fileutils/test_dryrun.rb2
-rw-r--r--test/fileutils/test_fileutils.rb2
-rw-r--r--test/fileutils/test_nowrite.rb2
-rw-r--r--test/fileutils/test_verbose.rb2
-rw-r--r--test/gdbm/test_gdbm.rb8
-rw-r--r--test/iconv/test_basic.rb49
-rw-r--r--test/iconv/test_option.rb31
-rw-r--r--test/iconv/test_partial.rb41
-rw-r--r--test/iconv/utils.rb26
-rw-r--r--test/matrix/test_matrix.rb43
-rw-r--r--test/matrix/test_vector.rb43
-rw-r--r--test/net/http/test_https_proxy.rb9
-rw-r--r--test/net/imap/test_imap.rb11
-rw-r--r--test/net/pop/test_pop.rb132
-rw-r--r--test/openssl/test_ec.rb113
-rw-r--r--test/openssl/test_ssl.rb348
-rw-r--r--test/optparse/test_getopts.rb31
-rw-r--r--test/pathname/test_pathname.rb26
-rw-r--r--test/rdoc/parsers/test_parse_c.rb261
-rw-r--r--test/rexml/test_document.rb65
-rw-r--r--test/rinda/test_rinda.rb103
-rw-r--r--test/rss/dot.pngbin0 -> 111 bytes-rw-r--r--test/rss/rss-assertions.rb1894
-rw-r--r--test/rss/rss-testcase.rb208
-rw-r--r--test/rss/test_1.0.rb61
-rw-r--r--test/rss/test_2.0.rb28
-rw-r--r--test/rss/test_atom.rb681
-rw-r--r--test/rss/test_content.rb68
-rw-r--r--test/rss/test_dublincore.rb316
-rw-r--r--test/rss/test_image.rb49
-rw-r--r--test/rss/test_inherit.rb5
-rw-r--r--test/rss/test_itunes.rb347
-rw-r--r--test/rss/test_maker_0.9.rb147
-rw-r--r--test/rss/test_maker_1.0.rb205
-rw-r--r--test/rss/test_maker_2.0.rb56
-rw-r--r--test/rss/test_maker_atom_entry.rb367
-rw-r--r--test/rss/test_maker_atom_feed.rb389
-rw-r--r--test/rss/test_maker_content.rb13
-rw-r--r--test/rss/test_maker_dc.rb9
-rw-r--r--test/rss/test_maker_itunes.rb471
-rw-r--r--test/rss/test_maker_slash.rb37
-rw-r--r--test/rss/test_maker_sy.rb1
-rw-r--r--test/rss/test_maker_xml-stylesheet.rb8
-rw-r--r--test/rss/test_parser.rb26
-rw-r--r--test/rss/test_parser_1.0.rb10
-rw-r--r--test/rss/test_parser_atom_entry.rb163
-rw-r--r--test/rss/test_parser_atom_feed.rb276
-rw-r--r--test/rss/test_setup_maker_0.9.rb25
-rw-r--r--test/rss/test_setup_maker_1.0.rb26
-rw-r--r--test/rss/test_setup_maker_atom_entry.rb409
-rw-r--r--test/rss/test_setup_maker_atom_feed.rb445
-rw-r--r--test/rss/test_setup_maker_itunes.rb144
-rw-r--r--test/rss/test_setup_maker_slash.rb38
-rw-r--r--test/rss/test_slash.rb64
-rw-r--r--test/rss/test_syndication.rb4
-rw-r--r--test/rss/test_taxonomy.rb16
-rw-r--r--test/rss/test_to_s.rb232
-rw-r--r--test/rss/test_version.rb2
-rw-r--r--test/rss/test_xml-stylesheet.rb6
-rw-r--r--test/ruby/marshaltestlib.rb6
-rw-r--r--test/ruby/suicide.rb2
-rw-r--r--test/ruby/test_array.rb1159
-rw-r--r--test/ruby/test_beginendblock.rb47
-rw-r--r--test/ruby/test_bignum.rb19
-rw-r--r--test/ruby/test_enum.rb258
-rw-r--r--test/ruby/test_enumerator.rb105
-rw-r--r--test/ruby/test_fixnum.rb26
-rw-r--r--test/ruby/test_float.rb34
-rw-r--r--test/ruby/test_hash.rb567
-rw-r--r--test/ruby/test_integer.rb653
-rw-r--r--test/ruby/test_iterator.rb12
-rw-r--r--test/ruby/test_marshal.rb26
-rw-r--r--test/ruby/test_method.rb18
-rw-r--r--test/ruby/test_objectspace.rb2
-rw-r--r--test/ruby/test_proc.rb5
-rw-r--r--test/ruby/test_settracefunc.rb6
-rw-r--r--test/ruby/test_sleep.rb10
-rw-r--r--test/ruby/test_super.rb17
-rw-r--r--test/ruby/test_symbol.rb15
-rw-r--r--test/ruby/test_system.rb5
-rw-r--r--test/ruby/test_time.rb21
-rw-r--r--test/runner.rb2
-rw-r--r--test/strscan/test_stringscanner.rb13
-rw-r--r--test/testunit/collector/test_dir.rb29
-rwxr-xr-xtest/thread/lbtest.rb51
-rw-r--r--test/thread/test_thread.rb81
-rw-r--r--test/uri/test_common.rb5
-rw-r--r--test/uri/test_ftp.rb22
-rw-r--r--test/uri/test_generic.rb80
-rw-r--r--test/webrick/.htaccess1
-rw-r--r--test/webrick/test_cgi.rb9
-rw-r--r--test/webrick/test_cookie.rb31
-rw-r--r--test/webrick/test_filehandler.rb135
-rw-r--r--test/webrick/utils.rb12
-rw-r--r--test/webrick/webrick_long_filename.cgi36
-rw-r--r--test/xmlrpc/test_cookie.rb96
-rw-r--r--test/yaml/test_yaml.rb10
-rw-r--r--test/yaml/test_yamlstore.rb74
-rw-r--r--time.c41
-rw-r--r--util.c3454
-rw-r--r--util.h4
-rw-r--r--variable.c108
-rw-r--r--version.c35
-rw-r--r--version.h33
-rw-r--r--win32/Makefile.sub239
-rwxr-xr-xwin32/configure.bat4
-rw-r--r--win32/dir.h4
-rwxr-xr-x[-rw-r--r--]win32/mkexports.rb17
-rwxr-xr-x[-rw-r--r--]win32/resource.rb26
-rw-r--r--win32/setup.mak32
-rw-r--r--win32/win32.c665
-rw-r--r--win32/win32.h27
-rw-r--r--wince/Makefile.sub489
-rw-r--r--wince/mkconfig_wce.rb7
-rw-r--r--wince/mkexports.rb35
-rw-r--r--wince/resource.rb96
-rw-r--r--wince/setup.mak2
-rw-r--r--x68/_dtos18.c2
-rw-r--r--x68/_round.c2
-rw-r--r--x68/fconvert.c2
-rw-r--r--x68/select.c2
992 files changed, 72206 insertions, 18610 deletions
diff --git a/.cvsignore b/.cvsignore
index 9fd96ca149..a72211d03f 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -3,12 +3,14 @@
*.rej
*.sav
*~
+.*.list
+.*.time
.ccmalloc
.ppack
.ext
.git
.svn
-.rbconfig.time
+.pc
COPYING.LIB
ChangeLog.pre-alpha
ChangeLog.pre1_1
@@ -26,32 +28,20 @@ config.h.in
config.log
config.status
configure
-foo.rb
libruby.so.*
miniruby
-miniruby.elhash
-miniruby.elhash2
-miniruby.orig2
-miniruby.plhash
-miniruby.plhash2
-modex.rb
newdate.rb
newver.rb
parse.c
-parse.y.try
-pitest.rb
+patches
ppack
preview
rbconfig.rb
-rename2.h
repack
riscos
rubicon
ruby
ruby-man.rd.gz
-rubyunit
-st.c.power
-this that
tmp
web
y.output
diff --git a/ChangeLog b/ChangeLog
index 5f5a850a2a..38fab4707a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,61 +1,4015 @@
-Thu Aug 16 04:52:11 2007 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+Tue Feb 3 14:35:26 2009 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.
+
+Mon Feb 2 20:03:58 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * time.c (time_mdump, time_mload): preserves GMT status.
+ [ruby-core:19252]
+
+Mon Feb 2 11:34:51 2009 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]
+
+Thu Jan 29 11:54:22 2009 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb (today,now): should produce own instances.
+ [ruby-talk:317020]
+
+Wed Jan 28 22:51:55 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_mod_modfunc): method undefined in included module
+ may not have nd_body. [ruby-core:18738]
+
+Wed Jan 28 20:53:27 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (marshal_dump): fixed for check_dump_arg.
+
+Tue Jan 27 17:30:11 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (marshal_dump): initializes dump_arg before any funcall.
+ [ruby-dev:36648]
+
+Tue Jan 27 15:17:35 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/socket/socket.c (host_str): numeric address should be unsigned.
+ [ruby-core:18971]
+
+Mon Jan 26 11:12:03 2009 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/tmpdir.rb: setup buffer with nul characters instead of spaces.
+ fixed [ruby-dev:36493]
+
+Sun Jan 25 00:07:23 2009 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]
+ fix: #342
+
+Sun Jan 25 00:02:23 2009 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.
+
+Fri Jan 23 11:49:45 2009 Shugo Maeda <shugo@ruby-lang.org>
+
+ * NEWS: added an entry for REXML.
+
+ * lib/rexml/document.rb: fixed typo.
+
+Fri Jan 23 11:49:45 2009 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/rexml/document.rb: limit entity expansion. Thanks, Luka
+ Treiber, Mitja Kolsek, and Michael Koziarski. backported from
+ trunk r19033, r19317, r19318.
+
+ * lib/rexml/entity.rb: ditto.
+
+ * test/rexml/test_document.rb: ditto.
+
+Thu Jan 22 15:19:39 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (marshal_load): arg.data is no longer a VALUE but a
+ st_table, and freed in load_ensure. pointed out by pegacorn.
+ [ruby-dev:37008]
+
+Thu Jan 22 15:19:39 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (rb_mark_set): new function to mark keys.
+
+ * marshal.c (struct dump_arg, struct load_arg): added wrappers to mark
+ data entries. backport from trunk r13527,r13528,r13961,r16533.
+ [ruby-dev:36082]
+
+Wed Jan 21 11:12:55 2009 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (filetime_to_timeval): new function, split from
+ gettimeofday().
+
+ * win32/win32.c (gettimeofday): use above function.
+
+ * win32/win32.c (filetime_to_unixtime): ditto. [ruby-dev:36135]
+
+Wed Jan 21 11:12:55 2009 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (gettimeofday): tv_usec is usec, not msec.
+ [ruby-dev:36094]
+
+Wed Jan 21 11:12:55 2009 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (gettimeofday): calc tv_sec and tv_usec from system
+ time by myself. [ruby-dev:36084]
+
+Wed Jan 21 11:12:55 2009 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (gettimeofday): shouldn't use mktime(2) because it's
+ buggy about handling summer time.
+ reported by Yoshikawa <yoshixool AT gmail.com> at [ruby-dev:36071]
+
+Tue Jan 20 12:23:38 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/scanf.rb (Scanf::FormatSpecifier#initialize): %i should accept
+ single digit decimal. [ruby-core:18355]
+
+Mon Jan 19 18:25:28 2009 Tanaka Akira <akr@fsij.org>
+
+ * configure.in (rb_cv_broken_glibc_ia64_erfc): renamed from
+ rb_broken_glibc_ia64_erfc.
+ [ruby-core:18228]
+
+Sat Jan 17 12:16:10 2009 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * random.c (Init_Random): always initialize seed.
+
+Fri Jan 16 10:59:31 2009 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * class.c (clone_method): should copy cbase in cref as well.
+ [ruby-dev:35116]
+
+ * node.h (NEW_CREF): new NEW_ macro.
+
+ * eval.c (PUSH_CREF): use NEW_CREF().
+
+Thu Jan 15 14:34:32 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (STACK_LEVEL_MAX, ruby_stack_length): returns size_t.
+ [ruby-core:18207]
+Wed Jan 14 10:39:56 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * stable/ext/socket/socket.c (NI_MAXHOST, NI_MAXSERV): fixed invalid
+ preprocessor directives. a patch from Peter Bowen at
+ [ruby-core:18211].
+
+Tue Jan 13 04:40:30 2009 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/ftp.rb (login): raise FTPReplyError if passwd or acct
+ is not supplied. backported from trunk. fixed [ruby-core:18058].
+
+Mon Jan 12 00:23:37 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (gc_sweep, obj_free, run_final): defer finalizers of IO and
+ Data. [ruby-dev:35578]
+
+ * gc.c (rb_gc_call_finalizer_at_exit): self-referencing finalizers
+ cannot be invoked. [ruby-dev:35681]
+
+Sun Jan 11 11:33:27 2009 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/ftp.rb (chdir): handle 5xx errors correctly.
+ backported from trunk. fixed [ruby-core:18057].
+
+Fri Jan 9 19:25:25 2009 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb (disconnect): do not refer SSL::SSLSocket for
+ environments without OpenSSL. backported from trunk.
+ fixed [ruby-dev:35755].
+
+Thu Jan 8 13:24:23 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (deferred_nodes, compstmt, arg, fixup_nodes, range_op): fix
+ up fixnum range literal in conditional as automagical line number
+ comparison. [ruby-core:12124], [ruby-dev:35731]
+
+Wed Jan 7 10:09:46 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (timeofday): use monotonic clock. based on a patch
+ from zimbatm <zimbatm@oree.ch> in [ruby-core:16627].
+
+Tue Jan 6 09:03:35 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (yylex): 8 and 9 in octal integer should cause compile
+ error. [ruby-dev:35729]
+
+Mon Jan 5 11:14:39 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_thread_schedule): runs deferred finalizers.
+
+ * gc.c (gc_sweep): sets rb_thread_pending to run deferred finalizers.
+
+ * rubysig.h (CHECK_INTS): now checks rb_thread_pending even on
+ platforms where setitimer is not available. [ruby-core:18045]
+
+Mon Jan 5 11:14:39 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * rubysig.h (CHECK_INTS): gives the chance to perform to deferred
+ finalizers before explicit GC.start or the process termination.
+ [ruby-core:18045]
+
+Sun Jan 4 04:49:01 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_telldir): just returns loc.
+
+ * win32/win32.c (rb_w32_rewinddir): needs to intialize loc.
+ [ruby-core:18041]
+
+Sun Jan 4 04:45:26 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_select): recalc the rest of timeout for each
+ iterations. [ruby-core:18015]
+
+Fri Jan 2 03:08:47 2009 Kouhei Sutou <kou@cozmixng.org>
+
+ * test/rss/: use PNG instead of zlib as binary data. [ruby-dev:35666]
+
+Tue Nov 11 01:07:32 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * configure.in: fix SEGV on Mac OS X 10.5.3 with --enable-pthread.
+ a patch from Wataru Kimura in Bug #193 [ruby-core:17333].
+
+Mon Aug 11 09:37:17 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/dl/dl.c (rb_str_to_ptr): should propagate taint to dlptr.
+
+ * ext/dl/dl.c (rb_ary_to_ptr): ditto.
+
+ * ext/dl/sym.c (rb_dlsym_call): should check taint of DLPtrData as
+ well.
+
+Fri Aug 8 10:53:52 2008 Tanaka Akira <akr@fsij.org>
+
+ * lib/resolv.rb: randomize source port and transaction id.
+ CVE-2008-1447.
+
+ * lib/resolv-replace.rb (UDPSocket#bind): don't resolv host if host is
+ "".
+
+Mon Aug 4 14:49:35 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * lib/net/smtp.rb (Net::SMTP::rcptto): fix a typo. a patch from
+ Masao Takaku <masao at nii.ac.jp>
+ fix [ruby-dev:35489].
+
+Mon Aug 4 14:13:15 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * regex.c (xmalloc, xrealloc, xfree): not to use ruby managed memory.
+
+ * regex.c (DOUBLE_STACK, re_compile_fastmap0, re_adjust_startpos),
+ (re_search, re_match_exec): check if failed to allocate memory.
+
+Mon Aug 4 13:53:42 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big2str0, bigsqr): made interruptible. [ruby-Bugs-20622]
+
+Mon Aug 4 13:31:41 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * numeric.c (check_uint, rb_num2uint, rb_fix2uint): fixed wrong check
+ about 64bit positive value.
+Mon Aug 4 13:31:41 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * numeric.c (check_uint, rb_num2uint, rb_fix2uint): strict check.
+ fixed [ruby-dev:33683]
+
+Thu Jul 17 21:42:07 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * lib/net/smtp.rb (Net::SMTP::start): revert to avoid RFC2821
+ violation. [ruby-dev:35487]
+
+Thu Jul 17 21:32:49 2008 Tanaka Akira <akr@fsij.org>
+
+ * string.c (rb_str_format_m): make tmp volatile to avoid possible GC
+ problem.
+
+Thu Jul 17 21:30:55 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser#environment): requires shellwords.
+ [ruby-dev:35466]
+
+Thu Jul 17 02:05:10 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/xmlrpc/client.rb (XMLRPC::Client#do_rpc): requires
+ webrick/cookie. [ ruby-Bugs-21139 ]
+
+Thu Jul 17 01:38:31 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * ext/zlib/zlib.c (rb_gzfile_set_mtime): fix typo. [ruby-core:17713]
+
+Sun Jul 13 00:08:16 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/ipaddr.rb (IPAddr#initialize): get rid of ArgumentError in
+ IPAddr#to_range. a patch from okkez <okkez000 AT gmail.com> in
+ [ruby-dev:35091].
+
+Sun Jul 13 00:04:38 2008 Tanaka Akira <akr@fsij.org>
+
+ * configure.in (erfc): erfc of glibc comes with Debian GNU/Linux Etch
+ on IA64 is broken. erfc(10000.0) aborts.
+ use missing/erf.c instead.
+ http://sources.redhat.com/ml/libc-hacker/2005-08/msg00008.html
+
+Thu Jul 10 18:50:48 2008 Tanaka Akira <akr@fsij.org>
+
+ * common.mk (SPEC_GIT_BASE): update RubySpec GIT URL.
+
+Thu Jul 10 18:46:28 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_file_s_extname): fix for file name with spaces.
+ [ruby-talk:307404]
+
+Thu Jul 10 18:42:37 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/erb.rb (PercentScanner#scan): fix %% line bug. [ruby-core:17491]
+
+ * test/erb/test_erb.rb (test_percent): ditto.
+
+Thu Jul 10 18:40:22 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/net/ftp.rb (Net::FTP#sendport): use divmod. [ruby-core:17557]
+
+Thu Jul 10 18:36:53 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * ruby.c: Mac OS X needs origargc times of '\0' in
+ origargv. [ruby-dev:35308]
+
+Thu Jul 10 13:53:08 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/ruby.h (POSFIXABLE): use FIXNUM_MAX+1 instead of
+ FIXNUM_MAX to make it possible to convert to double accurately.
+ It assumes FLT_RADIX is 2.
+ fix RubyForge bug #14102.
+ backported from 1.9.
+
+Mon Jul 7 16:21:38 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/net/smtp.rb (Net::SMTP::start): use 'localhost' instead of
+ 'localhost.localdomain'. [ruby-dev:35333]
+
+ * lib/net/smtp.rb (Net::SMTP::SMTP.start): ditto.
+
+Mon Jul 7 15:02:13 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_longjmp): duplicate the thrown exception to set backtrace
+ if it was frozen. clear all raised flags.
+
+ * eval.c (stack_check): leave clearing flag to rb_longjmp.
+
+ * eval.c (rb_thread_set_raised, rb_thread_reset_raised): use generic
+ flags.
+
+ * eval.c (Init_Proc), gc.c (Init_GC): freeze preallocated special exceptions.
+
+ * gc.c (rb_memerror): use thread raised flag instead of static flag,
+ and raise nomem_error without backtrace if failed to make backtrace.
+ [ruby-dev:34724]
+
+ * gc.c (ruby_xmalloc): increase malloc_increase only if malloc
+ succeeds. failed malloc size can be huge. it may increase
+ malloc_limit too big which cause less GC and memory full.
+ (ruby_xrealloc): ditto.
+
+Mon Jul 7 12:23:05 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c: avoid creating Ruby object during
+ GC. thanks to arton <artonx AT yahoo.co.jp>. [ruby-dev:35313]
+
+ * ext/win32ole/tests: add test_win32ole_event.rb, remove
+ testOLEEVENT.rb
+
+ * ext/win32ole/tests/testWIN32OLE.rb(test_convert_bignum):
+ fix test.
+
+Mon Jul 7 12:23:05 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * gc.c: add rb_during_gc(). based on a patch from arton <artonx AT
+ yahoo.co.jp> at [ruby-dev:35313].
+
+ * intern.h: ditto.
+
+Thu Jul 3 20:13:20 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (w_object, marshal_dump, r_object0, marshal_load): search
+ public methods only. [ruby-core:17283]
+
+ * object.c (convert_type): ditto.
+
+ * lib/singleton.rb (Singleton#_dump): conversion method should be
+ public.
+
+Wed Jul 2 19:06:43 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/cgi.rb (CGI::QueryExtension.read_multipart): blanks inside
+ double quotes are allowed. [ruby-list:45140]
+
+Wed Jul 2 19:03:37 2008 Tanaka Akira <akr@fsij.org>
+
+ * numeric.c (num_coerce): call rb_Float(x) first. don't depend on
+ evaluation order of function arguments.
+
+Wed Jul 2 18:57:19 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/syslog/syslog.c (syslog_write): syslog operations should be
+ protected from $SAFE level 4. a patch from Keita Yamaguchi
+ <keita.yamaguchi at gmail.com>.
+
+ * ext/syslog/syslog.c (mSyslog_close): ditto.
+
+ * ext/syslog/syslog.c (mSyslog_set_mask): ditto.
+
+Wed Jul 2 18:26:20 2008 Tanaka Akira <akr@fsij.org>
+
+ * math.c (domain_check): fix preprocess condition.
+
+Wed Jul 2 18:22:52 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/tmpdir.rb (@@systmpdir): prior LOCAL_APPDATA if possible, and
+ should be clean. based on a patch from arton <artonx AT
+ yahoo.co.jp> at [ruby-dev:35269]
+
+Wed Jul 2 18:16:19 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (date2time_str): fix the overflow in
+ some situation. [ruby-bugs-20793]
+
+Tue Jul 1 15:11:14 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (rb_ary_fill): check if beg is too big.
+
+Mon Jun 30 20:35:32 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (str_buf_cat): check for self concatenation.
+
+Sun Jun 29 21:39:54 2008 Tanaka Akira <akr@fsij.org>
+
+ * eval.c (rb_obj_respond_to): use RTEST to test the result of
+ respond_to? method.
+
+Sun Jun 29 21:20:17 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * array.c (rb_ary_fill): (compatibility) do not raise
+ ArgumentError on negative length. This behaviour shall change
+ in a future release.
+
+Sun Jun 29 20:08:11 2008 Tanaka Akira <akr@fsij.org>
+
+ * time.c (time_timeval): fix rounding negative float.
+
+Sun Jun 29 19:19:08 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * test/inlinetest.rb (InlineTest.in_progname): workaround for frozen
+ $0. [ruby-dev:35261]
+
+ * lib/test/unit/ui/console/testrunner.rb (TestRunner#finished): ditto.
+
+Sun Jun 29 19:19:08 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ruby.c (set_arg0, ruby_prog_init): freeze $0. a patch from Keita
+ Yamaguchi <keita.yamaguchi at gmail.com>.
+
+Sun Jun 29 18:33:33 2008 Tanaka Akira <akr@fsij.org>
+
+ * process.c: include sys/resource.h if HAVE_SYS_RESOURCE_H is defined.
+ pointed by TOYOFUKU Chikanobu. [ruby-dev:35258]
+
+Sun Jun 29 18:26:01 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * variable.c (rb_f_trace_var): should not be allowed at safe level 4.
+ a patch from Keita Yamaguchi <keita.yamaguchi at gmail.com>.
+
+ * eval.c (rb_call0): wrong condition to check insecure method.
+ a patch from Keita Yamaguchi <keita.yamaguchi at gmail.com>.
+
+Sun Jun 29 18:22:52 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (rb_ary_fill): not depend on unspecified behavior at integer
+ overflow. reported by Vincenzo Iozzo <snagg AT openssl.it>.
+
+Sun Jun 29 18:22:06 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c(ole_invoke): fix memory leak.
+ [ruby-bugs-20792]
+
+Sun Jun 29 18:19:11 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (PUSH_FRAME, PUSH_CLASS): Add volatile to avoid a
+ possible optimization bug on OS X/PPC. This at least makes
+ build with gcc -O1 and `make test' pass.
+
+Sun Jun 29 17:24:43 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/rdoc/parsers/parse_rb.rb (RDoc#collect_first_comment): skip
+ magic comment.
+
+Sun Jun 29 17:22:09 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_each, strio_readlines): IO#each and
+ IO#readlines do not affect $_. [ruby-core:17277]
+
+Sun Jun 29 17:19:59 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_readline, strio_each)
+ (strio_readlines): set lastline. [ruby-core:17257]
+
+Sun Jun 29 17:15:49 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/openssl/ossl.h: include winsock.h if USE_WINSOCK2 is not defined.
+ a patch from arton <artonx at yahoo.co.jp> in [ruby-dev:35078]
+
+Sun Jun 29 17:09:48 2008 wanabe <s.wanabe@gmail.com>
+
+ * util.c (ruby_strtod): ruby_strtod don't allow a trailing
+ decimal point like "7.". [ruby-dev:34835] [ruby-dev:35009]
+
+Sat Jun 28 19:23:40 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * class.c (clone_method): use rb_copy_node_scope.
+ fixed [ruby-list:45102]
+ fixed [ruby-core:17393]
+
+Sat Jun 28 18:49:50 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * class.c: revert to r15855.
+
+Fri Jun 20 18:25:18 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (rb_str_buf_append): should infect.
+
+Fri Jun 20 16:33:09 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (rb_ary_store, rb_ary_splice): not depend on unspecified
+ behavior at integer overflow.
+
+ * string.c (str_buf_cat): ditto.
+
+Wed Jun 18 22:24:46 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * array.c (ary_new, rb_ary_initialize, rb_ary_store,
+ rb_ary_aplice, rb_ary_times): integer overflows should be
+ checked. based on patches from Drew Yao <ayao at apple.com>
+ fixed CVE-2008-2726
+
+ * string.c (rb_str_buf_append): fixed unsafe use of alloca,
+ which led memory corruption. based on a patch from Drew Yao
+ <ayao at apple.com> fixed CVE-2008-2726
+
+ * sprintf.c (rb_str_format): backported from trunk.
+
+ * intern.h: ditto.
+
+Tue Jun 17 15:09:46 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (file_expand_path): no need to expand root path which has no
+ short file name. [ruby-dev:35095]
+
+Sun Jun 15 19:27:40 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * configure.in: Fix $LOAD_PATH. Properly expand vendor_ruby
+ directories; submitted by Takahiro Kambe <taca at
+ back-street.net> in [ruby-dev:35099].
+
+Mon Jun 9 17:56:30 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/set.rb (Set#delete_if): Call to_a.
+ (SortedSet#delete_if, TC_SortedSet#test_sortedset): Use super to
+ yield elements in sorted order; [ruby-core:17144] by Arthur
+ Schreiber.
+ (SortedSet#each, SortedSet#each, TC_Set#test_each)
+ (TC_SortedSet#test_sortedset): Return self; [ruby-dev:35002] by
+ Arthur Schreiber.
+
+Mon Jun 9 03:28:05 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/zlib/zlib.c (rb_deflate_initialize, Init_zlib): Fix up
+ initialize_copy; [ruby-list:45016], [ruby-list:45018].
+
+Mon Jun 9 03:26:03 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * NEWS: Mention new constants.
+
+Mon Jun 9 03:24:18 2008 Tanaka Akira <akr@fsij.org>
+
+ * hash.c (hash_i): make Hash#hash order insensitive.
+
+Mon Jun 9 03:22:43 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (VENDOR_DIR): use LIBDIR instead of PREFIX as well as
+ SITE_DIR. a patch from Richard Brown <rbrown AT exherbo.org> in
+ [ruby-core:17129].
+
+Mon Jun 9 03:21:20 2008 Tanaka Akira <akr@fsij.org>
+
+ * gc.c (os_obj_of): assure to not free the scanning heap.
+
+Mon Jun 9 03:20:12 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * io.c (rb_open_file, rb_io_s_sysopen): fmode should be unsigned int.
+ fixed [ruby-dev:34979]
+
+Fri Jun 6 21:16:55 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/Makefile.sub (COMMON_HEADERS): include ws2tcpip.h.
+
+ * ext/socket/addrinfo.h (addrinfo, getaddrinfo, getnameinfo,
+ freehostent, freeaddrinfo): undef before define because these are
+ macros in some versions of Windows SDK.
+
+ * win32/setup.mak: maybe commit miss.
+
+Fri Jun 6 19:34:22 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * mkconfig.rb: hide build path from rbconfig.rb.
+
+ * util.c (ruby_strtod, dtoa): initialize more variables for error
+ handling.
+
+ * io.c (rscheck), marshal.c (w_nbyte, w_bytes, w_unique),
+ (path2class, path2module): constified.
+
+ * pack.c (pack_unpack), process.c (rb_syswait): suppress warnings.
+
+ * suppress warnings on cygwin, mingw and mswin.
+
+Fri Jun 6 19:23:53 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (file_expand_path): fix for non-existent files and SFN of
+ symlinks. [ruby-talk:303736]
+
+Fri Jun 6 18:25:43 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * test/iconv: Tests fixed.
+
+Fri Jun 6 17:04:56 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * win32/win32.h: include ws2tcpip.h. fixed [ruby-Bugs-20528]
+
+ * lib/time.rb (Time.xmlschema): don't use float. fix
+ http://rubyforge.org/tracker/index.php?func=detail&group_id=426&atid=1698&aid=20504
+
+ * object.c (rb_obj_alloc): RDoc updated. a patch from Gaston
+ Ramos <ramos.gaston at gmail.com> in [ruby-core:17073].
+
+ * lib/rdoc.rb: massive spelling correction patch from Evan Farrar
+ <evanfarrar at gmail.com> in [ruby-doc:1382] applied.
+
+ * ext/openssl/ossl_ssl_session.c (ossl_ssl_session_initialize):
+ Add a null check for ssl; submitted by akira yamada
+ in [ruby-dev:34950].
+
+ * ext/openssl/ossl_ssl.c (Init_ossl_ssl): Define OP_NO_TICKET if
+ SSL_OP_NO_TICKET is present; submitted by akira yamada
+ in [ruby-dev:34944].
+
+ * test/openssl/test_ssl.rb (OpenSSL#test_server_session): Add a
+ workaround for the case where OpenSSL is configured with
+ --enable-tlsext; submitted by akira yamada in [ruby-dev:34944].
+
+Fri Jun 6 16:58:23 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/iconv/iconv.c (iconv_iconv): fix for length argument and now
+ allows range. [ruby-core:17092] [ruby-core:17115]
+
+Wed Jun 4 17:22:30 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * NEWS: Fix typos and move misplaced entries.
+ NEWS: Somehow optflags and warnflags were not actually included
+ in this release.
+
+Tue Jun 3 19:33:22 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enumerator.c (enumerator_init_copy): Take care of
+ initialize_copy as well as initialize.
+
+ * test/ruby/test_enumerator.rb: Pull in the test suite for
+ enumerator from trunk.
+
+Tue Jun 3 12:51:57 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enumerator.c (enumerator_allocate, enumerator_ptr): Properly
+ detect if the object is initialized and raise error when
+ appropriate.
+ (enumerator_initialize): Fix a typo in rdoc. [ruby-core:17052]
+
+Tue Jun 3 10:16:40 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/erb.rb (ERB::Compiler::TrimScanner#scan_line): Fix a bug
+ where tokens are not yilelded one by one.
+ (ERB::Compiler::TrimScanner#explicit_trim_line): Fix without-
+ strscan problems. [ruby_core:17028].
+
+ * test/erb/test_erb.rb (TestERBCore#_test_01)
+ (TestERBCore#test_02_safe_04): The expected value should come
+ first for assert_equal().
+ (TestERBCoreWOStrScan): Add test class for without-strscan.
+
+Mon Jun 2 19:47:16 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/delegate.rb (DelegateClass, Delegator#respond_to?):
+ respond_to? must take optional second argument. This was a
+ latent bug exposed by a recent internal change of marshal.c to
+ call respond_to? with a second argument; submitted by Jeremy
+ Kemper <jeremy at bitsweat.net> in [ruby-core:17045].
+
+Sat May 31 23:53:35 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * .: Release as Ruby 1.8.7.
+
+Sat May 31 23:33:34 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * README, README.ja: Add a note about default C flags.
+
+Sat May 31 22:11:15 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * version.c (ruby_description, ruby_copyright): backported from
+ 1.9. bug#19002, [ruby-dev:34883]
+
+ * error.c (report_bug): uses ruby_description.
+
+Sat May 31 20:56:04 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_delete_if): should return enumerator if no block
+ is given. [ruby-dev:34901]
+
+Sat May 31 18:28:17 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * suppress warnings with -Wwrite-string.
+
+Sat May 31 15:58:08 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in, configure.in (warnflags): defaulted to -Wall
+ -Wno-parentheses with gcc. [ruby-dev:34810]
+
+Fri May 30 05:28:18 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * enum.c (count_i, count_iter_i, count_all_i): add prototypes for VC.
+
+Fri May 30 04:32:07 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enum.c (count_i, count_iter_i): Sync with trunk.
+ enum.c (enum_count, count_all_i, Init_Enumerable),
+ array.c (rb_ary_count): Sync with trunk. If no argument or
+ block is given, count the number of all elements.
+
+Fri May 30 03:12:18 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/openssl/ossl_bn.c (ossl_bn_s_rand, ossl_bn_s_pseudo_rand):
+ Int should be enough here.
+
+Fri May 30 02:35:00 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/openssl/ossl_bn.c (ossl_bn_s_rand, ossl_bn_s_pseudo_rand),
+ ext/openssl/ossl_pkey_dh.c (ossl_dh_s_generate)
+ (ossl_dh_initialize),
+ ext/openssl/ossl_pkey_dsa.c (ossl_dsa_s_generate),
+ ext/openssl/ossl_rand.c (ossl_rand_bytes)
+ (ossl_rand_pseudo_bytes, ossl_rand_egd_bytes),
+ ext/openssl/ossl_x509store.c (ossl_x509stctx_set_error): Do not
+ use FIX2INT() without checking the value type. Use NUM2INT()
+ instead; found by akr in [ruby-dev:34890].
+
+Thu May 29 20:07:45 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * configure.in, win32/Makefile.sub, mkconfig.rb, instruby.rb,
+ ruby.c, lib/mkmf.rb, README.EXT, README.EXT.ja: Backport the
+ vendor_ruby directory support.
+
+Thu May 29 17:52:31 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/zlib/extconf.rb: search zlib1, and regard mswin32 later than VC6
+ as WIN32. [ruby-core:16984]
+
+Wed May 28 17:54:29 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * string.c (rb_str_start_with): Remove an unused variable.
+ (rb_str_upto_m): Fix a prototype.
+
+Wed May 28 17:48:28 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * range.c (range_step): Fix brokenness when a non-integer numeric
+ value is specified as step. [rubyspec]
+ (range_step): Make use of String#step internally if a string (or
+ string-alike) range is given.
+
+ * string.c (rb_str_upto_m, Init_String): Add an optional second
+ argument to specify if the last value should be included.
+
+Wed May 28 16:53:39 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_slice_bang): Call rb_ary_modify_check() at the
+ beginning. [rubyspec]
+
+Wed May 28 16:12:44 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/webrick/httpservlet/cgihandler.rb (WEBrick::HTTPServlet::CGIHandler#do_GET):
+ Set the HTTP status code to 302 if a Location header field is
+ present and the status code is not valid as a client
+ redirection. cf. RFC 3875 6.2.3, 6.2.4.
+
+Wed May 28 15:18:16 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/singleton.rb (SingletonClassMethods): _load should be public.
+
+Wed May 28 12:52:41 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (w_object, marshal_dump, r_object0, marshal_load): search
+ private methods too. [ruby-dev:34671]
+
+ * object.c (convert_type): ditto.
+
+Tue May 27 23:26:49 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * error.c (rb_bug): description from rb_bug() should include
+ patchlevel. [ruby-dev:34826]
+
+Tue May 27 20:19:22 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_slice_bang): Return an empty array instead of
+ nil when pos is valid and len is adjusted from a valid value to
+ zero; caught by RubySpec.
+
+Tue May 27 19:45:20 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * numeric.c (flo_divmod): Revert the behavior change; do not
+ suppress an exception when div is NaN or Inf. [ruby-dev:34857]
+
+Tue May 27 19:24:40 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enum.c (enum_to_a): Pass arguments through to #each().
+ (enum_sort): Follow the enum_to_a signature change.
+ (enum_reverse_each): Add #reverse_each().
+
+Tue May 27 18:54:02 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/stringio/stringio.c (strio_each_char, Init_stringio): Add
+ StringIO#{each_char,chars}.
+
+Tue May 27 17:59:34 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/stringio/stringio.c (strio_each): Return an enumerator if no
+ block is given.
+ (strio_each_byte): Return an enumerator if no block is given,
+ and return self if one is given as the rdoc says.
+
+ * io.c (rb_io_each_byte): Fix rdoc. IO#each_byte returns self,
+ not nil.
+
+Tue May 27 16:02:58 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (rb_mod_module_exec, Init_eval): Add
+ Module#{module_exec,class_exec}.
+
+Tue May 27 15:36:37 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * io.c (rb_io_each_char, argf_each_char, Init_IO):
+ Add {IO#,ARGF.}{each_char,chars}.
+
+Tue May 27 13:46:52 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/stringio/stringio.c (Init_stringio): Define
+ StringIO#{getbyte,readbyte}.
+
+Tue May 27 13:38:51 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * io.c (Init_IO): Define {IO#,ARGF.}{getbyte,readbyte}.
+
+Tue May 27 13:26:15 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/stringio/stringio.c (Init_stringio): Define #bytes and
+ #lines.
+
+Tue May 27 13:20:35 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * io.c: (rb_io_lines, rb_io_bytes, Init_IO): Define
+ IO#{lines,bytes} and ARGF.{lines,bytes}.
+
+Tue May 27 12:13:17 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * file.c (BUFCHECK): wrong condition. [ruby-core:16921]
+
+ * file.c (file_expand_buf): shouldn't use buflen for length of string.
+
+Mon May 26 18:24:48 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (BUFCHECK): no resize if enough room.
+
+ * file.c (file_expand_path): use BUFCHECK.
+
+Mon May 26 16:46:19 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * file.c (ntfs_tail): filename which starts with '.' is valid.
+
+ * file.c (file_expand_path): cygwin symlink support.
+
+Mon May 26 12:16:43 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * .: Release as Ruby 1.8.7-preview4.
+
+Mon May 26 12:12:26 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * marshal.c (dump_ensure, load_ensure): should return values.
+
+ * eval.c (yield_under, yield_under_i, yield_args_under_i)
+ (specific_eval, rb_obj_instance_exec, Init_eval): Implement
+ Object#instance_exec(), a 1.9 feature.
+
+Mon May 26 11:53:21 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (rb_yield_0, proc_invoke, proc_arity): allow passing a
+ block to a Proc. [ruby-dev:23533]; by nobu; backported from
+ 1.9. This implementation in current shape is known to be
+ buggy/broken, especially with nested block invocation. Take
+ this as an experimental feature.
+
+ * parse.y (block_par, block_var): ditto.
+
+Mon May 26 08:00:52 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * marshal.c (r_object0, Init_marshal): Fix the garbled s_call
+ definition; fixes [ruby-dev:34843].
+
+Mon May 26 03:16:20 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * hash.c (rb_hash_default): Fix rdoc.
+ (rb_hash_each, env_each_value, env_each_pair): Return an
+ enumerator if no block is given.
+ (rb_hash_update): Update rdoc.
+ (envix): Conditionalize the definition itself.
+ (rb_f_getenv, env_fetch, env_keys, env_values, env_values_at)
+ (env_select, env_inspect, env_to_a, env_empty_p, env_has_key)
+ (env_has_value, env_index, env_indexes, env_to_hash, env_shift)
+ (env_update): Require secure level 4.
+ (env_each_value, env_each_i): Delay variable initialization.
+ (env_each_key, env_each_value, env_reject_bang)
+ (env_clear, env_replace): Omit duplicated secure level check.
+ (env_has_value): Do to_str conversion.
+
+Sun May 25 19:48:12 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * hash.c (env_delete_if): Return an enumerator if no block is
+ given.
+ (env_each_key): Delay a variable initialization after
+ RETURN_ENUMERATOR().
+
+Sun May 25 05:07:19 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_slice_bang): Be consistent with Array#slice()
+ and String#slice!(). Just return nil when a negative length or
+ out of boundary index is given instead of raising an exception
+ via internal functions.
+ (rb_ary_slice_bang): should not use rb_ary_subseq() which shares
+ internal pointer. splice modifies the receiver right after
+ subseq. [ruby-dev:34005]
+ (rb_ary_slice_bang): should adjust length before making
+ sub-array.
+
+ * enumerator.c (Init_Enumerator): Override
+ Enumerable::Enumerator#each_with_index with #with_index.
+
+Sun May 25 03:13:09 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (Init_Thread): Initialize recursive_key.
+
+Sun May 25 02:45:49 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * error.c (syserr_eqq): Use en.
+
+Sat May 24 22:32:49 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (rb_cstr_to_dbl): should clear errno before calling
+ strtod(3). [ruby-dev:34834]
+
+Sat May 24 22:27:44 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (marshal_load): should initialize arg.data used for
+ reentrant check. [ruby-dev:34837]
+
+Sat May 24 00:34:59 2008 Tanaka Akira <akr@fsij.org>
+
+ * lib/rational.rb (Rational#to_i): fix rdoc. Rational(-7,4).to_i
+ should be -1.
+
+Fri May 23 20:22:44 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (reentrant_check): check reentrance via callcc.
+ [ruby-dev:34802]
+
+Fri May 23 16:46:28 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enumerator.c (proc_call): Remove an unused static function.
+
+Fri May 23 13:46:09 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (cflags): commit miss.
+
+Fri May 23 09:52:21 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (MINIRUBY), common.mk (RUBYOPT): add purelib.rb.
+ [ruby-core:16642]
+
+ * ext/extmk.rb: load purelib.rb only when not cross compiling.
+
+Fri May 23 08:47:02 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * error.c (syserr_eqq): === should be able to handle delegated
+ objects as well.
+
+Fri May 23 04:22:19 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tcltklib.c, ext/tk/tkutil/tkutil.c: fix memory leak.
+
+ * ext/tk/lib/tk.rb: avoid trouble when finalize TclTkIp.
+
+ * ext/tk/lib/tk.rb, ext/tk/lib/tk/*: help to fix troubles when
+ use Ttk widgets on old Tk scripts.
+
+ * ext/tk/sample/*: update and add demo scripts. some of them are
+ introduction about new features of Tcl/Tk8.5.
+
+Fri May 23 03:48:10 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * class.c (clone_method): Just use ruby_cref as cref.
+
+Fri May 23 01:03:23 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * class.c (rb_singleton_class_clone): Pass Qnil, not 0.
+
+Fri May 23 00:51:48 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * class.c (clone_method): Totally revamp the previous fix which
+ was incorrect.
+ (rb_mod_init_copy): Ditto.
+ (singleton_class_clone_int): Ditto.
+
+Fri May 23 00:48:10 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (rb_copy_node_scope), node.h: Rename from copy_node_scope
+ and export.
+
+Thu May 22 21:24:15 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (top_local_setup): fixed memory leak bug based on a
+ patch from Roger Pack <rogerpack2005 at gmail.com> in
+ [ruby-core:16610].
+
+Thu May 22 14:20:54 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (flatten): check if reentered. [ruby-dev:34798]
+
+Thu May 22 08:28:49 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (flatten): free memo hash table before raising exception.
+ [ruby-dev:34789]
+
+Thu May 22 06:30:10 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * array.c (flatten): fix memory leak.
+
+Thu May 22 05:45:30 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * proc.c (proc_dup): should copy safe_level from src proc
+ properly. a patch from Keita Yamaguchi
+ <keita.yamaguchi at gmail.com>
+
+Wed May 21 23:31:44 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_get_method_body, rb_alias, rb_eval): should not cache
+ uninitialized value, since search_method doesn't set origin if the
+ method wasn't found.
+
+ * eval.c (search_method, remove_method, error_print, rb_alias)
+ (rb_eval, rb_rescue2, search_required, Init_eval, rb_thread_create),
+ gc.c (rb_source_filename, Init_stack), io.c (rb_io_getline),
+ parse.y (rb_id2name, rb_parser_free): suppress warnings.
+
+Wed May 21 12:34:51 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (rb_hash_delete): rdoc fix based on a patch from Gaston Ramos
+ <ramos.gaston AT gmail.com>. [ruby-core:16825]
+
+Tue May 20 13:15:46 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * file.c (lchmod_internal): Remove a compiler warning.
+
+Mon May 19 18:22:35 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/openssl/ossl_pkcs5.c (ossl_pkcs5_pbkdf2_hmac): Fix the type
+ of md; pointed out by Takahiro Kambe <taca at back-street.net>
+ in [ruby-dev:34748].
+
+Mon May 19 14:20:13 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): fixed SEGV on win32 with "% 0e" % 1.0/0.0.
+
+Mon May 19 13:29:58 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * process.c (rb_f_system): set last_status when status == -1 because
+ there is no path to set it on win32. this patch is derived from
+ [ruby-core:16787], submitted by Luis Lavena <luislavena at gmail.com>
+
+Mon May 19 13:01:05 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk ({MSPEC,RUBYSPEC}_GIT_URL): moved from Makefine.in.
+
+ * {win32,bcc32}/Makefile.sub (update-rubyspec): added.
+
+Mon May 19 11:53:45 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/openssl/openssl_missing.c (HMAC_CTX_copy): adopted
+ prototype change in openssl bundled with newer OpenBSD.
+ a patch from Takahiro Kambe <taca at back-street.net> in
+ [ruby-dev:34691].
+
+Mon May 19 06:36:37 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * .: Release as Ruby 1.8.7-preview3.
+
+Sun May 18 22:26:51 2008 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httpservlet/filehandler.rb: should normalize path
+ name in path_info to prevent script disclosure vulnerability on
+ DOSISH filesystems. (fix: CVE-2008-1891)
+ Note: NTFS/FAT filesystem should not be published by the platforms
+ other than Windows. Pathname interpretation (including short
+ filename) is less than perfect.
+
+ * lib/webrick/httpservlet/abstract.rb
+ (WEBrick::HTTPServlet::AbstracServlet#redirect_to_directory_uri):
+ should escape the value of Location: header.
+
+ * lib/webrick/httpservlet/cgi_runner.rb: accept interpreter
+ command line arguments.
+
+Sat May 17 23:53:57 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (file_expand_path): fix for short file name on Cygwin.
+
+Sat May 17 11:29:11 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_file_s_extname): first dot is not an extension name.
+
+Sat May 17 10:18:44 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (rb_reg_search): need to free allocated buffer in re_register.
+
+Fri May 16 17:01:44 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/Makefile.sub (test-rubyspec): added.
+
+Fri May 16 16:22:40 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tcltklib.c: sometimes freeze when receive Interrupt signal.
+
+Fri May 16 14:54:56 2008 Tanaka Akira <akr@fsij.org>
+
+ * Makefile.in (update-rubyspec): move rubyspec to srcdir.
+ (test-rubyspec): ditto.
+
+Fri May 16 14:25:22 2008 Tanaka Akira <akr@fsij.org>
+
+ * Makefile.in (test-rubyspec): use RUNRUBY. suggested by nobu.
+
+Fri May 16 13:01:43 2008 Tanaka Akira <akr@fsij.org>
+
+ * Makefile.in (update-rubyspec): new target to download rubyspec.
+ (test-rubyspec): new target to run rubyspec. this doesn't work
+ before install.
+
+Fri May 16 08:15:52 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: fix memory (object) leak bug.
+
+ * ext/tk/sample/demos-jp/aniwave.rb, ext/tk/sample/demos-en/aniwave.rb:
+ bug fix.
+
+Thu May 15 17:00:22 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * string.c (Init_String): Define #bytesize as an alias for #size
+ for compatibility with 1.9.
+
+Thu May 15 15:33:59 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (file_expand_path): support for alternative data stream
+ and ignored trailing garbages of NTFS.
+
+ * file.c (rb_file_s_basename): ditto.
+
+ * file.c (rb_file_s_extname): ditto.
+
+Wed May 14 19:24:59 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_count): Override Enumerable#count for better
+ performance.
+ (rb_ary_nitems): Undo the backport. Use #count {} instead.
+
+ * enumerator.c (enumerator_iter_i): Remove an unused function.
+ (enumerator_with_index, enumerator_each): Remove unused
+ variables.
+
+Wed May 14 17:15:11 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/tk/tkutil/extronf.rb: check stdndup() because it's not standard
+ function of C.
+
+ * ext/tk/tkutil/tkutil.c (cbsubst_table_setup): use malloc() and
+ strncpy() instead of strndup() if not available.
+
+Wed May 14 09:52:02 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tkutil/tkutil.c: improve handling callback-subst-keys.
+ Now, support longnam-keys (e.g. '%CTT' on tkdnd-2.0; however, still
+ not support tkdnd-2.0 on tkextlib), and symbols of parameters (e.g.
+ :widget=>'%W', :keycode=>'%k', '%x'=>:x, '%X'=>:root_x, and so on;
+ those are attributes of event object). It means that Ruby/Tk accepts
+ not only "widget.bind(ev, '%W', '%k', ...){|w, k, ...| ... }", but
+ also "widget.bind(ev, :widget, :keycode, ...){|w, k, ...| ... }".
+ It is potentially incompatible, when user passes symbols to the
+ arguments of the callback block (the block receives the symbols as
+ strings). I think that is very rare case (probably, used by Ruby/Tk
+ experts only). When causes such trouble, please give strings instead
+ of such symbol parameters (e.g. call Symbol#to_s method).
+
+ * ext/tk/lib/tk/event.rb, ext/tk/lib/tk/validation.rb,
+ ext/tk/lib/tkextlib/blt/treeview.rb,
+ ext/tk/lib/tkextlib/winico/winico.rb: ditto.
+
+ * ext/tk/tkutil/tkutil.c: strings are available on subst_tables on
+ TkUtil::CallbackSubst class (it is useful on Ruby 1.9).
+
+ * ext/tk/lib/tk/spinbox.rb, ext/tk/lib/tkextlib/iwidgets/hierarchy.rb,
+ ext/tk/lib/tkextlib/iwidgets/spinner.rb,
+ ext/tk/lib/tkextlib/iwidgets/entryfield.rb,
+ ext/tk/lib/tkextlib/iwidgets/calendar.rb,
+ ext/tk/lib/tkextlib/blt/dragdrop.rb,
+ ext/tk/lib/tkextlib/tkDND/tkdnd.rb,
+ ext/tk/lib/tkextlib/treectrl/tktreectrl.rb,
+ ext/tk/lib/tkextlib/tktable/tktable.rb: disable code piece became
+ unnecessary by reason of the changes of ext/tk/tkutil/tkutil.c.
+
+Tue May 13 15:10:50 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enumerator.c: Update rdoc.
+ (enumerator_initialize): Discourage the use.
+ (enum_each_slice, enum_each_cons, enumerator_each)
+ (enumerator_with_index): Add a note about a call without a block.
+
+ * NEWS: Intentionally omit enum_slice and enum_cons, which are
+ removed in 1.9.
+
+Tue May 13 07:56:36 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_cat): fixed buffer overrun reported by
+ Christopher Thompson <cthompson at nexopia.com> in [ruby-core:16746]
+
+Mon May 12 13:57:19 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (is_defined): add NODE_OP_ASGN_{OR,AND}. "defined?(a||=1)"
+ should not operate assignment. [ruby-dev:34645]
+
+Mon May 12 12:59:23 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/wm.rb: Wm#overrideredirect overwrites arguemnt to
+ an invalid value.
+
+ * ext/tk/sample/ttk_wrapper.rb: support "if __FILE__ == $0" idiom.
+
+Mon May 12 12:36:55 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_select): backport from trunk.
+ [ruby-talk:300743]
+
+Mon May 12 12:33:21 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (RUBYLIB, RUBYOPT): clear.
+
+Mon May 12 10:41:10 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/delegate.rb (SimpleDelegator::dup): removed needless argument.
+ [ruby-list:44910]
+
+ * lib/delegate.rb (clone, dup): keep relationship with the target
+ object.
+
+Sun May 11 23:19:39 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * enum.c (all_iter_i, any_iter_i): reduced duplicated code.
+
+Sun May 11 17:57:36 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (MINIRUBY): should not include extension library path.
+
+Sun May 11 10:36:10 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * eval.c (method_name, method_owner): New methods; backported
+ from 1.9. (UnboundMethod#name, UnboundMethod#owner)
+
+Sun May 11 02:48:13 2008 <nagai@orca16.orcabay.ddo.jp>
+
+ * ext/tk/lib/tk/pack.rb, ext/tk/lib/tk/grid.rb: fail to do pack/grid
+ without options.
+
+ * ext/tk/lib/tk.rb: add TkWindow#grid_anchor, grid_column, grid_row.
+
+Sat May 10 18:19:16 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_each_line): RDoc updated. [ruby-dev:34586]
+
+Sat May 10 13:17:56 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/pack.rb, ext/tk/lib/tk/grid.rb: increase supported
+ parameter patterns of configure method.
+
+Sat May 10 09:16:13 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * util.c (ruby_strtod): backported from 1.9. a patch from Satoshi
+ Nakagawa <psychs at limechat.net> in [ruby-dev:34625].
+ fixed: [ruby-dev:34623]
+
+Fri May 9 23:33:25 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/wm.rb: methods of Tk::Wm_for_General module cannot
+ pass the given block to methods of Tk::Wm module.
+
+ * ext/tk/lib/tk/grid.rb: lack of module-method definitions.
+
+ * ext/tk/lib/tkextlib/tile.rb: lack of autoload definitions.
+
+ * ext/tk/lib/tkextlib/tile/tnotebook.rb: cannot use kanji (not UTF-8)
+ characters for headings.
+
+ * ext/tk/tcltklib.c: maybe a little more stable about @encoding value
+ of TclTkIp object.
+
+Wed May 7 08:46:44 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * struct.c (rb_struct_s_def): to_str should be called only once.
+ [ruby-core:16647]
+
+Wed May 7 00:54:25 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/zlib/zlib.c (gzreader_gets): may cause infinite loop.
+ a patch from Kouya <kouyataifu4 at gmail.com> in
+ [ruby-reference-manual:762].
+
+Sun May 4 09:35:51 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * sample/erb/erb4html.rb (ERB4Html) : add example of ERB#set_eoutvar.
+ ERB4Html is an auto-quote ERB.
+
+Sat May 3 22:52:48 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tkextlib/tile.rb, ext/tk/lib/tkextlib/tile/style.rb,
+ ext/tk/sample/ttk_wrapper.rb: improve treating and control themes.
+ add Tk::Tile.themes and Tk::Tile.set_theme(theme).
+
+Fri May 2 14:52:33 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * misc/ruby-mode.el: move fontifying code from hook. a patch from
+ Phil Hagelberg <phil at hagelb.org> in [ruby-core:16636].
+
+Fri May 2 13:47:51 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (match_select): restore previous behavior of MatchData#select.
+ RDoc updated as well, mentioning the plan to remove this method
+ in the future. [ruby-dev:34556]
+
+Fri May 2 13:04:04 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/dbm/dbm.c (Init_dbm): defines DBM::VERSION even when
+ DB_VERSION_STRING is not available. [ruby-dev:34569]
+
+Thu May 1 23:57:06 2008 James Edward Gray II <jeg2@ruby-lang.org>
+
+ Merged 16257 from trunk.
+
+ * lib/net/telnet.rb: This patch from Brian Candler adds a FailEOF mode which
+ can be activated to have net/telnet raise EOFError exceptions when the
+ remote connection is closed. The default behavior remains unchanged though.
+
+Thu May 1 23:43:21 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * range.c (range_step): check if step can be converted to an integer.
+ [ruby-dev:34558]
+
+ * range.c (range_step): allow float step bigger than zero but less
+ than one. [ruby-dev:34557]
+
+Wed Apr 30 20:22:40 2008 James Edward Gray II <jeg2@ruby-lang.org>
+
+ Merged 16241 from trunk.
+
+ * lib/net/telnet.rb: Fixing a bug where line endings would not be properly
+ escaped when the two character ending was broken up into separate TCP
+ packets. Issue reported and patched by Brian Candler.
+
+Wed Apr 30 17:47:21 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * re.c (rb_reg_search): use local variable. a patch from wanabe
+ <s.wanabe AT gmail.com> in [ruby-dev:34537]. [ruby-dev:34492]
+
+Sat Apr 26 19:40:34 2008 Guy Decoux <decoux@moulon.inra.fr>
+
+ * class.c (struct clone_method_data): Add cref.
+ (clone_method): Properly handle NODE_BMETHOD and NODE_DMETHOD.
+ (rb_singleton_class_clone, singleton_class_clone_int): Set a
+ proper value to klass and propagate cref. [ruby-core:16238]
+
+ * eval.c (rb_block_dup, rb_method_dup), intern.h: Add duplicator
+ methods for use from class.c#clone_method().
+
+Fri Apr 25 15:46:37 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb, ext/tk/lib/tk/scrollbar.rb, ext/tk/lib/tk/scale.rb:
+ improve unknonw-option check when create a widget.
+
+ * ext/tk/lib/tkextlib/blt/unix_dnd.rb, ext/tk/lib/tkextlib/blt/ted.rb,
+ ext/tk/lib/tkextlib/treectrl/tktreectrl.rb: bug fix on 'cget'.
+
+ * ext/tk/lib/tk/menuspec.rb: option check will fail when
+ TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ is true.
+
+ * ext/tk/lib/tk/palette.rb: bug fix.
+
+Fri Apr 25 12:37:54 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (flatten): returns an instance of same class.
+ [ruby-core:16554]
+
+Thu Apr 24 23:47:50 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * lib/net/pop.rb: backported from 1.9. bug#19003
+
+ * ext/openssl/lib/openssl/ssl.rb: set_params; backported from 1.9.
+ bug#19552, [ruby-dev:34402]
+
+ * ext/openssl/ossl_ssl.c: ditto.
+
+ * test/openssl/test_ssl.rb: ditto.
+
+Thu Apr 24 17:06:34 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (THREAD_SAVE_CONTEXT): remove unnecessary
+ FLUSH_REGISTER_WINDOWS before calling setjmp(). [ruby-core:16285]
+
+Thu Apr 24 14:15:11 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dln.c (dln_find_1): prior files with extensions to files sans
+ extensions. [ruby-core:16517]
+
+Wed Apr 23 15:39:31 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (bind_eval): Add Binding#eval, a shorthand method for
+ eval(str, binding, ..); backported from 1.9.
+
+Wed Apr 23 15:28:52 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * test/gdbm/test_gdbm.rb (TestGDBM#test_s_open_no_create): failed
+ notice moved from comment to assertion message. [ruby-dev:29127]
+
+Wed Apr 23 14:00:05 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/mkmf.rb (create_makefile): Add a missing dependency on the
+ target directory for each .rb file. This will hopefully fix
+ parallel make (-jN). Tested on FreeBSD.
+
+Wed Apr 23 11:49:54 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/set.rb (Set#each, SortedSet#each, TC_Set#test_each): Return
+ an enumerator if no block is given.
+
+Wed Apr 23 00:42:49 2008 Tanaka Akira <akr@fsij.org>
+
+ * eval.c (error_print): show full stack grace except SystemStackError.
+ backport from 1.9. [ruby-dev:31014]
+
+Wed Apr 23 00:18:45 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * test/ruby/test_symbol.rb (TestSymbol#test_to_proc): Improve
+ tests of Symbol#to_proc.
+
+Tue Apr 22 22:43:05 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (rb_proc_new, YIELD_FUNC_LAMBDA): Add a new nd_state
+ YIELD_FUNC_LAMBDA which avoids automatic `avalue' conversion for
+ arguments. This fixes a bug where [1,[2,3]].map(&:object_id)
+ fails.
+
+ * intern.h, object.c: Hide rb_proc_new() from intern.h. It should
+ not be considered an official API function yet.
+
+Tue Apr 22 21:24:32 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (rb_proc_new): Turn the BLOCK_LAMBDA flag on.
+
+ * object.c (sym_to_proc), test/ruby/test_symbol.rb: Add back
+ Symbol#to_proc, now that it passes the tests.
+
+Tue Apr 22 19:35:03 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enumerator.c (enumerator_initialize): Remove an undocumented
+ feature (passing a block to the constructor) that's broken.
+ This is not what I intended.
+
+Tue Apr 22 17:49:46 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): should protect temporary string from
+ GC. [ruby-dev:34480]
+
+Tue Apr 22 17:12:05 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * regex.c (re_search): string might be NULL. [ruby-core:16478]
+
+Tue Apr 22 16:44:00 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * object.c (rb_obj_tap): Correct documentation; pointed out by
+ okkez in [ruby-dev:34472].
+
+Tue Apr 22 10:05:51 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * file.c (eaccess): workaround for recent msvcrt's behavior.
+ [ruby-core:16460]
+
+Mon Apr 21 16:06:47 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * enumerator.c (enumerator_init): preserve the method name in ID.
+
+ * enumerator.c (enumerator_each): need not to call rb_to_id().
+
+ * enumerator.c (enumerator_with_index): ditto.
+
+Mon Apr 21 17:19:52 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (rb_f_method_name): New gloval function: __method__;
+ backported from matzruby / 1.9.
+
+ * eval.c (rb_frame_this_func), intern.h: New internal function.
+
+ * intern.h (RETURN_ENUMERATOR): Use rb_frame_this_func() instead
+ of rb_frame_last_func(), to accommodate the behavior to that of
+ 1.9.
+
+Mon Apr 21 15:54:48 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/tempfile.rb (Tempfile::_close): check @data before modifying
+ it; backported from 1.9. [ruby-dev:34094]
+
+ * lib/tempfile.rb (Tempfile::close): clear @data and @tmpname.
+
+Mon Apr 21 10:17:17 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * time.c: should include <errno.h> to refer errno.
+
+Mon Apr 21 10:02:43 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * hash.c (recursive_hash): prototype.
+
+Mon Apr 21 10:00:51 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * time.c (rb_strftime): check errno to detect strftime(3)'s error.
+ this is workaround for recent version of MSVCRT.
+ [ruby-dev:34456]
+
+Sun Apr 20 21:10:04 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * .: Release as Ruby 1.8.7-preview2.
+
+Sun Apr 20 21:02:06 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enumerator.c: Resolve the method every time an enumeration
+ method is run, not once when the enumerator is initialized as it
+ was before, so that method_missing() and method (re)definition
+ afterwards are both in effect; pointed out in: [ruby-core:16441]
+
+Sun Apr 20 17:59:25 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * object.c, NEWS, test/ruby/test_symbol.rb: Revert Symbol#to_proc
+ since it does not pass the tests.
+
+Sun Apr 20 14:29:35 2008 Technorama Ltd. <oss-ruby@technorama.net>
+
+ * ext/openssl/ossl_ssl.c: initialize session class.
+
+Sat Apr 19 20:54:42 2008 akira yamada <akira@arika.org>
+
+ * lib/uri/ftp.rb, lib/uri/generic.rb, test/uri/test_common.rb,
+ test/uri/test_ftp.rb, test/uri/test_generic.rb: backported from 1.9.
+ [ruby-dev:31318]
+
+Sat Apr 19 20:35:02 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/yaml/baseemitter.rb, lib/yaml/encoding.rb: performance
+ tuning around String#gsub.
+
+ * lib/yaml/tag.rb: Replace nodoc with stopdoc so Module methods get
+ documented.
+
+ * lib/yaml/store.rb (YAML::load): modified to support empty
+ database.
+
+ * lib/yaml/store.rb (YAML::Store::marshal_dump_supports_canonical_option?):
+ add a method to support faster PStore.
+
+Sat Apr 19 20:16:52 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/yaml/types.rb: Likewise, pass self to YAML::quick_emit;
+ merged from 1.9.
+
+ * lib/yaml.rb (quick_emit): use combination of object_id and hash to
+ identify repeated object references, since GC will reuse memory of
+ objects during output of YAML. [ruby-Bugs-8548] [ruby-Bugs-3698];
+ merged from 1.9.
+
+Sat Apr 19 20:05:39 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_equal, rb_ary_eql, rb_ary_hash, rb_ary_cmp):
+ Make Array#eql?, #hash, #== and #<=> use rb_exec_recursive() and
+ handle recursive data properly.
+
+ * hash.c (hash_equal, rb_hash_hash): Make Hash#eql?, #hash and #==
+ use rb_exec_recursive() and handle recursive data properly.
+
+Sat Apr 19 19:26:09 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * intern.h, eval.c (rb_exec_recursive): New internal function to
+ help perform recursive operation; backported from 1.9.
+
+Sat Apr 19 18:42:04 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * intern.h, hash.c (rb_hash_lookup): New internal function to
+ check if a key exists in a hash, ignoring #default; backported
+ from 1.9.
+
+Fri Apr 18 18:56:57 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/syck/rubyext.c (syck_genericresolver_node_import): should
+ not set instance variable "@kind" before initializing it.
+ [ruby-dev:32677]
+
+ * ext/syck/rubyext.c (syck_resolver_initialize,
+ syck_resolver_detect_implicit, syck_emitter_emit): remove unused
+ variables.
+
+Fri Apr 18 18:54:57 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/syck/rubyext.c: Node#value defined twice.
+
+ * lib/yaml/: several method redefinitions causing warnings.
+
+Fri Apr 18 16:36:16 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/rexml/node.rb (REXML::Node::indent): should initialize rv
+ variable. a patch from Tadayoshi Funaba <tadf AT dotrb.org> in
+ [ruby-dev:32783].
+
+Fri Apr 18 16:01:37 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/rexml: Merge fixes since 1.8.6 made solely on the ruby_1_8_6
+ branch.
+
+Wed Apr 16 06:11:49 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * test/ruby/test_settracefunc.rb (TestSetTraceFunc#test_event):
+ Fix tests to reflect the following changes: r15833, r15759.
+
+Wed Apr 16 05:03:48 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * .: Release as Ruby 1.8.7-preview1.
+
+Wed Apr 16 02:09:14 2008 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/xmlrpc/client.rb: fix cookie handling. [ruby-dev:34403]
+
+ * test/xmlrpc/test_cookie.rb: add a test for the above fix.
+
+Tue Apr 15 23:48:28 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * version.h: Branch off ruby_1_8_7 from ruby_1_8 in preparation
+ for the forthcoming 1.8.7 release.
+
+Tue Apr 15 23:40:39 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/syck/rubyext.c (rb_syck_mktime): Avoid buffer overflow.
+
+Tue Apr 15 20:32:03 2008 Tanaka Akira <akr@fsij.org>
+
+ * re.c (match_inspect): backported from 1.9.
+
+Tue Apr 15 19:03:28 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * eval.c (method_receiver, method_name, method_owner): New
+ methods; backported from 1.9. bug#19007
+
+Tue Apr 15 18:39:14 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * lib/uri.rb, lib/uri/ldaps.rb: added LDAPS
+ scheme; backported from 1.9. bug#19015, [ruby-dev:31896]
+
+Tue Apr 15 17:45:43 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * lib/net/smtp.rb: backported from 1.9. bug#19003
+
+Tue Apr 15 17:06:12 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * test/ruby/test_symbol.rb (TestSymbol#test_to_proc): add tests.
+
+Tue Apr 15 16:58:55 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/menuspec.rb: option check will fail when
+ TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ is true.
+
+ * ext/tk/lib/tk/palette.rb: bug fix.
+
+Tue Apr 15 16:47:48 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * signal.c, gc.c: New methods: GC.stress, GC.stress=;
+ backported from 1.9. a patch from Tadashi Saito
+ in [ruby-dev:34394] and bug#19000
+
+Tue Apr 15 12:35:44 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * rubyio.h (rb_io_t): renamed from OpenFile.
+
+ * ruby.h (struct RHash), file.c, gc.c, io.c, ext/dl/dl.c,
+ ext/io/wait/wait.c, ext/pty/pty.c, ext/readline/readline.c,
+ ext/socket/socket.c: ditto.
+
+ * win32/win32.h: removed workaround for OpenFile.
+
+Tue Apr 15 00:15:29 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/text.rb: typo. call a wrong method.
+
+ * ext/tk/lib/tk/itemconfig.rb: ditto.
+
+ * ext/tk/sample/ttk_wrapper.rb: bug fix.
+
+ * ext/tk/sample/tktextio.rb: add binding for 'Ctrl-u' at console mode.
+
+ * ext/tk/lib/tk.rb, ext/tk/lib/tk/itemfont.rb, ext/tk/lib/font.rb:
+ support __IGNORE_UNKNOWN_CONFIGURE_OPTION__ about font options.
+
+ * ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb,
+ ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb,
+ ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb: bug fix.
+
+ * ext/tk/lib/tkextlib/tile/tpaned.rb: improve TPaned#add.
+
+ * ext/tk/lib/tk/timer.rb: add TkTimer#at_end(proc) to register the
+ procedure which called at end of the timer.
+
+Mon Apr 14 19:54:21 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_flatten, rb_ary_flatten_bang): Take an optional
+ argument that determines the level of recursion to flatten;
+ backported from 1.9.
+
+ * array.c (rb_ary_shuffle_bang, rb_ary_shuffle, rb_ary_choice,
+ rb_ary_cycle, rb_ary_permutation, rb_ary_combination,
+ rb_ary_product, rb_ary_take, rb_ary_take_while, rb_ary_drop,
+ rb_ary_drop_while): New methods: Array#shuffle, #shuffle!,
+ #choice, #cycle, #permutation, #combination, #product, #take,
+ #take_while, #drop, #drop_while; backported from 1.9.
+
+Mon Apr 14 19:52:35 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ruby.h: New macro: RB_GC_GUARD().
+
+Mon Apr 14 19:49:35 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * random.c (rb_genrand_int32, rb_genrand_real), intern.h: Export.
+
+ * string.c (rb_str_tmp_new), intern.h: New function.
+
+Mon Apr 14 19:18:55 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * enum.c (inject_i, inject_op_i): prototype.
+
+Mon Apr 14 19:10:47 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enum.c New methods: Enumerable#take, #take_while, #drop and
+ #drop_while; backported from 1.9.
+
+Mon Apr 14 18:50:15 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enum.c: New methods: Enumerable#one?, #none?, #minmax, #min_by,
+ #max_by, #minmax_by and #cycle; backported from 1.9.
+
+ * enum.c (enum_find_index): Add support for find_index(obj);
+ [ruby-dev:34313]; backported from 1.9.
+
+ * enum.c (enum_inject): Add support for Enumerable#inject(:binop);
+ backported from 1.9.
+
+ * enum.c: Alias Enumerable#reject to #inject; backported from 1.9.
+
+Mon Apr 14 18:14:19 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enum.c (enum_find, enum_reject): Return an enumerator if no
+ block is given; backported from 1.9.
+
+ * io.c (rb_io_each_line, rb_io_each_byte, rb_io_s_foreach,
+ argf_each_line, argf_each_byte): Ditto.
+
+ * string.c (str_gsub): Ditto.
+
+Mon Apr 14 18:10:05 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * enum.c (find_index_i, find_index_iter_i): add prototype for VC.
+
+Mon Apr 14 17:55:30 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_collect_bang, rb_ary_select): Return an
+ enumerator if no block is given; backported from 1.9.
+
+ * dir.c (dir_each, dir_foreach): Ditto.
+
+ * enum.c (enum_partition, enum_sort_by): Ditto.
+
+ * gc.c (os_each_obj): Ditto.
+
+ * hash.c (rb_hash_delete_if, rb_hash_reject_bang, rb_hash_select,
+ rb_hash_each_value, rb_hash_each_key, rb_hash_each_pair,
+ env_each_key, env_each_value, env_each, env_each_pair,
+ env_reject_bang, env_delete_if, env_select): Ditto.
+
+ * numeric.c (num_step, int_upto, int_downto, int_dotimes): Ditto.
+
+Mon Apr 14 16:42:53 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * ruby.h (rb_block_call_func): Fix prototype.
+
+ * enumerator.c (enumerator_iter_i, enumerator_each_i): Ditto.
+
+Mon Apr 14 15:49:05 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enum.c (enum_count, enum_find_index): New methods:
+ Enumerable#count and #find_index; backported from 1.9.
+
+Mon Apr 14 14:16:08 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * enumerator.c (enumerator_mark, enumerator_iter_i, enumerator_each_i,
+ enumerator_allocate): add prototype.
+
+ * enumerator.c (enumerator_each_i): declare unused two arguments.
+
+Mon Apr 14 13:58:32 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * string.c (rb_str_each_char): New methods: String#chars and
+ #each_char; backported from 1.9.
+
+Mon Apr 14 13:42:20 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * string.c (rb_str_each_line, rb_str_each_byte): Reflect
+ enumerator integration. #lines and #bytes are now aliases to
+ #each_line and #each_byte, respectively.
+
+Mon Apr 14 13:19:36 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * range.c (range_each, range_step): Return an enumerator if no
+ block is given; backported from 1.9.
+
+ * struct.c (rb_struct_each, rb_struct_each_pair): Ditto.
+
+Mon Apr 14 13:07:59 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * string.c (rb_str_partition, rb_str_rpartition,
+ rb_str_start_with, rb_str_end_with): New methods:
+ String#partition, #rpartition, #start_with? and #end_with?;
+ backported from 1.9. These methods are $KCODE aware unlike
+ #index, #rindex and #include?.
+
+Sun Apr 13 15:55:52 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * object.c (sym_to_proc): new method Symbol#to_proc; backported
+ from 1.9. bug#19012
+
+Fri Apr 11 19:14:30 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * object.c (rb_obj_tap): new method Object#tap; backported from
+ 1.9. bug#19008
+
+Fri Apr 11 18:58:09 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * process.c: new method Process.exec; backported from 1.9. bug#19006
+
+Fri Apr 11 12:43:56 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tkextlib/tile.rb, ext/tk/lib/tkextlib/tile/style.rb,
+ ext/tk/sample/tkextlib/tile/demo.rb: previous patch is not complete.
+
+Fri Apr 11 10:22:54 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tkextlib/tile.rb:
+ __define_LoadImages_proc_for_compatibility__! do nothing when the
+ Tcl command exists.
+
+ * ext/tk/lib/tkextlib/tile/style.rb:
+ __define_wrapper_proc_for_compatibility__! do nothing when the Tcl
+ command exists.
+
+ * ext/tk/sample/tkextlib/tile/demo.rb: don't create 'step' theme if
+ it already exists.
+
+Fri Apr 11 08:05:12 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (w_object): add volatile to avoid potential GC bug. a
+ patch from Tomoyuki Chikanaga <chikanag at nippon-control-system.co.jp>
+ in [ruby-dev:34311].
+
+Thu Apr 10 20:29:13 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * misc/rdebug.el, misc/README: Remove rdebug.el as per request
+ from the maintainer and mention the ruby-debug project at
+ RubyForge in README; bug#19043.
+
+Thu Apr 10 20:08:37 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enum.c (enum_first, enum_group_by): New methods:
+ Enumerable#first and #group_by; backported from 1.9.
+
+Thu Apr 10 19:49:10 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enumerator.c (rb_eStopIteration), eval.c (rb_f_loop), ruby.h:
+ Add a new exception class StopIteration, which breaks Kernel#loop
+ iteration when raised; backported from 1.9.
+
+ * enumerator.c (enumerator_next, enumerator_rewind): Implement
+ #next and #rewind using the "generator" library.
+
+ * lib/generator.rb: Implement Enumerable::Enumerator#next and
+ #rewind.
+
+Thu Apr 10 19:29:48 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_first, rb_ary_last): Return a shared array when
+ possible.
+
+ * array.c (rb_ary_pop, rb_ary_pop_m, rb_ary_shift, rb_ary_shift_m):
+ Array#pop and Array#shift can take an optional argument
+ specifying the number of elements to remove and return;
+ backported from 1.9.
+
+Thu Apr 10 14:00:44 2008 Tanaka Akira <akr@fsij.org>
+
+ * lib/resolv.rb (Resolv::DNS#each_address): backport from 1.9 for
+ CNAME. [ruby-dev:34200]
+
+Thu Apr 10 01:42:25 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * enum.c (iterate_method): add prototype to avoid warning on VC++.
+
+Wed Apr 9 23:12:41 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tcltklib.c: SEGV when tcltk-stubs is enabled.
+
+ * ext/tk/tcltklib.c: avoid error on a shared object.
+
+ * ext/tk/extconf.rb: support --with-tcltkversion
+
+ * ext/tk/README.tcltklib: add document about --with-tcltkversion
+
+ * ext/tk/sample/demos-jp/widget, ext/tk/sample/demos-en/widget,
+ ext/tk/sample/demos-jp/style.rb, ext/tk/sample/demos-en/style.rb,
+ ext/tk/sample/demos-jp/bind.rb, ext/tk/sample/demos-en/bind.rb:
+ bug fix.
+
+Wed Apr 9 21:54:45 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_pop): Do not reallocate too often; backported
+ from 1.9.
+
+Wed Apr 9 21:13:05 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_each, rb_ary_each_index, rb_ary_reverse_each,
+ rb_ary_reject, rb_ary_reject_bang): Array#each, #each_index,
+ #reverse_each, #reject, #reject! and #delete_if return an
+ enumerator if no block is given; backported from 1.9.
+
+Wed Apr 9 20:47:16 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_index, rb_ary_index): Array#index and #rindex
+ can take a block instead of an argument; backported from 1.9.
+
+Wed Apr 9 19:58:31 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enumerator.c, inits.c (rb_call_inits), ruby.h, intern.h,
+ ext/enumerator, common.mk (OBJS, enumerator.$(OBJEXT)): Make the
+ enumerator module built-in.
+
+ * enumerator.c: New method: Enumerable::Enumerator#with_index.
+
+ * enum.c (enum_each_with_index): Enumerable#each_with_index now
+ returns an enumerator instead of raising an exception if no
+ block is given. Enumerable#enum_with_index, formerly defined in
+ the enumerator module, is kept as an alias to each_with_index
+ for backward compatibility.
+
+Wed Apr 9 19:43:51 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (rb_obj_method, rb_proc_call), intern.h: Export.
+
+Tue Apr 8 11:11:28 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (EXEC_TAG): remove unnecessary FLUSH_REGISTER_WINDOWS for
+ better performance on SPARC. [ruby-core:16159]
+
+Tue Apr 8 10:49:54 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (rb_reg_quote): should always copy the quoting string.
+ [ruby-core:16235]
+
+Mon Apr 7 21:35:08 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_nitems): Backport Array#nitems with a block;
+ suggested by Bertram Scharpf <lists@bertram-scharpf.de> in
+ [ruby-talk:134083].
+
+Sun Apr 6 09:45:00 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (dir_tell): check if closed. [ruby-core:16223]
+
+Sat Apr 5 10:05:00 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * object.c (rb_check_to_integer): backported for range_step.
+
+Fri Apr 4 05:57:11 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/net/pop.rb (Net::POP3::do_finish): clear @n_mails and
+ @n_bytes as well. [ruby-core:16144]
+
+Fri Apr 4 02:17:06 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * range.c (range_step): should not round step into integer if
+ begin and end are numeric. [ruby-core:15990]
+
+Tue Apr 1 14:43:38 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in: get rid of empty expansion.
+
+ * {bcc,win}32/Makefile (config.h): need to define RUBY_SETJMP, etc.
+
+Tue Apr 1 11:36:19 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in: _setjmp is available but _longjmp is not on mingw.
+
+Tue Apr 1 03:20:40 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (RUBY_SETJMP, RUBY_LONGJMP, RUBY_JMP_BUF): prefers
+ _setjmp over setjmp and sigsetjmp. [ruby-core:16023]
+ __builtin_setjmp cannot handle a variable.
+
+ * configure.in (--with-setjmp-type): new option to override the
+ default rule in the above.
+
+ * eval_intern.h (ruby_setjmp, ruby_longjmp), gc.c (rb_setjmp),
+ vm_core.h (rb_jmpbuf_t): use RUBY_SETJMP, RUBY_LONGJMP and
+ RUBY_JMP_BUF.
+
+Tue Apr 1 01:55:52 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/resolv.rb (Resolv::Config.default_config_hash): requires
+ win32/resolv to use Win32::Resolv. [ruby-dev:34138]
+
+Mon Mar 31 14:51:11 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big_div): Bignum#div should return integer for
+ floating number operand.
+
+Sun Mar 30 07:00:32 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/tk/tcltklib.c: rb_hash_lookup has not been backported yet.
+
+Sat Mar 29 14:18:41 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/*: full update Ruby/Tk to support Ruby(1.9|1.8) and Tc/Tk8.5.
+
+ * ext/tk/lib/tkextlib/tile.rb: [incompatible] remove TileWidgets'
+ instate/state/identify method to avoid the conflict with standard
+ widget options. Those methods are renamed to ttk_instate/ttk_state/
+ ttk_identify (tile_instate/tile_state/tile_identify are available
+ too). Although I don't recommend, if you realy need old methods,
+ please define "Tk::USE_OBSOLETE_TILE_STATE_METHOD = true" before
+ "require 'tkextlib/tile'".
+
+ * ext/tk/lib/tkextlib/tile.rb: "Tk::Tile::__Import_Tile_Widgets__!"
+ is obsolete. It outputs warning. To control default widget set,
+ use "Tk.default_widget_set = :Ttk".
+
+ * ext/tk/lib/tk.rb: __IGNORE_UNKNOWN_CONFIGURE_OPTION__ method and
+ __set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode) method are defind
+ as module methods of TkConfigMethod. It may help users to wrap old
+ Ruby/Tk scripts (use standard widgets) to force to use Ttk widgets.
+ Ttk widgets don't have some options of standard widgets which are
+ control the view of widgets. When set ignore-mode true, configure
+ method tries to ignoure such unknown options with no exception.
+ Of course, it may raise other troubles on the GUI design.
+ So, those are a little danger methods.
+
+ * ext/tk/lib/tk/itemconfig.rb: __IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ method and __set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode) method
+ are defind as module methods of TkItemConfigMethod as the same
+ purpose as TkConfigMethod's ones.
+
+ * ext/tk/sample/ttk_wrapper.rb: A new example. This is a tool for
+ wrapping old Ruby/Tk scripts (which use standard widgets) to use
+ Ttk (Tile) widgets as default.
+
+ * ext/tk/sample/tkextlib/tile/demo.rb: use ttk_instate/ttk_state
+ method instead of instate/state method.
+
+ * ext/tk/lib/tk/root, ext/tk/lib/tk/namespace.rb,
+ ext/tk/lib/tk/text.rb, ext/tk/lib/tkextlib/*: some 'instance_eval's
+ are replaced to "instance_exec(self)".
+
+ * ext/tk/lib/tk/event.rb: bug fix on KEY_TBL and PROC_TBL (?x is not
+ a character code on Ruby1.9).
+
+ * ext/tk/lib/tk/variable.rb: support new style of operation argument
+ on Tcl/Tk's 'trace' command for variables.
+
+ * ext/tk/sample/demos-jp/widget, ext/tk/sample/demos-en/widget: bug fix
+
+ * ext/tk/sammple/demos-jp/textpeer.rb,
+ ext/tk/sammple/demos-en/textpeer.rb: new widget demo.
+
+ * ext/tk/tcltklib.c: decrase SEGV troubles (probably)
+
+ * ext/tk/lib/tk.rb: remove Thread.critical access if Ruby1.9
+
+ * ext/tk/lib/tk/multi-tk.rb: support Ruby1.9 (probably)
+
+ * ext/tk/lib/tkextlib/tile.rb: add method to define Tcl/Tk command
+ to make Tcl/Tk theme sources (based on different version of Tile
+ extension) available.
+ (Tk::Tile::__define_LoadImages_proc_for_comaptibility__)
+
+ * ext/tk/lib/tk.rb, ext/tk/lib/tk/wm.rb: support dockable frames
+ (Tcl/Tk8.5 feature). 'wm' command can treat many kinds of widgets
+ as toplevel widgets.
+
+ * ext/tk/lib/tkextlib/tile/style.rb: ditto.
+ (Tk::Tile::Style.__define_wrapper_proc_for_compatibility__)
+
+ * ext/tk/lib/tk/font.rb: add actual_hash and metrics_hash to get
+ properties as a hash. metrics_hash method returns a boolean value
+ for 'fixed' option. But metrics method returns numeric value
+ (0 or 1) for 'fixed' option, because of backward compatibility.
+
+ * ext/tk/lib/tk/timer.rb: somtimes fail to set callback procedure.
+
+ * ext/tk/lib/tk.rb: add Tk.sleep and Tk.wakeup method. Tk.sleep
+ doesn't block the eventloop. It will be better to use the method
+ in event callbacks.
+
+ * ext/tk/sample/tksleep_sample.rb: sample script about Tk.sleep.
+
+Sat Mar 29 04:08:59 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * class.c (clone_method): should copy cref as well.
+ [ruby-core:15833]
+
+Mon Mar 24 20:07:42 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * eval.c (rb_eval): Call trace hook for if expression after the
+ condition has been evaluated, not before; submitted by Rocky
+ Bernstein in #18722.
+
+Mon Mar 24 19:44:53 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * parse.y (yycompile): Always prepare a new array for each file's
+ SCRIPT_LINES__ storage, instead of appending source lines every
+ time a file is re-loaded; submitted by Rocky Bernstein in
+ #18517.
+
+Mon Mar 24 10:25:54 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in: sitearch should use target_cpu. [ruby-core:15986]
+
+Mon Mar 24 01:24:24 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/erb.rb (result): use proc instead of Thread. [ruby-dev:33692]
+
+Fri Mar 21 21:26:52 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/resolv.rb (Resolv::Hosts): should not use win32/resolv on cygwin.
+ [ruby-dev:29945], [ruby-dev:34095]
+
+ * lib/win32/registry.rb (Win32::Registry.expand_environ): try upcased
+ name too for cygwin. [ruby-dev:29945]
+
+ * lib/win32/resolv.rb (Win32::Resolv.get_hosts_path): use expand_path.
+
+Fri Mar 21 21:10:00 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/ipaddr.rb: Say that I am the current maintainer.
+
+ * lib/set.rb: Ditto.
+
+ * lib/shellwords.rb: Ditto.
+
+ * ext/syslog/syslog.txt: Ditto.
+
+Fri Mar 21 09:24:28 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * instruby.rb (open_for_install): write block result and rewrite only
+ if changed from existing file.
+
+Wed Mar 19 21:01:08 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (dir_inspect, dir_path, dir_tell): check for frozen and closed
+ is not needed. [ruby-dev:32640]
+
+Wed Mar 19 20:25:40 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (Init_Dir): define inspect method. [ruby-core:15960]
+
+Wed Mar 19 14:59:12 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * misc/ruby-style.el (ruby-style-{case,label}-indent): fix for labels
+ inside blocks in switch and function top level.
+
+Wed Mar 19 14:36:40 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_cstr_to_inum): treat successive underscores as
+ nondigit. [ruby-dev:34089]
+
+Wed Mar 19 00:01:23 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/erb.rb (ERB::Compiler): Make some minor code optimization.
+
+Mon Mar 17 17:11:13 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-mode): should use `run-mode-hooks' instead
+ of calling `run-hooks' directly to run the mode hook. patch from
+ Chiyuan Zhang <pluskid AT gmail.com> in [ruby-core:15915]
+
+Mon Mar 17 16:41:08 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in: unset GREP_OPTIONS. [ruby-core:15918]
+
+Fri Mar 14 16:59:23 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (RUBY_LIB_PREFIX): fix for prefix.
+
+Fri Mar 14 16:35:11 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi.rb (CGI::Cookie::initialize): performance patch from
+ Makoto Kuwata <kwa@kuwata-lab.com> in [ruby-dev:34048].
+
+Fri Mar 14 15:49:05 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (RUBY_LIB_PREFIX): use libdir.
+
+Fri Mar 14 10:12:29 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (RUBY_CHECK_VARTYPE): should not indent preprocessor
+ directives.
+
+Thu Mar 13 00:37:20 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_call0): yields the last executed node line number at
+ return event. [ruby-core:15855]
+
+Wed Mar 12 02:12:20 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * lib/delegate.rb: check $@ to avoid NoMethodError.
+
+Tue Mar 11 19:48:09 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * numeric.c (fix_coerce): try conversion before type check.
+ [ruby-core:15838]
+
+Tue Mar 11 17:03:23 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/delegate.rb (Delegator#initialize, DelegateClass): skip correct
+ backtrace. [ruby-dev:34019]
+
+Tue Mar 11 16:43:53 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_cmdvector): terminate shrunken command line.
+
+Tue Mar 11 12:39:03 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (clean-local): removes MINOBJS.
+
+Sat Mar 8 18:50:57 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (isdirsep): backslash is valid path separator on cygwin too.
+
+Fri Mar 7 19:56:10 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb: rdoc added. [ruby-Patches-9762]
+
+Thu Mar 6 15:10:21 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * {bcc32,win32}/Makefile.sub (RUNRUBY): use $(PROGRAM) instead of
+ ruby$(EXEEXT).
+ suggested by KIMURA Koichi <kimura.koichi at canon.co.jp>.
+ [ruby-dev:34000]
+
+Thu Mar 6 12:15:06 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (opt_block_param): command can start just after block param
+ definition. [ruby-list:44479]
+
+Thu Mar 6 00:34:11 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/erb.rb: update RDoc. Thanks Makoto Kuwata [ruby-dev:33702]
+
+Mon Mar 3 23:28:34 2008 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/httpservlet/filehandler.rb: should normalize path
+ separators in path_info to prevent directory traversal attacks
+ on DOSISH platforms.
+ reported by Digital Security Research Group [DSECRG-08-026].
+
+ * lib/webrick/httpservlet/filehandler.rb: pathnames which have
+ not to be published should be checked case-insensitively.
+
+Mon Mar 3 16:14:24 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (rb_any_hash): shrinks all results in Fixnum range.
+ [ruby-core:15713]
+
+Sat Mar 1 02:35:08 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (big2str_find_n1): check integer overflow.
+
+Tue Feb 26 16:06:00 2008 Technorama Ltd. <oss-ruby@technorama.net>
+
+ * ext/openssl/ossl_pkey_{ec,dh,dsa,rsa}.c: Remove useless warnings.
+
+ * ext/openssl/ossl_asn1.c: Simplify code.
+
+ * ext/openssl/ossl_ssl_session.c Fix compiler warnings.
+ Undefine #id if SSL_SESSION_get_id is not supported.
+
+Tue Feb 26 15:43:42 2008 Tanaka Akira <akr@fsij.org>
+
+ * parse.y (tokadd_escape): refactored. [ruby-core:15657]
+
+Mon Feb 25 17:30:29 2008 Technorama Ltd. <oss-ruby@technorama.net>
+
+ * ext/openssl/digest.c ext/openssl/lib/openssl/digest.rb:
+ Commit patch #9280 from Akinori MUSHA.
+ Simplify the OpenSSL::Digest class and make use of the
+ existing Digest framework.
+ Enhance performance.
+
+Mon Feb 25 13:40:03 2008 Tanaka Akira <akr@fsij.org>
+
+ * process.c (Init_process): share bignum objects for RLIM_INFINITY,
+ RLIM_SAVED_MAX and RLIM_SAVED_CUR if they are equal.
+
+Sun Feb 24 23:29:48 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk, {bcc,win}32/Makefile.sub (clean-local): remove
+ intermediate files.
+
+Sun Feb 24 03:52:58 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * util.c (valid_filename): use O_EXCL to get rid of clobbering
+ existing files in race conditions.
+
+Fri Feb 22 19:50:19 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (BIGZEROP): fix for longer Bignum zeros. [ruby-Bugs-17454]
+
+Fri Feb 22 16:09:53 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big_lshift, rb_big_rshift, rb_big_aref): removed excess
+ arguments.
+
+Thu Feb 21 00:01:34 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (RPATHFLAG): -R option of HP-UX ld is not for runtime
+ load path. [ruby-list:44600]
+
+Wed Feb 20 23:55:19 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_map_errno): exported.
+
+Wed Feb 20 13:08:52 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * instruby.rb (parse_args): added --dir-mode, --script-mode and
+ --cmd-type options. [ruby-dev:33816]
+
+ * instruby.rb (parse_args): added bin-arch and bin-comm to install
+ type, for compiled files and script files.
+
+ * instruby.rb (parse_args): deal with make style command line macros,
+ and count as long syle options if prefixed with INSTALL_.
+
+ * instruby.rb (makedirs): use $dir_mode. [ruby-dev:33805]
+
+ * instruby.rb (open_for_install): set file mode, which is now
+ permission mode instead of access mode.
+
+ * instruby.rb (bin-comm): installs scripts with replacing shebang
+ lines.
+
+Tue Feb 19 18:34:32 2008 Tanaka Akira <akr@fsij.org>
+
+ * gc.c (STACK_LENGTH) [SPARC] : 0x80 offset removed. [ruby-dev:33857]
+
+Tue Feb 19 14:27:32 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/readline/readline.c (readline_event): prevent polling. based on
+ a patch from error errorsson in [ruby-Bugs-17675].
+
+Tue Feb 19 12:08:29 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (yycompile): clear ruby_eval_tree_begin if parse failed.
+
+Mon Feb 18 16:23:45 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (yycompile): clear ruby_eval_tree_begin too before parse.
+
+Mon Feb 18 10:17:42 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/pty/lib/expect.rb (IO#expect): check if peer is closed.
+ [ruby-Bugs-17940]
+
+Fri Feb 15 20:37:06 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/rational.rb (floor, ceil, truncate, round): do not use
+ definitions of Numeric.
+
+ * lib/rational.rb (to_i): should returns truncated self.
+
+ * lib/complex.rb (numerator): requires
+ Integer#{numerator,denominator}.
+
+ * lib/complex.rb (quo): do not use definition of Numeric.
+
+ * lib/complex.rb (div, divmod, floor, ceil, truncate, round):
+ undef'ed.
+
+Fri Feb 15 15:23:12 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/iconv/iconv.c (iconv_convert): check upper bound. a patch from
+ Daniel Luz at [ruby-Bugs-17910].
+
+Fri Feb 15 02:42:25 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (ftruncate): check if available.
+
+ * file.c (rb_file_truncate): check if ftruncate instead of truncate.
+
+Fri Feb 15 02:40:54 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (sigsetmask): check when signal semantics is not POSIX.
+
+ * signal.c (USE_TRAP_MASK): set true if sigprocmask or sigsetmask is
+ available.
+
+Thu Feb 14 17:44:32 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/dl/ptr.c (dlmem_each_i): typo fixed. a patch from IKOMA
+ Yoshiki <ikoma AT mb.i-chubu.ne.jp> in [ruby-dev:33776].
+
+Thu Feb 14 16:02:51 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_file_s_utime): inhibits with secure level 2 or higher.
+
+Thu Feb 14 01:43:16 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/timeout.rb (Timeout::timeout): made sensitive to location on the
+ stack. [ruby-core:15458]
+
+Thu Feb 14 00:49:53 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (INSTRUBY_ARGS): pass mode to install. [ruby-dev:33766]
+
+ * instruby.rb (parse_args): added --data-mode and --prog-mode options.
+
+Tue Feb 12 11:33:26 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * test/erb/test_erb.rb(TestERBCore): import from erb-2.0.4.
+
+ * test/erb/hello.erb: ditto
+
+Mon Feb 11 17:25:21 2008 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb (RSS::VERSION), test/rss/test_version.rb, NEWS:
+ 0.2.3 -> 0.2.4.
+
+ * lib/rss/maker.rb, lib/rss/maker/, test/rss/test_maker_2.0.rb:
+ fixed a bug that RSS::Maker.make("0.9")'s item doesn't make some
+ elements if description is missed.
+ Reported by Michael Auzenne. Thanks!!!
+
+ * lib/rss/maker/0.9.rb, test/rss/test_maker_0.9.rb:
+ RSS::Maker.make("0.9") generates RSS 0.92 not RSS 0.91.
+
+Mon Feb 11 16:57:00 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * ChangeLog: format-time-string under C locale. [ruby-dev:33261]
+
+Mon Feb 11 16:31:47 2008 URABE Shyouhei <shyouhei@ice.uec.ac.jp>
+
+ * gc.c (rb_newobj): prohibit call of rb_newobj() during gc.
+ Submitted by Sylvain Joyeux [ruby-core:12099].
+
+ * ext/dl/ptr.c: do not use LONG2NUM() inside dlptr_free().
+ Slightly modified fix bassed on a patch by Sylvain Joyeux
+ [ruby-core:12099] [ ruby-bugs-11859 ] [ ruby-bugs-11882 ]
+ [ ruby-patches-13151 ].
+
+Mon Feb 11 00:22:55 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * lib/benchmark.rb (Job::Benchmark#item): fix typo.
+
+Sat Feb 9 23:22:52 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/bigdecimal/extconf.rb: simplified the condition.
+
+Sat Feb 9 17:51:24 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/bigdecimal/bigdecimal.c (BigDecimal_to_f): use strtod() for more
+ precision. [ruby-talk:290296]
+
+ * ext/bigdecimal/bigdecimal.c (BASE_FIG): made constant.
+
+ * ext/bigdecimal/extconf.rb: ditto. [ruby-dev:33658]
+
+Sat Feb 9 00:44:52 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/irb.rb (IRB::Irb::eval_input): rescues Interrupt and other than
+ SystemExit and SignalException. [ruby-core:15359]
+
+Fri Feb 8 15:09:21 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (xsystem): expand macros like as make.
+
+Tue Feb 5 11:14:11 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (INSTALL_DIRS, install_dirs): added BINDIR.
+
+ * lib/mkmf.rb (install_files): rejects files matching to
+ $NONINSTALLFILES.
+
+ * lib/mkmf.rb (init_mkmf): defaults $NONINSTALLFILES to backup and
+ temporary filse.
+
+Mon Feb 4 16:44:24 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (darwin): NSIG is not defined if _XOPEN_SOURCE > 500L.
+ [ruby-dev:33584]
+
+Sat Feb 2 20:06:42 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/benchmark.rb (Benchmark::realtime): make Benchmark#realtime
+ a bit faster. a patch from Alexander Dymo <dymo AT ukrpost.ua> in
+ [ruby-core:15337].
+
+Sat Feb 2 09:53:39 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (darwin): disabled fat-binary support which confuses
+ configure much, since ``universal'' implies hidden cross-compiling.
+ TODO: ruby and libruby.bundle might be possible to bound with `lipo'
+ after builds for each archs. Anyway, config.h and rbconfig.rb must
+ be separated definitely at least.
+
+Fri Feb 1 21:42:37 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (darwin): _XOPEN_SOURCE is necessary to make ucontext_t
+ consistent with the library implementation of MacOS X 10.5.
+ [ruby-dev:33461]
+
+ * configure.in (darwin): ucontext on PowerPC MacOS X 10.5 is broken.
+
+Thu Jan 31 08:31:19 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (ext/extmk.rb, instruby.rb): inlined $(MAKE) so that can
+ be executed even with -n.
+
+Thu Jan 31 07:00:19 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/tuplespace.rb (bin_for_find): should find a symbol by
+ Symbol class.
+
+ * test/rinda/test_rinda.rb (test_symbol_tuple): ditto.
+
+Wed Jan 30 22:07:58 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb: refined deprecated methods.
+
+Wed Jan 30 22:06:54 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * bignum.c (rb_cstr_to_inum): '0_2' is a valid representation.
+
+Tue Jan 29 22:40:12 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * range.c (step_i): rb_funcall receives VALUE as an argument.
+
+Tue Jan 29 11:53:05 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in: rm largefile.h.
+
+Mon Jan 28 01:21:15 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_open_file): should check NUL in path.
+ <http://www.rubyist.net/~matz/20080125.html#c01>.
+
+ * io.c (rb_io_s_popen): ditto.
+
+ * io.c (rb_io_reopen): ditto.
+
+ * io.c (next_argv): ditto.
+
+ * io.c (rb_io_s_foreach): ditto.
+
+ * io.c (rb_io_s_readlines): ditto.
+
+ * io.c (rb_io_s_read): ditto.
+
+Fri Jan 25 22:33:38 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * math.c: fix comment. [ruby-dev:33276]
+
+Fri Jan 25 10:31:58 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * */*.bat: set svn:mime-type to text/batch.
+
+Thu Jan 24 19:36:22 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/uri/generic.rb (URI::Generic::inspect): use Kernel#to_s instead
+ object_id with printf. [ruby-dev:33347]
+
+Tue Jan 22 11:22:47 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/setup.mak ($(ARCH)): if a macro is appended by $(APPEND),
+ a space will be inserted on the top of the line.
+
+ * win32/Makefile.sub (MKFILES): stop make process if Makefile is
+ updated.
+
+Mon Jan 21 17:34:41 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * io.c (rb_io_mode_flags, rb_io_mode_modenum): Ignore encoding
+ options for forward compatibility.
+
+Mon Jan 21 12:50:02 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c, gc.c (setjmp): sigsetjmp is a macro on cygwin.
+
+Sat Jan 19 11:21:53 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (sigsetjmp): check if available.
+
+ * eval.c, gc.c (setjmp): do not use _setjmp if sigsetjmp is available.
+
+Sat Jan 19 11:10:11 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in: Remove wrong assumptions about Cygwin. a patch from
+ Corinna Vinschen in [ruby-Bugs-17018].
+
+Thu Jan 17 21:06:01 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb (Date::Infinity#<=>): didn't work. A patch from
+ Dirkjan Bussink <d.bussink AT gmail.com> [ruby-core:15098].
+ This is a bug obviously. However it didn't affect the library's
+ functions.
+
+ * lib/date.rb, lib/date/format.rb: some trivial changes.
+
+Tue Jan 15 15:09:28 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/setup.mak: strip out empty lines from CPP output.
+
+Tue Jan 15 03:41:42 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (eval): check if backtrace is empty. [ruby-core:15040]
+
+Tue Jan 15 01:28:47 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk: simplified dummy objects dependencies.
+
+Mon Jan 14 16:12:58 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/shellwords.rb: scape should be an alias to shellescape. a
+ patch from Masahiro Kawato <m-kawato AT mwb.biglobe.ne.jp> in
+ [ruby-dev:33060].
+
+Mon Jan 14 09:32:40 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/time.rb: do not reference Time directly from the inside of
+ definitions. [ruby-dev:33059]
+
+Sat Jan 12 18:27:41 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_define_alloc_func, rb_undef_alloc_func): should
+ define/undef on a signleton class. [ruby-core:09959]
+
+Sat Jan 12 12:04:14 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: tuning for performance.
+
+Fri Jan 11 12:35:56 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in: moved broken syscall checks from process.c etc.
+
+ * defines.h (WORDS_BIGENDIAN): honor __BIG_ENDIAN__ than the result of
+ configure.
+
+ * dln.c: use dlopen on Mac OS X 10.3 or later. backport from trunk.
+
+ * lib/rdoc/options.rb (check_diagram): more precise check, darwin
+ is not Windows but minwg is on it.
+
+Thu Jan 10 10:53:50 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_open_osfhandle): reverted to old definition.
+ [ ruby-Bugs-16948 ]
+
+Tue Jan 8 20:02:08 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win{32,ce}/Makefile.sub: merged.
+
+Sun Jan 6 09:39:02 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: introduced some constants
+ (for internal use).
+
+ * sample/cal.rb: trivial adjustments.
+
+Fri Jan 4 23:08:48 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * time.c (time_arg): use converted object. [ruby-core:14759]
+
+Fri Jan 4 01:20:21 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32.h: only VC6 needs extern "C++" for math.h. [ruby-talk:285660]
+
+Thu Jan 3 11:28:58 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (fptr_finalize): clear errno first. [ruby-talk:284492]
+
+Wed Jan 2 10:18:56 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * sample/time.rb: use Process.times instead of Time.times.
+
+Wed Jan 2 09:18:11 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * sample/goodfriday.rb: examples for date are enough. retired.
+
+Wed Jan 2 09:06:55 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * sample/cal.rb: just updated with the newest version.
+
+Mon Dec 31 06:50:38 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * trunk/common.mk: not use -I$(srcdir)/lib with $(MINIRUBY) for cross
+ compiling.
+
+ * configure.in, {win,bcc}32/Makefile.sub (MINIRUBY): -I$(srcdir)/lib
+ moved.
+
+Sun Dec 30 22:48:37 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb (_valid_time?): I'm not sure to recommend such an
+ expression. but anyway it is acceptable now. [ruby-core:14580]
+
+Fri Dec 28 16:36:33 2007 NARUSE, Yui <naruse@airemix.com>
+
+ * lib/resolv.rb (Resolv::DNS#each_address): now returns IPv6 address.
+
+Fri Dec 28 13:21:32 2007 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb, test/rss/test_version.rb, NEWS: 0.2.2 -> 0.2.3.
+
+ * lib/rss/parser.rb, test/rss/test_parser.rb: supported "-" in tag name.
+ Reported by Ray Chen. Thanks.
+
+Thu Dec 27 23:56:01 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * mkconfig.rb: should not use the libraries under the source directory
+ at cross compiling.
+
+Thu Dec 27 11:02:45 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * intern.h, string.c (rb_str_set_len): added for upgrading path from
+ 1.8 to 1.9. [ruby-dev:32807]
+
+ * string.c (rb_str_lines, rb_str_bytes): ditto.
+
+Thu Dec 27 10:47:32 2007 Technorama Ltd. <oss-ruby@technorama.net>
+
+ * ext/openssl/ossl_ssl.c: Only show a warning if the default
+ DH callback is actually used.
+
+ * ext/openssl/ossl_rand.c: New method: random_add().
+
+Wed Dec 26 22:27:45 2007 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * lib/resolv.rb (Resolv::DNS::Name.==): fix for other is array of
+ Resolv::DNS::Label::Str.
+
+ * lib/resolv.rb (Resolv::DNS::MessageEncoder#put_label): String#string
+ is not defined, so replace to_s.
+
+ * lib/resolv.rb (Resolv::IPv6#to_name): ip6.int is obsoleted by
+ int.arpa.
+
+Mon Dec 24 16:18:57 2007 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/ri/ri_options.rb: Fix ri --help listing of gem ri paths.
+ Merge of r14567 and r14569 from trunk.
+
+ * lib/rdoc/ri/ri_paths.rb: Fix duplication of ri data for multiple
+ gems. Merge of r14567 from trunk
+
+Mon Dec 24 12:35:03 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win{32,ce}/Makefile.sub (MFLAGS): defaulted to -l.
+
+Mon Dec 24 11:56:31 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * {bcc32,win{32,ce}}/Makefile.sub (SET_MAKE): set MFLAGS which is not
+ set by default, to get rid of chaotic situation of MFLAGS/MAKEFLAGS.
+
+Sat Dec 22 14:49:46 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb: don't freeze nil even if 1.8 will not be aware of
+ the issue. [ruby-dev:32677]
+
+Wed Dec 19 13:57:43 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (TIMEZONE_VOID): check whether timezone requires zero
+ arguments. [ruby-dev:32631]
+
+Wed Dec 19 12:01:42 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (f_rest_arg): check if duplicated. [ruby-core:14140]
+
+Wed Dec 19 10:52:29 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_cstr_to_inum): an underscore succeeding after octal
+ prefix is allowed. [ruby-core:14139]
+
+Mon Dec 17 13:43:15 2007 Tanaka Akira <akr@fsij.org>
+
+ * gc.c (stack_end_address): use local variable address instead of
+ __builtin_frame_address(0) to avoid SEGV on SunOS 5.11 on x86 with
+ gcc (GCC) 3.4.3 (csl-sol210-3_4-20050802).
+ stack_end_address returned a frame address of garbage_collect
+ since stack_end_address doesn't create its own frame.
+ So a VALUE stored in a callee saved register, %edi, pushed into
+ the stack at the beginning of garbage_collect was not marked.
+
+Mon Dec 17 12:21:25 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in (RUNRUBY): added RUNRUBYOPT.
+
+Fri Dec 14 12:36:35 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (RUBY_CHECK_VARTYPE): check if a variable is defined
+ and its type.
+
+ * configure.in (timezone, altzone): check for recent cygwin.
+
+ * missing/strftime.c (strftime): fix for timezone. [ruby-dev:32536]
+
+ * lib/mkmf.rb (try_var): should fail for functions.
+
+ * ext/readline/extconf.rb: should use have_func for functions instead
+ of have_var.
+
+Tue Dec 11 00:04:05 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * array.c (rb_ary_slice_bang): If an invalid negative index (<
+ -size) is given, do not raise an exception but return nil just
+ like slice() does.
+
+ * test/ruby/test_array.rb (TestArray::test_slice,
+ TestArray::test_slice!): Pull in test cases from trunk.
+
+Mon Dec 10 21:47:53 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * transcode.c (str_transcode): allow non-registered encodings.
+ [ruby-dev:32520]
+
+Mon Dec 10 21:00:30 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_slice_bang): should return nil if position out
+ of range. a patch from Akinori MUSHA <knu AT iDaemons.org>.
+ [ruby-dev:32518]
+
+Mon Dec 10 18:28:06 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/uri/common.rb (URI::REGEXP::PATTERN): typo in REG_NAME
+ regular expression. a patch from Ueda Satoshi
+ <s-ueda AT livedoor.jp>. [ruby-dev:32514]
+
+Sun Dec 9 12:39:01 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/cgi.rb (read_multipart): exclude blanks from header values.
+ [ruby-list:44327]
+
+Wed Dec 5 23:38:50 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * range.c (range_each): followed step_i change.
+
+Wed Dec 5 18:08:45 2007 Tanaka Akira <akr@fsij.org>
+
+ * numeric.c (int_odd_p): new method Integer#odd?.
+ (int_even_p): new method Integer#even?.
+ (int_pred): new method Integer#pred.
+ (fix_odd_p): new method Fixnum#odd?.
+ (fix_even_p): new method Fixnum#even?.
+
+Wed Dec 5 15:15:21 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * range.c (step_i, range_step): support non-fixnum steps.
+ [ruby-talk:282100]
+
+Tue Dec 4 11:23:50 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_cstr_to_inum): trailing spaces may exist at sqeezing
+ preceeding 0s. [ruby-core:13873]
+
+Sun Dec 2 22:43:45 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (error_print): put newline unless multiple line message ends
+ with a newline. [ruby-dev:32429]
+
+Sun Dec 2 15:49:20 2007 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb, test/rss/test_version.rb, NEWS: 0.2.1 -> 0.2.2.
+
+ * lib/rss/maker/itunes.rb: fixed new_itunes_category.
+ * lib/rss/maker/taxonomy.rb: new_taxo_topic -> new_topic because
+ of consistency.
+
+ * test/rss/test_maker_itunes.rb, test/rss/test_itunes.rb: removed
+ needless UTF-8 characters.
+
+Sun Dec 2 01:12:15 2007 James Edward Gray II <jeg2@ruby-lang.org>
+
+ Merged 14070 from trunk.
+
+ * lib/xmlrpc/server.rb (XMLRPC::Server#server): Improve signal handling so
+ pressing control-c in the controlling terminal or sending SIGTERM stops
+ the XML-RPC server.
+
+Sat Dec 1 15:13:33 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/resolv.rb: documentation update. backported from 1.9.
+ [ruby-core:13273]
+
+Sat Dec 1 03:30:47 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (newline_node): set line from outermost node before removing
+ NODE_BEGIN. [ruby-dev:32406]
+
+Fri Nov 30 21:53:28 2007 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/rss.rb, test/rss/test_version.rb: 0.2.0 -> 0.2.1.
+
+ * lib/rss/content.rb, lib/rss/content/1.0.rb,
+ lib/rss/content/2.0.rb, lib/rss/maker/content.rb,
+ test/rss/rss-testcase.rb, test/rss/test_content.rb,
+ test/rss/test_maker_content.rb: supported content:encoded with RSS
+ 2.0.
+ Suggested by Sam Lown. Thanks.
+
+ * NEWS: added the above changes.
+
+Thu Nov 29 16:59:10 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (stmt): remove unnecessary NODE_BEGIN. [ruby-core:13814]
+
+Wed Nov 28 14:43:14 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb (extract_makefile): use dldflags instead of DLDFLAGS to
+ get rid of mixing $LDFLAGS and $ARCH_FLAG.
+
+ * lib/mkmf.rb (configuration): ditto.
+
+ * lib/mkmf.rb (create_makefile): support for extensions which has no
+ shared object.
+
+Wed Nov 28 09:51:42 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big2str0): do not clobber space for sign.
+
+ * sprintf.c (remove_sign_bits): extends sign bit first.
+
+Wed Nov 21 01:04:12 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (nil_plus): remove unused function. [ruby-core:13737]
+
+Sun Nov 18 14:03:44 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_alias): do not call hook functions until initialization
+ finishes. [ruby-talk:279538]
+
+Sun Nov 18 09:09:48 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (String#tr_cpp): make preprocessor identifiers.
+
+Sat Nov 17 13:58:11 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (ole_invoke): bug fix. [ruby-talk:279100]
+
+Fri Nov 16 17:41:34 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/iconv/iconv.c (Document-class): moved the simplest example to
+ the top.
+
+ * ext/iconv/iconv.c (iconv_s_iconv): Document-method: needs class
+ prefix for class method. [ruby-core:13542]
+
+ * ext/iconv/iconv.c (iconv_iconv): also instance method needs to be
+ qualified.
+
+Fri Nov 16 11:16:41 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/yaml/rubytypes.rb (String#is_binary_data?): use Integer#fdiv.
+
+Thu Nov 15 19:50:46 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/curses/extconf.rb: check macro if cannot find func.
+ [ruby-list:44224]
+
+Thu Nov 15 12:19:14 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi/session.rb (CGI::Session::FileStore::restore): use
+ lockfile for exclusive locks. a patch from <tommy AT tmtm.org>.
+ [ruby-dev:32296]
+
+Wed Nov 14 01:52:59 2007 Tanaka Akira <akr@fsij.org>
+
+ * missing/isinf.c (isinf): don't define if the macro is defined.
+
+Wed Nov 14 01:34:42 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * numeric.c (round): fallback definition.
+
+ * numeric.c (flo_divmod, flo_round): use round() always.
+ [ruby-dev:32269]
+
+Tue Nov 13 22:02:23 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb: remove Thread.exclusive.
+
+ * lib/drb/extservm.rb: ditto.
+
+Tue Nov 13 16:33:07 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * numeric.c (flodivmod): work around for infinity.
+
+ * numeric.c (flo_divmod): work around for platforms have no round().
+ [ruby-dev:32247]
+
+Tue Nov 13 13:58:51 2007 Tanaka Akira <akr@fsij.org>
+
+ * numeric.c (numeric.c): Integer#ord implemented. [ruby-dev:32206]
+
+Tue Nov 13 02:57:04 2007 URABE Shyouhei <shyouhei@ice.uec.ac.jp>
+
+ * numeric.c (flo_divmod): round to the nearest integer.
+ [ ruby-Bugs-14540 ]
+
+Mon Nov 12 16:52:29 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (create_makefile): rdoc about srcprefix. a patch from
+ Daniel Berger <djberg96 AT gmail.com> in [ruby-core:13378].
+
+Mon Nov 12 13:53:06 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-parse-partial): handle stringified
+ symbols properly using ruby-forward-string.
+
+Mon Nov 12 12:38:31 2007 Tanaka Akira <akr@fsij.org>
+
+ * Makefile.in (lex.c): don't remove lex.c at first.
+
+Fri Nov 9 07:26:04 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * random.c: update MT URL.[ruby-core:13305].
+
+Wed Nov 7 03:32:38 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/rexml/encodings/SHIFT-JIS.rb (REXML::Encoding): place -x for
+ nkf conversion. a patch from <moonwolf AT moonwolf.com>.
+ [ruby-dev:32183]
+
+Mon Nov 5 05:17:04 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser::Switch::summarize): fix for long form
+ option with very long argument. a patch from Kobayashi Noritada
+ <nori1 AT dolphin.c.u-tokyo.ac.jp> in [ruby-list:44179].
+
+Mon Nov 5 01:20:33 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (call_args): remove "parenthesize argument(s) for future
+ version" warning. when I added this warning, I had a plan to
+ reimplement the parser that is simpler than the current one.
+ since we abandoned the plan, warning no longer required.
+
+Fri Nov 2 00:13:51 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_assoc): check and convert inner arrays (assocs)
+ using #to_ary.
+
+ * hash.c (rb_hash_s_create): check and convert argument hash
+ using #to_hash.
+
+ * hash.c (rb_hash_s_create): Hash#[] now takes assocs as source of
+ hash conversion.
+
+Thu Nov 1 23:47:43 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb (DRbTCPSocket): Improving with multiple network
+ interface.
+
+ * test/drb/drbtest.rb: ditto.
+
+Fri Oct 26 17:14:14 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * numeric.c (fix_pow): returns 1.0 for 0**0.0.
+
+ * numeric.c (fix_pow): returns infinity for 0**-1. [ruby-dev:32084]
+
+Wed Oct 25 07:18:09 2007 James Edward Gray II <jeg2@ruby-lang.org>
+
+ Merged 13781 from trunk.
+
+ * lib/net/telnet.rb (Net::Telnet#login): Allowing "passphrase" in
+ addition to "password" for Telnet login prompts. [ruby-Bugs-10746]
+
+Wed Oct 25 06:46:21 2007 James Edward Gray II <jeg2@ruby-lang.org>
+
+ Merged 13779 from trunk.
+
+ * lib/net/telnet.rb (Net::Telnet#login): Making the password prompt
+ pattern case insensitive. [ruby-Bugs-10746]
+
+Thu Oct 25 14:19:33 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (rb_io_tell, rb_io_seek): check errno too. [ruby-dev:32093]
+
+Wed Oct 25 08:03:53 2007 James Edward Gray II <jeg2@ruby-lang.org>
+
+ Merged 13767, 13768, 13769, and 13770 from trunk.
+
+ * lib/xmlrpc/parser.rb (XMLRPC::Convert::dateTime): Fixing a bug that
+ caused time zone conversion to fail for some ISO 8601 date formats.
+ [ruby-Bugs-12677]
+
+ * lib/xmlrpc/client.rb (XMLRPC::Client#do_rpc): Explicitly start
+ the HTTP connection to support keepalive requests. [ruby-Bugs-9353]
+
+ * lib/xmlrpc/client.rb (XMLRPC::Client#do_rpc): Improving the error
+ message for Content-Type check failures. [ruby-core:12163]
+
+ * lib/xmlrpc/utils.rb (XMLRPC::ParseContentType#parse_content_type):
+ Making Content-Type checks case insensitive. [ruby-Bugs-3367]
+
+Sun Oct 21 21:16:43 2007 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss.rb, lib/rss/, test/rss/, sample/rss/: merged from trunk.
+ - 0.1.6 -> 2.0.0.
+ - fixed image module URI. Thanks to Dmitry Borodaenko.
+ - supported Atom.
+ - supported ITunes module.
+ - supported Slash module.
+
+ * NEWS: added an entry for RSS Parser.
+
+Thu Oct 18 10:57:06 2007 Tanaka Akira <akr@fsij.org>
+
+ * ruby.h (RCLASS_IV_TBL): defined.
+ (RCLASS_M_TBL): ditto.
+ (RCLASS_SUPER): ditto.
+ (RMODULE_IV_TBL): ditto.
+ (RMODULE_M_TBL): ditto.
+ (RMODULE_SUPER): ditto.
+
+Mon Oct 15 22:08:55 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * NEWS: Merge some of the sub-sections, as the differences were
+ unclear.
+
+Mon Oct 15 21:57:07 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * NEWS: Mention ipaddr enhancements.
+
+ * lib/ipaddr.rb (in_addr, in6_addr, addr_mask): Make some minor
+ code optimization.
+
+ * lib/ipaddr.rb (<=>): Implement IPAddr#<=> and make IPAddr
+ comparable.
+
+ * lib/ipaddr.rb (succ): Implement IPAddr#succ. You can now create
+ a range between two IPAddr's, which (Range) object is
+ enumerable.
+
+ * lib/ipaddr.rb (to_range): A new method to create a Range object
+ for the (network) address.
+
+ * lib/ipaddr.rb (coerce_other): Support type coercion and make &,
+ |, == and include? accept a string or an integer instead of an
+ IPAddr object as the argument.
+
+ * lib/ipaddr.rb (initialize): Give better error messages.
+
+ * lib/ipaddr.rb: Improve documentation.
+
+Mon Oct 15 21:24:25 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * NEWS: Mention shellwords and tempfile enhancements.
+
+ * NEWS: Move the entry about Tk::X_Scrollable to a better section.
+
+Mon Oct 15 17:28:20 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/openssl/lib/openssl/buffering.rb (read, readpartial): revert
+ r12496. handling EOF is a little differnt in ruby 1.8 and ruby 1.9.
+ [ruby-dev:31979]
+
+Mon Oct 15 11:45:12 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (r_bytes0): refined length check. [ruby-dev:32059]
+
+Mon Oct 15 09:58:07 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (r_bytes0): check if source has enough data.
+ [ruby-dev:32054]
+
+Mon Oct 15 01:15:09 2007 Tanaka Akira <akr@fsij.org>
+
+ * ext/socket/socket.c (s_accept_nonblock): make accepted fd
+ nonblocking. [ruby-talk:274079]
+
+Sun Oct 14 04:08:34 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (AC_SYS_LARGEFILE): keep results also in command
+ options, to vail out of mismatch. [ruby-list:44114]
+
+ * mkconfig.rb, lib/mkmf.rb (configuration): add DEFS.
+
+Sun Oct 14 03:55:52 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/mkexports.rb: deal with __fastcall name decorations.
+ [ruby-list:44111]
+
+Sat Oct 13 09:02:16 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * {bcc,win}32/mkexports.rb: explicit data. [ruby-list:44108]
+
+Sat Oct 13 00:35:03 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/rexml/source.rb (REXML::SourceFactory::SourceFactory): typo
+ fixed. [ruby-list:44099]
+
+Fri Oct 12 11:22:15 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (match_values_at): make #select to be alias to #values_at
+ to adapt RDoc description. [ruby-core:12588]
+
+Thu Oct 11 14:32:46 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * {bcc32,win32}/Makefile.sub (COMMON_MACROS): workaround for old SDK's
+ bug. [ruby-core:12584]
+
+Wed Oct 10 23:34:45 2007 Tanaka Akira <akr@fsij.org>
+
+ * lib/securerandom.rb: new file. [ruby-dev:31928]
+
+ * lib/cgi/session.rb (create_new_id): use securerandom if available.
+
+Tue Oct 9 01:01:55 2007 Tanaka Akira <akr@fsij.org>
+
+ * re.c (rb_reg_s_union_m): Regexp.union accepts single
+ argument which is an array of patterns. [ruby-list:44084]
+
+Mon Oct 8 20:06:23 2007 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/net/http.rb, lib/open-uri.rb: remove
+ Net::HTTP#enable_post_connection_check. [ruby-dev:31960]
+
+ * lib/net/imap.rb: hostname should be verified against server's
+ indentity as persented in the server's certificate. [ruby-dev:31960]
+
+ * ext/openssl/lib/net/telnets.rb, ext/openssl/lib/net/ftptls.rb: ditto.
+
+Sat Oct 6 23:14:54 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_to_i): update RDoc since base can be any value
+ between 2 and 36. [ruby-talk:272879]
+
+Fri Oct 5 15:44:50 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/shellwords.rb: Add shellescape() and shelljoin().
+
+ * lib/shellwords.rb: Rename shellwords() to shellsplit() and make
+ the former an alias to the latter.
+
+ * lib/shellwords.rb: Add escape(), split(), join() as class
+ methods, which are aliases to their respective long names
+ prefixed with `shell'.
+
+ * lib/shellwords.rb: Add String#shellescape(), String#shellsplit()
+ and Array#shelljoin() for convenience.
+
+Fri Oct 5 15:40:04 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/tempfile.rb (Tempfile::make_tmpname): Allow to specify a
+ suffix for a temporary file name.
+
+ * lib/tempfile.rb (Tempfile::make_tmpname): Make temporary file
+ names less predictable by including a random string.
+ [inspired by: akr]
+
+Tue Oct 2 21:20:14 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (make_cmdvector): adjust escaped successive
+ double-quote handling. (merge from trunk)
+
+Tue Oct 2 20:35:24 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (init_env): initialize HOME and USER environment
+ variables unless set. [ruby-core:12328] (merge from trunk)
+
+ * win32/win32.c (NtInitialize, getlogin): ditto.
+
+ * configure.in, win32/Makefile.sub (LIBS): need to link shell32
+ library for SH* functions on mswin32 and mingw32.
+
+Mon Oct 1 12:50:59 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (id2ref): valid id should not refer T_VALUE nor T_ICLASS.
+ [ruby-dev:31911]
+
+Wed Sep 26 23:54:37 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb (extmake), lib/mkmf.rb (configuration): top_srcdir
+ should not prefixed with DESTDIR.
+
+Wed Sep 26 08:36:31 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in (ext/extinit.o): use $(OUTFLAG) as well as other
+ objects. [ruby-Bugs-14228]
+
+Wed Sep 26 05:12:17 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (yyerror): limit error message length. [ruby-dev:31848]
+
+ * regex.c (re_mbc_startpos): separated from re_adjust_startpos.
+
+Tue Sep 25 13:47:38 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (remove_method): should not remove undef place holder.
+ [ruby-dev:31817]
+
+Mon Sep 24 16:52:11 2007 Urabe Shyouhei <shyouhei@ruby-lang.org>
+
+ * lib/net/http.rb: fix typo.
+
+Sun Sep 23 21:57:25 2007 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/net/http.rb: an SSL verification (the server hostname should
+ be matched with its certificate's commonName) is added.
+ this verification can be skipped by
+ "Net::HTTP#enable_post_connection_check=(false)".
+ suggested by Chris Clark <cclark at isecpartners.com>
+
+ * lib/net/open-uri.rb: use Net::HTTP#enable_post_connection_check to
+ perform SSL post connection check.
+
+ * ext/openssl/lib/openssl/ssl.c
+ (OpenSSL::SSL::SSLSocket#post_connection_check): refine error message.
+
+Sun Sep 23 09:05:05 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (os_obj_of, os_each_obj): hide objects to be finalized.
+ [ruby-dev:31810]
+
+Sun Sep 23 08:58:01 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval_method.ci (rb_attr): should not use alloca for unknowen size
+ input. [ruby-dev:31816]
+
+ * parse.y (rb_intern_str): prevent str from optimization.
+
+Sun Sep 23 05:42:35 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * lib/rdoc/options.rb (Options::check_diagram): dot -V output
+ changed. [ ruby-Bugs-11978 ], Thanks Florian Frank.
+
+Sat Sep 22 06:02:11 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser::List::summarize): use each_line if
+ defined rather than each. [ruby-Patches-14096]
+
+Sat Sep 22 05:19:49 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_init): separate from strio_initialize
+ to share with strio_reopen properly. [ruby-Bugs-13919]
+
+Fri Sep 21 15:46:20 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * process.c (struct rb_exec_arg): proc should be a VALUE.
+
+ * process.c (rb_f_exec): suppress a warning.
+
+Fri Sep 21 03:05:35 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c, intern.h, ext/thread/thread.c: should not free queue while
+ any live threads are waiting. [ruby-dev:30653]
+
+Thu Sep 20 17:24:59 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * process.c (rb_detach_process): cast for the platforms where size of
+ pointer differs from size of int.
+
+ * process.c (rb_f_exec, rb_f_system): should not exceptions after
+ fork. [ruby-core:08262]
+
+Fri Sep 14 00:34:25 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/extservm.rb (invoke_service): use Thread.exclusive instead of
+ Thread.critical
+
+Wed Sep 12 23:12:22 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.c (proc_options): -W should be allowed in RUBYOPT
+ environment variable. [ruby-core:12118]
+
+Mon Sep 10 01:05:25 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * range.c (range_step): fixed integer overflow. [ruby-dev:31763]
+
+Sun Sep 9 09:14:45 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb (_strptime): now also attaches an element
+ which denotes leftover substring if exists.
+
+Sat Sep 8 10:22:20 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * struct.c (rb_struct_s_members): should raise TypeError instead
+ of call rb_bug(). [ruby-dev:31709]
+
+ * marshal.c (r_object0): no nil check require any more.
+
+Sat Sep 8 09:38:19 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb (str[fp]time): now check specifications more
+ strictly.
+
+Fri Sep 7 05:36:19 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * test/rinda/test_rinda.rb (MockClock): correct synchronous problems
+ of the MultiThreading. [ruby-dev:31692]
+
+Wed Sep 5 22:02:27 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_subseq): need integer overflow check.
+ [ruby-dev:31736]
+
+ * array.c (rb_ary_splice): ditto. [ruby-dev:31737]
+
+ * array.c (rb_ary_fill): ditto. [ruby-dev:31738]
+
+ * string.c (rb_str_splice): integer overflow for length.
+ [ruby-dev:31739]
+
+Sun Sep 2 00:48:15 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb (_parse): improved parsing of ordinal dates.
+
+ * lib/date/format.rb (_parse): use named character classes in some
+ regular expressions.
+
+Sat Sep 1 08:13:36 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c: add WIN32OLE#ole_activex_initialize.
+
+Thu Aug 30 13:13:13 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (try_const, have_const): check for a const is defined.
+ [ruby-core:04422]
+
+Thu Aug 30 13:10:57 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (group_member): check if presents.
+
+ * configure.in (XCFLAGS): add _GNU_SOURCE on linux.
+
+ * file.c (group_member): use system routine if available.
+
+Thu Aug 30 08:24:18 2007 Tanaka Akira <akr@fsij.org>
+
+ * ruby.h (RHASH_TBL): defined for compatibility to 1.9.
+ * (RHASH_ITER_LEV): ditto.
+ * (RHASH_IFNONE): ditto.
+ * (RHASH_SIZE): ditto.
+ * (RHASH_EMPTY_P): ditto.
+
+Wed Aug 29 13:05:59 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * include/ruby/defines.h (flush_register_windows): call "ta 0x03"
+ even on Linux/Sparc. [ruby-dev:31674]
+
+Tue Aug 28 23:26:12 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (ole_type_progid, reg_enum_key,
+ reg_get_val, ole_wc2mb): fix the bug. Thanks, arton.
+ [ruby-dev:31576]
+
+Mon Aug 27 19:10:50 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/etc/etc.c (etc_getlogin): update documentation to note
+ security issue. [ruby-Bugs-11821]
+
+Tue Aug 21 21:09:48 2007 Tanaka Akira <akr@fsij.org>
+
+ * lib/tmpdir.rb (Dir.mktmpdir): make directory suffix specifiable.
+
+Tue Aug 21 13:57:04 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (st_foreach_func, rb_foreach_func): typedefed.
+
+Mon Aug 20 17:25:33 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (mnew): should preserve noex as safe_level.
+
+ * eval.c (rb_call0): tighten security check condition..
+
+Sat Aug 18 21:32:20 2007 Tanaka Akira <akr@fsij.org>
+
+ * lib/tmpdir.rb (Dir.mktmpdir): new method.
+ [ruby-dev:31462]
+
+Sat Aug 18 17:44:42 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/tk/tcltklib.c (Init_tcltklib): use rb_set_end_proc().
+
+Sat Aug 18 15:59:52 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * process.c (detach_process_watcher): should not pass the pointer
+ to an auto variable to the thread to be created. pointed and
+ fix by KUBO Takehiro <kubo at jiubao.org> [ruby-dev:30618]
+
+Sat Aug 18 12:24:30 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * sample/test.rb, test/ruby/test_system.rb(valid_syntax?): keep
+ comment lines first.
+
+Thu Aug 16 20:40:50 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (bigtrunc): RBIGNUM(x)->len may be zero. out of bound
+ access. [ruby-dev:31404]
+
+Thu Aug 16 16:46:07 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (aix): enable shared by default.
+
+ * configure.in (aix): for 64bit-mode AIX. [ruby-dev:31401]
+ + use CC for LDSHARED if non-gcc,
+ + moved -G option from *LDFLAGS to LDSHARED,
+ + set -brtl only in XLDFLAGS.
+
+Thu Aug 16 13:06:08 2007 Tanaka Akira <akr@fsij.org>
+
+ * bignum.c (big_lshift): make shift offset long type.
+ (big_rshift): ditto.
+ (rb_big_lshift): ditto.
+ (big_rshift): ditto.
+ [ruby-dev:31434]
+
+Thu Aug 16 04:09:19 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/tuplespace.rb (Rinda::TupleSpace#start_keeper): improve
+ keeper thread.
+
+Wed Aug 15 13:50:10 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (rb_hash_delete_key): delete the entry without calling block.
+
+ * hash.c (rb_hash_shift): should consider iter_lev too.
+
+ * hash.c (delete_if_i): use rb_hash_delete_key() so that the block
+ isn't called twice. [ruby-core:11556]
+
+Sun Arg 12 03:56:30 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/tuplespace.rb: fix Rinda::TupleSpace keeper thread bug.
+ the thread is started too early. [ruby-talk:264062]
+
+ * test/rinda/test_rinda.rb: ditto.
+
+Sat Aug 11 07:34:10 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb: reverted some wrongly erased "o" options
+ (pointed out by nobu).
+
+Tue Aug 7 14:58:39 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/pty/pty.c (establishShell): handshaking before close slave
+ device. [ruby-talk:263410]
+
+ * ext/pty/pty.c (MasterDevice, SlaveDevice, deviceNo): constified.
+
+ * ext/pty/pty.c (SlaveName): removed static buffer.
+
+ * ext/pty/expect_sample.rb: support for autologin.
+
+Tue Aug 7 12:45:13 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (ac_cv_func_isinf): set yes also on OpenSolaris.
+ [ruby-Bugs-12859]
+
+Mon Aug 6 17:36:29 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/rexml/encodings/{ISO-8859-15,CP-1252}.rb: fixed invalid syntax.
+
+Fri Aug 3 11:05:54 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb (extmake): save all CONFIG values.
+
+ * ext/extmk.rb (extmake): remove mkmf.log at clean, and extconf.h at
+ distclean, respectively.
+
+ * ext/extmk.rb: remove rdoc at clean, and installed list file at
+ distclean, respectively.
+
+Fri Aug 3 07:09:05 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb: more verbose message. [ruby-Bugs-12766]
+
+ * lib/mkmf.rb (have_type): suppress a warning with -Wall.
+
+ * lib/mkmf.rb (find_type): new method.
+
+Thu Aug 2 13:46:39 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): should not check positional number as
+ width. [ruby-core:11838]
+
+Mon Jul 30 11:16:40 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big_aref): check for Bignum index range.
+ [ruby-dev:31271]
+
+Sat Jul 28 09:35:41 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/digest/lib/digest.rb (Digest::self.const_missing): avoid
+ infinite recursive const_missing call. [ruby-talk:262193]
+
+Thu Jul 26 13:57:45 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dln.c (load_1, dln_find_1): constified.
+
+ * dln.c (conv_to_posix_path): removed.
+
+ * ruby.c (usage): constified.
+
+ * ruby.c (rubylib_mangled_path, rubylib_mangled_path2): return
+ VALUE instead of a pointer to static buffer.
+
+ * ruby.c (push_include_cygwin): fixed buffer overflow.
+ [ruby-dev:31297]
+
+ * ruby.c (ruby_init_loadpath): not convert built-in paths.
+
+Sun Jul 22 16:07:12 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * intern.h (is_ruby_native_thread): removed since declared as an int
+ function in ruby.h already.
+
+Sun Jul 22 14:33:40 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_file_s_rename): deleted code to get rid of a bug of
+ old Cygwin.
+
+ * file.c (rb_file_truncate): added prototype of GetLastError()
+ on cygwin. [ruby-dev:31239]
+
+ * intern.h (is_ruby_native_thread): prototype.
+
+ * missing/strftime.c (strftime): fix printf format and actual
+ arguments.
+
+ * ext/Win32API/Win32API.c (Win32API_initialize): ditto.
+
+ * ext/tk/tcltklib.c (ip_finalize): ditto.
+
+ * ext/dl/ptr.c (rb_dlptr_inspect): ditto. [ruby-dev:31268]
+
+ * ext/dl/sym.c (rb_dlsym_inspect): ditto.
+
+ * ext/socket/getnameinfo.c: include stdio.h always.
+
+ * ext/win32ole/win32ole.c (ole_hresult2msg, folevariable_name,
+ folevariable_ole_type, folevariable_ole_type_detail,
+ folevariable_value, folemethod_visible): missing return value.
+
+Sat Jul 21 17:48:26 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (create_makefile): make OBJS depend on RUBY_EXTCONF_H
+ only if extconf.h is created.
+
+ * bcc32/{Makefile.sub,configure.bat,setup.mak: configure_args
+ support.
+
+ * bcc32/setup.mak: check runtime version.
+
+ * win32/win32.c (rb_w32_open_osfhandle): prototype has changed
+ in bcc 5.82.
+
+ * {win32,wince,bcc32}/setup.mak (-version-): no RUBY_EXTERN magic.
+
+ * win32/resource.rb: include patchlevel number.
+
+Sat Jul 21 12:06:48 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (init_mkmf): should remove mkmf.log too.
+
+Sat Jul 21 01:53:17 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb (Date._parse): completes calendar week based year.
+
+ * lib/date/format.rb (Date._parse): detects year of ordinal date in
+ extended format.
+
+Fri Jul 20 15:22:51 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/openssl/ossl_config.c (ossl_config_set_section): do not
+ initialize aggregations with dynamic values. [ruby-talk:259306]
+
+Thu Jul 19 19:24:14 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (get_backtrace): check the result more.
+ [ruby-dev:31261] [ruby-bugs-12398]
+
+Thu Jul 19 14:38:45 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big_lshift, rb_big_rshift): separated functions
+ to get rid of infinite recursion. fixed calculation in edge
+ cases. [ruby-dev:31244]
+
+ * numeric.c (rb_fix_lshift, rb_fix_rshift): ditto.
+
+Wed Jul 18 16:57:41 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big_pow): refine overflow check. [ruby-dev:31242]
+
+Wed Jul 18 08:47:09 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * time.c (time_succ): Time#succ should return a time object in the
+ same timezone mode to the original. [ruby-talk:260256]
+
+Tue Jul 17 00:50:53 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (fix_pow): integer power calculation: 0**n => 0,
+ 1**n => 1, -1**n => 1 (n: even) / -1 (n: odd).
+
+ * test/ruby/test_fixnum.rb (TestFixnum::test_pow): update test
+ suite. pow(-3, 2^64) gives NaN when pow(3, 2^64) gives Inf.
+
+Mon Jul 16 23:07:51 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/base64.rb (Base64::b64encode): should not specify /o option
+ for regular expression. [ruby-dev:31221]
+
+Mon Jul 16 18:29:33 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (rb_str_rindex_m): accept string-like object convertible
+ with #to_str method, as well as rb_str_index_m. [ruby-core:11692]
+
+Mon Jul 16 05:45:53 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): more checks for format argument.
+ [ruby-core:11569], [ruby-core:11570], [ruby-core:11571],
+ [ruby-core:11573]
+
+Mon Jul 16 00:26:10 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big_pow): removed invariant variable. [ruby-dev:31236]
+
+Sun Jul 15 23:59:57 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big_neg): SIGNED_VALUE isn't in 1.8.
+
+Sun Jul 15 22:24:49 2007 pegacorn <subscriber.jp AT gmail.com>
+
+ * ext/digest/digest.c (rb_digest_instance_update,
+ rb_digest_instance_finish, rb_digest_instance_reset,
+ rb_digest_instance_block_length): %s in rb_raise() expects char*.
+ [ruby-dev:31222]
+
+ * ext/openssl/ossl.h: include ossl_pkcs5.h. [ruby-dev:31231]
+
+ * ext/openssl/ossl_pkcs5.h: new file for PKCS5. [ruby-dev:31231]
+
+ * ext/openssl/ossl_x509name.c (ossl_x509name_to_s): use ossl_raise()
+ instead of rb_raise(). [ruby-dev:31222]
+
+ * ext/sdbm/_sdbm.c: DOSISH platforms need io.h. [ruby-dev:31232]
+
+ * ext/syck/syck.h: include stdlib.h for malloc() and free().
+ [ruby-dev:31232]
+
+ * ext/syck/syck.h (syck_parser_set_input_type): prototype added.
+ [ruby-dev:31231]
+
+ * win32/win32.c: include mbstring.h for _mbspbrk(). [ruby-dev:31232]
+
+ * win32.h (rb_w32_getcwd): prototype added. [ruby-dev:31232]
+
+Sun Jul 15 21:07:43 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (bigtrunc): do not empty Bignum. [ruby-dev:31229]
+
+Sun Jul 15 19:05:28 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_cstr_to_inum): check leading non-digits.
+ [ruby-core:11691]
+
+Sun Jul 15 04:42:20 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (get2comp): do nothing for empty Bignum. [ruby-dev:31225]
+
+Sat Jul 14 14:04:06 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * enum.c (sort_by_cmp): check if reentered. [ruby-dev:24291]
+
+Sat Jul 14 12:44:14 2007 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/openssl/test_pkcs7.rb: reverted the previous patch. it should
+ be as it was to check interface compatibility. sorry for bothering
+ with this.
+
+Sat Jul 14 12:16:17 2007 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
+ * test/openssl/test_pkcs7.rb: follow the library change. applied a
+ patch from <zn at mbf.nifty.com> [ruby-dev:31214].
+ NOTE: r12496 imports the latest openssl libs from trunk to ruby_1_8
+ though its's not ChangeLog-ed. maintainer should aware that.
+
+Sat Jul 14 02:51:52 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (fix_pow): 0**2 should not raise floating point
+ exception. [ruby-dev:31216]
+
+Sat Jul 14 02:25:48 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (int_pow): wrong overflow detection. [ruby-dev:31213]
+
+ * numeric.c (int_pow): wrong overflow detection. [ruby-dev:31215]
+
+Fri Jul 13 16:10:00 2007 Tanaka Akira <akr@fsij.org>
+
+ * lib/open-uri.rb (URI::Generic#find_proxy): use ENV.to_hash to access
+ http_proxy environment variable to avoid case insensitive
+ environment search.
+
+Fri Jul 13 15:02:15 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (CreateChild): enclose command line except for
+ command.com which can not handle quotes. [ruby-talk:258939]
+
+Fri Jul 13 10:10:46 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (link_command, cc_command, cpp_command): do not expand
+ ::CONFIG which is an alias of MAKEFILE_CONFIG.
+
+Thu Jul 12 17:03:15 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * struct.c (rb_struct_init_copy): disallow changing the size.
+ [ruby-dev:31168]
+
+Wed Jul 11 23:38:14 2007 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
* random.c: documentation fix. srand(0) initializes PRNG with '0',
not with random_seed.
-Thu Aug 16 04:49:10 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Tue Jul 10 14:50:01 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* bcc32/{Makefile.sub,setup.mak}: remove surplus slash from srcdir.
-Thu Aug 16 04:40:37 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Fri Jul 6 15:22:58 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_interrupt): suppress a gcc's officious warning.
+
+Thu Jul 5 16:44:28 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * numeric.c (int_pow): fix previous nubu's commit.
+
+ * test/ruby/test_fixnum.rb: new test.
+
+Thu Jul 5 15:56:06 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * numeric.c (int_pow): even number multiplication never be negative.
+
+Mon Jul 2 14:34:43 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* sprintf.c (rb_f_sprintf): sign bit extension should not be done
if FPLUS flag is specified. [ruby-list:39224]
-Thu Aug 16 04:39:15 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+Sat Jun 30 16:05:41 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
* array.c (rb_ary_initialize): should call rb_ary_modify() first.
[ruby-core:11562]
-Thu Aug 16 04:38:39 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Sat Jun 30 00:17:00 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* parse.y (yylex): return non-valid token for an invalid
- instance/class variable name. a patch from from Yusuke ENDOH
+ instance/class variable name. a patch from Yusuke ENDOH
<mame AT tsg.ne.jp>. [ruby-dev:31095]
-Thu Aug 16 04:36:41 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Fri Jun 29 11:23:09 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* parse.y (dsym): return non-null NODE even if yyerror(). based on a
- patch from from Yusuke ENDOH <mame AT tsg.ne.jp>. [ruby-dev:31085]
+ patch from Yusuke ENDOH <mame AT tsg.ne.jp>. [ruby-dev:31085]
-Thu Aug 16 04:34:56 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Tue Jun 26 16:35:21 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * process.c (ruby_setreuid, ruby_setregid): rename to get rid of name
+ clash.
* process.c (proc_exec_v, rb_proc_exec): preserve errno.
-Thu Aug 16 04:30:45 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Sat Jun 23 00:37:46 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * hash.c (rb_hash_select): remove unnecessary varargs for
+ rb_hash_select. a patch from Daniel Berger
+ <Daniel.Berger at qwest.com>. [ruby-core:11527]
+
+ * hash.c: ditto.
+
+Mon Jun 18 08:47:54 2007 Technorama Ltd. <oss-ruby@technorama.net>
+
+ * ext/openssl/{extconf.rb,ossl_ssl_session.c}:
+ Fix ruby-Bugs-11513.
+
+ * ext/openssl/ossl_pkey_ec.c
+ New methods EC::Point.[eql,make_affine!,invert!,on_curve?,infinity?]
+ By default output the same key form as the openssl command.
+
+ * ext/openssl/ossl_rand.c
+ New method Random.status?
+
+Mon Jun 18 13:54:36 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (ruby_cleanup): return EXIT_FAILURE if any exceptions occured
+ in at_exit blocks. [ruby-core:11263]
+
+Mon Jun 18 01:14:10 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* variable.c (rb_path2class): get rid of dangling pointer caused by
optimized out value.
-Thu Aug 16 04:24:28 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+ * variable.c (rb_global_entry, rb_f_untrace_var, rb_alias_variable,
+ rb_generic_ivar_table, generic_ivar_get, generic_ivar_set,
+ generic_ivar_defined, generic_ivar_remove, rb_mark_generic_ivar,
+ rb_free_generic_ivar, rb_copy_generic_ivar,
+ rb_obj_instance_variables): suppress warnings.
+
+Fri Jun 15 22:33:29 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (realclean): separate local and ext.
+
+ * ext/extmk.rb: not remove unrelated directories.
+
+Fri Jun 15 17:01:20 2007 NAKAMURA Usaku <usa@ruby-lang.org>
* ext/dl/lib/dl/win32.rb: seems that dl doesn't accept void argument.
fixed [ruby-bugs:PR#5489].
-Thu Aug 16 04:23:44 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Thu Jun 14 17:09:48 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser): handle more
extensions. [ruby-dev:30972]
-Thu Aug 16 04:14:17 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Wed Jun 13 06:05:12 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
- * process.c (ruby_setreuid, ruby_setregid): rename to get rid of name
- clash.
-Thu Aug 16 04:11:17 2007 Ryan Davis <ryand@zenspider.com>
+ * configure.in (darwin): prohibit loading extension libraries to
+ miniruby.
+
+Wed Jun 13 05:47:58 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_kill_thread): renamed in order to get rid of conflict
+ with a BeOS system function. [ruby-core:10830]
+
+Tue Jun 12 14:53:51 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (Logging.quiet, Logging.message): added quiet flag and
+ use it. [ruby-core:10909]
+
+ * lib/mkmf.rb (find_header): use header names in the message.
+
+Sun Jun 10 13:47:36 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * test/ruby/test_beginendblock.rb (test_should_propagate_signaled):
+ get rid of invoking shell. [ruby-dev:30942]
+
+Thu Jun 7 19:02:48 2007 Tanaka Akira <akr@fsij.org>
- * lib/rexml/dtd/dtd.rb: Fixed typo in code. Fixes bug #10420
+ * lib/pp.rb: call original "method" method instead of redefined one.
-Thu Aug 16 04:08:20 2007 Shugo Maeda <shugo@ruby-lang.org>
+Mon Jun 4 11:11:12 2007 Shugo Maeda <shugo@ruby-lang.org>
* lib/net/imap.rb (ResponseParser#next_token): fixed
error message. (backported from HEAD)
@@ -64,58 +4018,219 @@ Thu Aug 16 04:08:20 2007 Shugo Maeda <shugo@ruby-lang.org>
the condition not to refer @token.symbol unexpectedly.
Thanks, Dick Monahan. (backported from HEAD)
-Thu Aug 16 04:05:20 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+Thu May 31 17:27:53 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
- * marshal.c (w_extended): erroneous check condition when dump
- method is defined. [ruby-core:10646]
+ * lib/benchmark.rb (Benchmark::Job::item): avoid modifying the
+ argument unintentionally. [ruby-talk:253676]
+
+Thu May 31 02:12:32 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/tuplespace.rb (Rinda::TupleBag): create index on tuple bag
+ by first column.
+
+Wed May 30 13:27:40 2007 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/ftp.rb (Net::FTP#transfercmd): skip 2XX
+ responses for some FTP servers. (backported from HEAD)
+
+Wed May 30 05:17:55 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_eval): get rid of SEGV at ZSUPER in a block
+ [ruby-dev:30836]
+
+Wed May 30 04:29:43 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
-Sat Jun 9 10:40:00 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
+ * eval.c (thread_timer): timer thread should not receive any
+ signals. submitted by Sylvain Joyeux. [ruby-core:08546]
- * stable version 1.8.5-p52 released.
+Wed May 30 04:18:37 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
-Thu Jun 7 14:53:46 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
+ * eval.c (rb_eval_cmd): just return if no exceptions.
+ [ruby-dev:30820]
- * eval.c (method_inspect): show proper class name.
- [ruby-talk:248647], Thanks Calamitas.
+Tue May 29 11:01:06 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
-Mon May 28 19:37:24 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+ * win32/win32.c (rb_w32_opendir): store attributes of the second
+ entries or later too.
- * win32/win32.c (move_to_next_entry): revert r12338. not necessary
- on ruby_1_8_5.
+ * win32/win32.c (rb_w32_opendir, rb_w32_readdir): eliminate magic
+ numbers.
-Sun May 27 05:52:37 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
+Mon May 28 02:54:05 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
- * eval.c (mnew): call of super via a method object should work again.
- [ruby-talk:248647], Thanks Calamitas.
+ * lib/rinda/tuplespace.rb (Rinda::TupleBag#delete): use rindex and
+ delete_at instead of delete for little improvement.
- * test/ruby/test_method.rb (TestMethod::test_method_super): test for
- above fix.
+Sat May 26 00:05:22 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * test/ruby/test_beginendblock.rb (test_should_propagate_signaled):
+ skip tests for exitstatus and termsig on the platforms where
+ signals not supported.
Wed May 23 06:51:46 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
* lib/cgi.rb (CGI#[]): get rid of exceptions being raised.
[ruby-dev:30740], Thanks Kentaro KAWAMOTO.
-Wed May 23 06:14:15 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Wed May 23 05:49:49 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb, ext/purelib.rb, lib/mkmf.rb, runruby.rb: clear default
+ load path to get rid of load pre-installed extensions/libraries.
+ [ruby-core:11017]
+
+Sat May 19 10:29:18 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb (Date._parse): detects some OFX dates
+ (Of course not fully).
+
+Fri May 18 23:07:33 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_first): call rb_ary_subseq() instead of pushing
+ values by itself. [ruby-talk:252062]
+
+ * array.c (rb_ary_first): add negative length check.
+
+Fri May 18 17:10:31 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* win32/win32.c (move_to_next_entry): loc also must move forward.
[ruby-talk:251987]
-Wed May 23 05:55:04 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+Fri May 18 03:02:40 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/mkexports.rb: preserve prefixed underscores for WINAPI
+ symbols.
+
+ * wince/mkconfig_wce.rb, wince/mkexports.rb: obsolete.
+
+Thu May 17 17:03:11 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * misc/ruby-style.el (ruby-style-label-indent): for yacc rules.
+
+Tue May 15 14:54:07 2007 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/win32.c (init_stdhandle): stderr should be without buffering,
but mswin32 use buffering when stderr is not connected to tty.
-Wed May 23 03:33:55 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Mon May 14 13:28:03 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/thread/thread.c (wait_list): supress a warning.
+
+Thu May 10 15:21:51 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/iconv/iconv.c (iconv_s_conv): rdoc fix.
+
+Thu May 10 10:14:14 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_thread_priority): rdoc fix; the initial value is
+ inherited from the creating thread. [ruby-core:10607]
+
+Wed May 9 12:28:57 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (Init_Bignum), numeric.c (Init_Numeric): added fdiv as
+ aliases of quo. [ruby-dev:30771]
+
+Wed May 9 11:55:15 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big_quo): now calculate in integer. [ruby-dev:30753]
+
+Wed May 9 11:51:06 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big_pow): reduce multiplying for even number.
+
+ * bignum.c (rb_big_pow): truncate all zero BDIGITs. [ruby-dev:30733]
+
+ * bignum.c (rb_big_pow): improvement by calculating from MSB and using
+ factorization. <http://yowaken.dip.jp/tdiary/20070426.html#p01>
+
+ * numeric.c (int_pow): calculate power in Fixnum as possible.
+ [ruby-dev:30726]
+
+Tue May 8 23:42:51 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb (Date._parse): revised treatment of
+ hyphened/separatorless dates.
+
+ * lib/date/format.rb: some trivial adjustments.
+
+Tue May 8 20:25:05 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb: reverted.
+
+Sat May 5 16:26:33 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/date/format.rb (Format::Bag#method_missing): get rid of
+ modifying orginal argument. [ruby-core:11090]
+
+Mon Apr 30 01:17:51 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/rinda/tuplespace.rb (TupleSpace#create_entry, TupleBag#push,
+ delete): extract method, and rename parameter.
+
+Fri Apr 27 02:00:17 2007 Ryan Davis <ryand-ruby@zenspider.com>
+
+ * signal.c: Fixed backwards compatibility for 'raise Interrupt'.
+
+ * lib/yaml/tag.rb: Running rdoc over the 1.8.6 tree skips
+ Module. Patch from James Britt
+
+Thu Apr 26 13:54:51 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * misc/ruby-style.el: new file. C/C++ style for ruby source code.
+
+Wed Apr 25 19:49:16 2007 Tanaka Akira <akr@fsij.org>
+
+ * ext/socket/socket.c (unix_send_io, unix_recv_io): use CMSG_DATA to
+ align file descriptor appropriately.
+
+Tue Apr 24 09:33:57 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (do_stat, do_lstat, do_opendir): should not warn ENOTDIR.
+ [ruby-talk:248288]
+
+Mon Apr 23 22:14:42 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb ($ruby): add extout directory to include path.
+ [ruby-core:11003]
+
+ * lib/mkmf.rb (libpathflag): not to append RPATHFLAG to current
+ directory.
+
+ * lib/mkmf.rb (init_mkmf): add current directory to default
+ library path with highest priority. [ruby-core:10960]
+
+ * lib/mkmf.rb (LINK_SO): LIBPATH to be placed before DLDFLAGS.
+
+Fri Apr 20 16:05:22 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (LIBPATHFLAG, RPATHFLAG): no needs to be quoted,
+ it is done by libpathflag in mkmf.rb.
+
+Fri Apr 20 12:27:04 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb: fix to override conv proc.
+
+Fri Apr 20 12:17:05 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (ruby_cleanup): inversed the order of errinfos.
+
+Thu Apr 19 14:53:32 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* lib/monitor.rb (ConditionVariable#wait, mon_enter, mon_exit_for_cond):
ensures Thread.critical to be false. [ruby-talk:248300]
-Wed May 23 03:25:13 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Wed Apr 18 10:41:21 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* util.c (ruby_strtod): exponent is radix 10. [ruby-talk:248272]
-Wed May 23 02:09:32 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+Wed Apr 18 02:30:24 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (LDFLAGS): prepend -L. instead appending it to
+ XLDFLAGS. [ruby-core:10933]
+
+ * configure.in (Makefile): remove $U for automake from MISSING.
+ [ruby-talk:248171]
+
+Tue Apr 17 16:46:46 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
* eval.c (rb_yield_0): should not clear state on TAG_NEXT when
it's invoked from within lambda body. [ruby-talk:248136]
@@ -123,34 +4238,143 @@ Wed May 23 02:09:32 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
* eval.c (proc_invoke): handle TAG_NEXT which would be caused by
next in the lambda body as well.
-Wed May 23 01:55:49 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+Mon Apr 16 22:56:01 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/pty/expect_sample.rb: avoid symbolic link representation for
+ expect. a patch from Kazuhiro NISHIYAMA <zn at mbf.nifty.com>.
+ [ruby-dev:30714]
+
+Mon Apr 16 22:51:11 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * sample: replace TRUE, FALSE with true, false respectively.
+ a patch from Kazuhiro NISHIYAMA <zn at mbf.nifty.com>.
+ [ruby-dev:30713]
+
+Mon Apr 16 17:08:02 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (make_switch): do not clobber converter if pattern
+ has no convert method. reported by sheepman in [ruby-dev:30709].
+
+Mon Apr 16 16:49:32 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_seek): consistent behavior with
+ IO#seek. patch by sheepman in [ruby-dev:30710].
+
+Mon Apr 16 16:34:08 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (parser_yylex): should set command_start after block
+ starting "do"s and braces. [ruby-core:10916]
+
+Sun Apr 15 09:19:57 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb: added some zone names.
+
+ * lib/date/format.rb (_parse): now interprets doted numerical
+ dates as a big endian (except dd.mm.yyyy).
+
+Tue Apr 10 17:37:36 2007 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/win32.c (rb_w32_fclose, rb_w32_close): need to save errno
before calling original fclose()/close().
-Wed May 23 01:42:29 2007 Shugo Maeda <shugo@ruby-lang.org>
+Mon Apr 9 09:30:44 2007 Shugo Maeda <shugo@ruby-lang.org>
* lib/net/imap.rb (disconnect): call shutdown for
SSLSocket. Thanks, Technorama Ltd.
-Wed May 23 01:28:14 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Thu Apr 5 00:42:48 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* error.c (rb_notimplement), io.c (pipe_open): removed definite
articles and UNIX manual section from messages. [ruby-dev:30690]
+Wed Apr 4 17:09:17 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (pipe_open): refined the message of NotImplementedError.
+ [ruby-dev:30685]
+
+Wed Apr 4 10:18:04 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
* io.c (pipe_open): raise NotImplementedError for command "-" on
platforms where fork(2) is not available. [ruby-dev:30681]
-Wed May 23 00:06:19 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+Tue Apr 3 15:45:41 2007 NAKAMURA Usaku <usa@ruby-lang.org>
* ext/socket/socket.c (s_recv, s_recvfrom): some systems (such as
windows) doesn't set fromlen if the socket is connection-oriented.
reported by Bram Whillock in [ruby-core:10512] [ruby-Bugs#9061]
+Sat Mar 24 23:40:29 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * node.h (struct rb_thread.locals): explicit as struct.
+ [ruby-core:10585]
+
+ * eval.c, node.h (enum rb_thread_status, struct rb_thread,
+ rb_curr_thread, rb_main_thread): prefixed. [ruby-core:10586]
+
+ * file.c (chompdirsep): made an unprefixed name static.
+
+ * io.c (io_fread): ditto.
+
+Sat Mar 24 01:54:03 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (ruby_cleanup): exit by SystemExit and SignalException in END
+ block. [ruby-core:10609]
+
+ * test/ruby/test_beginendblock.rb (test_should_propagate_exit_code):
+ test for exit in END block. [ruby-core:10760]
+
+ * test/ruby/test_beginendblock.rb (test_should_propagate_signaled):
+ test for signal in END block.
+
+Thu Mar 22 23:13:17 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_provided): check for extension library if SOEXT is
+ explicitly given. [ruby-dev:30657]
+
+Thu Mar 22 10:29:25 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * test/ruby/test_bignum.rb (test_to_s): add tests for Bignum#to_s.
+
+Wed Mar 21 17:04:30 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bignum.c (rb_big2str0): round up for the most significant digit.
+ [ruby-core:10686]
+
+Wed Mar 21 07:21:24 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/thread.c (remove_one): Preserve List invariants;
+ submitted by: MenTaLguY <mental AT rydia.net>
+ in [ruby-core:10598] and [ruby-bugs:PR#9388].
+
+Tue Mar 20 22:54:50 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (w_extended): erroneous check condition when dump
+ method is defined. [ruby-core:10646]
+
Tue Mar 20 15:37:24 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
* distruby.rb: Add zip generation.
+Tue Mar 20 11:28:41 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/matrix.rb (Matrix::inverse_from): adding partial pivoting to
+ the Gauss-Jordan algorithm, making it stable. a patch from
+ Peter Vanbroekhoven. [ruby-core:10641]
+
+Mon Mar 19 11:39:29 2007 Minero Aoki <aamine@loveruby.net>
+
+ * lib/net/protocol.rb (rbuf_read): extend buffer size for speed.
+
+Sun Mar 18 04:23:52 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * NEWS: Add a note about the new `date' library defining
+ Time#to_date and Time#to_datetime private methods.
+
+ * NEWS: Inform that the old `thread' library is considered to be
+ stable.
+
+ * NEWS: Sort library entries in alphabetical order.
+
Fri Mar 16 21:48:11 2007 Akinori MUSHA <knu@iDaemons.org>
* ext/dl/dl.c (rb_ary2cary): Fix a bug in type validation;
@@ -164,40 +4388,101 @@ Fri Mar 16 18:28:06 2007 Akinori MUSHA <knu@iDaemons.org>
reported by: UEDA Hiroyuki <ueda AT netforest.ad.jp>
in [ruby-dev:30586].
+Fri Mar 16 16:33:58 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/thread.c (unlock_mutex_inner): Make sure that the
+ given mutex is actually owned by the caller; submitted by:
+ Sylvain Joyeux <sylvain.joyeux AT m4x.org> in [ruby-core:10598].
+
+Fri Mar 16 16:21:35 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/thread.c (wait_condvar, lock_mutex): Fix a problem in
+ ConditionVariable#wait that occurs when two threads that are
+ trying to access the condition variable are also in concurrence
+ for the given mutex; submitted by: Sylvain Joyeux
+ <sylvain.joyeux AT m4x.org> and MenTaLguY <mental AT rydia.net>
+ in [ruby-core:10598].
+
+Fri Mar 16 16:17:27 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * test/thread/test_thread.rb: Add a test script for the `thread'
+ library. This should result in failure as of now with
+ ext/thread; submitted by: Sylvain Joyeux <sylvain.joyeux AT
+ m4x.org> in [ruby-core:10598].
+
Wed Mar 14 12:30:00 2007 Shigeo Kobayashi <shigeo@tinyforest.jp>
* ext/bigdecimal/bigdecimal.c: BigDecimal("-.31") is now
treated as ("-0.31") not as ("0.31").
-Fri Mar 16 18:05:40 2007 Akinori MUSHA <knu@iDaemons.org>
+Tue Mar 13 09:25:10 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (clear-installed-list): separated from install-prereq.
+
+Tue Mar 13 06:38:43 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * NEWS: Reword and improve entries.
+
+Tue Mar 13 06:03:46 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * stable version 1.8.6 released from the ruby_1_8_6 branch.
+
+Tue Mar 13 03:24:07 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * runruby.rb: added --pure (turned on by default) and --debugger
+ options.
+
+Tue Mar 13 02:50:28 2007 Akinori MUSHA <knu@iDaemons.org>
* lib/cgi.rb (CGI::header): IIS >= 5.0 does not need the nph
assumption any more; submitted by MIYASAKA Masaru <alkaid AT
coral.ocn.ne.jp> in [ruby-dev:30537].
-Tue Mar 13 17:29:43 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
+Mon Mar 12 11:07:44 2007 Akinori MUSHA <knu@iDaemons.org>
- * stable version 1.8.5-p35 released.
+ * ext/openssl/ossl_asn1.c (Init_ossl_asn1): Let rdoc know about
+ externally defined modules; submitted by Technorama
+ Ltd. <oss-ruby AT technorama.net> in [ruby-bugs:PR#4704].
-Tue Mar 13 14:42:10 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
+ * ext/openssl/ossl_bn.c (Init_ossl_bn): Ditto.
- * test/fileutils/fileasserts.rb: Fix wrong error message.
+ * ext/openssl/ossl_cipher.c (Init_ossl_cipher): Ditto.
- * lib/fileutils.rb (FileUtils::mv): Type Error; should utilize
- Strings instead of Symbols here.
+ * ext/openssl/ossl_digest.c (Init_ossl_digest): Ditto.
-Mon Mar 12 17:22:44 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+ * ext/openssl/ossl_hmac.c (Init_ossl_hmac): Ditto.
- * lib/fileutils.rb (FileUtils::mv): fix incomplete backport of
- FileUtils.mv changes at r11988
+ * ext/openssl/ossl_pkey.c (Init_ossl_pkey): Ditto.
-Mon Mar 12 16:09:28 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+ * ext/openssl/ossl_pkey_dh.c (Init_ossl_dh): Ditto.
- * mkconfig.rb (patchlevel): read from version.h.
+ * ext/openssl/ossl_pkey_dsa.c (Init_ossl_dsa): Ditto.
+
+ * ext/openssl/ossl_pkey_rsa.c (Init_ossl_rsa): Ditto.
+
+ * ext/openssl/ossl_rand.c (Init_ossl_rand): Ditto.
+
+ * ext/openssl/ossl_ssl.c (Init_ossl_ssl): Ditto.
+
+Mon Mar 12 01:05:17 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/dl/sym.c (rb_dlsym_inspect): Use "0x%x" rather for pointers.
+ This might not be very right but it is commonly used in other
+ parts of the code; submitted by sheepman <sheepman AT
+ sheepman.sakura.ne.jp> in [ruby-dev:30532].
+
+ * ext/dl/ptr.c (rb_dlptr_inspect): Ditto.
+
+Mon Mar 12 00:59:19 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/dl/lib/dl/import.rb (DL::Importable::Internal::import,
+ DL::Importable::Internal::callback): Avoid race condition for an
+ instance variable; submitted by sheepman <sheepman AT
+ sheepman.sakura.ne.jp> in [ruby-dev:30530].
Sun Mar 11 18:57:50 2007 Akinori MUSHA <knu@iDaemons.org>
- * misc/README: Add a note about ruby-electric.el.
+ * misc/README: Add a note about ruby-electric.el.
* misc/ruby-mode.el (ruby-non-block-do-re): Fix
ruby-non-block-do-re. [ruby-core:03719]
@@ -215,24 +4500,118 @@ Sun Mar 11 17:45:51 2007 Akinori MUSHA <knu@iDaemons.org>
it; submitted by sheepman <sheepman AT sheepman.sakura.ne.jp>
in [ruby-dev:30524].
+Sun Mar 11 12:09:37 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (error_handle): no message when exiting by signal.
+
+ * eval.c (ruby_cleanup): re-send signal. [ruby-dev:30516]
+
+ * eval.c (rb_thread_interrupt): instantiate SignalException.
+
+ * eval.c (rb_thread_signal_raise): now takes signal number instead
+ of signal name.
+
+ * intern.h (rb_thread_signal_raise, ruby_default_signal): prototypes.
+
+ * signal.c (esignal_init): takes a signal number and an optional
+ signal name.
+
+ * signal.c (interrupt_init): pass SIGINT always.
+
+ * signal.c (ruby_default_signal): invoke system default signal
+ handler.
+
+ * signal.c (rb_signal_exec, trap): handle SIGTERM. [ruby-dev:30505]
+
+Tue Mar 6 19:08:46 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/lib/md5.rb (MD5::new, MD5::md5): Do not modify
+ Digest::MD5.
+
+ * ext/digest/lib/sha1.rb (SHA1::new, SHA1::sha1): Ditto.
+
Tue Mar 6 18:58:37 2007 Keiju Ishitsuka <keiju@ruby-lang.org>
-
+
* lib/shell/process-controller.rb: fix thread synchronization
problem for [ruby-dev:30477].
-
-Sun Mar 4 23:53:27 2007 Minero Aoki <aamine@loveruby.net>
+
+Tue Mar 6 18:44:26 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/lib/md5.rb (MD5::new, MD5::md5): Catch up with
+ Digest's API changes; noted by: Kazuhiro Yoshida <moriq AT
+ moriq.com> in [ruby-dev:30500].
+
+ * ext/digest/lib/sha1.rb (SHA1::new, SHA1::sha1): Ditto.
+
+Tue Mar 6 18:24:19 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * time.c (time_to_s): Back out the format changes; discussed
+ in [ruby-dev:30495].
+
+Tue Mar 6 11:53:25 2007 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/sample/irbtkw.rbw: fails to exit process.
+
+Mon Mar 5 20:14:49 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * time.c (time_to_s): Correct the wrong format which did not
+ really conform to RFC 2822; pointed out by: OHARA Shigeki <os at
+ iij.ad.jp> in [ruby-dev:30487].
+
+Sun Mar 4 23:38:07 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_stat_s_utime): fixed a commit miss for the platforms
+ where utimes() does not exist.
+
+ * lib/fileutils.rb (touch): ditto.
+
+Sun Mar 4 14:46:56 2007 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * util.c (push_element): should return a int value.
+
+Sun Mar 4 01:05:57 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/set.rb (Set#^, Set#&): Correct documentation. Those methods
+ return sets, not arrays; noted by Oliver Frank Wittich <nietz AT
+ mangabrain.de>.
+
+Sat Mar 3 23:01:07 2007 Minero Aoki <aamine@loveruby.net>
* lib/fileutils.rb (mv): could not move a directory between
different filesystems. [ruby-dev:30411]
-Sat Mar 3 21:41:31 2007 Akinori MUSHA <knu@iDaemons.org>
+Sat Mar 3 22:57:11 2007 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (touch): last commit causes error if :mtime
+ option was not given.
+
+Sat Mar 3 22:37:02 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_file_s_utime): allow nil to set the current time.
+
+ * lib/fileutils.rb (touch): ditto, and added :mtime and :nocreate
+ options. fixed: [ruby-talk:219037]
+
+Sat Mar 3 21:17:35 2007 Akinori MUSHA <knu@iDaemons.org>
* eval.c (stack_check): Unset inline to fix build with GCC 3.4.6;
submitted by: NISHIMATSU Takeshi <t_nissie AT yahoo.co.jp> in
[ruby-list:43218].
cf. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24556
-Sat Mar 3 16:30:39 2007 Akinori MUSHA <knu@iDaemons.org>
+Sat Mar 3 19:05:31 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/thread.c (push_list): Use ALLOC().
+
+ * ext/thread/thread.c (rb_mutex_alloc): Ditto.
+
+ * ext/thread/thread.c (rb_condvar_alloc): Ditto.
+
+Sat Mar 3 18:53:11 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * NEWS: Add a note for String#intern.
+
+Sat Mar 3 16:23:13 2007 Akinori MUSHA <knu@iDaemons.org>
* env.h (SCOPE_CLONE): Introduce a new scope flag to prevent a
local_tbl region from getting freed many times; submitted by
@@ -245,17 +4624,78 @@ Sat Mar 3 16:30:39 2007 Akinori MUSHA <knu@iDaemons.org>
* parse.y (top_local_setup_gen): Ditto.
-Sat Mar 3 15:41:33 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Sat Mar 3 16:07:02 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * object.c (rb_obj_ivar_set): RDoc updated according to a
+ suggestion from Brian Candler <B.Candler AT pobox.com>.
+ [ruby-core:10469]
+
+Thu Mar 1 21:38:07 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* parse.y (stmt, arg): should not omit lhs of OP_ASGN1 even if
+ empty. [ruby-dev:30455]
+
+Thu Mar 1 08:55:38 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_feature_p): check loading_tbl if the given ext is
empty. [ruby-dev:30452]
+ * eval.c (rb_feature_p): fix possible buffer overrun.
+
+Thu Mar 1 03:30:21 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/digest.c (get_digest_base_metadata): Allow inheriting
+ Digest::Base subclasses, which was unintentionally made
+ impossible while restructuring Digest classes.
+
+Thu Mar 1 02:05:17 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * mkconfig.rb (patchlevel): read from version.h.
+
+Thu Mar 1 00:09:39 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (rb_provided): return true only for features loaded from
+ .rb files, and not search actual library type. [ruby-dev:30414]
+
+Wed Feb 28 21:15:00 2007 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in (ac_cv_func_fcntl): fcntl support for MinGW.
+
+ * missing/flock.c: workaround for MinGW.
+
Wed Feb 28 20:51:32 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
* pack.c (pack_unpack): properly ignore non-base64 octets such as
UTF-8 encoded BOMs; submitted by SOUMA Yutaka <holon@radastery.jp>
to fix [ruby-core:10437]
+Wed Feb 28 18:59:57 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * NEWS: Add NEWS, a document file to keep user visible feature
+ changes between releases.
+
+Wed Feb 28 18:35:50 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/openssl/extconf.rb: no need to check unistd.h and sys/time.h.
+ they are already checked at configure.
+ reported by KOBAYASHI Yasuhiro [ruby-list:43225]
+
+Wed Feb 28 18:34:48 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/mkmf.rb ($DEFLIBPATH): default library paths ($(topdir), etc)
+ should be the first elements of library paths list.
+ reported by KOBAYASHI Yasuhiro [ruby-list:43225]
+
+Wed Feb 28 18:31:32 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * doc/NEWS-1.8.0: Rename NEWS to NEWS-1.8.0. This is way too old
+ NEWS.
+
+Wed Feb 28 01:22:58 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * test/{dbm,gdbm}/test_{dbm,gdbm}.rb: shouldn't use host_os. use
+ target_os instead. reported by KOBAYASHI Yasuhiro [ruby-list:43225]
+
Wed Feb 28 00:08:11 2007 URABE Shyouhei <shyouhei@ice.uec.ac.jp>
* mkconfig.rb (RbConfig): add CONFIG['PATCHLEVEL']
@@ -264,43 +4704,305 @@ Wed Feb 28 00:08:11 2007 URABE Shyouhei <shyouhei@ice.uec.ac.jp>
* distruby.rb: new file
-Tue Feb 27 21:19:35 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+Tue Feb 27 22:18:45 2007 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in (--enable-auto-image-base): avoid the neccessity to
+ rebase the shared libs as much as possible;
+ submitted by Corinna Vinschen <spam at vinschen.de> in
+ [ruby-talk:240964].
+
+Tue Feb 27 21:36:47 2007 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * util.c (__crt0_glob_function): use ruby_glob() instead of rb_globi().
+
+Tue Feb 27 21:33:04 2007 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in (ac_cv_func_setrlimit): workaround for djgpp.
+
+Tue Feb 27 19:38:52 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/base64.rb (Base64::b64encode): Fix documentation; submitted
+ by David Symonds <dsymonds@gmail.com> in [ruby-core:10432].
+
+Tue Feb 27 19:36:57 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * regex.c (calculate_must_string, slow_search, re_search): Silence
+ warnings regarding char * vs. unsigned char * mismatch;
+ submitted by Lyle Johnson <lyle.johnson@gmail.com>
+ in [ruby-core:10416].
+
+ * ext/bigdecimal/bigdecimal.c (BigDecimal_load): Ditto.
+
+ * ext/digest/sha1/sha1ossl.c (SHA1_Finish): Ditto.
+
+ * ext/digest/rmd160/rmd160ossl.c (RMD160_Finish): Ditto.
+
+ * ext/digest/digest.c (rb_digest_base_finish,
+ rb_digest_base_update): Ditto.
+
+ * ext/nkf/nkf.c (rb_str_resize, rb_nkf_kconv, rb_nkf_guess1,
+ rb_nkf_guess2): Ditto.
+
+Tue Feb 27 03:40:09 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/thread.c (wait_list_cleanup, rb_mutex_try_lock):
+ Eliminate rb_thread_critical switching where unnecessary;
+ implied by shugo in [ruby-dev:30412].
+
+ * ext/thread/thread.c (set_critical): Merge in
+ thread_exclusive_ensure().
+
+ * ext/thread/thread.c: Consistently use 0 and 1 for
+ rb_thread_critical values.
+
+Mon Feb 26 15:18:23 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/thread.c: Use xmalloc()/xfree() instead of
+ malloc()/free(); pointed out by shugo in [ruby-dev:30412].
+
+Sun Feb 25 23:02:55 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/test/unit/autorunner.rb (Test::Unit::AutoRunner::initialize):
+ Initialize @workdir properly to silence a warning under -w.
+ Submitted by <tommy at tmtm.org> in [ruby-dev:30400].
+
+Sun Feb 25 02:47:43 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * defines.h: Pull the RUBY_MBCHAR_MAXSIZE definition from trunk,
+ which is necessary for dir.c to compile on djgpp and emx.
+
+Sat Feb 24 10:42:01 2007 Minero Aoki <aamine@loveruby.net>
+
+ * ext/racc/cparse/cparse.c (cparse_params_mark): remove useless
+ rb_gc_mark. Thanks Tomoyuki Chikanaga. [ruby-dev:30405]
+
+Fri Feb 23 15:10:46 2007 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/win32.c (set_pioinfo_extra): new function for VC++8 SP1
workaround. [ruby-core:10259]
* win32/win32.c (NtInitialize): call above function.
-Mon Feb 26 09:57:58 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+Fri Feb 23 14:19:40 2007 NAKAMURA Usaku <usa@ruby-lang.org>
- * signal.c (ruby_signal): don't set SA_RESTART. a backport from
- the HEAD. [ruby-talk:220937] [ruby-talk:147220]
+ * signal.c (sighandler): need to tell to be interrupted to main
+ context when handler is installed.
+
+ * win32/win32.[ch] (rb_win32_interrupted): new function to listen
+ interrupt.
+
+Fri Feb 23 13:02:17 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * numeric.c (fix_cmp, fix_equal): Remove FIX2LONG() to optimize.
+ suggested in
+ http://t-a-w.blogspot.com/2007/02/making-ruby-faster.html.
+ [ruby-talk:240223]
+
+Fri Feb 23 12:43:17 2007 James Edward Gray II <james@grayproductions.net>
+
+ * lib/xmlrpc/client.rb (XMLRPC::Client::do_rpc): Make the
+ Content-Length parameter optional for responses in
+ xmlrpc/client.rb; suggested by Daniel Berger
+ <Daniel.Berger@qwest.com> and approved by the maintainer.
+
+ * lib/xmlrpc/create.rb (XMLRPC::Create::conv2value): Add DateTime
+ support to xmlrpc; approved by the maintainer.
+
+Mon Feb 19 18:22:52 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in, defines.h, eval.c (rb_feature_p, rb_provided,
+ load_wait, search_required, rb_require_safe), ext/extmk.rb: Fix
+ a bug where a statically linked extension cannot be autoloaded.
+ [ruby-dev:30023] / [ruby-dev:30239]
+
+Mon Feb 19 17:14:28 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c (unix_peeraddr): wrong syscall name in error
+ message for #peeraddr. a patch from Sam Roberts
+ <sroberts at uniserve.com>. [ruby-core:10366]
+
+Sun Feb 18 19:35:21 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb: updated based on date2 4.0.3.
+
+Fri Feb 16 11:18:21 2007 Eric Hodel <drbrain@segment7.net>
+
+ * lib/.document: Apply patch for irb, e2mmap and README by Hugh Sasse
+ <hgs at dmu.ac.uk> from [ruby-core:10135]
+
+ * lib/prettyprint.rb: Suppress RDoc for PrettyPrint test suite.
+
+Thu Feb 15 20:26:30 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/uri/ftp.rb: Revert the previous change pending discussion.
+
+Thu Feb 15 18:08:17 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * dir.c (glob_helper): Fix the function declaration.
+
+Thu Feb 15 17:13:32 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * version.h: Welcome to the post-1.8.6 world. Radical changes are
+ inhibited in the ruby_1_8 branch until the 1.8.6 final release
+ goes out of the door.
+
+Thu Feb 15 16:44:14 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/uri/generic.rb (URI::Generic::userinfo): Considering how
+ `scheme://user:@...', `scheme://:password@...' and
+ `scheme://:@...' are parsed, an empty user name or password
+ should be allowed and represented as it is.
+
+Thu Feb 15 11:46:05 2007 KIMURA Koichi <hogemuta@gmail.com>
+
+ * dir.c, win32/win32.c, win32/dir.h, ruby.h, intern.h: Bring
+ encoding aware globbing support in from trunk. Dir.[] and
+ Dir.glob() can now take many patterns in an array. Minor fixes
+ will follow.
+
+Thu Feb 15 11:00:26 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/uri/generic.rb (URI::Generic::userinfo): should support
+ empty password. [ruby-core:10290]
+
+ * lib/uri/generic.rb (URI::Generic::set_password): password can be
+ cleared by nil. [ruby-core:10290]
+
+ * lib/uri/common.rb (escape): regard second string argument as a
+ character set properly. [ruby-dev:27692]
+
+ * lib/uri/ftp.rb: Attempt to conform to RFC 1738 with regard to
+ relative/absolute paths.
+
+ * lib/uri: Lovely RDOC patches from mathew (metaATpoboxDOTcom).
+
+Thu Feb 15 10:57:38 2007 Tietew <tietew@tietew.net>>
+
+ * lib/cgi.rb (CGI::unescapeHTML): invalid decoding for single
+ unescaped ampersand. a patch from Tietew
+ <tietew+ruby-dev at tietew.net> in [ruby-dev:30292].
+ fixed: [ruby-dev:30289]
+
+Thu Feb 15 10:48:40 2007 MenTaLguY <mental@rydia.net>
+
+ * ext/thread/thread.c: Handle interrupted waits correctly.
+ [ruby-bugs:PR#8663]
+
+Wed Feb 14 19:22:15 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/lib/digest.rb (Digest::self.const_missing): Drop
+ autoloads for sha2 classes in favor of handling in
+ const_missing(), to work around a problem exposed on OS X.
Tue Feb 13 02:21:12 2007 Sam Roberts <sroberts@uniserve.com>
* io.c (rb_f_syscall): Fix buffer overflow with syscall
arguments. [ruby-bugs:PR#8541]
-Sat Feb 10 09:33:47 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+Sun Feb 11 07:46:45 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/cgi.rb (CGI::QueryExtension::read_multipart): Properly parse
+ a quoted-string in a Content-Disposition value.
+
+Sun Feb 11 06:27:54 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * configure.in, ext/thread/extconf.rb, lib/thread.rb: Add a
+ configure option `--disable-fastthread', to choose the original,
+ pure ruby version of the "thread" library instead of the new,
+ much faster implementation in ext/thread.
+
+Sun Feb 11 06:22:20 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/Setup: Add thread except for platforms without threads
+ support.
+
+Sun Feb 11 06:15:16 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/lib/thread.rb: Add a replacement of thread.rb that
+ loads this extension.
+
+Sun Feb 11 05:39:47 2007 Akinori MUSHA <knu@iDaemons.org>
- * ext/win32ole/win32ole.c (ole_variant2val): sorry, fix the enbug.
+ * lib/thread.rb: Remove an ineffective part of the code.
-Sat Feb 10 09:08:01 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+Sun Feb 11 05:32:54 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/thread.c (rb_thread_exclusive): Implement
+ Thread.exclusive.
+
+Sun Feb 11 05:26:51 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread/thread.c: Get rid of use of a dummy function.
+
+Sun Feb 11 01:45:31 2007 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/thread/thread.c (Init_thread): Define missing aliases:
+ Queue#enq and SizedQueue#enq.
+
+Sat Feb 10 09:27:35 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
* ext/win32ole/win32ole.c (ole_variant2val): fix compile error
on VC++.
-Sat Feb 10 08:38:30 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+Sat Feb 10 07:41:52 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
* ext/win32ole/win32ole.c (ole_variant2val): fix the bug when
SAFEARRAY pointer is NULL.
-Tue Feb 6 20:41:39 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+Sat Feb 10 00:13:11 2007 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: fix typo (TkConfigMethod::__confinfo_cmd,
+ __conv_keyonly_opts).
+
+Fri Feb 9 20:44:53 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread: Make style fixes (mostly de-K&R'ism) to match the
+ rest of the source code.
+
+ * ext/thread: Make USE_MEM_POOLS an extconf option.
+
+Fri Feb 9 20:43:01 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/thread: Import the "fastthread" implementation by MenTaLguY
+ in the original form. This module is not hooked into the build
+ yet since it needs some style fixes and adjustments.
+
+Fri Feb 9 15:46:09 2007 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/bigdecimal: Synchronize with trunk. Better function
+ prototypes, removal of a useless method `!=', and document
+ updates.
+
+Tue Feb 06 22:06:45 2007 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/nkf-utf8/{nkf.c,utf8tbl.c}:
+ imported nkf 2007-01-28.
+ * Fixed: can't decode MIME encode JIS string.
+ * Fixed: Fullwitdh-halfwidth conversion.
+ * Support DoCoMo's and Softbank's EMOJI
+ * Support CP932, CP5022x, eucJP-ms UDC
+ * Support UTF-32 encoding
+ * Support beyond BMP
+ [ruby-dev:29700] [ruby-dev:29922] [ruby-dev:30144]
+
+Wed Jan 31 14:52:09 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_iterate): need to PUSH_ITER in proper order.
+ [ruby-core:10125]
+
+ * test/ruby/test_iterator.rb (TestIterator::test_block_given_within_iterator):
+ add new test. [ruby-core:10125]
+
+Tue Jan 30 14:58:51 2007 NAKAMURA Usaku <usa@ruby-lang.org>
* string.c (rb_str_sub_bang): calling rb_str_modify() should be just
before actually modifying the string.
fixed: [ruby-dev:30211] (originally reported by zunda)
+Tue Jan 30 12:05:35 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * mkconfig.rb: autoconf 2.61 support. [ruby-core:10016]
+
Sat Jan 27 15:20:11 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
* parse.y (dyna_var_lookup): should not alter dvar->val not to
@@ -308,68 +5010,216 @@ Sat Jan 27 15:20:11 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
* parse.y (dyna_init): ditto.
+Fri Jan 26 12:03:39 2007 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb (TkConfigMethod#__confinfo_cmd,
+ __conv_keyonly_optkeys): make them private [ruby-dev:30074].
+
+ * ext/tk/lib/tk/txtwin_abst.rb: fix typo [ruby-dev:30073].
+
+ * ext/tk/lib/tk/canvas.rb (TkCanvas#scan_dragto): lack of an argument.
+
+ * ext/tk/lib/tk/canvas.rb: clarify the including module name
+ [ruby-dev:30080].
+
+ * ext/tk/lib/tk/scrollable.rb: change primary name of modules
+ [ruby-dev:30080].
+
Wed Jan 24 18:05:39 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
* misc/ruby-mode.el (ruby-font-lock-syntactic-keywords): fix
regexp font-lock bug. [ruby-talk:235758]
-Sun Jan 14 07:26:44 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+Tue Jan 23 11:02:33 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/webrick/httprequest.rb (WEBrick::HTTPRequest::read_line):
+
+Tue Jan 23 18:26:12 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi.rb (CGI::QueryExtension::read_multipart): use == instead
+ of ===. [ruby-dev:30176]
+
+Tue Jan 23 10:48:17 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * hash.c: added documentation for Hash about how it uses eql? and
+ hash methods for the keys. [ruby-core:09995]
+
+Mon Jan 22 14:57:25 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c: fix errors in socket sample code.
+ [ruby-core:09992]
+
+Sat Jan 13 23:54:48 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
- * ext/win32ole/win32ole.c (ole_free, ole_type_free,
- olemethod_free, olevariable_free, oleparam_free,
+ * ext/win32ole/win32ole.c (ole_free, ole_type_free,
+ olemethod_free, olevariable_free, oleparam_free,
ole_event_free): fix memory leak. [ruby-core:09846]
-Tue Jan 9 12:29:20 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Fri Jan 12 11:13:55 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/etc/etc.c (etc_getpwuid, etc_getgrgid): fix to correctly
- convert uid/gid from VALUE.
+ convert uid/gid from VALUE. (backport of r11521)
- * ext/etc/etc.c (etc_getpwuid): ditto.
+Wed Jan 10 18:57:57 2007 Minero Aoki <aamine@loveruby.net>
-Mon Dec 25 20:08:28 2006 URABE Shyouhei <shyouhei@ruby-lang.org>
+ * ext/strscan/strscan.c (strscan_do_scan): should set kcode option
+ before match. [ruby-dev:29914]
- * ext/openssl/ossl.h: fixed compilation problem on gcc 3.2.
- [ruby-talk:214786]
+ * test/strscan/test_stringscanner.rb: test it.
-Mon Dec 25 10:40:40 2006 URABE Shyouhei <shyouhei@ruby-lang.org>
+ * re.c: export kcode_set_option and kcode_reset_option (with "rb_"
+ prefix).
- * stable version 1.8.5-p12 released.
+ * intern.h: ditto.
-Sat Dec 16 04:02:10 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+Tue Jan 9 17:45:17 2007 NAKAMURA Usaku <usa@ruby-lang.org>
- * ext/tk/tcltklib.c: shouldn't run the killed thread at callback.
- [ruby-talk: 227408]
+ * file.c (rb_find_file): should not call fpath_check() with NULL.
+ fixed: [ruby-core:09867]
-Fri Dec 15 17:21:14 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+Tue Jan 9 03:54:38 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
- * lib/rdoc/ri/ri_options.rb: prevent NameError. [ruby-dev:29597]
+ * string.c (rb_str_upto): String#upto from empty string makes
+ inifinite loop. [ruby-core:09864]
-Thu Dec 14 23:37:38 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Sun Jan 7 12:13:26 2007 Eric Hodel <drbrain@segment7.net>
- * dir.c (glob_helper): get rid of possible memory leak.
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser#find_class_comment):
+ Look for class and module comments above rb_define_class and
+ rb_define_module. Patch by Daniel Berger <djberg96 at gmail.com>
- * win32/win32.c (cmdglob, rb_w32_cmdvector, rb_w32_opendir,
- rb_w32_get_environ): not to use GC before initialization.
+Sun Jan 7 10:32:12 2007 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser#handle_constants):
+ Properly handle escaping of : in comments.
+ * test/rdoc/parsers/test_parse_c.rb:
+ Test RDoc::C_Parser#do_classes and Rdoc::C_Parser#find_class_comment.
+
+Sun Jan 7 09:33:02 2007 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb: updated based on date2 4.0.1.
+
+Wed Jan 3 11:36:51 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (ruby_dup): start GC on ENOMEM as well.
+
+Mon Jan 1 06:13:11 2007 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/parsers/c_parser.rb: Make Rdoc accessible. Update constant
+ value information.
+
+Mon Jan 1 06:13:11 2007 Eric Hodel <drbrain@segment7.net>
+
+ * ext/bigdecimal/bigdecimal.c: Update constant comments to provide
+ values for RDoc.
+
+Mon Jan 1 06:05:55 2007 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser#handle_constansts):
+ Allow RDoc comment to give friendly value for rb_define_const. Patch
+ by Daniel Berger <djberg96 at gmail.com>, [ruby-patches-7499].
+ * lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser#handle_constansts): Fix
+ whitespace handling in constant comments.
+
+Sun Dec 31 00:31:16 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: updated based on date2 4.0.
+
+Thu Dec 14 18:29:13 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/readline/readline.c: NetBSD editline does not have
+ rl_username_completion_function() and rl_completion_matches().
+ a patch from Takahiro Kambe <taca at back-street.net>.
+ [ruby-dev:30008]
+
+Thu Dec 14 18:20:43 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/irb/locale.rb (IRB::Locale::puts): typo fixed. a patch from
+ NAKAMURA Usaku <usa@ruby-lang.org>. [ruby-dev:30012]
+
+Mon Dec 11 11:58:36 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/sha2/lib/sha2.rb: Moved one level up from under
+ the superfluous subdirectory digest/.
+
+Mon Dec 11 11:46:18 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * variable.c (rb_define_const): typo fixed.
+
+Mon Dec 11 09:36:29 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_aset): index double decode problem.
+ [ruby-core:09695]
+
+Sat Dec 9 21:39:24 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (ruby_cleanup): keep the exception till after END blocks.
+ [ruby-core:09675]
+
+Sat Dec 9 11:22:00 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/irb/locale.rb (IRB::Locale::search_file): ues File.exist?
+ instead of File.exists?. a patch from Yutaka Kanemoto
+ <kinpoco at gmail.com> in [ruby-dev:30000].
+
+Thu Dec 7 09:29:02 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/weakref.rb (WeakRef::__setobj__): should support
+ marshaling. [ruby-talk:228508]
+
+ * lib/delegate.rb (Delegator::marshal_load): need to call
+ __setobj__.
-Wed Dec 6 19:53:41 2006 WATANABE Hirofumi <eban@ruby-lang.org>
+Wed Dec 6 23:56:14 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in, common.mk (NULLCMD): moved for platforms that empty
+ command does not run. fixed: [ruby-dev:29994]
+
+Wed Dec 6 17:17:26 2006 WATANABE Hirofumi <eban@ruby-lang.org>
* configure.in (SITE_DIR): fixed to emtpy RUBY_SITE_LIB in config.h on
NetBSD. fixed: [ruby-dev:29358]
+Tue Dec 5 00:59:05 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-parse-partial): need to parse "/=" as
+ self assignment operator, not regex. [ruby-talk:227324]
+
+Mon Dec 4 10:48:03 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.h (OFFT2NUM): use LONG2NUM() if sizeof(long) equals to
+ sizeof(off_t).
+
Mon Dec 4 10:43:46 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* parse.y (dyna_init_gen): dvar initialization only if dvar is
assigned inner block. [ruby-talk:227402]
-Mon Dec 4 10:22:26 2006 URABE Shyouhei <shyouhei@ice.uec.ac.jp>
-
- * stable version 1.8.5-p2 released.
-
-Sun Dec 3 17:11:12 2006 Shugo Maeda <shugo@ruby-lang.org>
+Mon Dec 4 08:32:49 2006 Shugo Maeda <shugo@ruby-lang.org>
* lib/cgi.rb (CGI::QueryExtension::read_multipart): should quote
boundary. JVN#84798830
+Sat Dec 2 07:09:04 2006 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_ocsp.c: OpenSSL::OCSP::OSCPError should be
+ subclass of OpenSSL::OpenSSLError. [ruby-dev:29980]
+
+Fri Dec 1 17:01:49 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * gc.c (ruby_init_stack): decrease "stack level too deep" in Windows.
+ merge from trunk.
+
+Fri Dec 1 16:31:53 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/tcltklib.c: shouldn't run the killed thread at callback.
+ [ruby-talk: 227408]
+
+Mon Nov 27 17:18:27 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * sprintf.c (rb_f_sprintf): need not to truncate string if no
+ width specifier given for %s. [ruby-dev:29952]
+
Sun Nov 26 16:36:46 2006 URABE Shyouhei <shyouhei@ruby-lang.org>
* version.h: addition of RUBY_PATCHLEVEL.
@@ -380,26 +5230,891 @@ Fri Nov 24 10:17:51 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* bignum.c (bignorm): avoid segmentation. a patch from Hiroyuki
Ito <ZXB01226@nifty.com>. [ruby-list:43012]
+Thu Nov 23 10:38:40 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_mod_define_method): set implicit visibility only when
+ it's called for the target class (ruby_cbase).
+
+Wed Nov 22 16:00:49 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/extconf.rb: support --with-X11/--without-X11 option.
+
+ * ext/tk/README.tcltklib: add description about --with-X11-* option
+ [ruby-talk:225166] and --with-X11/--without-X11 option.
+
+ * ext/tk/tkutil/extconf.rb: able to be called manually
+ [ruby-talk:225950].
+
+Wed Nov 15 23:22:54 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (test_grpowned, rb_stat_grpowned): should honor
+ supplementary group IDs. [ruby-core:09546]
+
+Thu Nov 9 03:15:22 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (BEGIN_CALLARGS): ruby_block may be NULL even when
+ ITER_PRE.
+
+Tue Nov 7 18:34:34 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/lib/digest/hmac.rb: Keep this out of the 1.8 tree
+ until we reach a consensus that HMAC should be put under Digest.
+
+Tue Nov 7 18:05:01 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/itemconfig.rb: minor bug fix.
+
+Mon Nov 6 20:11:20 2006 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/0.9.rb (RSS::Rss): removed needless include.
+
+Mon Nov 6 15:41:55 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/itemconfig.rb: ext/tk/lib/tk/itemconfig.rb: bug
+ fix on 'itemconfiginfo' method, and modify to make it easy to
+ override 'itemconfiginfo' method.
+
+ * ext/tk/lib/tkextlib/tile/treeview.rb : support Tile 0.7.8.
+
+ * ext/tk/lib/tkextlib/version.rb : [new] add Tk::Tkextlib_RELEASE_DATE
+ to get the information from scripts.
+
+ * ext/tk/lib/tk.rb: load 'tkextlib/version.rb', and update RELEASE_DATE
+
+ * ext/tk/lib/tkextlib/SUPPORT_STATUS: update.
+
+ * ext/tk/sample/editable_listbox.rb: [new] the listbox with editable
+ items. It's one of the example about usage of Place geometry manager.
+
+ * ext/tk/sample/tktextio.rb: improve the functions of TkTextIO class.
+ Those are required by 'irbtkw.rbw'.
+
+ * ext/tk/sample/irbtkw.rbw: [new] IRB on Ruby/Tk. It doesn't need any
+ real console. IRB works on a text widget without I/O blocking. That
+ is, thread switching on IRB will work properly, even if on Windows.
+
+Sun Nov 5 19:53:49 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb: updated based on date2 3.9.7.
+
+Sat Nov 4 13:13:57 2006 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb: accept NOMODSEQ. [ruby-core:9002]
+ (backported from HEAD)
+
+Fri Nov 3 00:16:37 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c (ruby_getnameinfo__aix): AF_INET6 workaround
+ for AIX. a patch from Yutaka Kanemoto <kinpoco AT gmail.com>.
+ [ruby-dev:29744]
+
Thu Nov 2 15:43:39 2006 NAKAMURA Usaku <usa@ruby-lang.org>
* parse.y (primary): should set NODE even when compstmt is NULL.
merge from trunk. fixed: [ruby-dev:29732]
+Thu Nov 2 14:48:30 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/set.rb (Set#^): Fix XOR operation against a container that
+ holds duplicate values. [issue: #6444]
+
+Wed Nov 1 02:41:38 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/lib/digest/hmac.rb (Digest::HMAC::update): Minor
+ optimization.
+
+ * ext/digest/digest.c (rb_digest_instance_equal): Allow comparing
+ a digest instance with another of a different class.
+
+Wed Nov 1 01:05:13 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * eval.c (rb_call0): fixed bug of zsuper with both of opt and rest.
+ fixed: [ruby-list:42928]
+
+ * test/ruby/test_super.rb: add tests to check above bug.
+
+Tue Oct 31 17:03:21 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * time.c (time_dup): duplicate the class of original time.
+ [ruby-core:09357]
+
+ * lib/time.rb (Time::make_time, Time::rfc2822, Time::httpdate):
+ should respect subclasses. [ruby-core:09357]
+
+Mon Oct 30 23:40:52 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in (miniruby): add XLDFLAGS.
+
+ * configure.in (aix): use -bE option for miniruby. [ruby-dev:29698]
+
+ * dir.c (glob_helper): get rid of possible memory leak.
+
+ * win32/win32.c (cmdglob, rb_w32_cmdvector, rb_w32_opendir,
+ rb_w32_get_environ): not to use GC before initialization.
+
+Mon Oct 30 19:29:20 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * bignum.c (rb_big2str0): use better approximation.
+
+Mon Oct 30 18:35:33 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big2str0): wrong allocation length. a patch from
+ U.Nakamura <usa at garbagecollect.jp> [ruby-dev:29710]
+
+Mon Oct 30 12:34:02 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_eval): fix commit miss. [ruby-dev:29707]
+
+Mon Oct 30 12:20:58 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big2str0): a bug in length adjustment.
+
+Mon Oct 30 11:15:40 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * sprintf.c (rb_str_format): should preserve leading zero
+ information for negative %b and %x. [ruby-talk:221347]
+
+Thu Oct 26 21:05:58 2006 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * ext/openssl/ossl_pkcs7.c (ossl_pkcs7_verify): should clear error.
+ (fix http://bugs.debian.org/394336)
+
+ * ext/openssl/ossl_ns_spki.c (ossl_spki_initialize): ditto.
+
+Thu Oct 26 15:21:10 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/digest/digest.c (Init_digest): typo.
+
+Wed Oct 25 17:23:28 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest, test/digest/test_digest.rb: Merge from trunk:
+ - Introduce versioning in Digest::Base API, and prefix C
+ constants with RUBY_ and C type names with rb_ to avoid name
+ clash in writing extensions.
+ - Introduce Digest::Class and Digest::Instance for ease of
+ implementing subclasses and add-ons.
+ - Digest::Instance module requires and assumes that any instance
+ be resettable and clonable. An instance method #new() is
+ added so digest instances work just like digest classes.
+ - The constructor does no longer take an initial string to feed;
+ digest() and hexdigest() now do, instead. This allows digest
+ classes to take their own hashing parameters.
+ - Make some changes to digest() and hexdigest() class methods,
+ which now take extra arguments, which are passed through to
+ the constructor in an internal call.
+ - Add #digest_length/size/length() and #block_length(),
+ - Add the Digest::SHA2 class to wrap up SHA2 variants: SHA256,
+ SHA384 and SHA512, hoping this module would make a decent
+ example of a digest subclass written in Ruby.
+ - Rip BubbleBabble support out of the base class and have a
+ separate module named digest/bubblebabble.
+ - Remove RD documents in favor of newly written and embedded
+ RDoc documentation.
+
+Wed Oct 25 08:03:23 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb: updated based on date2 3.9.6.
+ [ruby-core:09323]
+
+Sun Oct 22 14:48:31 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * signal.c (ruby_signal): don't set SA_RESTART. a backport from
+ the HEAD. [ruby-talk:220937] [ruby-talk:147220]
+
+ * signal.c (Init_signal): avoid duplicated installation of SIGCHLD
+ handler.
+
+Sun Oct 22 16:47:56 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (rb_str_substr): should be infected with only original
+ string, but not the shared string. fixed: [ruby-core:09152]
+
+ * string.c (rb_str_new4): keep shared string untainted when orignal
+ string is tainted. fixed: [ruby-dev:29672]
+
+Sun Oct 22 05:20:34 2006 URABE Shyouhei <shyouhei@ice.uec.ac.jp>
+
+ * configure.in: alloca is broken; use C_ALLOCA instead.
+ [ruby-dev:29416]
+
+Fri Oct 20 10:47:43 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/mkmf.rb: fixed the bug of handling COMMON_MACROS.
+
+Fri Oct 20 08:42:38 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (NULLCMD): dummy command.
+
+ * bcc32/Makefile.sub (post-install-*): Borland make cannot ignore
+ command-less double-colon rules. [ruby-dev:29676]
+
+Fri Oct 20 00:37:07 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bcc32/Makefile.sub ($(LIBRUBY_SO)): execute pre-link hook.
+
+ * ext/extmk.rb: workaround for Borland make.
+
+Wed Oct 18 23:02:40 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (rb_ary_shift): shorten copy size. fixed: [ruby-list:42907]
+
+ * signal.c (Init_signal): handle SIGTERM. fixed: [ruby-list:42895]
+
+ * win32/win32.c (rb_w32_utime): allow NULL to set the current time.
+ [ruby-talk:219248]
+
+Wed Oct 18 00:55:33 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (parser_yylex): use particular enums. [ruby-core:09221]
+
+Mon Oct 16 08:30:43 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * mkconfig.rb: *OBJS are not needed for extension libraries.
+
+ * {bcc32,wince,win32}/Makefile.sub (config.status): fixed typo,
+ missing comma.
+
+Sun Oct 15 01:03:08 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/test/unit/collector/dir.rb (Collector::Dir#collect): append base
+ directory but not prepend.
+
+ * lib/test/unit/collector/dir.rb (Collector::Dir#collect_file): do not
+ join with dot. fixed: [ruby-core:09179]
+
+Sat Oct 14 23:39:50 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (singleton): no need to re-create NODE_SELF() again.
+ [ruby-core:09177]
+
+Sat Oct 14 23:25:31 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (parser_warning, parser_warn): some error message may
+ contain format specifiers. a patch from Akinori MUSHA <knu at
+ iDaemons.org>. [ruby-dev:29657]
+
+ * ext/bigdecimal/bigdecimal.c (VpException): ditto.
+
+ * ext/dl/handle.c (rb_dlhandle_initialize): ditto.
+
+ * ext/gdbm/gdbm.c (rb_gdbm_fatal): ditto.
+
+Sat Oct 14 08:24:45 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/lib/digest/hmac: Back out the addition of digest/hmac
+ for now because the API is too premature for a stable branch.
+
+Sat Oct 14 00:55:08 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * bcc32/Makefile.sub (post-install-ext): no longer needed.
+
+ * bcc32/configure.bat: get rid of a quirk of Borland make, which
+ sets empty macro in command line to "1".
+
+Fri Oct 13 22:50:43 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb: updated based on date2 3.9.5.
+
+Fri Oct 13 22:33:28 2006 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb (FileUtils.cp_r): dereference_root=true is
+ default in Ruby 1.8. This line is wrongly removed in last commit.
+
+Fri Oct 13 18:19:31 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c: Class#inherited RDoc added. a patch from Daniel
+ Berger <djberg96 at gmail.com> [ruby-core:08942]
+
+Fri Oct 13 02:30:12 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/test/unit/collector/dir.rb (Collector::Dir#collect): prepend
+ base directory to load path.
+
+ * lib/test/unit/collector/dir.rb (Collector::Dir#collect_file): should
+ use the given File-like interface, but not File directly.
+
+ * test/testunit/collector/test_dir.rb (TestDir::FileSystem): implement
+ File-like methods correctly.
+
+Fri Oct 13 01:48:42 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/date.rb (Date::self.complete_hash): need to check if g is
+ nil before dereference. [ruby-core:09116]
+
+Fri Oct 13 00:34:26 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (rb_mod_cvar_defined): wrong id check. a patch from
+ Mauricio Fernandez <mfp at acm.org>. [ruby-core:09158]
+
+ * object.c (rb_mod_cvar_get): typo fixed. [ruby-core:09168]
+
+ * object.c (rb_mod_cvar_set): ditto.
+
+Wed Oct 11 22:21:41 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest: Merge from trunk; metadata location changed,
+ Digest::Base#reset() added, Digest::Base#equal() changed, and
+ digest/hmac added with some modifications made for ruby 1.8.
+
+Tue Oct 10 17:24:12 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * {bcc32,win32,wince}/Makefile.sub (config.status): shouldn't use
+ copy command instead of install. use -run install.
+
+Tue Oct 10 16:49:16 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest/digest.c (hexdigest_str_new, bubblebabble_str_new):
+ Perform StringValue() checks properly.
+
+ * ext/digest/digest.c: Use RSTRING_{PTR,LEN} macros.
+
+Tue Oct 10 13:49:53 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/digest: Merge from trunk; apply all changes since the
+ initial import, except for the removal of compatibility stub
+ libraries (md5.rb and sha1.rb).
+
+Mon Oct 9 23:46:29 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/parsedate.rb: documentation patch from Konrad Meyer
+ <konrad.meyer@gmail.com>. [ruby-doc:1238]
+
+ * lib/open3.rb, lib/ping.rb: ditto.
+
+Mon Oct 9 22:56:12 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/rexml/encoding.rb (REXML::Encoding::check_encoding): spaces
+ are allowed around equal sign. [ruby-core:09032]
+
+ * lib/rexml/parsers/baseparser.rb (REXML::Parsers::BaseParser): ditto.
+
+Sat Oct 7 23:53:08 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_scan): small documentation fix.
+ [ruby-core:09007]
+
+Sat Oct 7 23:44:33 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big_rshift): a bug in right shift of negative
+ bignums. [ruby-core:09020]
+
+Sat Oct 7 00:27:58 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * class.c (rb_include_module): remove unnecessary check.
+ [ruby-talk:218402]
+
+Fri Oct 6 04:30:30 2006 Akinori MUSHA <knu@iDaemons.org>
+
+ * sample/openssl/c_rehash.rb: Use digest/md5 instead of obsolete md5.
+
+Wed Oct 4 18:47:25 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tkextlib/*: bugfix and update
+ (see ext/tk/ChangeLog.tkextlib).
+
+Wed Oct 4 17:25:14 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_call): check protected visibility based on real self,
+ not ruby_frame->self. [ruby-talk:217822]
+
+Wed Oct 4 08:52:30 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * test/optparse/test_getopts.rb: changed the class name of test case
+ to get rid of conflict with test_optparse.rb.
+
+Tue Oct 3 23:32:27 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/test/unit/testcase.rb (Test::Unit::TestCase.suite): test name
+ must be string. fixed: [ruby-core:08978]
+
+Mon Oct 2 23:47:55 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/test/unit/autorunner.rb (Test::Unit::AutoRunner::COLLECTORS):
+ base directory should be lower precedence. fixed: [ruby-dev:29622]
+
+ * lib/test/unit/autorunner.rb (Test::Unit::AutoRunner#options): typo.
+
+ * lib/test/unit/collector/dir.rb (Test::Unit::Collector::Dir#collect_file):
+ load expanded path. fixed: [ruby-dev:29621]
+
+Mon Oct 2 15:49:19 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * instruby.rb: batfile should be CRLF'ed.
+
+Mon Oct 2 01:24:26 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (test-all): separate directory where running test cases
+ from source tree.
+
+ * lib/test/unit/autorunner.rb (options): added --basedir, --workdir
+ and --load-path options.
+
+ * lib/test/unit/collector/dir.rb (recursive_collect, collect_file):
+ base directory support.
+
+Sun Oct 1 23:56:52 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in, common.mk, ext/extmk.rb, win{32,ce}/Makefile.in: keep
+ LIBRUBY_SO unless need to be removed.
+
+Sun Oct 1 23:12:19 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser#make_switch): pass arguments directly.
+
+Sat Sep 30 15:12:25 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: updated based on date2 3.9.4.
+
+Fri Sep 29 12:11:04 2006 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * jcode.rb (succ!): call original succ! if $KCODE == 'n'.
+ fixed: [ruby-talk:216845]
+
+Fri Sep 29 11:43:40 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (try_func): revert fallback checking undeclared function.
+ fixed: [ruby-core:08949]
+
+Fri Sep 29 09:56:56 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/extmk.rb: extout is needed for also clean.
+ fixed: [ruby-core:08944]
+
+ * lib/optparse.rb (OptionParser::Switch#conv_arg): unsplat by
+ Proc#call if no conversion is given.
+
+Thu Sep 28 23:59:31 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * node.h (struct thread): declare win32_exception_list on cygwin and
+ win32 regardless if it is implemented. Provisional fix for
+ [ruby-core:08917].
+
+Thu Sep 28 20:53:16 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/tmpdir.rb: use return value of getdir.call for length.
+
+Wed Sep 27 01:04:49 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (try_func): check function pointer first and macro next.
+
+ * lib/mkmf.rb (have_type): simplified with typedef and sizeof.
+
+Tue Sep 26 23:57:03 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser#getopts): use strings as key.
+ fixed: [ruby-dev:29614]
+
+Tue Sep 26 15:31:26 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * {win32,wince}/Makefile.sub (CPP): check predefined value.
+
+Tue Sep 26 07:55:16 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_shift): should not move memory region if array
+ body is shared. a patch from Kent Sibilev <ksruby at gmail.com>.
+ [ruby-core:08922]
+
+Mon Sep 25 22:26:26 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rb_path_end): skip root directory. fixed: [ruby-core:08913]
+
+ * lib/mkmf.rb (init_mkmf): set default $LDFLAGS. Patch by Michal
+ Suchanek <hramrach at centrum.cz>. [ruby-talk:216256]
+
+Mon Sep 25 08:14:43 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_shift): should clear shifting top element.
+ [ruby-talk:216055]
+
+ * array.c (rb_ary_shift): avoid creating shared object if array
+ size is small.
+
+Mon Sep 25 08:11:35 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * random.c (rb_f_rand): RDoc typo fix. a patch from Frederick
+ Cheung <fred at 82ask.com>. [ruby-talk:216047]
+
+Sun Sep 24 22:28:20 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * runruby.rb: extension library scripts moved into common directory.
+
+Sun Sep 24 14:59:50 2006 Tanaka Akira <akr@fsij.org>
+
+ * node.h (struct thread): ia64 support is broken by sandbox patch.
+
+Sun Sep 24 12:11:16 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: updated based on date2 3.9.3.
+
+Sat Sep 23 23:24:57 2006 why the lucky stiff <why@ruby-lang.org>
+
+ * eval.c (rb_thread_save_context, rb_thread_restore_context):
+ sandbox hook to save and restore sandbox state.
+
+ * eval.c (thread_no_ensure): added THREAD_NO_ENSURE thread flag.
+
+ * eval.c (rb_thread_kill_bang): Thread#kill! uses the above flag
+ to circumvent ensure, in order to prevent endless loops.
+ [ruby-core:08768]
+
+ * eval.c (rb_thread_kill): fix Thread#kill docs, which returns
+ the thread object in all cases.
+
+ * node.h: expose the rb_jmpbuf_t and rb_thread_t structs, along
+ with the thread flags. used by the sandbox extension.
+
+ * ruby.h: extern rb_eThreadError, so sandbox can swap it.
+
Sat Sep 23 21:34:15 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* lib/cgi.rb (CGI::QueryExtension::read_multipart): CGI content
may be empty. a patch from Jamis Buck <jamis at 37signals.com>.
+Sat Sep 23 08:35:53 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/rdoc/ri/ri_options.rb: prevent NameError. [ruby-dev:29597]
+
+Sat Sep 23 01:04:20 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: updated based on date2 3.9.2.
+
+Fri Sep 22 02:06:26 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * .cvsignore: ignore timestamp files and installed list file.
+
+Fri Sep 22 01:36:34 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * instruby.rb: include FileUtils unconditionally.
+
+Thu Sep 21 22:56:20 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (no-install): not install rdoc actually.
+
+ * common.mk (install-doc, no-install-doc): use instruby.rb.
+
+ * instruby.rb: rdoc installation.
+
+ * ext/extmk.rb: expand ruby executable names.
+
+Thu Sep 21 13:55:07 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/etc/etc.c (etc_getpwuid): uid integer should be wraped in
+ uid_t value. [ruby-core:08897]
+
+ * ext/etc/etc.c (etc_getpwuid): uid_t may be bigger than plain
+ 'int' type.
+
+Wed Sep 20 23:17:41 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (pre-install-doc): create data directory before install.
+
+ * lib/mkmf.rb (dir_re): fixed typo.
+
+ * lib/mkmf.rb (install_dirs): remove extra slash.
+
+Wed Sep 20 09:53:38 2006 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * {bcc32,win32,wince}/Makefile.sub (INSTALLED_LIST): need to define
+ this macro to install.
+
+Wed Sep 20 09:43:10 2006 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb: allow extra spaces in responses.
+ Thanks, Tom Soderlund. (backported from HEAD)
+
+Wed Sep 20 09:25:39 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/gdbm/gdbm.c: add RDoc documentation. a patch from Peter
+ Adolphs <futzilogik at users dot sourceforge dot net>.
+ [ruby-doc:1223]
+
+Tue Sep 19 01:28:00 2006 Minero Aoki <aamine@loveruby.net>
+
+ * lib/fileutils.rb: backport from HEAD (rev 1.71).
+
+ * lib/fileutils.rb (FileUtils.cp_r): new option
+ :remove_destination.
+
+Tue Sep 19 00:42:15 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * object.c (rb_obj_ivar_defined, rb_mod_cvar_defined): new methods,
+ Kernel#instance_variable_defined? and Module#class_variable_defined?.
+ [ruby-dev:29587]
+
+ * lib/date/format.rb (Date::Bag#method_missing): use new method,
+ instance_variable_defined? to check if an instance variable is
+ defined. fixed: [ruby-dev:29554]
+ -- This didn't fix anything.
+
+Sun Sep 17 23:44:58 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/rdoc/rdoc.rb (RDoc::RDoc#document): scan only files modified
+ after the previous generation.
+
+Sun Sep 17 17:42:13 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (install-doc): reverted.
+
+ * instruby.rb: stores file name list without destdir prefix.
+
+ * lib/rdoc/generators/ri_generator.rb: do not chdir twice.
+
+Sat Sep 16 23:14:29 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/pty/pty.c (establishShell): remove remaining unused line.
+
+Sat Sep 16 16:40:44 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in, common.in, instruby.rb, ext/extmk.rb, lib/mkmf.rb:
+ use instruby.rb to install extensions instead of ext/extmk.rb.
+
+ * instruby.rb: store installed list into the file.
+
+ * ext/dbm/extconf.rb: allow multiple candidates for dbm-type.
+
+ * ext/io/wait/extconf.rb: suspicious checking_for.
+
+ * ext/pty/pty.c (establishShell): parent pid is not used.
+
+ * ext/pty/pty.c (freeDevice): not used.
+
+ * ext/pty/pty.c (get_device_once): removed garbage right brace.
+
+ * lib/mkmf.rb (checking_for): improved the messages.
+
+Thu Sep 14 16:11:15 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_intern): raise SecurityError only when $SAFE
+ level is greater than zero. [ruby-core:08862]
+
+ * parse.y (rb_interned_p): new function to check if a string is
+ already interned.
+
+ * object.c (str_to_id): use rb_str_intern().
+
+Wed Sep 13 18:43:05 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * README.EXT: English adjustment. [ruby-core:08851] and
+ [ruby-core:08852]
+
+Wed Sep 13 18:25:18 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-parse-partial): better here-doc support.
+ a patch from Marshall T. Vandegrift <llasram at gmail.com>.
+ [ruby-core:08804]
+
+Wed Sep 13 16:43:36 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_intern): prohibit interning tainted string.
+
+Wed Sep 13 01:14:21 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser#getopts): works with pre-registered
+ options. [ruby-core:08826]
+
+Sun Sep 10 20:27:13 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: updated based on date2 3.9.1.
+
+Tue Jan 10 09:18:03 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (stack_extend): fixed prototype.
+
+ * eval.c (rb_require_safe): prevent extension from loading twice.
+ fixed: [ruby-dev:29523]
+
+Sat Sep 9 23:50:38 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big_mul0): bignum multiplication without
+ normalization.
+
+ * bignum.c (rb_big_pow): use rb_big_mul0(). [ruby-dev:29547]
+
+Sat Sep 9 14:08:38 2006 Eric Hodel <drbrain@segment7.net>
+
+ * lib/test/unit/testcase.rb (Test::Unit::TestCase#run): Rescue
+ Exception in Test::Unit::TestCase#run. [ruby-core:08783]
+
+Sat Sep 9 04:55:59 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/pstore.rb: open all in binary mode, and get rid of the quirk of
+ msvcrt. fixed: [ruby-dev:29518]
+
+Sat Sep 9 04:54:42 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * Makefile.in, win32/Makefile.sub (MINIRUBY): append MINIRUBYOPT.
+
+ * mkconfig.rb, ext/extmk.rb, lib/mkmf.rb, win32/mkexports.rb: suppress
+ warnings with $VERBOSE.
+
+ * ext/extmk.rb: Proc#call does not pass the block in 1.8.
+
+ * win32/resource.rb: add more info.
+
+Fri Sep 8 10:03:59 2006 GOTOU Yuuzou <gotoyuzo@notwork.org>
+
+ * lib/webrick/cookie.rb (WEBrick::Cookie.parse_set_cookies): new
+ method to parse multiple cookies per Set-Cookie header.
+ Thanks to Aaron Patterson <aaron_patterson at speakeasy.net>.
+ [ruby-core:08802]
+
+Fri Sep 8 08:59:30 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/Makefile.sub, win32/configure.bat win32/setup.mak: program
+ name transform.
+
+Fri Sep 8 01:33:08 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.h (RSTRING_PTR): add migration macro.
+
+ * ruby.h (RARRAY_PTR): ditto.
+
+Thu Sep 7 23:27:05 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (path_check_0, fpath_check): disable path check on cygwin.
+ [ruby-talk:213074]
+
+Wed Sep 06 12:05:19 2006 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/lib/kconv.rb (Kconv::RegexpEucjp): fix regexp for euc-jp
+ [ruby-dev:29344]
+
+ * ext/nkf/lib/kconv.rb (Kconv::toeuc): remove -m0 [ruby-dev:29505]
+
+Tue Sep 5 06:47:22 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * time.c (time_to_s): variable declaration after an execution
+ statement.
+
+Tue Sep 5 05:56:51 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * numeric.c (flo_hash): improve collision. fixed: [ruby-dev:29352]
+
+Tue Sep 5 05:49:41 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (path_check_0): check if sticky bit is set on parent
+ directories for executable path. fixed: [ruby-dev:29415]
+
+Tue Sep 5 05:03:46 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (fix_plus): addition in Fixnum will never overflow
+ long. a patch from Ondrej Bilka <neleai at seznam.cz>.
+ [ruby-core:08794]
+
+ * numeric.c (fix_minus): ditto.
+
+ * bignum.c (rb_big_pow): eagerly truncate resulting bignum.
+ [ruby-core:08794]
+
+Mon Sep 4 23:15:34 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * time.c (time_to_s): make it conform to RFC2822 date format.
+ [ruby-dev:29467]
+
Mon Sep 4 21:43:57 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/dbm/extconf.rb: create makefile according to the result of check
for dbm header. fixed: [ruby-dev:29445]
+Mon Sep 4 21:42:35 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: updated based on date2 3.9.
+
+Mon Sep 4 21:14:20 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * time.c (time_strftime): include nul character. fixed: [ruby-dev:29422]
+
+Mon Sep 4 16:29:33 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/cgi.rb (CGI::out): specify -m0 -x option for nkf.
+ [ruby-dev:29284]
+
+Mon Sep 4 16:13:23 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (pipe_open): command name should not contain null bytes.
+ [ruby-dev:29421]
+
+ * process.c (proc_spawn): ditto.
+
+ * process.c (proc_spawn_n): ditto.
+
+ * process.c (rb_f_system): ditto.
+
+Sun Sep 3 15:32:44 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb: get rid of nil.to_s.
+
+Sun Sep 3 06:24:38 2006 Tanaka Akira <akr@fsij.org>
+
+ * ext/socket/socket.c (ruby_connect): sockerrlen should be socklen_t.
+
+Sun Sep 3 04:40:42 2006 Tanaka Akira <akr@fsij.org>
+
+ * ext/socket/extconf.rb: check arpa/inet.h for ntohs.
+
+ * ext/socket/socket.c: include arpa/inet.h if available.
+
+Sun Sep 3 02:34:55 2006 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/unix.rb (DRbUNIXSocket#close): don't get path if client mode.
+ [ruby-dev:29417]
+
+Sun Sep 3 01:45:17 2006 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/acl.rb (ACLEntry#initialize): examine whether '*' is
+ included before IPAddr.new. [ruby-dev:29406]
+
+Sat Sep 2 13:23:01 2006 Tanaka Akira <akr@fsij.org>
+
+ * common.mk (ia64.o): use the compiler driver to assemble ia64.s
+ to use appropriate ABI.
+
+Sat Sep 2 03:36:22 2006 Tanaka Akira <akr@fsij.org>
+
+ * common.mk, configure.in, defines.h, eval.c, gc.c, main.c,
+ numeric.c, ruby.h, ia64.s: backport IA64 HP-UX support.
+
+Fri Sep 1 13:52:57 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk/font.rb: TkFont#current_configinfo() doesn't work
+ on Tcl/Tk8.x.
+
+Thu Aug 31 12:46:55 2006 why the lucky stiff <why@ruby-lang.org>
+
+ * eval.c (ruby_init): rename top_cref to ruby_top_cref and export,
+ along with ruby_cref, for use by the sandbox. [ruby-core:08762]
+
+ * node.h: ditto.
+
Tue Aug 29 19:10:10 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
* hash.c (rb_hash_s_create): fixed memory leak, based on the patch
by Kent Sibilev <ksruby at gmail.com>. fixed: [ruby-talk:211233]
+Mon Aug 28 11:36:02 2006 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/parsers/parse_rb.rb: Fix typo. Submitted by
+ <calamitas at gmail.com>. [ruby-core:08724]
+
+Mon Aug 28 07:53:44 2006 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc/ri/ri_formatter.rb: Don't unescape HTML in HtmlFormatter.
+ Submitted by Kent Sibilev <ksruby at gmail.com>. [ruby-core:08392].
+
+Mon Aug 28 07:25:45 2006 Eric Hodel <drbrain@segment7.net>
+
+ * file.c (File#size?): Fix documentation submitted by Rick Ohnemus.
+ ruby-Bugs-5529. [ruby-core:08725]
+
+Sat Aug 26 08:07:13 2006 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb, lib/date/format.rb: updated based on date2 3.8.2.
+
+Fri Aug 25 22:32:04 2006 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/rexml/source.rb (REXML::IOSource#initialize): encoding have to
+ be set with the accessor. fixed: [ruby-list:42737]
+
Fri Aug 25 17:15:17 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* stable version 1.8.5 released.
@@ -412,7 +6127,7 @@ Tue Aug 22 18:47:51 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* lib/rdoc/parsers/parse_c.rb (RDoc::C_Parser::handle_method):
rdoc documents C module methods as instance methods. a patch in
- [ruby-core:08536].
+ [ruby-core:08536].
Sat Aug 19 14:15:02 2006 NAKAMURA Usaku <usa@ruby-lang.org>
@@ -739,7 +6454,7 @@ Thu Jul 20 15:07:14 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
Thu Jul 20 00:06:29 2006 Keiju Ishitsuka <keiju@ishitsuka.com>
* lib/irb/completion.rb: support for completion of numeric
- number. [ruby-dev: 29038]
+ number. [ruby-dev: 29038]
Wed Jul 19 23:53:05 2006 Kouhei Sutou <kou@cozmixng.org>
@@ -853,7 +6568,7 @@ Thu Jul 13 22:23:56 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
Thu Jul 13 20:32:19 2006 Kouhei Sutou <kou@cozmixng.org>
* lib/rss/parser.rb: updated documents by a patch from
- Hugh Sasse <hgs at dmu.ac.uk>. [ruby-core:8194]
+ Hugh Sasse <hgs at dmu.ac.uk>. [ruby-core:8194]
Wed Jul 12 13:54:09 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
@@ -3926,8 +9641,8 @@ Sat Sep 17 09:45:26 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
Sat Sep 17 08:35:39 2005 Kouhei Sutou <kou@cozmixng.org>
* lib/rss/maker/base.rb (RSS::Maker::ItemsBase#normalize): fixed
- strange RSS::Maker::Item#max_size behavior.
- Thanks to Kazuhiko <kazuhiko@fdiary.net>.
+ strange RSS::Maker::Item#max_size behavior.
+ Thanks to Kazuhiko <kazuhiko@fdiary.net>.
* test/rss/test_maker_1.0.rb (RSS::TestMaker10#test_items): ditto.
@@ -4685,6 +10400,7 @@ Mon Aug 1 01:17:40 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
* test/drb/ut_drb.rb: ditto.
Mon Aug 1 00:07:32 2005 Keiju Ishitsuka <keiju@ruby-lang.org>
+
* lib/irb/context.rb: fix `irb --readline` option. [ruby-list:40955]
Fri Jul 29 09:59:38 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
@@ -5169,6 +10885,7 @@ Fri Jul 1 00:18:40 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
destination object. [ruby-talk:146894]
Thu Jun 30 19:00:21 2005 Keiju Ishitsuka <keiju@ruby-lang.org>
+
* lib/irb/ruby-lex.rb (RubyLex::identify_number): alternative implements
for [ruby-dev:26410]. And support a numeric form of 0d99999.
@@ -6140,7 +11857,6 @@ Sat Apr 9 11:59:57 2005 Kouhei Sutou <kou@cozmixng.org>
- gave a name to 'x'.
- undef_method -> remove_method for avoiding a warning in ruby 1.6.
-
* lib/rss/parser.rb: @@setter -> @@setters.
* lib/rss/parser.rb
@@ -6168,34 +11884,28 @@ Sat Apr 9 11:59:57 2005 Kouhei Sutou <kou@cozmixng.org>
elements. (ex. have childlen elements, have some attributes and
a child element and so on.)
-
* lib/rss/dublincore.rb: supported multiple Dublin Core items.
* lib/rss/maker/dublincore.rb: ditto.
* lib/rss/maker/image.rb: supproted new Dublin Core API.
-
* lib/rss/maker/base.rb: added default current_element implementation.
-
* lib/rss/trackback.rb (RSS::TrackBackUtils.new_with_value_if_need):
moved to RSS::Utils.
* lib/rss/utils.rb (RSS::Utils.new_with_value_if_need):
moved from RSS::TrackBackUtils.
-
* lib/rss/maker/image.rb: fixed invalid argument of
add_need_initialize_variable bug.
* lib/rss/maker/trackback.rb: ditto.
-
* lib/rss/rss.rb (Hash#merge): added for ruby 1.6.
* lib/rss/rss.rb (RSS::BaseModel.date_writer): changed to accept nil
for date value.
-
* test/test_dublincore.rb: added tests for plural accessor and
multiple Dublin Core items.
@@ -6211,7 +11921,6 @@ Sat Apr 9 11:59:57 2005 Kouhei Sutou <kou@cozmixng.org>
* test/rss/test_maker_dc.rb (test_date): added a test for #date=
and #dc_date=.
-
* sample/rss/tdiary_plugin/rss-recent.rb:
new option: @options['rss-recent.use-image-link']:
use image as link instread of text if available.
@@ -7202,7 +12911,7 @@ Wed Feb 2 21:56:01 2005 Kouhei Sutou <kou@cozmixng.org>
Tue Feb 1 22:48:48 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
* lib/drb/drb.rb (DRb::DRbObject#respond_to?): check marshal_dump and
- _dump.
+ _dump.
Tue Feb 1 00:20:23 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
@@ -8109,7 +13818,7 @@ Wed Dec 15 18:57:01 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
Wed Dec 15 18:48:42 2004 Shugo Maeda <shugo@ruby-lang.org>
* ext/curses/curses.c (window_subwin): call NUM2INT() before
- GetWINDOW(). (backported from CVS HEAD)
+ GetWINDOW(). (backported from CVS HEAD)
Wed Dec 15 17:03:50 2004 NAKAMURA Usaku <usa@ruby-lang.org>
@@ -8732,7 +14441,7 @@ Thu Nov 18 18:41:08 2004 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
* test/ruby/test_stringchar.rb (test_bang): added.
* string.c (rb_str_upcase_bang, rb_str_capitalize_bang)
- (rb_str_swapcase_bang): missing rb_str_modify(). [ruby-dev:24915]
+ (rb_str_swapcase_bang): missing rb_str_modify(). [ruby-dev:24915]
Thu Nov 18 00:21:15 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
@@ -9348,7 +15057,7 @@ Mon Oct 18 15:58:01 2004 NAKAMURA Usaku <usa@ruby-lang.org>
Fri Oct 29 16:34:19 2004 Daiki Ueno <ueno@unixuser.org>
* misc/ruby-mode.el (ruby-parse-partial): Parse the rest of the
- line after opening heredoc identifier. [ruby-dev:24635]
+ line after opening heredoc identifier. [ruby-dev:24635]
Mon Oct 18 07:26:21 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
@@ -9544,7 +15253,7 @@ Mon Oct 4 12:53:45 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
Sun Oct 3 21:20:03 2004 Shugo Maeda <shugo@ruby-lang.org>
* lib/net/imap.rb (TEXT_REGEXP): allow 8-bit characters for the german
- version of Microsoft Exchange Server. (backported from HEAD)
+ version of Microsoft Exchange Server. (backported from HEAD)
* lib/net/imap.rb (RTEXT_REGEXP): ditto.
@@ -9869,7 +15578,6 @@ Sun Sep 12 02:41:58 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* ext/tcltklib/tcltklib.c: add TclTkIp#allow_ruby_exit? and
allow_ruby_exit=
-
* ext/tk/lib/multi-tk.rb: ditto.
* ext/tk/lib/remote-tk.rb: ditto.
@@ -10350,9 +16058,9 @@ Sun Jul 18 03:21:42 2004 Akinori MUSHA <knu@iDaemons.org>
Sun Jul 18 03:12:11 2004 Shugo Maeda <shugo@ruby-lang.org>
* lib/net/imap.rb (receive_responses): return if a LOGOUT response
- received. (backported from HEAD)
+ received. (backported from HEAD)
* lib/net/imap.rb (send_string_data): wait command continuation
- requests before sending octet data of literals. (backported from HEAD)
+ requests before sending octet data of literals. (backported from HEAD)
Sat Jul 17 23:54:59 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
@@ -10423,7 +16131,7 @@ Thu Jul 15 23:53:38 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
Thu Jul 15 22:59:48 2004 Shugo Maeda <shugo@ruby-lang.org>
* ext/readline/extconf.rb: added dir_config for curses, ncurses,
- termcap. (backported from HEAD)
+ termcap. (backported from HEAD)
Thu Jul 15 20:29:15 2004 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
@@ -10455,7 +16163,6 @@ Thu Jul 15 10:15:04 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* ext/tk/sample/tkextlib/: add samples of Iwidget and TkTable
-
Wed Jul 14 18:08:37 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
* ext/openssl/ossl_asn1.c (ossl_asn1cons_to_der): fix type of
@@ -10944,7 +16651,7 @@ Tue Jun 22 21:11:36 2004 Masaki Suketa <masaki.suketa@nifty.ne.jp>
Tue Jun 22 16:47:42 2004 Shugo Maeda <shugo@ruby-lang.org>
* lib/net/ftp.rb (MDTM_REGEXP): fix for demon's ftp server.
- Thanks, Rutger Nijlunsing.
+ Thanks, Rutger Nijlunsing.
Mon Jun 21 10:19:23 2004 NAKAMURA Usaku <usa@ruby-lang.org>
@@ -12932,7 +18639,6 @@ Tue Dec 30 12:30:30 2003 Dave Thomas <dave@pragprog.com>
class and a method have the same name, finding Xxx.abc was trying
to find 'abc' in method 'Xxx', not class 'Xxx'.
-
Tue Dec 30 08:32:32 2003 Dave Thomas <dave@pragprog.com>
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_method):
@@ -12940,7 +18646,6 @@ Tue Dec 30 08:32:32 2003 Dave Thomas <dave@pragprog.com>
def each_entry(&b) Dir.foreach(@path) {|f| yield P.new(f) } end
-
Tue Dec 30 08:32:32 2003 Dave Thomas <dave@pragprog.com>
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_method):
@@ -14846,6 +20551,7 @@ Sat Nov 8 13:49:50 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* configure.in: improvement of pthread check
Sat Nov 8 13:28:46 2003 Takaaki Tateishi <ttate@ttsky.net>
+
* ext/dl/sym.c: Add DL.win32_last_error and DL.last_error.
Thanks, Kaoru Shirai.
@@ -17683,6 +23389,7 @@ Tue Aug 12 02:48:56 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* eval.c (THREAD_ALLOC): initialize IA64 members.
Mon Aug 11 22:31:50 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+
* lib/debug.rb(debug_command): inspection command should inspect
resulting value even if it's nil. [ruby-dev:21180] by OMAE, jun
<jun66j5@ybb.ne.jp>.
@@ -17883,9 +23590,10 @@ For the changes before 1.8.0, see doc/ChangeLog-1.8.0
Local variables:
add-log-time-format: (lambda ()
(let* ((time (current-time))
+ (system-time-locale "C")
(diff (+ (cadr time) 32400))
(lo (% diff 65536))
- (hi (+ (car time) (/ diff 65536))))
+ (hi (+ (car time) (/ diff 65536))))
(format-time-string "%a %b %e %H:%M:%S %Y" (list hi lo) t)))
indent-tabs-mode: t
tab-width: 8
diff --git a/Makefile.in b/Makefile.in
index 254f1656ee..a37bcf65fb 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,4 +1,5 @@
SHELL = /bin/sh
+NULLCMD = :
#### Start of system configuration section. ####
@@ -34,6 +35,9 @@ RIDATADIR = $(DESTDIR)$(datadir)/ri/$(MAJOR).$(MINOR)/system
empty =
OUTFLAG = @OUTFLAG@$(empty)
CFLAGS = @CFLAGS@ @XCFLAGS@ @ARCH_FLAG@
+cflags = @cflags@
+optflags = @optflags@
+debugflags = @debugflags@
CPPFLAGS = -I. -I$(srcdir) @CPPFLAGS@
LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@
EXTLDFLAGS =
@@ -52,8 +56,8 @@ RUBY_SO_NAME=@RUBY_SO_NAME@
EXEEXT = @EXEEXT@
PROGRAM=$(RUBY_INSTALL_NAME)$(EXEEXT)
RUBY = $(RUBY_INSTALL_NAME)
-MINIRUBY = @MINIRUBY@
-RUNRUBY = @RUNRUBY@
+MINIRUBY = @MINIRUBY@ $(MINIRUBYOPT)
+RUNRUBY = @RUNRUBY@ $(RUNRUBYOPT) --
#### End of system configuration section. ####
@@ -85,7 +89,7 @@ ASFLAGS = @ASFLAGS@
OBJEXT = @OBJEXT@
MANTYPE = @MANTYPE@
-PREINSTALL = @PREINSTALL@
+INSTALLED_LIST= .installed.list
#### End of variables
all:
@@ -97,7 +101,7 @@ all:
miniruby$(EXEEXT):
@$(RM) $@
- $(PURIFY) $(CC) $(MAINOBJ) $(MINIOBJS) $(LIBRUBY_A) $(LIBS) $(OUTFLAG)$@ $(LDFLAGS) $(MAINLIBS)
+ $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINLIBS) $(MAINOBJ) $(MINIOBJS) $(LIBRUBY_A) $(LIBS) $(OUTFLAG)$@
$(PROGRAM):
@$(RM) $@
@@ -112,6 +116,7 @@ $(LIBRUBY_A):
@-$(RANLIB) $@ 2> /dev/null || true
$(LIBRUBY_SO):
+ @-$(PRE_LIBRUBY_UPDATE)
$(LDSHARED) $(DLDFLAGS) $(OBJS) $(DLDOBJS) $(SOLIBS) $(OUTFLAG)$@
@-$(MINIRUBY) -e 'ARGV.each{|link| File.delete link if File.exist? link; \
File.symlink "$(LIBRUBY_SO)", link}' \
@@ -153,9 +158,12 @@ $(srcdir)/configure: $(srcdir)/configure.in
cd $(srcdir) && $(AUTOCONF)
lex.c: keywords
- @-$(RM) $@
- gperf -p -j1 -i 1 -g -o -t -N rb_reserved_word -k1,3,$$ $? > $@ || \
- cp "$(srcdir)/$@" .
+ ( gperf -C -p -j1 -i 1 -g -o -t -N rb_reserved_word -k1,3,$$ $? > $@.tmp && mv $@.tmp $@ ) || \
+ if test -f $@; then \
+ touch $@ && echo $@ touched.; \
+ else \
+ cp $(srcdir)/lex.c $@ && echo $@ copied.; \
+ fi
.y.c:
$(YACC) $<
@@ -175,4 +183,20 @@ distclean-local::
@$(RM) ext/config.cache $(RBCONFIG)
ext/extinit.$(OBJEXT): ext/extinit.c $(SETUP)
- $(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -o$@ -c ext/extinit.c
+ $(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(OUTFLAG)$@ -c ext/extinit.c
+
+update-rubyspec:
+ if [ -d $(srcdir)/rubyspec ]; then \
+ cd $(srcdir)/rubyspec/mspec; \
+ git pull; \
+ cd ../spec/rubyspec; \
+ git pull; \
+ else \
+ git clone $(MSPEC_GIT_URL) $(srcdir)/rubyspec/mspec; \
+ git clone $(RUBYSPEC_GIT_URL) $(srcdir)/rubyspec/spec/rubyspec; \
+ fi
+
+test-rubyspec:
+ @if [ ! -d $(srcdir)/rubyspec ]; then echo No rubyspec here. make update-rubyspec first.; exit 1; fi
+ $(RUNRUBY) $(srcdir)/rubyspec/mspec/bin/mspec -r$(srcdir)/ext/purelib.rb $(srcdir)/rubyspec/spec/rubyspec/$(MAJOR).$(MINOR)
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000000..965ce6de5a
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,638 @@
+= NEWS
+
+This document is a list of user visible feature changes made between
+releases except for bug fixes.
+
+Note that each entry is kept so brief that no reason behind or
+reference information is supplied with. For a full list of changes
+with all sufficient information, see the ChangeLog file.
+
+* REXML
+
+ * REXML::Document.entity_expansion_limit=
+
+ New method to set the entity expansion limit. By default the limit is
+ set to 10000. See the following URL for details.
+
+ http://www.ruby-lang.org/en/news/2008/08/23/dos-vulnerability-in-rexml/
+
+== Changes since the 1.8.6 release
+
+=== Configuration changes
+
+* vendor_ruby directory
+
+ A new library directory named `vendor_ruby' is introduced in
+ addition to `site_ruby'. The idea is to separate libraries
+ installed by the package system (`vendor') from manually (`site')
+ installed libraries preventing the former from getting overwritten
+ by the latter, while preserving the user option to override vendor
+ libraries with site libraries. (`site_ruby' takes precedence over
+ `vendor_ruby')
+
+ If you are a package maintainer, make each library package configure
+ the library passing the `--vendor' option to `extconf.rb' so that
+ the library files will get installed under `vendor_ruby'.
+
+ You can change the directory locations using configure options such
+ as `--with-sitedir=DIR' and `--with-vendordir=DIR'.
+
+=== Global constants
+
+* new constants
+
+ * RUBY_COPYRIGHT
+ * RUBY_DESCRIPTION
+
+=== Library updates (outstanding ones only)
+
+* new library
+
+ * securerandom
+
+* builtin classes
+
+ * Array#flatten
+ * Array#flatten!
+
+ Takes an optional argument that determines the level of recursion
+ to flatten.
+
+ * Array#eql?
+ * Array#hash
+ * Array#==
+ * Array#<=>
+
+ Handle recursive data properly.
+
+ * Array#index
+ * Array#rindex
+
+ Take a block instead of an argument.
+
+ * Array#collect!
+ * Array#map!
+ * Array#each
+ * Array#each_index
+ * Array#reverse_each
+ * Array#reject
+ * Array#reject!
+ * Array#delete_if
+
+ Return an enumerator if no block is given.
+
+ Note that #map and #collect still return an array unlike Ruby 1.9
+ to keep compatibility.
+
+ * Array#pop
+ * Array#shift
+
+ Take an optional argument specifying the number of elements to
+ remove.
+
+ * Array#choice
+ * Array#combination
+ * Array#cycle
+ * Array#drop
+ * Array#drop_while
+ * Array#permutation
+ * Array#product
+ * Array#shuffle
+ * Array#shuffle!
+ * Array#take,
+ * Array#take_while
+
+ New methods.
+
+ * Binding#eval
+
+ New method.
+
+ * Dir#each
+ * Dir#foreach
+
+ Return an enumerator if no block is given.
+
+ * Enumerable::Enumerator
+
+ New class for various enumeration defined by the enumerator library.
+
+ * Enumerable#each_slice
+ * Enumerable#each_cons
+ * Object#to_enum
+ * Object#enum_for
+
+ New methods for various enumeration defined by the enumerator library.
+
+ * Enumerable#count
+ * Enumerable#cycle
+ * Enumerable#drop
+ * Enumerable#drop_while
+ * Enumerable#find_index
+ * Enumerable#first
+ * Enumerable#group_by
+ * Enumerable#max_by
+ * Enumerable#min_by
+ * Enumerable#minmax
+ * Enumerable#minmax_by
+ * Enumerable#none?
+ * Enumerable#one?
+ * Enumerable#take
+ * Enumerable#take_while
+
+ New methods.
+
+ * Enumerable#find
+ * Enumerable#find_all
+ * Enumerable#partition
+ * Enumerable#reject
+ * Enumerable#select
+ * Enumerable#sort_by
+
+ Return an enumerator if no block is given.
+
+ Note that #map and #collect still return an array unlike Ruby 1.9
+ to keep compatibility.
+
+ * Enumerable#inject
+
+ Accepts a binary operator instead of a block.
+
+ * Enumerable#reduce
+
+ New alias to #inject.
+
+ * Hash#eql?
+ * Hash#hash
+ * Hash#==
+
+ Handle recursive data properly.
+
+ * Hash#delete_if
+ * Hash#each
+ * Hash#each_key
+ * Hash#each_pair
+ * Hash#each_value
+ * Hash#reject!
+ * Hash#select
+ * ENV.delete_if
+ * ENV.each
+ * ENV.each_key
+ * ENV.each_pair
+ * ENV.each_value
+ * ENV.reject!
+ * ENV.select
+
+ Return an enumerator if no block is given.
+
+ * GC.stress
+ * GC.stress=
+
+ New methods.
+
+ * Integer#ord
+ * Integer#odd?
+ * Integer#even?
+ * Integer#pred
+
+ New methods.
+
+ * Integer#downto
+ * Integer#times
+ * Integer#upto
+
+ Return an enumerator if no block is given.
+
+ * IO#each
+ * IO#each_line
+ * IO#each_byte
+ * IO.foreach
+ * ARGF.each
+ * ARGF.each_line
+ * ARGF.each_byte
+
+ Return an enumerator if no block is given.
+
+ * IO#bytes
+ * IO#chars
+ * IO#each_char
+ * IO#getbyte
+ * IO#lines
+ * IO#readbyte
+ * ARGF.bytes
+ * ARGF.chars
+ * ARGF.each_char
+ * ARGF.getbyte
+ * ARGF.lines
+ * ARGF.readbyte
+
+ New methods.
+
+ * Method#name
+ * Method#owner
+ * Method#receiver
+ * UnboundMethod#name
+ * UnboundMethod#owner
+
+ New methods.
+
+ * Module#class_exec
+ * Module#module_exec
+
+ New methods.
+
+ * Numeric#step
+
+ Return an enumerator if no block is given.
+
+ * Object#instance_exec
+ * Object#tap
+
+ New methods.
+
+ * ObjectSpace.each_object
+
+ Return an enumerator if no block is given.
+
+ * Process.exec implemented.
+
+ * Range#each
+ * Range#step
+
+ Return an enumerator if no block is given.
+
+ * Regexp.union accepts an array of patterns.
+
+ * String#bytesize
+
+ New method, returning the size in bytes. (alias length and size)
+
+ * String#chars
+ * String#each_char
+ * String#partition
+ * String#rpartition
+ * String#start_with?
+ * String#end_with?
+
+ New methods. These are $KCODE aware unlike #index, #rindex and
+ #include?.
+
+ * String#each_byte
+ * String#each
+ * String#each_line
+ * String#gsub(pattern)
+
+ Return an enumerator if no block is given.
+
+ * String#upto
+
+ An optional second argument is added to specify if the last value
+ should be included.
+
+ * StopIteration
+
+ New exception class that causes Kernel#loop to stop iteration when
+ raised.
+
+ * Struct#each
+ * Struct#each_pair
+
+ Return an enumerator if no block is given.
+
+ * Symbol#to_proc
+
+ New method.
+
+ * __method__
+
+ New global function that returns the name of the current method as
+ a Symbol.
+
+* enumerator
+
+ * Enumerator is now a built-in module. The #next and #rewind
+ methods are implemented using the "generator" library. Use with
+ care and be aware of the performance loss.
+
+* ipaddr
+
+ * New methods
+ * IPAddr#<=>
+ * IPAddr#succ
+
+ IPAddr objects are now comparable and enumerable having these
+ methods. This also means that it is possible to have a Range
+ object between two IPAddr objects.
+
+ * IPAddr#to_range
+
+ A new method to create a Range object for the (network) address.
+
+ * Type coercion support
+ * IPAddr#&
+ * IPAddr#|
+ * IPAddr#==
+ * IPAddr#include?
+
+ These methods now accept a string or an integer instead of an
+ IPAddr object as the argument.
+
+* net/smtp
+
+ * Support SSL/TLS.
+
+* openssl
+
+ * New classes
+ * OpenSSL::PKey::EC
+ * OpenSSL::PKey::EC::Group
+ * OpenSSL::PKey::EC::Point
+ * OpenSSL::PKey::PKCS5
+ * OpenSSL::SSL::Session
+
+ * Documentation!
+
+ * Various new methods (see documentation).
+
+ * Remove redundant module namespace in Cipher, Digest, PKCS7, PKCS12.
+ Compatibility classes are provided which will be removed in Ruby 1.9.
+
+* shellwords
+
+ * Add methods for escaping shell-unsafe characters:
+ * Shellwords.join
+ * Shellwords.escape
+ * Array#shelljoin
+ * String#shellescape
+
+ * Add shorthand methods:
+ * Shellwords.split (alias shellwords)
+ * String#shellsplit
+
+* stringio
+
+ * StringIO#getbyte
+ * StringIO#readbyte
+
+ New methods. (aliases for compatibility with 1.9)
+
+ * StringIO#each_char
+ * StringIO#chars
+
+ New methods.
+
+ * StringIO#each
+ * StringIO#each_line
+ * StringIO#each_byte
+
+ Return an enumerator if no block is given.
+
+* tempfile
+
+ * Tempfile.open and Tempfile.new now accept a suffix for the
+ temporary file to be created. To specify a suffix, pass an array
+ of [basename, suffix] as the first argument.
+
+ Tempfile.open(['image', 'jpg']) { |tempfile| ... }
+
+* tmpdir
+
+ * New method:
+
+ * Dir.mktmpdir
+
+* uri
+
+ * added LDAPS scheme.
+ * Change for RFC3986:
+ * FTP
+ * URI('ftp://example.com/foo').path #=> 'foo'
+ * URI('ftp://example.com/%2Ffoo').path #=> '/foo'
+ * URI::FTP.build([nil, 'example.com', nil, '/foo', 'i').to_s #=> 'ftp://example.com/%2Ffoo;type=i'
+ * URI merge
+ * URI('http://a/b/c/d;p?q').merge('?y') == URI('http://a/b/c/d;p?y')
+ * URI('http://a/b/c/d;p?q').merge('/./g') == URI('http://a/g')
+ * URI('http://a/b/c/d;p?q').merge('/../g') == URI('http://a/g')
+ * URI('http://a/b/c/d;p?q').merge('../../../g') == URI('http://a/g')
+ * URI('http://a/b/c/d;p?q').merge('../../../../g') == URI('http://a/g')
+
+* rss
+
+ * 0.1.6 -> 0.2.4
+
+ * Fix image module URI
+
+ * Atom support
+
+ * ITunes module support
+
+ * Slash module support
+
+ * content:encoded with RSS 2.0 support
+
+=== Interpreter Implementation
+
+* passing a block to a Proc [experimental]
+
+ This implementation in current shape is known to be buggy/broken,
+ especially with nested block invocation. Take this as an
+ experimental feature.
+
+* stack trace
+
+ On non-SystemStackError exception, full stack trace is shown.
+
+=== Compatibility issues (excluding feature bug fixes)
+
+* String#slice! had some unintentional bugs and they have been fixed
+ because either they disagreed with documentation or their respective
+ behavior of #slice. Unfortunately, this causes some
+ incompatibilities in the following (somewhat rare) cases.
+
+ * #slice! no longer expands the array when an out-of-boundary value
+ is given.
+
+ # Ruby 1.8.6
+ a = [1,2]
+ a.slice!(4,0) #=> nil
+ a #=> [1,2,nil,nil]
+
+ # Ruby 1.8.7
+ a = [1,2]
+ a.slice!(4,0) #=> nil
+ a #=> [1,2]
+
+ * #slice! no longer raises an exception but returns nil when a
+ negative length or out-of-boundary negative position is given.
+
+ # Ruby 1.8.6
+ a = [1,2]
+ a.slice!(1,-1) #=> (raises IndexError)
+ a.slice!(-5,1) #=> (raises IndexError)
+
+ # Ruby 1.8.7
+ a = [1,2]
+ a.slice!(1,-1) #=> nil
+ a.slice!(-5,1) #=> nil
+
+* String#to_i, String#hex and String#oct no longer accept a sequence
+ of underscores (`__') as part of a number.
+
+ # Ruby 1.8.6
+ '1__0'.to_i #=> 10
+ '1__0'.to_i(2) #=> 2 # 0b10
+ '1__0'.oct #=> 8 # 010
+ '1__0'.hex #=> 16 # 0x10
+
+ # Ruby 1.8.7
+ '1__0'.to_i #=> 1
+ '1__0'.to_i(2) #=> 1
+ '1__0'.oct #=> 1
+ '1__0'.hex #=> 1
+
+ The old behavior was inconsistent with Ruby syntax and considered as
+ a bug.
+
+* date
+
+ * Date.parse
+
+ '##.##.##' (where each '#' is a digit) is now taken as 'YY.MM.DD'
+ instead of 'MM.DD.YY'. While the change may confuse you, you can
+ always use Date.strptime() when you know what you are dealing
+ with.
+
+* stringio
+
+ * StringIO#each_byte
+
+ The return value changed from nil to self. This is what the
+ document says and the same as each_line() does.
+
+* tempfile
+
+ * The file name format has changed. No dots are included by default
+ in temporary file names any more. See above for how to specify a
+ suffix.
+
+* uri
+
+ * See above for details.
+
+== Changes since the 1.8.5 release
+
+=== New platforms/build tools support
+
+* IA64 HP-UX
+
+* Visual C++ 8 SP1
+
+* autoconf 2.6x
+
+=== Global constants
+
+* RUBY_PATCHLEVEL
+
+ New constant since 1.8.5-p1.
+
+=== Library updates (outstanding ones only)
+
+* builtin classes
+
+ * New method: Kernel#instance_variable_defined?
+
+ * New method: Module#class_variable_defined?
+
+ * New feature: Dir::glob() can now take an array of glob patterns.
+
+* date
+
+ * Updated based on date2 4.0.3.
+
+* digest
+
+ * New internal APIs for C and Ruby.
+
+ * Support for autoloading.
+
+ require 'digest'
+
+ # autoloads digest/md5
+ md = Digest::MD5.digest("string")
+
+ * New digest class methods: file
+
+ * New digest instance methods: clone, reset, new, inspect,
+ digest_length (alias size or length), block_length()
+
+ * New library: digest/bubblebabble
+
+ * New function: Digest(name)
+
+* fileutils
+
+ * New option for FileUtils.cp_r(): :remove_destination
+
+* nkf
+
+ * Updated based on nkf as of 2007-01-28.
+
+* thread
+
+ * Replaced with much faster mutex implementation in C. The former
+ implementation, which is slow but considered to be stable, is
+ available with a configure option `--disable-fastthread'.
+
+* tk
+
+ * Updated Tile extension support based on Tile 0.7.8.
+
+ * Support --without-X11 configure option for non-X11 versions of
+ Tcl/Tk (e.g. Tcl/Tk Aqua).
+
+ * New sample script: irbtkw.rbw -- IRB on Ruby/Tk. It has no trouble
+ about STDIN blocking on Windows.
+
+* webrick
+
+ * New method: WEBrick::Cookie.parse_set_cookies()
+
+=== Compatibility issues (excluding feature bug fixes)
+
+* builtin classes
+
+ * String#intern now raises SecurityError when $SAFE level is greater
+ than zero.
+
+* date
+
+ * Time#to_date and Time#to_datetime are added as private methods.
+ They cause name conflict error in ActiveSupport 1.4.1 and prior,
+ which comes with Rails 1.2.2 and prior. Updating ActiveSupport
+ and/or Rails to the latest versions fixes the problem.
+
+* digest
+
+ * The constructor does no longer take an initial string to feed.
+ The following examples show how to migrate:
+
+ # Before
+ md = Digest::MD5.new("string")
+ # After (works with any version)
+ md = Digest::MD5.new.update("string")
+
+ # Before
+ hd = Digest::MD5.new("string").hexdigest
+ # After (works with any version)
+ hd = Digest::MD5.hexdigest("string")
+
+* fileutils
+
+ * A minor implementation change breaks Rake <=0.7.1.
+ Updating Rake to 0.7.2 or higher fixes the problem.
+
+* tk
+
+ * Tk::X_Scrollable (Y_Scrollable) is renamed to Tk::XScrollable
+ (YScrollable). Tk::X_Scrollable (Y_Scrollable) is still available,
+ but it is an alias name.
diff --git a/README b/README
index cf836415ad..1b79781367 100644
--- a/README
+++ b/README
@@ -29,7 +29,7 @@ The Ruby distribution files can be found in the following FTP site:
The latest source code of this version series can be checked out
through SVN with the following command:
- $ svn co http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8_6/
+ $ svn co http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8/
The trunk of the Ruby source tree can be checked out with the
following command:
@@ -70,6 +70,10 @@ This is what you need to do to compile and install Ruby:
2. Run ./configure, which will generate config.h and Makefile.
+ Some C compiler flags may be added by default depending on your
+ environment. Specify optflags=.. and warnflags=.. as necessary
+ to override them.
+
3. Edit defines.h if you need. Usually this step will not be needed.
4. Remove comment mark(#) before the module names from ext/Setup (or
diff --git a/README.EXT b/README.EXT
index e5d39911ca..637b19d25b 100644
--- a/README.EXT
+++ b/README.EXT
@@ -8,8 +8,8 @@ In C, variables have types and data do not have types. In contrast,
Ruby variables do not have a static type, and data themselves have
types, so data will need to be converted between the languages.
-Data in Ruby are represented by C type `VALUE'. Each VALUE data has
-its data-type.
+Data in Ruby are represented by the C type `VALUE'. Each VALUE data
+has its data-type.
To retrieve C data from a VALUE, you need to:
@@ -91,26 +91,26 @@ The data for type T_NIL, T_FALSE, T_TRUE are nil, true, false
respectively. They are singletons for the data type.
The T_FIXNUM data is a 31bit length fixed integer (63bit length on
-some machines), which can be convert to a C integer by using the
+some machines), which can be converted to a C integer by using the
FIX2INT() macro. There is also NUM2INT() which converts any Ruby
numbers into C integers. The NUM2INT() macro includes a type check, so
an exception will be raised if the conversion failed. NUM2DBL() can
-be used to retrieve the double float value in same way.
+be used to retrieve the double float value in the same way.
-To get char* from a VALUE, version 1.7 recommend to use new macros
-StringValue() and StringValuePtr(). StringValue(var) replaces var's
-value to the result of "var.to_str()". StringValuePtr(var) does same
-replacement and returns char* representation of var. These macros
-will skip the replacement if var is a String. Notice that the macros
-requires to take only lvalue as their argument, to change the value
-of var in the replacement.
+In version 1.7 or later it is recommended that you use the new macros
+StringValue() and StringValuePtr() to get a char* from a VALUE.
+StringValue(var) replaces var's value with the result of "var.to_str()".
+StringValuePtr(var) does same replacement and returns char*
+representation of var. These macros will skip the replacement if var is
+a String. Notice that the macros take only the lvalue as their
+argument, to change the value of var in place.
-In version 1.6 or earlier, STR2CSTR() was used to do same thing
-but now it is obsoleted in version 1.7 because of STR2CSTR() has
-a risk of dangling pointer problem in to_str() impliclit conversion.
+In version 1.6 or earlier, STR2CSTR() was used to do the same thing
+but now it is deprecated in version 1.7, because STR2CSTR() has a risk
+of a dangling pointer problem in the to_str() impliclit conversion.
Other data types have corresponding C structures, e.g. struct RArray
-for T_ARRAY etc. The VALUE of the type which has corresponding structure
+for T_ARRAY etc. The VALUE of the type which has the corresponding structure
can be cast to retrieve the pointer to the struct. The casting macro
will be of the form RXXXX for each data type; for instance, RARRAY(obj).
See "ruby.h".
@@ -205,7 +205,7 @@ interpreter. Some (not all) of the useful functions are listed below:
rb_ary_unshift(VALUE ary, VALUE val)
Array operations. The first argument to each functions must be an
- array. They may dump core if other types given.
+ array. They may dump core if other types are given.
2. Extending Ruby with C
@@ -244,7 +244,7 @@ To define methods or singleton methods, use these functions:
VALUE (*func)(), int argc)
The `argc' represents the number of the arguments to the C function,
-which must be less than 17. But I believe you don't need that much. :-)
+which must be less than 17. But I doubt you'll need that many.
If `argc' is negative, it specifies the calling sequence, not number of
the arguments.
@@ -272,7 +272,7 @@ private methods:
The other is to define module functions, which are private AND singleton
methods of the module. For example, sqrt is the module function
-defined in Math module. It can be call in the form like:
+defined in Math module. It can be called in the following way:
Math.sqrt(4)
@@ -291,7 +291,7 @@ in the Kernel module, can be defined using:
void rb_define_global_function(const char *name, VALUE (*func)(), int argc)
-To define alias to the method,
+To define an alias for the method,
void rb_define_alias(VALUE module, const char* new, const char* old);
@@ -321,7 +321,7 @@ There are several ways to invoke Ruby's features from C code.
2.2.1 Evaluate Ruby Programs in a String
The easiest way to use Ruby's functionality from a C program is to
-evaluate the string as Ruby program. This function will do the job.
+evaluate the string as Ruby program. This function will do the job:
VALUE rb_eval_string(const char *str)
@@ -434,7 +434,7 @@ The prototypes of the getter and setter functions are as follows:
(*getter)(ID id, void *data, struct global_entry* entry);
(*setter)(VALUE val, ID id, void *data, struct global_entry* entry);
-3.3 Encapsulate C data into Ruby object
+3.3 Encapsulate C data into a Ruby object
To wrap and objectify a C pointer as a Ruby object (so called
DATA), use Data_Wrap_Struct().
@@ -619,7 +619,7 @@ are not exported to the Ruby world. You need to protect them by
If the file named extconf.rb exists, it will be executed to generate
Makefile.
-extconf.rb is the file for check compilation conditions etc. You
+extconf.rb is the file for checking compilation conditions etc. You
need to put
require 'mkmf'
@@ -639,12 +639,12 @@ The value of the variables below will affect the Makefile.
$LDFLAGS: included in LDFLAGS make variable (such as -L)
$objs: list of object file names
-In normal, object files list is automatically generated by searching
-source files, but you need directs them explicitly if any sources will
+Normally, the object files list is automatically generated by searching
+source files, but you must define them explicitly if any sources will
be generated while building.
If a compilation condition is not fulfilled, you should not call
-``create_makefile''. The Makefile will not generated, compilation will
+``create_makefile''. The Makefile will not be generated, compilation will
not be done.
(5) prepare depend (optional)
@@ -654,7 +654,7 @@ check dependencies. You can make this file by invoking
% gcc -MM *.c > depend
-It's no harm. Prepare it.
+It's harmless. Prepare it.
(6) generate Makefile
@@ -662,6 +662,11 @@ Try generating the Makefile by:
ruby extconf.rb
+If the library should be installed under vendor_ruby directory
+instead of site_ruby directory, use --vendor option as follows.
+
+ ruby extconf.rb --vendor
+
You don't need this step if you put the extension library under the ext
directory of the ruby source tree. In that case, compilation of the
interpreter will do this step for you.
@@ -673,12 +678,12 @@ Type
make
to compile your extension. You don't need this step either if you have
-put extension library under the ext directory of the ruby source tree.
+put the extension library under the ext directory of the ruby source tree.
(8) debug
You may need to rb_debug the extension. Extensions can be linked
-statically by the adding directory name in the ext/Setup file so that
+statically by adding the directory name in the ext/Setup file so that
you can inspect the extension with the debugger.
(9) done, now you have the extension library
@@ -843,15 +848,15 @@ it can't be seen from Ruby programs.
void rb_define_readonly_variable(const char *name, VALUE *var)
Defines a read-only global variable. Works just like
-rb_define_variable(), except defined variable is read-only.
+rb_define_variable(), except the defined variable is read-only.
void rb_define_virtual_variable(const char *name,
VALUE (*getter)(), VALUE (*setter)())
Defines a virtual variable, whose behavior is defined by a pair of C
functions. The getter function is called when the variable is
-referred. The setter function is called when the value is set to the
-variable. The prototype for getter/setter functions are:
+referenced. The setter function is called when the variable is set to a
+value. The prototype for getter/setter functions are:
VALUE getter(ID id)
void setter(VALUE val, ID id)
@@ -1011,7 +1016,7 @@ Terminates the interpreter immediately. This function should be
called under the situation caused by the bug in the interpreter. No
exception handling nor ensure execution will be done.
-** Initialize and Starts the Interpreter
+** Initialize and Start the Interpreter
The embedding API functions are below (not needed for extension libraries):
@@ -1031,6 +1036,32 @@ Starts execution of the interpreter.
Specifies the name of the script ($0).
+** Hooks for the Interpreter Events
+
+ void rb_add_event_hook(rb_event_hook_func_t func, rb_event_t events)
+
+Adds a hook function for the specified interpreter events.
+events should be Or'ed value of:
+
+ RUBY_EVENT_LINE
+ RUBY_EVENT_CLASS
+ RUBY_EVENT_END
+ RUBY_EVENT_CALL
+ RUBY_EVENT_RETURN
+ RUBY_EVENT_C_CALL
+ RUBY_EVENT_C_RETURN
+ RUBY_EVENT_RAISE
+ RUBY_EVENT_ALL
+
+The definition of rb_event_hook_func_t is below:
+
+ typedef void (*rb_event_hook_func_t)(rb_event_t event, NODE *node,
+ VALUE self, ID id, VALUE klass)
+
+ int rb_remove_event_hook(rb_event_hook_func_t func)
+
+Removes the specified hook function.
+
Appendix C. Functions Available in extconf.rb
These functions are available in extconf.rb:
@@ -1122,7 +1153,7 @@ Returns an array of the added directories ([include_dir, lib_dir]).
pkg_config(pkg)
-Obtains the information of pkg by pkg-config command. The actual
+Obtains the information for pkg by pkg-config command. The actual
command name can be overriden by --with-pkg-config command line
option.
diff --git a/README.EXT.ja b/README.EXT.ja
index 30c4d520ba..73425c2cdb 100644
--- a/README.EXT.ja
+++ b/README.EXT.ja
@@ -765,6 +765,12 @@ Makefileºݤ뤿ˤ
ȤƤ
+site_ruby ǥ쥯ȥǤʤ
+vendor_ruby ǥ쥯ȥ˥󥹥ȡ뤹ˤ
+ʲΤ褦 --vendor ץäƤ
+
+ ruby extconf.rb --vendor
+
ǥ쥯ȥextʲѰդˤRubyΤmakeλ
ưŪMakefileޤΤǡΥƥåפפǤ
diff --git a/README.ja b/README.ja
index df8cfc03f4..71ce4ee12c 100644
--- a/README.ja
+++ b/README.ja
@@ -36,7 +36,7 @@ RubyϥƥȽطǽϤʤɤͥ졤PerlƱ餤
ܥ֥RubyκǿΥɤϼΥޥɤǼǤޤ
- $ svn co http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8_6/
+ $ svn co http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8/
ȯüΥɤϼΥޥɤǼǤޤ
@@ -92,6 +92,10 @@ Rubyĥ⥸塼ˤĤä礦ruby-ext᡼󥰥ꥹȤ
2. configure¹ԤMakefileʤɤ
+ ĶˤäƤϥǥեȤCѥѥץդ
+ ޤconfigureץ optflags=.. warnflags=..
+ Ǿ񤭤Ǥޤ
+
3. (ɬפʤ)defines.hԽ
¿ʬɬ̵Ȼפޤ
diff --git a/array.c b/array.c
index a67e9233d1..7e8c12b683 100644
--- a/array.c
+++ b/array.c
@@ -2,8 +2,8 @@
array.c -
- $Author: akr $
- $Date: 2006/06/24 14:53:36 $
+ $Author$
+ $Date$
created at: Fri Aug 6 09:46:12 JST 1993
Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -20,6 +20,7 @@ VALUE rb_cArray;
static ID id_cmp;
#define ARY_DEFAULT_SIZE 16
+#define ARY_MAX_SIZE (LONG_MAX / sizeof(VALUE))
void
rb_mem_clear(mem, size)
@@ -120,7 +121,7 @@ ary_new(klass, len)
if (len < 0) {
rb_raise(rb_eArgError, "negative array size (or size too big)");
}
- if (len > 0 && len * sizeof(VALUE) <= len) {
+ if (len > ARY_MAX_SIZE) {
rb_raise(rb_eArgError, "array size too big");
}
if (len == 0) len++;
@@ -195,6 +196,27 @@ rb_ary_new4(n, elts)
return ary;
}
+static VALUE
+ary_make_shared(ary)
+ VALUE ary;
+{
+ if (!FL_TEST(ary, ELTS_SHARED)) {
+ NEWOBJ(shared, struct RArray);
+ OBJSETUP(shared, rb_cArray, 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);
+ OBJ_FREEZE(shared);
+ return (VALUE)shared;
+ }
+ else {
+ return RARRAY(ary)->aux.shared;
+ }
+}
+
VALUE
rb_assoc_new(car, cdr)
VALUE car, cdr;
@@ -293,7 +315,7 @@ rb_ary_initialize(argc, argv, ary)
if (len < 0) {
rb_raise(rb_eArgError, "negative array size");
}
- if (len > 0 && len * (long)sizeof(VALUE) <= len) {
+ if (len > ARY_MAX_SIZE) {
rb_raise(rb_eArgError, "array size too big");
}
if (len > RARRAY(ary)->aux.capa) {
@@ -358,6 +380,9 @@ rb_ary_store(ary, idx, val)
idx - RARRAY(ary)->len);
}
}
+ else if (idx >= ARY_MAX_SIZE) {
+ rb_raise(rb_eIndexError, "index %ld too big", idx);
+ }
rb_ary_modify(ary);
if (idx >= RARRAY(ary)->aux.capa) {
@@ -366,10 +391,10 @@ rb_ary_store(ary, idx, val)
if (new_capa < ARY_DEFAULT_SIZE) {
new_capa = ARY_DEFAULT_SIZE;
}
- new_capa += idx;
- if (new_capa * (long)sizeof(VALUE) <= new_capa) {
- rb_raise(rb_eArgError, "index too big");
+ if (new_capa >= ARY_MAX_SIZE - idx) {
+ new_capa = (ARY_MAX_SIZE - idx) / 2;
}
+ new_capa += idx;
REALLOC_N(RARRAY(ary)->ptr, VALUE, new_capa);
RARRAY(ary)->aux.capa = new_capa;
}
@@ -384,6 +409,50 @@ rb_ary_store(ary, idx, val)
RARRAY(ary)->ptr[idx] = val;
}
+static VALUE
+ary_shared_array(klass, ary)
+ VALUE klass;
+ VALUE ary;
+{
+ VALUE val = ary_alloc(klass);
+
+ 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;
+}
+
+static VALUE
+ary_shared_first(argc, argv, ary, last)
+ int argc;
+ VALUE *argv;
+ VALUE ary;
+ int last;
+{
+ VALUE nv, result;
+ long n;
+ long offset = 0;
+
+ rb_scan_args(argc, argv, "1", &nv);
+ n = NUM2LONG(nv);
+ if (n > RARRAY(ary)->len) {
+ n = RARRAY(ary)->len;
+ }
+ else if (n < 0) {
+ rb_raise(rb_eArgError, "negative array size");
+ }
+ if (last) {
+ offset = RARRAY(ary)->len - n;
+ }
+ result = ary_shared_array(rb_cArray, ary);
+ RARRAY(result)->ptr += offset;
+ RARRAY(result)->len = n;
+
+ return result;
+}
+
/*
* call-seq:
* array << obj -> array
@@ -431,18 +500,6 @@ rb_ary_push_m(argc, argv, ary)
return ary;
}
-/*
- * call-seq:
- * array.pop -> obj or nil
- *
- * Removes the last element from <i>self</i> and returns it, or
- * <code>nil</code> if the array is empty.
- *
- * a = [ "a", "m", "z" ]
- * a.pop #=> "z"
- * a #=> ["a", "m"]
- */
-
VALUE
rb_ary_pop(ary)
VALUE ary;
@@ -450,7 +507,7 @@ rb_ary_pop(ary)
rb_ary_modify_check(ary);
if (RARRAY(ary)->len == 0) return Qnil;
if (!FL_TEST(ary, ELTS_SHARED) &&
- RARRAY(ary)->len * 2 < RARRAY(ary)->aux.capa &&
+ RARRAY(ary)->len * 3 < RARRAY(ary)->aux.capa &&
RARRAY(ary)->aux.capa > ARY_DEFAULT_SIZE) {
RARRAY(ary)->aux.capa = RARRAY(ary)->len * 2;
REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->aux.capa);
@@ -458,54 +515,112 @@ rb_ary_pop(ary)
return RARRAY(ary)->ptr[--RARRAY(ary)->len];
}
+/*
+ * call-seq:
+ * array.pop -> obj or nil
+ * array.pop(n) -> array
+ *
+ * Removes the last element from <i>self</i> and returns it, or
+ * <code>nil</code> if the array is empty.
+ *
+ * If a number _n_ is given, returns an array of the last n elements
+ * (or less) just like <code>array.slice!(-n, n)</code> does.
+ *
+ * a = [ "a", "b", "c", "d" ]
+ * a.pop #=> "d"
+ * a.pop(2) #=> ["b", "c"]
+ * a #=> ["a"]
+ */
+
static VALUE
-ary_make_shared(ary)
+rb_ary_pop_m(argc, argv, ary)
+ int argc;
+ VALUE *argv;
VALUE ary;
{
- if (!FL_TEST(ary, ELTS_SHARED)) {
- NEWOBJ(shared, struct RArray);
- OBJSETUP(shared, rb_cArray, T_ARRAY);
+ VALUE result;
- 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);
- OBJ_FREEZE(shared);
- return (VALUE)shared;
+ if (argc == 0) {
+ return rb_ary_pop(ary);
}
- else {
- return RARRAY(ary)->aux.shared;
+
+ rb_ary_modify_check(ary);
+ result = ary_shared_first(argc, argv, ary, Qtrue);
+ RARRAY(ary)->len -= RARRAY(result)->len;
+ return result;
+}
+
+VALUE
+rb_ary_shift(ary)
+ VALUE ary;
+{
+ VALUE top;
+
+ rb_ary_modify_check(ary);
+ if (RARRAY(ary)->len == 0) return Qnil;
+ top = RARRAY(ary)->ptr[0];
+ if (!FL_TEST(ary, ELTS_SHARED)) {
+ if (RARRAY(ary)->len < ARY_DEFAULT_SIZE) {
+ MEMMOVE(RARRAY(ary)->ptr, RARRAY(ary)->ptr+1, VALUE, RARRAY(ary)->len-1);
+ RARRAY(ary)->len--;
+ return top;
+ }
+ RARRAY(ary)->ptr[0] = Qnil;
+ ary_make_shared(ary);
}
+ RARRAY(ary)->ptr++; /* shift ptr */
+ RARRAY(ary)->len--;
+
+ return top;
}
/*
* call-seq:
- * array.shift -> obj or nil
+ * array.shift -> obj or nil
+ * array.shift(n) -> array
*
* Returns the first element of <i>self</i> and removes it (shifting all
* other elements down by one). Returns <code>nil</code> if the array
* is empty.
+ *
+ * If a number _n_ is given, returns an array of the first n elements
+ * (or less) just like <code>array.slice!(0, n)</code> does.
*
* args = [ "-m", "-q", "filename" ]
- * args.shift #=> "-m"
- * args #=> ["-q", "filename"]
+ * args.shift #=> "-m"
+ * args #=> ["-q", "filename"]
+ *
+ * args = [ "-m", "-q", "filename" ]
+ * args.shift(2) #=> ["-m", "-q"]
+ * args #=> ["filename"]
*/
-VALUE
-rb_ary_shift(ary)
+static VALUE
+rb_ary_shift_m(argc, argv, ary)
+ int argc;
+ VALUE *argv;
VALUE ary;
{
- VALUE top;
+ VALUE result;
+ long n;
+
+ if (argc == 0) {
+ return rb_ary_shift(ary);
+ }
rb_ary_modify_check(ary);
- if (RARRAY(ary)->len == 0) return Qnil;
- top = RARRAY(ary)->ptr[0];
- ary_make_shared(ary);
- RARRAY(ary)->ptr++; /* shift ptr */
- RARRAY(ary)->len--;
+ result = ary_shared_first(argc, argv, ary, Qfalse);
+ n = RARRAY(result)->len;
+ if (FL_TEST(ary, ELTS_SHARED)) {
+ RARRAY(ary)->ptr += n;
+ RARRAY(ary)->len -= n;
+ }
+ else {
+ MEMMOVE(RARRAY(ary)->ptr, RARRAY(ary)->ptr+n, VALUE, RARRAY(ary)->len-n);
+ RARRAY(ary)->len -= n;
+ }
- return top;
+ return result;
}
VALUE
@@ -598,7 +713,7 @@ rb_ary_subseq(ary, beg, len)
if (beg > RARRAY(ary)->len) return Qnil;
if (beg < 0 || len < 0) return Qnil;
- if (beg + len > RARRAY(ary)->len) {
+ if (RARRAY(ary)->len < len || RARRAY(ary)->len < beg + len) {
len = RARRAY(ary)->len - beg;
if (len < 0)
len = 0;
@@ -740,17 +855,7 @@ rb_ary_first(argc, argv, ary)
return RARRAY(ary)->ptr[0];
}
else {
- VALUE nv, result;
- long n, i;
-
- rb_scan_args(argc, argv, "01", &nv);
- n = NUM2LONG(nv);
- if (n > RARRAY(ary)->len) n = RARRAY(ary)->len;
- result = rb_ary_new2(n);
- for (i=0; i<n; i++) {
- rb_ary_push(result, RARRAY(ary)->ptr[i]);
- }
- return result;
+ return ary_shared_first(argc, argv, ary, Qfalse);
}
}
@@ -776,17 +881,7 @@ rb_ary_last(argc, argv, ary)
return RARRAY(ary)->ptr[RARRAY(ary)->len-1];
}
else {
- VALUE nv, result;
- long n, i;
-
- rb_scan_args(argc, argv, "01", &nv);
- n = NUM2LONG(nv);
- if (n > RARRAY(ary)->len) n = RARRAY(ary)->len;
- result = rb_ary_new2(n);
- for (i=RARRAY(ary)->len-n; n--; i++) {
- rb_ary_push(result, RARRAY(ary)->ptr[i]);
- }
- return result;
+ return ary_shared_first(argc, argv, ary, Qtrue);
}
}
@@ -842,24 +937,41 @@ rb_ary_fetch(argc, argv, ary)
/*
* call-seq:
- * array.index(obj) -> int or nil
+ * array.index(obj) -> int or nil
+ * array.index {|item| block} -> int or nil
*
- * Returns the index of the first object in <i>self</i> such that is
- * <code>==</code> to <i>obj</i>. Returns <code>nil</code> if
- * no match is found.
+ * Returns the index of the first object in <i>self</i> such that is
+ * <code>==</code> to <i>obj</i>. If a block is given instead of an
+ * argument, returns first object for which <em>block</em> is true.
+ * Returns <code>nil</code> if no match is found.
*
* a = [ "a", "b", "c" ]
- * a.index("b") #=> 1
- * a.index("z") #=> nil
+ * a.index("b") #=> 1
+ * a.index("z") #=> nil
+ * a.index{|x|x=="b"} #=> 1
+ *
+ * This is an alias of <code>#find_index</code>.
*/
static VALUE
-rb_ary_index(ary, val)
+rb_ary_index(argc, argv, ary)
+ int argc;
+ VALUE *argv;
VALUE ary;
- VALUE val;
{
+ VALUE val;
long i;
+ if (argc == 0) {
+ RETURN_ENUMERATOR(ary, 0, 0);
+ for (i=0; i<RARRAY(ary)->len; i++) {
+ if (RTEST(rb_yield(RARRAY(ary)->ptr[i]))) {
+ return LONG2NUM(i);
+ }
+ }
+ return Qnil;
+ }
+ rb_scan_args(argc, argv, "01", &val);
for (i=0; i<RARRAY(ary)->len; i++) {
if (rb_equal(RARRAY(ary)->ptr[i], val))
return LONG2NUM(i);
@@ -871,29 +983,44 @@ rb_ary_index(ary, val)
* call-seq:
* array.rindex(obj) -> int or nil
*
- * Returns the index of the last object in <i>array</i>
- * <code>==</code> to <i>obj</i>. Returns <code>nil</code> if
- * no match is found.
+ * Returns the index of the last object in <i>array</i>
+ * <code>==</code> to <i>obj</i>. If a block is given instead of an
+ * argument, returns first object for which <em>block</em> is
+ * true. Returns <code>nil</code> if no match is found.
*
* a = [ "a", "b", "b", "b", "c" ]
- * a.rindex("b") #=> 3
- * a.rindex("z") #=> nil
+ * a.rindex("b") #=> 3
+ * a.rindex("z") #=> nil
+ * a.rindex{|x|x=="b"} #=> 3
*/
static VALUE
-rb_ary_rindex(ary, val)
+rb_ary_rindex(argc, argv, ary)
+ int argc;
+ VALUE *argv;
VALUE ary;
- VALUE val;
{
+ VALUE val;
long i = RARRAY(ary)->len;
+ if (argc == 0) {
+ RETURN_ENUMERATOR(ary, 0, 0);
+ while (i--) {
+ if (RTEST(rb_yield(RARRAY(ary)->ptr[i])))
+ return LONG2NUM(i);
+ if (i > RARRAY(ary)->len) {
+ i = RARRAY(ary)->len;
+ }
+ }
+ return Qnil;
+ }
+ rb_scan_args(argc, argv, "01", &val);
while (i--) {
+ if (rb_equal(RARRAY(ary)->ptr[i], val))
+ return LONG2NUM(i);
if (i > RARRAY(ary)->len) {
i = RARRAY(ary)->len;
- continue;
}
- if (rb_equal(RARRAY(ary)->ptr[i], val))
- return LONG2NUM(i);
}
return Qnil;
}
@@ -953,7 +1080,7 @@ rb_ary_splice(ary, beg, len, rpl)
rb_raise(rb_eIndexError, "index %ld out of array", beg);
}
}
- if (beg + len > RARRAY(ary)->len) {
+ if (RARRAY(ary)->len < len || RARRAY(ary)->len < beg + len) {
len = RARRAY(ary)->len - beg;
}
@@ -967,6 +1094,9 @@ rb_ary_splice(ary, beg, len, rpl)
rb_ary_modify(ary);
if (beg >= RARRAY(ary)->len) {
+ if (beg > ARY_MAX_SIZE - rlen) {
+ rb_raise(rb_eIndexError, "index %ld too big", beg);
+ }
len = beg + rlen;
if (len >= RARRAY(ary)->aux.capa) {
REALLOC_N(RARRAY(ary)->ptr, VALUE, len);
@@ -1126,6 +1256,7 @@ rb_ary_each(ary)
{
long i;
+ RETURN_ENUMERATOR(ary, 0, 0);
for (i=0; i<RARRAY(ary)->len; i++) {
rb_yield(RARRAY(ary)->ptr[i]);
}
@@ -1153,6 +1284,7 @@ rb_ary_each_index(ary)
{
long i;
+ RETURN_ENUMERATOR(ary, 0, 0);
for (i=0; i<RARRAY(ary)->len; i++) {
rb_yield(LONG2NUM(i));
}
@@ -1178,8 +1310,10 @@ static VALUE
rb_ary_reverse_each(ary)
VALUE ary;
{
- long len = RARRAY(ary)->len;
+ long len;
+ RETURN_ENUMERATOR(ary, 0, 0);
+ len = RARRAY(ary)->len;
while (len--) {
rb_yield(RARRAY(ary)->ptr[len]);
if (RARRAY(ary)->len < len) {
@@ -1726,6 +1860,7 @@ rb_ary_collect_bang(ary)
{
long i;
+ RETURN_ENUMERATOR(ary, 0, 0);
rb_ary_modify(ary);
for (i = 0; i < RARRAY(ary)->len; i++) {
rb_ary_store(ary, i, rb_yield(RARRAY(ary)->ptr[i]));
@@ -1810,6 +1945,7 @@ rb_ary_select(ary)
VALUE result;
long i;
+ RETURN_ENUMERATOR(ary, 0, 0);
result = rb_ary_new2(RARRAY(ary)->len);
for (i = 0; i < RARRAY(ary)->len; i++) {
if (RTEST(rb_yield(RARRAY(ary)->ptr[i]))) {
@@ -1949,22 +2085,42 @@ rb_ary_slice_bang(argc, argv, ary)
VALUE ary;
{
VALUE arg1, arg2;
- long pos, len;
+ long pos, len, orig_len;
+ rb_ary_modify_check(ary);
if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
pos = NUM2LONG(arg1);
len = NUM2LONG(arg2);
delete_pos_len:
+ if (len < 0) return Qnil;
+ orig_len = RARRAY_LEN(ary);
if (pos < 0) {
- pos = RARRAY(ary)->len + pos;
+ pos += orig_len;
+ if (pos < 0) return Qnil;
+ }
+ else if (orig_len < pos) return Qnil;
+ if (orig_len < pos + len) {
+ len = orig_len - pos;
}
- arg2 = rb_ary_subseq(ary, pos, len);
- rb_ary_splice(ary, pos, len, Qnil); /* Qnil/rb_ary_new2(0) */
+ if (len == 0) return rb_ary_new2(0);
+ arg2 = rb_ary_new4(len, RARRAY_PTR(ary)+pos);
+ RBASIC(arg2)->klass = rb_obj_class(ary);
+ rb_ary_splice(ary, pos, len, Qnil); /* Qundef in 1.9 */
return arg2;
}
- if (!FIXNUM_P(arg1) && rb_range_beg_len(arg1, &pos, &len, RARRAY(ary)->len, 1)) {
- goto delete_pos_len;
+ if (!FIXNUM_P(arg1)) {
+ switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
+ case Qtrue:
+ /* valid range */
+ goto delete_pos_len;
+ case Qnil:
+ /* invalid range */
+ return Qnil;
+ default:
+ /* not a range */
+ break;
+ }
}
return rb_ary_delete_at(ary, NUM2LONG(arg1));
@@ -1986,6 +2142,7 @@ rb_ary_reject_bang(ary)
{
long i1, i2;
+ RETURN_ENUMERATOR(ary, 0, 0);
rb_ary_modify(ary);
for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
VALUE v = RARRAY(ary)->ptr[i1];
@@ -2014,6 +2171,7 @@ static VALUE
rb_ary_reject(ary)
VALUE ary;
{
+ RETURN_ENUMERATOR(ary, 0, 0);
ary = rb_ary_dup(ary);
rb_ary_reject_bang(ary);
return ary;
@@ -2034,6 +2192,7 @@ static VALUE
rb_ary_delete_if(ary)
VALUE ary;
{
+ RETURN_ENUMERATOR(ary, 0, 0);
rb_ary_reject_bang(ary);
return ary;
}
@@ -2257,6 +2416,12 @@ rb_ary_fill(argc, argv, ary)
break;
}
rb_ary_modify(ary);
+ if (len < 0) {
+ return ary;
+ }
+ if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
+ rb_raise(rb_eArgError, "argument too big");
+ }
end = beg + len;
if (end > RARRAY(ary)->len) {
if (end >= RARRAY(ary)->aux.capa) {
@@ -2367,7 +2532,7 @@ rb_ary_times(ary, times)
if (len < 0) {
rb_raise(rb_eArgError, "negative argument");
}
- if (LONG_MAX/len < RARRAY(ary)->len) {
+ if (ARY_MAX_SIZE/len < RARRAY(ary)->len) {
rb_raise(rb_eArgError, "argument too big");
}
len *= RARRAY(ary)->len;
@@ -2411,9 +2576,8 @@ rb_ary_assoc(ary, key)
VALUE v;
for (i = 0; i < RARRAY(ary)->len; ++i) {
- v = RARRAY(ary)->ptr[i];
- if (TYPE(v) == T_ARRAY &&
- RARRAY(v)->len > 0 &&
+ v = rb_check_array_type(RARRAY(ary)->ptr[i]);
+ if (!NIL_P(v) && RARRAY(v)->len > 0 &&
rb_equal(RARRAY(v)->ptr[0], key))
return v;
}
@@ -2451,6 +2615,22 @@ rb_ary_rassoc(ary, value)
return Qnil;
}
+static VALUE recursive_equal _((VALUE, VALUE, int));
+static VALUE
+recursive_equal(ary1, ary2, recur)
+ VALUE ary1, ary2;
+ int recur;
+{
+ long i;
+
+ if (recur) return Qfalse;
+ for (i=0; i<RARRAY(ary1)->len; i++) {
+ if (!rb_equal(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
+ return Qfalse;
+ }
+ return Qtrue;
+}
+
/*
* call-seq:
* array == other_array -> bool
@@ -2469,8 +2649,6 @@ static VALUE
rb_ary_equal(ary1, ary2)
VALUE ary1, ary2;
{
- long i;
-
if (ary1 == ary2) return Qtrue;
if (TYPE(ary2) != T_ARRAY) {
if (!rb_respond_to(ary2, rb_intern("to_ary"))) {
@@ -2479,8 +2657,20 @@ rb_ary_equal(ary1, ary2)
return rb_equal(ary2, ary1);
}
if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse;
+ return rb_exec_recursive(recursive_equal, ary1, ary2);
+}
+
+static VALUE recursive_eql _((VALUE, VALUE, int));
+static VALUE
+recursive_eql(ary1, ary2, recur)
+ VALUE ary1, ary2;
+ int recur;
+{
+ long i;
+
+ if (recur) return Qfalse;
for (i=0; i<RARRAY(ary1)->len; i++) {
- if (!rb_equal(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
+ if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
return Qfalse;
}
return Qtrue;
@@ -2498,33 +2688,26 @@ static VALUE
rb_ary_eql(ary1, ary2)
VALUE ary1, ary2;
{
- long i;
-
if (ary1 == ary2) return Qtrue;
if (TYPE(ary2) != T_ARRAY) return Qfalse;
if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse;
- for (i=0; i<RARRAY(ary1)->len; i++) {
- if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
- return Qfalse;
- }
- return Qtrue;
+ return rb_exec_recursive(recursive_eql, ary1, ary2);
}
-/*
- * call-seq:
- * array.hash -> fixnum
- *
- * Compute a hash-code for this array. Two arrays with the same content
- * will have the same hash code (and will compare using <code>eql?</code>).
- */
-
+static VALUE recursive_hash _((VALUE, VALUE, int));
static VALUE
-rb_ary_hash(ary)
+recursive_hash(ary, dummy, recur)
VALUE ary;
+ VALUE dummy;
+ int recur;
{
long i, h;
VALUE n;
+ if (recur) {
+ return LONG2FIX(0);
+ }
+
h = RARRAY(ary)->len;
for (i=0; i<RARRAY(ary)->len; i++) {
h = (h << 1) | (h<0 ? 1 : 0);
@@ -2536,6 +2719,21 @@ rb_ary_hash(ary)
/*
* call-seq:
+ * array.hash -> fixnum
+ *
+ * Compute a hash-code for this array. Two arrays with the same content
+ * will have the same hash code (and will compare using <code>eql?</code>).
+ */
+
+static VALUE
+rb_ary_hash(ary)
+ VALUE ary;
+{
+ return rb_exec_recursive(recursive_hash, ary, 0);
+}
+
+/*
+ * call-seq:
* array.include?(obj) -> true or false
*
* Returns <code>true</code> if the given object is present in
@@ -2563,6 +2761,29 @@ rb_ary_includes(ary, item)
}
+static VALUE recursive_cmp _((VALUE, VALUE, int));
+static VALUE
+recursive_cmp(ary1, ary2, recur)
+ VALUE ary1;
+ VALUE ary2;
+ int recur;
+{
+ long i, len;
+
+ if (recur) return Qnil;
+ len = RARRAY(ary1)->len;
+ if (len > RARRAY(ary2)->len) {
+ len = RARRAY(ary2)->len;
+ }
+ for (i=0; i<len; i++) {
+ VALUE v = rb_funcall(rb_ary_elt(ary1, i), id_cmp, 1, rb_ary_elt(ary2, i));
+ if (v != INT2FIX(0)) {
+ return v;
+ }
+ }
+ return Qundef;
+}
+
/*
* call-seq:
* array <=> other_array -> -1, 0, +1
@@ -2587,19 +2808,13 @@ VALUE
rb_ary_cmp(ary1, ary2)
VALUE ary1, ary2;
{
- long i, len;
+ long len;
+ VALUE v;
ary2 = to_ary(ary2);
- len = RARRAY(ary1)->len;
- if (len > RARRAY(ary2)->len) {
- len = RARRAY(ary2)->len;
- }
- for (i=0; i<len; i++) {
- VALUE v = rb_funcall(rb_ary_elt(ary1, i), id_cmp, 1, rb_ary_elt(ary2, i));
- if (v != INT2FIX(0)) {
- return v;
- }
- }
+ if (ary1 == ary2) return INT2FIX(0);
+ v = rb_exec_recursive(recursive_cmp, ary1, ary2);
+ if (v != Qundef) return v;
len = RARRAY(ary1)->len - RARRAY(ary2)->len;
if (len == 0) return INT2FIX(0);
if (len > 0) return INT2FIX(1);
@@ -2839,6 +3054,7 @@ rb_ary_compact(ary)
* array.nitems -> int
*
* Returns the number of non-<code>nil</code> elements in _self_.
+ *
* May be zero.
*
* [ 1, nil, 3, nil, 5 ].nitems #=> 3
@@ -2851,110 +3067,691 @@ rb_ary_nitems(ary)
long n = 0;
VALUE *p, *pend;
- p = RARRAY(ary)->ptr;
- pend = p + RARRAY(ary)->len;
-
- while (p < pend) {
+ for (p = RARRAY(ary)->ptr, pend = p + RARRAY(ary)->len; p < pend; p++) {
if (!NIL_P(*p)) n++;
- p++;
}
return LONG2NUM(n);
}
-static long
-flatten(ary, idx, ary2, memo)
+/*
+ * call-seq:
+ * array.count -> int
+ * array.count(obj) -> int
+ * array.count { |item| block } -> int
+ *
+ * Returns the number of elements. If an argument is given, counts
+ * the number of elements which equals to <i>obj</i>. If a block is
+ * given, counts the number of elements yielding a true value.
+ *
+ * ary = [1, 2, 4, 2]
+ * ary.count # => 4
+ * ary.count(2) # => 2
+ * ary.count{|x|x%2==0} # => 3
+ *
+ */
+
+static VALUE
+rb_ary_count(argc, argv, ary)
+ int argc;
+ VALUE *argv;
VALUE ary;
- long idx;
- VALUE ary2, memo;
{
- VALUE id;
- long i = idx;
- long n, lim = idx + RARRAY(ary2)->len;
+ long n = 0;
+
+ if (argc == 0) {
+ VALUE *p, *pend;
- id = rb_obj_id(ary2);
- if (rb_ary_includes(memo, id)) {
- rb_raise(rb_eArgError, "tried to flatten recursive array");
+ if (!rb_block_given_p())
+ return LONG2NUM(RARRAY_LEN(ary));
+
+ for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
+ if (RTEST(rb_yield(*p))) n++;
+ }
}
- rb_ary_push(memo, id);
- rb_ary_splice(ary, idx, 1, ary2);
- while (i < lim) {
- VALUE tmp;
+ else {
+ VALUE obj, *p, *pend;
- tmp = rb_check_array_type(rb_ary_elt(ary, i));
- if (!NIL_P(tmp)) {
- n = flatten(ary, i, tmp, memo);
- i += n; lim += n;
+ rb_scan_args(argc, argv, "1", &obj);
+ if (rb_block_given_p()) {
+ rb_warn("given block not used");
+ }
+ for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
+ if (rb_equal(*p, obj)) n++;
+ }
+ }
+
+ return LONG2NUM(n);
+}
+
+static VALUE
+flatten(ary, level, modified)
+ VALUE ary;
+ int level;
+ int *modified;
+{
+ long i = 0;
+ VALUE stack, result, tmp, elt;
+ st_table *memo;
+ st_data_t id;
+
+ stack = ary_new(0, ARY_DEFAULT_SIZE);
+ result = ary_new(0, RARRAY_LEN(ary));
+ memo = st_init_numtable();
+ st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
+ *modified = 0;
+
+ while (1) {
+ while (i < RARRAY(ary)->len) {
+ elt = RARRAY(ary)->ptr[i++];
+ tmp = rb_check_array_type(elt);
+ if (RBASIC(result)->klass) {
+ rb_raise(rb_eRuntimeError, "flatten reentered");
+ }
+ if (NIL_P(tmp) || (level >= 0 && RARRAY(stack)->len / 2 >= level)) {
+ rb_ary_push(result, elt);
+ }
+ else {
+ *modified = 1;
+ id = (st_data_t)tmp;
+ if (st_lookup(memo, id, 0)) {
+ st_free_table(memo);
+ rb_raise(rb_eArgError, "tried to flatten recursive array");
+ }
+ st_insert(memo, id, (st_data_t)Qtrue);
+ rb_ary_push(stack, ary);
+ rb_ary_push(stack, LONG2NUM(i));
+ ary = tmp;
+ i = 0;
+ }
+ }
+ if (RARRAY(stack)->len == 0) {
+ break;
}
- i++;
+ id = (st_data_t)ary;
+ st_delete(memo, &id, 0);
+ tmp = rb_ary_pop(stack);
+ i = NUM2LONG(tmp);
+ ary = rb_ary_pop(stack);
}
- rb_ary_pop(memo);
- return lim - idx - 1; /* returns number of increased items */
+ st_free_table(memo);
+
+ RBASIC(result)->klass = rb_class_of(ary);
+ return result;
}
/*
* call-seq:
* array.flatten! -> array or nil
+ * array.flatten!(level) -> array or nil
*
* Flattens _self_ in place.
* Returns <code>nil</code> if no modifications were made (i.e.,
- * <i>array</i> contains no subarrays.)
+ * <i>array</i> contains no subarrays.) If the optional <i>level</i>
+ * argument determines the level of recursion to flatten.
*
* a = [ 1, 2, [3, [4, 5] ] ]
* a.flatten! #=> [1, 2, 3, 4, 5]
* a.flatten! #=> nil
* a #=> [1, 2, 3, 4, 5]
+ * a = [ 1, 2, [3, [4, 5] ] ]
+ * a.flatten!(1) #=> [1, 2, 3, [4, 5]]
*/
static VALUE
-rb_ary_flatten_bang(ary)
+rb_ary_flatten_bang(argc, argv, ary)
+ int argc;
+ VALUE *argv;
VALUE ary;
{
- long i = 0;
- int mod = 0;
- VALUE memo = Qnil;
+ int mod = 0, level = -1;
+ VALUE result, lv;
- while (i<RARRAY(ary)->len) {
- VALUE ary2 = RARRAY(ary)->ptr[i];
- VALUE tmp;
+ rb_scan_args(argc, argv, "01", &lv);
+ if (!NIL_P(lv)) level = NUM2INT(lv);
+ if (level == 0) return ary;
- tmp = rb_check_array_type(ary2);
- if (!NIL_P(tmp)) {
- if (NIL_P(memo)) {
- memo = rb_ary_new();
- }
- i += flatten(ary, i, tmp, memo);
- mod = 1;
- }
- i++;
- }
+ result = flatten(ary, level, &mod);
if (mod == 0) return Qnil;
+ rb_ary_replace(ary, result);
+
return ary;
}
/*
* call-seq:
* array.flatten -> an_array
+ * array.flatten(level) -> an_array
*
* Returns a new array that is a one-dimensional flattening of this
* array (recursively). That is, for every element that is an array,
- * extract its elements into the new array.
+ * extract its elements into the new array. If the optional
+ * <i>level</i> argument determines the level of recursion to flatten.
*
* s = [ 1, 2, 3 ] #=> [1, 2, 3]
* t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]]
* a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
- * a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10
+ * a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ * a = [ 1, 2, [3, [4, 5] ] ]
+ * a.flatten(1) #=> [1, 2, 3, [4, 5]]
*/
static VALUE
-rb_ary_flatten(ary)
+rb_ary_flatten(argc, argv, ary)
+ int argc;
+ VALUE *argv;
VALUE ary;
{
+ int mod = 0, level = -1;
+ VALUE result, lv;
+
+ rb_scan_args(argc, argv, "01", &lv);
+ if (!NIL_P(lv)) level = NUM2INT(lv);
+ if (level == 0) return ary;
+
+ result = flatten(ary, level, &mod);
+ if (OBJ_TAINTED(ary)) OBJ_TAINT(result);
+
+ return result;
+}
+
+/*
+ * call-seq:
+ * array.shuffle! -> array or nil
+ *
+ * Shuffles elements in _self_ in place.
+ */
+
+
+static VALUE
+rb_ary_shuffle_bang(ary)
+ VALUE ary;
+{
+ long i = RARRAY(ary)->len;
+
+ rb_ary_modify(ary);
+ while (i) {
+ long j = rb_genrand_real()*i;
+ VALUE tmp = RARRAY(ary)->ptr[--i];
+ RARRAY(ary)->ptr[i] = RARRAY(ary)->ptr[j];
+ RARRAY(ary)->ptr[j] = tmp;
+ }
+ return ary;
+}
+
+
+/*
+ * call-seq:
+ * array.shuffle -> an_array
+ *
+ * Returns a new array with elements of this array shuffled.
+ *
+ * a = [ 1, 2, 3 ] #=> [1, 2, 3]
+ * a.shuffle #=> [2, 3, 1]
+ */
+
+static VALUE
+rb_ary_shuffle(VALUE ary)
+{
ary = rb_ary_dup(ary);
- rb_ary_flatten_bang(ary);
+ rb_ary_shuffle_bang(ary);
+ return ary;
+}
+
+
+/*
+ * call-seq:
+ * array.choice -> obj
+ *
+ * Choose a random element from an array.
+ */
+
+
+static VALUE
+rb_ary_choice(ary)
+ VALUE ary;
+{
+ long i, j;
+
+ i = RARRAY(ary)->len;
+ if (i == 0) return Qnil;
+ j = rb_genrand_real()*i;
+ return RARRAY(ary)->ptr[j];
+}
+
+
+/*
+ * call-seq:
+ * ary.cycle {|obj| block }
+ * ary.cycle(n) {|obj| block }
+ *
+ * Calls <i>block</i> for each element repeatedly _n_ times or
+ * forever if none or nil is given. If a non-positive number is
+ * given or the array is empty, does nothing. Returns nil if the
+ * loop has finished without getting interrupted.
+ *
+ * a = ["a", "b", "c"]
+ * a.cycle {|x| puts x } # print, a, b, c, a, b, c,.. forever.
+ * a.cycle(2) {|x| puts x } # print, a, b, c, a, b, c.
+ *
+ */
+
+static VALUE
+rb_ary_cycle(argc, argv, ary)
+ int argc;
+ VALUE *argv;
+ VALUE ary;
+{
+ long n, i;
+ VALUE nv = Qnil;
+
+ rb_scan_args(argc, argv, "01", &nv);
+
+ RETURN_ENUMERATOR(ary, argc, argv);
+ if (NIL_P(nv)) {
+ n = -1;
+ }
+ else {
+ n = NUM2LONG(nv);
+ if (n <= 0) return Qnil;
+ }
+
+ while (RARRAY(ary)->len > 0 && (n < 0 || 0 < n--)) {
+ for (i=0; i<RARRAY(ary)->len; i++) {
+ rb_yield(RARRAY(ary)->ptr[i]);
+ }
+ }
+ return Qnil;
+}
+
+#define tmpbuf(n, size) rb_str_tmp_new((n)*(size))
+
+/*
+ * Recursively compute permutations of r elements of the set [0..n-1].
+ * When we have a complete permutation of array indexes, copy the values
+ * at those indexes into a new array and yield that array.
+ *
+ * n: the size of the set
+ * r: the number of elements in each permutation
+ * p: the array (of size r) that we're filling in
+ * index: what index we're filling in now
+ * used: an array of booleans: whether a given index is already used
+ * values: the Ruby array that holds the actual values to permute
+ */
+static void
+permute0(n, r, p, index, used, values)
+ long n, r, *p, index;
+ int *used;
+ VALUE values;
+{
+ long i,j;
+ for (i = 0; i < n; i++) {
+ if (used[i] == 0) {
+ p[index] = i;
+ if (index < r-1) { /* if not done yet */
+ used[i] = 1; /* mark index used */
+ permute0(n, r, p, index+1, /* recurse */
+ used, values);
+ used[i] = 0; /* index unused */
+ }
+ else {
+ /* We have a complete permutation of array indexes */
+ /* Build a ruby array of the corresponding values */
+ /* And yield it to the associated block */
+ VALUE result = rb_ary_new2(r);
+ VALUE *result_array = RARRAY(result)->ptr;
+ const VALUE *values_array = RARRAY(values)->ptr;
+
+ for (j = 0; j < r; j++) result_array[j] = values_array[p[j]];
+ RARRAY(result)->len = r;
+ rb_yield(result);
+ }
+ }
+ }
+}
+
+/*
+ * call-seq:
+ * ary.permutation { |p| block } -> array
+ * ary.permutation -> enumerator
+ * ary.permutation(n) { |p| block } -> array
+ * ary.permutation(n) -> enumerator
+ *
+ * When invoked with a block, yield all permutations of length <i>n</i>
+ * of the elements of <i>ary</i>, then return the array itself.
+ * If <i>n</i> is not specified, yield all permutations of all elements.
+ * The implementation makes no guarantees about the order in which
+ * the permutations are yielded.
+ *
+ * When invoked without a block, return an enumerator object instead.
+ *
+ * Examples:
+ *
+ * a = [1, 2, 3]
+ * a.permutation.to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
+ * a.permutation(1).to_a #=> [[1],[2],[3]]
+ * a.permutation(2).to_a #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
+ * a.permutation(3).to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
+ * a.permutation(0).to_a #=> [[]] # one permutation of length 0
+ * a.permutation(4).to_a #=> [] # no permutations of length 4
+ */
+
+static VALUE
+rb_ary_permutation(argc, argv, ary)
+ int argc;
+ VALUE *argv;
+ VALUE ary;
+{
+ VALUE num;
+ long r, n, i;
+
+ n = RARRAY(ary)->len; /* Array length */
+ RETURN_ENUMERATOR(ary, argc, argv); /* Return enumerator if no block */
+ rb_scan_args(argc, argv, "01", &num);
+ r = NIL_P(num) ? n : NUM2LONG(num); /* Permutation size from argument */
+
+ if (r < 0 || n < r) {
+ /* no permutations: yield nothing */
+ }
+ else if (r == 0) { /* exactly one permutation: the zero-length array */
+ rb_yield(rb_ary_new2(0));
+ }
+ else if (r == 1) { /* this is a special, easy case */
+ for (i = 0; i < RARRAY(ary)->len; i++) {
+ rb_yield(rb_ary_new3(1, RARRAY(ary)->ptr[i]));
+ }
+ }
+ else { /* this is the general case */
+ volatile VALUE t0 = tmpbuf(n,sizeof(long));
+ long *p = (long*)RSTRING(t0)->ptr;
+ volatile VALUE t1 = tmpbuf(n,sizeof(int));
+ int *used = (int*)RSTRING(t1)->ptr;
+ VALUE ary0 = ary_make_shared(ary); /* private defensive copy of ary */
+
+ 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);
+ }
return ary;
}
+static long
+combi_len(n, k)
+ long n, k;
+{
+ long i, val = 1;
+
+ if (k*2 > n) k = n-k;
+ if (k == 0) return 1;
+ if (k < 0) return 0;
+ val = 1;
+ for (i=1; i <= k; i++,n--) {
+ long m = val;
+ val *= n;
+ if (val < m) {
+ rb_raise(rb_eRangeError, "too big for combination");
+ }
+ val /= i;
+ }
+ return val;
+}
+
+/*
+ * call-seq:
+ * ary.combination(n) { |c| block } -> ary
+ * ary.combination(n) -> enumerator
+ *
+ * When invoked with a block, yields all combinations of length <i>n</i>
+ * of elements from <i>ary</i> and then returns <i>ary</i> itself.
+ * The implementation makes no guarantees about the order in which
+ * the combinations are yielded.
+ *
+ * When invoked without a block, returns an enumerator object instead.
+ *
+ * Examples:
+ *
+ * a = [1, 2, 3, 4]
+ * a.combination(1).to_a #=> [[1],[2],[3],[4]]
+ * a.combination(2).to_a #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
+ * a.combination(3).to_a #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
+ * a.combination(4).to_a #=> [[1,2,3,4]]
+ * a.combination(0).to_a #=> [[]] # one combination of length 0
+ * a.combination(5).to_a #=> [] # no combinations of length 5
+ *
+ */
+
+static VALUE
+rb_ary_combination(ary, num)
+ VALUE ary;
+ VALUE num;
+{
+ long n, i, len;
+
+ n = NUM2LONG(num);
+ RETURN_ENUMERATOR(ary, 1, &num);
+ len = RARRAY(ary)->len;
+ if (n < 0 || len < n) {
+ /* yield nothing */
+ }
+ else if (n == 0) {
+ rb_yield(rb_ary_new2(0));
+ }
+ else if (n == 1) {
+ for (i = 0; i < len; i++) {
+ rb_yield(rb_ary_new3(1, RARRAY(ary)->ptr[i]));
+ }
+ }
+ else {
+ volatile VALUE t0 = tmpbuf(n+1, sizeof(long));
+ long *stack = (long*)RSTRING(t0)->ptr;
+ long nlen = combi_len(len, n);
+ volatile VALUE cc = rb_ary_new2(n);
+ VALUE *chosen = RARRAY(cc)->ptr;
+ long lev = 0;
+
+ RBASIC(cc)->klass = 0;
+ MEMZERO(stack, long, n);
+ stack[0] = -1;
+ for (i = 0; i < nlen; i++) {
+ chosen[lev] = RARRAY(ary)->ptr[stack[lev+1]];
+ for (lev++; lev < n; lev++) {
+ chosen[lev] = RARRAY(ary)->ptr[stack[lev+1] = stack[lev]+1];
+ }
+ rb_yield(rb_ary_new4(n, chosen));
+ do {
+ stack[lev--]++;
+ } while (lev && (stack[lev+1]+n == len+lev+1));
+ }
+ }
+ return ary;
+}
+
+/*
+ * call-seq:
+ * ary.product(other_ary, ...)
+ *
+ * Returns an array of all combinations of elements from all arrays.
+ * The length of the returned array is the product of the length
+ * of ary and the argument arrays
+ *
+ * [1,2,3].product([4,5]) # => [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]
+ * [1,2].product([1,2]) # => [[1,1],[1,2],[2,1],[2,2]]
+ * [1,2].product([3,4],[5,6]) # => [[1,3,5],[1,3,6],[1,4,5],[1,4,6],
+ * # [2,3,5],[2,3,6],[2,4,5],[2,4,6]]
+ * [1,2].product() # => [[1],[2]]
+ * [1,2].product([]) # => []
+ */
+
+static VALUE
+rb_ary_product(argc, argv, ary)
+ int argc;
+ VALUE *argv;
+ VALUE ary;
+{
+ int n = argc+1; /* How many arrays we're operating on */
+ volatile VALUE t0 = tmpbuf(n, sizeof(VALUE));
+ volatile VALUE t1 = tmpbuf(n, sizeof(int));
+ VALUE *arrays = (VALUE*)RSTRING(t0)->ptr; /* The arrays we're computing the product of */
+ int *counters = (int*)RSTRING(t1)->ptr; /* The current position in each one */
+ VALUE result; /* The array we'll be returning */
+ long i,j;
+ long resultlen = 1;
+
+ RBASIC(t0)->klass = 0;
+ RBASIC(t1)->klass = 0;
+
+ /* initialize the arrays of arrays */
+ arrays[0] = ary;
+ for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
+
+ /* initialize the counters for the arrays */
+ for (i = 0; i < n; i++) counters[i] = 0;
+
+ /* Compute the length of the result array; return [] if any is empty */
+ for (i = 0; i < n; i++) {
+ long k = RARRAY(arrays[i])->len, l = resultlen;
+ if (k == 0) return rb_ary_new2(0);
+ resultlen *= k;
+ if (resultlen < k || resultlen < l || resultlen / k != l) {
+ rb_raise(rb_eRangeError, "too big to product");
+ }
+ }
+
+ /* Otherwise, allocate and fill in an array of results */
+ result = rb_ary_new2(resultlen);
+ for (i = 0; i < resultlen; i++) {
+ int m;
+ /* fill in one subarray */
+ VALUE subarray = rb_ary_new2(n);
+ for (j = 0; j < n; j++) {
+ rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
+ }
+
+ /* put it on the result array */
+ rb_ary_push(result, subarray);
+
+ /*
+ * Increment the last counter. If it overflows, reset to 0
+ * and increment the one before it.
+ */
+ m = n-1;
+ counters[m]++;
+ while (m > 0 && counters[m] == RARRAY(arrays[m])->len) {
+ counters[m] = 0;
+ m--;
+ counters[m]++;
+ }
+ }
+
+ return result;
+}
+
+/*
+ * call-seq:
+ * ary.take(n) => array
+ *
+ * Returns first n elements from <i>ary</i>.
+ *
+ * a = [1, 2, 3, 4, 5, 0]
+ * a.take(3) # => [1, 2, 3]
+ *
+ */
+
+static VALUE
+rb_ary_take(obj, n)
+ VALUE obj;
+ VALUE n;
+{
+ long len = NUM2LONG(n);
+ if (len < 0) {
+ rb_raise(rb_eArgError, "attempt to take negative size");
+ }
+
+ return rb_ary_subseq(obj, 0, len);
+}
+
+/*
+ * call-seq:
+ * ary.take_while {|arr| block } => array
+ *
+ * Passes elements to the block until the block returns nil or false,
+ * then stops iterating and returns an array of all prior elements.
+ *
+ * a = [1, 2, 3, 4, 5, 0]
+ * a.take_while {|i| i < 3 } # => [1, 2]
+ *
+ */
+
+static VALUE
+rb_ary_take_while(ary)
+ VALUE ary;
+{
+ long i;
+
+ RETURN_ENUMERATOR(ary, 0, 0);
+ for (i = 0; i < RARRAY(ary)->len; i++) {
+ if (!RTEST(rb_yield(RARRAY(ary)->ptr[i]))) break;
+ }
+ return rb_ary_take(ary, LONG2FIX(i));
+}
+
+/*
+ * call-seq:
+ * ary.drop(n) => array
+ *
+ * Drops first n elements from <i>ary</i>, and returns rest elements
+ * in an array.
+ *
+ * a = [1, 2, 3, 4, 5, 0]
+ * a.drop(3) # => [4, 5, 0]
+ *
+ */
+
+static VALUE
+rb_ary_drop(ary, n)
+ VALUE ary;
+ VALUE n;
+{
+ VALUE result;
+ long pos = NUM2LONG(n);
+ if (pos < 0) {
+ rb_raise(rb_eArgError, "attempt to drop negative size");
+ }
+
+ result = rb_ary_subseq(ary, pos, RARRAY(ary)->len);
+ if (result == Qnil) result = rb_ary_new();
+ return result;
+}
+
+/*
+ * call-seq:
+ * ary.drop_while {|arr| block } => array
+ *
+ * Drops elements up to, but not including, the first element for
+ * which the block returns nil or false and returns an array
+ * containing the remaining elements.
+ *
+ * a = [1, 2, 3, 4, 5, 0]
+ * a.drop_while {|i| i < 3 } # => [3, 4, 5, 0]
+ *
+ */
+
+static VALUE
+rb_ary_drop_while(ary)
+ VALUE ary;
+{
+ long i;
+
+ RETURN_ENUMERATOR(ary, 0, 0);
+ for (i = 0; i < RARRAY(ary)->len; i++) {
+ if (!RTEST(rb_yield(RARRAY(ary)->ptr[i]))) break;
+ }
+ return rb_ary_drop(ary, LONG2FIX(i));
+}
+
+
/* Arrays are ordered, integer-indexed collections of any object.
* Array indexing starts at 0, as in C or Java. A negative index is
@@ -2993,8 +3790,8 @@ Init_Array()
rb_define_method(rb_cArray, "concat", rb_ary_concat, 1);
rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
- rb_define_method(rb_cArray, "pop", rb_ary_pop, 0);
- rb_define_method(rb_cArray, "shift", rb_ary_shift, 0);
+ rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
+ rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
rb_define_method(rb_cArray, "each", rb_ary_each, 0);
@@ -3003,8 +3800,9 @@ Init_Array()
rb_define_method(rb_cArray, "length", rb_ary_length, 0);
rb_define_alias(rb_cArray, "size", "length");
rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
- rb_define_method(rb_cArray, "index", rb_ary_index, 1);
- rb_define_method(rb_cArray, "rindex", rb_ary_rindex, 1);
+ rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
+ rb_define_method(rb_cArray, "index", rb_ary_index, -1);
+ rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
rb_define_method(rb_cArray, "indexes", rb_ary_indexes, -1);
rb_define_method(rb_cArray, "indices", rb_ary_indexes, -1);
rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
@@ -3048,9 +3846,22 @@ Init_Array()
rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
- rb_define_method(rb_cArray, "flatten", rb_ary_flatten, 0);
- rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, 0);
+ rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
+ rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
rb_define_method(rb_cArray, "nitems", rb_ary_nitems, 0);
+ rb_define_method(rb_cArray, "count", rb_ary_count, -1);
+ rb_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, 0);
+ rb_define_method(rb_cArray, "shuffle", rb_ary_shuffle, 0);
+ rb_define_method(rb_cArray, "choice", rb_ary_choice, 0);
+ rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
+ rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
+ rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
+ rb_define_method(rb_cArray, "product", rb_ary_product, -1);
+
+ rb_define_method(rb_cArray, "take", rb_ary_take, 1);
+ rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
+ rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
+ rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
id_cmp = rb_intern("<=>");
inspect_key = rb_intern("__inspect_key__");
diff --git a/bcc32/Makefile.sub b/bcc32/Makefile.sub
index 07c6bc9975..713b5c69df 100644
--- a/bcc32/Makefile.sub
+++ b/bcc32/Makefile.sub
@@ -4,8 +4,12 @@ SHELL = $(COMSPEC)
MKFILES = Makefile
#### Start of system configuration section. ####
+!ifndef OS
OS = bccwin32
-RT = $(OS)
+!endif
+!if !defined(RT)
+!error RT not defined. Retry from configure pass.
+!endif
## variables may be overridden by $(compile_dir)/Makefile
!ifndef srcdir
@@ -137,7 +141,7 @@ STACK = 0x2000000
XCFLAGS = -DRUBY_EXPORT -I. -I$(srcdir) -I$(srcdir)/missing
-ARFLAGS = /a
+ARFLAGS = /a /p32
LD = ilink32 -q -Gn
LDSHARED = $(LD)
XLDFLAGS = -Tpe c0x32.obj
@@ -153,8 +157,8 @@ EXEEXT = .exe
PROGRAM=$(RUBY_INSTALL_NAME)$(EXEEXT)
WPROGRAM=$(RUBYW_INSTALL_NAME)$(EXEEXT)
RUBYDEF = $(RUBY_SO_NAME).def
-MINIRUBY = .\miniruby$(EXEEXT)
-RUNRUBY = .\ruby$(EXEEXT) "$(srcdir)/runruby.rb" --extout="$(EXTOUT)" --
+MINIRUBY = .\miniruby$(EXEEXT) -I$(srcdir)/lib $(MINIRUBYOPT)
+RUNRUBY = .\$(PROGRAM) "$(srcdir)/runruby.rb" --extout="$(EXTOUT)" --
ORGLIBPATH = $(LIB)
@@ -169,6 +173,8 @@ PREP = miniruby$(EXEEXT)
OBJEXT = obj
+INSTALLED_LIST= .installed.list
+
WINMAINOBJ = winmain.$(OBJEXT)
MINIOBJS = dmydln.$(OBJEXT)
@@ -195,7 +201,13 @@ rubyw: $(WPROGRAM)
!include $(srcdir)/common.mk
-PHONY: Makefile
+$(MKFILES): $(srcdir)/bcc32/Makefile.sub $(srcdir)/bcc32/configure.bat $(srcdir)/bcc32/setup.mak
+ $(COMSPEC) /C $(srcdir:/=\)\bcc32\configure.bat $(configure_args)
+ @echo $(MKFILES) should be updated, re-run $(MAKE).
+ @$(MAKE) > nul -q -f &&|
+PHONY: nul
+ @exit
+|
CONFIG_H = ./.config.h.time
@@ -251,6 +263,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/bcc32/Makefile.sub
\#define HAVE_STRTOD 1
\#define HAVE_STRTOL 1
\#define HAVE_STRTOUL 1
+\#define HAVE_VSNPRINTF 1
\#define HAVE_ISNAN 1
\#define HAVE_FINITE 1
\#define HAVE_HYPOT 1
@@ -270,6 +283,9 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/bcc32/Makefile.sub
\#define RSHIFT(x,y) ((x)>>(int)y)
\#define FILE_COUNT level
\#define FILE_READPTR curp
+\#define RUBY_SETJMP(env) _setjmp(env)
+\#define RUBY_LONGJMP(env,val) longjmp(env,val)
+\#define RUBY_JMP_BUF jmp_buf
\#define inline __inline
\#define NEED_IO_SEEK_BETWEEN_RW 1
\#define STACK_GROW_DIRECTION -1
@@ -278,9 +294,12 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/bcc32/Makefile.sub
\#define RUBY_LIB "/lib/ruby/$(MAJOR).$(MINOR)"
\#define RUBY_SITE_LIB "/lib/ruby/site_ruby"
\#define RUBY_SITE_LIB2 "/lib/ruby/site_ruby/$(MAJOR).$(MINOR)"
+\#define RUBY_VENDOR_LIB "/lib/ruby/vendor_ruby"
+\#define RUBY_VENDOR_LIB2 "/lib/ruby/vendor_ruby/$(MAJOR).$(MINOR)"
\#define RUBY_PLATFORM "$(ARCH)-$(OS)"
\#define RUBY_ARCHLIB "/lib/ruby/$(MAJOR).$(MINOR)/$(ARCH)-$(OS)"
\#define RUBY_SITE_ARCHLIB "/lib/ruby/site_ruby/$(MAJOR).$(MINOR)/$(ARCH)-$(OS)"
+\#define RUBY_VENDOR_ARCHLIB "/lib/ruby/vendor_ruby/$(MAJOR).$(MINOR)/$(ARCH)-$(OS)"
|
@exit > $@
@@ -334,11 +353,8 @@ s,@RANLIB@,,;t t
s,@AR@,$(AR),;t t
s,@ARFLAGS@,$(ARFLAGS) ,;t t
s,@LN_S@,$(LN_S),;t t
-s,@SET_MAKE@,$(SET_MAKE),;t t
+s,@SET_MAKE@,MFLAGS = -$$(MAKEFLAGS),;t t
s,@CP@,copy > nul,;t t
-s,@INSTALL@,copy > nul,;t t
-s,@INSTALL_PROG@,$$(INSTALL),;t t
-s,@INSTALL_DATA@,$$(INSTALL),;t t
s,@LIBOBJS@, acosh.obj crypt.obj erf.obj win32.obj,;t t
s,@ALLOCA@,$(ALLOCA),;t t
s,@DEFAULT_KCODE@,$(DEFAULT_KCODE),;t t
@@ -389,13 +405,14 @@ s,@COMPILE_CXX@,$$(CXX) $$(INCFLAGS) $$(CXXFLAGS) $$(CPPFLAGS) -P -c $$(<:/=\),;
s,@COMPILE_RULES@,{$$(srcdir)}.%s{}.%s: {$$(topdir)}.%s{}.%s: {$$(hdrdir)}.%s{}.%s: .%s.%s:,;t t
s,@RULE_SUBST@,{.;$$(VPATH)}%s,;t t
s,@COMMON_LIBS@,m advapi32 avicap32 avifil32 cap comctl32 comdlg32 dlcapi gdi32 glu32 imagehlp imm32 inetmib1 kernel32 loadperf lsapi32 lz32 mapi32 mgmtapi mpr msacm32 msvfw32 nddeapi netapi32 ole32 oleaut32 oledlg olepro32 opengl32 pdh pkpd32 rasapi32 rasdlg rassapi rpcrt4 setupapi shell32 shfolder snmpapi sporder tapi32 url user32 vdmdbg version win32spl winmm wintrust wsock32,;t t
-s,@COMMON_MACROS@,WIN32_LEAN_AND_MEAN;t t
+s,@COMMON_MACROS@,WIN32_LEAN_AND_MEAN WIN32,;t t
s,@COMMON_HEADERS@,winsock2.h windows.h,;t t
s,@TRY_LINK@,$$(CC) -oconftest $$(INCFLAGS) -I$$(hdrdir) $$(CPPFLAGS) $$(CFLAGS) $$(LIBPATH) $$(LDFLAGS) $$(src) $$(LOCAL_LIBS) $$(LIBS),;t t
s,@EXPORT_PREFIX@,_,;t t
s,@arch@,$(ARCH)-$(OS),;t t
s,@sitearch@,$(ARCH)-$(OS),;t t
s,@sitedir@,$${prefix}/lib/ruby/site_ruby,;t t
+s,@vendordir@,$${prefix}/lib/ruby/vendor_ruby,;t t
s,@configure_args@,--enable-shared $(configure_args),;t t
s,@configure_input@,$$configure_input,;t t
s,@srcdir@,$(srcdir),;t t
@@ -421,6 +438,7 @@ $(LIBRUBY_A): $(OBJS) $(DMYEXT)
$(LIBRUBY_SO): $(LIBRUBY_A) $(DLDOBJS) $(RUBYDEF) $(RUBY_SO_NAME).res
@echo $(DLDOBJS)
+ @$(PRE_LIBRUBY_UPDATE)
$(LIBRUBY_LDSHARED) $(LIBRUBY_DLDFLAGS) $(DLDOBJS:/=\),$(LIBRUBY_SO),nul,$(LIBRUBY_A) $(LIBS),$(RUBYDEF),$(RUBY_SO_NAME).res
$(LIBRUBY): $(LIBRUBY_SO)
@@ -435,19 +453,60 @@ $(RUBY_INSTALL_NAME).rc $(RUBYW_INSTALL_NAME).rc $(RUBY_SO_NAME).rc: rbconfig.rb
-so_name=$(RUBY_SO_NAME) \
. $(icondirs) $(srcdir)/win32
-post-install-ext::
- $(MINIRUBY) -I$(srcdir)lib -rrbconfig -rfileutils \
- -e "FileUtils.rm_f(Dir[ARGV[0]+Config::CONFIG['archdir']+'/**/*.tds'])" "$(DESTDIR:\=/)"
+post-install-bin::
+ @$(NULLCMD)
+post-install-lib::
+ @$(NULLCMD)
+post-install-ext-comm::
+ @$(NULLCMD)
+post-install-ext-arch::
+ @$(NULLCMD)
+post-install-man::
+ @$(NULLCMD)
+post-install-doc::
+ @$(NULLCMD)
clean-local::
- @$(RM) ext\extinit.c ext\extinit.$(OBJEXT) *.tds *.il? $(RUBY_SO_NAME).lib
+ @$(RM) $(WINMAINOBJ) ext\extinit.c ext\extinit.$(OBJEXT) *.tds *.il? $(RUBY_SO_NAME).lib
@$(RM) $(RUBY_INSTALL_NAME).res $(RUBYW_INSTALL_NAME).res $(RUBY_SO_NAME).res
+ @$(RM) *.map *.pdb *.ilk *.exp $(RUBYDEF)
distclean-local::
@$(RM) ext\config.cache $(RBCONFIG:/=\)
- @$(RM) *.map *.pdb *.ilk *.exp $(RUBYDEF)
@$(RM) $(RUBY_INSTALL_NAME).rc $(RUBYW_INSTALL_NAME).rc $(RUBY_SO_NAME).rc
+update-rubyspec:
+ @echo SPEC_EXISTS=0 > $@.mk
+ @if exist $(srcdir:/=\)\rubyspec\nul echo SPEC_EXISTS=1 >> $@.mk
+ @type >> $@.mk &&|
+$()update-rubyspec:
+$() @del $@.mk
+$()!if $$(SPEC_EXISTS)
+$() cd $(srcdir:/=\)\rubyspec\mspec
+$() git pull
+$() cd ..\spec\rubyspec
+$() git pull
+$()!else
+$() git clone $(MSPEC_GIT_URL) $(srcdir)/rubyspec/mspec
+$() git clone $(RUBYSPEC_GIT_URL) $(srcdir)/rubyspec/spec/rubyspec
+$()!endif
+|
+ @$(MAKE) -$(MAKEFLAGS)$(MFLAGS) -f $@.mk
+
+test-rubyspec:
+ @echo SPEC_EXISTS=0 > $@.mk
+ @if exist $(srcdir:/=\)\rubyspec\nul echo SPEC_EXISTS=1 >> $@.mk
+ @type >> $@.mk &&|
+$()test-rubyspec:
+$()!if $$(SPEC_EXISTS)
+$() $(RUNRUBY) $(srcdir)/rubyspec/mspec/bin/mspec -r$(srcdir)/ext/purelib.rb $(srcdir)/rubyspec/spec/rubyspec/$(MAJOR).$(MINOR)
+$()!else
+$() @echo No rubyspec here. put rubyspec to srcdir first.
+$() @cd $(srcdir:/=\)\rubyspec
+$()!endif
+|
+ @$(MAKE) -$(MAKEFLAGS) -f $@.mk
+
ext/extinit.obj: ext/extinit.c $(SETUP)
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -o$@ -c ext/extinit.c
diff --git a/bcc32/configure.bat b/bcc32/configure.bat
index 123a3f23c8..95575cbc60 100755
--- a/bcc32/configure.bat
+++ b/bcc32/configure.bat
@@ -6,70 +6,110 @@
echo> ~tmp~.mak ####
echo>> ~tmp~.mak conf = %0
echo>> ~tmp~.mak $(conf:\=/): nul
-echo>> ~tmp~.mak @del ~tmp~.mak
+echo>> ~tmp~.mak @del ~setup~.mak
echo>> ~tmp~.mak @-$(MAKE) -l$(MAKEFLAGS) -f $(@D)setup.mak \
+if exist pathlist.tmp del pathlist.tmp
+if exist confargs.mk del confargs.mk
:loop
if "%1" == "" goto :end
if "%1" == "--prefix" goto :prefix
+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" == "RUBY_SUFFIX" goto :suffix
+if "%1" == "--program-name" goto :installname
+if "%1" == "--install-name" goto :installname
+if "%1" == "RUBY_INSTALL_NAME" goto :installname
+if "%1" == "--so-name" goto :soname
+if "%1" == "RUBY_SO_NAME" goto :soname
if "%1" == "--enable-install-doc" goto :enable-rdoc
if "%1" == "--disable-install-doc" goto :disable-rdoc
if "%1" == "--extout" goto :extout
+if "%1" == "EXTOUT" goto :extout
+if "%1" == "--path" goto :path
if "%1" == "-h" goto :help
if "%1" == "--help" goto :help
- echo>> ~tmp~.mak "%1" \
+ echo>>confargs.tmp %1 \
shift
goto :loop
:srcdir
- echo>> ~tmp~.mak -D"srcdir=%2" \
+ echo>> ~tmp~.mak -Dsrcdir=%2 \
+ echo>>confargs.tmp --srcdir=%2 \
shift
shift
goto :loop
:prefix
- echo>> ~tmp~.mak -D"prefix=%2" \
+ echo>> ~tmp~.mak -Dprefix=%2 \
+ echo>>confargs.tmp %1=%2 \
shift
shift
goto :loop
:suffix
- echo>> ~tmp~.mak -D"RUBY_SUFFIX=%2" \
+ echo>>confargs.mk !ifndef RUBY_SUFFIX
+ echo>>confargs.mk RUBY_SUFFIX = %2
+ echo>>confargs.mk !endif
+ echo>>confargs.tmp %1=%2 \
shift
shift
goto :loop
:installname
- echo>> ~tmp~.mak -D"RUBY_INSTALL_NAME=%2" \
+ echo>>confargs.mk !ifndef RUBY_INSTALL_NAME
+ echo>>confargs.mk RUBY_INSTALL_NAME = %2
+ echo>>confargs.mk !endif
+ echo>>confargs.tmp %1=%2 \
shift
shift
goto :loop
:soname
- echo>> ~tmp~.mak -D"RUBY_SO_NAME=%2" \
+ echo>>confargs.mk !ifndef RUBY_SO_NAME
+ echo>>confargs.mk RUBY_SO_NAME = %2
+ echo>>confargs.mk !endif
+ echo>>confargs.tmp %1=%2 \
shift
shift
goto :loop
:target
- echo>> ~tmp~.mak "%2" \
+ echo>> ~tmp~.mak %2 \
+ echo>>confargs.tmp --target=%2 \
shift
shift
goto :loop
:extstatic
- echo>> ~tmp~.mak -D"EXTSTATIC=static" \
+ echo>>confargs.mk !ifndef EXTSTATIC
+ echo>>confargs.mk EXTSTATIC = static
+ echo>>confargs.mk !endif
+ echo>>confargs.tmp %1 \
shift
goto :loop
:enable-rdoc
- echo>> ~tmp~.mak -D"RDOCTARGET=install-doc" \
+ echo>>confargs.mk !ifndef RDOCTARGET
+ echo>>confargs.mk RDOCTARGET = install-doc
+ echo>>confargs.mk !endif
+ echo>>confargs.tmp %1 \
shift
goto :loop
:disable-rdoc
- echo>> ~tmp~.mak -D"RDOCTARGET=install-nodoc" \
+ echo>>confargs.mk !ifndef RDOCTARGET
+ echo>>confargs.mk RDOCTARGET = install-nodoc
+ echo>>confargs.mk !endif
+ echo>>confargs.tmp %1 \
shift
goto :loop
:extout
- echo>> ~tmp~.mak "EXTOUT=%2" \
+ echo>>confargs.mk !ifndef EXTOUT
+ echo>>confargs.mk EXTOUT = %2
+ echo>>confargs.mk !endif
+ echo>>confargs.tmp %1=%2 \
+ shift
+ shift
+goto :loop
+:path
+ echo>>pathlist.tmp %2;\
+ echo>>confargs.tmp %1=%2 \
shift
shift
goto :loop
@@ -83,10 +123,30 @@ goto :loop
echo --target=TARGET configure for TARGET [i386-bccwin32]
echo Optional Package:
echo --with-static-linked-ext link external modules statically
- echo --enable-install-doc install rdoc indexes during install
+ echo --disable-install-doc install rdoc indexes during install
+ del *.tmp
del ~tmp~.mak
goto :exit
:end
-echo>> ~tmp~.mak bcc32dir="$(@D)"
-make -s -f ~tmp~.mak
+echo>> ~tmp~.mak -Dbcc32dir=$(@D)
+if not exist confargs.tmp goto :noconfargs
+ echo>>confargs.mk configure_args = \
+ type>>confargs.mk confargs.tmp
+ echo.>>confargs.mk
+ echo>>confargs.mk ####
+:noconfargs
+if not exist pathlist.tmp goto :nopathlist
+ echo>>confargs.mk pathlist = \
+ type>>confargs.mk pathlist.tmp
+ echo.>>confargs.mk
+ echo>>confargs.mk ####
+ echo>>confargs.mk PATH = $(pathlist:;=/bin;)$(PATH)
+ echo>>confargs.mk INCLUDE = $(pathlist:;=/include;)
+ echo>>confargs.mk LIB = $(pathlist:;=/lib;)
+:nopathlist
+if exist confargs.mk copy confargs.mk ~setup~.mak > nul
+type>>~setup~.mak ~tmp~.mak
+del *.tmp > nul
+del ~tmp~.mak > nul
+make -s -f ~setup~.mak
:exit
diff --git a/bcc32/mkexports.rb b/bcc32/mkexports.rb
index e34b441e2f..dc523e2541 100644..100755
--- a/bcc32/mkexports.rb
+++ b/bcc32/mkexports.rb
@@ -1,5 +1,7 @@
#!./miniruby -s
+$name = $library = $description = nil
+
SYM = {}
STDIN.reopen(open("nul"))
ARGV.each do |obj|
diff --git a/bcc32/setup.mak b/bcc32/setup.mak
index efc15c3ea7..483292ed51 100644
--- a/bcc32/setup.mak
+++ b/bcc32/setup.mak
@@ -30,7 +30,9 @@ i586-$(OS): -prologue- -i586- -epilogue-
i686-$(OS): -prologue- -i686- -epilogue-
alpha-$(OS): -prologue- -alpha- -epilogue-
--prologue-: nul
+-prologue-: -basic-vars- -version- -system-vars-
+
+-basic-vars-: nul
@echo Creating $(MAKEFILE)
@type > $(MAKEFILE) &&|
\#\#\# Makefile for ruby $(OS) \#\#\#
@@ -40,36 +42,68 @@ $(BANG)endif
$(BANG)ifndef prefix
prefix = $(prefix:\=/)
$(BANG)endif
-$(BANG)ifndef EXTSTATIC
-EXTSTATIC = $(EXTSTATIC)
-$(BANG)endif
-!if defined(RDOCTARGET)
-$(BANG)ifndef RDOCTARGET
-RDOCTARGET = $(RDOCTARGET)
-$(BANG)endif
-!endif
-!if defined(EXTOUT)
-$(BANG)ifndef EXTOUT
-EXTOUT = $(EXTOUT)
-$(BANG)endif
+|
+!if exist(confargs.mk)
+ @type confargs.mk >> $(MAKEFILE)
+ @del confargs.mk
!endif
+
+-system-vars-: -runtime- -bormm-
+
+-bormm-: nul
+ @-ilink32 -q -Gn -x usebormm.lib > nul
+ @-if exist usebormm.tds $(APPEND) MEMLIB = usebormm.lib
+ @if exist usebormm.* del usebormm.*
+
+-osname-: nul
+ @echo OS = >>$(MAKEFILE)
+
+-runtime-: nul
+ type > conftest.c &&|
+\#include <stdio.h>
+int main(){printf("");return 0;}
|
- @type > usebormm.bat &&|
-@echo off
-ilink32 -Gn -x usebormm.lib > nul
-if exist usebormm.tds echo MEMLIB = usebormm.lib
+ bcc32 conftest.c cw32i.lib > nul
+ tdump conftest.exe < nul > conftest.i
+ grep "^Imports from CC" conftest.i > conftest.c
+ cpp32 -P- -DFile=\# -DImports=RTNAME -Dfrom== conftest.c > nul
+ $(MAKE) > nul -DBANG=$(BANG) -f &&|
+-runtime-: nul
+$(BANG)include conftest.i
+RT = $$(RTNAME:.DLL=)
+OS = $$(RT:CC32=)
+-runtime-:
+ del conftest.*
+$(BANG)if "$$(OS)" == "50"
+ echo OS = bccwin32 >> $(MAKEFILE)
+$(BANG)else
+ echo OS = bccwin32_$$(OS) >> $(MAKEFILE)
+$(BANG)endif
|
- @usebormm.bat >> $(MAKEFILE)
- @del usebormm.*
+ @echo RT = $$(OS) >> $(MAKEFILE)
- @cpp32 -I$(srcdir) -DRUBY_EXTERN="//" -P- -o$(MAKEFILE) > nul &&|
+-version-: nul
+ @cpp32 -I$(srcdir) -P- -o$(MAKEFILE) > nul &&|
\#include "version.h"
MAJOR = RUBY_VERSION_MAJOR
MINOR = RUBY_VERSION_MINOR
TEENY = RUBY_VERSION_TEENY
+
+BORLANDC = __BORLANDC__
|
- @type $(MAKEFILE).i >> $(MAKEFILE)
+ @$(MAKE) > nul -DBANG=$(BANG) -f &&,
+-version-: nul
+$(BANG)include $(MAKEFILE)
+$(BANG)include $(MAKEFILE).i
+-version-:
@del $(MAKEFILE).i
+ @type >> $(MAKEFILE) &&|
+MAJOR = $$(MAJOR)
+MINOR = $$(MINOR)
+TEENY = $$(TEENY)
+BORLANDC = $$(BORLANDC)
+|
+,
-generic-: nul
!if defined(PROCESSOR_ARCHITECTURE) || defined(PROCESSOR_LEVEL)
@@ -84,7 +118,6 @@ $(BANG)ifndef PROCESSOR_LEVEL
PROCESSOR_LEVEL = $(PROCESSOR_LEVEL)
$(BANG)endif
!endif
-
|
!endif
@@ -117,8 +150,6 @@ $(BANG)endif
-epilogue-: nul
@type >> $(MAKEFILE) &&|
-\# OS = $(OS)
-\# RT = $(RT)
\# RUBY_INSTALL_NAME = ruby
\# RUBY_SO_NAME = $$(RT)-$$(RUBY_INSTALL_NAME)$$(MAJOR)$$(MINOR)
\# CFLAGS = -q $$(DEBUGFLAGS) $$(OPTFLAGS) $$(PROCESSOR_FLAG) -w- -wsus -wcpt -wdup -wext -wrng -wrpt -wzdi
@@ -129,5 +160,4 @@ $(BANG)endif
\# EXTLIBS = cw32.lib import32.lib user32.lib kernel32.lib
$(BANG)include $$(srcdir)/bcc32/Makefile.sub
|
- @$(srcdir:/=\)\win32\rm.bat config.h config.status
@echo type "`$(MAKE)'" to make ruby for $(OS).
diff --git a/bignum.c b/bignum.c
index 3057f1d45a..7f14aee709 100644
--- a/bignum.c
+++ b/bignum.c
@@ -2,8 +2,8 @@
bignum.c -
- $Author: shyouhei $
- $Date: 2006/12/06 10:14:12 $
+ $Author$
+ $Date$
created at: Fri Jun 10 00:48:55 JST 1994
Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -11,8 +11,10 @@
**********************************************************************/
#include "ruby.h"
+#include "rubysig.h"
#include <math.h>
+#include <float.h>
#include <ctype.h>
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
@@ -36,7 +38,21 @@ VALUE rb_cBignum;
#define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1)))
#define BDIGMAX ((BDIGIT)-1)
-#define BIGZEROP(x) (RBIGNUM(x)->len == 0 || (RBIGNUM(x)->len == 1 && BDIGITS(x)[0] == 0))
+#define BIGZEROP(x) (RBIGNUM(x)->len == 0 || \
+ (BDIGITS(x)[0] == 0 && \
+ (RBIGNUM(x)->len == 1 || bigzero_p(x))))
+
+static int bigzero_p(VALUE);
+static int
+bigzero_p(x)
+ VALUE x;
+{
+ long i;
+ for (i = 0; i < RBIGNUM(x)->len; ++i) {
+ if (BDIGITS(x)[i]) return 0;
+ }
+ return 1;
+}
static VALUE
bignew_1(klass, len, sign)
@@ -74,6 +90,7 @@ get2comp(x)
BDIGIT *ds = BDIGITS(x);
BDIGIT_DBL num;
+ if (!i) return;
while (i--) ds[i] = ~ds[i];
i = 0; num = 1;
do {
@@ -96,35 +113,52 @@ rb_big_2comp(x) /* get 2's complement */
}
static VALUE
-bignorm(x)
+bigtrunc(x)
VALUE x;
{
- if (FIXNUM_P(x)) {
- return x;
- }
- else if (TYPE(x) == T_BIGNUM) {
- long len = RBIGNUM(x)->len;
- BDIGIT *ds = BDIGITS(x);
+ long len = RBIGNUM(x)->len;
+ BDIGIT *ds = BDIGITS(x);
+
+ if (len == 0) return x;
+ while (--len && !ds[len]);
+ RBIGNUM(x)->len = ++len;
+ return x;
+}
- while (len-- && !ds[len]) ;
- RBIGNUM(x)->len = ++len;
+static VALUE
+bigfixize(x)
+ VALUE x;
+{
+ long len = RBIGNUM(x)->len;
+ BDIGIT *ds = BDIGITS(x);
- if (len*SIZEOF_BDIGITS <= sizeof(VALUE)) {
- long num = 0;
- while (len--) {
- num = BIGUP(num) + ds[len];
+ if (len*SIZEOF_BDIGITS <= sizeof(VALUE)) {
+ long num = 0;
+ while (len--) {
+ num = BIGUP(num) + ds[len];
+ }
+ if (num >= 0) {
+ if (RBIGNUM(x)->sign) {
+ if (POSFIXABLE(num)) return LONG2FIX(num);
}
- if (num >= 0) {
- if (RBIGNUM(x)->sign) {
- if (POSFIXABLE(num)) return LONG2FIX(num);
- }
- else if (NEGFIXABLE(-(long)num)) return LONG2FIX(-(long)num);
+ else {
+ if (NEGFIXABLE(-(long)num)) return LONG2FIX(-(long)num);
}
}
}
return x;
}
+static VALUE
+bignorm(x)
+ VALUE x;
+{
+ if (!FIXNUM_P(x) && TYPE(x) == T_BIGNUM) {
+ x = bigfixize(bigtrunc(x));
+ }
+ return x;
+}
+
VALUE
rb_big_norm(x)
VALUE x;
@@ -331,6 +365,13 @@ rb_cstr_to_inum(str, base, badcheck)
VALUE z;
BDIGIT *zds;
+#define conv_digit(c) \
+ (!ISASCII(c) ? -1 : \
+ isdigit(c) ? ((c) - '0') : \
+ islower(c) ? ((c) - 'a' + 10) : \
+ isupper(c) ? ((c) - 'A' + 10) : \
+ -1)
+
if (!str) {
if (badcheck) goto bad;
return INT2FIX(0);
@@ -422,8 +463,21 @@ rb_cstr_to_inum(str, base, badcheck)
break;
}
if (*str == '0') { /* squeeze preceeding 0s */
- while (*++str == '0');
- --str;
+ int us = 0;
+ while ((c = *++str) == '0' || c == '_') {
+ if (c == '_') {
+ if (++us >= 2)
+ break;
+ } else
+ us = 0;
+ }
+ if (!(c = *str) || ISSPACE(c)) --str;
+ }
+ c = *str;
+ c = conv_digit(c);
+ if (c < 0 || c >= base) {
+ if (badcheck) goto bad;
+ return INT2FIX(0);
}
len *= strlen(str)*sizeof(char);
@@ -457,27 +511,16 @@ rb_cstr_to_inum(str, base, badcheck)
z = bignew(len, sign);
zds = BDIGITS(z);
for (i=len;i--;) zds[i]=0;
- while (c = *str++) {
+ while ((c = *str++) != 0) {
if (c == '_') {
- if (badcheck) {
- if (nondigit) goto bad;
- nondigit = c;
+ if (nondigit) {
+ if (badcheck) goto bad;
+ break;
}
+ nondigit = c;
continue;
}
- else if (!ISASCII(c)) {
- break;
- }
- else if (isdigit(c)) {
- c -= '0';
- }
- else if (islower(c)) {
- c -= 'a' - 10;
- }
- else if (isupper(c)) {
- c -= 'A' - 10;
- }
- else {
+ else if ((c = conv_digit(c)) < 0) {
break;
}
if (c >= base) break;
@@ -536,7 +579,7 @@ rb_str_to_inum(str, base, badcheck)
s = p;
}
}
- return rb_cstr_to_inum(s, base, badcheck);
+ return rb_cstr_to_inum(s, base, badcheck);
}
#if HAVE_LONG_LONG
@@ -598,7 +641,7 @@ rb_ll2inum(n)
}
#endif /* HAVE_LONG_LONG */
-
+
VALUE
rb_cstr2inum(str, base)
const char *str;
@@ -617,15 +660,16 @@ rb_str2inum(str, base)
const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
VALUE
-rb_big2str(x, base)
+rb_big2str0(x, base, trim)
VALUE x;
int base;
+ int trim;
{
volatile VALUE t;
BDIGIT *ds;
long i, j, hbase;
VALUE ss;
- char *s, c;
+ char *s;
if (FIXNUM_P(x)) {
return rb_fix2str(x, base);
@@ -634,34 +678,37 @@ rb_big2str(x, base)
if (BIGZEROP(x)) {
return rb_str_new2("0");
}
+ if (i >= LONG_MAX/SIZEOF_BDIGITS/CHAR_BIT) {
+ rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
+ }
j = SIZEOF_BDIGITS*CHAR_BIT*i;
switch (base) {
case 2: break;
case 3:
- j = j * 647L / 1024;
+ j = j * 53L / 84 + 1;
break;
case 4: case 5: case 6: case 7:
- j /= 2;
+ j = (j + 1) / 2;
break;
case 8: case 9:
- j /= 3;
+ j = (j + 2) / 3;
break;
case 10: case 11: case 12: case 13: case 14: case 15:
- j = j * 241L / 800;
+ j = j * 28L / 93 + 1;
break;
case 16: case 17: case 18: case 19: case 20: case 21:
case 22: case 23: case 24: case 25: case 26: case 27:
case 28: case 29: case 30: case 31:
- j /= 4;
+ j = (j + 3) / 4;
break;
case 32: case 33: case 34: case 35: case 36:
- j /= 5;
+ j = (j + 4) / 5;
break;
default:
rb_raise(rb_eArgError, "illegal radix %d", base);
break;
}
- j += 2;
+ j++; /* space for sign */
hbase = base * base;
#if SIZEOF_BDIGITS > 2
@@ -670,11 +717,12 @@ rb_big2str(x, base)
t = rb_big_clone(x);
ds = BDIGITS(t);
- ss = rb_str_new(0, j);
+ ss = rb_str_new(0, j+1);
s = RSTRING(ss)->ptr;
s[0] = RBIGNUM(x)->sign ? '+' : '-';
- while (i && j) {
+ TRAP_BEG;
+ while (i && j > 1) {
long k = i;
BDIGIT_DBL num = 0;
@@ -683,30 +731,44 @@ rb_big2str(x, base)
ds[k] = (BDIGIT)(num / hbase);
num %= hbase;
}
- if (ds[i-1] == 0) i--;
+ if (trim && ds[i-1] == 0) i--;
k = SIZEOF_BDIGITS;
while (k--) {
- c = (char)(num % base);
- s[--j] = ruby_digitmap[(int)c];
+ s[--j] = ruby_digitmap[num % base];
num /= base;
- if (i == 0 && num == 0) break;
+ if (!trim && j <= 1) break;
+ if (trim && i == 0 && num == 0) break;
}
}
- while (s[j] == '0') j++;
- RSTRING(ss)->len -= RBIGNUM(x)->sign?j:j-1;
- memmove(RBIGNUM(x)->sign?s:s+1, s+j, RSTRING(ss)->len);
+ if (trim) {while (s[j] == '0') j++;}
+ i = RSTRING(ss)->len - j;
+ if (RBIGNUM(x)->sign) {
+ memmove(s, s+j, i);
+ RSTRING(ss)->len = i-1;
+ }
+ else {
+ memmove(s+1, s+j, i);
+ RSTRING(ss)->len = i;
+ }
s[RSTRING(ss)->len] = '\0';
+ TRAP_END;
return ss;
}
+VALUE
+rb_big2str(VALUE x, int base)
+{
+ return rb_big2str0(x, base, Qtrue);
+}
+
/*
* call-seq:
* big.to_s(base=10) => string
- *
+ *
* Returns a string containing the representation of <i>big</i> radix
* <i>base</i> (2 through 36).
- *
+ *
* 12345654321.to_s #=> "12345654321"
* 12345654321.to_s(2) #=> "1011011111110110111011110000110001"
* 12345654321.to_s(8) #=> "133766736061"
@@ -750,15 +812,15 @@ big2ulong(x, type)
}
unsigned long
-rb_big2ulong_pack(x)
- VALUE x;
-{
+rb_big2ulong_pack(x)
+ VALUE x;
+{
unsigned long num = big2ulong(x, "unsigned long");
if (!RBIGNUM(x)->sign) {
return -num;
}
return num;
-}
+}
unsigned long
rb_big2ulong(x)
@@ -876,8 +938,8 @@ rb_dbl2big(d)
return bignorm(dbl2big(d));
}
-double
-rb_big2dbl(x)
+static double
+big2dbl(x)
VALUE x;
{
double d = 0.0;
@@ -887,21 +949,30 @@ rb_big2dbl(x)
while (i--) {
d = ds[i] + BIGRAD*d;
}
+ if (!RBIGNUM(x)->sign) d = -d;
+ return d;
+}
+
+double
+rb_big2dbl(x)
+ VALUE x;
+{
+ double d = big2dbl(x);
+
if (isinf(d)) {
rb_warn("Bignum out of Float range");
d = HUGE_VAL;
}
- if (!RBIGNUM(x)->sign) d = -d;
return d;
}
/*
* call-seq:
* big.to_f -> float
- *
+ *
* Converts <i>big</i> to a <code>Float</code>. If <i>big</i> doesn't
* fit in a <code>Float</code>, the result is infinity.
- *
+ *
*/
static VALUE
@@ -914,11 +985,11 @@ rb_big_to_f(x)
/*
* call-seq:
* big <=> numeric => -1, 0, +1
- *
+ *
* Comparison---Returns -1, 0, or +1 depending on whether <i>big</i> is
* less than, equal to, or greater than <i>numeric</i>. This is the
* basis for the tests in <code>Comparable</code>.
- *
+ *
*/
static VALUE
@@ -959,11 +1030,11 @@ rb_big_cmp(x, y)
/*
* call-seq:
* big == obj => true or false
- *
+ *
* Returns <code>true</code> only if <i>obj</i> has the same value
* as <i>big</i>. Contrast this with <code>Bignum#eql?</code>, which
* requires <i>obj</i> to be a <code>Bignum</code>.
- *
+ *
* 68719476736 == 68719476736.0 #=> true
*/
@@ -998,11 +1069,11 @@ rb_big_eq(x, y)
/*
* call-seq:
* big.eql?(obj) => true or false
- *
+ *
* Returns <code>true</code> only if <i>obj</i> is a
* <code>Bignum</code> with the same value as <i>big</i>. Contrast this
* with <code>Bignum#==</code>, which performs type conversions.
- *
+ *
* 68719476736.eql?(68719476736.0) #=> false
*/
@@ -1043,7 +1114,7 @@ rb_big_uminus(x)
* length, the result acts as if it had an infinite number of one
* bits to the left. In hex representations, this is displayed
* as two periods to the left of the digits.
- *
+ *
* sprintf("%X", ~0x1122334455) #=> "..FEEDDCCBBAA"
*/
@@ -1058,6 +1129,7 @@ rb_big_neg(x)
if (!RBIGNUM(x)->sign) get2comp(z);
ds = BDIGITS(z);
i = RBIGNUM(x)->len;
+ if (!i) return INT2FIX(~0);
while (i--) ds[i] = ~ds[i];
RBIGNUM(z)->sign = !RBIGNUM(z)->sign;
if (RBIGNUM(x)->sign) get2comp(z);
@@ -1073,7 +1145,7 @@ bigsub(x, y)
BDIGIT *zds;
BDIGIT_DBL_SIGNED num;
long i = RBIGNUM(x)->len;
-
+
/* if x is larger than y, swap */
if (RBIGNUM(x)->len < RBIGNUM(y)->len) {
z = x; x = y; y = z; /* swap x y */
@@ -1094,11 +1166,11 @@ bigsub(x, y)
z = bignew(RBIGNUM(x)->len, z==0);
zds = BDIGITS(z);
- for (i = 0, num = 0; i < RBIGNUM(y)->len; i++) {
+ for (i = 0, num = 0; i < RBIGNUM(y)->len; i++) {
num += (BDIGIT_DBL_SIGNED)BDIGITS(x)[i] - BDIGITS(y)[i];
zds[i] = BIGLO(num);
num = BIGDN(num);
- }
+ }
while (num && i < RBIGNUM(x)->len) {
num += BDIGITS(x)[i];
zds[i++] = BIGLO(num);
@@ -1108,7 +1180,7 @@ bigsub(x, y)
zds[i] = BDIGITS(x)[i];
i++;
}
-
+
return z;
}
@@ -1209,15 +1281,8 @@ rb_big_minus(x, y)
}
}
-/*
- * call-seq:
- * big * other => Numeric
- *
- * Multiplies big and other, returning the result.
- */
-
VALUE
-rb_big_mul(x, y)
+rb_big_mul0(x, y)
VALUE x, y;
{
long i, j;
@@ -1246,7 +1311,7 @@ rb_big_mul(x, y)
zds = BDIGITS(z);
while (j--) zds[j] = 0;
for (i = 0; i < RBIGNUM(x)->len; i++) {
- BDIGIT_DBL dd = BDIGITS(x)[i];
+ BDIGIT_DBL dd = BDIGITS(x)[i];
if (dd == 0) continue;
n = 0;
for (j = 0; j < RBIGNUM(y)->len; j++) {
@@ -1260,7 +1325,21 @@ rb_big_mul(x, y)
}
}
- return bignorm(z);
+ return z;
+}
+
+/*
+ * call-seq:
+ * big * other => Numeric
+ *
+ * Multiplies big and other, returning the result.
+ */
+
+VALUE
+rb_big_mul(x, y)
+ VALUE x, y;
+{
+ return bignorm(rb_big_mul0(x, y));
}
static void
@@ -1309,7 +1388,7 @@ bigdivrem(x, y, divp, modp)
dd = 0;
q = yds[ny-1];
- while ((q & (1<<(BITSPERDIG-1))) == 0) {
+ while ((q & (1U<<(BITSPERDIG-1))) == 0) {
q <<= 1;
dd++;
}
@@ -1433,9 +1512,6 @@ rb_big_div(x, y)
case T_BIGNUM:
break;
- case T_FLOAT:
- return rb_float_new(rb_big2dbl(x) / RFLOAT(y)->value);
-
default:
return rb_num_coerce_bin(x, y);
}
@@ -1478,9 +1554,9 @@ rb_big_modulo(x, y)
/*
* call-seq:
* big.remainder(numeric) => number
- *
+ *
* Returns the remainder after dividing <i>big</i> by <i>numeric</i>.
- *
+ *
* -1234567890987654321.remainder(13731) #=> -6966
* -1234567890987654321.remainder(13731.24) #=> -9906.22531493148
*/
@@ -1506,12 +1582,47 @@ rb_big_remainder(x, y)
return bignorm(z);
}
+static int
+bdigbitsize(BDIGIT x)
+{
+ int size = 1;
+ int nb = BITSPERDIG / 2;
+ BDIGIT bits = (~0 << nb);
+
+ if (!x) return 0;
+ while (x > 1) {
+ if (x & bits) {
+ size += nb;
+ x >>= nb;
+ }
+ x &= ~bits;
+ nb /= 2;
+ bits >>= nb;
+ }
+
+ return size;
+}
+
+static VALUE big_lshift _((VALUE, unsigned long));
+static VALUE big_rshift _((VALUE, unsigned long));
+
+static VALUE big_shift(x, n)
+ VALUE x;
+ int n;
+{
+ if (n < 0)
+ return big_lshift(x, (unsigned int)n);
+ else if (n > 0)
+ return big_rshift(x, (unsigned int)n);
+ return x;
+}
+
/*
* call-seq:
* big.divmod(numeric) => array
- *
+ *
* See <code>Numeric#divmod</code>.
- *
+ *
*/
VALUE
rb_big_divmod(x, y)
@@ -1538,22 +1649,51 @@ rb_big_divmod(x, y)
/*
* call-seq:
* big.quo(numeric) -> float
- *
+ * big.fdiv(numeric) -> float
+ *
* Returns the floating point result of dividing <i>big</i> by
* <i>numeric</i>.
- *
+ *
* -1234567890987654321.quo(13731) #=> -89910996357705.5
* -1234567890987654321.quo(13731.24) #=> -89909424858035.7
- *
+ *
*/
static VALUE
rb_big_quo(x, y)
VALUE x, y;
{
- double dx = rb_big2dbl(x);
+ double dx = big2dbl(x);
double dy;
+ if (isinf(dx)) {
+#define DBL_BIGDIG ((DBL_MANT_DIG + BITSPERDIG) / BITSPERDIG)
+ VALUE z;
+ int ex, ey;
+
+ ex = (RBIGNUM(bigtrunc(x))->len - 1) * BITSPERDIG;
+ ex += bdigbitsize(BDIGITS(x)[RBIGNUM(x)->len - 1]);
+ ex -= 2 * DBL_BIGDIG * BITSPERDIG;
+ if (ex) x = big_shift(x, ex);
+
+ switch (TYPE(y)) {
+ case T_FIXNUM:
+ y = rb_int2big(FIX2LONG(y));
+ case T_BIGNUM: {
+ ey = (RBIGNUM(bigtrunc(y))->len - 1) * BITSPERDIG;
+ ey += bdigbitsize(BDIGITS(y)[RBIGNUM(y)->len - 1]);
+ ey -= DBL_BIGDIG * BITSPERDIG;
+ if (ey) y = big_shift(y, ey);
+ bignum:
+ bigdivrem(x, y, &z, 0);
+ return rb_float_new(ldexp(big2dbl(z), ex - ey));
+ }
+ case T_FLOAT:
+ y = dbl2big(ldexp(frexp(RFLOAT(y)->value, &ey), DBL_MANT_DIG));
+ ey -= DBL_MANT_DIG;
+ goto bignum;
+ }
+ }
switch (TYPE(y)) {
case T_FIXNUM:
dy = (double)FIX2LONG(y);
@@ -1573,6 +1713,52 @@ rb_big_quo(x, y)
return rb_float_new(dx / dy);
}
+static VALUE
+bigsqr(x)
+ VALUE x;
+{
+ long len = RBIGNUM(x)->len, k = len / 2, i;
+ VALUE a, b, a2, z;
+ BDIGIT_DBL num;
+
+ if (len < 4000 / BITSPERDIG) {
+ return rb_big_mul0(x, x);
+ }
+
+ a = bignew(len - k, 1);
+ MEMCPY(BDIGITS(a), BDIGITS(x) + k, BDIGIT, len - k);
+ b = bignew(k, 1);
+ MEMCPY(BDIGITS(b), BDIGITS(x), BDIGIT, k);
+
+ a2 = bigtrunc(bigsqr(a));
+ z = bigsqr(b);
+ REALLOC_N(RBIGNUM(z)->digits, BDIGIT, (len = 2 * k + RBIGNUM(a2)->len) + 1);
+ while (RBIGNUM(z)->len < 2 * k) BDIGITS(z)[RBIGNUM(z)->len++] = 0;
+ MEMCPY(BDIGITS(z) + 2 * k, BDIGITS(a2), BDIGIT, RBIGNUM(a2)->len);
+ RBIGNUM(z)->len = len;
+ a2 = bigtrunc(rb_big_mul0(a, b));
+ len = RBIGNUM(a2)->len;
+ TRAP_BEG;
+ for (i = 0, num = 0; i < len; i++) {
+ num += (BDIGIT_DBL)BDIGITS(z)[i + k] + ((BDIGIT_DBL)BDIGITS(a2)[i] << 1);
+ BDIGITS(z)[i + k] = BIGLO(num);
+ num = BIGDN(num);
+ }
+ TRAP_END;
+ if (num) {
+ len = RBIGNUM(z)->len;
+ for (i += k; i < len && num; ++i) {
+ num += (BDIGIT_DBL)BDIGITS(z)[i];
+ BDIGITS(z)[i] = BIGLO(num);
+ num = BIGDN(num);
+ }
+ if (num) {
+ BDIGITS(z)[RBIGNUM(z)->len++] = BIGLO(num);
+ }
+ }
+ return bigtrunc(z);
+}
+
/*
* call-seq:
* big ** exponent #=> numeric
@@ -1592,7 +1778,7 @@ rb_big_pow(x, y)
{
double d;
long yy;
-
+
if (y == INT2FIX(0)) return INT2FIX(1);
switch (TYPE(y)) {
case T_FLOAT:
@@ -1607,21 +1793,21 @@ rb_big_pow(x, y)
case T_FIXNUM:
yy = FIX2LONG(y);
if (yy > 0) {
- VALUE z = x;
+ VALUE z = 0;
+ long mask;
+ const long BIGLEN_LIMIT = 1024*1024 / SIZEOF_BDIGITS;
- if (RBIGNUM(x)->len * SIZEOF_BDIGITS * yy > 1024*1024) {
+ if ((RBIGNUM(x)->len > BIGLEN_LIMIT) ||
+ (RBIGNUM(x)->len > BIGLEN_LIMIT / yy)) {
rb_warn("in a**b, b may be too big");
d = (double)yy;
break;
}
- for (;;) {
- yy -= 1;
- if (yy == 0) break;
- while (yy % 2 == 0) {
- yy /= 2;
- x = rb_big_mul(x, x);
+ for (mask = FIXNUM_MAX + 1; mask; mask >>= 1) {
+ if (z) z = bigtrunc(bigsqr(z));
+ if (yy & mask) {
+ z = z ? bigtrunc(rb_big_mul0(z, x)) : x;
}
- z = rb_big_mul(z, x);
}
return bignorm(z);
}
@@ -1807,7 +1993,15 @@ rb_big_xor(xx, yy)
return bignorm(z);
}
-static VALUE rb_big_rshift _((VALUE,VALUE));
+static VALUE
+check_shiftdown(VALUE y, VALUE x)
+{
+ if (!RBIGNUM(x)->len) return INT2FIX(0);
+ if (RBIGNUM(y)->len > SIZEOF_LONG / SIZEOF_BDIGITS) {
+ return RBIGNUM(x)->sign ? INT2FIX(0) : INT2FIX(-1);
+ }
+ return Qnil;
+}
/*
* call-seq:
@@ -1820,15 +2014,46 @@ VALUE
rb_big_lshift(x, y)
VALUE x, y;
{
+ long shift;
+ int neg = 0;
+
+ for (;;) {
+ if (FIXNUM_P(y)) {
+ shift = FIX2LONG(y);
+ if (shift < 0) {
+ neg = 1;
+ shift = -shift;
+ }
+ break;
+ }
+ else if (TYPE(y) == T_BIGNUM) {
+ if (!RBIGNUM(y)->sign) {
+ VALUE t = check_shiftdown(y, x);
+ if (!NIL_P(t)) return t;
+ neg = 1;
+ }
+ shift = big2ulong(y, "long");
+ break;
+ }
+ y = rb_to_int(y);
+ }
+
+ if (neg) return big_rshift(x, shift);
+ return big_lshift(x, shift);
+}
+
+static VALUE
+big_lshift(x, shift)
+ VALUE x;
+ unsigned long shift;
+{
BDIGIT *xds, *zds;
- int shift = NUM2INT(y);
- int s1 = shift/BITSPERDIG;
+ long s1 = shift/BITSPERDIG;
int s2 = shift%BITSPERDIG;
VALUE z;
BDIGIT_DBL num = 0;
long len, i;
- if (shift < 0) return rb_big_rshift(x, INT2FIX(-shift));
len = RBIGNUM(x)->len;
z = bignew(len+s1+1, RBIGNUM(x)->sign);
zds = BDIGITS(z);
@@ -1852,21 +2077,53 @@ rb_big_lshift(x, y)
* Shifts big right _numeric_ positions (left if _numeric_ is negative).
*/
-static VALUE
+VALUE
rb_big_rshift(x, y)
VALUE x, y;
{
+ long shift;
+ int neg = 0;
+
+ for (;;) {
+ if (FIXNUM_P(y)) {
+ shift = FIX2LONG(y);
+ if (shift < 0) {
+ neg = 1;
+ shift = -shift;
+ }
+ break;
+ }
+ else if (TYPE(y) == T_BIGNUM) {
+ if (RBIGNUM(y)->sign) {
+ VALUE t = check_shiftdown(y, x);
+ if (!NIL_P(t)) return t;
+ }
+ else {
+ neg = 1;
+ }
+ shift = big2ulong(y, "long");
+ break;
+ }
+ y = rb_to_int(y);
+ }
+
+ if (neg) return big_lshift(x, shift);
+ return big_rshift(x, shift);
+}
+
+static VALUE
+big_rshift(x, shift)
+ VALUE x;
+ unsigned long shift;
+{
BDIGIT *xds, *zds;
- int shift = NUM2INT(y);
long s1 = shift/BITSPERDIG;
- long s2 = shift%BITSPERDIG;
+ int s2 = shift%BITSPERDIG;
VALUE z;
BDIGIT_DBL num = 0;
long i, j;
volatile VALUE save_x;
- if (shift < 0) return rb_big_lshift(x, INT2FIX(-shift));
-
if (s1 > RBIGNUM(x)->len) {
if (RBIGNUM(x)->sign)
return INT2FIX(0);
@@ -1879,6 +2136,10 @@ rb_big_rshift(x, y)
}
xds = BDIGITS(x);
i = RBIGNUM(x)->len; j = i - s1;
+ if (j == 0) {
+ if (RBIGNUM(x)->sign) return INT2FIX(0);
+ else return INT2FIX(-1);
+ }
z = bignew(j, RBIGNUM(x)->sign);
if (!RBIGNUM(x)->sign) {
num = ((BDIGIT_DBL)~0) << BITSPERDIG;
@@ -1898,20 +2159,20 @@ rb_big_rshift(x, y)
/*
* call-seq:
* big[n] -> 0, 1
- *
+ *
* Bit Reference---Returns the <em>n</em>th bit in the (assumed) binary
* representation of <i>big</i>, where <i>big</i>[0] is the least
* significant bit.
- *
+ *
* a = 9**15
* 50.downto(0) do |n|
* print a[n]
* end
- *
+ *
* <em>produces:</em>
- *
+ *
* 000101110110100000111000011110010100111100010111001
- *
+ *
*/
static VALUE
@@ -1919,29 +2180,39 @@ rb_big_aref(x, y)
VALUE x, y;
{
BDIGIT *xds;
- int shift;
- long s1, s2;
+ BDIGIT_DBL num;
+ unsigned long shift;
+ long i, s1, s2;
if (TYPE(y) == T_BIGNUM) {
- if (!RBIGNUM(y)->sign || RBIGNUM(x)->sign)
+ if (!RBIGNUM(y)->sign)
return INT2FIX(0);
- return INT2FIX(1);
+ if (RBIGNUM(bigtrunc(y))->len > SIZEOF_LONG/SIZEOF_BDIGITS) {
+ out_of_range:
+ return RBIGNUM(x)->sign ? INT2FIX(0) : INT2FIX(1);
+ }
+ shift = big2ulong(y, "long");
+ }
+ else {
+ i = NUM2LONG(y);
+ if (i < 0) return INT2FIX(0);
+ shift = (VALUE)i;
}
- shift = NUM2INT(y);
- if (shift < 0) return INT2FIX(0);
s1 = shift/BITSPERDIG;
s2 = shift%BITSPERDIG;
+ if (s1 >= RBIGNUM(x)->len) goto out_of_range;
if (!RBIGNUM(x)->sign) {
- if (s1 >= RBIGNUM(x)->len) return INT2FIX(1);
- x = rb_big_clone(x);
- get2comp(x);
+ xds = BDIGITS(x);
+ i = 0; num = 1;
+ while (num += ~xds[i], ++i <= s1) {
+ num = BIGDN(num);
+ }
}
else {
- if (s1 >= RBIGNUM(x)->len) return INT2FIX(0);
+ num = BDIGITS(x)[s1];
}
- xds = BDIGITS(x);
- if (xds[s1] & (1<<s2))
+ if (num & ((BDIGIT_DBL)1<<s2))
return INT2FIX(1);
return INT2FIX(0);
}
@@ -1992,9 +2263,9 @@ rb_big_coerce(x, y)
/*
* call-seq:
* big.abs -> aBignum
- *
+ *
* Returns the absolute value of <i>big</i>.
- *
+ *
* -1234567890987654321.abs #=> 1234567890987654321
*/
@@ -2022,7 +2293,7 @@ rb_big_rand(max, rand_buf)
}
v = bignew(len,1);
len--;
- BDIGITS(v)[len] = BDIGITS(max)[len] * rand_buf[len];
+ BDIGITS(v)[len] = BDIGITS(max)[len] * rand_buf[len];
while (len--) {
BDIGITS(v)[len] = ((BDIGIT)~0) * rand_buf[len];
}
@@ -2033,10 +2304,10 @@ rb_big_rand(max, rand_buf)
/*
* call-seq:
* big.size -> integer
- *
+ *
* Returns the number of bytes in the machine representation of
* <i>big</i>.
- *
+ *
* (256**10 - 1).size #=> 12
* (256**20 - 1).size #=> 20
* (256**40 - 1).size #=> 40
@@ -2056,15 +2327,15 @@ rb_big_size(big)
* Fixnum. When a calculation involving
* Bignum objects returns a result that will fit in a
* Fixnum, the result is automatically converted.
- *
+ *
* For the purposes of the bitwise operations and <code>[]</code>, a
* Bignum is treated as if it were an infinite-length
* bitstring with 2's complement representation.
- *
+ *
* While Fixnum values are immediate, Bignum
* objects are not---assignment and parameter passing work with
* references to objects, not the objects themselves.
- *
+ *
*/
void
@@ -2085,6 +2356,7 @@ Init_Bignum()
rb_define_method(rb_cBignum, "modulo", rb_big_modulo, 1);
rb_define_method(rb_cBignum, "remainder", rb_big_remainder, 1);
rb_define_method(rb_cBignum, "quo", rb_big_quo, 1);
+ rb_define_method(rb_cBignum, "fdiv", rb_big_quo, 1);
rb_define_method(rb_cBignum, "**", rb_big_pow, 1);
rb_define_method(rb_cBignum, "&", rb_big_and, 1);
rb_define_method(rb_cBignum, "|", rb_big_or, 1);
diff --git a/bin/irb b/bin/irb
index 13474a932b..f277bc4b69 100644
--- a/bin/irb
+++ b/bin/irb
@@ -2,8 +2,8 @@
#
# irb.rb - intaractive ruby
# $Release Version: 0.9.5 $
-# $Revision: 1.2.2.1 $
-# $Date: 2005/04/19 19:24:56 $
+# $Revision$
+# $Date$
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
#
diff --git a/bin/rdoc b/bin/rdoc
index d08ce838f6..fe619137fd 100644
--- a/bin/rdoc
+++ b/bin/rdoc
@@ -6,7 +6,7 @@
# Copyright (c) 2003 Dave Thomas
# Released under the same terms as Ruby
#
-# $Revision: 1.1 $
+# $Revision$
## Transitional Hack ####
#
diff --git a/class.c b/class.c
index 9e41b1e260..80f57a1622 100644
--- a/class.c
+++ b/class.c
@@ -2,8 +2,8 @@
class.c -
- $Author: nobu $
- $Date: 2005/09/28 14:42:46 $
+ $Author$
+ $Date$
created at: Tue Aug 10 15:05:44 JST 1993
Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -48,13 +48,26 @@ rb_class_new(super)
return rb_class_boot(super);
}
+struct clone_method_data {
+ st_table *tbl;
+ VALUE klass;
+};
+
static int
-clone_method(mid, body, tbl)
+clone_method(mid, body, data)
ID mid;
NODE *body;
- st_table *tbl;
+ struct clone_method_data *data;
{
- st_insert(tbl, mid, (st_data_t)NEW_METHOD(body->nd_body, body->nd_noex));
+ NODE *fbody = body->nd_body;
+
+ if (fbody && nd_type(fbody) == NODE_SCOPE) {
+ NODE *cref = (NODE*)fbody->nd_rval;
+
+ if (cref) cref = cref->nd_next;
+ fbody = rb_copy_node_scope(fbody, NEW_CREF(data->klass, cref));
+ }
+ st_insert(data->tbl, mid, (st_data_t)NEW_METHOD(fbody, body->nd_noex));
return ST_CONTINUE;
}
@@ -65,7 +78,8 @@ rb_mod_init_copy(clone, orig)
{
rb_obj_init_copy(clone, orig);
if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
- RBASIC(clone)->klass = rb_singleton_class_clone(orig);
+ RBASIC(clone)->klass = RBASIC(orig)->klass;
+ RBASIC(clone)->klass = rb_singleton_class_clone(clone);
}
RCLASS(clone)->super = RCLASS(orig)->super;
if (RCLASS(orig)->iv_tbl) {
@@ -78,9 +92,12 @@ rb_mod_init_copy(clone, orig)
st_delete(RCLASS(clone)->iv_tbl, (st_data_t*)&id, 0);
}
if (RCLASS(orig)->m_tbl) {
- RCLASS(clone)->m_tbl = st_init_numtable();
- st_foreach(RCLASS(orig)->m_tbl, clone_method,
- (st_data_t)RCLASS(clone)->m_tbl);
+ struct clone_method_data data;
+
+ data.tbl = RCLASS(clone)->m_tbl = st_init_numtable();
+ data.klass = (VALUE)clone;
+
+ st_foreach(RCLASS(orig)->m_tbl, clone_method, (st_data_t)&data);
}
return clone;
@@ -126,9 +143,22 @@ rb_singleton_class_clone(obj)
if (RCLASS(klass)->iv_tbl) {
clone->iv_tbl = st_copy(RCLASS(klass)->iv_tbl);
}
- clone->m_tbl = st_init_numtable();
- st_foreach(RCLASS(klass)->m_tbl, clone_method,
- (st_data_t)clone->m_tbl);
+ {
+ struct clone_method_data data;
+
+ data.tbl = clone->m_tbl = st_init_numtable();
+ switch (TYPE(obj)) {
+ case T_CLASS:
+ case T_MODULE:
+ data.klass = obj;
+ break;
+ default:
+ data.klass = 0;
+ break;
+ }
+
+ st_foreach(RCLASS(klass)->m_tbl, clone_method, (st_data_t)&data);
+ }
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
FL_SET(clone, FL_SINGLETON);
return (VALUE)clone;
@@ -379,9 +409,6 @@ rb_include_module(klass, module)
rb_secure(4);
}
- if (NIL_P(module)) return;
- if (klass == module) return;
-
if (TYPE(module) != T_MODULE) {
Check_Type(module, T_MODULE);
}
diff --git a/common.mk b/common.mk
index 3584b83e35..bf49aade4a 100644
--- a/common.mk
+++ b/common.mk
@@ -1,13 +1,20 @@
bin: $(PROGRAM) $(WPROGRAM)
-lib: $(LIBRUBY);
-dll: $(LIBRUBY_SO);
+lib: $(LIBRUBY)
+dll: $(LIBRUBY_SO)
-RUBYOPT =
+RUBYLIB = -
+RUBYOPT = -
+
+SPEC_GIT_BASE = git://github.com/rubyspec
+MSPEC_GIT_URL = $(SPEC_GIT_BASE)/mspec.git
+RUBYSPEC_GIT_URL = $(SPEC_GIT_BASE)/rubyspec.git
STATIC_RUBY = static-ruby
EXTCONF = extconf.rb
RBCONFIG = ./.rbconfig.time
+LIBRUBY_EXTS = ./.libruby-with-ext.time
+RDOCOUT = $(EXTOUT)/rdoc
DMYEXT = dmyext.$(OBJEXT)
MAINOBJ = main.$(OBJEXT)
@@ -21,6 +28,7 @@ OBJS = array.$(OBJEXT) \
dir.$(OBJEXT) \
dln.$(OBJEXT) \
enum.$(OBJEXT) \
+ enumerator.$(OBJEXT) \
error.$(OBJEXT) \
eval.$(OBJEXT) \
file.$(OBJEXT) \
@@ -53,13 +61,25 @@ OBJS = array.$(OBJEXT) \
$(MISSING)
SCRIPT_ARGS = --dest-dir="$(DESTDIR)" \
- --make="$(MAKE)" \
+ --extout="$(EXTOUT)" \
--mflags="$(MFLAGS)" \
--make-flags="$(MAKEFLAGS)"
-EXTMK_ARGS = $(SCRIPT_ARGS) --extout="$(EXTOUT)" --extension $(EXTS) --extstatic $(EXTSTATIC) --
+EXTMK_ARGS = $(SCRIPT_ARGS) --extension $(EXTS) --extstatic $(EXTSTATIC) --
+INSTRUBY_ARGS = $(SCRIPT_ARGS) \
+ --data-mode=$(INSTALL_DATA_MODE) \
+ --prog-mode=$(INSTALL_PROG_MODE) \
+ --installed-list $(INSTALLED_LIST)
+INSTALL_PROG_MODE = 0755
+INSTALL_DATA_MODE = 0644
+
+PRE_LIBRUBY_UPDATE = $(MINIRUBY) -e 'ARGV[1] or File.unlink(ARGV[0]) rescue nil' -- \
+ $(LIBRUBY_EXTS) $(LIBRUBY_SO_UPDATE)
+
+TESTSDIR = $(srcdir)/test
+TESTWORKDIR = testwork
all: $(MKFILES) $(PREP) $(RBCONFIG) $(LIBRUBY)
- @$(MINIRUBY) $(srcdir)/ext/extmk.rb $(EXTMK_ARGS)
+ @$(MINIRUBY) $(srcdir)/ext/extmk.rb --make="$(MAKE)" $(EXTMK_ARGS)
prog: $(PROGRAM) $(WPROGRAM)
miniruby$(EXEEXT): config.status $(LIBRUBY_A) $(MAINOBJ) $(MINIOBJS) $(OBJS) $(DMYEXT)
@@ -68,7 +88,10 @@ $(PROGRAM): $(LIBRUBY) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(SETUP) $(PREP)
$(LIBRUBY_A): $(OBJS) $(DMYEXT) $(ARCHFILE)
-$(LIBRUBY_SO): $(OBJS) $(DLDOBJS) $(LIBRUBY_A) $(PREP)
+$(LIBRUBY_SO): $(OBJS) $(DLDOBJS) $(LIBRUBY_A) $(PREP) $(LIBRUBY_SO_UPDATE)
+
+$(LIBRUBY_EXTS):
+ @exit > $@
$(STATIC_RUBY)$(EXEEXT): $(MAINOBJ) $(DLDOBJS) $(EXTOBJS) $(LIBRUBY_A)
@$(RM) $@
@@ -80,64 +103,201 @@ ruby.imp: $(OBJS)
install: install-nodoc $(RDOCTARGET)
install-all: install-nodoc install-doc
-install-nodoc: install-local install-ext
+install-nodoc: pre-install-nodoc do-install-nodoc post-install-nodoc
+pre-install-nodoc:: pre-install-local pre-install-ext
+do-install-nodoc:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --mantype="$(MANTYPE)"
+post-install-nodoc:: post-install-local post-install-ext
+
install-local: pre-install-local do-install-local post-install-local
-install-ext: pre-install-ext do-install-ext post-install-ext
+pre-install-local:: pre-install-bin pre-install-lib pre-install-man
+do-install-local:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=local --mantype="$(MANTYPE)"
+loadpath: $(PREP)
+ $(MINIRUBY) -e 'p $$:'
-do-install-local: $(RBCONFIG)
- $(MINIRUBY) $(srcdir)/instruby.rb $(SCRIPT_ARGS) --mantype="$(MANTYPE)"
-do-install-ext: $(RBCONFIG)
- $(MINIRUBY) $(srcdir)/ext/extmk.rb $(EXTMK_ARGS) install
+post-install-local:: post-install-bin post-install-lib post-install-man
-install-bin: $(RBCONFIG)
- $(MINIRUBY) $(srcdir)/instruby.rb $(SCRIPT_ARGS) --install=bin
-install-lib: $(RBCONFIG)
- $(MINIRUBY) $(srcdir)/instruby.rb $(SCRIPT_ARGS) --install=lib
-install-man: $(RBCONFIG)
- $(MINIRUBY) $(srcdir)/instruby.rb $(SCRIPT_ARGS) --install=man --mantype="$(MANTYPE)"
+install-ext: pre-install-ext do-install-ext post-install-ext
+pre-install-ext:: pre-install-ext-arch pre-install-ext-comm
+do-install-ext:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=ext
+post-install-ext:: post-install-ext-arch post-install-ext-comm
+
+install-arch: pre-install-arch do-install-arch post-install-arch
+pre-install-arch:: pre-install-bin pre-install-ext-arch
+do-install-arch:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=bin --install=ext-arch
+post-install-arch:: post-install-bin post-install-ext-arch
+
+install-comm: pre-install-comm do-install-comm post-install-comm
+pre-install-comm:: pre-install-lib pre-install-ext-comm pre-install-man
+do-install-comm:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=lib --install=ext-comm --install=man
+post-install-comm:: post-install-lib post-install-ext-comm post-install-man
+
+install-bin: pre-install-bin do-install-bin post-install-bin
+pre-install-bin:: install-prereq
+do-install-bin:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=bin
+post-install-bin::
+ @$(NULLCMD)
+
+install-lib: pre-install-lib do-install-lib post-install-lib
+pre-install-lib:: install-prereq
+do-install-lib:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=lib
+post-install-lib::
+ @$(NULLCMD)
+
+install-ext-comm: pre-install-ext-comm do-install-ext-comm post-install-ext-comm
+pre-install-ext-comm:: install-prereq
+do-install-ext-comm:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=ext-comm
+post-install-ext-comm::
+ @$(NULLCMD)
+
+install-ext-arch: pre-install-ext-arch do-install-ext-arch post-install-ext-arch
+pre-install-ext-arch:: install-prereq
+do-install-ext-arch:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=ext-arch
+post-install-ext-arch::
+ @$(NULLCMD)
+
+install-man: pre-install-man do-install-man post-install-man
+pre-install-man:: install-prereq
+do-install-man:
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=man --mantype="$(MANTYPE)"
+post-install-man::
+ @$(NULLCMD)
+
+what-where: no-install
+no-install: no-install-nodoc no-install-doc
+what-where-all: no-install-all
+no-install-all: no-install-nodoc
+
+what-where-nodoc: no-install-nodoc
+no-install-nodoc: pre-no-install-nodoc dont-install-nodoc post-no-install-nodoc
+pre-no-install-nodoc:: pre-no-install-local pre-no-install-ext
+dont-install-nodoc:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --mantype="$(MANTYPE)"
+post-no-install-nodoc:: post-no-install-local post-no-install-ext
-what-where-all no-install-all: no-install no-install-doc
-what-where no-install: no-install-local no-install-ext
what-where-local: no-install-local
-no-install-local: $(RBCONFIG)
- $(MINIRUBY) $(srcdir)/instruby.rb -n $(SCRIPT_ARGS) --mantype="$(MANTYPE)"
-what-where-ext: no-install-ext
-no-install-ext: $(RBCONFIG)
- $(MINIRUBY) $(srcdir)/ext/extmk.rb -n $(EXTMK_ARGS) install
+no-install-local: pre-no-install-local dont-install-local post-no-install-local
+pre-no-install-local:: pre-no-install-bin pre-no-install-lib pre-no-install-man
+dont-install-local:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=local --mantype="$(MANTYPE)"
+post-no-install-local:: post-no-install-bin post-no-install-lib post-no-install-man
-install-doc: pre-install-doc do-install-doc post-install-doc
+what-where-ext: no-install-ext
+no-install-ext: pre-no-install-ext dont-install-ext post-no-install-ext
+pre-no-install-ext:: pre-no-install-ext-arch pre-no-install-ext-comm
+dont-install-ext:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=ext
+post-no-install-ext:: post-no-install-ext-arch post-no-install-ext-comm
+
+what-where-arch: no-install-arch
+no-install-arch: pre-no-install-arch dont-install-arch post-no-install-arch
+pre-no-install-arch:: pre-no-install-bin pre-no-install-ext-arch
+dont-install-arch:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=bin --install=ext-arch
+post-no-install-arch:: post-no-install-lib post-no-install-man post-no-install-ext-arch
+
+what-where-comm: no-install-comm
+no-install-comm: pre-no-install-comm dont-install-comm post-no-install-comm
+pre-no-install-comm:: pre-no-install-lib pre-no-install-ext-comm pre-no-install-man
+dont-install-comm:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=lib --install=ext-comm --install=man
+post-no-install-comm:: post-no-install-lib post-no-install-ext-comm post-no-install-man
+
+what-where-bin: no-install-bin
+no-install-bin: pre-no-install-bin dont-install-bin post-no-install-bin
+pre-no-install-bin:: install-prereq
+dont-install-bin:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=bin
+post-no-install-bin::
+ @$(NULLCMD)
+
+what-where-lib: no-install-lib
+no-install-lib: pre-no-install-lib dont-install-lib post-no-install-lib
+pre-no-install-lib:: install-prereq
+dont-install-lib:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=lib
+post-no-install-lib::
+ @$(NULLCMD)
+
+what-where-ext-comm: no-install-ext-comm
+no-install-ext-comm: pre-no-install-ext-comm dont-install-ext-comm post-no-install-ext-comm
+pre-no-install-ext-comm:: install-prereq
+dont-install-ext-comm:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=ext-comm
+post-no-install-ext-comm::
+ @$(NULLCMD)
+
+what-where-ext-arch: no-install-ext-arch
+no-install-ext-arch: pre-no-install-ext-arch dont-install-ext-arch post-no-install-ext-arch
+pre-no-install-ext-arch:: install-prereq
+dont-install-ext-arch:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=ext-arch
+post-no-install-ext-arch::
+ @$(NULLCMD)
+
+what-where-man: no-install-man
+no-install-man: pre-no-install-man dont-install-man post-no-install-man
+pre-no-install-man:: install-prereq
+dont-install-man:
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=man --mantype="$(MANTYPE)"
+post-no-install-man::
+ @$(NULLCMD)
+
+install-doc: rdoc pre-install-doc do-install-doc post-install-doc
+pre-install-doc:: install-prereq
do-install-doc: $(PROGRAM)
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=rdoc --rdoc-output="$(RDOCOUT)"
+post-install-doc::
+ @$(NULLCMD)
+
+rdoc: $(PROGRAM) PHONY
@echo Generating RDoc documentation
- $(RUNRUBY) "$(srcdir)/bin/rdoc" --all --ri --op "$(RIDATADIR)" "$(srcdir)"
+ $(RUNRUBY) "$(srcdir)/bin/rdoc" --all --ri --op "$(RDOCOUT)" "$(srcdir)"
+
+what-where-doc: no-install-doc
+no-install-doc: pre-no-install-doc dont-install-doc post-no-install-doc
+pre-no-install-doc:: install-prereq
+dont-install-doc::
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=rdoc --rdoc-output="$(RDOCOUT)"
+post-no-install-doc::
+ @$(NULLCMD)
-pre-install: pre-install-local pre-install-ext
-pre-install-local:: PHONY
- $(PREINSTALL)
-pre-install-ext:: PHONY
-pre-install-doc:: PHONY
+CLEAR_INSTALLED_LIST = clear-installed-list
-post-install: post-install-local post-install-ext
-post-install-local:: PHONY
-post-install-ext:: PHONY
-post-install-doc:: PHONY
+install-prereq: $(CLEAR_INSTALLED_LIST)
+
+clear-installed-list:
+ @exit > $(INSTALLED_LIST)
clean: clean-ext clean-local
clean-local::
- @$(RM) $(OBJS) $(MAINOBJ) $(WINMAINOBJ) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY) $(LIBRUBY_ALIASES)
- @$(RM) $(PROGRAM) $(WPROGRAM) miniruby$(EXEEXT) dmyext.$(OBJEXT) $(ARCHFILE)
+ @$(RM) $(OBJS) $(MINIOBJS) $(MAINOBJ) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY) $(LIBRUBY_ALIASES)
+ @$(RM) $(PROGRAM) $(WPROGRAM) miniruby$(EXEEXT) dmyext.$(OBJEXT) $(ARCHFILE) .*.time
+ @$(RM) y.tab.c y.output
clean-ext:
- @-$(MINIRUBY) $(srcdir)/ext/extmk.rb $(EXTMK_ARGS) clean
+ @-$(MINIRUBY) $(srcdir)/ext/extmk.rb --make="$(MAKE)" $(EXTMK_ARGS) clean
distclean: distclean-ext distclean-local
distclean-local:: clean-local
@$(RM) $(MKFILES) config.h rbconfig.rb
@$(RM) config.cache config.log config.status
- @$(RM) *~ *.bak *.stackdump core *.core gmon.out y.tab.c y.output $(PREP)
+ @$(RM) *~ *.bak *.stackdump core *.core gmon.out $(PREP)
distclean-ext:
- @-$(MINIRUBY) $(srcdir)/ext/extmk.rb $(EXTMK_ARGS) distclean
+ @-$(MINIRUBY) $(srcdir)/ext/extmk.rb --make="$(MAKE)" $(EXTMK_ARGS) distclean
-realclean:: distclean
+realclean:: realclean-ext realclean-local
+realclean-local:: distclean-local
@$(RM) parse.c lex.c
+realclean-ext::
+ @-$(MINIRUBY) $(srcdir)/ext/extmk.rb --make="$(MAKE)" $(EXTMK_ARGS) realclean
check: test test-all
@@ -145,10 +305,10 @@ test: miniruby$(EXEEXT) $(RBCONFIG) $(PROGRAM) PHONY
@$(MINIRUBY) $(srcdir)/rubytest.rb
test-all:
- $(RUNRUBY) -C "$(srcdir)/test" runner.rb --runner=$(TESTUI) $(TESTS)
+ $(RUNRUBY) "$(srcdir)/test/runner.rb" --basedir="$(TESTSDIR)" --runner=$(TESTUI) $(TESTS)
extconf:
- $(MINIRUBY) -I$(srcdir)/lib -run -e mkdir -- -p "$(EXTCONFDIR)"
+ $(MINIRUBY) -run -e mkdir -- -p "$(EXTCONFDIR)"
$(RUNRUBY) -C "$(EXTCONFDIR)" $(EXTCONF) $(EXTCONFARGS)
$(RBCONFIG): $(srcdir)/mkconfig.rb config.status $(PREP)
@@ -189,6 +349,8 @@ 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
+ $(CC) $(CFLAGS) -c $<
# when I use -I., there is confliction at "OpenFile"
# so, set . into environment varible "include"
@@ -200,7 +362,8 @@ array.$(OBJEXT): {$(VPATH)}array.c {$(VPATH)}ruby.h config.h \
{$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
{$(VPATH)}util.h {$(VPATH)}st.h
bignum.$(OBJEXT): {$(VPATH)}bignum.c {$(VPATH)}ruby.h config.h \
- {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}rubysig.h
class.$(OBJEXT): {$(VPATH)}class.c {$(VPATH)}ruby.h config.h \
{$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
{$(VPATH)}rubysig.h {$(VPATH)}node.h {$(VPATH)}st.h
@@ -212,13 +375,13 @@ dir.$(OBJEXT): {$(VPATH)}dir.c {$(VPATH)}ruby.h config.h \
dln.$(OBJEXT): {$(VPATH)}dln.c {$(VPATH)}ruby.h config.h \
{$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
{$(VPATH)}dln.h
-dmydln.$(OBJEXT): {$(VPATH)}dmydln.c {$(VPATH)}dln.c {$(VPATH)}ruby.h \
- config.h {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
- {$(VPATH)}dln.h
+dmydln.$(OBJEXT): {$(VPATH)}dmydln.c dln.$(OBJEXT)
dmyext.$(OBJEXT): {$(VPATH)}dmyext.c
enum.$(OBJEXT): {$(VPATH)}enum.c {$(VPATH)}ruby.h config.h \
{$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
{$(VPATH)}node.h {$(VPATH)}util.h
+enumerator.$(OBJEXT): {$(VPATH)}enumerator.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
error.$(OBJEXT): {$(VPATH)}error.c {$(VPATH)}ruby.h config.h \
{$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
{$(VPATH)}env.h {$(VPATH)}st.h
diff --git a/compar.c b/compar.c
index 3cd3216b77..1488b2c65d 100644
--- a/compar.c
+++ b/compar.c
@@ -2,8 +2,8 @@
compar.c -
- $Author: dave $
- $Date: 2003/12/19 00:01:18 $
+ $Author$
+ $Date$
created at: Thu Aug 26 14:39:48 JST 1993
Copyright (C) 1993-2003 Yukihiro Matsumoto
diff --git a/configure.in b/configure.in
index b3288f8c03..d922bd20da 100644
--- a/configure.in
+++ b/configure.in
@@ -44,10 +44,20 @@ fi
GNU_LD=$rb_cv_prog_gnu_ld
AC_SUBST(GNU_LD)])
+unset GREP_OPTIONS
rb_version=`grep RUBY_VERSION $srcdir/version.h`
MAJOR=`expr "$rb_version" : '#define RUBY_VERSION "\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*"'`
MINOR=`expr "$rb_version" : '#define RUBY_VERSION "[0-9][0-9]*\.\([0-9][0-9]*\)\.[0-9][0-9]*"'`
TEENY=`expr "$rb_version" : '#define RUBY_VERSION "[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\)"'`
+if test "$MAJOR" = ""; then
+ AC_MSG_ERROR(could not determine MAJOR number from version.h)
+fi
+if test "$MINOR" = ""; then
+ AC_MSG_ERROR(could not determine MINOR number from version.h)
+fi
+if test "$TEENY" = ""; then
+ AC_MSG_ERROR(could not determine TEENY number from version.h)
+fi
AC_SUBST(MAJOR)
AC_SUBST(MINOR)
AC_SUBST(TEENY)
@@ -75,6 +85,7 @@ AC_CANONICAL_TARGET
target_os=`echo $target_os | sed 's/linux-gnu$/linux/;s/linux-gnu/linux-/'`
ac_install_sh='' # unusable for extension libraries.
+ifelse(currently,disabled, [
dnl checks for fat-binary
AC_ARG_ENABLE(fat-binary,
[ --enable-fat-binary=ARCHS
@@ -128,6 +139,7 @@ if test "$fat_binary" != no; then
done
AC_DEFINE(NEXT_FAT_BINARY)
fi
+], [fat_binary=no])
case $target_cpu in
i?86) frame_address=yes;;
@@ -149,6 +161,11 @@ if test x"${build}" != x"${host}"; then
fi
AC_PROG_CC
AC_PROG_GCC_TRADITIONAL
+if test "$GCC" = yes; then
+ linker_flag=-Wl,
+else
+ linker_flag=
+fi
RUBY_PROG_GNU_LD
RUBY_CPPOUTFILE
@@ -229,7 +246,12 @@ else
fi
dnl check for large file stuff
+mv confdefs.h confdefs1.h
+: > confdefs.h
AC_SYS_LARGEFILE
+mv confdefs.h largefile.h
+mv confdefs1.h confdefs.h
+cat largefile.h >> confdefs.h
AC_CHECK_TYPES([long long, off_t])
@@ -286,16 +308,42 @@ if test "$rb_cv_stdarg" = yes; then
AC_DEFINE(HAVE_STDARG_PROTOTYPES)
fi
-AC_CACHE_CHECK([for noreturn], rb_cv_noreturn,
-[rb_cv_noreturn=x
-for mac in "x __attribute__ ((noreturn))" "__declspec(noreturn) x" x; do
+AC_DEFUN([RUBY_FUNC_ATTRIBUTE], [dnl
+m4_ifval([$2], dnl
+ [AS_VAR_PUSHDEF([attrib],[$2])], dnl
+ [AS_VAR_PUSHDEF([attrib],[FUNC_]AS_TR_CPP($1))] dnl
+)dnl
+m4_ifval([$3], dnl
+ [AS_VAR_PUSHDEF([rbcv],[$3])], dnl
+ [AS_VAR_PUSHDEF([rbcv],[rb_cv_func_][$1])]dnl
+)dnl
+AC_CACHE_CHECK(for [$1] function attribute, rbcv,
+[rbcv=x
+if test "${ac_c_werror_flag+set}"; then
+ rb_c_werror_flag="$ac_c_werror_flag"
+else
+ unset rb_c_werror_flag
+fi
+ac_c_werror_flag=yes
+for mac in "__attribute__ (($1)) x" "x __attribute__ (($1))" "__declspec($1) x" x; do
AC_TRY_COMPILE(
- [#define NORETURN(x) $mac
-NORETURN(void exit(int x));],
- [],
- [rb_cv_noreturn="$mac"; break])
-done])
-AC_DEFINE_UNQUOTED([NORETURN(x)], $rb_cv_noreturn)
+ [#define ]attrib[(x) $mac
+ ]attrib[(void conftest_attribute_check(void));], [],
+ [rbcv="$mac"; break])
+done
+if test "${rb_c_werror_flag+set}"; then
+ ac_c_werror_flag="$rb_c_werror_flag"
+else
+ unset ac_c_werror_flag
+fi
+])
+AC_DEFINE_UNQUOTED(attrib[(x)], $rbcv)
+AS_VAR_POPDEF([attrib])
+AS_VAR_POPDEF([rbcv])
+])
+
+RUBY_FUNC_ATTRIBUTE(noreturn, NORETURN)
+RUBY_FUNC_ATTRIBUTE(noinline, NOINLINE)
AC_CACHE_CHECK([for RUBY_EXTERN], rb_cv_ruby_extern,
[rb_cv_ruby_extern=no
@@ -324,28 +372,45 @@ AC_ARG_ENABLE(pthread,
[ --enable-pthread use pthread library.],
[enable_pthread=$enableval], [enable_pthread=no])
+AC_ARG_ENABLE(fastthread,
+ [ --disable-fastthread do not use the fastthread mutex], [
+ : handled by ext/thread/extconf.rb
+ ])
+
dnl Checks for libraries.
case "$target_os" in
nextstep*) ;;
openstep*) ;;
rhapsody*) ;;
-darwin*) LIBS="-lobjc $LIBS";;
+darwin*) LIBS="-lobjc $LIBS"
+ CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE"
+ AC_TRY_CPP([#include <AvailabilityMacros.h>
+ #if MAC_OS_X_VERSION_MAX_ALLOWED <= 1040
+ #error pre OS X 10.4
+ [!<===== pre OS X 10.4 =====>]
+ #endif
+ ],
+ [
+ test "x$target_cpu" = xpowerpc && ac_cv_header_ucontext_h=no
+ ],
+ [
+ AC_DEFINE(BROKEN_SETREUID, 1)
+ AC_DEFINE(BROKEN_SETREGID, 1)
+ ])
+ ;;
hpux*) LIBS="-lm $LIBS"
ac_cv_c_inline=no;;
human*) ac_cv_func_getpgrp_void=yes
ac_cv_func_setitimer=no
;;
beos*) ac_cv_func_link=no;;
-cygwin*) rb_cv_have_daylight=no
- ac_cv_var_tzname=no
- ac_cv_func__setjmp=no
- ac_cv_func_setitimer=no
- ;;
+cygwin*) ;;
mingw*) if test "$with_winsock2" = yes; then
LIBS="-lws2_32 $LIBS"
else
LIBS="-lwsock32 $LIBS"
fi
+ LIBS="-lshell32 $LIBS"
ac_cv_header_a_out_h=no
ac_cv_header_pwd_h=no
ac_cv_header_utime_h=no
@@ -373,6 +438,7 @@ mingw*) if test "$with_winsock2" = yes; then
rb_cv_binary_elf=no
rb_cv_negative_time_t=no
enable_pthread=no
+ ac_cv_func_fcntl=yes
;;
os2-emx*) LIBS="-lm $LIBS"
ac_cv_lib_dir_opendir=no;;
@@ -380,8 +446,11 @@ msdosdjgpp*) LIBS="-lm $LIBS"
ac_cv_func_getpgrp_void=yes
ac_cv_func_setitimer=no
ac_cv_sizeof_rlim_t=4
+ ac_cv_func_setrlimit=no
;;
bsdi*) LIBS="-lm $LIBS"
+ AC_DEFINE(BROKEN_SETREUID, 1)
+ AC_DEFINE(BROKEN_SETREGID, 1)
ac_cv_sizeof_rlim_t=8;;
freebsd*) LIBS="-lm $LIBS"
AC_CACHE_CHECK([whether -lxpg4 has to be linked],
@@ -422,16 +491,17 @@ bow) ac_cv_func_setitimer=no
;;
superux*) ac_cv_func_setitimer=no
;;
-solaris*2.10) if test -z "$GCC"; then
- ac_cv_func_isinf=yes
+solaris*2.1*) if test -z "$GCC"; then
+ ac_cv_func_isinf=yes
fi
- LIBS="-lm $LIBS"
+ LIBS="-lm $LIBS"
;;
*) LIBS="-lm $LIBS";;
esac
AC_CHECK_LIB(crypt, crypt)
AC_CHECK_LIB(dl, dlopen) # Dynamic linking for SunOS/Solaris and SYSV
AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX
+AC_CHECK_LIB(rt, clock_gettime) # GNU/Linux
case "$target_cpu" in
alpha*) case "$target_os"::"$GCC" in
@@ -476,22 +546,104 @@ AC_STRUCT_ST_RDEV
dnl Checks for library functions.
AC_TYPE_GETGROUPS
AC_TYPE_SIGNAL
-AC_FUNC_ALLOCA
+case "${target_cpu}-${target_os}" in
+powerpc-darwin*)
+ AC_LIBSOURCES(alloca.c)
+ AC_SUBST([ALLOCA], [\${LIBOBJDIR}alloca.${ac_objext}])
+ AC_DEFINE(C_ALLOCA)
+ AC_DEFINE_UNQUOTED(alloca, alloca)
+ ;;
+*)
+ AC_FUNC_ALLOCA
+ ;;
+esac
AC_FUNC_MEMCMP
AC_FUNC_FSEEKO
AC_CHECK_FUNCS(ftello)
+
+# http://sources.redhat.com/ml/libc-hacker/2005-08/msg00008.html
+# Debian GNU/Linux Etch's libc6.1 2.3.6.ds1-13etch5 has this problem.
+# Debian GNU/Linux Lenny's libc6.1 2.7-10 has no problem.
+AC_CACHE_CHECK(for broken erfc of glibc-2.3.6 on IA64, rb_cv_broken_glibc_ia64_erfc,
+ [AC_TRY_RUN([
+#include <math.h>
+int
+main()
+{
+ erfc(10000.0);
+ return 0;
+}
+],
+ rb_cv_broken_glibc_ia64_erfc=no,
+ rb_cv_broken_glibc_ia64_erfc=yes,
+ rb_cv_broken_glibc_ia64_erfc=no)])
+case $rb_cv_broken_glibc_ia64_erfc in
+ yes) ac_cv_func_erf=no;;
+esac
+
AC_REPLACE_FUNCS(dup2 memmove strcasecmp strncasecmp strerror strftime\
strchr strstr strtoul crypt flock vsnprintf\
isnan finite isinf hypot acosh erf)
AC_CHECK_FUNCS(fmod killpg wait4 waitpid syscall chroot fsync getcwd eaccess\
- truncate chsize times utimes fcntl lockf lstat symlink link\
+ truncate ftruncate chsize times utimes fcntl lockf lstat symlink link\
readlink setitimer setruid seteuid setreuid setresuid\
setproctitle setrgid setegid setregid setresgid issetugid pause\
lchown lchmod getpgrp setpgrp getpgid setpgid initgroups\
getgroups setgroups getpriority getrlimit setrlimit sysconf\
- dlopen sigprocmask\
- sigaction _setjmp setsid telldir seekdir fchmod mktime timegm\
- cosh sinh tanh setuid setgid setenv unsetenv)
+ group_member dlopen sigprocmask\
+ sigaction sigsetjmp _setjmp _longjmp setsid telldir seekdir fchmod\
+ mktime timegm gettimeofday\
+ cosh sinh tanh round setuid setgid setenv unsetenv)
+
+AC_CACHE_CHECK(for __builtin_setjmp, ac_cv_func___builtin_setjmp,
+[AC_TRY_LINK([@%:@include <setjmp.h>
+ jmp_buf jb; void t(v) int v; {__builtin_longjmp(jb, v);}],
+ [__builtin_setjmp(jb);],
+ [ac_cv_func___builtin_setjmp=yes],
+ [ac_cv_func___builtin_setjmp=no])
+])
+
+test x$ac_cv_func__longjmp = xno && ac_cv_func__setjmp=no
+
+AC_MSG_CHECKING(for setjmp type)
+AC_ARG_WITH(setjmp-type,
+ [ --with-setjmp-type select setjmp type], [
+ case $withval in
+ __builtin_setjmp) setjmp_prefix=__builtin_;;
+ _setjmp) setjmp_prefix=_;;
+ sigsetjmp) setjmp_prefix=sig;;
+ setjmp) setjmp_prefix=;;
+ '') unset setjmp_prefix;;
+ *) AC_MSG_ERROR(invalid setjmp type: $withval);;
+ esac], [unset setjmp_prefix])
+if test ${setjmp_prefix+set}; then
+ if test "${setjmp_prefix}" && eval test '$ac_cv_func_'${setjmp_prefix}setjmp = no; then
+ AC_MSG_ERROR(${setjmp_prefix}setjmp is not available)
+ fi
+elif test "$ac_cv_func___builtin_setjmp" = yes; then
+ setjmp_prefix=__builtin_
+elif test "$ac_cv_func__setjmp" = yes; then
+ setjmp_prefix=_
+elif test "$ac_cv_func_sigsetjmp" = yes; then
+ case $target_os in
+ solaris*|cygwin*)
+ setjmp_prefix=;;
+ *)
+ setjmp_prefix=sig;;
+ esac
+else
+ setjmp_prefix=
+fi
+if test x$setjmp_prefix = xsig; then
+ setjmp_sigmask=yes
+else
+ unset setjmp_sigmask
+fi
+AC_MSG_RESULT(${setjmp_prefix}setjmp)
+AC_DEFINE_UNQUOTED([RUBY_SETJMP(env)], [${setjmp_prefix}setjmp(env${setjmp_sigmask+,0})])
+AC_DEFINE_UNQUOTED([RUBY_LONGJMP(env,val)], [${setjmp_prefix}longjmp(env,val)])
+AC_DEFINE_UNQUOTED(RUBY_JMP_BUF, ${setjmp_sigmask+${setjmp_prefix}}jmp_buf)
+
AC_ARG_ENABLE(setreuid,
[ --enable-setreuid use setreuid()/setregid() according to need even if obsolete.],
[use_setreuid=$enableval])
@@ -517,6 +669,50 @@ AC_CACHE_CHECK(for external int daylight, rb_cv_have_daylight,
if test "$rb_cv_have_daylight" = yes; then
AC_DEFINE(HAVE_DAYLIGHT)
fi
+AC_DEFUN([RUBY_CHECK_VARTYPE], [dnl
+AC_CACHE_CHECK([for external $1], rb_cv_var_$1,
+ [rb_cv_var_$1=no
+ AC_TRY_COMPILE([
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 1
+#endif
+$2
+;
+const volatile void *volatile t;],
+ [t = &(&$1)[0];],
+ [for t in $3; do
+ AC_TRY_COMPILE([
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 1
+#endif
+$2
+;
+extern $t $1;
+const volatile void *volatile t;],
+ [t = &(&$1)[0];],
+ [rb_cv_var_$1=$t; break])
+ done])])
+if test "[$rb_cv_var_]$1" != no; then
+ AC_DEFINE([HAVE_VAR_]m4_toupper($1))
+ AC_DEFINE_UNQUOTED([TYPEOF_VAR_]m4_toupper($1), $rb_cv_var_$1)
+fi])
+RUBY_CHECK_VARTYPE(timezone, [@%:@include <time.h>], [long int])
+RUBY_CHECK_VARTYPE(altzone, [@%:@include <time.h>], [long int])
+if test "$rb_cv_var_timezone" = no; then
+ AC_CHECK_FUNCS(timezone)
+ if test "$ac_cv_func_timezone" = yes; then
+ AC_CACHE_CHECK([whether timezone requires zero arguments], rb_cv_func_timezone_void,
+ [AC_TRY_COMPILE([@%:@include <time.h>],
+ [(void)timezone(0, 0);],
+ [rb_cv_func_timezone_void=no],
+ [rb_cv_func_timezone_void=yes])]
+ )
+ if test $rb_cv_func_timezone_void = yes; then
+ AC_DEFINE(TIMEZONE_VOID)
+ fi
+ fi
+fi
+
AC_CACHE_CHECK(for negative time_t for gmtime(3), rb_cv_negative_time_t,
[AC_TRY_RUN([
#include <time.h>
@@ -558,6 +754,7 @@ fi
if test "$ac_cv_func_sigprocmask" = yes && test "$ac_cv_func_sigaction" = yes; then
AC_DEFINE(POSIX_SIGNAL)
else
+ AC_CHECK_FUNCS(sigsetmask)
AC_CACHE_CHECK(for BSD signal semantics, rb_cv_bsd_signal,
[AC_TRY_RUN([
#include <stdio.h>
@@ -580,7 +777,7 @@ main()
],
rb_cv_bsd_signal=yes,
rb_cv_bsd_signal=no,
- rb_cv_bsd_signal=no)])
+ rb_cv_bsd_signal=$ac_cv_func_sigsetmask)])
if test "$rb_cv_bsd_signal" = yes; then
AC_DEFINE(BSD_SIGNAL)
fi
@@ -595,6 +792,21 @@ AC_C_CHAR_UNSIGNED
AC_C_INLINE
AC_C_VOLATILE
+if test x"$target_cpu" = xia64; then
+ AC_LIBOBJ([ia64])
+ AC_CACHE_CHECK(for __libc_ia64_register_backing_store_base,
+ rb_cv___libc_ia64_register_backing_store_base,
+ [rb_cv___libc_ia64_register_backing_store_base=no
+ AC_TRY_LINK(
+ [extern unsigned long __libc_ia64_register_backing_store_base;],
+ [unsigned long p = __libc_ia64_register_backing_store_base;
+ printf("%ld\n", p);],
+ [rb_cv___libc_ia64_register_backing_store_base=yes])])
+ if test $rb_cv___libc_ia64_register_backing_store_base = yes; then
+ AC_DEFINE(HAVE___LIBC_IA64_REGISTER_BACKING_STORE_BASE)
+ fi
+fi
+
AC_CACHE_CHECK(whether right shift preserve sign bit, rb_cv_rshift_sign,
[AC_TRY_RUN([
int
@@ -827,7 +1039,7 @@ if test x"$enable_pthread" = xyes; then
fi
fi
if test x"$ac_cv_header_ucontext_h" = xyes; then
- if test x"$target_cpu" = xia64 -o x"$rb_with_pthread" = xyes; then
+ if test x"$rb_with_pthread" = xyes; then
AC_CHECK_FUNCS(getcontext setcontext)
fi
fi
@@ -901,7 +1113,7 @@ AC_SUBST(DLEXT2)dnl
AC_SUBST(LIBEXT)dnl
STATIC=
-: ${LIBPATHFLAG=' -L"%s"'}
+: ${LIBPATHFLAG=' -L%s'}
: ${PATHFLAG=''}
if test "$with_dln_a_out" != yes; then
@@ -926,11 +1138,23 @@ if test "$with_dln_a_out" != yes; then
esac
fi
+
+ AC_ARG_ENABLE(rpath,
+ [ --disable-rpath embed run path into extension libraries.],
+ [enable_rpath=$enableval], [enable_rpath="$rb_cv_binary_elf"])
+ if test "$enable_rpath" = yes; then
+ LIBPATHFLAG=" -L%1\$-s"
+ RPATHFLAG=" ${linker_flag}-R%1\$-s"
+ fi
+
case "$target_os" in
hpux*) DLDFLAGS="$DLDFLAGS -E"
: ${LDSHARED='ld -b'}
XLDFLAGS="$XLDFLAGS -Wl,-E"
: ${LIBPATHENV=SHLIB_PATH}
+ if test "$rb_cv_prog_gnu_ld" = no; then
+ RPATHFLAG=' +b %1$-s'
+ fi
rb_cv_dlopen=yes;;
solaris*) if test "$GCC" = yes; then
: ${LDSHARED='$(CC) -shared'}
@@ -965,7 +1189,7 @@ if test "$with_dln_a_out" != yes; then
rb_cv_dlopen=yes ;;
interix*) : ${LDSHARED="$CC -shared"}
XLDFLAGS="$XLDFLAGS -Wl,-E"
- LIBPATHFLAG=" -L'%1\$-s'"
+ LIBPATHFLAG=" -L%1\$-s"
rb_cv_dlopen=yes ;;
freebsd*|dragonfly*) : ${LDSHARED="$CC -shared"}
if test "$rb_cv_binary_elf" = yes; then
@@ -994,14 +1218,13 @@ if test "$with_dln_a_out" != yes; then
: ${LIBPATHENV=DYLD_LIBRARY_PATH}
rb_cv_dlopen=yes ;;
aix*) if test "$GCC" = yes; then
- : ${LDSHARED='gcc -shared'}
- DLDFLAGS='-Wl,-G -eInit_$(TARGET)'
- LDFLAGS='-Wl,-brtl -Wl,-bE:ruby.imp'
- else
- : ${LDSHARED='/usr/ccs/bin/ld'}
- DLDFLAGS='-G -eInit_$(TARGET)'
- LDFLAGS="-brtl -bE:ruby.imp"
- fi
+ : ${LDSHARED='$(CC) -shared'}
+ else
+ : ${LDSHARED='$(CC)'}
+ fi
+ LDSHARED="$LDSHARED ${linker_flag}-G"
+ DLDFLAGS='-eInit_$(TARGET)'
+ XLDFLAGS="${linker_flag}-bE:ruby.imp ${linker_flag}-brtl"
: ${ARCHFILE="ruby.imp"}
TRY_LINK='$(CC) $(LDFLAGS) -oconftest $(INCFLAGS) -I$(hdrdir) $(CPPFLAGS)'
TRY_LINK="$TRY_LINK"' $(CFLAGS) $(src) $(LIBPATH) $(LOCAL_LIBS) $(LIBS)'
@@ -1030,7 +1253,7 @@ if test "$with_dln_a_out" != yes; then
rb_cv_dlopen=yes;;
cygwin*|mingw*) : ${LDSHARED="${CC} -shared -s"}
XLDFLAGS="$XLDFLAGS -Wl,--stack,0x02000000"
- DLDFLAGS="${DLDFLAGS} -Wl,--enable-auto-import,--export-all"
+ DLDFLAGS="${DLDFLAGS} -Wl,--enable-auto-image-base,--enable-auto-import,--export-all"
: ${LIBPATHENV=""}
rb_cv_dlopen=yes ;;
hiuxmpp) : ${LDSHARED='ld -r'} ;;
@@ -1041,18 +1264,6 @@ if test "$with_dln_a_out" != yes; then
*) : ${LDSHARED='ld'} ;;
esac
AC_MSG_RESULT($rb_cv_dlopen)
-
- AC_ARG_ENABLE(rpath,
- [ --disable-rpath embed run path into extension libraries.],
- [enable_rpath=$enableval], [enable_rpath="$rb_cv_binary_elf"])
- if test "$enable_rpath" = yes; then
- LIBPATHFLAG=" -L'%1\$-s'"
- if test "$GCC" = yes; then
- RPATHFLAG=" -Wl,-R'%1\$-s'"
- else
- RPATHFLAG=" -R'%1\$-s'"
- fi
- fi
fi
AC_SUBST(LINK_SO)
AC_SUBST(LIBPATHFLAG)
@@ -1086,30 +1297,24 @@ if test "$dln_a_out_works" = yes; then
STATIC=-Bstatic
fi
DLEXT=so
- AC_DEFINE(DLEXT, ".so")
CCDLFLAGS=
else
case "$target_os" in
- hpux*) DLEXT=sl
- AC_DEFINE(DLEXT, ".sl");;
- nextstep*) DLEXT=bundle
- AC_DEFINE(DLEXT, ".bundle");;
- openstep*) DLEXT=bundle
- AC_DEFINE(DLEXT, ".bundle");;
- rhapsody*) DLEXT=bundle
- AC_DEFINE(DLEXT, ".bundle");;
- darwin*) DLEXT=bundle
- AC_DEFINE(DLEXT, ".bundle");;
- os2-emx*) DLEXT=dll
- AC_DEFINE(DLEXT, ".dll");;
- cygwin*|mingw*) DLEXT=so
- AC_DEFINE(DLEXT, ".so")
- DLEXT2=dll
- AC_DEFINE(DLEXT2, ".dll");;
- *) DLEXT=so
- AC_DEFINE(DLEXT, ".so");;
+ hpux*) DLEXT=sl;;
+ nextstep*|openstep*|rhapsody*|darwin*)
+ DLEXT=bundle;;
+ os2-emx*) DLEXT=dll;;
+ cygwin*|mingw*)
+ DLEXT=so DLEXT2=dll;;
+ *) DLEXT=so;;
esac
fi
+len=2 # .rb
+n=`expr "$DLEXT" : '.*'`; test "$n" -gt "$len" && len=$n
+n=`expr "$DLEXT2" : '.*'`; test "$n" -gt "$len" && len=$n
+AC_DEFINE_UNQUOTED(DLEXT_MAXLEN, `expr $len + 1`)
+test ".$DLEXT" = "." || AC_DEFINE_UNQUOTED(DLEXT, ".$DLEXT")
+test ".$DLEXT2" = "." || AC_DEFINE_UNQUOTED(DLEXT2, ".$DLEXT2")
AC_SUBST(STRIP)dnl
if test "$with_dln_a_out" = yes; then
@@ -1145,7 +1350,7 @@ case "$target_os" in
human*)
AC_CHECK_LIB(signal, _harderr)
AC_CHECK_LIB(hmem, hmemset)
- AC_CHECK_FUNCS(select gettimeofday)
+ AC_CHECK_FUNCS(select)
AC_CACHE_CHECK(whether PD libc _dtos18 fail to convert big number,
rb_cv_missing__dtos18,
[AC_TRY_RUN(
@@ -1218,9 +1423,10 @@ if test x"$cross_compiling" = xyes; then
PREP=fake.rb
RUNRUBY='$(MINIRUBY) -I`cd $(srcdir)/lib; pwd`'
else
- MINIRUBY='./miniruby$(EXEEXT)'
+ MINIRUBY='./miniruby$(EXEEXT) -I$(srcdir)/lib'
+ MINIRUBY="$MINIRUBY"' -I$(EXTOUT)/common -I./- -r$(srcdir)/ext/purelib.rb'
PREP='miniruby$(EXEEXT)'
- RUNRUBY='$(MINIRUBY) $(srcdir)/runruby.rb --extout=$(EXTOUT) --'
+ RUNRUBY='$(MINIRUBY) $(srcdir)/runruby.rb --extout=$(EXTOUT)'
fi
AC_SUBST(MINIRUBY)
AC_SUBST(PREP)
@@ -1307,14 +1513,8 @@ if test "$enable_shared" = 'yes'; then
LIBRUBY_ALIASES='lib$(RUBY_SO_NAME).sl.$(MAJOR).$(MINOR) lib$(RUBY_SO_NAME).sl'
;;
aix*)
- if test "$GCC" = yes; then
- LIBRUBY_LDSHARED='$(CC) -shared'
- LIBRUBY_DLDFLAGS='-Wl,-G -Wl,-bE:ruby.imp -Wl,-bnoentry'
- else
- LIBRUBY_LDSHARED='/usr/ccs/bin/ld'
- LIBRUBY_DLDFLAGS='-G -bE:ruby.imp -bnoentry'
- fi
- LIBRUBYARG_SHARED='-L${libdir} -lruby'
+ LIBRUBY_DLDFLAGS="${linker_flag}-bnoentry $XLDFLAGS"
+ LIBRUBYARG_SHARED='-L${libdir} -l${RUBY_SO_NAME}'
SOLIBS='-lm -lc'
;;
beos*)
@@ -1331,21 +1531,17 @@ if test "$enable_shared" = 'yes'; then
LIBRUBY_ALIASES='lib$(RUBY_SO_NAME).$(MAJOR).$(MINOR).dylib lib$(RUBY_SO_NAME).dylib'
;;
interix*)
- LIBRUBYARG_SHARED='-L${libdir} -L. -l$(RUBY_SO_NAME)'
+ LIBRUBYARG_SHARED='-L. -L${libdir} -l$(RUBY_SO_NAME)'
;;
*)
;;
esac
fi
if test "$enable_rpath" = yes; then
- if test "$GCC" = yes; then
- LIBRUBYARG_SHARED='-Wl,-R -Wl,$(libdir) -L$(libdir) -L. '"$LIBRUBYARG_SHARED"
- else
- LIBRUBYARG_SHARED='-R $(libdir) -L$(libdir) -L. '"$LIBRUBYARG_SHARED"
- fi
+ LIBRUBYARG_SHARED="${linker_flag}-R ${linker_flag}\$(libdir) -L\$(libdir) $LIBRUBYARG_SHARED"
fi
-XLDFLAGS="$XLDFLAGS -L."
+LDFLAGS="-L. $LDFLAGS"
AC_SUBST(ARCHFILE)
dnl build rdoc index if requested
@@ -1359,6 +1555,9 @@ fi
AC_SUBST(RDOCTARGET)
case "$target_os" in
+ linux*)
+ XCFLAGS="$XCFLAGS -D_GNU_SOURCE=1"
+ ;;
netbsd*)
CFLAGS="$CFLAGS -pipe"
;;
@@ -1378,6 +1577,7 @@ case "$target_os" in
;;
darwin*)
CFLAGS="$CFLAGS -pipe -fno-common"
+ MINIOBJS=dmydln.o
;;
os2-emx)
CFLAGS="$CFLAGS -DOS2 -Zmts"
@@ -1400,7 +1600,7 @@ case "$target_os" in
rm -f /tmp/main.o
CFLAGS="$CFLAGS -std"
fi
- ;;
+ ;;
beos*)
case "$target_cpu" in
powerpc*)
@@ -1415,7 +1615,6 @@ case "$target_os" in
LIBRUBY_SO='cyg$(RUBY_SO_NAME)'${MAJOR}${MINOR}.dll
LIBRUBY='lib$(RUBY_SO_NAME).dll.a'
fi
- AC_LIBOBJ([strftime])
;;
mingw*)
RUBY_SO_NAME=${rb_cv_msvcrt}-'$(RUBY_INSTALL_NAME)'${MAJOR}${MINOR}
@@ -1449,9 +1648,6 @@ case "$target_os" in
esac
MINIOBJS=dmydln.o
;;
- aix*)
- PREINSTALL='@$(RM) -r $(prefix)/lib/$(LIBRUBY_A) $(prefix)/lib/$(LIBRUBY_SO) $(prefix)/lib/ruby/$(MAJOR).$(MINOR)/$(arch)'
- ;;
*)
;;
esac
@@ -1460,6 +1656,13 @@ case "$build_os" in
*msdosdjgpp*) FIRSTMAKEFILE=GNUmakefile:djgpp/GNUmakefile.in;;
esac
+CPPFLAGS="$CPPFLAGS "'$(DEFS)'
+test -z "$CFLAGS" || CFLAGS="$CFLAGS "; CFLAGS="$CFLAGS"'${cflags}'
+test -z "$CPPFLAGS" || CPPFLAGS="$CPPFLAGS "; CPPFLAGS="$CPPFLAGS"'${cppflags}'
+AC_SUBST(cppflags, [])dnl
+AC_SUBST(cflags, ['${optflags} ${debugflags}'])dnl
+AC_SUBST(optflags)dnl
+AC_SUBST(debugflags)dnl
AC_SUBST(XCFLAGS)dnl
AC_SUBST(XLDFLAGS)dnl
AC_SUBST(LIBRUBY_LDSHARED)
@@ -1484,7 +1687,6 @@ AC_SUBST(COMMON_MACROS)
AC_SUBST(COMMON_HEADERS)
AC_SUBST(EXPORT_PREFIX)
AC_SUBST(MINIOBJS)
-AC_SUBST(PREINSTALL)
MAKEFILES="Makefile `echo $FIRSTMAKEFILE | sed 's/:.*//'`"
MAKEFILES="`echo $MAKEFILES`"
@@ -1505,37 +1707,53 @@ case "$target_os" in
rubyw_install_name="$RUBYW_INSTALL_NAME"
;;
esac
-case "$target_os" in
- cygwin*|mingw*|*djgpp*|os2-emx*)
- RUBY_LIB_PREFIX="/lib/ruby"
- ;;
- *)
- RUBY_LIB_PREFIX="${prefix}/lib/ruby"
- ;;
-esac
-RUBY_LIB_PATH="${RUBY_LIB_PREFIX}/${MAJOR}.${MINOR}"
+RUBY_LIB_PREFIX=`eval echo \\"${libdir}/ruby\\"`
AC_ARG_WITH(sitedir,
- [ --with-sitedir=DIR site libraries in DIR [PREFIX/lib/ruby/site_ruby]],
+ [ --with-sitedir=DIR site libraries in DIR [[LIBDIR/ruby/site_ruby]]],
[sitedir=$withval],
- [sitedir='${prefix}/lib/ruby/site_ruby'])
+ [sitedir='${libdir}/ruby/site_ruby'])
SITE_DIR=`eval echo \\"${sitedir}\\"`
+
case "$target_os" in
cygwin*|mingw*|*djgpp*|os2-emx*)
- RUBY_SITE_LIB_PATH="`expr "$SITE_DIR" : "$prefix\(/.*\)"`" ||
- RUBY_SITE_LIB_PATH="$SITE_DIR";;
+ RUBY_LIB_PREFIX="`eval echo "$RUBY_LIB_PREFIX" | sed 's|^NONE/|/|;s|^'"$prefix"'/|/|'`"
+ RUBY_SITE_LIB_PATH="`eval echo "$SITE_DIR" | sed 's|^NONE/|/|;s|^'"$prefix"'/|/|'`"
+ ;;
*)
- RUBY_SITE_LIB_PATH="$SITE_DIR";;
+ RUBY_LIB_PREFIX="`eval echo \\"$RUBY_LIB_PREFIX\\" | sed 's|^NONE/|'"$prefix"'/|'`"
+ RUBY_SITE_LIB_PATH="`eval echo \\"$SITE_DIR\\" | sed 's|^NONE/|'"$prefix"'/|'`"
+ ;;
esac
+RUBY_LIB_PATH="${RUBY_LIB_PREFIX}/${MAJOR}.${MINOR}"
RUBY_SITE_LIB_PATH2="${RUBY_SITE_LIB_PATH}/${MAJOR}.${MINOR}"
AC_DEFINE_UNQUOTED(RUBY_LIB, "${RUBY_LIB_PATH}")
AC_DEFINE_UNQUOTED(RUBY_SITE_LIB, "${RUBY_SITE_LIB_PATH}")
AC_DEFINE_UNQUOTED(RUBY_SITE_LIB2, "${RUBY_SITE_LIB_PATH2}")
+AC_ARG_WITH(vendordir,
+ [ --with-vendordir=DIR vendor libraries in DIR [[LIBDIR/ruby/vendor_ruby]]],
+ [vendordir=$withval],
+ [vendordir='${libdir}/ruby/vendor_ruby'])
+VENDOR_DIR=`eval echo \\"${vendordir}\\"`
+case "$target_os" in
+ cygwin*|mingw*|*djgpp*|os2-emx*)
+ RUBY_VENDOR_LIB_PATH="`eval echo "$VENDOR_DIR" | sed 's|^NONE/|/|;s|^'"$prefix"'/|/|'`"
+ ;;
+ *)
+ RUBY_VENDOR_LIB_PATH="`eval echo \\"$VENDOR_DIR\\" | sed 's|^NONE/|'"$prefix"'/|'`"
+ ;;
+esac
+RUBY_VENDOR_LIB_PATH2="${RUBY_VENDOR_LIB_PATH}/${MAJOR}.${MINOR}"
+
+AC_DEFINE_UNQUOTED(RUBY_VENDOR_LIB, "${RUBY_VENDOR_LIB_PATH}")
+AC_DEFINE_UNQUOTED(RUBY_VENDOR_LIB2, "${RUBY_VENDOR_LIB_PATH2}")
+
AC_SUBST(arch)dnl
AC_SUBST(sitearch)dnl
AC_SUBST(sitedir)dnl
+AC_SUBST(vendordir)dnl
configure_args=$ac_configure_args
AC_SUBST(configure_args)dnl
@@ -1548,6 +1766,8 @@ if test "$fat_binary" != no ; then
AC_DEFINE_UNQUOTED(RUBY_SITE_THIN_ARCHLIB,
"${RUBY_SITE_LIB_PATH}/" __ARCHITECTURE__ "-${target_os}")
+ AC_DEFINE_UNQUOTED(RUBY_VENDOR_THIN_ARCHLIB,
+ "${RUBY_VENDOR_LIB_PATH}/" __ARCHITECTURE__ "-${target_os}")
AC_DEFINE_UNQUOTED(RUBY_PLATFORM, __ARCHITECTURE__ "-${target_os}")
else
arch="${target_cpu}-${target_os}"
@@ -1555,12 +1775,13 @@ else
fi
case "$target_os" in
- mingw*) sitearch="i386-$rb_cv_msvcrt" ;;
+ mingw*) sitearch="$target_cpu-$rb_cv_msvcrt" ;;
*) sitearch="${arch}" ;;
esac
AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "${RUBY_LIB_PATH}/${arch}")
AC_DEFINE_UNQUOTED(RUBY_SITE_ARCHLIB, "${RUBY_SITE_LIB_PATH2}/${sitearch}")
+AC_DEFINE_UNQUOTED(RUBY_VENDOR_ARCHLIB, "${RUBY_VENDOR_LIB_PATH2}/${sitearch}")
AC_ARG_WITH(search-path,
[ --with-search-path=DIR specify the additional search path],
@@ -1597,12 +1818,15 @@ else
echo "creating config.h"
tr -d '\015' < confdefs.h > config.h
fi
-: > confdefs.h
+tr -d '\015' < largefile.h > confdefs.h
+rm largefile.h
AC_CONFIG_FILES($FIRSTMAKEFILE)
AC_CONFIG_FILES(Makefile, [{
+ sed '/^MISSING/s/\$U\././g' Makefile
echo; test x"$EXEEXT" = x || echo 'miniruby: miniruby$(EXEEXT)'
test "$RUBY_INSTALL_NAME$EXEEXT" = ruby || echo 'ruby: $(PROGRAM);'
sed ['s/{\$([^(){}]*)[^{}]*}//g'] ${srcdir}/common.mk
-} >> Makefile], [RUBY_INSTALL_NAME=$RUBY_INSTALL_NAME EXEEXT=$EXEEXT])
+ } >> confmk$$.tmp && mv -f confmk$$.tmp Makefile],
+[RUBY_INSTALL_NAME=$RUBY_INSTALL_NAME EXEEXT=$EXEEXT])
AC_OUTPUT
diff --git a/defines.h b/defines.h
index 89167e537e..f39097fea4 100644
--- a/defines.h
+++ b/defines.h
@@ -2,8 +2,8 @@
defines.h -
- $Author: nobu $
- $Date: 2005/10/25 16:59:57 $
+ $Author$
+ $Date$
created at: Wed May 18 00:21:44 JST 1994
************************************************/
@@ -102,6 +102,16 @@ void xfree _((void*));
#endif
#endif
+#if defined(__NeXT__) || defined(__APPLE__)
+/* Do not trust WORDS_BIGENDIAN from configure since -arch compiler flag may
+ result in a different endian. Instead trust __BIG_ENDIAN__ and
+ __LITTLE_ENDIAN__ which are set correctly by -arch. */
+#undef WORDS_BIGENDIAN
+#ifdef __BIG_ENDIAN__
+#define WORDS_BIGENDIAN
+#endif
+#endif
+
#ifdef __NeXT__
/* NextStep, OpenStep, Rhapsody */
#ifndef S_IRUSR
@@ -155,13 +165,6 @@ void xfree _((void*));
#ifndef S_ISREG
#define S_ISREG(mode) (((mode) & (0170000)) == (0100000))
#endif
-/* Do not trust WORDS_BIGENDIAN from configure since -arch compiler flag may
- result in a different endian. Instead trust __BIG_ENDIAN__ and
- __LITTLE_ENDIAN__ which are set correctly by -arch. */
-#undef WORDS_BIGENDIAN
-#ifdef __BIG_ENDIAN__
-#define WORDS_BIGENDIAN
-#endif
#ifndef __APPLE__
/* NextStep, OpenStep (but not Rhapsody) */
#ifndef GETPGRP_VOID
@@ -203,6 +206,11 @@ void xfree _((void*));
#define EXTERN RUBY_EXTERN /* deprecated */
#endif
+#ifndef RUBY_MBCHAR_MAXSIZE
+#define RUBY_MBCHAR_MAXSIZE INT_MAX
+ /* MB_CUR_MAX will not work well in C locale */
+#endif
+
#if defined(sparc) || defined(__sparc__)
static inline void
flush_register_windows(void)
@@ -213,21 +221,16 @@ flush_register_windows(void)
#endif
# if defined(__sparc_v9__) || defined(__sparcv9) || defined(__arch64__)
("flushw")
-# elif defined(linux) || defined(__linux__)
- ("ta 0x83")
-# else /* Solaris, OpenBSD, NetBSD, etc. */
+# else
("ta 0x03")
# endif /* trap always to flush register windows if we are on a Sparc system */
;
}
# define FLUSH_REGISTER_WINDOWS flush_register_windows()
-#elif defined(__ia64__)
-void flush_register_windows(void)
-# if defined(__GNUC__) && (( __GNUC__ == 3 && __GNUC_MINOR__ > 0 ) || __GNUC__ > 3)
-__attribute__ ((noinline))
-# endif
- ;
-# define FLUSH_REGISTER_WINDOWS flush_register_windows()
+#elif defined(__ia64)
+void *rb_ia64_bsp(void);
+void rb_ia64_flushrs(void);
+# define FLUSH_REGISTER_WINDOWS rb_ia64_flushrs()
#else
# define FLUSH_REGISTER_WINDOWS ((void)0)
#endif
@@ -251,6 +254,18 @@ __attribute__ ((noinline))
#define ENV_IGNORECASE
#endif
+#ifndef CASEFOLD_FILESYSTEM
+# if defined DOSISH || defined __VMS
+# define CASEFOLD_FILESYSTEM 1
+# else
+# define CASEFOLD_FILESYSTEM 0
+# endif
+#endif
+
+#ifndef DLEXT_MAXLEN
+#define DLEXT_MAXLEN 4
+#endif
+
#ifndef RUBY_PLATFORM
#define RUBY_PLATFORM "unknown-unknown"
#endif
diff --git a/dir.c b/dir.c
index 0798b3f76f..c2c3f9452f 100644
--- a/dir.c
+++ b/dir.c
@@ -2,8 +2,8 @@
dir.c -
- $Author: shyouhei $
- $Date: 2006/12/14 14:50:13 $
+ $Author$
+ $Date$
created at: Wed Jan 5 09:51:01 JST 1994
Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -89,153 +89,261 @@ char *strchr _((char*,char));
#define FNM_ERROR 2
#define downcase(c) (nocase && ISUPPER(c) ? tolower(c) : (c))
+#define compare(c1, c2) (((unsigned char)(c1)) - ((unsigned char)(c2)))
+
+/* caution: in case *p == '\0'
+ Next(p) == p + 1 in single byte environment
+ Next(p) == p in multi byte environment
+*/
+#if defined(CharNext)
+# define Next(p) CharNext(p)
+#elif defined(DJGPP)
+# define Next(p) ((p) + mblen(p, RUBY_MBCHAR_MAXSIZE))
+#elif defined(__EMX__)
+# define Next(p) ((p) + emx_mblen(p))
+static inline int
+emx_mblen(const char *p)
+{
+ int n = mblen(p, RUBY_MBCHAR_MAXSIZE);
+ return (n < 0) ? 1 : n;
+}
+#endif
-#ifndef CharNext /* defined as CharNext[AW] on Windows. */
-# if defined(DJGPP)
-# define CharNext(p) ((p) + mblen(p, MB_CUR_MAX))
-# else
-# define CharNext(p) ((p) + 1)
-# endif
+#ifndef Next /* single byte environment */
+# define Next(p) ((p) + 1)
+# define Inc(p) (++(p))
+# define Compare(p1, p2) (compare(downcase(*(p1)), downcase(*(p2))))
+#else /* multi byte environment */
+# define Inc(p) ((p) = Next(p))
+# define Compare(p1, p2) (CompareImpl(p1, p2, nocase))
+static int
+CompareImpl(const char *p1, const char *p2, int nocase)
+{
+ const int len1 = Next(p1) - p1;
+ const int len2 = Next(p2) - p2;
+#ifdef _WIN32
+ char buf1[10], buf2[10]; /* large enough? */
#endif
-#if defined DOSISH
-#define isdirsep(c) ((c) == '/' || (c) == '\\')
-#else
-#define isdirsep(c) ((c) == '/')
+ if (len1 < 0 || len2 < 0) {
+ rb_fatal("CompareImpl: negative len");
+ }
+
+ if (len1 == 0) return len2;
+ if (len2 == 0) return -len1;
+
+#ifdef _WIN32
+ if (nocase && rb_w32_iswinnt()) {
+ if (len1 > 1) {
+ if (len1 >= sizeof(buf1)) {
+ rb_fatal("CompareImpl: too large len");
+ }
+ memcpy(buf1, p1, len1);
+ buf1[len1] = '\0';
+ CharLower(buf1);
+ p1 = buf1; /* trick */
+ }
+ if (len2 > 1) {
+ if (len2 >= sizeof(buf2)) {
+ rb_fatal("CompareImpl: too large len");
+ }
+ memcpy(buf2, p2, len2);
+ buf2[len2] = '\0';
+ CharLower(buf2);
+ p2 = buf2; /* trick */
+ }
+ }
#endif
+ if (len1 == 1)
+ if (len2 == 1)
+ return compare(downcase(*p1), downcase(*p2));
+ else {
+ const int ret = compare(downcase(*p1), *p2);
+ return ret ? ret : -1;
+ }
+ else
+ if (len2 == 1) {
+ const int ret = compare(*p1, downcase(*p2));
+ return ret ? ret : 1;
+ }
+ else {
+ const int ret = memcmp(p1, p2, len1 < len2 ? len1 : len2);
+ return ret ? ret : len1 - len2;
+ }
+}
+#endif /* environment */
static char *
-range(pat, test, flags)
- const char *pat;
- int test;
+bracket(p, s, flags)
+ const char *p; /* pattern (next to '[') */
+ const char *s; /* string */
int flags;
{
- int not, ok = 0;
- int nocase = flags & FNM_CASEFOLD;
- int escape = !(flags & FNM_NOESCAPE);
+ const int nocase = flags & FNM_CASEFOLD;
+ const int escape = !(flags & FNM_NOESCAPE);
- not = *pat == '!' || *pat == '^';
- if (not)
- pat++;
+ int ok = 0, not = 0;
- test = downcase(test);
+ if (*p == '!' || *p == '^') {
+ not = 1;
+ p++;
+ }
- while (*pat != ']') {
- int cstart, cend;
- if (escape && *pat == '\\')
- pat++;
- cstart = cend = *pat++;
- if (!cstart)
+ while (*p != ']') {
+ const char *t1 = p;
+ if (escape && *t1 == '\\')
+ t1++;
+ if (!*t1)
return NULL;
- if (*pat == '-' && pat[1] != ']') {
- pat++;
- if (escape && *pat == '\\')
- pat++;
- cend = *pat++;
- if (!cend)
+ p = Next(t1);
+ if (p[0] == '-' && p[1] != ']') {
+ const char *t2 = p + 1;
+ if (escape && *t2 == '\\')
+ t2++;
+ if (!*t2)
return NULL;
+ p = Next(t2);
+ if (!ok && Compare(t1, s) <= 0 && Compare(s, t2) <= 0)
+ ok = 1;
}
- if (downcase(cstart) <= test && test <= downcase(cend))
- ok = 1;
+ else
+ if (!ok && Compare(t1, s) == 0)
+ ok = 1;
}
- return ok == not ? NULL : (char *)pat + 1;
+
+ return ok == not ? NULL : (char *)p + 1;
}
-#define ISDIRSEP(c) (pathname && isdirsep(c))
-#define PERIOD(s) (period && *(s) == '.' && \
- ((s) == string || ISDIRSEP((s)[-1])))
+/* If FNM_PATHNAME is set, only path element will be matched. (upto '/' or '\0')
+ Otherwise, entire string will be matched.
+ End marker itself won't be compared.
+ And if function succeeds, *pcur reaches end marker.
+*/
+#define UNESCAPE(p) (escape && *(p) == '\\' ? (p) + 1 : (p))
+#define ISEND(p) (!*(p) || (pathname && *(p) == '/'))
+#define RETURN(val) return *pcur = p, *scur = s, (val);
+
static int
-fnmatch(pat, string, flags)
- const char *pat;
- const char *string;
+fnmatch_helper(pcur, scur, flags)
+ const char **pcur; /* pattern */
+ const char **scur; /* string */
int flags;
{
- int c;
- int test;
- const char *s = string;
- int escape = !(flags & FNM_NOESCAPE);
- int pathname = flags & FNM_PATHNAME;
- int period = !(flags & FNM_DOTMATCH);
- int nocase = flags & FNM_CASEFOLD;
+ const int period = !(flags & FNM_DOTMATCH);
+ const int pathname = flags & FNM_PATHNAME;
+ const int escape = !(flags & FNM_NOESCAPE);
+ const int nocase = flags & FNM_CASEFOLD;
- while ((c = *pat++) != '\0') {
- switch (c) {
- case '?':
- if (!*s || ISDIRSEP(*s) || PERIOD(s))
- return FNM_NOMATCH;
- s++;
- break;
- case '*':
- while ((c = *pat++) == '*')
- ;
+ const char *ptmp = 0;
+ const char *stmp = 0;
- if (PERIOD(s))
- return FNM_NOMATCH;
+ const char *p = *pcur;
+ const char *s = *scur;
- if (!c) {
- if (pathname && *rb_path_next(s))
- return FNM_NOMATCH;
- else
- return 0;
- }
- else if (ISDIRSEP(c)) {
- s = rb_path_next(s);
- if (*s) {
- s++;
- break;
- }
- return FNM_NOMATCH;
- }
+ if (period && *s == '.' && *UNESCAPE(p) != '.') /* leading period */
+ RETURN(FNM_NOMATCH);
- test = escape && c == '\\' ? *pat : c;
- test = downcase(test);
- pat--;
- while (*s) {
- if ((c == '?' || c == '[' || downcase(*s) == test) &&
- !fnmatch(pat, s, flags | FNM_DOTMATCH))
- return 0;
- else if (ISDIRSEP(*s))
- break;
- s++;
+ while (1) {
+ switch (*p) {
+ case '*':
+ do { p++; } while (*p == '*');
+ if (ISEND(UNESCAPE(p))) {
+ p = UNESCAPE(p);
+ RETURN(0);
}
- return FNM_NOMATCH;
+ if (ISEND(s))
+ RETURN(FNM_NOMATCH);
+ ptmp = p;
+ stmp = s;
+ continue;
- case '[':
- if (!*s || ISDIRSEP(*s) || PERIOD(s))
- return FNM_NOMATCH;
- pat = range(pat, *s, flags);
- if (pat == NULL)
- return FNM_NOMATCH;
- s++;
- break;
+ case '?':
+ if (ISEND(s))
+ RETURN(FNM_NOMATCH);
+ p++;
+ Inc(s);
+ continue;
- case '\\':
- if (escape
-#if defined DOSISH
- && *pat && strchr("*?[]\\", *pat)
-#endif
- ) {
- c = *pat;
- if (!c)
- c = '\\';
- else
- pat++;
+ case '[': {
+ const char *t;
+ if (ISEND(s))
+ RETURN(FNM_NOMATCH);
+ if ((t = bracket(p + 1, s, flags)) != 0) {
+ p = t;
+ Inc(s);
+ continue;
}
- /* FALLTHROUGH */
+ goto failed;
+ }
+ }
- default:
-#if defined DOSISH
- if (ISDIRSEP(c) && isdirsep(*s))
- ;
- else
-#endif
- if(downcase(c) != downcase(*s))
- return FNM_NOMATCH;
- s++;
- break;
+ /* ordinary */
+ p = UNESCAPE(p);
+ if (ISEND(s))
+ RETURN(ISEND(p) ? 0 : FNM_NOMATCH);
+ if (ISEND(p))
+ goto failed;
+ if (Compare(p, s) != 0)
+ goto failed;
+ Inc(p);
+ Inc(s);
+ continue;
+
+ failed: /* try next '*' position */
+ if (ptmp && stmp) {
+ p = ptmp;
+ Inc(stmp); /* !ISEND(*stmp) */
+ s = stmp;
+ continue;
+ }
+ RETURN(FNM_NOMATCH);
+ }
+}
+
+static int
+fnmatch(p, s, flags)
+ const char *p; /* pattern */
+ const char *s; /* string */
+ int flags;
+{
+ const int period = !(flags & FNM_DOTMATCH);
+ const int pathname = flags & FNM_PATHNAME;
+
+ const char *ptmp = 0;
+ const char *stmp = 0;
+
+ if (pathname) {
+ while (1) {
+ if (p[0] == '*' && p[1] == '*' && p[2] == '/') {
+ do { p += 3; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
+ ptmp = p;
+ stmp = s;
+ }
+ if (fnmatch_helper(&p, &s, flags) == 0) {
+ while (*s && *s != '/') Inc(s);
+ if (*p && *s) {
+ p++;
+ s++;
+ continue;
+ }
+ if (!*p && !*s)
+ return 0;
+ }
+ /* failed : try next recursion */
+ if (ptmp && stmp && !(period && *stmp == '.')) {
+ while (*stmp && *stmp != '/') Inc(stmp);
+ if (*stmp) {
+ p = ptmp;
+ stmp++;
+ s = stmp;
+ continue;
+ }
+ }
+ return FNM_NOMATCH;
}
}
- return !*s ? 0 : FNM_NOMATCH;
+ else
+ return fnmatch_helper(&p, &s, flags);
}
VALUE rb_cDir;
@@ -355,6 +463,29 @@ dir_check(dir)
/*
* call-seq:
+ * dir.inspect => string
+ *
+ * Return a string describing this Dir object.
+ */
+static VALUE
+dir_inspect(dir)
+ VALUE dir;
+{
+ struct dir_data *dirp;
+
+ Data_Get_Struct(dir, struct dir_data, dirp);
+ if (dirp->path) {
+ const char *c = rb_obj_classname(dir);
+ int len = strlen(c) + strlen(dirp->path) + 4;
+ VALUE s = rb_str_new(0, len);
+ snprintf(RSTRING_PTR(s), len+1, "#<%s:%s>", c, dirp->path);
+ return s;
+ }
+ return rb_funcall(dir, rb_intern("to_s"), 0, 0);
+}
+
+/*
+ * call-seq:
* dir.path => string or nil
*
* Returns the path parameter passed to <em>dir</em>'s constructor.
@@ -368,7 +499,7 @@ dir_path(dir)
{
struct dir_data *dirp;
- GetDIR(dir, dirp);
+ Data_Get_Struct(dir, struct dir_data, dirp);
if (!dirp->path) return Qnil;
return rb_str_new2(dirp->path);
}
@@ -431,6 +562,7 @@ dir_each(dir)
struct dir_data *dirp;
struct dirent *dp;
+ RETURN_ENUMERATOR(dir, 0, 0);
GetDIR(dir, dirp);
rewinddir(dirp->dir);
for (dp = readdir(dirp->dir); dp != NULL; dp = readdir(dirp->dir)) {
@@ -538,6 +670,9 @@ dir_rewind(dir)
{
struct dir_data *dirp;
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(dir)) {
+ rb_raise(rb_eSecurityError, "Insecure: can't close");
+ }
GetDIR(dir, dirp);
rewinddir(dirp->dir);
return dir;
@@ -559,9 +694,6 @@ dir_close(dir)
{
struct dir_data *dirp;
- if (rb_safe_level() >= 4 && !OBJ_TAINTED(dir)) {
- rb_raise(rb_eSecurityError, "Insecure: can't close");
- }
GetDIR(dir, dirp);
closedir(dirp->dir);
dirp->dir = NULL;
@@ -819,109 +951,252 @@ sys_warning_1(mesg)
rb_sys_warning("%s", mesg);
}
-#define GLOB_VERBOSE (1U << (sizeof(int) * CHAR_BIT - 1))
+#define GLOB_VERBOSE (1UL << (sizeof(int) * CHAR_BIT - 1))
#define sys_warning(val) \
(void)((flags & GLOB_VERBOSE) && rb_protect((VALUE (*)_((VALUE)))sys_warning_1, (VALUE)(val), 0))
#define GLOB_ALLOC(type) (type *)malloc(sizeof(type))
#define GLOB_ALLOC_N(type, n) (type *)malloc(sizeof(type) * (n))
-#define GLOB_REALLOC_N(var, type, n) (type *)realloc((var), sizeof(type) * (n))
#define GLOB_JUMP_TAG(status) ((status == -1) ? rb_memerror() : rb_jump_tag(status))
+/*
+ * ENOTDIR can be returned by stat(2) if a non-leaf element of the path
+ * is not a directory.
+ */
+#define to_be_ignored(e) ((e) == ENOENT || (e) == ENOTDIR)
+
+/* System call with warning */
+static int
+do_stat(const char *path, struct stat *pst, int flags)
+
+{
+ int ret = stat(path, pst);
+ if (ret < 0 && !to_be_ignored(errno))
+ sys_warning(path);
+
+ return ret;
+}
+
+static int
+do_lstat(const char *path, struct stat *pst, int flags)
+{
+ int ret = lstat(path, pst);
+ if (ret < 0 && !to_be_ignored(errno))
+ sys_warning(path);
+
+ return ret;
+}
+
+static DIR *
+do_opendir(const char *path, int flags)
+{
+ DIR *dirp = opendir(path);
+ if (dirp == NULL && !to_be_ignored(errno))
+ sys_warning(path);
+
+ return dirp;
+}
+
/* Return nonzero if S has any special globbing chars in it. */
static int
-has_magic(s, send, flags)
- const char *s, *send;
+has_magic(s, flags)
+ const char *s;
int flags;
{
- register const char *p = s;
- register char c;
- int open = 0;
const int escape = !(flags & FNM_NOESCAPE);
const int nocase = flags & FNM_CASEFOLD;
- while ((c = *p++) != '\0') {
+ register const char *p = s;
+ register char c;
+
+ while ((c = *p++) != 0) {
switch (c) {
- case '?':
case '*':
- return Qtrue;
-
- case '[': /* Only accept an open brace if there is a close */
- open++; /* brace to match it. Bracket expressions must be */
- continue; /* complete, according to Posix.2 */
- case ']':
- if (open)
- return Qtrue;
- continue;
+ case '?':
+ case '[':
+ return 1;
case '\\':
- if (escape && *p++ == '\0')
- return Qfalse;
- break;
+ if (escape && !(c = *p++))
+ return 0;
+ continue;
default:
if (!FNM_SYSCASE && ISALPHA(c) && nocase)
- return Qtrue;
+ return 1;
}
- if (send && p >= send) break;
+ p = Next(p-1);
}
- return Qfalse;
+
+ return 0;
}
-static char*
-extract_path(p, pend)
- const char *p, *pend;
+/* Find separator in globbing pattern. */
+static char *
+find_dirsep(const char *s, int flags)
{
- char *alloc;
- int len;
-
- len = pend - p;
- alloc = GLOB_ALLOC_N(char, len+1);
- if (!alloc) return NULL;
- memcpy(alloc, p, len);
- if (len > 1 && pend[-1] == '/'
-#if defined DOSISH_DRIVE_LETTER
- && pend[-2] != ':'
-#endif
- ) {
- alloc[len-1] = 0;
- }
- else {
- alloc[len] = 0;
- }
+ const int escape = !(flags & FNM_NOESCAPE);
- return alloc;
-}
+ register const char *p = s;
+ register char c;
+ int open = 0;
-static char*
-extract_elem(path)
- const char *path;
-{
- const char *pend;
+ while ((c = *p++) != 0) {
+ switch (c) {
+ case '[':
+ open = 1;
+ continue;
+ case ']':
+ open = 0;
+ continue;
+
+ case '/':
+ if (!open)
+ return (char *)p-1;
+ continue;
+
+ case '\\':
+ if (escape && !(c = *p++))
+ return (char *)p-1;
+ continue;
+ }
- pend = strchr(path, '/');
- if (!pend) pend = path + strlen(path);
+ p = Next(p-1);
+ }
- return extract_path(path, pend);
+ return (char *)p-1;
}
+/* Remove escaping backslashes */
static void
remove_backslashes(p)
char *p;
{
- char *pend = p + strlen(p);
char *t = p;
+ char *s = p;
- while (p < pend) {
+ while (*p) {
if (*p == '\\') {
- if (++p == pend) break;
+ if (t != s)
+ memmove(t, s, p - s);
+ t += p - s;
+ s = ++p;
+ if (!*p) break;
+ }
+ Inc(p);
+ }
+
+ while (*p++);
+
+ if (t != s)
+ memmove(t, s, p - s); /* move '\0' too */
+}
+
+/* Globing pattern */
+enum glob_pattern_type { PLAIN, MAGICAL, RECURSIVE, MATCH_ALL, MATCH_DIR };
+
+struct glob_pattern {
+ char *str;
+ enum glob_pattern_type type;
+ struct glob_pattern *next;
+};
+
+static void glob_free_pattern(struct glob_pattern *list);
+
+static struct glob_pattern *
+glob_make_pattern(const char *p, int flags)
+{
+ struct glob_pattern *list, *tmp, **tail = &list;
+ int dirsep = 0; /* pattern is terminated with '/' */
+
+ while (*p) {
+ tmp = GLOB_ALLOC(struct glob_pattern);
+ if (!tmp) goto error;
+ if (p[0] == '*' && p[1] == '*' && p[2] == '/') {
+ /* fold continuous RECURSIVEs (needed in glob_helper) */
+ do { p += 3; } while (p[0] == '*' && p[1] == '*' && p[2] == '/');
+ tmp->type = RECURSIVE;
+ tmp->str = 0;
+ dirsep = 1;
+ }
+ else {
+ const char *m = find_dirsep(p, flags);
+ char *buf = GLOB_ALLOC_N(char, m-p+1);
+ if (!buf) {
+ free(tmp);
+ goto error;
+ }
+ memcpy(buf, p, m-p);
+ buf[m-p] = '\0';
+ tmp->type = has_magic(buf, flags) ? MAGICAL : PLAIN;
+ tmp->str = buf;
+ if (*m) {
+ dirsep = 1;
+ p = m + 1;
+ }
+ else {
+ dirsep = 0;
+ p = m;
+ }
}
- *t++ = *p++;
+ *tail = tmp;
+ tail = &tmp->next;
+ }
+
+ tmp = GLOB_ALLOC(struct glob_pattern);
+ if (!tmp) {
+ error:
+ *tail = 0;
+ glob_free_pattern(list);
+ return 0;
}
- *t = '\0';
+ tmp->type = dirsep ? MATCH_DIR : MATCH_ALL;
+ tmp->str = 0;
+ *tail = tmp;
+ tmp->next = 0;
+
+ return list;
}
+static void
+glob_free_pattern(struct glob_pattern *list)
+{
+ while (list) {
+ struct glob_pattern *tmp = list;
+ list = list->next;
+ if (tmp->str)
+ free(tmp->str);
+ free(tmp);
+ }
+}
+
+static char *
+join_path(const char *path, int dirsep, const char *name)
+{
+ long len = strlen(path);
+ char *buf = GLOB_ALLOC_N(char, len+strlen(name)+(dirsep?1:0)+1);
+
+ if (!buf) return 0;
+ memcpy(buf, path, len);
+ if (dirsep) {
+ strcpy(buf+len, "/");
+ len++;
+ }
+ strcpy(buf+len, name);
+ return buf;
+}
+
+enum answer { YES, NO, UNKNOWN };
+
+#ifndef S_ISLNK
+# ifndef S_IFLNK
+# define S_ISLNK(m) (0)
+# else
+# define S_ISLNK(m) ((m & S_IFMT) == S_IFLNK)
+# endif
+#endif
+
#ifndef S_ISDIR
# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
#endif
@@ -946,235 +1221,239 @@ glob_func_caller(val)
#define glob_call_func(func, path, arg) (*func)(path, arg)
-static int glob_helper _((const char *path, const char *sub, int flags, int (*func)(const char *,VALUE), VALUE arg));
+static int glob_helper _((const char *, int, enum answer, enum answer, struct glob_pattern **, struct glob_pattern **, int, ruby_glob_func *, VALUE));
static int
-glob_helper(path, sub, flags, func, arg)
+glob_helper(path, dirsep, exist, isdir, beg, end, flags, func, arg)
const char *path;
- const char *sub;
+ int dirsep; /* '/' should be placed before appending child entry's name to 'path'. */
+ enum answer exist; /* Does 'path' indicate an existing entry? */
+ enum answer isdir; /* Does 'path' indicate a directory or a symlink to a directory? */
+ struct glob_pattern **beg;
+ struct glob_pattern **end;
int flags;
- int (*func) _((const char *, VALUE));
+ ruby_glob_func *func;
VALUE arg;
{
struct stat st;
- const char *p, *m;
int status = 0;
- char *buf = 0;
- char *newpath = 0;
- char *newbuf;
-
- p = sub ? sub : path;
- if (!has_magic(p, 0, flags)) {
-#if !defined DOSISH
- if (!(flags & FNM_NOESCAPE))
-#endif
- {
- newpath = strdup(path);
- if (!newpath) return -1;
- if (sub) {
- p = newpath + (sub - path);
- remove_backslashes(newpath + (sub - path));
- sub = p;
+ struct glob_pattern **cur, **new_beg, **new_end;
+ int plain = 0, magical = 0, recursive = 0, match_all = 0, match_dir = 0;
+ int escape = !(flags & FNM_NOESCAPE);
+
+ for (cur = beg; cur < end; ++cur) {
+ struct glob_pattern *p = *cur;
+ if (p->type == RECURSIVE) {
+ recursive = 1;
+ p = p->next;
+ }
+ switch (p->type) {
+ case PLAIN:
+ plain = 1;
+ break;
+ case MAGICAL:
+ magical = 1;
+ break;
+ case MATCH_ALL:
+ match_all = 1;
+ break;
+ case MATCH_DIR:
+ match_dir = 1;
+ break;
+ case RECURSIVE:
+ rb_bug("continuous RECURSIVEs");
+ }
+ }
+
+ if (*path) {
+ if (match_all && exist == UNKNOWN) {
+ if (do_lstat(path, &st, flags) == 0) {
+ exist = YES;
+ isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
}
else {
- remove_backslashes(newpath);
- p = path = newpath;
+ exist = NO;
+ isdir = NO;
}
}
- if (lstat(path, &st) == 0) {
+ if (match_dir && isdir == UNKNOWN) {
+ if (do_stat(path, &st, flags) == 0) {
+ exist = YES;
+ isdir = S_ISDIR(st.st_mode) ? YES : NO;
+ }
+ else {
+ exist = NO;
+ isdir = NO;
+ }
+ }
+ if (match_all && exist == YES) {
status = glob_call_func(func, path, arg);
+ if (status) return status;
}
- else if (errno != ENOENT) {
- /* In case stat error is other than ENOENT and
- we may want to know what is wrong. */
- sys_warning(path);
+ if (match_dir && isdir == YES) {
+ char *tmp = join_path(path, dirsep, "");
+ if (!tmp) return -1;
+ status = glob_call_func(func, tmp, arg);
+ free(tmp);
+ if (status) return status;
}
- if (newpath) free(newpath);
- return status;
}
- while (p && !status) {
- if (*p == '/') p++;
- m = strchr(p, '/');
- if (has_magic(p, m, flags)) {
- char *dir, *base, *magic;
- DIR *dirp;
- struct dirent *dp;
- int recursive = 0;
-
- struct d_link {
- char *path;
- struct d_link *next;
- } *tmp, *link, **tail = &link;
-
- base = extract_path(path, p);
- if (!base) {
+ if (exist == NO || isdir == NO) return 0;
+
+ if (magical || recursive) {
+ struct dirent *dp;
+ DIR *dirp = do_opendir(*path ? path : ".", flags);
+ if (dirp == NULL) return 0;
+
+ for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
+ char *buf = join_path(path, dirsep, dp->d_name);
+ enum answer new_isdir = UNKNOWN;
+
+ if (!buf) {
status = -1;
break;
}
- if (path == p) dir = ".";
- else dir = base;
+ if (recursive && strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0
+ && fnmatch("*", dp->d_name, flags) == 0) {
+#ifndef _WIN32
+ if (do_lstat(buf, &st, flags) == 0)
+ new_isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
+ else
+ new_isdir = NO;
+#else
+ new_isdir = dp->d_isdir ? (!dp->d_isrep ? YES : UNKNOWN) : NO;
+#endif
+ }
- magic = extract_elem(p);
- if (!magic) {
+ new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, (end - beg) * 2);
+ if (!new_beg) {
status = -1;
break;
}
- if (stat(dir, &st) < 0) {
- if (errno != ENOENT)
- sys_warning(dir);
- free(base);
- free(magic);
- break;
- }
- if (S_ISDIR(st.st_mode)) {
- if (m && strcmp(magic, "**") == 0) {
- int n = strlen(base);
- recursive = 1;
- newbuf = GLOB_REALLOC_N(buf, char, n+strlen(m)+3);
- if (!newbuf) {
- status = -1;
- goto finalize;
- }
- buf = newbuf;
- sprintf(buf, "%s%s", base, *base ? m : m+1);
- status = glob_helper(buf, buf+n, flags, func, arg);
- if (status) goto finalize;
+
+ for (cur = beg; cur < end; ++cur) {
+ struct glob_pattern *p = *cur;
+ if (p->type == RECURSIVE) {
+ if (new_isdir == YES) /* not symlink but real directory */
+ *new_end++ = p; /* append recursive pattern */
+ p = p->next; /* 0 times recursion */
}
- dirp = opendir(dir);
- if (dirp == NULL) {
- sys_warning(dir);
- free(base);
- free(magic);
- break;
+ if (p->type == PLAIN || p->type == MAGICAL) {
+ if (fnmatch(p->str, dp->d_name, flags) == 0)
+ *new_end++ = p->next;
}
}
- else {
- free(base);
- free(magic);
- break;
- }
-#if defined DOSISH_DRIVE_LETTER
-#define BASE (*base && !((isdirsep(*base) && !base[1]) || (base[1] == ':' && isdirsep(base[2]) && !base[3])))
-#else
-#define BASE (*base && !(isdirsep(*base) && !base[1]))
-#endif
+ status = glob_helper(buf, 1, YES, new_isdir, new_beg, new_end, flags, func, arg);
+ free(buf);
+ free(new_beg);
+ if (status) break;
+ }
- for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- if (recursive) {
- if (strcmp(".", dp->d_name) == 0 || strcmp("..", dp->d_name) == 0)
- continue;
- if (fnmatch("*", dp->d_name, flags) != 0)
- continue;
- newbuf = GLOB_REALLOC_N(buf, char, strlen(base)+NAMLEN(dp)+strlen(m)+6);
- if (!newbuf) {
- status = -1;
- break;
- }
- buf = newbuf;
- sprintf(buf, "%s%s%s", base, (BASE) ? "/" : "", dp->d_name);
- if (lstat(buf, &st) < 0) {
- if (errno != ENOENT)
- sys_warning(buf);
- continue;
- }
- if (S_ISDIR(st.st_mode)) {
- char *t = buf+strlen(buf);
- strcpy(t, "/**");
- strcpy(t+3, m);
- status = glob_helper(buf, t, flags, func, arg);
- if (status) break;
- continue;
- }
- continue;
+ closedir(dirp);
+ }
+ else if (plain) {
+ struct glob_pattern **copy_beg, **copy_end, **cur2;
+
+ copy_beg = copy_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg);
+ if (!copy_beg) return -1;
+ for (cur = beg; cur < end; ++cur)
+ *copy_end++ = (*cur)->type == PLAIN ? *cur : 0;
+
+ for (cur = copy_beg; cur < copy_end; ++cur) {
+ if (*cur) {
+ char *buf;
+ char *name;
+ name = GLOB_ALLOC_N(char, strlen((*cur)->str) + 1);
+ if (!name) {
+ status = -1;
+ break;
}
- if (fnmatch(magic, dp->d_name, flags) == 0) {
- newbuf = GLOB_REALLOC_N(buf, char, strlen(base)+NAMLEN(dp)+2);
- if (!newbuf) {
- status = -1;
- break;
- }
- buf = newbuf;
- sprintf(buf, "%s%s%s", base, (BASE) ? "/" : "", dp->d_name);
- if (!m) {
- status = glob_call_func(func, buf, arg);
- if (status) break;
- continue;
- }
- tmp = GLOB_ALLOC(struct d_link);
- if (!tmp) {
- status = -1;
- break;
- }
- tmp->path = buf;
- buf = 0;
- *tail = tmp;
- tail = &tmp->next;
+ strcpy(name, (*cur)->str);
+ if (escape) remove_backslashes(name);
+
+ new_beg = new_end = GLOB_ALLOC_N(struct glob_pattern *, end - beg);
+ if (!new_beg) {
+ free(name);
+ status = -1;
+ break;
}
- }
- closedir(dirp);
- finalize:
- *tail = 0;
- free(base);
- free(magic);
- if (link) {
- while (link) {
- if (status == 0) {
- if (stat(link->path, &st) == 0) {
- if (S_ISDIR(st.st_mode)) {
- int len = strlen(link->path);
- int mlen = strlen(m);
-
- newbuf = GLOB_REALLOC_N(buf, char, len+mlen+1);
- if (!newbuf) {
- status = -1;
- goto next_elem;
- }
- buf = newbuf;
- sprintf(buf, "%s%s", link->path, m);
- status = glob_helper(buf, buf+len, flags, func, arg);
- }
- }
- else {
- sys_warning(link->path);
- }
+ *new_end++ = (*cur)->next;
+ for (cur2 = cur + 1; cur2 < copy_end; ++cur2) {
+ if (*cur2 && fnmatch((*cur2)->str, name, flags) == 0) {
+ *new_end++ = (*cur2)->next;
+ *cur2 = 0;
}
- next_elem:
- tmp = link;
- link = link->next;
- free(tmp->path);
- free(tmp);
}
- break;
+
+ buf = join_path(path, dirsep, name);
+ free(name);
+ if (!buf) {
+ free(new_beg);
+ status = -1;
+ break;
+ }
+ status = glob_helper(buf, 1, UNKNOWN, UNKNOWN, new_beg, new_end, flags, func, arg);
+ free(buf);
+ free(new_beg);
+ if (status) break;
}
}
- p = m;
+
+ free(copy_beg);
}
- if (buf) free(buf);
- if (newpath) free(newpath);
+
return status;
}
-int
-ruby_glob(path, flags, func, arg)
+static int
+ruby_glob0(path, flags, func, arg)
const char *path;
int flags;
- int (*func) _((const char *, VALUE));
+ ruby_glob_func *func;
VALUE arg;
{
+ struct glob_pattern *list;
+ const char *root, *start;
+ char *buf;
+ int n;
+ int status;
+
+ start = root = path;
flags |= FNM_SYSCASE;
- return glob_helper(path, 0, flags & ~GLOB_VERBOSE, func, arg);
+#if defined DOSISH
+ root = rb_path_skip_prefix(root);
+#endif
+
+ if (root && *root == '/') root++;
+
+ n = root - start;
+ buf = GLOB_ALLOC_N(char, n + 1);
+ if (!buf) return -1;
+ MEMCPY(buf, start, char, n);
+ buf[n] = '\0';
+
+ list = glob_make_pattern(root, flags);
+ if (!list) {
+ free(buf);
+ return -1;
+ }
+ status = glob_helper(buf, 0, UNKNOWN, UNKNOWN, &list, &list + 1, flags, func, arg);
+ glob_free_pattern(list);
+ free(buf);
+
+ return status;
}
int
-ruby_globi(path, flags, func, arg)
+ruby_glob(path, flags, func, arg)
const char *path;
int flags;
- int (*func) _((const char *, VALUE));
+ ruby_glob_func *func;
VALUE arg;
{
- return glob_helper(path, 0, flags | FNM_CASEFOLD, func, arg);
+ return ruby_glob0(path, flags & ~GLOB_VERBOSE, func, arg);
}
static int rb_glob_caller _((const char *, VALUE));
@@ -1204,8 +1483,11 @@ rb_glob2(path, flags, func, arg)
args.func = func;
args.v = arg;
- flags |= FNM_SYSCASE;
- return glob_helper(path, 0, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args);
+ if (flags & FNM_SYSCASE) {
+ rb_warning("Dir.glob() ignores File::FNM_CASEFOLD");
+ }
+
+ return ruby_glob0(path, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args);
}
void
@@ -1215,19 +1497,10 @@ rb_glob(path, func, arg)
VALUE arg;
{
int status = rb_glob2(path, 0, func, arg);
- if (status) rb_jump_tag(status);
-}
-
-void
-rb_globi(path, func, arg)
- const char *path;
- void (*func) _((const char*, VALUE));
- VALUE arg;
-{
- int status = rb_glob2(path, FNM_CASEFOLD, func, arg);
- if (status) rb_jump_tag(status);
+ if (status) GLOB_JUMP_TAG(status);
}
+static void push_pattern _((const char* path, VALUE ary));
static void
push_pattern(path, ary)
const char *path;
@@ -1236,155 +1509,196 @@ push_pattern(path, ary)
rb_ary_push(ary, rb_tainted_str_new2(path));
}
-static int
-push_globs(ary, s, flags)
- VALUE ary;
- const char *s;
- int flags;
-{
- return rb_glob2(s, flags, push_pattern, ary);
-}
-
-static int
-push_braces(ary, str, flags)
- VALUE ary;
+int
+ruby_brace_expand(str, flags, func, arg)
const char *str;
int flags;
+ ruby_glob_func *func;
+ VALUE arg;
{
- char *buf = 0;
- char *b, *newbuf;
- const char *s, *p, *t;
- const char *lbrace, *rbrace;
- int nest = 0;
- int status = 0;
+ const int escape = !(flags & FNM_NOESCAPE);
+ const char *p = str;
+ const char *s = p;
+ const char *lbrace = 0, *rbrace = 0;
+ int nest = 0, status = 0;
- s = p = str;
- lbrace = rbrace = 0;
while (*p) {
- if (*p == '{') {
+ if (*p == '{' && nest++ == 0) {
lbrace = p;
- break;
}
- p++;
- }
- while (*p) {
- if (*p == '{') nest++;
- if (*p == '}' && --nest == 0) {
+ if (*p == '}' && --nest <= 0) {
rbrace = p;
break;
}
- p++;
+ if (*p == '\\' && escape) {
+ if (!*++p) break;
+ }
+ Inc(p);
}
if (lbrace && rbrace) {
- int len = strlen(s);
+ char *buf = GLOB_ALLOC_N(char, strlen(s) + 1);
+ long shift;
+
+ if (!buf) return -1;
+ memcpy(buf, s, lbrace-s);
+ shift = (lbrace-s);
p = lbrace;
- while (*p != '}') {
- t = p + 1;
- for (p = t; *p!='}' && *p!=','; p++) {
- /* skip inner braces */
- if (*p == '{') {
- nest = 1;
- while (*++p != '}' || --nest) {
- if (*p == '{') nest++;
- }
+ while (p < rbrace) {
+ const char *t = ++p;
+ nest = 0;
+ while (p < rbrace && !(*p == ',' && nest == 0)) {
+ if (*p == '{') nest++;
+ if (*p == '}') nest--;
+ if (*p == '\\' && escape) {
+ if (++p == rbrace) break;
}
+ Inc(p);
}
- newbuf = GLOB_REALLOC_N(buf, char, len+1);
- if (!newbuf) {
- status = -1;
- break;
- }
- buf = newbuf;
- memcpy(buf, s, lbrace-s);
- b = buf + (lbrace-s);
- memcpy(b, t, p-t);
- strcpy(b+(p-t), rbrace+1);
- status = push_braces(ary, buf, flags);
+ memcpy(buf+shift, t, p-t);
+ strcpy(buf+shift+(p-t), rbrace+1);
+ status = ruby_brace_expand(buf, flags, func, arg);
if (status) break;
}
+ free(buf);
}
- else {
- status = push_globs(ary, str, flags);
+ else if (!lbrace && !rbrace) {
+ status = (*func)(s, arg);
}
- if (buf) free(buf);
return status;
}
-#define isdelim(c) ((c)=='\0')
+struct brace_args {
+ ruby_glob_func *func;
+ VALUE value;
+ int flags;
+};
+
+static int glob_brace _((const char *, VALUE));
+static int
+glob_brace(path, val)
+ const char *path;
+ VALUE val;
+{
+ struct brace_args *arg = (struct brace_args *)val;
+
+ return ruby_glob0(path, arg->flags, arg->func, arg->value);
+}
+
+static int
+ruby_brace_glob0(str, flags, func, arg)
+ const char *str;
+ int flags;
+ ruby_glob_func *func;
+ VALUE arg;
+{
+ struct brace_args args;
+
+ args.func = func;
+ args.value = arg;
+ args.flags = flags;
+ return ruby_brace_expand(str, flags, glob_brace, (VALUE)&args);
+}
+
+int
+ruby_brace_glob(str, flags, func, arg)
+ const char *str;
+ int flags;
+ ruby_glob_func *func;
+ VALUE arg;
+{
+ return ruby_brace_glob0(str, flags & ~GLOB_VERBOSE, func, arg);
+}
+
+static int
+push_glob(VALUE ary, const char *str, int flags)
+{
+ struct glob_args args;
+
+ args.func = push_pattern;
+ args.v = ary;
+ return ruby_brace_glob0(str, flags | GLOB_VERBOSE, rb_glob_caller, (VALUE)&args);
+}
static VALUE
-rb_push_glob(str, flags)
+rb_push_glob(str, flags) /* '\0' is delimiter */
VALUE str;
int flags;
{
- const char *p, *pend, *buf;
- int nest, maxnest;
- int status = 0;
- int noescape = flags & FNM_NOESCAPE;
+ long offset = 0;
VALUE ary;
ary = rb_ary_new();
SafeStringValue(str);
- p = RSTRING(str)->ptr;
- pend = p + RSTRING(str)->len;
-
- while (p < pend) {
- nest = maxnest = 0;
- while (p < pend && isdelim(*p)) p++;
- buf = p;
- while (p < pend && !isdelim(*p)) {
- if (*p == '{') nest++, maxnest++;
- if (*p == '}') nest--;
- if (!noescape && *p == '\\') {
- if (++p == pend) break;
- }
+
+ while (offset < RSTRING_LEN(str)) {
+ int status = push_glob(ary, RSTRING(str)->ptr + offset, flags);
+ char *p, *pend;
+ if (status) GLOB_JUMP_TAG(status);
+ if (offset >= RSTRING_LEN(str)) break;
+ p = RSTRING(str)->ptr + offset;
+ p += strlen(p) + 1;
+ pend = RSTRING(str)->ptr + RSTRING_LEN(str);
+ while (p < pend && !*p)
p++;
- }
- if (maxnest == 0) {
- status = push_globs(ary, buf, flags);
- if (status) break;
- }
- else if (nest == 0) {
- status = push_braces(ary, buf, flags);
- if (status) break;
- }
- /* else unmatched braces */
+ offset = p - RSTRING(str)->ptr;
}
- if (status) GLOB_JUMP_TAG(status);
- if (rb_block_given_p()) {
- rb_ary_each(ary);
- return Qnil;
+
+ return ary;
+}
+
+static VALUE
+dir_globs(argc, argv, flags)
+ long argc;
+ VALUE *argv;
+ int flags;
+{
+ VALUE ary = rb_ary_new();
+ long i;
+
+ for (i = 0; i < argc; ++i) {
+ int status;
+ VALUE str = argv[i];
+ StringValue(str);
+ status = push_glob(ary, RSTRING(str)->ptr, flags);
+ if (status) GLOB_JUMP_TAG(status);
}
+
return ary;
}
/*
* call-seq:
- * Dir[ string ] => array
+ * Dir[ array ] => array
+ * Dir[ string [, string ...] ] => array
*
* Equivalent to calling
- * <em>dir</em>.<code>glob(</code><i>string,</i><code>0)</code>.
+ * <code>Dir.glob(</code><i>array,</i><code>0)</code> and
+ * <code>Dir.glob([</code><i>string,...</i><code>],0)</code>.
*
*/
static VALUE
-dir_s_aref(obj, str)
- VALUE obj, str;
-{
- return rb_push_glob(str, 0);
-}
+dir_s_aref(int argc, VALUE *argv, VALUE obj)
+ {
+ if (argc == 1) {
+ return rb_push_glob(argv[0], 0);
+ }
+ return dir_globs(argc, argv, 0);
+ }
/*
* call-seq:
- * Dir.glob( string, [flags] ) => array
- * Dir.glob( string, [flags] ) {| filename | block } => nil
+ * Dir.glob( pattern, [flags] ) => array
+ * Dir.glob( pattern, [flags] ) {| filename | block } => nil
*
- * Returns the filenames found by expanding the pattern given in
- * <i>string</i>, either as an <i>array</i> or as parameters to the
- * block. Note that this pattern is not a regexp (it's closer to a
- * shell glob). See <code>File::fnmatch</code> for the meaning of
- * the <i>flags</i> parameter.
+ * Returns the filenames found by expanding <i>pattern</i> which is
+ * an +Array+ of the patterns or the pattern +String+, either as an
+ * <i>array</i> or as parameters to the block. Note that this pattern
+ * is not a regexp (it's closer to a shell glob). See
+ * <code>File::fnmatch</code> for the meaning of the <i>flags</i>
+ * parameter. Note that case sensitivity depends on your system (so
+ * <code>File::FNM_CASEFOLD</code> is ignored)
*
* <code>*</code>:: Matches any file. Can be restricted by
* other values in the glob. <code>*</code>
@@ -1439,7 +1753,7 @@ dir_s_glob(argc, argv, obj)
VALUE *argv;
VALUE obj;
{
- VALUE str, rflags;
+ VALUE str, rflags, ary;
int flags;
if (rb_scan_args(argc, argv, "11", &str, &rflags) == 2)
@@ -1447,7 +1761,20 @@ dir_s_glob(argc, argv, obj)
else
flags = 0;
- return rb_push_glob(str, flags);
+ ary = rb_check_array_type(str);
+ if (NIL_P(ary)) {
+ ary = rb_push_glob(str, flags);
+ }
+ else {
+ volatile VALUE v = ary;
+ ary = dir_globs(RARRAY_LEN(v), RARRAY_PTR(v), flags);
+ }
+
+ if (rb_block_given_p()) {
+ rb_ary_each(ary);
+ return Qnil;
+ }
+ return ary;
}
static VALUE
@@ -1488,6 +1815,7 @@ dir_foreach(io, dirname)
{
VALUE dir;
+ RETURN_ENUMERATOR(io, 1, &dirname);
dir = dir_open_dir(dirname);
rb_ensure(dir_each, dir, dir_close, dir);
return Qnil;
@@ -1534,6 +1862,8 @@ dir_entries(io, dirname)
* have <code>c</code> in them (including at
* the beginning or end). Equivalent to
* <code>/ .* /x</code> in regexp.
+ * <code>**</code>:: Matches directories recursively or files
+ * expansively.
* <code>?</code>:: Matches any one character. Equivalent to
* <code>/.{1}/</code> in regexp.
* <code>[set]</code>:: Matches any one character in +set+.
@@ -1546,31 +1876,52 @@ dir_entries(io, dirname)
* parameters. The same glob pattern and flags are used by
* <code>Dir::glob</code>.
*
- * File.fnmatch('cat', 'cat') #=> true
- * File.fnmatch('cat', 'category') #=> false
- * File.fnmatch('c{at,ub}s', 'cats') #=> false
- * File.fnmatch('c{at,ub}s', 'cubs') #=> false
- * File.fnmatch('c{at,ub}s', 'cat') #=> false
+ * File.fnmatch('cat', 'cat') #=> true : match entire string
+ * File.fnmatch('cat', 'category') #=> false : only match partial string
+ * File.fnmatch('c{at,ub}s', 'cats') #=> false : { } isn't supported
+ *
+ * File.fnmatch('c?t', 'cat') #=> true : '?' match only 1 character
+ * File.fnmatch('c??t', 'cat') #=> false : ditto
+ * File.fnmatch('c*', 'cats') #=> true : '*' match 0 or more characters
+ * File.fnmatch('c*t', 'c/a/b/t') #=> true : ditto
+ * File.fnmatch('ca[a-z]', 'cat') #=> true : inclusive bracket expression
+ * File.fnmatch('ca[^t]', 'cat') #=> false : exclusive bracket expression ('^' or '!')
+ *
+ * File.fnmatch('cat', 'CAT') #=> false : case sensitive
+ * File.fnmatch('cat', 'CAT', File::FNM_CASEFOLD) #=> true : case insensitive
+ *
+ * File.fnmatch('?', '/', File::FNM_PATHNAME) #=> false : wildcard doesn't match '/' on FNM_PATHNAME
+ * File.fnmatch('*', '/', File::FNM_PATHNAME) #=> false : ditto
+ * File.fnmatch('[/]', '/', File::FNM_PATHNAME) #=> false : ditto
+ *
+ * File.fnmatch('\?', '?') #=> true : escaped wildcard becomes ordinary
+ * File.fnmatch('\a', 'a') #=> true : escaped ordinary remains ordinary
+ * File.fnmatch('\a', '\a', File::FNM_NOESCAPE) #=> true : FNM_NOESACPE makes '\' ordinary
+ * File.fnmatch('[\?]', '?') #=> true : can escape inside bracket expression
+ *
+ * File.fnmatch('*', '.profile') #=> false : wildcard doesn't match leading
+ * File.fnmatch('*', '.profile', File::FNM_DOTMATCH) #=> true period by default.
+ * File.fnmatch('.*', '.profile') #=> true
+ *
+ * rbfiles = '**' '/' '*.rb' # you don't have to do like this. just write in single string.
+ * File.fnmatch(rbfiles, 'main.rb') #=> false
+ * File.fnmatch(rbfiles, './main.rb') #=> false
+ * File.fnmatch(rbfiles, 'lib/song.rb') #=> true
+ * File.fnmatch('**.rb', 'main.rb') #=> true
+ * File.fnmatch('**.rb', './main.rb') #=> false
+ * File.fnmatch('**.rb', 'lib/song.rb') #=> true
+ * File.fnmatch('*', 'dave/.profile') #=> true
*
- * File.fnmatch('c?t', 'cat') #=> true
- * File.fnmatch('c\?t', 'cat') #=> false
- * File.fnmatch('c??t', 'cat') #=> false
- * File.fnmatch('c*', 'cats') #=> true
- * File.fnmatch('c/ * FIXME * /t', 'c/a/b/c/t') #=> true
- * File.fnmatch('c*t', 'cat') #=> true
- * File.fnmatch('c\at', 'cat') #=> true
- * File.fnmatch('c\at', 'cat', File::FNM_NOESCAPE) #=> false
- * File.fnmatch('a?b', 'a/b') #=> true
- * File.fnmatch('a?b', 'a/b', File::FNM_PATHNAME) #=> false
+ * pattern = '*' '/' '*'
+ * File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME) #=> false
+ * File.fnmatch(pattern, 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
*
- * File.fnmatch('*', '.profile') #=> false
- * File.fnmatch('*', '.profile', File::FNM_DOTMATCH) #=> true
- * File.fnmatch('*', 'dave/.profile') #=> true
- * File.fnmatch('*', 'dave/.profile', File::FNM_DOTMATCH) #=> true
- * File.fnmatch('*', 'dave/.profile', File::FNM_PATHNAME) #=> false
- * File.fnmatch('* / FIXME *', 'dave/.profile', File::FNM_PATHNAME) #=> false
- * STRICT = File::FNM_PATHNAME | File::FNM_DOTMATCH
- * File.fnmatch('* / FIXME *', 'dave/.profile', STRICT) #=> true
+ * pattern = '**' '/' 'foo'
+ * File.fnmatch(pattern, 'a/b/c/foo', File::FNM_PATHNAME) #=> true
+ * File.fnmatch(pattern, '/a/b/c/foo', File::FNM_PATHNAME) #=> true
+ * File.fnmatch(pattern, 'c:/a/b/c/foo', File::FNM_PATHNAME) #=> true
+ * File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME) #=> false
+ * File.fnmatch(pattern, 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
*/
static VALUE
file_s_fnmatch(argc, argv, obj)
@@ -1621,6 +1972,7 @@ Init_Dir()
rb_define_method(rb_cDir,"initialize", dir_initialize, 1);
rb_define_method(rb_cDir,"path", dir_path, 0);
+ rb_define_method(rb_cDir,"inspect", dir_inspect, 0);
rb_define_method(rb_cDir,"read", dir_read, 0);
rb_define_method(rb_cDir,"each", dir_each, 0);
rb_define_method(rb_cDir,"rewind", dir_rewind, 0);
@@ -1640,7 +1992,7 @@ Init_Dir()
rb_define_singleton_method(rb_cDir,"unlink", dir_s_rmdir, 1);
rb_define_singleton_method(rb_cDir,"glob", dir_s_glob, -1);
- rb_define_singleton_method(rb_cDir,"[]", dir_s_aref, 1);
+ rb_define_singleton_method(rb_cDir,"[]", dir_s_aref, -1);
rb_define_singleton_method(rb_cFile,"fnmatch", file_s_fnmatch, -1);
rb_define_singleton_method(rb_cFile,"fnmatch?", file_s_fnmatch, -1);
diff --git a/dln.c b/dln.c
index 016d0c12a2..5ba25b6415 100644
--- a/dln.c
+++ b/dln.c
@@ -2,8 +2,8 @@
dln.c -
- $Author: matz $
- $Date: 2006/08/07 03:43:39 $
+ $Author$
+ $Date$
created at: Tue Jan 18 17:05:06 JST 1994
Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -81,19 +81,28 @@ char *getenv();
# 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) */
+# define MACOSX_DLOPEN
+# else
+# define MACOSX_DYLD
+# endif
+#endif
+
#ifdef __BEOS__
# include <image.h>
#endif
#ifndef NO_DLN_LOAD
-#if defined(HAVE_DLOPEN) && !defined(USE_DLN_A_OUT) && !defined(_AIX) && !defined(__APPLE__) && !defined(_UNICOSMP)
+#if defined(HAVE_DLOPEN) && !defined(USE_DLN_A_OUT) && !defined(_AIX) && !defined(MACOSX_DYLD) && !defined(_UNICOSMP)
/* dynamic load with dlopen() */
# define USE_DLN_DLOPEN
#endif
#ifndef FUNCNAME_PATTERN
-# if defined(__hp9000s300) || (defined(__NetBSD__) && !defined(__ELF__)) || defined(__BORLANDC__) || (defined(__FreeBSD__) && !defined(__ELF__)) || (defined(__OpenBSD__) && !defined(__ELF__)) || defined(NeXT) || defined(__WATCOMC__) || defined(__APPLE__)
+# if defined(__hp9000s300) || (defined(__NetBSD__) && !defined(__ELF__)) || defined(__BORLANDC__) || (defined(__FreeBSD__) && !defined(__ELF__)) || (defined(__OpenBSD__) && !defined(__ELF__)) || defined(NeXT) || defined(__WATCOMC__) || defined(MACOSX_DYLD)
# define FUNCNAME_PATTERN "_Init_%s"
# else
# define FUNCNAME_PATTERN "Init_%s"
@@ -636,7 +645,7 @@ load_1(fd, disp, need_init)
long disp;
const char *need_init;
{
- static char *libc = LIBC_NAME;
+ static const char *libc = LIBC_NAME;
struct exec hdr;
struct relocation_info *reloc = NULL;
long block = 0;
@@ -1141,7 +1150,7 @@ dln_sym(name)
#endif
#endif
#else
-#ifdef __APPLE__
+#ifdef MACOSX_DYLD
#include <mach-o/dyld.h>
#endif
#endif
@@ -1403,7 +1412,7 @@ dln_load(file)
}
#endif /* _AIX */
-#if defined(NeXT) || defined(__APPLE__)
+#if defined(NeXT) || defined(MACOSX_DYLD)
#define DLN_DEFINED
/*----------------------------------------------------
By SHIROYAMA Takayuki Psi@fortune.nest.or.jp
@@ -1527,7 +1536,7 @@ dln_load(file)
}
#endif /* __BEOS__*/
-#ifdef __MACOS__
+#ifdef __MACOS__ /* Mac OS 9 or before */
# define DLN_DEFINED
{
OSErr err;
@@ -1676,64 +1685,35 @@ dln_find_file(fname, path)
#endif
}
-#if defined(__CYGWIN32__)
-const char *
-conv_to_posix_path(win32, posix, len)
- char *win32;
- char *posix;
- int len;
-{
- char *first = win32;
- char *p = win32;
- char *dst = posix;
-
- posix[0] = '\0';
- for (p = win32; *p; p++)
- if (*p == ';') {
- *p = 0;
- cygwin32_conv_to_posix_path(first, posix);
- posix += strlen(posix);
- *posix++ = ':';
- first = p + 1;
- *p = ';';
- }
- if (len < strlen(first))
- fprintf(stderr, "PATH length too long: %s\n", first);
- else
- cygwin32_conv_to_posix_path(first, posix);
- return dst;
-}
-#endif
-
static char fbuf[MAXPATHLEN];
static char *
dln_find_1(fname, path, exe_flag)
- char *fname;
- char *path;
+ const char *fname;
+ const char *path;
int exe_flag; /* non 0 if looking for executable. */
{
- register char *dp;
- register char *ep;
+ register const char *dp;
+ register const char *ep;
register char *bp;
struct stat st;
#ifdef __MACOS__
const char* mac_fullpath;
#endif
- if (!fname) return fname;
- if (fname[0] == '/') return fname;
+ if (!fname) return (char *)fname;
+ if (fname[0] == '/') return (char *)fname;
if (strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0)
- return fname;
- if (exe_flag && strchr(fname, '/')) return fname;
+ return (char *)fname;
+ if (exe_flag && strchr(fname, '/')) return (char *)fname;
#ifdef DOSISH
- if (fname[0] == '\\') return fname;
+ if (fname[0] == '\\') return (char *)fname;
# ifdef DOSISH_DRIVE_LETTER
- if (strlen(fname) > 2 && fname[1] == ':') return fname;
+ if (strlen(fname) > 2 && fname[1] == ':') return (char *)fname;
# endif
if (strncmp(".\\", fname, 2) == 0 || strncmp("..\\", fname, 3) == 0)
- return fname;
- if (exe_flag && strchr(fname, '\\')) return fname;
+ return (char *)fname;
+ if (exe_flag && strchr(fname, '\\')) return (char *)fname;
#endif
for (dp = path;; dp = ++ep) {
@@ -1801,26 +1781,9 @@ dln_find_1(fname, path, exe_flag)
}
memcpy(bp, fname, i + 1);
-#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
#if defined(DOSISH)
if (exe_flag) {
- static const char *extension[] = {
+ static const char extension[][5] = {
#if defined(MSDOS)
".com", ".exe", ".bat",
#if defined(DJGPP)
@@ -1833,11 +1796,10 @@ dln_find_1(fname, path, exe_flag)
".r", ".R", ".x", ".X", ".bat", ".BAT",
/* __human68k__ */
#endif
- (char *) NULL
};
int j;
- for (j = 0; extension[j]; j++) {
+ for (j = 0; j < sizeof(extension) / sizeof(extension[0]); j++) {
if (fspace < strlen(extension[j])) {
fprintf(stderr, "openpath: pathname too long (ignored)\n");
fprintf(stderr, "\tDirectory \"%.*s\"\n", (int) (bp - fbuf), fbuf);
@@ -1854,9 +1816,28 @@ dln_find_1(fname, path, exe_flag)
#endif
}
+ goto next;
}
#endif /* MSDOS or _WIN32 or __human68k__ 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/dln.h b/dln.h
index 3d52ea2827..182cf9f9f4 100644
--- a/dln.h
+++ b/dln.h
@@ -2,8 +2,8 @@
dln.h -
- $Author: michal $
- $Date: 2003/01/16 07:34:01 $
+ $Author$
+ $Date$
created at: Wed Jan 19 16:53:09 JST 1994
Copyright (C) 1993-2003 Yukihiro Matsumoto
diff --git a/doc/NEWS b/doc/NEWS-1.8.0
index b4445fa59f..b4445fa59f 100644
--- a/doc/NEWS
+++ b/doc/NEWS-1.8.0
diff --git a/doc/forwardable.rd b/doc/forwardable.rd
index f9c8234761..7272c374b6 100644
--- a/doc/forwardable.rd
+++ b/doc/forwardable.rd
@@ -1,8 +1,8 @@
-- forwardable.rb
$Release Version: 1.1 $
- $Revision: 1.2 $
- $Date: 2001/05/07 23:52:57 $
+ $Revision$
+ $Date$
Original version by Tosh
=begin
diff --git a/doc/forwardable.rd.ja b/doc/forwardable.rd.ja
index a56823dd1a..d928fddc5e 100644
--- a/doc/forwardable.rd.ja
+++ b/doc/forwardable.rd.ja
@@ -1,7 +1,7 @@
-- forwatable.rb
$Release Version: 1.1 $
- $Revision: 1.1 $
- $Date: 2001/07/19 05:42:06 $
+ $Revision$
+ $Date$
=begin
= Forwardable
diff --git a/doc/irb/irb-tools.rd.ja b/doc/irb/irb-tools.rd.ja
index 38145576dc..64d9ab29c8 100644
--- a/doc/irb/irb-tools.rd.ja
+++ b/doc/irb/irb-tools.rd.ja
@@ -1,7 +1,7 @@
irbϢޤޥɤȥ饤֥
$Release Version: 0.7.1 $
- $Revision: 1.1 $
- $Date: 2001/07/19 05:42:06 $
+ $Revision$
+ $Date$
by Keiju ISHITSUKA(Nihon Rational Co.,Ltd.)
=begin
diff --git a/doc/irb/irb.rd b/doc/irb/irb.rd
index f56e8b60e0..a42cd46680 100644
--- a/doc/irb/irb.rd
+++ b/doc/irb/irb.rd
@@ -1,7 +1,7 @@
irb -- interactive ruby
$Release Version: 0.9 $
- $Revision: 1.6 $
- $Date: 2003/07/31 16:34:07 $
+ $Revision$
+ $Date$
by Keiju ISHITSUKA(keiju@ishitsuka.com)
by gotoken-san who is original translater from japanese version
diff --git a/doc/irb/irb.rd.ja b/doc/irb/irb.rd.ja
index aa3c0e13aa..338dcc644e 100644
--- a/doc/irb/irb.rd.ja
+++ b/doc/irb/irb.rd.ja
@@ -1,7 +1,7 @@
irb -- interactive ruby
$Release Version: 0.9.5 $
- $Revision: 1.3.2.1 $
- $Date: 2005/04/19 19:24:56 $
+ $Revision$
+ $Date$
by Keiju ISHITSUKA(keiju@ruby-lang.org)
=begin
= irbȤ?
diff --git a/doc/shell.rd b/doc/shell.rd
index ae6855cbd8..02ee1b020a 100644
--- a/doc/shell.rd
+++ b/doc/shell.rd
@@ -1,7 +1,7 @@
-- shell.rb
$Release Version: 0.6.0 $
- $Revision: 1.2 $
- $Date: 2001/05/17 10:09:49 $
+ $Revision$
+ $Date$
by Keiju ISHITSUKA(keiju@ishitsuka.com)
=begin
diff --git a/doc/shell.rd.ja b/doc/shell.rd.ja
index aab9e5c7d2..073e71ea42 100644
--- a/doc/shell.rd.ja
+++ b/doc/shell.rd.ja
@@ -1,7 +1,7 @@
-- shell.rb
$Release Version: 0.6.0 $
- $Revision: 1.1 $
- $Date: 2001/07/19 05:42:06 $
+ $Revision$
+ $Date$
by Keiju ISHITSUKA(keiju@ishitsuka.com)
=begin
diff --git a/enum.c b/enum.c
index 112a5f820b..df35c2fe03 100644
--- a/enum.c
+++ b/enum.c
@@ -2,8 +2,8 @@
enum.c -
- $Author: drbrain $
- $Date: 2006/06/15 01:24:40 $
+ $Author$
+ $Date$
created at: Fri Oct 1 15:15:19 JST 1993
Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -15,7 +15,43 @@
#include "util.h"
VALUE rb_mEnumerable;
-static ID id_each, id_eqq, id_cmp;
+static ID id_each, id_eqq, id_cmp, id_size;
+
+struct iter_method_arg {
+ VALUE obj;
+ ID mid;
+ int argc;
+ VALUE *argv;
+};
+
+static VALUE iterate_method _((VALUE obj));
+static VALUE
+iterate_method(obj)
+ VALUE obj;
+{
+ struct iter_method_arg *arg;
+
+ arg = (struct iter_method_arg *)obj;
+ return rb_funcall2(arg->obj, arg->mid, arg->argc, arg->argv);
+}
+
+VALUE
+rb_block_call(obj, mid, argc, argv, bl_proc, data2)
+ VALUE obj;
+ ID mid;
+ int argc;
+ VALUE *argv;
+ VALUE (*bl_proc) (ANYARGS);
+ VALUE data2;
+{
+ struct iter_method_arg arg;
+
+ arg.obj = obj;
+ arg.mid = mid;
+ arg.argc = argc;
+ arg.argv = argv;
+ return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
+}
VALUE
rb_each(obj)
@@ -48,18 +84,18 @@ grep_iter_i(i, arg)
* call-seq:
* enum.grep(pattern) => array
* enum.grep(pattern) {| obj | block } => array
- *
+ *
* Returns an array of every element in <i>enum</i> for which
* <code>Pattern === element</code>. If the optional <em>block</em> is
* supplied, each matching element is passed to it, and the block's
* result is stored in the output array.
- *
+ *
* (1..100).grep 38..44 #=> [38, 39, 40, 41, 42, 43, 44]
* c = IO.constants
* c.grep(/SEEK/) #=> ["SEEK_END", "SEEK_SET", "SEEK_CUR"]
* res = c.grep(/SEEK/) {|v| IO.const_get(v) }
* res #=> [2, 0, 1]
- *
+ *
*/
static VALUE
@@ -73,10 +109,99 @@ enum_grep(obj, pat)
arg[1] = ary;
rb_iterate(rb_each, obj, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)arg);
-
+
return ary;
}
+static VALUE count_i _((VALUE, VALUE));
+static VALUE
+count_i(i, memop)
+ VALUE i, memop;
+{
+ VALUE *memo = (VALUE*)memop;
+
+ if (rb_equal(i, memo[1])) {
+ memo[0]++;
+ }
+ return Qnil;
+}
+
+static VALUE count_iter_i _((VALUE, VALUE));
+static VALUE
+count_iter_i(i, memop)
+ VALUE i, memop;
+{
+ VALUE *memo = (VALUE*)memop;
+
+ if (RTEST(rb_yield(i))) {
+ memo[0]++;
+ }
+ return Qnil;
+}
+
+static VALUE count_all_i _((VALUE, VALUE));
+static VALUE
+count_all_i(i, memop)
+ VALUE i, memop;
+{
+ VALUE *memo = (VALUE*)memop;
+
+ memo[0]++;
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.count => int
+ * enum.count(item) => int
+ * enum.count {| obj | block } => int
+ *
+ * Returns the number of items in <i>enum</i>, where #size is called
+ * if it responds to it, otherwise the items are counted through
+ * enumeration. If an argument is given, counts the number of items
+ * in <i>enum</i>, for which equals to <i>item</i>. If a block is
+ * given, counts the number of elements yielding a true value.
+ *
+ * ary = [1, 2, 4, 2]
+ * ary.count # => 4
+ * ary.count(2) # => 2
+ * ary.count{|x|x%2==0} # => 3
+ *
+ */
+
+static VALUE
+enum_count(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE memo[2]; /* [count, condition value] */
+ rb_block_call_func *func;
+
+ if (argc == 0) {
+ if (rb_block_given_p()) {
+ func = count_iter_i;
+ }
+ else {
+ if (rb_respond_to(obj, id_size)) {
+ return rb_funcall(obj, id_size, 0, 0);
+ }
+ func = count_all_i;
+ }
+ }
+ else {
+ rb_scan_args(argc, argv, "1", &memo[1]);
+ if (rb_block_given_p()) {
+ rb_warn("given block not used");
+ }
+ func = count_i;
+ }
+
+ memo[0] = 0;
+ rb_block_call(obj, id_each, 0, 0, func, (VALUE)&memo);
+ return INT2NUM(memo[0]);
+}
+
static VALUE
find_i(i, memo)
VALUE i;
@@ -93,15 +218,15 @@ find_i(i, memo)
* call-seq:
* enum.detect(ifnone = nil) {| obj | block } => obj or nil
* enum.find(ifnone = nil) {| obj | block } => obj or nil
- *
+ *
* Passes each entry in <i>enum</i> to <em>block</em>. Returns the
* first for which <em>block</em> is not <code>false</code>. If no
* object matches, calls <i>ifnone</i> and returns its result when it
* is specified, or returns <code>nil</code>
- *
+ *
* (1..10).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> nil
* (1..100).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> 35
- *
+ *
*/
static VALUE
@@ -114,6 +239,7 @@ enum_find(argc, argv, obj)
VALUE if_none;
rb_scan_args(argc, argv, "01", &if_none);
+ RETURN_ENUMERATOR(obj, argc, argv);
rb_iterate(rb_each, obj, find_i, (VALUE)&memo);
if (memo != Qundef) {
return memo;
@@ -124,6 +250,81 @@ enum_find(argc, argv, obj)
return Qnil;
}
+static VALUE find_index_i _((VALUE, VALUE));
+static VALUE
+find_index_i(i, memop)
+ VALUE i;
+ VALUE memop;
+{
+ VALUE *memo = (VALUE*)memop;
+
+ if (rb_equal(i, memo[2])) {
+ memo[0] = UINT2NUM(memo[1]);
+ rb_iter_break();
+ }
+ memo[1]++;
+ return Qnil;
+}
+
+static VALUE find_index_iter_i _((VALUE, VALUE));
+static VALUE
+find_index_iter_i(i, memop)
+ VALUE i;
+ VALUE memop;
+{
+ VALUE *memo = (VALUE*)memop;
+
+ if (RTEST(rb_yield(i))) {
+ memo[0] = UINT2NUM(memo[1]);
+ rb_iter_break();
+ }
+ memo[1]++;
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.find_index(value) => int or nil
+ * enum.find_index {| obj | block } => int or nil
+ *
+ * Compares each entry in <i>enum</i> with <em>value</em> or passes
+ * to <em>block</em>. Returns the index for the first for which the
+ * evaluated value is non-false. If no object matches, returns
+ * <code>nil</code>
+ *
+ * (1..10).find_index {|i| i % 5 == 0 and i % 7 == 0 } #=> nil
+ * (1..100).find_index {|i| i % 5 == 0 and i % 7 == 0 } #=> 34
+ * (1..100).find_index(50) #=> 49
+ *
+ */
+
+static VALUE
+enum_find_index(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE memo[3]; /* [return value, current index, condition value] */
+ rb_block_call_func *func;
+
+ if (argc == 0) {
+ RETURN_ENUMERATOR(obj, 0, 0);
+ func = find_index_iter_i;
+ }
+ else {
+ rb_scan_args(argc, argv, "1", &memo[2]);
+ if (rb_block_given_p()) {
+ rb_warn("given block not used");
+ }
+ func = find_index_i;
+ }
+
+ memo[0] = Qnil;
+ memo[1] = 0;
+ rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
+ return memo[0];
+}
+
static VALUE
find_all_i(i, ary)
VALUE i, ary;
@@ -138,13 +339,13 @@ find_all_i(i, ary)
* call-seq:
* enum.find_all {| obj | block } => array
* enum.select {| obj | block } => array
- *
+ *
* Returns an array containing all elements of <i>enum</i> for which
* <em>block</em> is not <code>false</code> (see also
* <code>Enumerable#reject</code>).
- *
+ *
* (1..10).find_all {|i| i % 3 == 0 } #=> [3, 6, 9]
- *
+ *
*/
static VALUE
@@ -152,7 +353,8 @@ enum_find_all(obj)
VALUE obj;
{
VALUE ary = rb_ary_new();
-
+
+ RETURN_ENUMERATOR(obj, 0, 0);
rb_iterate(rb_each, obj, find_all_i, ary);
return ary;
@@ -171,12 +373,12 @@ reject_i(i, ary)
/*
* call-seq:
* enum.reject {| obj | block } => array
- *
+ *
* Returns an array for all elements of <i>enum</i> for which
* <em>block</em> is false (see also <code>Enumerable#find_all</code>).
- *
+ *
* (1..10).reject {|i| i % 3 == 0 } #=> [1, 2, 4, 5, 7, 8, 10]
- *
+ *
*/
static VALUE
@@ -184,7 +386,8 @@ enum_reject(obj)
VALUE obj;
{
VALUE ary = rb_ary_new();
-
+
+ RETURN_ENUMERATOR(obj, 0, 0);
rb_iterate(rb_each, obj, reject_i, ary);
return ary;
@@ -212,13 +415,13 @@ collect_all(i, ary)
* call-seq:
* enum.collect {| obj | block } => array
* enum.map {| obj | block } => array
- *
+ *
* Returns a new array with the results of running <em>block</em> once
* for every element in <i>enum</i>.
- *
+ *
* (1..4).collect {|i| i*i } #=> [1, 4, 9, 16]
* (1..4).collect { "cat" } #=> ["cat", "cat", "cat", "cat"]
- *
+ *
*/
static VALUE
@@ -236,80 +439,135 @@ enum_collect(obj)
* call-seq:
* enum.to_a => array
* enum.entries => array
- *
+ *
* Returns an array containing the items in <i>enum</i>.
- *
+ *
* (1..7).to_a #=> [1, 2, 3, 4, 5, 6, 7]
* { 'a'=>1, 'b'=>2, 'c'=>3 }.to_a #=> [["a", 1], ["b", 2], ["c", 3]]
*/
static VALUE
-enum_to_a(obj)
+enum_to_a(argc, argv, obj)
+ int argc;
+ VALUE *argv;
VALUE obj;
{
VALUE ary = rb_ary_new();
- rb_iterate(rb_each, obj, collect_all, ary);
+ rb_block_call(obj, id_each, argc, argv, collect_all, ary);
return ary;
}
+static VALUE inject_i _((VALUE, VALUE));
static VALUE
-inject_i(i, memo)
+inject_i(i, p)
VALUE i;
- VALUE *memo;
+ VALUE p;
{
- if (*memo == Qundef) {
- *memo = i;
+ VALUE *memo = (VALUE *)p;
+ if (memo[0] == Qundef) {
+ memo[0] = i;
+ }
+ else {
+ memo[0] = rb_yield_values(2, memo[0], i);
+ }
+ return Qnil;
+}
+
+static VALUE inject_op_i _((VALUE, VALUE));
+static VALUE
+inject_op_i(i, p)
+ VALUE i;
+ VALUE p;
+{
+ VALUE *memo = (VALUE *)p;
+
+ if (memo[0] == Qundef) {
+ memo[0] = i;
}
else {
- *memo = rb_yield_values(2, *memo, i);
+ memo[0] = rb_funcall(memo[0], (ID)memo[1], 1, i);
}
return Qnil;
}
/*
* call-seq:
+ * enum.inject(initial, sym) => obj
+ * enum.inject(sym) => obj
* enum.inject(initial) {| memo, obj | block } => obj
* enum.inject {| memo, obj | block } => obj
- *
- * Combines the elements of <i>enum</i> by applying the block to an
- * accumulator value (<i>memo</i>) and each element in turn. At each
- * step, <i>memo</i> is set to the value returned by the block. The
- * first form lets you supply an initial value for <i>memo</i>. The
- * second form uses the first element of the collection as a the
- * initial value (and skips that element while iterating).
- *
+ *
+ * enum.reduce(initial, sym) => obj
+ * enum.reduce(sym) => obj
+ * enum.reduce(initial) {| memo, obj | block } => obj
+ * enum.reduce {| memo, obj | block } => obj
+ *
+ * Combines all elements of <i>enum</i> by applying a binary
+ * operation, specified by a block or a symbol that names a
+ * method or operator.
+ *
+ * If you specify a block, then for each element in <i>enum<i>
+ * the block is passed an accumulator value (<i>memo</i>) and the element.
+ * If you specify a symbol instead, then each element in the collection
+ * will be passed to the named method of <i>memo</i>.
+ * In either case, the result becomes the new value for <i>memo</i>.
+ * At the end of the iteration, the final value of <i>memo</i> is the
+ * return value fo the method.
+ *
+ * If you do not explicitly specify an <i>initial</i> value for <i>memo</i>,
+ * then uses the first element of collection is used as the initial value
+ * of <i>memo</i>.
+ *
+ * Examples:
+ *
* # Sum some numbers
- * (5..10).inject {|sum, n| sum + n } #=> 45
+ * (5..10).reduce(:+) #=> 45
+ * # Same using a block and inject
+ * (5..10).inject {|sum, n| sum + n } #=> 45
* # Multiply some numbers
- * (5..10).inject(1) {|product, n| product * n } #=> 151200
- *
+ * (5..10).reduce(1, :*) #=> 151200
+ * # Same using a block
+ * (5..10).inject(1) {|product, n| product * n } #=> 151200
* # find the longest word
* longest = %w{ cat sheep bear }.inject do |memo,word|
* memo.length > word.length ? memo : word
* end
- * longest #=> "sheep"
- *
- * # find the length of the longest word
- * longest = %w{ cat sheep bear }.inject(0) do |memo,word|
- * memo >= word.length ? memo : word.length
- * end
- * longest #=> 5
- *
+ * longest #=> "sheep"
+ *
*/
-
static VALUE
enum_inject(argc, argv, obj)
int argc;
- VALUE *argv, obj;
+ VALUE *argv;
+ VALUE obj;
{
- VALUE memo = Qundef;
-
- if (rb_scan_args(argc, argv, "01", &memo) == 0)
- memo = Qundef;
- rb_iterate(rb_each, obj, inject_i, (VALUE)&memo);
- if (memo == Qundef) return Qnil;
- return memo;
+ VALUE memo[2];
+ rb_block_call_func *iter = inject_i;
+
+ switch (rb_scan_args(argc, argv, "02", &memo[0], &memo[1])) {
+ case 0:
+ memo[0] = Qundef;
+ break;
+ case 1:
+ if (rb_block_given_p()) {
+ break;
+ }
+ memo[1] = (VALUE)rb_to_id(memo[0]);
+ memo[0] = Qundef;
+ iter = inject_op_i;
+ break;
+ case 2:
+ if (rb_block_given_p()) {
+ rb_warning("given block not used");
+ }
+ memo[1] = (VALUE)rb_to_id(memo[1]);
+ iter = inject_op_i;
+ break;
+ }
+ rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
+ if (memo[0] == Qundef) return Qnil;
+ return memo[0];
}
static VALUE
@@ -328,13 +586,13 @@ partition_i(i, ary)
/*
* call-seq:
* enum.partition {| obj | block } => [ true_array, false_array ]
- *
+ *
* Returns two arrays, the first containing the elements of
* <i>enum</i> for which the block evaluates to true, the second
* containing the rest.
- *
+ *
* (1..6).partition {|i| (i&1).zero?} #=> [[2, 4, 6], [1, 3, 5]]
- *
+ *
*/
static VALUE
@@ -343,6 +601,8 @@ enum_partition(obj)
{
VALUE ary[2];
+ RETURN_ENUMERATOR(obj, 0, 0);
+
ary[0] = rb_ary_new();
ary[1] = rb_ary_new();
rb_iterate(rb_each, obj, partition_i, (VALUE)ary);
@@ -350,11 +610,111 @@ enum_partition(obj)
return rb_assoc_new(ary[0], ary[1]);
}
+static VALUE
+group_by_i(i, hash)
+ VALUE i;
+ VALUE hash;
+{
+ VALUE group = rb_yield(i);
+ VALUE values;
+
+ values = rb_hash_aref(hash, group);
+ if (NIL_P(values)) {
+ values = rb_ary_new3(1, i);
+ rb_hash_aset(hash, group, values);
+ }
+ else {
+ rb_ary_push(values, i);
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.group_by {| obj | block } => a_hash
+ *
+ * Returns a hash, which keys are evaluated result from the
+ * block, and values are arrays of elements in <i>enum</i>
+ * corresponding to the key.
+ *
+ * (1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
+ *
+ */
+
+static VALUE
+enum_group_by(obj)
+ VALUE obj;
+{
+ VALUE hash;
+
+ RETURN_ENUMERATOR(obj, 0, 0);
+
+ hash = rb_hash_new();
+ rb_block_call(obj, id_each, 0, 0, group_by_i, hash);
+
+ return hash;
+}
+
+static VALUE
+first_i(i, ary)
+ VALUE i;
+ VALUE *ary;
+{
+ if (NIL_P(ary[0])) {
+ ary[1] = i;
+ rb_iter_break();
+ }
+ else {
+ long n = NUM2LONG(ary[0]);
+
+ if (n <= 0) {
+ rb_iter_break();
+ }
+ rb_ary_push(ary[1], i);
+ n--;
+ ary[0] = INT2NUM(n);
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.first -> obj or nil
+ * enum.first(n) -> an_array
+ *
+ * Returns the first element, or the first +n+ elements, of the enumerable.
+ * If the enumerable is empty, the first form returns <code>nil</code>, and the
+ * second form returns an empty array.
+ *
+ */
+
+static VALUE
+enum_first(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE n, ary[2];
+
+ if (argc == 0) {
+ ary[0] = ary[1] = Qnil;
+ }
+ else {
+ rb_scan_args(argc, argv, "01", &n);
+ ary[0] = n;
+ ary[1] = rb_ary_new2(NUM2LONG(n));
+ }
+ rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)ary);
+
+ return ary[1];
+}
+
+
/*
* call-seq:
* enum.sort => array
* enum.sort {| a, b | block } => array
- *
+ *
* Returns an array containing the items in <i>enum</i> sorted,
* either according to their own <code><=></code> method, or by using
* the results of the supplied block. The block should return -1, 0, or
@@ -362,7 +722,7 @@ enum_partition(obj)
* Ruby 1.8, the method <code>Enumerable#sort_by</code> implements a
* built-in Schwartzian Transform, useful when key computation or
* comparison is expensive..
- *
+ *
* %w(rhea kea flea).sort #=> ["flea", "kea", "rhea"]
* (1..10).sort {|a,b| b <=> a} #=> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
*/
@@ -371,7 +731,7 @@ static VALUE
enum_sort(obj)
VALUE obj;
{
- return rb_ary_sort(enum_to_a(obj));
+ return rb_ary_sort(enum_to_a(0, 0, obj));
}
static VALUE
@@ -391,65 +751,70 @@ sort_by_i(i, ary)
}
static int
-sort_by_cmp(aa, bb)
+sort_by_cmp(aa, bb, data)
NODE **aa, **bb;
+ void *data;
{
VALUE a = aa[0]->u1.value;
VALUE b = bb[0]->u1.value;
+ VALUE ary = (VALUE)data;
+ if (RBASIC(ary)->klass) {
+ rb_raise(rb_eRuntimeError, "sort_by reentered");
+ }
return rb_cmpint(rb_funcall(a, id_cmp, 1, b), a, b);
}
/*
* call-seq:
* enum.sort_by {| obj | block } => array
- *
+ *
* Sorts <i>enum</i> using a set of keys generated by mapping the
* values in <i>enum</i> through the given block.
- *
+ *
* %w{ apple pear fig }.sort_by {|word| word.length}
#=> ["fig", "pear", "apple"]
- *
+ *
* The current implementation of <code>sort_by</code> generates an
* array of tuples containing the original collection element and the
* mapped value. This makes <code>sort_by</code> fairly expensive when
* the keysets are simple
- *
+ *
* require 'benchmark'
* include Benchmark
- *
+ *
* a = (1..100000).map {rand(100000)}
- *
+ *
* bm(10) do |b|
* b.report("Sort") { a.sort }
* b.report("Sort by") { a.sort_by {|a| a} }
* end
- *
+ *
* <em>produces:</em>
- *
+ *
* user system total real
* Sort 0.180000 0.000000 0.180000 ( 0.175469)
* Sort by 1.980000 0.040000 2.020000 ( 2.013586)
- *
+ *
* However, consider the case where comparing the keys is a non-trivial
* operation. The following code sorts some files on modification time
* using the basic <code>sort</code> method.
- *
+ *
* files = Dir["*"]
* sorted = files.sort {|a,b| File.new(a).mtime <=> File.new(b).mtime}
* sorted #=> ["mon", "tues", "wed", "thurs"]
- *
+ *
* This sort is inefficient: it generates two new <code>File</code>
* objects during every comparison. A slightly better technique is to
* use the <code>Kernel#test</code> method to generate the modification
* times directly.
- *
+ *
* files = Dir["*"]
* sorted = files.sort { |a,b|
* test(?M, a) <=> test(?M, b)
* }
* sorted #=> ["mon", "tues", "wed", "thurs"]
- *
+ *
* This still generates many unnecessary <code>Time</code> objects. A
* more efficient technique is to cache the sort keys (modification
* times in this case) before the sort. Perl users often call this
@@ -457,14 +822,14 @@ sort_by_cmp(aa, bb)
* construct a temporary array, where each element is an array
* containing our sort key along with the filename. We sort this array,
* and then extract the filename from the result.
- *
+ *
* sorted = Dir["*"].collect { |f|
* [test(?M, f), f]
* }.sort.collect { |f| f[1] }
* sorted #=> ["mon", "tues", "wed", "thurs"]
- *
+ *
* This is exactly what <code>sort_by</code> does internally.
- *
+ *
* sorted = Dir["*"].sort_by {|f| test(?M, f)}
* sorted #=> ["mon", "tues", "wed", "thurs"]
*/
@@ -476,6 +841,8 @@ enum_sort_by(obj)
VALUE ary;
long i;
+ RETURN_ENUMERATOR(obj, 0, 0);
+
if (TYPE(obj) == T_ARRAY) {
ary = rb_ary_new2(RARRAY(obj)->len);
}
@@ -485,7 +852,8 @@ enum_sort_by(obj)
RBASIC(ary)->klass = 0;
rb_iterate(rb_each, obj, sort_by_i, ary);
if (RARRAY(ary)->len > 1) {
- qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE), sort_by_cmp, 0);
+ qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE),
+ sort_by_cmp, (void *)ary);
}
if (RBASIC(ary)->klass) {
rb_raise(rb_eRuntimeError, "sort_by reentered");
@@ -498,11 +866,11 @@ enum_sort_by(obj)
}
static VALUE
-all_iter_i(i, memo)
+all_i(i, memo)
VALUE i;
VALUE *memo;
{
- if (!RTEST(rb_yield(i))) {
+ if (!RTEST(i)) {
*memo = Qfalse;
rb_iter_break();
}
@@ -510,32 +878,28 @@ all_iter_i(i, memo)
}
static VALUE
-all_i(i, memo)
+all_iter_i(i, memo)
VALUE i;
VALUE *memo;
{
- if (!RTEST(i)) {
- *memo = Qfalse;
- rb_iter_break();
- }
- return Qnil;
+ return all_i(rb_yield(i), memo);
}
/*
* call-seq:
* enum.all? [{|obj| block } ] => true or false
- *
+ *
* Passes each element of the collection to the given block. The method
* returns <code>true</code> if the block never returns
* <code>false</code> or <code>nil</code>. If the block is not given,
* Ruby adds an implicit block of <code>{|obj| obj}</code> (that is
* <code>all?</code> will return <code>true</code> only if none of the
* collection members are <code>false</code> or <code>nil</code>.)
- *
+ *
* %w{ ant bear cat}.all? {|word| word.length >= 3} #=> true
* %w{ ant bear cat}.all? {|word| word.length >= 4} #=> false
* [ nil, true, 99 ].all? #=> false
- *
+ *
*/
static VALUE
@@ -549,11 +913,11 @@ enum_all(obj)
}
static VALUE
-any_iter_i(i, memo)
+any_i(i, memo)
VALUE i;
VALUE *memo;
{
- if (RTEST(rb_yield(i))) {
+ if (RTEST(i)) {
*memo = Qtrue;
rb_iter_break();
}
@@ -561,21 +925,17 @@ any_iter_i(i, memo)
}
static VALUE
-any_i(i, memo)
+any_iter_i(i, memo)
VALUE i;
VALUE *memo;
{
- if (RTEST(i)) {
- *memo = Qtrue;
- rb_iter_break();
- }
- return Qnil;
+ return any_i(rb_yield(i), memo);
}
/*
* call-seq:
* enum.any? [{|obj| block } ] => true or false
- *
+ *
* Passes each element of the collection to the given block. The method
* returns <code>true</code> if the block ever returns a value other
* than <code>false</code> or <code>nil</code>. If the block is not
@@ -583,11 +943,11 @@ any_i(i, memo)
* is <code>any?</code> will return <code>true</code> if at least one
* of the collection members is not <code>false</code> or
* <code>nil</code>.
- *
+ *
* %w{ ant bear cat}.any? {|word| word.length >= 3} #=> true
* %w{ ant bear cat}.any? {|word| word.length >= 4} #=> true
* [ nil, true, 99 ].any? #=> true
- *
+ *
*/
static VALUE
@@ -601,6 +961,105 @@ enum_any(obj)
}
static VALUE
+one_i(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ if (RTEST(i)) {
+ if (*memo == Qundef) {
+ *memo = Qtrue;
+ }
+ else if (*memo == Qtrue) {
+ *memo = Qfalse;
+ rb_iter_break();
+ }
+ }
+ return Qnil;
+}
+
+static VALUE
+one_iter_i(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ return one_i(rb_yield(i), memo);
+}
+
+/*
+ * call-seq:
+ * enum.one? [{|obj| block }] => true or false
+ *
+ * Passes each element of the collection to the given block. The method
+ * returns <code>true</code> if the block returns <code>true</code>
+ * exactly once. If the block is not given, <code>one?</code> will return
+ * <code>true</code> only if exactly one of the collection members is
+ * true.
+ *
+ * %w{ant bear cat}.one? {|word| word.length == 4} #=> true
+ * %w{ant bear cat}.one? {|word| word.length > 4} #=> false
+ * %w{ant bear cat}.one? {|word| word.length < 4} #=> false
+ * [ nil, true, 99 ].one? #=> false
+ * [ nil, true, false ].one? #=> true
+ *
+ */
+
+static VALUE
+enum_one(obj)
+ VALUE obj;
+{
+ VALUE result = Qundef;
+
+ rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? one_iter_i : one_i, (VALUE)&result);
+ if (result == Qundef) return Qfalse;
+ return result;
+}
+
+static VALUE
+none_i(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ if (RTEST(i)) {
+ *memo = Qfalse;
+ rb_iter_break();
+ }
+ return Qnil;
+}
+
+static VALUE
+none_iter_i(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ return none_i(rb_yield(i), memo);
+}
+
+/*
+ * call-seq:
+ * enum.none? [{|obj| block }] => true or false
+ *
+ * Passes each element of the collection to the given block. The method
+ * returns <code>true</code> if the block never returns <code>true</code>
+ * for all elements. If the block is not given, <code>none?</code> will return
+ * <code>true</code> only if none of the collection members is true.
+ *
+ * %w{ant bear cat}.none? {|word| word.length == 5} #=> true
+ * %w{ant bear cat}.none? {|word| word.length >= 4} #=> false
+ * [].none? #=> true
+ * [nil].none? #=> true
+ * [nil,false].none? #=> true
+ */
+static VALUE
+enum_none(obj)
+ VALUE obj;
+{
+ VALUE result = Qtrue;
+
+ rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? none_iter_i : none_i, (VALUE)&result);
+ return result;
+}
+
+static VALUE
min_i(i, memo)
VALUE i;
VALUE *memo;
@@ -643,11 +1102,11 @@ min_ii(i, memo)
* call-seq:
* enum.min => obj
* enum.min {| a,b | block } => obj
- *
+ *
* Returns the object in <i>enum</i> with the minimum value. The
* first form assumes all objects implement <code>Comparable</code>;
* the second uses the block to return <em>a <=> b</em>.
- *
+ *
* a = %w(albatross dog horse)
* a.min #=> "albatross"
* a.min {|a,b| a.length <=> b.length } #=> "dog"
@@ -668,11 +1127,11 @@ enum_min(obj)
* call-seq:
* enum.max => obj
* enum.max {| a,b | block } => obj
- *
+ *
* Returns the object in <i>enum</i> with the maximum value. The
* first form assumes all objects implement <code>Comparable</code>;
* the second uses the block to return <em>a <=> b</em>.
- *
+ *
* a = %w(albatross dog horse)
* a.max #=> "horse"
* a.max {|a,b| a.length <=> b.length } #=> "albatross"
@@ -720,15 +1179,15 @@ max_ii(i, memo)
* call-seq:
* enum.max => obj
* enum.max {|a,b| block } => obj
- *
+ *
* Returns the object in _enum_ with the maximum value. The
* first form assumes all objects implement <code>Comparable</code>;
* the second uses the block to return <em>a <=> b</em>.
- *
+ *
* a = %w(albatross dog horse)
* a.max #=> "horse"
* a.max {|a,b| a.length <=> b.length } #=> "albatross"
- */
+ */
static VALUE
enum_max(obj)
@@ -742,6 +1201,240 @@ enum_max(obj)
}
static VALUE
+minmax_i(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ int n;
+
+ if (memo[0] == Qundef) {
+ memo[0] = i;
+ memo[1] = i;
+ }
+ else {
+ n = rb_cmpint(rb_funcall(i, id_cmp, 1, memo[0]), i, memo[0]);
+ if (n < 0) {
+ memo[0] = i;
+ }
+ n = rb_cmpint(rb_funcall(i, id_cmp, 1, memo[1]), i, memo[1]);
+ if (n > 0) {
+ memo[1] = i;
+ }
+ }
+ return Qnil;
+}
+
+static VALUE
+minmax_ii(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ int n;
+
+ if (memo[0] == Qundef) {
+ memo[0] = i;
+ memo[1] = i;
+ }
+ else {
+ VALUE ary = memo[2];
+
+ RARRAY(ary)->ptr[0] = i;
+ RARRAY(ary)->ptr[1] = memo[0];
+ n = rb_cmpint(rb_yield(ary), i, memo[0]);
+ if (n < 0) {
+ memo[0] = i;
+ }
+ RARRAY(ary)->ptr[0] = i;
+ RARRAY(ary)->ptr[1] = memo[1];
+ n = rb_cmpint(rb_yield(ary), i, memo[1]);
+ if (n > 0) {
+ memo[1] = i;
+ }
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.minmax => [min,max]
+ * enum.minmax {|a,b| block } => [min,max]
+ *
+ * Returns two elements array which contains the minimum and the
+ * maximum value in the enumerable. The first form assumes all
+ * objects implement <code>Comparable</code>; the second uses the
+ * block to return <em>a <=> b</em>.
+ *
+ * a = %w(albatross dog horse)
+ * a.minmax #=> ["albatross", "horse"]
+ * a.minmax {|a,b| a.length <=> b.length } #=> ["dog", "albatross"]
+ */
+
+static VALUE
+enum_minmax(obj)
+ VALUE obj;
+{
+ VALUE result[3];
+ VALUE ary = rb_ary_new3(2, Qnil, Qnil);
+
+ result[0] = Qundef;
+ if (rb_block_given_p()) {
+ result[2] = ary;
+ rb_block_call(obj, id_each, 0, 0, minmax_ii, (VALUE)result);
+ }
+ else {
+ rb_block_call(obj, id_each, 0, 0, minmax_i, (VALUE)result);
+ }
+ if (result[0] != Qundef) {
+ RARRAY(ary)->ptr[0] = result[0];
+ RARRAY(ary)->ptr[1] = result[1];
+ }
+ return ary;
+}
+
+static VALUE
+min_by_i(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ VALUE v;
+
+ v = rb_yield(i);
+ if (memo[0] == Qundef) {
+ memo[0] = v;
+ memo[1] = i;
+ }
+ else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo[0]), v, memo[0]) < 0) {
+ memo[0] = v;
+ memo[1] = i;
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.min_by {| obj| block } => obj
+ *
+ * Returns the object in <i>enum</i> that gives the minimum
+ * value from the given block.
+ *
+ * a = %w(albatross dog horse)
+ * a.min_by {|x| x.length } #=> "dog"
+ */
+
+static VALUE
+enum_min_by(obj)
+ VALUE obj;
+{
+ VALUE memo[2];
+
+ RETURN_ENUMERATOR(obj, 0, 0);
+
+ memo[0] = Qundef;
+ memo[1] = Qnil;
+ rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo);
+ return memo[1];
+}
+
+static VALUE
+max_by_i(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ VALUE v;
+
+ v = rb_yield(i);
+ if (memo[0] == Qundef) {
+ memo[0] = v;
+ memo[1] = i;
+ }
+ else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo[0]), v, memo[0]) > 0) {
+ memo[0] = v;
+ memo[1] = i;
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.max_by {| obj| block } => obj
+ *
+ * Returns the object in <i>enum</i> that gives the maximum
+ * value from the given block.
+ *
+ * a = %w(albatross dog horse)
+ * a.max_by {|x| x.length } #=> "albatross"
+ */
+
+static VALUE
+enum_max_by(obj)
+ VALUE obj;
+{
+ VALUE memo[2];
+
+ RETURN_ENUMERATOR(obj, 0, 0);
+
+ memo[0] = Qundef;
+ memo[1] = Qnil;
+ rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo);
+ return memo[1];
+}
+
+static VALUE
+minmax_by_i(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ VALUE v;
+
+ v = rb_yield(i);
+ if (memo[0] == Qundef) {
+ memo[0] = v;
+ memo[1] = v;
+ memo[2] = i;
+ memo[3] = i;
+ }
+ else {
+ if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo[0]), v, memo[0]) < 0) {
+ memo[0] = v;
+ memo[2] = i;
+ }
+ if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo[1]), v, memo[1]) > 0) {
+ memo[1] = v;
+ memo[3] = i;
+ }
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.minmax_by {| obj| block } => [min, max]
+ *
+ * Returns two elements array array containing the objects in
+ * <i>enum</i> that gives the minimum and maximum values respectively
+ * from the given block.
+ *
+ * a = %w(albatross dog horse)
+ * a.minmax_by {|x| x.length } #=> ["dog", "albatross"]
+ */
+
+static VALUE
+enum_minmax_by(obj)
+ VALUE obj;
+{
+ VALUE memo[4];
+
+ RETURN_ENUMERATOR(obj, 0, 0);
+
+ memo[0] = Qundef;
+ memo[1] = Qundef;
+ memo[2] = Qnil;
+ memo[3] = Qnil;
+ rb_block_call(obj, id_each, 0, 0, minmax_by_i, (VALUE)memo);
+ return rb_assoc_new(memo[2], memo[3]);
+}
+
+static VALUE
member_i(item, memo)
VALUE item;
VALUE *memo;
@@ -757,13 +1450,13 @@ member_i(item, memo)
* call-seq:
* enum.include?(obj) => true or false
* enum.member?(obj) => true or false
- *
+ *
* Returns <code>true</code> if any member of <i>enum</i> equals
* <i>obj</i>. Equality is tested using <code>==</code>.
- *
+ *
* IO.constants.include? "SEEK_SET" #=> true
* IO.constants.include? "SEEK_NO_FURTHER" #=> false
- *
+ *
*/
static VALUE
@@ -791,29 +1484,56 @@ each_with_index_i(val, memo)
/*
* call-seq:
* enum.each_with_index {|obj, i| block } -> enum
- *
+ *
* Calls <em>block</em> with two arguments, the item and its index, for
* each item in <i>enum</i>.
- *
+ *
* hash = Hash.new
* %w(cat dog wombat).each_with_index {|item, index|
* hash[item] = index
* }
* hash #=> {"cat"=>0, "wombat"=>2, "dog"=>1}
- *
+ *
*/
static VALUE
enum_each_with_index(obj)
VALUE obj;
{
- VALUE memo = 0;
+ VALUE memo;
- rb_need_block();
+ RETURN_ENUMERATOR(obj, 0, 0);
+
+ memo = 0;
rb_iterate(rb_each, obj, each_with_index_i, (VALUE)&memo);
return obj;
}
+/*
+ * call-seq:
+ * enum.reverse_each {|item| block }
+ *
+ * Traverses <i>enum</i> in reverse order.
+ */
+
+static VALUE
+enum_reverse_each(int argc, VALUE *argv, VALUE obj)
+{
+ VALUE ary;
+ long i;
+
+ RETURN_ENUMERATOR(obj, argc, argv);
+
+ ary = enum_to_a(argc, argv, obj);
+
+ for (i = RARRAY_LEN(ary); --i >= 0; ) {
+ rb_yield(RARRAY_PTR(ary)[i]);
+ }
+
+ return obj;
+}
+
+
static VALUE
zip_i(val, memo)
VALUE val;
@@ -843,7 +1563,7 @@ zip_i(val, memo)
* call-seq:
* enum.zip(arg, ...) => array
* enum.zip(arg, ...) {|arr| block } => nil
- *
+ *
* Converts any arguments to arrays, then merges elements of
* <i>enum</i> with corresponding elements from each argument. This
* generates a sequence of <code>enum#size</code> <em>n</em>-element
@@ -852,14 +1572,14 @@ zip_i(val, memo)
* <code>nil</code> values are supplied. If a block given, it is
* invoked for each output array, otherwise an array of arrays is
* returned.
- *
+ *
* a = [ 4, 5, 6 ]
* b = [ 7, 8, 9 ]
- *
+ *
* (1..3).zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
* "cat\ndog".zip([1]) #=> [["cat\n", 1], ["dog", nil]]
* (1..3).zip #=> [[1], [2], [3]]
- *
+ *
*/
static VALUE
@@ -884,6 +1604,227 @@ enum_zip(argc, argv, obj)
return result;
}
+static VALUE
+take_i(i, arg)
+ VALUE i;
+ VALUE *arg;
+{
+ if (arg[1]-- == 0) rb_iter_break();
+ rb_ary_push(arg[0], i);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.take(n) => array
+ *
+ * Returns first n elements from <i>enum</i>.
+ *
+ * a = [1, 2, 3, 4, 5, 0]
+ * a.take(3) # => [1, 2, 3]
+ *
+ */
+
+static VALUE
+enum_take(obj, n)
+ VALUE obj;
+ VALUE n;
+{
+ VALUE args[2];
+ long len = NUM2LONG(n);
+
+ if (len < 0) {
+ rb_raise(rb_eArgError, "attempt to take negative size");
+ }
+
+ args[1] = len;
+ args[0] = rb_ary_new();
+ rb_block_call(obj, id_each, 0, 0, take_i, (VALUE)args);
+ return args[0];
+}
+
+
+static VALUE
+take_while_i(i, ary)
+ VALUE i;
+ VALUE *ary;
+{
+ if (!RTEST(rb_yield(i))) rb_iter_break();
+ rb_ary_push(*ary, i);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.take_while {|arr| block } => array
+ *
+ * Passes elements to the block until the block returns nil or false,
+ * then stops iterating and returns an array of all prior elements.
+ *
+ * a = [1, 2, 3, 4, 5, 0]
+ * a.take_while {|i| i < 3 } # => [1, 2]
+ *
+ */
+
+static VALUE
+enum_take_while(obj)
+ VALUE obj;
+{
+ VALUE ary;
+
+ RETURN_ENUMERATOR(obj, 0, 0);
+ ary = rb_ary_new();
+ rb_block_call(obj, id_each, 0, 0, take_while_i, (VALUE)&ary);
+ return ary;
+}
+
+static VALUE
+drop_i(i, arg)
+ VALUE i;
+ VALUE *arg;
+{
+ if (arg[1] == 0) {
+ rb_ary_push(arg[0], i);
+ }
+ else {
+ arg[1]--;
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.drop(n) => array
+ *
+ * Drops first n elements from <i>enum</i>, and returns rest elements
+ * in an array.
+ *
+ * a = [1, 2, 3, 4, 5, 0]
+ * a.drop(3) # => [4, 5, 0]
+ *
+ */
+
+static VALUE
+enum_drop(obj, n)
+ VALUE obj;
+ VALUE n;
+{
+ VALUE args[2];
+ long len = NUM2LONG(n);
+
+ if (len < 0) {
+ rb_raise(rb_eArgError, "attempt to drop negative size");
+ }
+
+ args[1] = len;
+ args[0] = rb_ary_new();
+ rb_block_call(obj, id_each, 0, 0, drop_i, (VALUE)args);
+ return args[0];
+}
+
+
+static VALUE
+drop_while_i(i, args)
+ VALUE i;
+ VALUE *args;
+{
+ if (!args[1] && !RTEST(rb_yield(i))) {
+ args[1] = Qtrue;
+ }
+ if (args[1]) {
+ rb_ary_push(args[0], i);
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.drop_while {|arr| block } => array
+ *
+ * Drops elements up to, but not including, the first element for
+ * which the block returns nil or false and returns an array
+ * containing the remaining elements.
+ *
+ * a = [1, 2, 3, 4, 5, 0]
+ * a.drop_while {|i| i < 3 } # => [3, 4, 5, 0]
+ *
+ */
+
+static VALUE
+enum_drop_while(obj)
+ VALUE obj;
+{
+ VALUE args[2];
+
+ RETURN_ENUMERATOR(obj, 0, 0);
+ args[0] = rb_ary_new();
+ args[1] = Qfalse;
+ rb_block_call(obj, id_each, 0, 0, drop_while_i, (VALUE)args);
+ return args[0];
+}
+
+static VALUE
+cycle_i(i, ary)
+ VALUE i;
+ VALUE ary;
+{
+ rb_ary_push(ary, i);
+ rb_yield(i);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.cycle {|obj| block }
+ * enum.cycle(n) {|obj| block }
+ *
+ * Calls <i>block</i> for each element of <i>enum</i> repeatedly _n_
+ * times or forever if none or nil is given. If a non-positive
+ * number is given or the collection is empty, does nothing. Returns
+ * nil if the loop has finished without getting interrupted.
+ *
+ * Enumerable#cycle saves elements in an internal array so changes
+ * to <i>enum</i> after the first pass have no effect.
+ *
+ * a = ["a", "b", "c"]
+ * a.cycle {|x| puts x } # print, a, b, c, a, b, c,.. forever.
+ * a.cycle(2) {|x| puts x } # print, a, b, c, a, b, c.
+ *
+ */
+
+static VALUE
+enum_cycle(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE ary;
+ VALUE nv = Qnil;
+ long n, i, len;
+
+ rb_scan_args(argc, argv, "01", &nv);
+
+ RETURN_ENUMERATOR(obj, argc, argv);
+ if (NIL_P(nv)) {
+ n = -1;
+ }
+ else {
+ n = NUM2LONG(nv);
+ if (n <= 0) return Qnil;
+ }
+ ary = rb_ary_new();
+ RBASIC(ary)->klass = 0;
+ rb_block_call(obj, id_each, 0, 0, cycle_i, ary);
+ len = RARRAY(ary)->len;
+ if (len == 0) return Qnil;
+ while (n < 0 || 0 < --n) {
+ for (i=0; i<len; i++) {
+ rb_yield(RARRAY(ary)->ptr[i]);
+ }
+ }
+ return Qnil; /* not reached */
+}
+
/*
* The <code>Enumerable</code> mixin provides collection classes with
* several traversal and searching methods, and with the ability to
@@ -900,32 +1841,51 @@ Init_Enumerable()
{
rb_mEnumerable = rb_define_module("Enumerable");
- rb_define_method(rb_mEnumerable,"to_a", enum_to_a, 0);
- rb_define_method(rb_mEnumerable,"entries", enum_to_a, 0);
-
- rb_define_method(rb_mEnumerable,"sort", enum_sort, 0);
- rb_define_method(rb_mEnumerable,"sort_by", enum_sort_by, 0);
- rb_define_method(rb_mEnumerable,"grep", enum_grep, 1);
- rb_define_method(rb_mEnumerable,"find", enum_find, -1);
- rb_define_method(rb_mEnumerable,"detect", enum_find, -1);
- rb_define_method(rb_mEnumerable,"find_all", enum_find_all, 0);
- rb_define_method(rb_mEnumerable,"select", enum_find_all, 0);
- rb_define_method(rb_mEnumerable,"reject", enum_reject, 0);
- rb_define_method(rb_mEnumerable,"collect", enum_collect, 0);
- rb_define_method(rb_mEnumerable,"map", enum_collect, 0);
- rb_define_method(rb_mEnumerable,"inject", enum_inject, -1);
- rb_define_method(rb_mEnumerable,"partition", enum_partition, 0);
- rb_define_method(rb_mEnumerable,"all?", enum_all, 0);
- rb_define_method(rb_mEnumerable,"any?", enum_any, 0);
- rb_define_method(rb_mEnumerable,"min", enum_min, 0);
- rb_define_method(rb_mEnumerable,"max", enum_max, 0);
- rb_define_method(rb_mEnumerable,"member?", enum_member, 1);
- rb_define_method(rb_mEnumerable,"include?", enum_member, 1);
- rb_define_method(rb_mEnumerable,"each_with_index", enum_each_with_index, 0);
+ rb_define_method(rb_mEnumerable, "to_a", enum_to_a, -1);
+ rb_define_method(rb_mEnumerable, "entries", enum_to_a, -1);
+
+ rb_define_method(rb_mEnumerable, "sort", enum_sort, 0);
+ rb_define_method(rb_mEnumerable, "sort_by", enum_sort_by, 0);
+ rb_define_method(rb_mEnumerable, "grep", enum_grep, 1);
+ rb_define_method(rb_mEnumerable, "count", enum_count, -1);
+ rb_define_method(rb_mEnumerable, "find", enum_find, -1);
+ rb_define_method(rb_mEnumerable, "detect", enum_find, -1);
+ rb_define_method(rb_mEnumerable, "find_index", enum_find_index, -1);
+ rb_define_method(rb_mEnumerable, "find_all", enum_find_all, 0);
+ rb_define_method(rb_mEnumerable, "select", enum_find_all, 0);
+ rb_define_method(rb_mEnumerable, "reject", enum_reject, 0);
+ rb_define_method(rb_mEnumerable, "collect", enum_collect, 0);
+ rb_define_method(rb_mEnumerable, "map", enum_collect, 0);
+ rb_define_method(rb_mEnumerable, "inject", enum_inject, -1);
+ rb_define_method(rb_mEnumerable, "reduce", enum_inject, -1);
+ rb_define_method(rb_mEnumerable, "partition", enum_partition, 0);
+ rb_define_method(rb_mEnumerable, "group_by", enum_group_by, 0);
+ rb_define_method(rb_mEnumerable, "first", enum_first, -1);
+ rb_define_method(rb_mEnumerable, "all?", enum_all, 0);
+ rb_define_method(rb_mEnumerable, "any?", enum_any, 0);
+ rb_define_method(rb_mEnumerable, "one?", enum_one, 0);
+ rb_define_method(rb_mEnumerable, "none?", enum_none, 0);
+ rb_define_method(rb_mEnumerable, "min", enum_min, 0);
+ rb_define_method(rb_mEnumerable, "max", enum_max, 0);
+ rb_define_method(rb_mEnumerable, "minmax", enum_minmax, 0);
+ rb_define_method(rb_mEnumerable, "min_by", enum_min_by, 0);
+ rb_define_method(rb_mEnumerable, "max_by", enum_max_by, 0);
+ rb_define_method(rb_mEnumerable, "minmax_by", enum_minmax_by, 0);
+ rb_define_method(rb_mEnumerable, "member?", enum_member, 1);
+ rb_define_method(rb_mEnumerable, "include?", enum_member, 1);
+ rb_define_method(rb_mEnumerable, "each_with_index", enum_each_with_index, 0);
+ rb_define_method(rb_mEnumerable, "enum_with_index", enum_each_with_index, 0);
+ rb_define_method(rb_mEnumerable, "reverse_each", enum_reverse_each, -1);
rb_define_method(rb_mEnumerable, "zip", enum_zip, -1);
+ rb_define_method(rb_mEnumerable, "take", enum_take, 1);
+ rb_define_method(rb_mEnumerable, "take_while", enum_take_while, 0);
+ rb_define_method(rb_mEnumerable, "drop", enum_drop, 1);
+ rb_define_method(rb_mEnumerable, "drop_while", enum_drop_while, 0);
+ rb_define_method(rb_mEnumerable, "cycle", enum_cycle, -1);
id_eqq = rb_intern("===");
id_each = rb_intern("each");
id_cmp = rb_intern("<=>");
+ id_size = rb_intern("size");
}
diff --git a/enumerator.c b/enumerator.c
new file mode 100644
index 0000000000..f95d931b62
--- /dev/null
+++ b/enumerator.c
@@ -0,0 +1,450 @@
+/************************************************
+
+ enumerator.c - provides Enumerator class
+
+ $Author$
+
+ Copyright (C) 2001-2003 Akinori MUSHA
+
+ $Idaemons: /home/cvs/rb/enumerator/enumerator.c,v 1.1.1.1 2001/07/15 10:12:48 knu Exp $
+ $RoughId: enumerator.c,v 1.6 2003/07/27 11:03:24 nobu Exp $
+ $Id$
+
+************************************************/
+
+#include "ruby.h"
+
+/*
+ * Document-class: Enumerable::Enumerator
+ *
+ * A class which provides a method `each' to be used as an Enumerable
+ * object.
+ */
+VALUE rb_cEnumerator;
+static VALUE sym_each;
+
+VALUE rb_eStopIteration;
+
+struct enumerator {
+ VALUE obj;
+ ID meth;
+ VALUE proc;
+ VALUE args;
+ rb_block_call_func *iter;
+};
+
+static void enumerator_mark _((void *));
+static void
+enumerator_mark(p)
+ void *p;
+{
+ struct enumerator *ptr = p;
+ rb_gc_mark(ptr->obj);
+ rb_gc_mark(ptr->args);
+}
+
+static struct enumerator *
+enumerator_ptr(obj)
+ VALUE obj;
+{
+ struct enumerator *ptr;
+
+ Data_Get_Struct(obj, struct enumerator, ptr);
+ if (RDATA(obj)->dmark != enumerator_mark) {
+ rb_raise(rb_eTypeError,
+ "wrong argument type %s (expected Enumerable::Enumerator)",
+ rb_obj_classname(obj));
+ }
+ if (!ptr || ptr->obj == Qundef) {
+ rb_raise(rb_eArgError, "uninitialized enumerator");
+ }
+ return ptr;
+}
+
+/*
+ * call-seq:
+ * obj.to_enum(method = :each, *args)
+ * obj.enum_for(method = :each, *args)
+ *
+ * Returns Enumerable::Enumerator.new(self, method, *args).
+ *
+ * e.g.:
+ *
+ * str = "xyz"
+ *
+ * enum = str.enum_for(:each_byte)
+ * a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
+ *
+ * # protects an array from being modified
+ * a = [1, 2, 3]
+ * some_method(a.to_enum)
+ *
+ */
+static VALUE
+obj_to_enum(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE meth = sym_each;
+
+ if (argc > 0) {
+ --argc;
+ meth = *argv++;
+ }
+ return rb_enumeratorize(obj, meth, argc, argv);
+}
+
+static VALUE
+each_slice_i(val, memo)
+ VALUE val;
+ VALUE *memo;
+{
+ VALUE ary = memo[0];
+ VALUE v = Qnil;
+ long size = (long)memo[1];
+
+ rb_ary_push(ary, val);
+
+ if (RARRAY_LEN(ary) == size) {
+ v = rb_yield(ary);
+ memo[0] = rb_ary_new2(size);
+ }
+
+ return v;
+}
+
+/*
+ * call-seq:
+ * e.each_slice(n) {...}
+ * e.each_slice(n)
+ *
+ * Iterates the given block for each slice of <n> elements. If no
+ * block is given, returns an enumerator.
+ *
+ * e.g.:
+ * (1..10).each_slice(3) {|a| p a}
+ * # outputs below
+ * [1, 2, 3]
+ * [4, 5, 6]
+ * [7, 8, 9]
+ * [10]
+ *
+ */
+static VALUE
+enum_each_slice(obj, n)
+ VALUE obj, n;
+{
+ long size = NUM2LONG(n);
+ VALUE args[2], ary;
+
+ if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
+ RETURN_ENUMERATOR(obj, 1, &n);
+ args[0] = rb_ary_new2(size);
+ args[1] = (VALUE)size;
+
+ rb_block_call(obj, SYM2ID(sym_each), 0, 0, each_slice_i, (VALUE)args);
+
+ ary = args[0];
+ if (RARRAY_LEN(ary) > 0) rb_yield(ary);
+
+ return Qnil;
+}
+
+static VALUE
+each_cons_i(val, memo)
+ VALUE val;
+ VALUE *memo;
+{
+ VALUE ary = memo[0];
+ VALUE v = Qnil;
+ long size = (long)memo[1];
+
+ if (RARRAY_LEN(ary) == size) {
+ rb_ary_shift(ary);
+ }
+ rb_ary_push(ary, val);
+ if (RARRAY_LEN(ary) == size) {
+ v = rb_yield(rb_ary_dup(ary));
+ }
+ return v;
+}
+
+/*
+ * call-seq:
+ * each_cons(n) {...}
+ * each_cons(n)
+ *
+ * Iterates the given block for each array of consecutive <n>
+ * elements. If no block is given, returns an enumerator.a
+ *
+ * e.g.:
+ * (1..10).each_cons(3) {|a| p a}
+ * # outputs below
+ * [1, 2, 3]
+ * [2, 3, 4]
+ * [3, 4, 5]
+ * [4, 5, 6]
+ * [5, 6, 7]
+ * [6, 7, 8]
+ * [7, 8, 9]
+ * [8, 9, 10]
+ *
+ */
+static VALUE
+enum_each_cons(obj, n)
+ VALUE obj, n;
+{
+ long size = NUM2LONG(n);
+ VALUE args[2];
+
+ if (size <= 0) rb_raise(rb_eArgError, "invalid size");
+ RETURN_ENUMERATOR(obj, 1, &n);
+ args[0] = rb_ary_new2(size);
+ args[1] = (VALUE)size;
+
+ rb_block_call(obj, SYM2ID(sym_each), 0, 0, each_cons_i, (VALUE)args);
+
+ return Qnil;
+}
+
+static VALUE enumerator_allocate _((VALUE));
+static VALUE
+enumerator_allocate(klass)
+ VALUE klass;
+{
+ struct enumerator *ptr;
+ VALUE enum_obj;
+
+ enum_obj = Data_Make_Struct(klass, struct enumerator,
+ enumerator_mark, -1, ptr);
+ ptr->obj = Qundef;
+
+ return enum_obj;
+}
+
+static VALUE enumerator_each_i _((VALUE, VALUE));
+static VALUE
+enumerator_each_i(v, enum_obj)
+ VALUE v;
+ VALUE enum_obj;
+{
+ return rb_yield(v);
+}
+
+static VALUE
+enumerator_init(enum_obj, obj, meth, argc, argv)
+ VALUE enum_obj;
+ VALUE obj;
+ VALUE meth;
+ int argc;
+ VALUE *argv;
+{
+ struct enumerator *ptr;
+
+ Data_Get_Struct(enum_obj, struct enumerator, ptr);
+
+ if (!ptr) {
+ rb_raise(rb_eArgError, "unallocated enumerator");
+ }
+
+ ptr->obj = obj;
+ ptr->meth = rb_to_id(meth);
+ ptr->iter = enumerator_each_i;
+ if (argc) ptr->args = rb_ary_new4(argc, argv);
+
+ return enum_obj;
+}
+
+/*
+ * call-seq:
+ * Enumerable::Enumerator.new(obj, method = :each, *args)
+ *
+ * Creates a new Enumerable::Enumerator object, which is to be
+ * used as an Enumerable object using the given object's given
+ * method with the given arguments.
+ *
+ * Use of this method is discouraged. Use Kernel#enum_for() instead.
+ */
+static VALUE
+enumerator_initialize(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE recv, meth = sym_each;
+
+ if (argc == 0)
+ rb_raise(rb_eArgError, "wrong number of argument (0 for 1)");
+ recv = *argv++;
+ if (--argc) {
+ meth = *argv++;
+ --argc;
+ }
+ return enumerator_init(obj, recv, meth, argc, argv);
+}
+
+/* :nodoc: */
+static VALUE
+enumerator_init_copy(obj, orig)
+ VALUE obj;
+ VALUE orig;
+{
+ struct enumerator *ptr0, *ptr1;
+
+ ptr0 = enumerator_ptr(orig);
+
+ Data_Get_Struct(obj, struct enumerator, ptr1);
+
+ if (!ptr1) {
+ rb_raise(rb_eArgError, "unallocated enumerator");
+ }
+
+ ptr1->obj = ptr0->obj;
+ ptr1->meth = ptr0->meth;
+ ptr1->iter = ptr0->iter;
+ ptr1->args = ptr0->args;
+
+ return obj;
+}
+
+VALUE
+rb_enumeratorize(obj, meth, argc, argv)
+ VALUE obj;
+ VALUE meth;
+ int argc;
+ VALUE *argv;
+{
+ return enumerator_init(enumerator_allocate(rb_cEnumerator), obj, meth, argc, argv);
+}
+
+/*
+ * call-seq:
+ * enum.each {...}
+ *
+ * Iterates the given block using the object and the method specified
+ * in the first place. If no block is given, returns self.
+ *
+ */
+static VALUE
+enumerator_each(obj)
+ VALUE obj;
+{
+ struct enumerator *e;
+ int argc = 0;
+ VALUE *argv = 0;
+
+ if (!rb_block_given_p()) return obj;
+ e = enumerator_ptr(obj);
+ if (e->args) {
+ argc = RARRAY_LEN(e->args);
+ argv = RARRAY_PTR(e->args);
+ }
+ return rb_block_call(e->obj, e->meth, argc, argv, e->iter, (VALUE)e);
+}
+
+static VALUE
+enumerator_with_index_i(val, memo)
+ VALUE val;
+ VALUE *memo;
+{
+ val = rb_yield_values(2, val, INT2FIX(*memo));
+ ++*memo;
+ return val;
+}
+
+/*
+ * call-seq:
+ * e.with_index {|(*args), idx| ... }
+ * e.with_index
+ *
+ * Iterates the given block for each elements with an index, which
+ * start from 0. If no block is given, returns an enumerator.
+ *
+ */
+static VALUE
+enumerator_with_index(obj)
+ VALUE obj;
+{
+ struct enumerator *e = enumerator_ptr(obj);
+ VALUE memo = 0;
+ int argc = 0;
+ VALUE *argv = 0;
+
+ RETURN_ENUMERATOR(obj, 0, 0);
+ if (e->args) {
+ argc = RARRAY_LEN(e->args);
+ argv = RARRAY_PTR(e->args);
+ }
+ return rb_block_call(e->obj, e->meth, argc, argv,
+ enumerator_with_index_i, (VALUE)&memo);
+}
+
+/*
+ * call-seq:
+ * e.next => object
+ *
+ * Returns the next object in the enumerator, and move the internal
+ * position forward. When the position reached at the end, internal
+ * position is rewinded then StopIteration is raised.
+ *
+ * Note that enumeration sequence by next method does not affect other
+ * non-external enumeration methods, unless underlying iteration
+ * methods itself has side-effect, e.g. IO#each_line.
+ *
+ * Caution: Calling this method causes the "generator" library to be
+ * loaded.
+ */
+
+static VALUE
+enumerator_next(obj)
+ VALUE obj;
+{
+ rb_require("generator");
+ return rb_funcall(obj, rb_intern("next"), 0, 0);
+}
+
+/*
+ * call-seq:
+ * e.rewind => e
+ *
+ * Rewinds the enumeration sequence by the next method.
+ */
+
+static VALUE
+enumerator_rewind(obj)
+ VALUE obj;
+{
+ rb_require("generator");
+ return rb_funcall(obj, rb_intern("rewind"), 0, 0);
+}
+
+void
+Init_Enumerator()
+{
+ rb_define_method(rb_mKernel, "to_enum", obj_to_enum, -1);
+ rb_define_method(rb_mKernel, "enum_for", obj_to_enum, -1);
+
+ rb_define_method(rb_mEnumerable, "each_slice", enum_each_slice, 1);
+ rb_define_method(rb_mEnumerable, "enum_slice", enum_each_slice, 1);
+ rb_define_method(rb_mEnumerable, "each_cons", enum_each_cons, 1);
+ rb_define_method(rb_mEnumerable, "enum_cons", enum_each_cons, 1);
+
+ rb_cEnumerator = rb_define_class_under(rb_mEnumerable, "Enumerator", rb_cObject);
+ rb_include_module(rb_cEnumerator, rb_mEnumerable);
+
+ rb_define_alloc_func(rb_cEnumerator, enumerator_allocate);
+ rb_define_method(rb_cEnumerator, "initialize", enumerator_initialize, -1);
+ rb_define_method(rb_cEnumerator, "initialize_copy", enumerator_init_copy, 1);
+ rb_define_method(rb_cEnumerator, "each", enumerator_each, 0);
+ rb_define_method(rb_cEnumerator, "each_with_index", enumerator_with_index, 0);
+ rb_define_method(rb_cEnumerator, "with_index", enumerator_with_index, 0);
+ rb_define_method(rb_cEnumerator, "next", enumerator_next, 0);
+ rb_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0);
+
+ rb_eStopIteration = rb_define_class("StopIteration", rb_eIndexError);
+
+ sym_each = ID2SYM(rb_intern("each"));
+
+ rb_provide("enumerator.so"); /* for backward compatibility */
+}
diff --git a/env.h b/env.h
index 196090f387..c50103f71e 100644
--- a/env.h
+++ b/env.h
@@ -2,8 +2,8 @@
env.h -
- $Author: matz $
- $Date: 2006/02/13 09:10:55 $
+ $Author$
+ $Date$
created at: Mon Jul 11 11:53:03 JST 1994
Copyright (C) 1993-2003 Yukihiro Matsumoto
diff --git a/error.c b/error.c
index 93093e0e0f..a991f55e57 100644
--- a/error.c
+++ b/error.c
@@ -2,8 +2,8 @@
error.c -
- $Author: matz $
- $Date: 2006/07/20 07:04:13 $
+ $Author$
+ $Date$
created at: Mon Aug 9 16:11:34 JST 1993
Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -29,7 +29,7 @@
#define EXIT_SUCCESS 0
#endif
-extern const char ruby_version[], ruby_release_date[], ruby_platform[];
+extern const char *ruby_description;
int ruby_nerrs;
@@ -208,8 +208,7 @@ rb_bug(fmt, va_alist)
va_init_list(args, fmt);
vfprintf(out, fmt, args);
va_end(args);
- fprintf(out, "\nruby %s (%s) [%s]\n\n",
- ruby_version, ruby_release_date, ruby_platform);
+ fprintf(out, "\n%s\n\n", ruby_description);
}
abort();
}
@@ -258,7 +257,7 @@ rb_check_type(x, t)
if (TYPE(x) != t) {
while (type->type >= 0) {
if (type->type == t) {
- char *etype;
+ const char *etype;
if (NIL_P(x)) {
etype = "nil";
@@ -334,7 +333,7 @@ rb_exc_new3(etype, str)
VALUE etype, str;
{
StringValue(str);
- return rb_exc_new(etype, RSTRING(str)->ptr, RSTRING(str)->len);
+ return rb_funcall(etype, rb_intern("new"), 1, str);
}
/*
@@ -488,18 +487,18 @@ static VALUE
exc_backtrace(exc)
VALUE exc;
{
- ID bt = rb_intern("bt");
+ static ID bt;
- if (!rb_ivar_defined(exc, bt)) return Qnil;
- return rb_ivar_get(exc, bt);
+ if (!bt) bt = rb_intern("bt");
+ return rb_attr_get(exc, bt);
}
-static VALUE
-check_backtrace(bt)
+VALUE
+rb_check_backtrace(bt)
VALUE bt;
{
long i;
- static char *err = "backtrace must be Array of String";
+ static const char err[] = "backtrace must be Array of String";
if (!NIL_P(bt)) {
int t = TYPE(bt);
@@ -532,7 +531,7 @@ exc_set_backtrace(exc, bt)
VALUE exc;
VALUE bt;
{
- return rb_iv_set(exc, "bt", check_backtrace(bt));
+ return rb_iv_set(exc, "bt", rb_check_backtrace(bt));
}
/*
@@ -728,7 +727,7 @@ name_err_mesg_to_str(obj)
mesg = ptr[0];
if (NIL_P(mesg)) return Qnil;
else {
- char *desc = 0;
+ const char *desc = 0;
VALUE d = 0, args[3];
obj = ptr[1];
@@ -882,7 +881,7 @@ syserr_initialize(argc, argv, self)
#if !defined(_WIN32) && !defined(__VMS)
char *strerror();
#endif
- char *err;
+ const char *err;
VALUE mesg, error;
VALUE klass = rb_obj_class(self);
@@ -952,18 +951,16 @@ syserr_eqq(self, exc)
VALUE self, exc;
{
VALUE num, e;
+ ID en = rb_intern("errno");
- if (!rb_obj_is_kind_of(exc, rb_eSystemCallError)) return Qfalse;
- if (self == rb_eSystemCallError) return Qtrue;
+ if (!rb_obj_is_kind_of(exc, rb_eSystemCallError)) {
+ if (!rb_respond_to(exc, en)) return Qfalse;
+ }
+ else if (self == rb_eSystemCallError) return Qtrue;
- num = rb_attr_get(exc, rb_intern("errno"));
+ num = rb_attr_get(exc, en);
if (NIL_P(num)) {
- VALUE klass = CLASS_OF(exc);
-
- while (TYPE(klass) == T_ICLASS || FL_TEST(klass, FL_SINGLETON)) {
- klass = (VALUE)RCLASS(klass)->super;
- }
- num = rb_const_get(klass, rb_intern("Errno"));
+ num = rb_funcall(exc, en, 0, 0);
}
e = rb_const_get(self, rb_intern("Errno"));
if (FIXNUM_P(num) ? num == e : rb_equal(num, e))
diff --git a/eval.c b/eval.c
index 520eb987af..8eb16853af 100644
--- a/eval.c
+++ b/eval.c
@@ -2,8 +2,8 @@
eval.c -
- $Author: shyouhei $
- $Date: 2007/01/27 15:45:49 $
+ $Author$
+ $Date$
created at: Thu Jun 10 14:22:17 JST 1993
Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -29,11 +29,6 @@
#endif
#include <stdio.h>
-#if defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT)
-#include <ucontext.h>
-#define USE_CONTEXT
-#endif
-#include <setjmp.h>
#include "st.h"
#include "dln.h"
@@ -77,6 +72,8 @@ char *strrchr _((const char*,const char));
#include <unistd.h>
#endif
+#include <time.h>
+
#ifdef __BEOS__
#include <net/socket.h>
#endif
@@ -90,10 +87,6 @@ char *strrchr _((const char*,const char));
#endif
#ifdef USE_CONTEXT
-typedef struct {
- ucontext_t context;
- volatile int status;
-} rb_jmpbuf_t[1];
NORETURN(static void rb_jump_context(rb_jmpbuf_t, int));
static inline void
@@ -195,19 +188,18 @@ static int volatile freebsd_clear_carry_flag = 0;
# define POST_GETCONTEXT 0
# endif
# define ruby_longjmp(env, val) rb_jump_context(env, val)
-# define ruby_setjmp(j) ((j)->status = 0, \
+# define ruby_setjmp(just_before_setjmp, j) ((j)->status = 0, \
+ (just_before_setjmp), \
PRE_GETCONTEXT, \
getcontext(&(j)->context), \
POST_GETCONTEXT, \
(j)->status)
#else
-typedef jmp_buf rb_jmpbuf_t;
-# if !defined(setjmp) && defined(HAVE__SETJMP)
-# define ruby_setjmp(env) _setjmp(env)
-# define ruby_longjmp(env,val) _longjmp(env,val)
-# else
-# define ruby_setjmp(env) setjmp(env)
-# define ruby_longjmp(env,val) longjmp(env,val)
+# define ruby_setjmp(just_before_setjmp, env) \
+ ((just_before_setjmp), RUBY_SETJMP(env))
+# define ruby_longjmp(env,val) RUBY_LONGJMP(env,val)
+# ifdef __CYGWIN__
+int _setjmp(), _longjmp();
# endif
#endif
@@ -250,6 +242,8 @@ static int scope_vmode;
#define SCOPE_SET(f) (scope_vmode=(f))
#define SCOPE_TEST(f) (scope_vmode&(f))
+VALUE (*ruby_sandbox_save)_((rb_thread_t));
+VALUE (*ruby_sandbox_restore)_((rb_thread_t));
NODE* ruby_current_node;
int ruby_safe_level = 0;
/* safe-level:
@@ -458,7 +452,8 @@ rb_define_alloc_func(klass, func)
VALUE (*func) _((VALUE));
{
Check_Type(klass, T_CLASS);
- rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0), NOEX_PRIVATE);
+ rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0),
+ NOEX_PRIVATE);
}
void
@@ -466,7 +461,7 @@ rb_undef_alloc_func(klass)
VALUE klass;
{
Check_Type(klass, T_CLASS);
- rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
+ rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, 0, NOEX_UNDEF);
}
static NODE*
@@ -474,16 +469,16 @@ search_method(klass, id, origin)
VALUE klass, *origin;
ID id;
{
- NODE *body;
+ st_data_t body;
if (!klass) return 0;
- while (!st_lookup(RCLASS(klass)->m_tbl, id, (st_data_t *)&body)) {
+ while (!st_lookup(RCLASS(klass)->m_tbl, id, &body)) {
klass = RCLASS(klass)->super;
if (!klass) return 0;
}
if (origin) *origin = klass;
- return body;
+ return (NODE *)body;
}
static NODE*
@@ -494,7 +489,7 @@ rb_get_method_body(klassp, idp, noexp)
{
ID id = *idp;
VALUE klass = *klassp;
- VALUE origin;
+ VALUE origin = 0;
NODE * volatile body;
struct cache_entry *ent;
@@ -562,7 +557,8 @@ remove_method(klass, mid)
VALUE klass;
ID mid;
{
- NODE *body;
+ st_data_t data;
+ NODE *body = 0;
if (klass == rb_cObject) {
rb_secure(4);
@@ -574,8 +570,14 @@ remove_method(klass, mid)
if (mid == __id__ || mid == __send__ || mid == init) {
rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
}
- if (!st_delete(RCLASS(klass)->m_tbl, &mid, (st_data_t *)&body) ||
- !body->nd_body) {
+ if (st_lookup(RCLASS(klass)->m_tbl, mid, &data)) {
+ body = (NODE *)data;
+ if (!body || !body->nd_body) body = 0;
+ else {
+ st_delete(RCLASS(klass)->m_tbl, &mid, &data);
+ }
+ }
+ if (!body) {
rb_name_error(mid, "method `%s' not defined in %s",
rb_id2name(mid), rb_class2name(klass));
}
@@ -758,7 +760,7 @@ static struct SCOPE *top_scope;
static unsigned long frame_unique = 0;
#define PUSH_FRAME() do { \
- struct FRAME _frame; \
+ volatile struct FRAME _frame; \
_frame.prev = ruby_frame; \
_frame.tmp = 0; \
_frame.node = ruby_current_node; \
@@ -1027,7 +1029,7 @@ static struct tag *prot_tag;
#define PROT_LAMBDA INT2FIX(2) /* 5 */
#define PROT_YIELD INT2FIX(3) /* 7 */
-#define EXEC_TAG() (FLUSH_REGISTER_WINDOWS, ruby_setjmp(prot_tag->buf))
+#define EXEC_TAG() ruby_setjmp(((void)0), prot_tag->buf)
#define JUMP_TAG(st) do { \
ruby_frame = prot_tag->frame; \
@@ -1055,15 +1057,15 @@ VALUE ruby_class;
static VALUE ruby_wrapper; /* security wrapper */
#define PUSH_CLASS(c) do { \
- VALUE _class = ruby_class; \
+ volatile VALUE _class = ruby_class; \
ruby_class = (c)
#define POP_CLASS() ruby_class = _class; \
} while (0)
-static NODE *ruby_cref = 0;
-static NODE *top_cref;
-#define PUSH_CREF(c) ruby_cref = NEW_NODE(NODE_CREF,(c),0,ruby_cref)
+NODE *ruby_cref = 0;
+NODE *ruby_top_cref;
+#define PUSH_CREF(c) ruby_cref = NEW_CREF(c,ruby_cref)
#define POP_CREF() ruby_cref = ruby_cref->nd_next
#define PUSH_SCOPE() do { \
@@ -1078,9 +1080,11 @@ static NODE *top_cref;
ruby_scope = _scope; \
scope_vmode = SCOPE_PUBLIC
-typedef struct thread * rb_thread_t;
-static rb_thread_t curr_thread = 0;
-static rb_thread_t main_thread;
+rb_thread_t rb_curr_thread;
+rb_thread_t rb_main_thread;
+#define main_thread rb_main_thread
+#define curr_thread rb_curr_thread
+
static void scope_dup _((struct SCOPE *));
#define POP_SCOPE() \
@@ -1101,8 +1105,8 @@ static void scope_dup _((struct SCOPE *));
} while (0)
static VALUE rb_eval _((VALUE,NODE*));
-static VALUE eval _((VALUE,VALUE,VALUE,char*,int));
-static NODE *compile _((VALUE, char*, int));
+static VALUE eval _((VALUE,VALUE,VALUE,const char*,int));
+static NODE *compile _((VALUE, const char*, int));
static VALUE rb_yield_0 _((VALUE, VALUE, VALUE, int, int));
@@ -1111,8 +1115,9 @@ static VALUE rb_yield_0 _((VALUE, VALUE, VALUE, int, int));
#define YIELD_PUBLIC_DEF 4
#define YIELD_FUNC_AVALUE 1
#define YIELD_FUNC_SVALUE 2
+#define YIELD_FUNC_LAMBDA 3
-static VALUE rb_call _((VALUE,VALUE,ID,int,const VALUE*,int));
+static VALUE rb_call _((VALUE,VALUE,ID,int,const VALUE*,int,VALUE));
static VALUE module_setup _((VALUE,NODE*));
static VALUE massign _((VALUE,NODE*,VALUE,int));
@@ -1200,6 +1205,8 @@ error_pos()
}
}
+VALUE rb_check_backtrace(VALUE);
+
static VALUE
get_backtrace(info)
VALUE info;
@@ -1207,7 +1214,7 @@ get_backtrace(info)
if (NIL_P(info)) return Qnil;
info = rb_funcall(info, rb_intern("backtrace"), 0);
if (NIL_P(info)) return Qnil;
- return rb_check_array_type(info);
+ return rb_check_backtrace(info);
}
static void
@@ -1222,7 +1229,7 @@ error_print()
{
VALUE errat = Qnil; /* OK */
volatile VALUE eclass, e;
- char *einfo;
+ const char *einfo;
long elen;
if (NIL_P(ruby_errinfo)) return;
@@ -1283,7 +1290,7 @@ error_print()
long len = elen;
if (RSTRING(epath)->ptr[0] == '#') epath = 0;
- if (tail = memchr(einfo, '\n', elen)) {
+ if ((tail = memchr(einfo, '\n', elen)) != 0) {
len = tail - einfo;
tail++; /* skip newline */
}
@@ -1294,8 +1301,9 @@ error_print()
warn_print2(RSTRING(epath)->ptr, RSTRING(epath)->len);
warn_print(")\n");
}
- if (tail) {
+ if (tail && elen>len+1) {
warn_print2(tail, elen-len-1);
+ if (einfo[elen-1] != '\n') warn_print2("\n", 1);
}
}
}
@@ -1303,6 +1311,7 @@ error_print()
if (!NIL_P(errat)) {
long i;
struct RArray *ep = RARRAY(errat);
+ int truncate = eclass == rb_eSysStackError;
#define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
#define TRACE_HEAD 8
@@ -1313,7 +1322,7 @@ error_print()
if (TYPE(ep->ptr[i]) == T_STRING) {
warn_printf("\tfrom %s\n", RSTRING(ep->ptr[i])->ptr);
}
- if (i == TRACE_HEAD && ep->len > TRACE_MAX) {
+ if (truncate && i == TRACE_HEAD && ep->len > TRACE_MAX) {
warn_printf("\t ... %ld levels...\n",
ep->len - TRACE_HEAD - TRACE_TAIL);
i = ep->len - TRACE_TAIL;
@@ -1391,8 +1400,8 @@ ruby_init()
rb_call_inits();
ruby_class = rb_cObject;
ruby_frame->self = ruby_top_self;
- top_cref = rb_node_newnode(NODE_CREF,rb_cObject,0,0);
- ruby_cref = top_cref;
+ ruby_top_cref = rb_node_newnode(NODE_CREF,rb_cObject,0,0);
+ ruby_cref = ruby_top_cref;
rb_define_global_const("TOPLEVEL_BINDING", rb_f_binding(ruby_top_self));
#ifdef __MACOS__
_macruby_init();
@@ -1434,8 +1443,7 @@ int ruby_in_eval;
static void rb_thread_cleanup _((void));
static void rb_thread_wait_other_threads _((void));
-static int thread_set_raised();
-static int thread_reset_raised();
+static int thread_no_ensure _((void));
static VALUE exception_error;
static VALUE sysstack_error;
@@ -1453,8 +1461,10 @@ error_handle(ex)
int ex;
{
int status = EXIT_FAILURE;
+ rb_thread_t th = curr_thread;
- if (thread_set_raised()) return EXIT_FAILURE;
+ if (rb_thread_set_raised(th))
+ return EXIT_FAILURE;
switch (ex & TAG_MASK) {
case 0:
status = EXIT_SUCCESS;
@@ -1496,6 +1506,9 @@ error_handle(ex)
if (rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) {
status = sysexit_status(ruby_errinfo);
}
+ else if (rb_obj_is_instance_of(ruby_errinfo, rb_eSignal)) {
+ /* no message when exiting by signal */
+ }
else {
error_print();
}
@@ -1504,7 +1517,7 @@ error_handle(ex)
rb_bug("Unknown longjmp status %d", ex);
break;
}
- thread_reset_raised();
+ rb_thread_reset_raised(th);
return status;
}
@@ -1563,12 +1576,14 @@ ruby_cleanup(ex)
int ex;
{
int state;
- volatile VALUE err = ruby_errinfo;
+ volatile VALUE errs[2];
+ int nerr;
+ errs[1] = ruby_errinfo;
ruby_safe_level = 0;
- Init_stack((void*)&state);
+ Init_stack((void *)&state);
ruby_finalize_0();
- if (ruby_errinfo) err = ruby_errinfo;
+ errs[0] = ruby_errinfo;
PUSH_TAG(PROT_NONE);
PUSH_ITER(ITER_NOT);
if ((state = EXEC_TAG()) == 0) {
@@ -1579,15 +1594,39 @@ ruby_cleanup(ex)
ex = state;
}
POP_ITER();
- ruby_errinfo = err;
+ ruby_errinfo = errs[1];
ex = error_handle(ex);
ruby_finalize_1();
POP_TAG();
- if (err && rb_obj_is_kind_of(err, rb_eSystemExit)) {
- VALUE st = rb_iv_get(err, "status");
- return NUM2INT(st);
+ for (nerr = 0; nerr < sizeof(errs) / sizeof(errs[0]); ++nerr) {
+ VALUE err = errs[nerr];
+
+ if (!RTEST(err)) continue;
+
+ if (rb_obj_is_kind_of(err, rb_eSystemExit)) {
+ return sysexit_status(err);
+ }
+ else if (rb_obj_is_kind_of(err, rb_eSignal)) {
+ VALUE sig = rb_iv_get(err, "signo");
+ ruby_default_signal(NUM2INT(sig));
+ }
+ else if (ex == 0) {
+ ex = 1;
+ }
}
+
+#if EXIT_SUCCESS != 0 || EXIT_FAILURE != 1
+ switch (ex) {
+#if EXIT_SUCCESS != 0
+ case 0: return EXIT_SUCCESS;
+#endif
+#if EXIT_FAILURE != 1
+ case 1: return EXIT_FAILURE;
+#endif
+ }
+#endif
+
return ex;
}
@@ -1851,7 +1890,7 @@ rb_eval_cmd(cmd, arg, level)
POP_TAG();
POP_FRAME();
- jump_tag_but_local_jump(state, val);
+ if (state) jump_tag_but_local_jump(state, val);
return val;
}
@@ -1994,7 +2033,7 @@ void
rb_frozen_class_p(klass)
VALUE klass;
{
- char *desc = "something(?!)";
+ const char *desc = "something(?!)";
if (OBJ_FROZEN(klass)) {
if (FL_TEST(klass, FL_SINGLETON))
@@ -2032,7 +2071,7 @@ rb_undef(klass, id)
}
body = search_method(klass, id, &origin);
if (!body || !body->nd_body) {
- char *s0 = " class";
+ const char *s0 = " class";
VALUE c = klass;
if (FL_TEST(c, FL_SINGLETON)) {
@@ -2123,9 +2162,10 @@ rb_alias(klass, name, def)
VALUE klass;
ID name, def;
{
- VALUE origin;
+ VALUE origin = 0;
NODE *orig, *body, *node;
VALUE singleton = 0;
+ st_data_t data;
rb_frozen_class_p(klass);
if (name == def) return;
@@ -2153,7 +2193,8 @@ rb_alias(klass, name, def)
}
rb_clear_cache_by_id(name);
- if (RTEST(ruby_verbose) && st_lookup(RCLASS(klass)->m_tbl, name, (st_data_t *)&node)) {
+ if (RTEST(ruby_verbose) && st_lookup(RCLASS(klass)->m_tbl, name, &data)) {
+ node = (NODE *)data;
if (node->nd_cnt == 0 && node->nd_body) {
rb_warning("discarding old %s", rb_id2name(name));
}
@@ -2161,6 +2202,9 @@ rb_alias(klass, name, def)
st_insert(RCLASS(klass)->m_tbl, name,
(st_data_t)NEW_METHOD(NEW_FBODY(body, def, origin),
NOEX_WITH_SAFE(orig->nd_noex)));
+
+ if (!ruby_running) return;
+
if (singleton) {
rb_funcall(singleton, singleton_added, 1, ID2SYM(name));
}
@@ -2199,8 +2243,8 @@ rb_mod_alias_method(mod, newname, oldname)
return mod;
}
-static NODE*
-copy_node_scope(node, rval)
+NODE *
+rb_copy_node_scope(node, rval)
NODE *node;
NODE *rval;
{
@@ -2266,7 +2310,7 @@ copy_node_scope(node, rval)
int tmp_iter = ruby_iter->iter;\
switch (tmp_iter) {\
case ITER_PRE:\
- ruby_block = ruby_block->outer;\
+ if (ruby_block) ruby_block = ruby_block->outer;\
case ITER_PAS:\
tmp_iter = ITER_NOT;\
}\
@@ -2279,9 +2323,9 @@ copy_node_scope(node, rval)
#define MATCH_DATA *rb_svar(node->nd_cnt)
-static char* is_defined _((VALUE, NODE*, char*));
+static const char* is_defined _((VALUE, NODE*, char*));
-static char*
+static const char*
arg_defined(self, node, buf, type)
VALUE self;
NODE *node;
@@ -2308,7 +2352,7 @@ arg_defined(self, node, buf, type)
return type;
}
-static char*
+static const char*
is_defined(self, node, buf)
VALUE self;
NODE *node; /* OK */
@@ -2401,6 +2445,8 @@ is_defined(self, node, buf)
case NODE_ATTRSET:
case NODE_OP_ASGN1:
case NODE_OP_ASGN2:
+ case NODE_OP_ASGN_OR:
+ case NODE_OP_ASGN_AND:
case NODE_MASGN:
case NODE_LASGN:
case NODE_DASGN:
@@ -2626,27 +2672,27 @@ set_trace_func(obj, trace)
return trace;
}
-static char *
+static const char *
get_event_name(rb_event_t event)
{
switch (event) {
- case RUBY_EVENT_LINE:
+ case RUBY_EVENT_LINE:
return "line";
- case RUBY_EVENT_CLASS:
+ case RUBY_EVENT_CLASS:
return "class";
- case RUBY_EVENT_END:
+ case RUBY_EVENT_END:
return "end";
- case RUBY_EVENT_CALL:
+ case RUBY_EVENT_CALL:
return "call";
- case RUBY_EVENT_RETURN:
+ case RUBY_EVENT_RETURN:
return "return";
- case RUBY_EVENT_C_CALL:
+ case RUBY_EVENT_C_CALL:
return "c-call";
- case RUBY_EVENT_C_RETURN:
+ case RUBY_EVENT_C_RETURN:
return "c-return";
- case RUBY_EVENT_RAISE:
+ case RUBY_EVENT_RAISE:
return "raise";
- default:
+ default:
return "unknown";
}
}
@@ -2663,7 +2709,8 @@ call_trace_func(event, node, self, id, klass)
struct FRAME *prev;
NODE *node_save;
VALUE srcfile;
- char *event_name;
+ const char *event_name;
+ rb_thread_t th = curr_thread;
if (!trace_func) return;
if (tracing) return;
@@ -2695,7 +2742,7 @@ call_trace_func(event, node, self, id, klass)
}
}
PUSH_TAG(PROT_NONE);
- raised = thread_reset_raised();
+ raised = rb_thread_reset_raised(th);
if ((state = EXEC_TAG()) == 0) {
srcfile = rb_str_new2(ruby_sourcefile?ruby_sourcefile:"(ruby)");
event_name = get_event_name(event);
@@ -2707,7 +2754,7 @@ call_trace_func(event, node, self, id, klass)
klass),
Qundef, 0);
}
- if (raised) thread_set_raised();
+ if (raised) rb_thread_set_raised(th);
POP_TAG();
POP_FRAME();
@@ -2899,6 +2946,7 @@ rb_eval(self, n)
NODE * volatile node = n;
int state;
volatile VALUE result = Qnil;
+ st_data_t data;
#define RETURN(v) do { \
result = (v); \
@@ -2998,13 +3046,16 @@ rb_eval(self, n)
RETURN(Qfalse);
case NODE_IF:
- EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self,
- ruby_frame->last_func,
- ruby_frame->last_class);
if (RTEST(rb_eval(self, node->nd_cond))) {
+ EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self,
+ ruby_frame->last_func,
+ ruby_frame->last_class);
node = node->nd_body;
}
else {
+ EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self,
+ ruby_frame->last_func,
+ ruby_frame->last_class);
node = node->nd_else;
}
goto again;
@@ -3181,7 +3232,7 @@ rb_eval(self, n)
END_CALLARGS;
ruby_current_node = node;
SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(recv),recv,each,0,0,0);
+ result = rb_call(CLASS_OF(recv),recv,each,0,0,0,self);
}
POP_ITER();
}
@@ -3307,7 +3358,7 @@ rb_eval(self, n)
result = rb_eval(self, node->nd_head);
}
POP_TAG();
- if (node->nd_ensr) {
+ if (node->nd_ensr && !thread_no_ensure()) {
VALUE retval = prot_tag->retval; /* save retval */
VALUE errinfo = ruby_errinfo;
@@ -3422,7 +3473,7 @@ rb_eval(self, n)
ruby_current_node = node;
SET_CURRENT_SOURCE();
- rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,scope);
+ rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,scope,self);
result = argv[argc-1];
}
break;
@@ -3440,7 +3491,7 @@ rb_eval(self, n)
ruby_current_node = node;
SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0);
+ result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0,self);
}
break;
@@ -3455,13 +3506,13 @@ rb_eval(self, n)
ruby_current_node = node;
SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv,1);
+ result = rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv,1,self);
}
break;
case NODE_VCALL:
SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(self),self,node->nd_mid,0,0,2);
+ result = rb_call(CLASS_OF(self),self,node->nd_mid,0,0,2,self);
break;
case NODE_SUPER:
@@ -3490,6 +3541,10 @@ rb_eval(self, n)
}
argv = RARRAY(RBASIC(ruby_scope)->klass)->ptr;
}
+ else if (!ruby_scope->local_vars) {
+ argc = 0;
+ argv = 0;
+ }
else {
argv = ruby_scope->local_vars + 2;
}
@@ -3868,7 +3923,7 @@ rb_eval(self, n)
case NODE_DEFN:
if (node->nd_defn) {
NODE *body, *defn;
- VALUE origin;
+ VALUE origin = 0;
int noex;
if (NIL_P(ruby_class)) {
@@ -3902,7 +3957,7 @@ rb_eval(self, n)
noex |= NOEX_NOSUPER;
}
- defn = copy_node_scope(node->nd_defn, ruby_cref);
+ defn = rb_copy_node_scope(node->nd_defn, ruby_cref);
rb_add_method(ruby_class, node->nd_mid, defn, noex);
if (scope_vmode == SCOPE_MODFUNC) {
rb_add_method(rb_singleton_class(ruby_class),
@@ -3930,7 +3985,8 @@ rb_eval(self, n)
if (OBJ_FROZEN(recv)) rb_error_frozen("object");
klass = rb_singleton_class(recv);
- if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, (st_data_t *)&body)) {
+ if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, &data)) {
+ body = (NODE *)data;
if (ruby_safe_level >= 4) {
rb_raise(rb_eSecurityError, "redefining method prohibited");
}
@@ -3938,7 +3994,7 @@ rb_eval(self, n)
rb_warning("redefine %s", rb_id2name(node->nd_mid));
}
}
- defn = copy_node_scope(node->nd_defn, ruby_cref);
+ defn = rb_copy_node_scope(node->nd_defn, ruby_cref);
rb_add_method(klass, node->nd_mid, defn,
NOEX_PUBLIC|(body?body->nd_noex&NOEX_UNDEF:0));
result = Qnil;
@@ -4082,7 +4138,7 @@ rb_eval(self, n)
case NODE_DEFINED:
{
char buf[20];
- char *desc = is_defined(self, node->nd_head, buf);
+ const char *desc = is_defined(self, node->nd_head, buf);
if (desc) result = rb_str_new2(desc);
else result = Qnil;
@@ -4179,7 +4235,7 @@ rb_obj_respond_to(obj, id, priv)
int n = 0;
args[n++] = ID2SYM(id);
if (priv) args[n++] = Qtrue;
- return rb_funcall2(obj, respond_to, n, args);
+ return RTEST(rb_funcall2(obj, respond_to, n, args));
}
}
@@ -4517,8 +4573,9 @@ rb_longjmp(tag, mesg)
VALUE mesg;
{
VALUE at;
+ rb_thread_t th = curr_thread;
- if (thread_set_raised()) {
+ if (rb_thread_set_raised(th)) {
ruby_errinfo = exception_error;
JUMP_TAG(TAG_FATAL);
}
@@ -4532,6 +4589,9 @@ rb_longjmp(tag, mesg)
at = get_backtrace(mesg);
if (NIL_P(at)) {
at = make_backtrace();
+ if (OBJ_FROZEN(mesg)) {
+ mesg = rb_obj_dup(mesg);
+ }
set_backtrace(mesg, at);
}
}
@@ -4557,7 +4617,7 @@ rb_longjmp(tag, mesg)
ruby_errinfo = mesg;
}
else if (status) {
- thread_reset_raised();
+ rb_thread_reset_raised(th);
JUMP_TAG(status);
}
}
@@ -4572,11 +4632,20 @@ rb_longjmp(tag, mesg)
if (!prot_tag) {
error_print();
}
- thread_reset_raised();
+ rb_thread_raised_clear(th);
JUMP_TAG(tag);
}
void
+rb_exc_jump(mesg)
+ VALUE mesg;
+{
+ rb_thread_raised_clear(rb_curr_thread);
+ ruby_errinfo = mesg;
+ JUMP_TAG(TAG_RAISE);
+}
+
+void
rb_exc_raise(mesg)
VALUE mesg;
{
@@ -4593,7 +4662,8 @@ rb_exc_fatal(mesg)
void
rb_interrupt()
{
- rb_raise(rb_eInterrupt, "");
+ static const char fmt[1] = {'\0'};
+ rb_raise(rb_eInterrupt, fmt);
}
/*
@@ -4740,7 +4810,7 @@ rb_f_block_given_p()
return Qfalse;
}
-static VALUE rb_eThreadError;
+VALUE rb_eThreadError;
NORETURN(static void proc_jump_error(int, VALUE));
static void
@@ -4749,7 +4819,7 @@ proc_jump_error(state, result)
VALUE result;
{
char mesg[32];
- char *statement;
+ const char *statement;
switch (state) {
case TAG_BREAK:
@@ -4863,7 +4933,7 @@ rb_yield_0(val, self, klass, flags, avalue)
VALUE val, self, klass; /* OK */
int flags, avalue;
{
- NODE *node;
+ NODE *node, *var;
volatile VALUE result = Qnil;
volatile VALUE old_cref;
volatile VALUE old_wrapper;
@@ -4905,27 +4975,35 @@ rb_yield_0(val, self, klass, flags, avalue)
self = block->self;
}
node = block->body;
+ var = block->var;
- if (block->var) {
+ if (var) {
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
- if (block->var == (NODE*)1) { /* no parameter || */
+ NODE *bvar = NULL;
+ block_var:
+ if (var == (NODE*)1) { /* no parameter || */
if (lambda && RARRAY(val)->len != 0) {
rb_raise(rb_eArgError, "wrong number of arguments (%ld for 0)",
RARRAY(val)->len);
}
}
- else if (block->var == (NODE*)2) {
+ else if (var == (NODE*)2) {
if (TYPE(val) == T_ARRAY && RARRAY(val)->len != 0) {
rb_raise(rb_eArgError, "wrong number of arguments (%ld for 0)",
RARRAY(val)->len);
}
}
- else if (nd_type(block->var) == NODE_MASGN) {
+ else if (!bvar && nd_type(var) == NODE_BLOCK_PASS) {
+ bvar = var->nd_body;
+ var = var->nd_args;
+ goto block_var;
+ }
+ else if (nd_type(var) == NODE_MASGN) {
if (!avalue) {
- val = svalue_to_mrhs(val, block->var->nd_head);
+ val = svalue_to_mrhs(val, var->nd_head);
}
- massign(self, block->var, val, lambda);
+ massign(self, var, val, lambda);
}
else {
int len = 0;
@@ -4946,13 +5024,21 @@ rb_yield_0(val, self, klass, flags, avalue)
val = Qnil;
multi_values:
{
- ruby_current_node = block->var;
+ ruby_current_node = var;
rb_warn("multiple values for a block parameter (%d for 1)\n\tfrom %s:%d",
len, cnode->nd_file, nd_line(cnode));
ruby_current_node = cnode;
}
}
- assign(self, block->var, val, lambda);
+ assign(self, var, val, lambda);
+ }
+ if (bvar) {
+ VALUE blk;
+ if (flags & YIELD_PROC_CALL)
+ blk = block->block_obj;
+ else
+ blk = rb_block_proc();
+ assign(self, bvar, blk, 0);
}
}
POP_TAG();
@@ -4969,12 +5055,18 @@ rb_yield_0(val, self, klass, flags, avalue)
if ((state = EXEC_TAG()) == 0) {
redo:
if (nd_type(node) == NODE_CFUNC || nd_type(node) == NODE_IFUNC) {
- if (node->nd_state == YIELD_FUNC_AVALUE) {
+ switch (node->nd_state) {
+ case YIELD_FUNC_LAMBDA:
+ if (!avalue) {
+ val = rb_ary_new3(1, val);
+ }
+ break;
+ case YIELD_FUNC_AVALUE:
if (!avalue) {
val = svalue_to_avalue(val);
}
- }
- else {
+ break;
+ default:
if (avalue) {
val = avalue_to_svalue(val);
}
@@ -5112,6 +5204,16 @@ rb_yield_splat(values)
return rb_yield_0(values, 0, 0, 0, avalue);
}
+static VALUE
+loop_i()
+{
+ for (;;) {
+ rb_yield_0(Qundef, 0, 0, 0, Qfalse);
+ CHECK_INTS;
+ }
+ return Qnil;
+}
+
/*
* call-seq:
* loop {|| block }
@@ -5124,15 +5226,14 @@ rb_yield_splat(values)
* break if !line or line =~ /^qQ/
* # ...
* end
+ *
+ * StopIteration raised in the block breaks the loop.
*/
static VALUE
rb_f_loop()
{
- for (;;) {
- rb_yield_0(Qundef, 0, 0, 0, Qfalse);
- CHECK_INTS;
- }
+ rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
return Qnil; /* dummy */
}
@@ -5259,7 +5360,7 @@ assign(self, lhs, val, pcall)
/* attr set */
ruby_current_node = lhs;
SET_CURRENT_SOURCE();
- rb_call(CLASS_OF(recv), recv, lhs->nd_mid, 1, &val, scope);
+ rb_call(CLASS_OF(recv), recv, lhs->nd_mid, 1, &val, scope, self);
}
else {
/* array set */
@@ -5270,7 +5371,7 @@ assign(self, lhs, val, pcall)
ruby_current_node = lhs;
SET_CURRENT_SOURCE();
rb_call(CLASS_OF(recv), recv, lhs->nd_mid,
- RARRAY(args)->len, RARRAY(args)->ptr, scope);
+ RARRAY(args)->len, RARRAY(args)->ptr, scope, self);
}
}
break;
@@ -5291,9 +5392,9 @@ rb_iterate(it_proc, data1, bl_proc, data2)
NODE *node = NEW_IFUNC(bl_proc, data2);
VALUE self = ruby_top_self;
- PUSH_ITER(ITER_PRE);
PUSH_TAG(PROT_LOOP);
PUSH_BLOCK(0, node);
+ PUSH_ITER(ITER_PRE);
state = EXEC_TAG();
if (state == 0) {
iter_retry:
@@ -5307,9 +5408,9 @@ rb_iterate(it_proc, data1, bl_proc, data2)
state = 0;
goto iter_retry;
}
+ POP_ITER();
POP_BLOCK();
POP_TAG();
- POP_ITER();
switch (state) {
case 0:
@@ -5377,7 +5478,7 @@ rb_rescue2(b_proc, data1, r_proc, data2, va_alist)
if (handle) break;
handle = Qfalse;
va_init_list(args, data2);
- while (eclass = va_arg(args, VALUE)) {
+ while ((eclass = va_arg(args, VALUE)) != 0) {
if (rb_obj_is_kind_of(ruby_errinfo, eclass)) {
handle = Qtrue;
break;
@@ -5455,7 +5556,9 @@ rb_ensure(b_proc, data1, e_proc, data2)
}
POP_TAG();
retval = prot_tag ? prot_tag->retval : Qnil; /* save retval */
- (*e_proc)(data2);
+ if (!thread_no_ensure()) {
+ (*e_proc)(data2);
+ }
if (prot_tag) return_value(retval);
if (state) JUMP_TAG(state);
return result;
@@ -5490,18 +5593,11 @@ rb_with_disable_interrupt(proc, data)
static void
stack_check()
{
- static int overflowing = 0;
+ rb_thread_t th = rb_curr_thread;
- if (!overflowing && ruby_stack_check()) {
- int state;
- overflowing = 1;
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- rb_exc_raise(sysstack_error);
- }
- POP_TAG();
- overflowing = 0;
- JUMP_TAG(state);
+ if (!rb_thread_raised_p(th, RAISED_STACKOVERFLOW) && ruby_stack_check()) {
+ rb_thread_raised_set(th, RAISED_STACKOVERFLOW);
+ rb_exc_raise(sysstack_error);
}
}
@@ -5550,7 +5646,7 @@ rb_method_missing(argc, argv, obj)
{
ID id;
VALUE exc = rb_eNoMethodError;
- char *format = 0;
+ const char *format = 0;
NODE *cnode = ruby_current_node;
if (argc == 0 || !SYMBOL_P(argv[0])) {
@@ -5740,8 +5836,7 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
TMP_PROTECT;
volatile int safe = -1;
- if (NOEX_SAFE(flags) > ruby_safe_level &&
- !(flags&NOEX_TAINTED) && ruby_safe_level == 0 && NOEX_SAFE(flags) > 2) {
+ if (NOEX_SAFE(flags) > ruby_safe_level && NOEX_SAFE(flags) > 2) {
rb_raise(rb_eSecurityError, "calling insecure method: %s",
rb_id2name(id));
}
@@ -5844,7 +5939,7 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
}
result = proc_invoke(body->nd_cval, rb_ary_new4(argc, argv), recv, klass);
if (event_hooks) {
- EXEC_EVENT_HOOK(RUBY_EVENT_RETURN, body, recv, id, klass);
+ EXEC_EVENT_HOOK(RUBY_EVENT_RETURN, ruby_current_node, recv, id, klass);
}
break;
@@ -5928,14 +6023,21 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
while (opt && argc) {
assign(recv, opt->nd_head, *argv, 1);
argv++; argc--;
+ ++i;
opt = opt->nd_next;
}
if (opt) {
rb_eval(recv, opt);
+ while (opt) {
+ opt = opt->nd_next;
+ ++i;
+ }
}
+ }
+ if (!node->nd_rest) {
i = nopt;
}
- if (node->nd_rest) {
+ else {
VALUE v;
if (argc > 0) {
@@ -5960,7 +6062,7 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
}
POP_TAG();
if (event_hooks) {
- EXEC_EVENT_HOOK(RUBY_EVENT_RETURN, body, recv, id, klass);
+ EXEC_EVENT_HOOK(RUBY_EVENT_RETURN, ruby_current_node, recv, id, klass);
}
POP_VARS();
POP_CLASS();
@@ -5996,12 +6098,13 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
}
static VALUE
-rb_call(klass, recv, mid, argc, argv, scope)
+rb_call(klass, recv, mid, argc, argv, scope, self)
VALUE klass, recv;
ID mid;
int argc; /* OK */
const VALUE *argv; /* OK */
int scope;
+ VALUE self;
{
NODE *body; /* OK */
int noex;
@@ -6038,10 +6141,11 @@ rb_call(klass, recv, mid, argc, argv, scope)
if (noex & NOEX_PROTECTED) {
VALUE defined_class = klass;
+ if (self == Qundef) self = ruby_frame->self;
if (TYPE(defined_class) == T_ICLASS) {
defined_class = RBASIC(defined_class)->klass;
}
- if (!rb_obj_is_kind_of(ruby_frame->self, rb_class_real(defined_class)))
+ if (!rb_obj_is_kind_of(self, rb_class_real(defined_class)))
return method_missing(recv, mid, argc, argv, CSTAT_PROT);
}
}
@@ -6061,7 +6165,7 @@ rb_apply(recv, mid, args)
argc = RARRAY(args)->len; /* Assigns LONG, but argc is INT */
argv = ALLOCA_N(VALUE, argc);
MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);
- return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 1);
+ return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 1, Qundef);
}
/*
@@ -6094,7 +6198,7 @@ rb_f_send(argc, argv, recv)
vid = *argv++; argc--;
PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
- vid = rb_call(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, 1);
+ vid = rb_call(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, 1, Qundef);
POP_ITER();
return vid;
@@ -6123,7 +6227,7 @@ vafuncall(recv, mid, n, ar)
argv = 0;
}
- return rb_call(CLASS_OF(recv), recv, mid, n, argv, 1);
+ return rb_call(CLASS_OF(recv), recv, mid, n, argv, 1, Qundef);
}
VALUE
@@ -6182,7 +6286,7 @@ rb_funcall2(recv, mid, argc, argv)
int argc;
const VALUE *argv;
{
- return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 1);
+ return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 1, Qundef);
}
VALUE
@@ -6192,7 +6296,7 @@ rb_funcall3(recv, mid, argc, argv)
int argc;
const VALUE *argv;
{
- return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 0);
+ return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 0, Qundef);
}
VALUE
@@ -6214,7 +6318,7 @@ rb_call_super(argc, argv)
}
PUSH_ITER(ruby_iter->iter ? ITER_PRE : ITER_NOT);
- result = rb_call(RCLASS(klass)->super, self, ruby_frame->orig_func, argc, argv, 3);
+ result = rb_call(RCLASS(klass)->super, self, ruby_frame->orig_func, argc, argv, 3, Qundef);
POP_ITER();
return result;
@@ -6342,10 +6446,16 @@ rb_frame_last_func()
return ruby_frame->last_func;
}
+ID
+rb_frame_this_func()
+{
+ return ruby_frame->orig_func;
+}
+
static NODE*
compile(src, file, line)
VALUE src;
- char *file;
+ const char *file;
int line;
{
NODE *node;
@@ -6365,7 +6475,7 @@ compile(src, file, line)
static VALUE
eval(self, src, scope, file, line)
VALUE self, src, scope;
- char *file;
+ const char *file;
int line;
{
struct BLOCK *data = NULL;
@@ -6479,16 +6589,17 @@ eval(self, src, scope, file, line)
if (state) {
if (state == TAG_RAISE) {
if (strcmp(file, "(eval)") == 0) {
- VALUE mesg, errat;
+ VALUE mesg, errat, bt2;
errat = get_backtrace(ruby_errinfo);
- mesg = rb_attr_get(ruby_errinfo, rb_intern("mesg"));
- if (!NIL_P(errat) && TYPE(errat) == T_ARRAY) {
+ mesg = rb_attr_get(ruby_errinfo, rb_intern("mesg"));
+ if (!NIL_P(errat) && TYPE(errat) == T_ARRAY &&
+ (bt2 = backtrace(-2), RARRAY_LEN(bt2) > 0)) {
if (!NIL_P(mesg) && TYPE(mesg) == T_STRING) {
rb_str_update(mesg, 0, 0, rb_str_new2(": "));
- rb_str_update(mesg, 0, 0, RARRAY(errat)->ptr[0]);
+ rb_str_update(mesg, 0, 0, RARRAY_PTR(errat)[0]);
}
- RARRAY(errat)->ptr[0] = RARRAY(backtrace(-2))->ptr[0];
+ RARRAY_PTR(errat)[0] = RARRAY_PTR(bt2)[0];
}
}
rb_exc_raise(ruby_errinfo);
@@ -6525,7 +6636,7 @@ rb_f_eval(argc, argv, self)
VALUE self;
{
VALUE src, scope, vfile, vline;
- char *file = "(eval)";
+ const char *file = "(eval)";
int line = 1;
rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
@@ -6642,12 +6753,28 @@ yield_under_i(self)
return rb_yield_0(self, self, ruby_class, YIELD_PUBLIC_DEF, Qfalse);
}
+static VALUE
+yield_args_under_i(vinfo)
+ VALUE vinfo;
+{
+ VALUE *info = (VALUE *)vinfo;
+
+ return rb_yield_0(info[0], info[1], ruby_class, YIELD_PUBLIC_DEF, Qtrue);
+}
+
/* block eval under the class/module context */
static VALUE
-yield_under(under, self)
- VALUE under, self;
+yield_under(under, self, args)
+ VALUE under, self, args;
{
- return exec_under(yield_under_i, under, 0, self);
+ if (args == Qundef) {
+ return exec_under(yield_under_i, under, 0, self);
+ }
+ else {
+ VALUE info[2] = { args, self };
+
+ return exec_under(yield_args_under_i, under, 0, (VALUE)info);
+ }
}
static VALUE
@@ -6660,10 +6787,10 @@ specific_eval(argc, argv, klass, self)
if (argc > 0) {
rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
}
- return yield_under(klass, self);
+ return yield_under(klass, self, Qundef);
}
else {
- char *file = "(eval)";
+ const char *file = "(eval)";
int line = 1;
if (argc == 0) {
@@ -6732,6 +6859,41 @@ rb_obj_instance_eval(argc, argv, self)
/*
* call-seq:
+ * obj.instance_exec(arg...) {|var...| block } => obj
+ *
+ * Executes the given block within the context of the receiver
+ * (_obj_). In order to set the context, the variable +self+ is set
+ * to _obj_ while the code is executing, giving the code access to
+ * _obj_'s instance variables. Arguments are passed as block parameters.
+ *
+ * class KlassWithSecret
+ * def initialize
+ * @secret = 99
+ * end
+ * end
+ * k = KlassWithSecret.new
+ * k.instance_exec(5) {|x| @secret+x } #=> 104
+ */
+
+VALUE
+rb_obj_instance_exec(argc, argv, self)
+ int argc;
+ VALUE *argv;
+ VALUE self;
+{
+ VALUE klass;
+
+ if (SPECIAL_CONST_P(self)) {
+ klass = Qnil;
+ }
+ else {
+ klass = rb_singleton_class(self);
+ }
+ return yield_under(klass, self, rb_ary_new4(argc, argv));
+}
+
+/*
+ * call-seq:
* mod.class_eval(string [, filename [, lineno]]) => obj
* mod.module_eval {|| block } => obj
*
@@ -6763,6 +6925,35 @@ rb_mod_module_eval(argc, argv, mod)
return specific_eval(argc, argv, mod, mod);
}
+/*
+ * call-seq:
+ * mod.module_exec(arg...) {|var...| block } => obj
+ * mod.class_exec(arg...) {|var...| block } => obj
+ *
+ * Evaluates the given block in the context of the class/module.
+ * The method defined in the block will belong to the receiver.
+ *
+ * class Thing
+ * end
+ * Thing.class_exec{
+ * def hello() "Hello there!" end
+ * }
+ * puts Thing.new.hello()
+ *
+ * <em>produces:</em>
+ *
+ * Hello there!
+ */
+
+VALUE
+rb_mod_module_exec(argc, argv, mod)
+ int argc;
+ VALUE *argv;
+ VALUE mod;
+{
+ return yield_under(mod, mod, rb_ary_new4(argc, argv));
+}
+
VALUE rb_load_path;
NORETURN(static void load_failed _((VALUE)));
@@ -6780,7 +6971,6 @@ rb_load(fname, wrap)
volatile VALUE self = ruby_top_self;
NODE *volatile last_node;
NODE *saved_cref = ruby_cref;
- TMP_PROTECT;
if (wrap && ruby_safe_level >= 4) {
StringValue(fname);
@@ -6798,7 +6988,7 @@ rb_load(fname, wrap)
ruby_errinfo = Qnil; /* ensure */
PUSH_VARS();
PUSH_CLASS(ruby_wrapper);
- ruby_cref = top_cref;
+ ruby_cref = ruby_top_cref;
if (!wrap) {
rb_secure(4); /* should alter global state */
ruby_class = rb_cObject;
@@ -6924,13 +7114,25 @@ static st_table *loading_tbl;
#define IS_DLEXT(e) (strcmp(e, DLEXT) == 0)
#endif
-static char *
+
+static const char *const loadable_ext[] = {
+ ".rb", DLEXT,
+#ifdef DLEXT2
+ DLEXT2,
+#endif
+ 0
+};
+
+static int rb_feature_p _((const char *, const char *, int));
+static int search_required _((VALUE, VALUE *, VALUE *));
+
+static int
rb_feature_p(feature, ext, rb)
const char *feature, *ext;
int rb;
{
VALUE v;
- char *f, *e;
+ const char *f, *e;
long i, len, elen;
if (ext) {
@@ -6941,51 +7143,64 @@ rb_feature_p(feature, ext, rb)
len = strlen(feature);
elen = 0;
}
- for (i = 0; i < RARRAY(rb_features)->len; ++i) {
- v = RARRAY(rb_features)->ptr[i];
+ for (i = 0; i < RARRAY_LEN(rb_features); ++i) {
+ v = RARRAY_PTR(rb_features)[i];
f = StringValuePtr(v);
- if (strncmp(f, feature, len) != 0) continue;
+ if (RSTRING_LEN(v) < len || strncmp(f, feature, len) != 0)
+ continue;
if (!*(e = f + len)) {
if (ext) continue;
- return e;
+ return 'u';
}
if (*e != '.') continue;
if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) {
- return e;
+ return 's';
}
if ((rb || !ext) && (strcmp(e, ".rb") == 0)) {
- return e;
+ return 'r';
+ }
+ }
+ if (loading_tbl) {
+ if (st_lookup(loading_tbl, (st_data_t)feature, 0)) {
+ if (!ext) return 'u';
+ return strcmp(ext, ".rb") ? 's' : 'r';
+ }
+ else {
+ char *buf;
+
+ if (ext && *ext) return 0;
+ buf = ALLOCA_N(char, len + DLEXT_MAXLEN + 1);
+ MEMCPY(buf, feature, char, len);
+ for (i = 0; (e = loadable_ext[i]) != 0; i++) {
+ strncpy(buf + len, e, DLEXT_MAXLEN + 1);
+ if (st_lookup(loading_tbl, (st_data_t)buf, 0)) {
+ return i ? 's' : 'r';
+ }
+ }
}
}
return 0;
}
-static const char *const loadable_ext[] = {
- ".rb", DLEXT,
-#ifdef DLEXT2
- DLEXT2,
-#endif
- 0
-};
-
int
rb_provided(feature)
const char *feature;
{
- int i;
- char *buf;
+ const char *ext = strrchr(feature, '.');
- if (rb_feature_p(feature, 0, Qfalse))
- return Qtrue;
- if (!loading_tbl) return Qfalse;
- if (st_lookup(loading_tbl, (st_data_t)feature, 0)) return Qtrue;
- buf = ALLOCA_N(char, strlen(feature)+8);
- strcpy(buf, feature);
- for (i=0; ; i++) {
- if (!loadable_ext[i]) break;
- strcpy(buf+strlen(feature), loadable_ext[i]);
- if (st_lookup(loading_tbl, (st_data_t)buf, 0)) return Qtrue;
+ if (ext && !strchr(ext, '/')) {
+ if (strcmp(".rb", ext) == 0) {
+ if (rb_feature_p(feature, ext, Qtrue)) return Qtrue;
+ return Qfalse;
+ }
+ else if (IS_SOEXT(ext) || IS_DLEXT(ext)) {
+ if (rb_feature_p(feature, ext, Qfalse)) return Qtrue;
+ return Qfalse;
+ }
}
+ if (rb_feature_p(feature, feature + strlen(feature), Qtrue))
+ return Qtrue;
+
return Qfalse;
}
@@ -7003,19 +7218,41 @@ rb_provide(feature)
rb_provide_feature(rb_str_new2(feature));
}
-static int
-load_wait(ftptr)
- char *ftptr;
+static char *
+load_lock(ftptr)
+ const char *ftptr;
{
st_data_t th;
- if (!loading_tbl) return Qfalse;
- if (!st_lookup(loading_tbl, (st_data_t)ftptr, &th)) return Qfalse;
+ if (!loading_tbl ||
+ !st_lookup(loading_tbl, (st_data_t)ftptr, &th))
+ {
+ /* loading ruby library should be serialized. */
+ if (!loading_tbl) {
+ loading_tbl = st_init_strtable();
+ }
+ /* partial state */
+ ftptr = ruby_strdup(ftptr);
+ st_insert(loading_tbl, (st_data_t)ftptr, (st_data_t)curr_thread);
+ return (char *)ftptr;
+ }
do {
- if ((rb_thread_t)th == curr_thread) return Qtrue;
+ if ((rb_thread_t)th == curr_thread) return 0;
CHECK_INTS;
} while (st_lookup(loading_tbl, (st_data_t)ftptr, &th));
- return Qtrue;
+ return 0;
+}
+
+static void
+load_unlock(const char *ftptr)
+{
+ if (ftptr) {
+ st_data_t key = (st_data_t)ftptr;
+
+ if (st_delete(loading_tbl, &key, 0)) {
+ free((char *)key);
+ }
+ }
}
/*
@@ -7057,16 +7294,16 @@ search_required(fname, featurep, path)
*featurep = fname;
*path = 0;
- ext = strrchr(ftptr = RSTRING(fname)->ptr, '.');
+ ext = strrchr(ftptr = RSTRING_PTR(fname), '.');
if (ext && !strchr(ext, '/')) {
if (strcmp(".rb", ext) == 0) {
if (rb_feature_p(ftptr, ext, Qtrue)) return 'r';
- if (*path = rb_find_file(fname)) return 'r';
+ if ((*path = rb_find_file(fname)) != 0) return 'r';
return 0;
}
else if (IS_SOEXT(ext)) {
if (rb_feature_p(ftptr, ext, Qfalse)) return 's';
- tmp = rb_str_new(RSTRING(fname)->ptr, ext-RSTRING(fname)->ptr);
+ tmp = rb_str_new(RSTRING_PTR(fname), ext-RSTRING_PTR(fname));
*featurep = tmp;
#ifdef DLEXT2
OBJ_FREEZE(tmp);
@@ -7078,27 +7315,25 @@ search_required(fname, featurep, path)
#else
rb_str_cat2(tmp, DLEXT);
OBJ_FREEZE(tmp);
- if (*path = rb_find_file(tmp)) {
+ if ((*path = rb_find_file(tmp)) != 0) {
return 's';
}
#endif
}
else if (IS_DLEXT(ext)) {
if (rb_feature_p(ftptr, ext, Qfalse)) return 's';
- if (*path = rb_find_file(fname)) return 's';
+ if ((*path = rb_find_file(fname)) != 0) return 's';
}
}
tmp = fname;
- switch (type = rb_find_file_ext(&tmp, loadable_ext)) {
+ type = rb_find_file_ext(&tmp, loadable_ext);
+ *featurep = tmp;
+ switch (type) {
case 0:
- if ((ext = rb_feature_p(ftptr, 0, Qfalse))) {
- type = strcmp(".rb", ext);
- break;
- }
- return 0;
+ ftptr = RSTRING_PTR(tmp);
+ return rb_feature_p(ftptr, 0, Qfalse);
default:
- *featurep = tmp;
ext = strrchr(ftptr = RSTRING(tmp)->ptr, '.');
if (rb_feature_p(ftptr, ext, !--type)) break;
*path = rb_find_file(tmp);
@@ -7146,20 +7381,13 @@ rb_require_safe(fname, safe)
ruby_safe_level = safe;
found = search_required(fname, &feature, &path);
if (found) {
- if (!path || load_wait(RSTRING(feature)->ptr)) {
+ if (!path || !(ftptr = load_lock(RSTRING_PTR(feature)))) {
result = Qfalse;
}
else {
ruby_safe_level = 0;
switch (found) {
case 'r':
- /* loading ruby library should be serialized. */
- if (!loading_tbl) {
- loading_tbl = st_init_strtable();
- }
- /* partial state */
- ftptr = ruby_strdup(RSTRING(feature)->ptr);
- st_insert(loading_tbl, (st_data_t)ftptr, (st_data_t)curr_thread);
rb_load(path, 0);
break;
@@ -7184,11 +7412,7 @@ rb_require_safe(fname, safe)
ruby_frame->last_func = saved.func;
SCOPE_SET(saved.vmode);
ruby_safe_level = saved.safe;
- if (ftptr) {
- if (st_delete(loading_tbl, (st_data_t *)&ftptr, 0)) { /* loading done */
- free(ftptr);
- }
- }
+ load_unlock(ftptr);
if (state) JUMP_TAG(state);
if (NIL_P(result)) {
load_failed(fname);
@@ -7207,6 +7431,24 @@ rb_require(fname)
return rb_require_safe(fn, ruby_safe_level);
}
+void
+ruby_init_ext(name, init)
+ const char *name;
+ void (*init) _((void));
+{
+ ruby_current_node = 0;
+ ruby_sourcefile = rb_source_filename(name);
+ ruby_sourceline = 0;
+ ruby_frame->last_func = 0;
+ ruby_frame->orig_func = 0;
+ SCOPE_SET(SCOPE_PUBLIC);
+ if (load_lock(name)) {
+ (*init)();
+ rb_provide(name);
+ load_unlock(name);
+ }
+}
+
static void
secure_visibility(self)
VALUE self;
@@ -7455,7 +7697,7 @@ rb_mod_modfunc(argc, argv, module)
body = search_method(rb_cObject, id, &m);
}
if (body == 0 || body->nd_body == 0) {
- rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
+ print_undef(module, id);
}
if (nd_type(body->nd_body) != NODE_ZSUPER) {
break; /* normal case: need not to follow 'super' link */
@@ -7873,6 +8115,37 @@ rb_exec_end_proc()
ruby_safe_level = safe;
}
+/*
+ * call-seq:
+ * __method__ => symbol
+ *
+ * Returns the name of the current method as a Symbol.
+ * If called from inside of an aliased method it will return the original
+ * nonaliased name.
+ * If called outside of a method, it returns <code>nil</code>.
+ *
+ * def foo
+ * __method__
+ * end
+ * alias bar foo
+ *
+ * foo # => :foo
+ * bar # => :foo
+ *
+ */
+
+static VALUE
+rb_f_method_name()
+{
+ struct FRAME* prev = ruby_frame->prev;
+ if (prev && prev->orig_func) {
+ return ID2SYM(prev->orig_func);
+ }
+ else {
+ return Qnil;
+ }
+}
+
void
Init_eval()
{
@@ -7894,11 +8167,11 @@ Init_eval()
__id__ = rb_intern("__id__");
__send__ = rb_intern("__send__");
- rb_global_variable((VALUE*)&top_scope);
- rb_global_variable((VALUE*)&ruby_eval_tree_begin);
+ rb_global_variable((void *)&top_scope);
+ rb_global_variable((void *)&ruby_eval_tree_begin);
- rb_global_variable((VALUE*)&ruby_eval_tree);
- rb_global_variable((VALUE*)&ruby_dyna_vars);
+ rb_global_variable((void *)&ruby_eval_tree);
+ rb_global_variable((void *)&ruby_dyna_vars);
rb_define_virtual_variable("$@", errat_getter, errat_setter);
rb_define_hooked_variable("$!", &ruby_errinfo, 0, errinfo_setter);
@@ -7911,7 +8184,7 @@ Init_eval()
rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
respond_to = rb_intern("respond_to?");
- rb_global_variable((VALUE*)&basic_respond_to);
+ rb_global_variable((void *)&basic_respond_to);
basic_respond_to = rb_method_node(rb_cObject, respond_to);
rb_define_global_function("raise", rb_f_raise, -1);
@@ -7929,9 +8202,12 @@ Init_eval()
rb_define_global_function("global_variables", rb_f_global_variables, 0); /* in variable.c */
rb_define_global_function("local_variables", rb_f_local_variables, 0);
+ rb_define_global_function("__method__", rb_f_method_name, 0);
+
rb_define_method(rb_mKernel, "send", rb_f_send, -1);
rb_define_method(rb_mKernel, "__send__", rb_f_send, -1);
rb_define_method(rb_mKernel, "instance_eval", rb_obj_instance_eval, -1);
+ rb_define_method(rb_mKernel, "instance_exec", rb_obj_instance_exec, -1);
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);
@@ -7947,7 +8223,9 @@ Init_eval()
rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
+ rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
+ rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
rb_undef_method(rb_cClass, "module_function");
@@ -8236,20 +8514,42 @@ proc_clone(self)
* MISSING: documentation
*/
+#define PROC_TSHIFT (FL_USHIFT+1)
+#define PROC_TMASK (FL_USER1|FL_USER2|FL_USER3)
+#define PROC_TMAX (PROC_TMASK >> PROC_TSHIFT)
+
+static int proc_get_safe_level(VALUE);
+
static VALUE
proc_dup(self)
VALUE self;
{
struct BLOCK *orig, *data;
VALUE bind;
+ int safe = proc_get_safe_level(self);
Data_Get_Struct(self, struct BLOCK, orig);
bind = Data_Make_Struct(rb_obj_class(self),struct BLOCK,blk_mark,blk_free,data);
blk_dup(data, orig);
+ if (safe > PROC_TMAX) safe = PROC_TMAX;
+ FL_SET(bind, (safe << PROC_TSHIFT) & PROC_TMASK);
return bind;
}
+VALUE
+rb_block_dup(self, klass, cref)
+ VALUE self, klass, cref;
+{
+ struct BLOCK *block;
+ VALUE obj = proc_dup(self);
+ Data_Get_Struct(obj, struct BLOCK, block);
+ block->klass = klass;
+ block->cref = NEW_NODE(nd_type(block->cref), cref, block->cref->u2.node,
+ block->cref->u3.node);
+ return obj;
+}
+
/*
* call-seq:
* binding -> a_binding
@@ -8307,9 +8607,34 @@ rb_f_binding(self)
return bind;
}
-#define PROC_TSHIFT (FL_USHIFT+1)
-#define PROC_TMASK (FL_USER1|FL_USER2|FL_USER3)
-#define PROC_TMAX (PROC_TMASK >> PROC_TSHIFT)
+/*
+ * call-seq:
+ * binding.eval(string [, filename [,lineno]]) => obj
+ *
+ * Evaluates the Ruby expression(s) in <em>string</em>, in the
+ * <em>binding</em>'s context. If the optional <em>filename</em> and
+ * <em>lineno</em> parameters are present, they will be used when
+ * reporting syntax errors.
+ *
+ * def getBinding(param)
+ * return binding
+ * end
+ * b = getBinding("hello")
+ * b.eval("param") #=> "hello"
+ */
+
+static VALUE
+bind_eval(argc, argv, bindval)
+ int argc;
+ VALUE *argv;
+ VALUE bindval;
+{
+ VALUE args[4];
+
+ rb_scan_args(argc, argv, "12", &args[0], &args[2], &args[3]);
+ args[1] = bindval;
+ return rb_f_eval(argc+1, args, Qnil /* self will be searched in eval */);
+}
#define SAFE_LEVEL_MAX PROC_TMASK
@@ -8472,13 +8797,12 @@ proc_invoke(proc, args, self, klass)
volatile VALUE old_wrapper = ruby_wrapper;
volatile int pcall, avalue = Qtrue;
volatile VALUE tmp = args;
+ VALUE bvar = Qnil;
if (rb_block_given_p() && ruby_frame->last_func) {
if (klass != ruby_frame->last_class)
klass = rb_obj_class(proc);
- rb_warning("block for %s#%s is useless",
- rb_class2name(klass),
- rb_id2name(ruby_frame->last_func));
+ bvar = rb_block_proc();
}
Data_Get_Struct(proc, struct BLOCK, data);
@@ -8494,6 +8818,7 @@ proc_invoke(proc, args, self, klass)
/* PUSH BLOCK from data */
old_block = ruby_block;
_block = *data;
+ _block.block_obj = bvar;
if (self != Qundef) _block.frame.self = self;
if (klass) _block.frame.last_class = klass;
_block.frame.argc = RARRAY(tmp)->len;
@@ -8514,7 +8839,8 @@ proc_invoke(proc, args, self, klass)
state = EXEC_TAG();
if (state == 0) {
proc_set_safe_level(proc);
- result = rb_yield_0(args, self, (self!=Qundef)?CLASS_OF(self):0, pcall, avalue);
+ result = rb_yield_0(args, self, (self!=Qundef)?CLASS_OF(self):0,
+ pcall | YIELD_PROC_CALL, avalue);
}
else if (TAG_DST()) {
result = prot_tag->retval;
@@ -8583,8 +8909,8 @@ proc_invoke(proc, args, self, klass)
* from prog.rb:5
*/
-static VALUE
-proc_call(proc, args)
+VALUE
+rb_proc_call(proc, args)
VALUE proc, args; /* OK */
{
return proc_invoke(proc, args, Qundef, 0);
@@ -8618,30 +8944,36 @@ proc_arity(proc)
VALUE proc;
{
struct BLOCK *data;
- NODE *list;
+ NODE *var, *list;
int n;
Data_Get_Struct(proc, struct BLOCK, data);
- if (data->var == 0) {
+ var = data->var;
+ if (var == 0) {
if (data->body && nd_type(data->body) == NODE_IFUNC &&
data->body->nd_cfnc == bmcall) {
return method_arity(data->body->nd_tval);
}
return INT2FIX(-1);
}
- if (data->var == (NODE*)1) return INT2FIX(0);
- if (data->var == (NODE*)2) return INT2FIX(0);
- switch (nd_type(data->var)) {
+ if (var == (NODE*)1) return INT2FIX(0);
+ if (var == (NODE*)2) return INT2FIX(0);
+ if (nd_type(var) == NODE_BLOCK_ARG) {
+ var = var->nd_args;
+ if (var == (NODE*)1) return INT2FIX(0);
+ if (var == (NODE*)2) return INT2FIX(0);
+ }
+ switch (nd_type(var)) {
default:
return INT2FIX(1);
case NODE_MASGN:
- list = data->var->nd_head;
+ list = var->nd_head;
n = 0;
while (list) {
n++;
list = list->nd_next;
}
- if (data->var->nd_args) return INT2FIX(-n-1);
+ if (var->nd_args) return INT2FIX(-n-1);
return INT2FIX(n);
}
}
@@ -8689,7 +9021,7 @@ proc_to_s(self)
{
struct BLOCK *data;
NODE *node;
- char *cname = rb_obj_classname(self);
+ const char *cname = rb_obj_classname(self);
const int w = (sizeof(VALUE) * CHAR_BIT) / 4;
long len = strlen(cname)+6+w; /* 6:tags 16:addr */
VALUE str;
@@ -8903,6 +9235,7 @@ mnew(klass, obj, id, mklass)
(FL_TEST(rklass, FL_SINGLETON) || TYPE(rklass) == T_ICLASS)) {
rklass = RCLASS(rklass)->super;
}
+ if (TYPE(klass) == T_ICLASS) klass = RBASIC(klass)->klass;
method = Data_Make_Struct(mklass, struct METHOD, bm_mark, free, data);
data->klass = klass;
data->recv = obj;
@@ -8910,7 +9243,7 @@ mnew(klass, obj, id, mklass)
data->body = body;
data->rklass = rklass;
data->oid = oid;
- data->safe_level = NOEX_WITH_SAFE(0);
+ data->safe_level = NOEX_WITH_SAFE(noex);
OBJ_INFECT(method, klass);
return method;
@@ -9002,6 +9335,57 @@ method_unbind(obj)
/*
* call-seq:
+ * meth.receiver => object
+ *
+ * Returns the bound receiver of the method object.
+ */
+
+static VALUE
+method_receiver(obj)
+ VALUE obj;
+{
+ struct METHOD *data;
+
+ Data_Get_Struct(obj, struct METHOD, data);
+ return data->recv;
+}
+
+/*
+ * call-seq:
+ * meth.name => string
+ *
+ * Returns the name of the method.
+ */
+
+static VALUE
+method_name(obj)
+ VALUE obj;
+{
+ struct METHOD *data;
+
+ Data_Get_Struct(obj, struct METHOD, data);
+ return rb_str_new2(rb_id2name(data->oid));
+}
+
+/*
+ * call-seq:
+ * meth.owner => class_or_module
+ *
+ * Returns the class or module that defines the method.
+ */
+
+static VALUE
+method_owner(obj)
+ VALUE obj;
+{
+ struct METHOD *data;
+
+ Data_Get_Struct(obj, struct METHOD, data);
+ return data->klass;
+}
+
+/*
+ * call-seq:
* obj.method(sym) => method
*
* Looks up the named method as a receiver in <i>obj</i>, returning a
@@ -9028,7 +9412,7 @@ method_unbind(obj)
* m.call #=> "Hello, @iv = Fred"
*/
-static VALUE
+VALUE
rb_obj_method(obj, vid)
VALUE obj;
VALUE vid;
@@ -9095,6 +9479,29 @@ method_clone(self)
return clone;
}
+VALUE
+rb_method_dup(self, klass, cref)
+ VALUE self;
+ VALUE klass;
+ VALUE cref;
+{
+ VALUE clone;
+ struct METHOD *orig, *data;
+
+ Data_Get_Struct(self, struct METHOD, orig);
+ clone = Data_Make_Struct(CLASS_OF(self),struct METHOD, bm_mark, free, data);
+ *data = *orig;
+ data->rklass = klass;
+ if (data->body->nd_rval) {
+ NODE *tmp = NEW_NODE(nd_type(data->body->u2.node), cref,
+ data->body->u2.node->u2.node,
+ data->body->u2.node->u3.node);
+ data->body = NEW_NODE(nd_type(data->body), data->body->u1.node, tmp,
+ data->body->u3.node);
+ }
+ return clone;
+}
+
/*
* call-seq:
* meth.call(args, ...) => obj
@@ -9348,7 +9755,7 @@ method_inspect(method)
struct METHOD *data;
VALUE str;
const char *s;
- char *sharp = "#";
+ const char *sharp = "#";
Data_Get_Struct(method, struct METHOD, data);
str = rb_str_buf_new2("#<");
@@ -9377,12 +9784,8 @@ method_inspect(method)
else {
rb_str_buf_cat2(str, rb_class2name(data->rklass));
if (data->rklass != data->klass) {
- VALUE klass = data -> klass;
- if (TYPE(klass) == T_ICLASS) {
- klass = RBASIC(klass)->klass;
- }
rb_str_buf_cat2(str, "(");
- rb_str_buf_cat2(str, rb_class2name(klass));
+ rb_str_buf_cat2(str, rb_class2name(data->klass));
rb_str_buf_cat2(str, ")");
}
}
@@ -9431,7 +9834,8 @@ rb_proc_new(func, val)
VALUE proc = rb_iterate((VALUE(*)_((VALUE)))mproc, 0, func, val);
Data_Get_Struct(proc, struct BLOCK, data);
- data->body->nd_state = YIELD_FUNC_AVALUE;
+ data->body->nd_state = YIELD_FUNC_LAMBDA;
+ data->flags |= BLOCK_LAMBDA;
return proc;
}
@@ -9551,14 +9955,14 @@ rb_mod_define_method(argc, argv, mod)
rb_raise(rb_eTypeError, "wrong argument type (expected Proc/Method)");
}
- if (SCOPE_TEST(SCOPE_PRIVATE)) {
- noex = NOEX_PRIVATE;
- }
- else if (SCOPE_TEST(SCOPE_PROTECTED)) {
- noex = NOEX_PROTECTED;
- }
- else {
- noex = NOEX_PUBLIC;
+ noex = NOEX_PUBLIC;
+ if (ruby_cbase == mod) {
+ if (SCOPE_TEST(SCOPE_PRIVATE)) {
+ noex = NOEX_PRIVATE;
+ }
+ else if (SCOPE_TEST(SCOPE_PROTECTED)) {
+ noex = NOEX_PROTECTED;
+ }
}
rb_add_method(mod, id, node, noex);
return body;
@@ -9590,12 +9994,17 @@ Init_Proc()
rb_define_method(rb_eLocalJumpError, "reason", localjump_reason, 0);
rb_global_variable(&exception_error);
- exception_error = rb_exc_new2(rb_eFatal, "exception reentered");
+ exception_error = rb_exc_new3(rb_eFatal,
+ rb_obj_freeze(rb_str_new2("exception reentered")));
+ OBJ_TAINT(exception_error);
+ OBJ_FREEZE(exception_error);
rb_eSysStackError = rb_define_class("SystemStackError", rb_eStandardError);
rb_global_variable(&sysstack_error);
- sysstack_error = rb_exc_new2(rb_eSysStackError, "stack level too deep");
+ sysstack_error = rb_exc_new3(rb_eSysStackError,
+ rb_obj_freeze(rb_str_new2("stack level too deep")));
OBJ_TAINT(sysstack_error);
+ OBJ_FREEZE(sysstack_error);
rb_cProc = rb_define_class("Proc", rb_cObject);
rb_undef_alloc_func(rb_cProc);
@@ -9603,9 +10012,9 @@ Init_Proc()
rb_define_method(rb_cProc, "clone", proc_clone, 0);
rb_define_method(rb_cProc, "dup", proc_dup, 0);
- rb_define_method(rb_cProc, "call", proc_call, -2);
+ rb_define_method(rb_cProc, "call", rb_proc_call, -2);
rb_define_method(rb_cProc, "arity", proc_arity, 0);
- rb_define_method(rb_cProc, "[]", proc_call, -2);
+ rb_define_method(rb_cProc, "[]", rb_proc_call, -2);
rb_define_method(rb_cProc, "==", proc_eq, 1);
rb_define_method(rb_cProc, "to_s", proc_to_s, 0);
rb_define_method(rb_cProc, "to_proc", proc_to_self, 0);
@@ -9625,6 +10034,9 @@ Init_Proc()
rb_define_method(rb_cMethod, "inspect", method_inspect, 0);
rb_define_method(rb_cMethod, "to_s", method_inspect, 0);
rb_define_method(rb_cMethod, "to_proc", method_proc, 0);
+ rb_define_method(rb_cMethod, "receiver", method_receiver, 0);
+ 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_mKernel, "method", rb_obj_method, 1);
@@ -9636,6 +10048,8 @@ Init_Proc()
rb_define_method(rb_cUnboundMethod, "arity", method_arity, 0);
rb_define_method(rb_cUnboundMethod, "inspect", method_inspect, 0);
rb_define_method(rb_cUnboundMethod, "to_s", method_inspect, 0);
+ 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_cModule, "instance_method", rb_mod_method, 1);
}
@@ -9683,22 +10097,10 @@ Init_Binding()
rb_undef_method(CLASS_OF(rb_cBinding), "new");
rb_define_method(rb_cBinding, "clone", proc_clone, 0);
rb_define_method(rb_cBinding, "dup", proc_dup, 0);
+ rb_define_method(rb_cBinding, "eval", bind_eval, -1);
rb_define_global_function("binding", rb_f_binding, 0);
}
-#ifdef __ia64__
-#if defined(__FreeBSD__)
-/*
- * FreeBSD/ia64 currently does not have a way for a process to get the
- * base address for the RSE backing store, so hardcode it.
- */
-#define __libc_ia64_register_backing_store_base (4ULL<<61)
-#else
-#pragma weak __libc_ia64_register_backing_store_base
-extern unsigned long __libc_ia64_register_backing_store_base;
-#endif
-#endif
-
/* Windows SEH refers data on the stack. */
#undef SAVE_WIN32_EXCEPTION_LIST
#if defined _WIN32 || defined __CYGWIN__
@@ -9763,13 +10165,6 @@ VALUE rb_cThread;
extern VALUE rb_last_status;
-enum thread_status {
- THREAD_TO_KILL,
- THREAD_RUNNABLE,
- THREAD_STOPPED,
- THREAD_KILLED,
-};
-
#define WAIT_FD (1<<0)
#define WAIT_SELECT (1<<1)
#define WAIT_TIME (1<<2)
@@ -9787,70 +10182,9 @@ enum thread_status {
# endif
#endif
-/* typedef struct thread * rb_thread_t; */
-
-struct thread {
- struct thread *next, *prev;
- rb_jmpbuf_t context;
-#ifdef SAVE_WIN32_EXCEPTION_LIST
- DWORD win32_exception_list;
-#endif
-
- VALUE result;
-
- long stk_len;
- long stk_max;
- VALUE *stk_ptr;
- VALUE *stk_pos;
-#ifdef __ia64__
- VALUE *bstr_ptr;
- long bstr_len;
-#endif
-
- struct FRAME *frame;
- struct SCOPE *scope;
- struct RVarmap *dyna_vars;
- struct BLOCK *block;
- struct iter *iter;
- struct tag *tag;
- VALUE klass;
- VALUE wrapper;
- NODE *cref;
-
- int flags; /* misc. states (vmode/rb_trap_immediate/raised) */
-
- NODE *node;
-
- int tracing;
- VALUE errinfo;
- VALUE last_status;
- VALUE last_line;
- VALUE last_match;
-
- int safe;
-
- enum thread_status status;
- int wait_for;
- int fd;
- fd_set readfds;
- fd_set writefds;
- fd_set exceptfds;
- int select_value;
- double delay;
- rb_thread_t join;
-
- int abort;
- int priority;
- VALUE thgroup;
-
- st_table *locals;
-
- VALUE thread;
-};
-
-#define THREAD_RAISED 0x200 /* temporary flag */
#define THREAD_TERMINATING 0x400 /* persistent flag */
-#define THREAD_FLAGS_MASK 0x400 /* mask for persistent flags */
+#define THREAD_NO_ENSURE 0x800 /* persistent flag */
+#define THREAD_FLAGS_MASK 0xfc00 /* mask for persistent flags */
#define FOREACH_THREAD_FROM(f,x) x = f; do { x = x->next;
#define END_FOREACH_FROM(f,x) } while (x != f)
@@ -9869,7 +10203,7 @@ struct thread_status_t {
int safe;
- enum thread_status status;
+ enum rb_thread_status status;
int wait_for;
int fd;
fd_set readfds;
@@ -9902,22 +10236,34 @@ struct thread_status_t {
(dst)->join = (src)->join, \
0)
-static int
-thread_set_raised()
+int
+rb_thread_set_raised(th)
+ rb_thread_t th;
{
- if (curr_thread->flags & THREAD_RAISED) return 1;
- curr_thread->flags |= THREAD_RAISED;
+ if (th->flags & RAISED_EXCEPTION) {
+ return 1;
+ }
+ th->flags |= RAISED_EXCEPTION;
return 0;
}
-static int
-thread_reset_raised()
+int
+rb_thread_reset_raised(th)
+ rb_thread_t th;
{
- if (!(curr_thread->flags & THREAD_RAISED)) return 0;
- curr_thread->flags &= ~THREAD_RAISED;
+ if (!(th->flags & RAISED_EXCEPTION)) {
+ return 0;
+ }
+ th->flags &= ~RAISED_EXCEPTION;
return 1;
}
+static int
+thread_no_ensure()
+{
+ return ((curr_thread->flags & THREAD_NO_ENSURE) == THREAD_NO_ENSURE);
+}
+
static void rb_thread_ready _((rb_thread_t));
static VALUE run_trap_eval _((VALUE));
@@ -9965,7 +10311,7 @@ rb_trap_eval(cmd, sig, safe)
static const char *
thread_status_name(status)
- enum thread_status status;
+ enum rb_thread_status status;
{
switch (status) {
case THREAD_RUNNABLE:
@@ -10019,6 +10365,13 @@ static double
timeofday()
{
struct timeval tv;
+#ifdef CLOCK_MONOTONIC
+ struct timespec tp;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
+ return (double)tp.tv_sec + (double)tp.tv_nsec * 1e-9;
+ }
+#endif
gettimeofday(&tv, NULL);
return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
}
@@ -10048,6 +10401,7 @@ thread_mark(th)
rb_gc_mark(th->last_match);
rb_mark_tbl(th->locals);
rb_gc_mark(th->thgroup);
+ rb_gc_mark_maybe(th->sandbox);
/* mark data in copied stack */
if (th == curr_thread) return;
@@ -10058,9 +10412,9 @@ thread_mark(th)
#if defined(THINK_C) || defined(__human68k__)
rb_gc_mark_locations(th->stk_ptr+2, th->stk_ptr+th->stk_len+2);
#endif
-#ifdef __ia64__
+#ifdef __ia64
if (th->bstr_ptr) {
- rb_gc_mark_locations(th->bstr_ptr, th->bstr_ptr+th->bstr_len);
+ rb_gc_mark_locations(th->bstr_ptr, th->bstr_ptr+th->bstr_len);
}
#endif
}
@@ -10146,7 +10500,7 @@ thread_free(th)
{
if (th->stk_ptr) free(th->stk_ptr);
th->stk_ptr = 0;
-#ifdef __ia64__
+#ifdef __ia64
if (th->bstr_ptr) free(th->bstr_ptr);
th->bstr_ptr = 0;
#endif
@@ -10175,7 +10529,6 @@ static VALUE th_raise_exception;
static NODE *th_raise_node;
static VALUE th_cmd;
static int th_sig, th_safe;
-static char *th_signm;
#define RESTORE_NORMAL 1
#define RESTORE_FATAL 2
@@ -10186,13 +10539,16 @@ static char *th_signm;
#define RESTORE_EXIT 7
extern VALUE *rb_gc_stack_start;
+#ifdef __ia64
+extern VALUE *rb_gc_register_stack_start;
+#endif
static void
rb_thread_save_context(th)
rb_thread_t th;
{
VALUE *pos;
- int len;
+ size_t len;
static VALUE tval;
len = ruby_stack_length(&pos);
@@ -10207,22 +10563,19 @@ rb_thread_save_context(th)
th->stk_len = len;
FLUSH_REGISTER_WINDOWS;
MEMCPY(th->stk_ptr, th->stk_pos, VALUE, th->stk_len);
-#ifdef __ia64__
- {
- ucontext_t ctx;
- VALUE *top, *bot;
-
- getcontext(&ctx);
- bot = (VALUE*)__libc_ia64_register_backing_store_base;
-#if defined(__FreeBSD__)
- top = (VALUE*)ctx.uc_mcontext.mc_special.bspstore;
-#else
- top = (VALUE*)ctx.uc_mcontext.sc_ar_bsp;
-#endif
- th->bstr_len = top - bot;
- REALLOC_N(th->bstr_ptr, VALUE, th->bstr_len);
- MEMCPY(th->bstr_ptr, (VALUE*)__libc_ia64_register_backing_store_base, VALUE, th->bstr_len);
- }
+#ifdef __ia64
+ th->bstr_pos = rb_gc_register_stack_start;
+ len = (VALUE*)rb_ia64_bsp() - th->bstr_pos;
+ th->bstr_len = 0;
+ if (len > th->bstr_max) {
+ VALUE *ptr = realloc(th->bstr_ptr, sizeof(VALUE) * len);
+ if (!ptr) rb_memerror();
+ th->bstr_ptr = ptr;
+ th->bstr_max = len;
+ }
+ th->bstr_len = len;
+ rb_ia64_flushrs();
+ MEMCPY(th->bstr_ptr, th->bstr_pos, VALUE, th->bstr_len);
#endif
#ifdef SAVE_WIN32_EXCEPTION_LIST
th->win32_exception_list = win32_get_exception_list();
@@ -10252,6 +10605,10 @@ rb_thread_save_context(th)
th->safe = ruby_safe_level;
th->node = ruby_current_node;
+ if (ruby_sandbox_save != NULL)
+ {
+ ruby_sandbox_save(th);
+ }
}
static int
@@ -10277,7 +10634,7 @@ rb_thread_switch(n)
rb_raise_jump(th_raise_exception);
break;
case RESTORE_SIGNAL:
- rb_raise(rb_eSignal, "SIG%s", th_signm);
+ rb_thread_signal_raise(th_sig);
break;
case RESTORE_EXIT:
ruby_errinfo = th_raise_exception;
@@ -10295,53 +10652,24 @@ rb_thread_switch(n)
}
#define THREAD_SAVE_CONTEXT(th) \
- (rb_thread_save_context(th),\
- rb_thread_switch((FLUSH_REGISTER_WINDOWS, ruby_setjmp((th)->context))))
+ (rb_thread_switch(ruby_setjmp(rb_thread_save_context(th), (th)->context)))
NORETURN(static void rb_thread_restore_context _((rb_thread_t,int)));
-
-# if defined(_MSC_VER) && _MSC_VER >= 1300
-__declspec(noinline) static void stack_extend(rb_thread_t, int);
-# endif
-static void
-stack_extend(th, exit)
- rb_thread_t th;
- int exit;
-{
- VALUE space[1024];
-
- memset(space, 0, 1); /* prevent array from optimization */
- rb_thread_restore_context(th, exit);
-}
+NORETURN(NOINLINE(static void rb_thread_restore_context_0(rb_thread_t,int,void*)));
+NORETURN(NOINLINE(static void stack_extend(rb_thread_t, int, VALUE *)));
static void
-rb_thread_restore_context(th, exit)
- rb_thread_t th;
- int exit;
+rb_thread_restore_context_0(rb_thread_t th, int exit, void *vp)
{
- VALUE v;
static rb_thread_t tmp;
static int ex;
static VALUE tval;
- if (!th->stk_ptr) rb_bug("unsaved context");
-
-#if STACK_GROW_DIRECTION < 0
- if (&v > th->stk_pos) stack_extend(th, exit);
-#elif STACK_GROW_DIRECTION > 0
- if (&v < th->stk_pos + th->stk_len) stack_extend(th, exit);
-#else
- if (&v < rb_gc_stack_start) {
- /* Stack grows downward */
- if (&v > th->stk_pos) stack_extend(th, exit);
- }
- else {
- /* Stack grows upward */
- if (&v < th->stk_pos + th->stk_len) stack_extend(th, exit);
- }
-#endif
-
rb_trap_immediate = 0; /* inhibit interrupts from here */
+ if (ruby_sandbox_restore != NULL)
+ {
+ ruby_sandbox_restore(th);
+ }
ruby_frame = th->frame;
ruby_scope = th->scope;
ruby_class = th->klass;
@@ -10366,8 +10694,8 @@ rb_thread_restore_context(th, exit)
ex = exit;
FLUSH_REGISTER_WINDOWS;
MEMCPY(tmp->stk_pos, tmp->stk_ptr, VALUE, tmp->stk_len);
-#ifdef __ia64__
- MEMCPY((VALUE*)__libc_ia64_register_backing_store_base, tmp->bstr_ptr, VALUE, tmp->bstr_len);
+#ifdef __ia64
+ MEMCPY(tmp->bstr_pos, tmp->bstr_ptr, VALUE, tmp->bstr_len);
#endif
tval = rb_lastline_get();
@@ -10380,6 +10708,78 @@ rb_thread_restore_context(th, exit)
ruby_longjmp(tmp->context, ex);
}
+#ifdef __ia64
+#define C(a) rse_##a##0, rse_##a##1, rse_##a##2, rse_##a##3, rse_##a##4
+#define E(a) rse_##a##0= rse_##a##1= rse_##a##2= rse_##a##3= rse_##a##4
+static volatile int C(a), C(b), C(c), C(d), C(e);
+static volatile int C(f), C(g), C(h), C(i), C(j);
+static volatile int C(k), C(l), C(m), C(n), C(o);
+static volatile int C(p), C(q), C(r), C(s), C(t);
+int rb_dummy_false = 0;
+NORETURN(NOINLINE(static void register_stack_extend(rb_thread_t, int, void *, VALUE *)));
+static void
+register_stack_extend(rb_thread_t th, int exit, void *vp, VALUE *curr_bsp)
+{
+ if (rb_dummy_false) {
+ /* use registers as much as possible */
+ E(a) = E(b) = E(c) = E(d) = E(e) =
+ E(f) = E(g) = E(h) = E(i) = E(j) =
+ E(k) = E(l) = E(m) = E(n) = E(o) =
+ E(p) = E(q) = E(r) = E(s) = E(t) = 0;
+ E(a) = E(b) = E(c) = E(d) = E(e) =
+ E(f) = E(g) = E(h) = E(i) = E(j) =
+ E(k) = E(l) = E(m) = E(n) = E(o) =
+ E(p) = E(q) = E(r) = E(s) = E(t) = 0;
+ }
+ if (curr_bsp < th->bstr_pos+th->bstr_len) {
+ register_stack_extend(th, exit, &exit, (VALUE*)rb_ia64_bsp());
+ }
+ rb_thread_restore_context_0(th, exit, &exit);
+}
+#undef C
+#undef E
+#endif
+
+# if defined(_MSC_VER) && _MSC_VER >= 1300
+__declspec(noinline) static void stack_extend(rb_thread_t, int, VALUE*);
+# endif
+static void
+stack_extend(rb_thread_t th, int exit, VALUE *addr_in_prev_frame)
+{
+#define STACK_PAD_SIZE 1024
+ VALUE space[STACK_PAD_SIZE];
+
+#if STACK_GROW_DIRECTION < 0
+ if (addr_in_prev_frame > th->stk_pos) stack_extend(th, exit, &space[0]);
+#elif STACK_GROW_DIRECTION > 0
+ if (addr_in_prev_frame < th->stk_pos + th->stk_len) stack_extend(th, exit, &space[STACK_PAD_SIZE-1]);
+#else
+ if (addr_in_prev_frame < rb_gc_stack_start) {
+ /* Stack grows downward */
+ if (addr_in_prev_frame > th->stk_pos) stack_extend(th, exit, &space[0]);
+ }
+ else {
+ /* Stack grows upward */
+ if (addr_in_prev_frame < th->stk_pos + th->stk_len) stack_extend(th, exit, &space[STACK_PAD_SIZE-1]);
+ }
+#endif
+#ifdef __ia64
+ register_stack_extend(th, exit, space, (VALUE*)rb_ia64_bsp());
+#else
+ rb_thread_restore_context_0(th, exit, space);
+#endif
+}
+
+static void
+rb_thread_restore_context(th, exit)
+ rb_thread_t th;
+ int exit;
+{
+ VALUE v;
+ if (!th->stk_ptr) rb_bug("unsaved context");
+ stack_extend(th, exit, &v);
+}
+
static void
rb_thread_ready(th)
rb_thread_t th;
@@ -10557,6 +10957,7 @@ rb_thread_schedule()
}
#endif
rb_thread_pending = 0;
+ rb_gc_finalize_deferred();
if (curr_thread == curr_thread->next
&& curr_thread->status == THREAD_RUNNABLE)
return;
@@ -10976,7 +11377,7 @@ rb_thread_join(th, limit)
rb_thread_t th;
double limit;
{
- enum thread_status last_status = THREAD_RUNNABLE;
+ enum rb_thread_status last_status = THREAD_RUNNABLE;
if (rb_thread_critical) rb_thread_deadlock();
if (!rb_thread_dead(th)) {
@@ -10999,7 +11400,7 @@ rb_thread_join(th, limit)
if (!rb_thread_dead(th)) return Qfalse;
}
- if (!NIL_P(th->errinfo) && (th->flags & THREAD_RAISED)) {
+ if (!NIL_P(th->errinfo) && (th->flags & RAISED_EXCEPTION)) {
VALUE oldbt = get_backtrace(th->errinfo);
VALUE errat = make_backtrace();
VALUE errinfo = rb_obj_dup(th->errinfo);
@@ -11166,10 +11567,19 @@ VALUE
rb_thread_wakeup(thread)
VALUE thread;
{
+ if (!RTEST(rb_thread_wakeup_alive(thread)))
+ rb_raise(rb_eThreadError, "killed thread");
+ return thread;
+}
+
+VALUE
+rb_thread_wakeup_alive(thread)
+ VALUE thread;
+{
rb_thread_t th = rb_thread_check(thread);
if (th->status == THREAD_KILLED)
- rb_raise(rb_eThreadError, "killed thread");
+ return Qnil;
rb_thread_ready(th);
return thread;
@@ -11207,16 +11617,34 @@ rb_thread_run(thread)
}
+static void
+rb_kill_thread(th, flags)
+ rb_thread_t th;
+ int flags;
+{
+ if (th != curr_thread && th->safe < 4) {
+ rb_secure(4);
+ }
+ if (th->status == THREAD_TO_KILL || th->status == THREAD_KILLED)
+ return;
+ if (th == th->next || th == main_thread) rb_exit(EXIT_SUCCESS);
+
+ rb_thread_ready(th);
+ th->flags |= flags;
+ th->status = THREAD_TO_KILL;
+ if (!rb_thread_critical) rb_thread_schedule();
+}
+
+
/*
* call-seq:
- * thr.exit => thr or nil
- * thr.kill => thr or nil
- * thr.terminate => thr or nil
+ * thr.exit => thr
+ * thr.kill => thr
+ * thr.terminate => thr
*
- * Terminates <i>thr</i> and schedules another thread to be run. If this thread
- * is already marked to be killed, <code>exit</code> returns the
- * <code>Thread</code>. If this is the main thread, or the last thread, exits
- * the process.
+ * Terminates <i>thr</i> and schedules another thread to be run, returning
+ * the terminated <code>Thread</code>. If this is the main thread, or the
+ * last thread, exits the process.
*/
VALUE
@@ -11225,22 +11653,35 @@ rb_thread_kill(thread)
{
rb_thread_t th = rb_thread_check(thread);
- if (th != curr_thread && th->safe < 4) {
- rb_secure(4);
- }
- if (th->status == THREAD_TO_KILL || th->status == THREAD_KILLED)
- return thread;
- if (th == th->next || th == main_thread) rb_exit(EXIT_SUCCESS);
-
- rb_thread_ready(th);
- th->status = THREAD_TO_KILL;
- if (!rb_thread_critical) rb_thread_schedule();
+ rb_kill_thread(th, 0);
return thread;
}
/*
* call-seq:
+ * thr.exit! => thr
+ * thr.kill! => thr
+ * thr.terminate! => thr
+ *
+ * Terminates <i>thr</i> without calling ensure clauses and schedules
+ * another thread to be run, returning the terminated <code>Thread</code>.
+ * If this is the main thread, or the last thread, exits the process.
+ *
+ * See <code>Thread#exit</code> for the safer version.
+ */
+
+static VALUE
+rb_thread_kill_bang(thread)
+ VALUE thread;
+{
+ rb_thread_t th = rb_thread_check(thread);
+ rb_kill_thread(th, THREAD_NO_ENSURE);
+ return thread;
+}
+
+/*
+ * call-seq:
* Thread.kill(thread) => thread
*
* Causes the given <em>thread</em> to exit (see <code>Thread::exit</code>).
@@ -11328,7 +11769,7 @@ rb_thread_pass()
VALUE
rb_thread_stop()
{
- enum thread_status last_status = THREAD_RUNNABLE;
+ enum rb_thread_status last_status = THREAD_RUNNABLE;
rb_thread_critical = 0;
if (curr_thread == curr_thread->next) {
@@ -11393,10 +11834,12 @@ rb_thread_sleep_forever()
/*
* call-seq:
* thr.priority => integer
- *
- * Returns the priority of <i>thr</i>. Default is zero; higher-priority threads
- * will run before lower-priority threads.
- *
+ *
+ * Returns the priority of <i>thr</i>. Default is inherited from the
+ * current thread which creating the new thread, or zero for the
+ * initial main thread; higher-priority threads will run before
+ * lower-priority threads.
+ *
* Thread.current.priority #=> 0
*/
@@ -11411,10 +11854,10 @@ rb_thread_priority(thread)
/*
* call-seq:
* thr.priority= integer => thr
- *
+ *
* Sets the priority of <i>thr</i> to <i>integer</i>. Higher-priority threads
* will run before lower-priority threads.
- *
+ *
* count1 = count2 = 0
* a = Thread.new do
* loop { count1 += 1 }
@@ -11585,14 +12028,14 @@ rb_thread_group(thread)
return group;
}
-#ifdef __ia64__
+#ifdef __ia64
# define IA64_INIT(x) x
#else
# define IA64_INIT(x)
#endif
#define THREAD_ALLOC(th) do {\
- th = ALLOC(struct thread);\
+ th = ALLOC(struct rb_thread);\
\
th->next = 0;\
th->prev = 0;\
@@ -11607,6 +12050,7 @@ rb_thread_group(thread)
th->wait_for = 0;\
IA64_INIT(th->bstr_ptr = 0);\
IA64_INIT(th->bstr_len = 0);\
+ IA64_INIT(th->bstr_max = 0);\
FD_ZERO(&th->readfds);\
FD_ZERO(&th->writefds);\
FD_ZERO(&th->exceptfds);\
@@ -11632,6 +12076,11 @@ rb_thread_group(thread)
th->thgroup = thgroup_default;\
th->locals = 0;\
th->thread = 0;\
+ if (curr_thread == 0) {\
+ th->sandbox = Qnil;\
+ } else {\
+ th->sandbox = curr_thread->sandbox;\
+ }\
} while (0)
static rb_thread_t
@@ -11651,7 +12100,7 @@ rb_thread_alloc(klass)
return th;
}
-static int thread_init = 0;
+static int thread_init;
#if defined(_THREAD_SAFE)
static void
@@ -11670,6 +12119,11 @@ static void*
thread_timer(dummy)
void *dummy;
{
+ sigset_t all_signals;
+
+ sigfillset(&all_signals);
+ pthread_sigmask(SIG_BLOCK, &all_signals, 0);
+
for (;;) {
#ifdef HAVE_NANOSLEEP
struct timespec req, rem;
@@ -11751,7 +12205,7 @@ rb_thread_start_0(fn, arg, th)
volatile rb_thread_t th_save = th;
volatile VALUE thread = th->thread;
struct BLOCK *volatile saved_block = 0;
- enum thread_status status;
+ enum rb_thread_status status;
int state;
if (OBJ_FROZEN(curr_thread->thgroup)) {
@@ -11822,7 +12276,7 @@ rb_thread_start_0(fn, arg, th)
}
if (state && status != THREAD_TO_KILL && !NIL_P(ruby_errinfo)) {
- th->flags |= THREAD_RAISED;
+ th->flags |= RAISED_EXCEPTION;
if (state == TAG_FATAL) {
/* fatal error within this thread, need to stop whole script */
main_thread->errinfo = ruby_errinfo;
@@ -11859,7 +12313,7 @@ rb_thread_create(fn, arg)
VALUE (*fn)();
void *arg;
{
- Init_stack((VALUE*)&arg);
+ Init_stack((void *)&arg);
return rb_thread_start_0(fn, arg, rb_thread_alloc(rb_cThread));
}
@@ -12040,7 +12494,7 @@ rb_thread_status(thread)
rb_thread_t th = rb_thread_check(thread);
if (rb_thread_dead(th)) {
- if (!NIL_P(th->errinfo) && (th->flags & THREAD_RAISED))
+ if (!NIL_P(th->errinfo) && (th->flags & RAISED_EXCEPTION))
return Qnil;
return Qfalse;
}
@@ -12061,7 +12515,7 @@ rb_thread_status(thread)
* thr.alive? #=> false
*/
-static VALUE
+VALUE
rb_thread_alive_p(thread)
VALUE thread;
{
@@ -12198,13 +12652,15 @@ rb_thread_interrupt()
void
rb_thread_signal_raise(sig)
- char *sig;
+ int sig;
{
- if (sig == 0) return; /* should not happen */
rb_thread_critical = 0;
if (curr_thread == main_thread) {
+ VALUE argv[1];
+
rb_thread_ready(curr_thread);
- rb_raise(rb_eSignal, "SIG%s", sig);
+ argv[0] = INT2FIX(sig);
+ rb_exc_raise(rb_class_new_instance(1, argv, rb_eSignal));
}
rb_thread_ready(main_thread);
if (!rb_thread_dead(curr_thread)) {
@@ -12212,7 +12668,7 @@ rb_thread_signal_raise(sig)
return;
}
}
- th_signm = sig;
+ th_sig = sig;
curr_thread = main_thread;
rb_thread_restore_context(curr_thread, RESTORE_SIGNAL);
}
@@ -12492,7 +12948,7 @@ static VALUE
rb_thread_inspect(thread)
VALUE thread;
{
- char *cname = rb_obj_classname(thread);
+ const char *cname = rb_obj_classname(thread);
rb_thread_t th = rb_thread_check(thread);
const char *status = thread_status_name(th->status);
VALUE str;
@@ -12847,6 +13303,109 @@ thgroup_add(group, thread)
}
+/* variables for recursive traversals */
+static ID recursive_key;
+
+static VALUE
+recursive_check(hash, obj)
+ VALUE hash;
+ VALUE obj;
+{
+ if (NIL_P(hash) || TYPE(hash) != T_HASH) {
+ return Qfalse;
+ }
+ else {
+ VALUE list = rb_hash_aref(hash, ID2SYM(rb_frame_last_func()));
+
+ if (NIL_P(list) || TYPE(list) != T_HASH)
+ return Qfalse;
+ if (NIL_P(rb_hash_lookup(list, obj)))
+ return Qfalse;
+ return Qtrue;
+ }
+}
+
+static VALUE
+recursive_push(hash, obj)
+ VALUE hash;
+ VALUE obj;
+{
+ VALUE list, sym;
+
+ sym = ID2SYM(rb_frame_last_func());
+ if (NIL_P(hash) || TYPE(hash) != T_HASH) {
+ hash = rb_hash_new();
+ rb_thread_local_aset(rb_thread_current(), recursive_key, hash);
+ list = Qnil;
+ }
+ else {
+ list = rb_hash_aref(hash, sym);
+ }
+ if (NIL_P(list) || TYPE(list) != T_HASH) {
+ list = rb_hash_new();
+ rb_hash_aset(hash, sym, list);
+ }
+ rb_hash_aset(list, obj, Qtrue);
+ return hash;
+}
+
+static void
+recursive_pop(hash, obj)
+ VALUE hash;
+ VALUE obj;
+{
+ VALUE list, sym;
+
+ sym = ID2SYM(rb_frame_last_func());
+ if (NIL_P(hash) || TYPE(hash) != T_HASH) {
+ VALUE symname;
+ VALUE thrname;
+ symname = rb_inspect(sym);
+ thrname = rb_inspect(rb_thread_current());
+
+ rb_raise(rb_eTypeError, "invalid inspect_tbl hash for %s in %s",
+ StringValuePtr(symname), StringValuePtr(thrname));
+ }
+ list = rb_hash_aref(hash, sym);
+ if (NIL_P(list) || TYPE(list) != T_HASH) {
+ VALUE symname = rb_inspect(sym);
+ VALUE thrname = rb_inspect(rb_thread_current());
+ rb_raise(rb_eTypeError, "invalid inspect_tbl list for %s in %s",
+ StringValuePtr(symname), StringValuePtr(thrname));
+ }
+ rb_hash_delete(list, obj);
+}
+
+VALUE
+rb_exec_recursive(func, obj, arg)
+ VALUE (*func) _((VALUE, VALUE, int));
+ VALUE obj;
+ VALUE arg;
+{
+ VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key);
+ VALUE objid = rb_obj_id(obj);
+
+ if (recursive_check(hash, objid)) {
+ return (*func) (obj, arg, Qtrue);
+ }
+ else {
+ VALUE result = Qundef;
+ int state;
+
+ hash = recursive_push(hash, objid);
+ PUSH_TAG(PROT_NONE);
+ if ((state = EXEC_TAG()) == 0) {
+ result = (*func) (obj, arg, Qfalse);
+ }
+ POP_TAG();
+ recursive_pop(hash, objid);
+ if (state)
+ JUMP_TAG(state);
+ return result;
+ }
+}
+
+
/*
* +Thread+ encapsulates the behavior of a thread of
* execution, including the main thread of the Ruby script.
@@ -12861,6 +13420,7 @@ Init_Thread()
{
VALUE cThGroup;
+ recursive_key = rb_intern("__recursive_key__");
rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);
rb_cThread = rb_define_class("Thread", rb_cObject);
rb_undef_alloc_func(rb_cThread);
@@ -12889,6 +13449,9 @@ Init_Thread()
rb_define_method(rb_cThread, "kill", rb_thread_kill, 0);
rb_define_method(rb_cThread, "terminate", rb_thread_kill, 0);
rb_define_method(rb_cThread, "exit", rb_thread_kill, 0);
+ rb_define_method(rb_cThread, "kill!", rb_thread_kill_bang, 0);
+ rb_define_method(rb_cThread, "terminate!", rb_thread_kill_bang, 0);
+ rb_define_method(rb_cThread, "exit!", rb_thread_kill_bang, 0);
rb_define_method(rb_cThread, "value", rb_thread_value, 0);
rb_define_method(rb_cThread, "status", rb_thread_status, 0);
rb_define_method(rb_cThread, "join", rb_thread_join_m, -1);
@@ -13060,13 +13623,3 @@ rb_throw(tag, val)
argv[1] = val;
rb_f_throw(2, argv);
}
-
-/* flush_register_windows must not be inlined because flushrs doesn't flush
- * current frame in register stack. */
-#ifdef __ia64__
-void flush_register_windows(void)
-{
- __asm__ ("flushrs");
-}
-#endif
-
diff --git a/ext/Setup b/ext/Setup
index 7b214abde3..d0d6317a5e 100644
--- a/ext/Setup
+++ b/ext/Setup
@@ -28,6 +28,7 @@
#syck
#syslog
#tcltklib
+#thread
#tk
#win32ole
#zlib
diff --git a/ext/Setup.atheos b/ext/Setup.atheos
index 9b1bdecb95..6bda3a4cfb 100644
--- a/ext/Setup.atheos
+++ b/ext/Setup.atheos
@@ -28,6 +28,7 @@ strscan
syck
syslog
#tcltklib
+thread
#tk
#win32ole
zlib
diff --git a/ext/Setup.dj b/ext/Setup.dj
index f2ed3a4f16..4f94788886 100644
--- a/ext/Setup.dj
+++ b/ext/Setup.dj
@@ -28,6 +28,7 @@ strscan
syck
#syslog
#tcltklib
+thread
#tk
#win32ole
zlib
diff --git a/ext/Setup.emx b/ext/Setup.emx
index 7ea04543c5..afc5923577 100644
--- a/ext/Setup.emx
+++ b/ext/Setup.emx
@@ -28,6 +28,7 @@ strscan
#syck
#syslog
#tcltklib
+thread
#tk
#win32ole
#zlib
diff --git a/ext/Setup.nt b/ext/Setup.nt
index 7a330f801a..9f8abf9b8d 100644
--- a/ext/Setup.nt
+++ b/ext/Setup.nt
@@ -28,6 +28,7 @@ strscan
syck
#syslog
#tcltklib
+thread
#tk
win32ole
#zlib
diff --git a/ext/Setup.x68 b/ext/Setup.x68
index 9b9563d941..0966e737e9 100644
--- a/ext/Setup.x68
+++ b/ext/Setup.x68
@@ -28,6 +28,7 @@ strscan
#syck
#syslog
#tcltklib
+thread
#tk
#win32ole
#zlib
diff --git a/ext/Win32API/Win32API.c b/ext/Win32API/Win32API.c
index 96ce8c6636..a4fd0396f0 100644
--- a/ext/Win32API/Win32API.c
+++ b/ext/Win32API/Win32API.c
@@ -108,7 +108,7 @@ Win32API_initialize(self, dllname, proc, import, export)
}
if (16 < RARRAY(a_import)->len) {
- rb_raise(rb_eRuntimeError, "too many parameters: %d\n", RARRAY(a_import)->len);
+ rb_raise(rb_eRuntimeError, "too many parameters: %ld\n", RARRAY(a_import)->len);
}
rb_iv_set(self, "__import__", a_import);
diff --git a/ext/Win32API/lib/win32/registry.rb b/ext/Win32API/lib/win32/registry.rb
index 2671551a33..9a2f3827b7 100644
--- a/ext/Win32API/lib/win32/registry.rb
+++ b/ext/Win32API/lib/win32/registry.rb
@@ -493,7 +493,7 @@ module Win32
# utility functions
#
def self.expand_environ(str)
- str.gsub(/%([^%]+)%/) { ENV[$1] || $& }
+ str.gsub(/%([^%]+)%/) { ENV[$1] || ENV[$1.upcase] || $& }
end
@@type2name = { }
diff --git a/ext/Win32API/lib/win32/resolv.rb b/ext/Win32API/lib/win32/resolv.rb
index 6534d20760..92336fac28 100644
--- a/ext/Win32API/lib/win32/resolv.rb
+++ b/ext/Win32API/lib/win32/resolv.rb
@@ -11,7 +11,7 @@ module Win32
def self.get_hosts_path
path = get_hosts_dir
- path = File.join(path.gsub(/\\/, File::SEPARATOR), 'hosts')
+ path = File.expand_path('hosts', path)
File.exist?(path) ? path : nil
end
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index fd0cd65418..636c0907d6 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -224,14 +224,14 @@ GetVpValue(VALUE v, int must)
#ifdef ENABLE_NUMERIC_STRING
case T_STRING:
SafeStringValue(v);
- return VpCreateRbObject(strlen(RSTRING(v)->ptr) + VpBaseFig() + 1,
- RSTRING(v)->ptr);
+ return VpCreateRbObject(strlen(RSTRING_PTR(v)) + VpBaseFig() + 1,
+ RSTRING_PTR(v));
#endif /* ENABLE_NUMERIC_STRING */
case T_BIGNUM:
bg = rb_big2str(v, 10);
- return VpCreateRbObject(strlen(RSTRING(bg)->ptr) + VpBaseFig() + 1,
- RSTRING(bg)->ptr);
+ return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1,
+ RSTRING_PTR(bg));
default:
goto SomeOneMayDoIt;
}
@@ -240,7 +240,7 @@ SomeOneMayDoIt:
if(must) {
rb_raise(rb_eTypeError, "%s can't be coerced into BigDecimal",
rb_special_const_p(v)?
- RSTRING(rb_inspect(v))->ptr:
+ RSTRING_PTR(rb_inspect(v)):
rb_obj_classname(v)
);
}
@@ -332,7 +332,7 @@ BigDecimal_load(VALUE self, VALUE str)
unsigned long m=0;
SafeStringValue(str);
- pch = RSTRING(str)->ptr;
+ pch = (unsigned char *)RSTRING_PTR(str);
/* First get max prec */
while((*pch)!=(unsigned char)'\0' && (ch=*pch++)!=(unsigned char)':') {
if(!ISDIGIT(ch)) {
@@ -341,7 +341,7 @@ BigDecimal_load(VALUE self, VALUE str)
m = m*10 + (unsigned long)(ch-'0');
}
if(m>VpBaseFig()) m -= VpBaseFig();
- GUARD_OBJ(pv,VpNewRbClass(m,pch,self));
+ GUARD_OBJ(pv,VpNewRbClass(m,(char *)pch,self));
m /= VpBaseFig();
if(m && pv->MaxPrec>m) pv->MaxPrec = m+1;
return ToValue(pv);
@@ -474,7 +474,7 @@ VpNewRbClass(U_LONG mx, char *str, VALUE klass)
}
VP_EXPORT Real *
-VpCreateRbObject(U_LONG mx, char *str)
+VpCreateRbObject(U_LONG mx, const char *str)
{
Real *pv = VpAlloc(mx,str);
pv->obj = (VALUE)Data_Wrap_Struct(rb_cBigDecimal, 0, BigDecimal_delete, pv);
@@ -586,19 +586,22 @@ BigDecimal_to_f(VALUE self)
{
ENTER(1);
Real *p;
- double d, d2;
+ double d;
S_LONG e;
+ char *buf;
GUARD_OBJ(p,GetVpValue(self,1));
if(VpVtoD(&d, &e, p)!=1) return rb_float_new(d);
+ buf = ALLOCA_N(char,(unsigned int)VpNumOfChars(p,"E"));
+ VpToString(p, buf, 0, 0);
errno = 0;
- d2 = pow(10.0,(double)e);
- if((errno == ERANGE && e>0) || (d2>1.0 && (fabs(d) > (DBL_MAX / d2)))) {
+ d = strtod(buf, 0);
+ if(errno == ERANGE) {
VpException(VP_EXCEPTION_OVERFLOW,"BigDecimal to Float conversion",0);
if(d>0.0) return rb_float_new(DBL_MAX);
else return rb_float_new(-DBL_MAX);
}
- return rb_float_new(d*d2);
+ return rb_float_new(d);
}
/* The coerce method provides support for Ruby type coercion. It is not
@@ -781,17 +784,6 @@ BigDecimal_eq(VALUE self, VALUE r)
return BigDecimalCmp(self, r, '=');
}
-/* Returns true if the values are not equal in value. Values may be coerced
- * to perform the comparison:
- *
- * BigDecimal.new('1.0') != 1.0 -> false
- */
-static VALUE
-BigDecimal_ne(VALUE self, VALUE r)
-{
- return BigDecimalCmp(self, r, '!');
-}
-
/* call-seq:
* a < b
*
@@ -1062,7 +1054,7 @@ static VALUE
BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
{
VALUE f;
- Real *d,*rv;
+ Real *d,*rv=0;
f = BigDecimal_divremain(self,r,&d,&rv);
if(f!=(VALUE)0) return f;
return ToValue(rv);
@@ -1276,7 +1268,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
{
ENTER(5);
Real *c, *a;
- int iLoc;
+ int iLoc = 0;
U_LONG mx;
VALUE vLoc;
VALUE vRound;
@@ -1510,13 +1502,13 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
if(rb_scan_args(argc,argv,"01",&f)==1) {
if(TYPE(f)==T_STRING) {
SafeStringValue(f);
- psz = RSTRING(f)->ptr;
+ psz = RSTRING_PTR(f);
if(*psz==' ') {
fPlus = 1; psz++;
} else if(*psz=='+') {
fPlus = 2; psz++;
}
- while(ch=*psz++) {
+ while((ch=*psz++)!=0) {
if(ISSPACE(ch)) continue;
if(!ISDIGIT(ch)) {
if(ch=='F' || ch=='f') fmt = 1; /* F format */
@@ -1687,7 +1679,7 @@ BigDecimal_global_new(int argc, VALUE *argv, VALUE self)
mf = GetPositiveInt(nFig);
}
SafeStringValue(iniValue);
- GUARD_OBJ(pv,VpCreateRbObject(mf, RSTRING(iniValue)->ptr));
+ GUARD_OBJ(pv,VpCreateRbObject(mf, RSTRING_PTR(iniValue)));
return ToValue(pv);
}
@@ -1718,7 +1710,7 @@ BigDecimal_new(int argc, VALUE *argv, VALUE self)
mf = GetPositiveInt(nFig);
}
SafeStringValue(iniValue);
- GUARD_OBJ(pv,VpNewRbClass(mf, RSTRING(iniValue)->ptr,self));
+ GUARD_OBJ(pv,VpNewRbClass(mf, RSTRING_PTR(iniValue),self));
return ToValue(pv);
}
@@ -1811,76 +1803,94 @@ Init_bigdecimal(void)
/* Exceptions */
/*
- * Determines whether overflow, underflow or zero divide result in
+ * 0xff: Determines whether overflow, underflow or zero divide result in
* an exception being thrown. See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_ALL",INT2FIX(VP_EXCEPTION_ALL));
/*
- * Determines what happens when the result of a computation is not a
+ * 0x02: Determines what happens when the result of a computation is not a
* number (NaN). See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_NaN",INT2FIX(VP_EXCEPTION_NaN));
/*
- * Determines what happens when the result of a computation is infinity.
- * See BigDecimal.mode.
+ * 0x01: Determines what happens when the result of a computation is
+ * infinity. See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_INFINITY",INT2FIX(VP_EXCEPTION_INFINITY));
/*
- * Determines what happens when the result of a computation is an underflow
- * (a result too small to be represented). See BigDecimal.mode.
+ * 0x04: Determines what happens when the result of a computation is an
+ * underflow (a result too small to be represented). See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_UNDERFLOW",INT2FIX(VP_EXCEPTION_UNDERFLOW));
/*
- * Determines what happens when the result of a computation is an underflow
- * (a result too large to be represented). See BigDecimal.mode.
+ * 0x01: Determines what happens when the result of a computation is an
+ * underflow (a result too large to be represented). See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW",INT2FIX(VP_EXCEPTION_OVERFLOW));
/*
- * Determines what happens when a division by zero is performed.
+ * 0x01: Determines what happens when a division by zero is performed.
* See BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE",INT2FIX(VP_EXCEPTION_ZERODIVIDE));
/*
- * Determines what happens when a result must be rounded in order to
- * fit in the appropriate number of significant digits. See
+ * 0x100: Determines what happens when a result must be rounded in order to
+ * fit in the appropriate number of significant digits. See
* BigDecimal.mode.
*/
rb_define_const(rb_cBigDecimal, "ROUND_MODE",INT2FIX(VP_ROUND_MODE));
- /* Indicates that values should be rounded away from zero. See BigDecimal.mode. */
+ /* 1: Indicates that values should be rounded away from zero. See
+ * BigDecimal.mode.
+ */
rb_define_const(rb_cBigDecimal, "ROUND_UP",INT2FIX(VP_ROUND_UP));
- /* Indicates that values should be rounded towards zero. See BigDecimal.mode. */
+
+ /* 2: Indicates that values should be rounded towards zero. See
+ * BigDecimal.mode.
+ */
rb_define_const(rb_cBigDecimal, "ROUND_DOWN",INT2FIX(VP_ROUND_DOWN));
- /* Indicates that digits >= 5 should be rounded up, others rounded down. See BigDecimal.mode. */
+
+ /* 3: Indicates that digits >= 5 should be rounded up, others rounded down.
+ * See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_HALF_UP",INT2FIX(VP_ROUND_HALF_UP));
- /* Indicates that digits >= 6 should be rounded up, others rounded down. See BigDecimal.mode. */
+
+ /* 4: Indicates that digits >= 6 should be rounded up, others rounded down.
+ * See BigDecimal.mode.
+ */
rb_define_const(rb_cBigDecimal, "ROUND_HALF_DOWN",INT2FIX(VP_ROUND_HALF_DOWN));
- /* Round towards +infinity. See BigDecimal.mode. */
+ /* 5: Round towards +infinity. See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_CEILING",INT2FIX(VP_ROUND_CEIL));
- /* Round towards -infinity. See BigDecimal.mode. */
+
+ /* 6: Round towards -infinity. See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_FLOOR",INT2FIX(VP_ROUND_FLOOR));
- /* Round towards the even neighbor. See BigDecimal.mode. */
+
+ /* 7: Round towards the even neighbor. See BigDecimal.mode. */
rb_define_const(rb_cBigDecimal, "ROUND_HALF_EVEN",INT2FIX(VP_ROUND_HALF_EVEN));
- /* Indicates that a value is not a number. See BigDecimal.sign. */
+ /* 0: Indicates that a value is not a number. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_NaN",INT2FIX(VP_SIGN_NaN));
- /* Indicates that a value is +0. See BigDecimal.sign. */
+
+ /* 1: Indicates that a value is +0. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_ZERO",INT2FIX(VP_SIGN_POSITIVE_ZERO));
- /* Indicates that a value is -0. See BigDecimal.sign. */
+
+ /* -1: Indicates that a value is -0. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_ZERO",INT2FIX(VP_SIGN_NEGATIVE_ZERO));
- /* Indicates that a value is positive and finite. See BigDecimal.sign. */
+
+ /* 2: Indicates that a value is positive and finite. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_FINITE",INT2FIX(VP_SIGN_POSITIVE_FINITE));
- /* Indicates that a value is negative and finite. See BigDecimal.sign. */
+
+ /* -2: Indicates that a value is negative and finite. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_FINITE",INT2FIX(VP_SIGN_NEGATIVE_FINITE));
- /* Indicates that a value is positive and infinite. See BigDecimal.sign. */
+
+ /* 3: Indicates that a value is positive and infinite. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_INFINITE",INT2FIX(VP_SIGN_POSITIVE_INFINITE));
- /* Indicates that a value is negative and infinite. See BigDecimal.sign. */
+
+ /* -3: Indicates that a value is negative and infinite. See BigDecimal.sign. */
rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE",INT2FIX(VP_SIGN_NEGATIVE_INFINITE));
/* instance methods */
@@ -1921,7 +1931,6 @@ Init_bigdecimal(void)
rb_define_method(rb_cBigDecimal, "==", BigDecimal_eq, 1);
rb_define_method(rb_cBigDecimal, "===", BigDecimal_eq, 1);
rb_define_method(rb_cBigDecimal, "eql?", BigDecimal_eq, 1);
- rb_define_method(rb_cBigDecimal, "!=", BigDecimal_ne, 1);
rb_define_method(rb_cBigDecimal, "<", BigDecimal_lt, 1);
rb_define_method(rb_cBigDecimal, "<=", BigDecimal_le, 1);
rb_define_method(rb_cBigDecimal, ">", BigDecimal_gt, 1);
@@ -1956,17 +1965,27 @@ static int gfCheckVal = 1; /* Value checking flag in VpNmlz() */
static U_LONG gnPrecLimit = 0; /* Global upper limit of the precision newly allocated */
static U_LONG gfRoundMode = VP_ROUND_HALF_UP; /* Mode for general rounding operation */
+#ifndef BASE_FIG
static U_LONG BASE_FIG = 4; /* =log10(BASE) */
static U_LONG BASE = 10000L; /* Base value(value must be 10**BASE_FIG) */
/* The value of BASE**2 + BASE must be represented */
/* within one U_LONG. */
static U_LONG HALF_BASE = 5000L;/* =BASE/2 */
-static S_LONG DBLE_FIG = 8; /* figure of double */
static U_LONG BASE1 = 1000L; /* =BASE/10 */
+#else
+#ifndef BASE
+#error BASE_FIG is defined but BASE is not
+#endif
+#define HALF_BASE (BASE/2)
+#define BASE1 (BASE/10)
+#endif
+#ifndef DBLE_FIG
+#define DBLE_FIG (DBL_DIG+1) /* figure of double */
+#endif
static Real *VpConstOne; /* constant 1.0 */
static Real *VpPt5; /* constant 0.5 */
-static U_LONG maxnr = 100; /* Maximum iterations for calcurating sqrt. */
+#define maxnr 100UL /* Maximum iterations for calcurating sqrt. */
/* used in VpSqrt() */
/* ETC */
@@ -2083,8 +2102,8 @@ VpSetRoundMode(unsigned long n)
* (to let the compiler know they may be changed in outside
* (... but not actually..)).
*/
-volatile double gZero_ABCED9B1_CE73__00400511F31D = 0.0;
-volatile double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
+volatile const double gZero_ABCED9B1_CE73__00400511F31D = 0.0;
+volatile const double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
static double
Zero(void)
{
@@ -2169,7 +2188,7 @@ VpIsNegDoubleZero(double v)
}
VP_EXPORT int
-VpException(unsigned short f,char *str,int always)
+VpException(unsigned short f, const char *str,int always)
{
VALUE exc;
int fatal=0;
@@ -2206,8 +2225,8 @@ VpException(unsigned short f,char *str,int always)
return 0; /* 0 Means VpException() raised no exception */
raise:
- if(fatal) rb_fatal(str);
- else rb_raise(exc,str);
+ if(fatal) rb_fatal("%s", str);
+ else rb_raise(exc, "%s", str);
return 0;
}
@@ -2311,7 +2330,7 @@ NaN:
* returns number of chars needed to represent vp in specified format.
*/
VP_EXPORT U_LONG
-VpNumOfChars(Real *vp,char *pszFmt)
+VpNumOfChars(Real *vp,const char *pszFmt)
{
S_INT ex;
U_LONG nc;
@@ -2356,16 +2375,15 @@ VpNumOfChars(Real *vp,char *pszFmt)
VP_EXPORT U_LONG
VpInit(U_LONG BaseVal)
{
- U_LONG w;
- double v;
-
/* Setup +/- Inf NaN -0 */
VpGetDoubleNaN();
VpGetDoublePosInf();
VpGetDoubleNegInf();
VpGetDoubleNegZero();
+#ifndef BASE_FIG
if(BaseVal <= 0) {
+ U_LONG w;
/* Base <= 0, then determine Base by calcuration. */
BASE = 1;
while(
@@ -2382,6 +2400,8 @@ VpInit(U_LONG BaseVal)
BASE1 = BASE / 10;
BASE_FIG = 0;
while(BaseVal /= 10) ++BASE_FIG;
+#endif
+
/* Allocates Vp constants. */
VpConstOne = VpAlloc((U_LONG)1, "1");
VpPt5 = VpAlloc((U_LONG)1, ".5");
@@ -2390,15 +2410,6 @@ VpInit(U_LONG BaseVal)
gnAlloc = 0;
#endif /* _DEBUG */
- /* Determine # of digits available in one 'double'. */
-
- v = 1.0;
- DBLE_FIG = 0;
- while(v + 1.0 > 1.0) {
- ++DBLE_FIG;
- v /= 10;
- }
-
#ifdef _DEBUG
if(gfDebug) {
printf("VpInit: BaseVal = %lu\n", BaseVal);
@@ -2414,7 +2425,7 @@ VpInit(U_LONG BaseVal)
}
VP_EXPORT Real *
-VpOne()
+VpOne(void)
{
return VpConstOne;
}
@@ -2464,7 +2475,7 @@ overflow:
* NULL be returned if memory allocation is failed,or any error.
*/
VP_EXPORT Real *
-VpAlloc(U_LONG mx, char *szVal)
+VpAlloc(U_LONG mx, const char *szVal)
{
U_LONG i, ni, ipn, ipf, nf, ipe, ne, nalloc;
char v,*psz;
@@ -2501,7 +2512,7 @@ VpAlloc(U_LONG mx, char *szVal)
psz = ALLOCA_N(char,strlen(szVal)+1);
i = 0;
ipn = 0;
- while(psz[i]=szVal[ipn]) {
+ while((psz[i]=szVal[ipn])!=0) {
if(ISDIGIT(psz[i])) ++ni;
if(psz[i]=='_') {
if(ni>0) {ipn++;continue;}
@@ -2544,7 +2555,7 @@ VpAlloc(U_LONG mx, char *szVal)
else if(szVal[i] == '+') ++i;
/* Skip digits */
ni = 0; /* digits in mantissa */
- while(v = szVal[i]) {
+ while((v = szVal[i]) != 0) {
if(!ISDIGIT(v)) break;
++i;
++ni;
@@ -2558,7 +2569,7 @@ VpAlloc(U_LONG mx, char *szVal)
if(szVal[i] == '.') { /* xxx. */
++i;
ipf = i;
- while(v = szVal[i]) { /* get fraction part. */
+ while((v = szVal[i]) != 0) { /* get fraction part. */
if(!ISDIGIT(v)) break;
++i;
++nf;
@@ -2576,7 +2587,7 @@ VpAlloc(U_LONG mx, char *szVal)
ipe = i;
v = szVal[i];
if((v == '-') ||(v == '+')) ++i;
- while(v=szVal[i]) {
+ while((v=szVal[i])!=0) {
if(!ISDIGIT(v)) break;
++i;
++ne;
@@ -3879,7 +3890,7 @@ VpToFString(Real *a,char *psz,int fFmt,int fPlus)
* ne ... number of characters in exp_chr[],not including '+/-'.
*/
VP_EXPORT int
-VpCtoV(Real *a, char *int_chr, U_LONG ni, char *frac, U_LONG nf, char *exp_chr, U_LONG ne)
+VpCtoV(Real *a, const char *int_chr, U_LONG ni, const char *frac, U_LONG nf, const char *exp_chr, U_LONG ne)
{
U_LONG i, j, ind_a, ma, mi, me;
U_LONG loc;
@@ -4428,7 +4439,7 @@ VpLeftRound(Real *y, int f, int nf)
if(!VpHasVal(y)) return 0; /* Unable to round */
v = y->frac[0];
nf -= VpExponent(y)*BASE_FIG;
- while(v=v/10) nf--;
+ while((v /= 10) != 0) nf--;
nf += (BASE_FIG-1);
return VpMidRound(y,f,nf);
}
diff --git a/ext/bigdecimal/bigdecimal.h b/ext/bigdecimal/bigdecimal.h
index aabc551a76..4f77feab00 100644
--- a/ext/bigdecimal/bigdecimal.h
+++ b/ext/bigdecimal/bigdecimal.h
@@ -105,7 +105,7 @@ typedef struct {
VP_EXPORT Real *
VpNewRbClass(U_LONG mx,char *str,VALUE klass);
-VP_EXPORT Real *VpCreateRbObject(U_LONG mx,char *str);
+VP_EXPORT Real *VpCreateRbObject(U_LONG mx,const char *str);
VP_EXPORT U_LONG VpBaseFig(void);
VP_EXPORT U_LONG VpDblFig(void);
@@ -126,13 +126,13 @@ VP_EXPORT int VpIsRoundMode(unsigned long n);
VP_EXPORT unsigned long VpGetRoundMode(void);
VP_EXPORT unsigned long VpSetRoundMode(unsigned long n);
-VP_EXPORT int VpException(unsigned short f,char *str,int always);
+VP_EXPORT int VpException(unsigned short f,const char *str,int always);
VP_EXPORT int VpIsNegDoubleZero(double v);
-VP_EXPORT U_LONG VpNumOfChars(Real *vp,char *pszFmt);
+VP_EXPORT U_LONG VpNumOfChars(Real *vp,const char *pszFmt);
VP_EXPORT U_LONG VpInit(U_LONG BaseVal);
VP_EXPORT void *VpMemAlloc(U_LONG mb);
VP_EXPORT void VpFree(Real *pv);
-VP_EXPORT Real *VpAlloc(U_LONG mx, char *szVal);
+VP_EXPORT Real *VpAlloc(U_LONG mx, const char *szVal);
VP_EXPORT int VpAsgn(Real *c,Real *a,int isw);
VP_EXPORT int VpAddSub(Real *c,Real *a,Real *b,int operation);
VP_EXPORT int VpMult(Real *c,Real *a,Real *b);
@@ -143,7 +143,7 @@ VP_EXPORT void VpSzMantissa(Real *a,char *psz);
VP_EXPORT int VpToSpecialString(Real *a,char *psz,int fPlus);
VP_EXPORT void VpToString(Real *a,char *psz,int fFmt,int fPlus);
VP_EXPORT void VpToFString(Real *a,char *psz,int fFmt,int fPlus);
-VP_EXPORT int VpCtoV(Real *a,char *int_chr,U_LONG ni,char *frac,U_LONG nf,char *exp_chr,U_LONG ne);
+VP_EXPORT int VpCtoV(Real *a,const char *int_chr,U_LONG ni,const char *frac,U_LONG nf,const char *exp_chr,U_LONG ne);
VP_EXPORT int VpVtoD(double *d,S_LONG *e,Real *m);
VP_EXPORT void VpDtoV(Real *m,double d);
VP_EXPORT void VpItoV(Real *m,S_INT ival);
@@ -155,7 +155,7 @@ VP_EXPORT void VpFrac(Real *y,Real *x);
VP_EXPORT int VpPower(Real *y,Real *x,S_INT n);
/* VP constants */
-VP_EXPORT Real *VpOne();
+VP_EXPORT Real *VpOne(void);
/*
* ------------------
diff --git a/ext/bigdecimal/bigdecimal_en.html b/ext/bigdecimal/bigdecimal_en.html
index 02c88df43e..c2b86faef6 100644
--- a/ext/bigdecimal/bigdecimal_en.html
+++ b/ext/bigdecimal/bigdecimal_en.html
@@ -379,7 +379,7 @@ after every n digits for readability.
<CODE><PRE>
BigDecimal("0.1234567890123456789").to_s(10) # ==> "0.1234567890 123456789E0"
</PRE></CODE>
-n can be an string representing a positive integer number.
+n can be a string representing a positive integer number.
<CODE><PRE>
BigDecimal("0.1234567890123456789").to_s("10") # ==> "0.1234567890 123456789E0"
</PRE></CODE>
@@ -678,10 +678,9 @@ structure.
</DL>
<H3>Disadvantage of decimal representation</H3>
-Advantages stated so far can also be disadvantages if the input from outside is
- represented in binary.
-Translation error from decimal to binary or vice versa is inevitable.
-So,translation from Float(binary) to BigDecimal(decimal) is not alway done exactly.
+Because most computers have no internal decimal representaion.
+Once you use BigDecimal,you need to keep using it without
+considering computation cost if exact computation is required.
<H4>Which is the first input?</H4>
Because most people uses decimal notatin for numeric data representation,
diff --git a/ext/bigdecimal/bigdecimal_ja.html b/ext/bigdecimal/bigdecimal_ja.html
index 8fd95a6fe3..37bbcbbb09 100644
--- a/ext/bigdecimal/bigdecimal_ja.html
+++ b/ext/bigdecimal/bigdecimal_ja.html
@@ -676,10 +676,11 @@ exponent=1Asign=2 Ȃ琔l 1234.56784321 ł̂͌Βɕ܂B
<H3>10ĩfbg</H3>
͍܂ł̃bǵÂ܂܃fbgɂȂ܂B
-A10i2iA2i10iɕϊ悤ȑ͕ϊ덷
+A10i2iɕϊ悤ȑ͕ϊ덷
𔺂ꍇ邱Ƃ͂ł܂B
-ɌvZ@Ɏ荞܂ꂽ2il BigDecimal ̓\
-ϊƂɂ͌덷Ȃꍇ܂B
+T̃Rs[^10i̓\ĂȂ̂ŁA
+BigDecimal 𗘗pČ덷̌vZꍇ́AvZx
+𖳎ĂŌ܂ BigDecimal gpKv܂B
<H3>ŏ͉H</H3>
ŌvZƂɂ킴킴2igl͋ɂ߂Ă܂łB
diff --git a/ext/bigdecimal/extconf.rb b/ext/bigdecimal/extconf.rb
index a68a656044..0c8b98e4a3 100644
--- a/ext/bigdecimal/extconf.rb
+++ b/ext/bigdecimal/extconf.rb
@@ -1,2 +1,10 @@
require 'mkmf'
+
+base_fig = 0
+src = "(BASE * (BASE+1)) / BASE == (BASE+1)"
+while try_static_assert(src, nil, "-DBASE=10#{'0'*base_fig}UL")
+ base_fig += 1
+end
+$defs << "-DBASE=1#{'0'*base_fig}UL" << "-DBASE_FIG=#{base_fig}"
+
create_makefile('bigdecimal')
diff --git a/ext/curses/curses.c b/ext/curses/curses.c
index 4e84b0837f..9c51a2127f 100644
--- a/ext/curses/curses.c
+++ b/ext/curses/curses.c
@@ -1,5 +1,5 @@
/* -*- C -*-
- * $Id: curses.c,v 1.24.2.8 2006/07/18 05:08:34 matz Exp $
+ * $Id$
*
* ext/curses/curses.c
*
@@ -1255,7 +1255,6 @@ window_color_set(VALUE obj, VALUE col)
GetWINDOW(obj, winp);
res = wcolor_set(winp->window, NUM2INT(col), NULL);
return (res == OK) ? Qtrue : Qfalse;
- return Qfalse;
}
#endif /* USE_COLOR */
diff --git a/ext/curses/extconf.rb b/ext/curses/extconf.rb
index 01fe971093..0124bbbf4a 100644
--- a/ext/curses/extconf.rb
+++ b/ext/curses/extconf.rb
@@ -20,7 +20,7 @@ end
if make
for f in %w(beep bkgd bkgdset curs_set deleteln doupdate flash getbkgd getnstr init isendwin keyname keypad resizeterm scrl set setscrreg ungetch wattroff wattron wattrset wbkgd wbkgdset wdeleteln wgetnstr wresize wscrl wsetscrreg def_prog_mode reset_prog_mode timeout wtimeout nodelay init_color wcolor_set)
- have_func(f)
+ have_func(f) || (have_macro(f, curses) && $defs.push(format("-DHAVE_%s", f.upcase)))
end
flag = "-D_XOPEN_SOURCE_EXTENDED"
src = "int test_var[(sizeof(char*)>sizeof(int))*2-1];"
diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c
index 83e6a9893b..0247387fdc 100644
--- a/ext/dbm/dbm.c
+++ b/ext/dbm/dbm.c
@@ -2,8 +2,8 @@
dbm.c -
- $Author: usa $
- $Date: 2005/06/20 07:53:19 $
+ $Author$
+ $Date$
created at: Mon Jan 24 15:59:52 JST 1994
Copyright (C) 1995-2001 Yukihiro Matsumoto
@@ -812,5 +812,7 @@ Init_dbm()
#ifdef DB_VERSION_STRING
rb_define_const(rb_cDBM, "VERSION", rb_str_new2(DB_VERSION_STRING));
+#else
+ rb_define_const(rb_cDBM, "VERSION", rb_str_new2("unknown"));
#endif
}
diff --git a/ext/dbm/extconf.rb b/ext/dbm/extconf.rb
index 52ec688952..0074ab605b 100644
--- a/ext/dbm/extconf.rb
+++ b/ext/dbm/extconf.rb
@@ -2,9 +2,13 @@ require 'mkmf'
dir_config("dbm")
-dblib = with_config("dbm-type", nil)
+if dblib = with_config("dbm-type", nil)
+ dblib = dblib.split(/[ ,]+/)
+else
+ dblib = %w(db db2 db1 dbm gdbm gdbm_compat qdbm)
+end
-$dbm_conf_headers = {
+headers = {
"db" => ["db.h"],
"db1" => ["db1/ndbm.h", "db1.h", "ndbm.h"],
"db2" => ["db2/db.h", "db2.h", "db.h"],
@@ -14,48 +18,36 @@ $dbm_conf_headers = {
"qdbm" => ["relic.h"],
}
-def db_check(db)
- $dbm_conf_db_prefix = ""
- $dbm_conf_have_gdbm = false
- hsearch = ""
+def headers.db_check(db)
+ db_prefix = nil
+ have_gdbm = false
+ hsearch = nil
case db
when /^db2?$/
- $dbm_conf_db_prefix = "__db_n"
+ db_prefix = "__db_n"
hsearch = "-DDB_DBM_HSEARCH "
when "gdbm"
- $dbm_conf_have_gdbm = true
+ have_gdbm = true
when "gdbm_compat"
- $dbm_conf_have_gdbm = true
+ have_gdbm = true
have_library("gdbm") or return false
end
-
- if have_library(db, db_prefix("dbm_open")) || have_func(db_prefix("dbm_open"))
- for hdr in $dbm_conf_headers.fetch(db, ["ndbm.h"])
- if have_header(hdr.dup) and have_type("DBM", hdr.dup, hsearch)
- $defs << hsearch << '-DDBM_HDR="<'+hdr+'>"'
- return true
- end
- end
- end
- return false
-end
-
-def db_prefix(func)
- $dbm_conf_db_prefix+func
-end
-
-if dblib
- dbm_hdr = db_check(dblib)
-else
- dbm_hdr = %w(db db2 db1 dbm gdbm gdbm_compat qdbm).any? do |dblib|
- db_check(dblib)
+ db_prefix ||= ""
+
+ if (have_library(db, db_prefix+"dbm_open") || have_func(db_prefix+"dbm_open")) and
+ hdr = self.fetch(db, ["ndbm.h"]).find {|hdr| have_type("DBM", hdr, hsearch)}
+ have_func(db_prefix+"dbm_clearerr") unless have_gdbm
+ $defs << hsearch if hsearch
+ $defs << '-DDBM_HDR="<'+hdr+'>"'
+ true
+ else
+ false
end
end
-have_header("cdefs.h")
-have_header("sys/cdefs.h")
-if dbm_hdr and have_func(db_prefix("dbm_open"))
- have_func(db_prefix("dbm_clearerr")) unless $dbm_conf_have_gdbm
+if dblib.any? {|db| headers.db_check(db)}
+ have_header("cdefs.h")
+ have_header("sys/cdefs.h")
create_makefile("dbm")
end
diff --git a/ext/enumerator/.cvsignore b/ext/digest/bubblebabble/.cvsignore
index fc802ff1c2..4088712231 100644
--- a/ext/enumerator/.cvsignore
+++ b/ext/digest/bubblebabble/.cvsignore
@@ -1,2 +1,3 @@
Makefile
mkmf.log
+*.def
diff --git a/ext/digest/bubblebabble/bubblebabble.c b/ext/digest/bubblebabble/bubblebabble.c
new file mode 100644
index 0000000000..3a03ceced0
--- /dev/null
+++ b/ext/digest/bubblebabble/bubblebabble.c
@@ -0,0 +1,142 @@
+/************************************************
+
+ bubblebabble.c - BubbleBabble encoding support
+
+ $Author$
+ created at: Fri Oct 13 18:31:42 JST 2006
+
+ Copyright (C) 2006 Akinori MUSHA
+
+ $Id$
+
+************************************************/
+
+#include "ruby.h"
+#include "digest.h"
+
+static ID id_digest;
+
+static VALUE
+bubblebabble_str_new(VALUE str_digest)
+{
+ char *digest;
+ size_t digest_len;
+ VALUE str;
+ char *p;
+ int i, j, seed = 1;
+ static const char vowels[] = {
+ 'a', 'e', 'i', 'o', 'u', 'y'
+ };
+ static const char consonants[] = {
+ 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', 'n',
+ 'p', 'r', 's', 't', 'v', 'z', 'x'
+ };
+
+ StringValue(str_digest);
+ digest = RSTRING_PTR(str_digest);
+ digest_len = RSTRING_LEN(str_digest);
+
+ if ((LONG_MAX - 2) / 3 < (digest_len | 1)) {
+ rb_raise(rb_eRuntimeError, "digest string too long");
+ }
+
+ str = rb_str_new(0, (digest_len | 1) * 3 + 2);
+ p = RSTRING_PTR(str);
+
+ i = j = 0;
+ p[j++] = 'x';
+
+ for (;;) {
+ unsigned char byte1, byte2;
+
+ if (i >= digest_len) {
+ p[j++] = vowels[seed % 6];
+ p[j++] = consonants[16];
+ p[j++] = vowels[seed / 6];
+ break;
+ }
+
+ byte1 = digest[i++];
+ p[j++] = vowels[(((byte1 >> 6) & 3) + seed) % 6];
+ p[j++] = consonants[(byte1 >> 2) & 15];
+ p[j++] = vowels[((byte1 & 3) + (seed / 6)) % 6];
+
+ if (i >= digest_len) {
+ break;
+ }
+
+ byte2 = digest[i++];
+ p[j++] = consonants[(byte2 >> 4) & 15];
+ p[j++] = '-';
+ p[j++] = consonants[byte2 & 15];
+
+ seed = (seed * 5 + byte1 * 7 + byte2) % 36;
+ }
+
+ p[j] = 'x';
+
+ return str;
+}
+
+/*
+ * call-seq:
+ * Digest.bubblebabble(string) -> bubblebabble_string
+ *
+ * Returns a BubbleBabble encoded version of a given _string_.
+ */
+static VALUE
+rb_digest_s_bubblebabble(VALUE klass, VALUE str)
+{
+ return bubblebabble_str_new(str);
+}
+
+/*
+ * call-seq:
+ * Digest::Class.bubblebabble(string, ...) -> hash_string
+ *
+ * Returns the BubbleBabble encoded hash value of a given _string_.
+ */
+static VALUE
+rb_digest_class_s_bubblebabble(int argc, VALUE *argv, VALUE klass)
+{
+ return bubblebabble_str_new(rb_funcall2(klass, id_digest, argc, argv));
+}
+
+/*
+ * call-seq:
+ * digest_obj.bubblebabble -> hash_string
+ *
+ * Returns the resulting hash value in a Bubblebabble encoded form.
+ */
+static VALUE
+rb_digest_instance_bubblebabble(VALUE self)
+{
+ return bubblebabble_str_new(rb_funcall(self, id_digest, 0));
+}
+
+/*
+ * This module adds some methods to Digest classes to perform
+ * BubbleBabble encoding.
+ */
+void
+Init_bubblebabble(void)
+{
+ VALUE mDigest, mDigest_Instance, cDigest_Class;
+
+ rb_require("digest");
+
+ mDigest = rb_path2class("Digest");
+ mDigest_Instance = rb_path2class("Digest::Instance");
+ cDigest_Class = rb_path2class("Digest::Class");
+
+ /* Digest::bubblebabble() */
+ rb_define_module_function(mDigest, "bubblebabble", rb_digest_s_bubblebabble, 1);
+
+ /* Digest::Class::bubblebabble() */
+ rb_define_singleton_method(cDigest_Class, "bubblebabble", rb_digest_class_s_bubblebabble, -1);
+
+ /* Digest::Instance#bubblebabble() */
+ rb_define_method(mDigest_Instance, "bubblebabble", rb_digest_instance_bubblebabble, 0);
+
+ id_digest = rb_intern("digest");
+}
diff --git a/ext/digest/bubblebabble/depend b/ext/digest/bubblebabble/depend
new file mode 100644
index 0000000000..b20148ded4
--- /dev/null
+++ b/ext/digest/bubblebabble/depend
@@ -0,0 +1,3 @@
+bubblebabble.o: bubblebabble.c $(srcdir)/../digest.h $(hdrdir)/ruby.h \
+ $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h \
+ $(srcdir)/../defs.h
diff --git a/ext/digest/bubblebabble/extconf.rb b/ext/digest/bubblebabble/extconf.rb
new file mode 100644
index 0000000000..53cb83934a
--- /dev/null
+++ b/ext/digest/bubblebabble/extconf.rb
@@ -0,0 +1,6 @@
+require 'mkmf'
+
+$defs << "-DHAVE_CONFIG_H"
+$INCFLAGS << " -I$(srcdir)/.."
+
+create_makefile('digest/bubblebabble')
diff --git a/ext/digest/defs.h b/ext/digest/defs.h
index d51c627cf9..b9a3470e65 100644
--- a/ext/digest/defs.h
+++ b/ext/digest/defs.h
@@ -1,5 +1,5 @@
/* -*- C -*-
- * $Id: defs.h,v 1.7 2003/06/01 15:39:52 eban Exp $
+ * $Id$
*/
#ifndef DEFS_H
@@ -23,12 +23,8 @@
typedef unsigned int uint32_t;
# if SIZEOF_LONG == 8
typedef unsigned long uint64_t;
-# elif defined(__GNUC__)
- typedef unsigned long long uint64_t;
-# elif defined(_MSC_VER)
- typedef unsigned _int64 uint64_t;
-# elif defined(__BORLANDC__)
- typedef unsigned __int64 uint64_t;
+# elif SIZEOF_LONG_LONG == 8
+ typedef unsigned LONG_LONG uint64_t;
# else
# define NO_UINT64_T
# endif
diff --git a/ext/digest/digest.c b/ext/digest/digest.c
index 957fe4f6ea..0b910e8c47 100644
--- a/ext/digest/digest.c
+++ b/ext/digest/digest.c
@@ -2,157 +2,491 @@
digest.c -
- $Author: matz $
+ $Author$
created at: Fri May 25 08:57:27 JST 2001
Copyright (C) 1995-2001 Yukihiro Matsumoto
- Copyright (C) 2001 Akinori MUSHA
+ Copyright (C) 2001-2006 Akinori MUSHA
$RoughId: digest.c,v 1.16 2001/07/13 15:38:27 knu Exp $
- $Id: digest.c,v 1.14.2.2 2005/12/12 00:36:51 matz Exp $
+ $Id$
************************************************/
+#include "digest.h"
+
+static VALUE rb_mDigest;
+static VALUE rb_mDigest_Instance;
+static VALUE rb_cDigest_Class;
+static VALUE rb_cDigest_Base;
+
+static ID id_reset, id_update, id_finish, id_digest, id_hexdigest, id_digest_length;
+static ID id_metadata;
+
+RUBY_EXTERN void Init_digest_base(void);
+
/*
- * This module provides an interface to the following hash algorithms:
+ * Document-module: Digest
*
- * - the MD5 Message-Digest Algorithm by the RSA Data Security,
- * Inc., described in RFC 1321
- *
- * - the SHA-1 Secure Hash Algorithm by NIST (the US' National
- * Institute of Standards and Technology), described in FIPS PUB
- * 180-1.
+ * This module provides a framework for message digest libraries.
+ */
+
+static VALUE
+hexencode_str_new(VALUE str_digest)
+{
+ char *digest;
+ size_t digest_len;
+ int i;
+ VALUE str;
+ char *p;
+ static const char hex[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+
+ StringValue(str_digest);
+ digest = RSTRING_PTR(str_digest);
+ digest_len = RSTRING_LEN(str_digest);
+
+ if (LONG_MAX / 2 < digest_len) {
+ rb_raise(rb_eRuntimeError, "digest string too long");
+ }
+
+ str = rb_str_new(0, digest_len * 2);
+
+ for (i = 0, p = RSTRING_PTR(str); i < digest_len; i++) {
+ unsigned char byte = digest[i];
+
+ p[i + i] = hex[byte >> 4];
+ p[i + i + 1] = hex[byte & 0x0f];
+ }
+
+ return str;
+}
+
+/*
+ * call-seq:
+ * Digest.hexencode(string) -> hexencoded_string
*
- * - the SHA-256/384/512 Secure Hash Algorithm by NIST (the US'
- * National Institute of Standards and Technology), described in
- * FIPS PUB 180-2.
+ * Generates a hex-encoded version of a given _string_.
+ */
+static VALUE
+rb_digest_s_hexencode(VALUE klass, VALUE str)
+{
+ return hexencode_str_new(str);
+}
+
+/*
+ * Document-module: Digest::Instance
*
- * - the RIPEMD-160 cryptographic hash function, designed by Hans
- * Dobbertin, Antoon Bosselaers, and Bart Preneel.
+ * This module provides instance methods for a digest implementation
+ * object to calculate message digest values.
*/
-#include "digest.h"
+/*
+ * call-seq:
+ * digest_obj.update(string) -> digest_obj
+ * digest_obj << string -> digest_obj
+ *
+ * Updates the digest using a given _string_ and returns self.
+ *
+ * The update() method and the left-shift operator are overridden by
+ * each implementation subclass. (One should be an alias for the
+ * other)
+ */
+static VALUE
+rb_digest_instance_update(VALUE self, VALUE str)
+{
+ rb_raise(rb_eRuntimeError, "%s does not implement update()", RSTRING_PTR(rb_inspect(self)));
+}
-static VALUE mDigest, cDigest_Base;
-static ID id_metadata;
+/*
+ * call-seq:
+ * digest_obj.instance_eval { finish } -> digest_obj
+ *
+ * Finishes the digest and returns the resulting hash value.
+ *
+ * This method is overridden by each implementation subclass and often
+ * made private, because some of those subclasses may leave internal
+ * data uninitialized. Do not call this method from outside. Use
+ * #digest!() instead, which ensures that internal data be reset for
+ * security reasons.
+ */
+static VALUE
+rb_digest_instance_finish(VALUE self)
+{
+ rb_raise(rb_eRuntimeError, "%s does not implement finish()", RSTRING_PTR(rb_inspect(self)));
+}
/*
- * Digest::Base
+ * call-seq:
+ * digest_obj.reset -> digest_obj
+ *
+ * Resets the digest to the initial state and returns self.
+ *
+ * This method is overridden by each implementation subclass.
*/
+static VALUE
+rb_digest_instance_reset(VALUE self)
+{
+ rb_raise(rb_eRuntimeError, "%s does not implement reset()", RSTRING_PTR(rb_inspect(self)));
+}
-static algo_t *
-get_digest_base_metadata(klass)
- VALUE klass;
+/*
+ * call-seq:
+ * digest_obj.new -> another_digest_obj
+ *
+ * Returns a new, initialized copy of the digest object. Equivalent
+ * to digest_obj.clone().reset().
+ */
+static VALUE
+rb_digest_instance_new(VALUE self)
{
- VALUE obj;
- algo_t *algo;
+ VALUE clone = rb_obj_clone(self);
+ rb_funcall(clone, id_reset, 0);
+ return clone;
+}
- if (rb_cvar_defined(klass, id_metadata) == Qfalse) {
- rb_notimplement();
+/*
+ * call-seq:
+ * digest_obj.digest -> string
+ * digest_obj.digest(string) -> string
+ *
+ * If none is given, returns the resulting hash value of the digest,
+ * keeping the digest's state.
+ *
+ * If a _string_ is given, returns the hash value for the given
+ * _string_, resetting the digest to the initial state before and
+ * after the process.
+ */
+static VALUE
+rb_digest_instance_digest(int argc, VALUE *argv, VALUE self)
+{
+ VALUE str, value;
+
+ if (rb_scan_args(argc, argv, "01", &str) > 0) {
+ rb_funcall(self, id_reset, 0);
+ rb_funcall(self, id_update, 1, str);
+ value = rb_funcall(self, id_finish, 0);
+ rb_funcall(self, id_reset, 0);
+ } else {
+ VALUE clone = rb_obj_clone(self);
+
+ value = rb_funcall(clone, id_finish, 0);
+ rb_funcall(clone, id_reset, 0);
}
- obj = rb_cvar_get(klass, id_metadata);
+ return value;
+}
- Data_Get_Struct(obj, algo_t, algo);
+/*
+ * call-seq:
+ * digest_obj.digest! -> string
+ *
+ * Returns the resulting hash value and resets the digest to the
+ * initial state.
+ */
+static VALUE
+rb_digest_instance_digest_bang(VALUE self)
+{
+ VALUE value = rb_funcall(self, id_finish, 0);
+ rb_funcall(self, id_reset, 0);
- return algo;
+ return value;
}
-static VALUE rb_digest_base_alloc _((VALUE));
+/*
+ * call-seq:
+ * digest_obj.hexdigest -> string
+ * digest_obj.hexdigest(string) -> string
+ *
+ * If none is given, returns the resulting hash value of the digest in
+ * a hex-encoded form, keeping the digest's state.
+ *
+ * If a _string_ is given, returns the hash value for the given
+ * _string_ in a hex-encoded form, resetting the digest to the initial
+ * state before and after the process.
+ */
static VALUE
-rb_digest_base_alloc(klass)
- VALUE klass;
+rb_digest_instance_hexdigest(int argc, VALUE *argv, VALUE self)
{
- algo_t *algo;
- VALUE obj;
- void *pctx;
-
- if (klass == cDigest_Base) {
- rb_raise(rb_eNotImpError, "Digest::Base is an abstract class");
+ VALUE str, value;
+
+ if (rb_scan_args(argc, argv, "01", &str) > 0) {
+ rb_funcall(self, id_reset, 0);
+ rb_funcall(self, id_update, 1, str);
+ value = rb_funcall(self, id_finish, 0);
+ rb_funcall(self, id_reset, 0);
+ } else {
+ VALUE clone = rb_obj_clone(self);
+
+ value = rb_funcall(clone, id_finish, 0);
+ rb_funcall(clone, id_reset, 0);
}
- algo = get_digest_base_metadata(klass);
+ return hexencode_str_new(value);
+}
- /* XXX: An uninitialized buffer leads ALGO_Equal() to fail */
- pctx = xcalloc(algo->ctx_size, 1);
- algo->init_func(pctx);
+/*
+ * call-seq:
+ * digest_obj.hexdigest! -> string
+ *
+ * Returns the resulting hash value and resets the digest to the
+ * initial state.
+ */
+static VALUE
+rb_digest_instance_hexdigest_bang(VALUE self)
+{
+ VALUE value = rb_funcall(self, id_finish, 0);
+ rb_funcall(self, id_reset, 0);
- obj = Data_Wrap_Struct(klass, 0, free, pctx);
+ return hexencode_str_new(value);
+}
- return obj;
+/*
+ * call-seq:
+ * digest_obj.to_s -> string
+ *
+ * Returns digest_obj.hexdigest().
+ */
+static VALUE
+rb_digest_instance_to_s(VALUE self)
+{
+ return rb_funcall(self, id_hexdigest, 0);
}
+/*
+ * call-seq:
+ * digest_obj.inspect -> string
+ *
+ * Creates a printable version of the digest object.
+ */
static VALUE
-rb_digest_base_s_digest(klass, str)
- VALUE klass;
+rb_digest_instance_inspect(VALUE self)
+{
VALUE str;
+ size_t digest_len = 32; /* about this size at least */
+ char *cname;
+
+ cname = rb_obj_classname(self);
+
+ /* #<Digest::ClassName: xxxxx...xxxx> */
+ str = rb_str_buf_new(2 + strlen(cname) + 2 + digest_len * 2 + 1);
+ rb_str_buf_cat2(str, "#<");
+ rb_str_buf_cat2(str, cname);
+ rb_str_buf_cat2(str, ": ");
+ rb_str_buf_append(str, rb_digest_instance_hexdigest(0, 0, self));
+ rb_str_buf_cat2(str, ">");
+ return str;
+}
+
+/*
+ * call-seq:
+ * digest_obj == another_digest_obj -> boolean
+ * digest_obj == string -> boolean
+ *
+ * If a string is given, checks whether it is equal to the hex-encoded
+ * hash value of the digest object. If another digest instance is
+ * given, checks whether they have the same hash value. Otherwise
+ * returns false.
+ */
+static VALUE
+rb_digest_instance_equal(VALUE self, VALUE other)
{
- algo_t *algo;
- void *pctx;
- size_t len;
- unsigned char *digest;
- volatile VALUE obj = rb_digest_base_alloc(klass);
+ VALUE str1, str2;
- algo = get_digest_base_metadata(klass);
- Data_Get_Struct(obj, void, pctx);
+ if (rb_obj_is_kind_of(other, rb_mDigest_Instance) == Qtrue) {
+ str1 = rb_digest_instance_digest(0, 0, self);
+ str2 = rb_digest_instance_digest(0, 0, other);
+ } else {
+ str1 = rb_digest_instance_to_s(self);
+ str2 = other;
+ }
- StringValue(str);
- algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len);
+ /* never blindly assume that subclass methods return strings */
+ StringValue(str1);
+ StringValue(str2);
- len = algo->digest_len;
+ if (RSTRING_LEN(str1) == RSTRING_LEN(str2) &&
+ rb_str_cmp(str1, str2) == 0) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
- digest = xmalloc(len);
- algo->final_func(digest, pctx);
+/*
+ * call-seq:
+ * digest_obj.digest_length -> integer
+ *
+ * Returns the length of the hash value of the digest.
+ *
+ * This method should be overridden by each implementation subclass.
+ * If not, digest_obj.digest().length() is returned.
+ */
+static VALUE
+rb_digest_instance_digest_length(VALUE self)
+{
+ /* subclasses really should redefine this method */
+ VALUE digest = rb_digest_instance_digest(0, 0, self);
- obj = rb_str_new(digest, len);
+ /* never blindly assume that #digest() returns a string */
+ StringValue(digest);
+ return INT2NUM(RSTRING_LEN(digest));
+}
- free(digest);
+/*
+ * call-seq:
+ * digest_obj.length -> integer
+ * digest_obj.size -> integer
+ *
+ * Returns digest_obj.digest_length().
+ */
+static VALUE
+rb_digest_instance_length(VALUE self)
+{
+ return rb_funcall(self, id_digest_length, 0);
+}
- return obj;
+/*
+ * call-seq:
+ * digest_obj.block_length -> integer
+ *
+ * Returns the block length of the digest.
+ *
+ * This method is overridden by each implementation subclass.
+ */
+static VALUE
+rb_digest_instance_block_length(VALUE self)
+{
+ rb_raise(rb_eRuntimeError, "%s does not implement block_length()", RSTRING_PTR(rb_inspect(self)));
}
+/*
+ * Document-class: Digest::Class
+ *
+ * This module stands as a base class for digest implementation
+ * classes.
+ */
+
+/*
+ * call-seq:
+ * Digest::Class.digest(string, *parameters) -> hash_string
+ *
+ * Returns the hash value of a given _string_. This is equivalent to
+ * Digest::Class.new(*parameters).digest(string), where extra
+ * _parameters_, if any, are passed through to the constructor and the
+ * _string_ is passed to #digest().
+ */
static VALUE
-rb_digest_base_s_hexdigest(klass, str)
- VALUE klass;
- VALUE str;
+rb_digest_class_s_digest(int argc, VALUE *argv, VALUE klass)
{
- algo_t *algo;
- void *pctx;
- size_t len;
- unsigned char *hexdigest;
- volatile VALUE obj = rb_digest_base_alloc(klass);
+ VALUE str;
+ volatile VALUE obj;
- algo = get_digest_base_metadata(klass);
- Data_Get_Struct(obj, void, pctx);
+ if (argc < 1) {
+ rb_raise(rb_eArgError, "no data given");
+ }
+
+ str = *argv++;
+ argc--;
StringValue(str);
- algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len);
- len = algo->digest_len * 2;
+ obj = rb_obj_alloc(klass);
+ rb_obj_call_init(obj, argc, argv);
+
+ return rb_funcall(obj, id_digest, 1, str);
+}
+
+/*
+ * call-seq:
+ * Digest::Class.hexdigest(string[, ...]) -> hash_string
+ *
+ * Returns the hex-encoded hash value of a given _string_. This is
+ * almost equivalent to
+ * Digest.hexencode(Digest::Class.new(*parameters).digest(string)).
+ */
+static VALUE
+rb_digest_class_s_hexdigest(int argc, VALUE *argv, VALUE klass)
+{
+ return hexencode_str_new(rb_funcall2(klass, id_digest, argc, argv));
+}
+
+/*
+ * Document-class: Digest::Base
+ *
+ * This abstract class provides a common interface to message digest
+ * implementation classes written in C.
+ */
+
+static rb_digest_metadata_t *
+get_digest_base_metadata(VALUE klass)
+{
+ VALUE p;
+ VALUE obj;
+ rb_digest_metadata_t *algo;
+
+ for (p = klass; p; p = RCLASS(p)->super) {
+ if (rb_ivar_defined(p, id_metadata)) {
+ obj = rb_ivar_get(p, id_metadata);
+ break;
+ }
+ }
+
+ if (!p)
+ rb_raise(rb_eRuntimeError, "Digest::Base cannot be directly inherited in Ruby");
+
+ Data_Get_Struct(obj, rb_digest_metadata_t, algo);
+
+ switch (algo->api_version) {
+ case 2:
+ break;
+
+ /*
+ * put conversion here if possible when API is updated
+ */
+
+ default:
+ rb_raise(rb_eRuntimeError, "Incompatible digest API version");
+ }
+
+ return algo;
+}
+
+static VALUE
+rb_digest_base_alloc(VALUE klass)
+{
+ rb_digest_metadata_t *algo;
+ VALUE obj;
+ void *pctx;
- hexdigest = xmalloc(len + 1); /* +1 is for '\0' */
- algo->end_func(pctx, hexdigest);
+ if (klass == rb_cDigest_Base) {
+ rb_raise(rb_eNotImpError, "Digest::Base is an abstract class");
+ }
- obj = rb_str_new(hexdigest, len);
+ algo = get_digest_base_metadata(klass);
+
+ pctx = xmalloc(algo->ctx_size);
+ algo->init_func(pctx);
- free(hexdigest);
+ obj = Data_Wrap_Struct(klass, 0, free, pctx);
return obj;
}
+/* :nodoc: */
static VALUE
-rb_digest_base_copy(copy, obj)
- VALUE copy, obj;
+rb_digest_base_copy(VALUE copy, VALUE obj)
{
- algo_t *algo;
+ rb_digest_metadata_t *algo;
void *pctx1, *pctx2;
if (copy == obj) return copy;
+
rb_check_frozen(copy);
+
algo = get_digest_base_metadata(rb_obj_class(copy));
- if (algo != get_digest_base_metadata(rb_obj_class(obj))) {
- rb_raise(rb_eTypeError, "wrong argument class");
- }
+
Data_Get_Struct(obj, void, pctx1);
Data_Get_Struct(copy, void, pctx2);
memcpy(pctx2, pctx1, algo->ctx_size);
@@ -160,157 +494,149 @@ rb_digest_base_copy(copy, obj)
return copy;
}
+/* :nodoc: */
static VALUE
-rb_digest_base_update(self, str)
- VALUE self, str;
+rb_digest_base_reset(VALUE self)
{
- algo_t *algo;
+ rb_digest_metadata_t *algo;
void *pctx;
- StringValue(str);
algo = get_digest_base_metadata(rb_obj_class(self));
+
Data_Get_Struct(self, void, pctx);
- algo->update_func(pctx, RSTRING(str)->ptr, RSTRING(str)->len);
+ algo->init_func(pctx);
return self;
}
+/* :nodoc: */
static VALUE
-rb_digest_base_init(argc, argv, self)
- int argc;
- VALUE* argv;
- VALUE self;
+rb_digest_base_update(VALUE self, VALUE str)
{
- VALUE arg;
+ rb_digest_metadata_t *algo;
+ void *pctx;
+
+ algo = get_digest_base_metadata(rb_obj_class(self));
- rb_scan_args(argc, argv, "01", &arg);
+ Data_Get_Struct(self, void, pctx);
- if (!NIL_P(arg)) rb_digest_base_update(self, arg);
+ StringValue(str);
+ algo->update_func(pctx, (unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str));
return self;
}
+/* :nodoc: */
static VALUE
-rb_digest_base_digest(self)
- VALUE self;
+rb_digest_base_finish(VALUE self)
{
- algo_t *algo;
- void *pctx1, *pctx2;
- unsigned char *digest;
- size_t len;
+ rb_digest_metadata_t *algo;
+ void *pctx;
VALUE str;
algo = get_digest_base_metadata(rb_obj_class(self));
- Data_Get_Struct(self, void, pctx1);
-
- len = algo->ctx_size;
-
- pctx2 = xmalloc(len);
- memcpy(pctx2, pctx1, len);
-
- len = algo->digest_len;
- digest = xmalloc(len);
- algo->final_func(digest, pctx2);
+ Data_Get_Struct(self, void, pctx);
- str = rb_str_new(digest, len);
+ str = rb_str_new(0, algo->digest_len);
+ algo->finish_func(pctx, (unsigned char *)RSTRING_PTR(str));
- free(digest);
- free(pctx2);
+ /* avoid potential coredump caused by use of a finished context */
+ algo->init_func(pctx);
return str;
}
+/* :nodoc: */
static VALUE
-rb_digest_base_hexdigest(self)
- VALUE self;
+rb_digest_base_digest_length(VALUE self)
{
- algo_t *algo;
- void *pctx1, *pctx2;
- unsigned char *hexdigest;
- size_t len;
- VALUE str;
+ rb_digest_metadata_t *algo;
algo = get_digest_base_metadata(rb_obj_class(self));
- Data_Get_Struct(self, void, pctx1);
-
- len = algo->ctx_size;
-
- pctx2 = xmalloc(len);
- memcpy(pctx2, pctx1, len);
-
- len = algo->digest_len * 2;
- hexdigest = xmalloc(len + 1); /* +1 is for '\0' */
- algo->end_func(pctx2, hexdigest);
-
- str = rb_str_new(hexdigest, len);
-
- free(hexdigest);
- free(pctx2);
-
- return str;
+ return INT2NUM(algo->digest_len);
}
+/* :nodoc: */
static VALUE
-rb_digest_base_equal(self, other)
- VALUE self, other;
+rb_digest_base_block_length(VALUE self)
{
- algo_t *algo;
- VALUE klass;
- VALUE str1, str2;
-
- klass = rb_obj_class(self);
- algo = get_digest_base_metadata(klass);
+ rb_digest_metadata_t *algo;
- if (rb_obj_class(other) == klass) {
- void *pctx1, *pctx2;
-
- Data_Get_Struct(self, void, pctx1);
- Data_Get_Struct(other, void, pctx2);
-
- return algo->equal_func(pctx1, pctx2) ? Qtrue : Qfalse;
- }
-
- StringValue(other);
- str2 = other;
-
- if (RSTRING(str2)->len == algo->digest_len)
- str1 = rb_digest_base_digest(self);
- else
- str1 = rb_digest_base_hexdigest(self);
-
- if (RSTRING(str1)->len == RSTRING(str2)->len
- && rb_str_cmp(str1, str2) == 0)
- return Qtrue;
+ algo = get_digest_base_metadata(rb_obj_class(self));
- return Qfalse;
+ return INT2NUM(algo->block_len);
}
-/*
- * Init
- */
-
void
-Init_digest()
+Init_digest(void)
{
- mDigest = rb_define_module("Digest");
+ id_reset = rb_intern("reset");
+ id_update = rb_intern("update");
+ id_finish = rb_intern("finish");
+ id_digest = rb_intern("digest");
+ id_hexdigest = rb_intern("hexdigest");
+ id_digest_length = rb_intern("digest_length");
+
+ /*
+ * module Digest
+ */
+ rb_mDigest = rb_define_module("Digest");
+
+ /* module functions */
+ rb_define_module_function(rb_mDigest, "hexencode", rb_digest_s_hexencode, 1);
+
+ /*
+ * module Digest::Instance
+ */
+ rb_mDigest_Instance = rb_define_module_under(rb_mDigest, "Instance");
+
+ /* instance methods that should be overridden */
+ rb_define_method(rb_mDigest_Instance, "update", rb_digest_instance_update, 1);
+ rb_define_method(rb_mDigest_Instance, "<<", rb_digest_instance_update, 1);
+ rb_define_private_method(rb_mDigest_Instance, "finish", rb_digest_instance_finish, 0);
+ rb_define_method(rb_mDigest_Instance, "reset", rb_digest_instance_reset, 0);
+ rb_define_method(rb_mDigest_Instance, "digest_length", rb_digest_instance_digest_length, 0);
+ rb_define_method(rb_mDigest_Instance, "block_length", rb_digest_instance_block_length, 0);
+
+ /* instance methods that may be overridden */
+ rb_define_method(rb_mDigest_Instance, "==", rb_digest_instance_equal, 1);
+ rb_define_method(rb_mDigest_Instance, "inspect", rb_digest_instance_inspect, 0);
+
+ /* instance methods that need not usually be overridden */
+ rb_define_method(rb_mDigest_Instance, "new", rb_digest_instance_new, 0);
+ rb_define_method(rb_mDigest_Instance, "digest", rb_digest_instance_digest, -1);
+ rb_define_method(rb_mDigest_Instance, "digest!", rb_digest_instance_digest_bang, 0);
+ rb_define_method(rb_mDigest_Instance, "hexdigest", rb_digest_instance_hexdigest, -1);
+ rb_define_method(rb_mDigest_Instance, "hexdigest!", rb_digest_instance_hexdigest_bang, 0);
+ rb_define_method(rb_mDigest_Instance, "to_s", rb_digest_instance_to_s, 0);
+ rb_define_method(rb_mDigest_Instance, "length", rb_digest_instance_length, 0);
+ rb_define_method(rb_mDigest_Instance, "size", rb_digest_instance_length, 0);
+
+ /*
+ * class Digest::Class
+ */
+ rb_cDigest_Class = rb_define_class_under(rb_mDigest, "Class", rb_cObject);
+ rb_include_module(rb_cDigest_Class, rb_mDigest_Instance);
+
+ /* class methods */
+ rb_define_singleton_method(rb_cDigest_Class, "digest", rb_digest_class_s_digest, -1);
+ rb_define_singleton_method(rb_cDigest_Class, "hexdigest", rb_digest_class_s_hexdigest, -1);
- cDigest_Base = rb_define_class_under(mDigest, "Base", rb_cObject);
+ id_metadata = rb_intern("metadata");
- rb_define_alloc_func(cDigest_Base, rb_digest_base_alloc);
- rb_define_singleton_method(cDigest_Base, "digest", rb_digest_base_s_digest, 1);
- rb_define_singleton_method(cDigest_Base, "hexdigest", rb_digest_base_s_hexdigest, 1);
+ /* class Digest::Base < Digest::Class */
+ rb_cDigest_Base = rb_define_class_under(rb_mDigest, "Base", rb_cDigest_Class);
- rb_define_method(cDigest_Base, "initialize", rb_digest_base_init, -1);
- rb_define_method(cDigest_Base, "initialize_copy", rb_digest_base_copy, 1);
- rb_define_method(cDigest_Base, "update", rb_digest_base_update, 1);
- rb_define_method(cDigest_Base, "<<", rb_digest_base_update, 1);
- rb_define_method(cDigest_Base, "digest", rb_digest_base_digest, 0);
- rb_define_method(cDigest_Base, "hexdigest", rb_digest_base_hexdigest, 0);
- rb_define_method(cDigest_Base, "to_s", rb_digest_base_hexdigest, 0);
- rb_define_method(cDigest_Base, "==", rb_digest_base_equal, 1);
+ rb_define_alloc_func(rb_cDigest_Base, rb_digest_base_alloc);
- id_metadata = rb_intern("metadata");
+ rb_define_method(rb_cDigest_Base, "initialize_copy", rb_digest_base_copy, 1);
+ rb_define_method(rb_cDigest_Base, "reset", rb_digest_base_reset, 0);
+ rb_define_method(rb_cDigest_Base, "update", rb_digest_base_update, 1);
+ rb_define_method(rb_cDigest_Base, "<<", rb_digest_base_update, 1);
+ rb_define_private_method(rb_cDigest_Base, "finish", rb_digest_base_finish, 0);
+ rb_define_method(rb_cDigest_Base, "digest_length", rb_digest_base_digest_length, 0);
+ rb_define_method(rb_cDigest_Base, "block_length", rb_digest_base_block_length, 0);
}
diff --git a/ext/digest/digest.h b/ext/digest/digest.h
index 578be0a3c4..6e4906c859 100644
--- a/ext/digest/digest.h
+++ b/ext/digest/digest.h
@@ -1,32 +1,32 @@
/************************************************
- digest.c -
+ digest.h - header file for ruby digest modules
- $Author: knu $
+ $Author$
created at: Fri May 25 08:54:56 JST 2001
- Copyright (C) 2001 Akinori MUSHA
+ Copyright (C) 2001-2006 Akinori MUSHA
$RoughId: digest.h,v 1.3 2001/07/13 15:38:27 knu Exp $
- $Id: digest.h,v 1.1 2001/07/13 20:06:13 knu Exp $
+ $Id$
************************************************/
#include "ruby.h"
-typedef void (*hash_init_func_t) _((void *));
-typedef void (*hash_update_func_t) _((void *, unsigned char *, size_t));
-typedef void (*hash_end_func_t) _((void *, unsigned char *));
-typedef void (*hash_final_func_t) _((unsigned char *, void *));
-typedef int (*hash_equal_func_t) _((void *, void *));
+#define RUBY_DIGEST_API_VERSION 2
+
+typedef void (*rb_digest_hash_init_func_t)(void *);
+typedef void (*rb_digest_hash_update_func_t)(void *, unsigned char *, size_t);
+typedef void (*rb_digest_hash_finish_func_t)(void *, unsigned char *);
typedef struct {
+ int api_version;
size_t digest_len;
+ size_t block_len;
size_t ctx_size;
- hash_init_func_t init_func;
- hash_update_func_t update_func;
- hash_end_func_t end_func;
- hash_final_func_t final_func;
- hash_equal_func_t equal_func;
-} algo_t;
+ rb_digest_hash_init_func_t init_func;
+ rb_digest_hash_update_func_t update_func;
+ rb_digest_hash_finish_func_t finish_func;
+} rb_digest_metadata_t;
diff --git a/ext/digest/digest.txt b/ext/digest/digest.txt
deleted file mode 100644
index 4969a9da90..0000000000
--- a/ext/digest/digest.txt
+++ /dev/null
@@ -1,113 +0,0 @@
-.\" digest.txt - -*- Indented-Text -*- created at: Fri May 25 08:13:50 JST 2001
-$RoughId: digest.txt,v 1.9 2001/07/13 19:46:51 knu Exp $
-$Id: digest.txt,v 1.1 2001/07/13 20:06:13 knu Exp $
-
-** MD5(Class)
-
-A class to implement the MD5 Message-Digest Algorithm by RSA Data
-Security, Inc., described in RFC1321.
-
-Superclass: Digest::Base
-
-require 'digest/md5'
-
-** SHA1(Class)
-
-A class to implement the SHA-1 Secure Hash Algorithm by NIST (the US'
-National Institute of Standards and Technology), described in FIPS PUB
-180-1.
-
-Superclass: Digest::Base
-
-require 'digest/sha1'
-
-** SHA256(Class)
-** SHA384(Class)
-** SHA512(Class)
-
-Classes to implement the SHA-256/384/512 Secure Hash Algorithm(s) by
-NIST (the US' National Institute of Standards and Technology),
-described in FIPS PUB 180-2.
-
-Superclass: Digest::Base
-
-require 'digest/sha2'
-
-** RMD160(Class)
-
-A class to implement the RIPEMD-160 cryptographic hash function,
-designed by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel.
-
-Superclass: Digest::Base
-
-require 'digest/rmd160'
-
-
-Those above classes provide a common interface as shown below.
-
-
-Class Methods:
-
- new([str])
-
- Creates a new digest object. If a string argument is given,
- it is added to the object. (see update.)
-
- digest(str)
-
- Immediately calculates and return the hash of the given
- strings as a string. Equivalent to new(str).digest.
-
- hexdigest(str)
-
- Immediately calculates and return the hash of the given
- strings as a string of hexadecimal digits. Equivalent to
- new(str).hexdigest.
-
-Methods:
-
- clone
-
- Creates a copy of the digest object.
-
- digest
-
- Returns the hash of the added strings as a string of 16 bytes
- for MD5, 20 bytes for SHA1 and RMD160, 32 bytes for SHA256, 48
- bytes for SHA384, and 64 bytes for SHA512.
-
- hexdigest
- to_s
-
- Returns the hash of the added strings as a string of 32
- hexadecimal digits for MD5, 40 hexadecimal digits for SHA1 and
- RMD160, 64 hexadecimal digits for SHA256, 96 hexadecimal
- digits for SHA384, and 128 hexadecimal digits for SHA512.
- This method is equal to:
-
- def hexdigest
- digest.unpack("H*")[0]
- end
-
- update(str)
- << str
-
- Appends the string str to the digest object. Repeated calls
- are equivalent to a single call with the concatenation of all
- the arguments, i.e. m.update(a); m.update(b) is equivalent to
- m.update(a + b) and m << a << b is equivalent to m << a + b.
-
- == md
-
- Checks if the object is equal to the given digest object.
-
- == str
-
- Regards the value as either a digest value or a hexdigest
- value (depending on the length) and checks if the object is
- equal to the given string.
-
--------------------------------------------------------
-Local variables:
-fill-column: 70
-end:
diff --git a/ext/digest/digest.txt.ja b/ext/digest/digest.txt.ja
deleted file mode 100644
index 7078c83573..0000000000
--- a/ext/digest/digest.txt.ja
+++ /dev/null
@@ -1,111 +0,0 @@
-.\" digest.txt.ja - -*- Indented-Text -*- created at: Fri May 25 08:22:19 JST 2001
-$RoughId: digest.txt.jp,v 1.8 2001/07/13 15:38:27 knu Exp $
-$Id: digest.txt.ja,v 1.1 2001/07/19 05:42:07 knu Exp $
-
-** MD5(饹)
-
-RFC1321˵ҤƤRSA Data Security, Inc. MD5 Message-Digest
-Algorithm륯饹
-
-Superclass: Digest::Base
-
-require 'digest/md5'
-
-** SHA1(饹)
-
-FIPS PUB 180-1˵ҤƤNIST (the US' National Institute of
-Standards and Technology) SHA-1 Secure Hash Algorithm륯饹
-
-Superclass: Digest::Base
-
-require 'digest/sha1'
-
-** SHA256(饹)
-** SHA384(饹)
-** SHA512(饹)
-
-FIPS PUB 180-2˵ҤƤNIST (the US' National Institute of
-Standards and Technology) SHA-256/384/512 Secure Hash Algorithm
-륯饹
-
-Superclass: Digest::Base
-
-require 'digest/sha2'
-
-** RMD160(饹)
-
-Hans Dobbertin, Antoon Bosselaers, Bart Preneel ˤä߷פ줿
-RIPEMD-160 ϥåؿ륯饹
-
-Superclass: Digest::Base
-
-require 'digest/rmd160'
-
-
-Υ饹ϰʲΤ褦ʶ̤Υ󥿡ե󶡤롣
-
-
-Class Methods:
-
- new([str])
-
- ȥ֥Ȥ롥ʸͿ
- Ȥɲä(see update)
-
- digest(str)
-
- Ϳ줿ʸФϥåͤʸ֤
- new(str).digest
-
- hexdigest(str)
-
- Ϳ줿ʸФϥåͤASCIIɤȤä
- 16ʿ򼨤ʸ˥󥳡ɤ֤
- new(str).hexdigest
-
-Methods:
-
- clone
-
- ȥ֥Ȥʣ롣
-
- digest
-
- ޤǤɲäʸФϥåͤʸ֤MD5Ǥ
- 16ХĹSHA1RMD160Ǥ20ХĹSHA256Ǥ32ХĹ
- SHA384Ǥ48ХĹSHA512Ǥ64ХĹȤʤ롣
-
- hexdigest
- to_s
-
- ޤǤɲäʸФϥåͤASCIIɤȤä
- 16ʿ򼨤ʸ˥󥳡ɤ֤MD5Ǥ32ХĹ
- SHA1RMD160Ǥ40ХĹSHA256Ǥ64ХĹSHA384Ǥ
- 96ХĹSHA512Ǥ128ХĹȤʤ롣Rubyǽ񤯤ȰʲƱ
-
- def hexdigest
- digest.unpack("H*")[0]
- end
-
- update(str)
- << str
-
- ʸɲä롣ʣupdateƤ֤ȤʸϢ뤷
- updateƤ֤Ȥʤ m.update(a); m.update(b)
- m.update(a + b) ȡ m << a << b m << a + b Ȥ줾
- Ǥ롣
-
- == md
-
- Ϳ줿ȥ֥ȤӤ롣
-
- == str
-
- Ϳ줿ʸ digest ͡⤷ hexdigest ͤӤ롣
- ͤȸ뤫Ϳ줿ʸĹˤäƼưȽ
- 롣
-
--------------------------------------------------------
-Local variables:
-fill-column: 70
-end:
diff --git a/ext/digest/extconf.rb b/ext/digest/extconf.rb
index 3e35bf5064..cf9127ecc0 100644
--- a/ext/digest/extconf.rb
+++ b/ext/digest/extconf.rb
@@ -1,6 +1,10 @@
# $RoughId: extconf.rb,v 1.6 2001/07/13 15:38:27 knu Exp $
-# $Id: extconf.rb,v 1.1 2001/07/13 20:06:13 knu Exp $
+# $Id$
require "mkmf"
+$INSTALLFILES = {
+ "digest.h" => "$(RUBYARCHDIR)"
+}
+
create_makefile("digest")
diff --git a/ext/digest/lib/digest.rb b/ext/digest/lib/digest.rb
new file mode 100644
index 0000000000..0c4ee3c2cc
--- /dev/null
+++ b/ext/digest/lib/digest.rb
@@ -0,0 +1,50 @@
+require 'digest.so'
+
+module Digest
+ def self.const_missing(name)
+ case name
+ when :SHA256, :SHA384, :SHA512
+ lib = 'digest/sha2.so'
+ else
+ lib = File.join('digest', name.to_s.downcase)
+ end
+
+ begin
+ require lib
+ rescue LoadError => e
+ raise LoadError, "library not found for class Digest::#{name} -- #{lib}", caller(1)
+ end
+ unless Digest.const_defined?(name)
+ raise NameError, "uninitialized constant Digest::#{name}", caller(1)
+ end
+ Digest.const_get(name)
+ end
+
+ class ::Digest::Class
+ # creates a digest object and reads a given file, _name_.
+ #
+ # p Digest::SHA256.file("X11R6.8.2-src.tar.bz2").hexdigest
+ # # => "f02e3c85572dc9ad7cb77c2a638e3be24cc1b5bea9fdbb0b0299c9668475c534"
+ def self.file(name)
+ new.file(name)
+ end
+ end
+
+ module Instance
+ # updates the digest with the contents of a given file _name_ and
+ # returns self.
+ def file(name)
+ File.open(name, "rb") {|f|
+ buf = ""
+ while f.read(16384, buf)
+ update buf
+ end
+ }
+ self
+ end
+ end
+end
+
+def Digest(name)
+ Digest.const_get(name)
+end
diff --git a/ext/digest/lib/md5.rb b/ext/digest/lib/md5.rb
index 6867fdc71b..c399f2de1d 100644
--- a/ext/digest/lib/md5.rb
+++ b/ext/digest/lib/md5.rb
@@ -1,14 +1,23 @@
# just for compatibility; requiring "md5" is obsoleted
#
# $RoughId: md5.rb,v 1.4 2001/07/13 15:38:27 knu Exp $
-# $Id: md5.rb,v 1.1 2001/07/13 20:06:14 knu Exp $
+# $Id$
require 'digest/md5'
-MD5 = Digest::MD5
+class MD5 < Digest::MD5
+ class << self
+ alias orig_new new
+ def new(str = nil)
+ if str
+ orig_new.update(str)
+ else
+ orig_new
+ end
+ end
-class MD5
- def self.md5(*args)
- new(*args)
+ def md5(*args)
+ new(*args)
+ end
end
end
diff --git a/ext/digest/lib/sha1.rb b/ext/digest/lib/sha1.rb
index 12fb5cdfa4..4446e12e8d 100644
--- a/ext/digest/lib/sha1.rb
+++ b/ext/digest/lib/sha1.rb
@@ -1,14 +1,23 @@
# just for compatibility; requiring "sha1" is obsoleted
#
# $RoughId: sha1.rb,v 1.4 2001/07/13 15:38:27 knu Exp $
-# $Id: sha1.rb,v 1.1 2001/07/13 20:06:14 knu Exp $
+# $Id$
require 'digest/sha1'
-SHA1 = Digest::SHA1
+class SHA1 < Digest::SHA1
+ class << self
+ alias orig_new new
+ def new(str = nil)
+ if str
+ orig_new.update(str)
+ else
+ orig_new
+ end
+ end
-class SHA1
- def self.sha1(*args)
- new(*args)
+ def sha1(*args)
+ new(*args)
+ end
end
end
diff --git a/ext/digest/md5/extconf.rb b/ext/digest/md5/extconf.rb
index ea29c9c5f8..018f8ccb02 100644
--- a/ext/digest/md5/extconf.rb
+++ b/ext/digest/md5/extconf.rb
@@ -1,5 +1,5 @@
# $RoughId: extconf.rb,v 1.3 2001/08/14 19:54:51 knu Exp $
-# $Id: extconf.rb,v 1.4.2.2 2006/05/25 23:44:05 nobu Exp $
+# $Id$
require "mkmf"
@@ -24,4 +24,6 @@ have_header("inttypes.h")
have_header("unistd.h")
+$preload = %w[digest]
+
create_makefile("digest/md5")
diff --git a/ext/digest/md5/md5.c b/ext/digest/md5/md5.c
index ed32cf95c1..993bc47a06 100644
--- a/ext/digest/md5/md5.c
+++ b/ext/digest/md5/md5.c
@@ -41,9 +41,15 @@
1999-05-03 lpd Original version.
*/
+/*
+ This code was modified for use in Ruby.
+
+ - Akinori MUSHA <knu@idaemons.org>
+ */
+
/*$OrigId: md5c.c,v 1.2 2001/03/26 08:57:14 matz Exp $ */
/*$RoughId: md5.c,v 1.2 2001/07/13 19:48:41 knu Exp $ */
-/*$Id: md5.c,v 1.1 2001/07/13 20:06:14 knu Exp $ */
+/*$Id$ */
#include "md5.h"
@@ -391,7 +397,7 @@ MD5_Update(MD5_CTX *pms, const uint8_t *data, size_t nbytes)
}
void
-MD5_Final(uint8_t *digest, MD5_CTX *pms)
+MD5_Finish(MD5_CTX *pms, uint8_t *digest)
{
static const uint8_t pad[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -412,21 +418,3 @@ MD5_Final(uint8_t *digest, MD5_CTX *pms)
for (i = 0; i < 16; ++i)
digest[i] = (uint8_t)(pms->state[i >> 2] >> ((i & 3) << 3));
}
-
-void
-MD5_End(MD5_CTX *pctx, uint8_t *hexdigest)
-{
- unsigned char digest[16];
- size_t i;
-
- MD5_Final(digest, pctx);
-
- for (i = 0; i < 16; i++)
- sprintf(hexdigest + i * 2, "%02x", digest[i]);
-}
-
-int MD5_Equal(MD5_CTX* pctx1, MD5_CTX* pctx2) {
- return memcmp(pctx1->count, pctx2->count, sizeof(pctx1->count)) == 0
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0;
-}
diff --git a/ext/digest/md5/md5.h b/ext/digest/md5/md5.h
index 736e034512..f4580ef5e7 100644
--- a/ext/digest/md5/md5.h
+++ b/ext/digest/md5/md5.h
@@ -41,7 +41,7 @@
/* $OrigId: md5.h,v 1.2 2001/03/26 08:57:14 matz Exp $ */
/* $RoughId: md5.h,v 1.3 2002/02/24 08:14:31 knu Exp $ */
-/* $Id: md5.h,v 1.2 2002/02/24 08:20:22 knu Exp $ */
+/* $Id$ */
#ifndef MD5_INCLUDED
# define MD5_INCLUDED
@@ -63,18 +63,15 @@ typedef struct md5_state_s {
} MD5_CTX;
#ifdef RUBY
+/* avoid name clash */
#define MD5_Init rb_Digest_MD5_Init
#define MD5_Update rb_Digest_MD5_Update
-#define MD5_Final rb_Digest_MD5_Final
-#define MD5_End rb_Digest_MD5_End
-#define MD5_Equal rb_Digest_MD5_Equal
+#define MD5_Finish rb_Digest_MD5_Finish
#endif
void MD5_Init _((MD5_CTX *pms));
void MD5_Update _((MD5_CTX *pms, const uint8_t *data, size_t nbytes));
-void MD5_Final _((uint8_t *digest, MD5_CTX *pms));
-void MD5_End _((MD5_CTX *pctx, uint8_t *hexdigest));
-int MD5_Equal _((MD5_CTX *pctx1, MD5_CTX *pctx2));
+void MD5_Finish _((MD5_CTX *pms, uint8_t *digest));
#define MD5_BLOCK_LENGTH 64
#define MD5_DIGEST_LENGTH 16
diff --git a/ext/digest/md5/md5init.c b/ext/digest/md5/md5init.c
index 52f5de540f..17658f4fce 100644
--- a/ext/digest/md5/md5init.c
+++ b/ext/digest/md5/md5init.c
@@ -1,5 +1,5 @@
/* $RoughId: md5init.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */
-/* $Id: md5init.c,v 1.5 2002/09/26 16:27:23 knu Exp $ */
+/* $Id$ */
#include "digest.h"
#if defined(HAVE_OPENSSL_MD5_H)
@@ -8,28 +8,33 @@
#include "md5.h"
#endif
-static algo_t md5 = {
+static rb_digest_metadata_t md5 = {
+ RUBY_DIGEST_API_VERSION,
MD5_DIGEST_LENGTH,
+ MD5_BLOCK_LENGTH,
sizeof(MD5_CTX),
- (hash_init_func_t)MD5_Init,
- (hash_update_func_t)MD5_Update,
- (hash_end_func_t)MD5_End,
- (hash_final_func_t)MD5_Final,
- (hash_equal_func_t)MD5_Equal,
+ (rb_digest_hash_init_func_t)MD5_Init,
+ (rb_digest_hash_update_func_t)MD5_Update,
+ (rb_digest_hash_finish_func_t)MD5_Finish,
};
+/*
+ * A class for calculating message digests using the MD5
+ * Message-Digest Algorithm by RSA Data Security, Inc., described in
+ * RFC1321.
+ */
void
Init_md5()
{
VALUE mDigest, cDigest_Base, cDigest_MD5;
- rb_require("digest.so");
+ rb_require("digest");
mDigest = rb_path2class("Digest");
cDigest_Base = rb_path2class("Digest::Base");
cDigest_MD5 = rb_define_class_under(mDigest, "MD5", cDigest_Base);
- rb_cvar_set(cDigest_MD5, rb_intern("metadata"),
- Data_Wrap_Struct(rb_cObject, 0, 0, &md5), Qtrue);
+ rb_ivar_set(cDigest_MD5, rb_intern("metadata"),
+ Data_Wrap_Struct(rb_cObject, 0, 0, &md5));
}
diff --git a/ext/digest/md5/md5ossl.c b/ext/digest/md5/md5ossl.c
index 4af7d19ba5..d94ae2cd2f 100644
--- a/ext/digest/md5/md5ossl.c
+++ b/ext/digest/md5/md5ossl.c
@@ -1,30 +1,9 @@
-/* $Id: md5ossl.c,v 1.2 2003/01/06 11:47:53 knu Exp $ */
+/* $Id$ */
#include "md5ossl.h"
-#include <sys/types.h>
-#include <stdio.h>
-#include <string.h>
void
-MD5_End(MD5_CTX *pctx, unsigned char *hexdigest)
+MD5_Finish(MD5_CTX *pctx, unsigned char *digest)
{
- unsigned char digest[16];
- size_t i;
-
MD5_Final(digest, pctx);
-
- for (i = 0; i < 16; i++)
- sprintf(hexdigest + i * 2, "%02x", digest[i]);
-}
-
-int
-MD5_Equal(MD5_CTX* pctx1, MD5_CTX* pctx2) {
- return pctx1->num == pctx2->num
- && pctx1->A == pctx2->A
- && pctx1->B == pctx2->B
- && pctx1->C == pctx2->C
- && pctx1->D == pctx2->D
- && pctx1->Nl == pctx2->Nl
- && pctx1->Nh == pctx2->Nh
- && memcmp(pctx1->data, pctx2->data, sizeof(pctx1->data)) == 0;
}
diff --git a/ext/digest/md5/md5ossl.h b/ext/digest/md5/md5ossl.h
index 401ef3418d..1680c4f5c9 100644
--- a/ext/digest/md5/md5ossl.h
+++ b/ext/digest/md5/md5ossl.h
@@ -1,4 +1,4 @@
-/* $Id: md5ossl.h,v 1.1.2.1 2005/08/30 10:43:34 gotoyuzo Exp $ */
+/* $Id$ */
#ifndef MD5OSSL_H_INCLUDED
#define MD5OSSL_H_INCLUDED
@@ -6,7 +6,8 @@
#include <stddef.h>
#include <openssl/md5.h>
-void MD5_End(MD5_CTX *pctx, unsigned char *hexdigest);
-int MD5_Equal(MD5_CTX *pctx1, MD5_CTX *pctx2);
+#define MD5_BLOCK_LENGTH MD5_CBLOCK
+
+void MD5_Finish(MD5_CTX *pctx, unsigned char *digest);
#endif
diff --git a/ext/digest/rmd160/depend b/ext/digest/rmd160/depend
index 0ca79c5f40..a21d7188dc 100644
--- a/ext/digest/rmd160/depend
+++ b/ext/digest/rmd160/depend
@@ -1,7 +1,5 @@
rmd160.o: rmd160.c rmd160.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
$(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
-rmd160hl.o: rmd160hl.c rmd160.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
- $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
rmd160init.o: rmd160init.c $(srcdir)/../digest.h $(hdrdir)/ruby.h \
$(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h \
rmd160.h $(srcdir)/../defs.h
diff --git a/ext/digest/rmd160/extconf.rb b/ext/digest/rmd160/extconf.rb
index 232a3a5e06..09359944f2 100644
--- a/ext/digest/rmd160/extconf.rb
+++ b/ext/digest/rmd160/extconf.rb
@@ -1,5 +1,5 @@
# $RoughId: extconf.rb,v 1.3 2001/08/14 19:54:51 knu Exp $
-# $Id: extconf.rb,v 1.4.2.2 2006/05/25 23:44:05 nobu Exp $
+# $Id$
require "mkmf"
@@ -14,7 +14,7 @@ if !with_config("bundled-rmd160") &&
have_library("crypto") && have_header("openssl/ripemd.h")
$objs << "rmd160ossl.#{$OBJEXT}"
else
- $objs << "rmd160.#{$OBJEXT}" << "rmd160hl.#{$OBJEXT}"
+ $objs << "rmd160.#{$OBJEXT}"
end
have_header("sys/cdefs.h")
@@ -23,4 +23,6 @@ have_header("inttypes.h")
have_header("unistd.h")
+$preload = %w[digest]
+
create_makefile("digest/rmd160")
diff --git a/ext/digest/rmd160/rmd160.c b/ext/digest/rmd160/rmd160.c
index 9562a6fe67..88918728cd 100644
--- a/ext/digest/rmd160/rmd160.c
+++ b/ext/digest/rmd160/rmd160.c
@@ -1,6 +1,6 @@
/* $NetBSD: rmd160.c,v 1.1.1.1 2001/03/06 11:21:05 agc Exp $ */
/* $RoughId: rmd160.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */
-/* $Id: rmd160.c,v 1.1 2001/07/13 20:06:14 knu Exp $ */
+/* $Id$ */
/********************************************************************\
*
@@ -409,7 +409,7 @@ RMD160_Update(RMD160_CTX *context, const uint8_t *data, size_t nbytes)
/********************************************************************/
void
-RMD160_Final(uint8_t digest[20], RMD160_CTX *context)
+RMD160_Finish(RMD160_CTX *context, uint8_t digest[20])
{
uint32_t i;
uint32_t X[16];
@@ -454,11 +454,4 @@ RMD160_Final(uint8_t digest[20], RMD160_CTX *context)
}
}
-int RMD160_Equal(RMD160_CTX* pctx1, RMD160_CTX* pctx2) {
- return pctx1->buflen == pctx2->buflen
- && memcmp(pctx1->length, pctx2->length, sizeof(pctx1->length)) == 0
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->bbuffer, pctx2->bbuffer, sizeof(pctx1->bbuffer)) == 0;
-}
-
/************************ end of file rmd160.c **********************/
diff --git a/ext/digest/rmd160/rmd160.h b/ext/digest/rmd160/rmd160.h
index 7df190413e..54d1ca9140 100644
--- a/ext/digest/rmd160/rmd160.h
+++ b/ext/digest/rmd160/rmd160.h
@@ -1,6 +1,6 @@
/* $NetBSD: rmd160.h,v 1.2 2000/07/07 10:47:06 ad Exp $ */
/* $RoughId: rmd160.h,v 1.3 2002/02/24 08:14:31 knu Exp $ */
-/* $Id: rmd160.h,v 1.2 2002/02/24 08:20:22 knu Exp $ */
+/* $Id$ */
/********************************************************************\
*
@@ -39,26 +39,14 @@ typedef struct {
#define RMD160_Init rb_Digest_RMD160_Init
#define RMD160_Transform rb_Digest_RMD160_Transform
#define RMD160_Update rb_Digest_RMD160_Update
-#define RMD160_Final rb_Digest_RMD160_Final
-#define RMD160_Equal rb_Digest_RMD160_Equal
-#ifndef _KERNEL
-#define RMD160_End rb_Digest_RMD160_End
-#define RMD160_File rb_Digest_RMD160_File
-#define RMD160_Data rb_Digest_RMD160_Data
-#endif /* _KERNEL */
+#define RMD160_Finish rb_Digest_RMD160_Finish
#endif
__BEGIN_DECLS
void RMD160_Init _((RMD160_CTX *));
void RMD160_Transform _((uint32_t[5], const uint32_t[16]));
void RMD160_Update _((RMD160_CTX *, const uint8_t *, size_t));
-void RMD160_Final _((uint8_t[20], RMD160_CTX *));
-int RMD160_Equal _((RMD160_CTX *, RMD160_CTX *));
-#ifndef _KERNEL
-char *RMD160_End _((RMD160_CTX *, char *));
-char *RMD160_File _((char *, char *));
-char *RMD160_Data _((const uint8_t *, size_t, char *));
-#endif /* _KERNEL */
+void RMD160_Finish _((RMD160_CTX *, uint8_t[20]));
__END_DECLS
#define RMD160_BLOCK_LENGTH 64
diff --git a/ext/digest/rmd160/rmd160hl.c b/ext/digest/rmd160/rmd160hl.c
deleted file mode 100644
index 14299d7c7a..0000000000
--- a/ext/digest/rmd160/rmd160hl.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* $NetBSD: rmd160hl.c,v 1.1.1.1 2001/03/06 11:21:05 agc Exp $ */
-/* $RoughId: rmd160hl.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */
-/* $Id: rmd160hl.c,v 1.1 2001/07/13 20:06:14 knu Exp $ */
-
-/* rmd160hl.c
- * ----------------------------------------------------------------------------
- * "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
- * ----------------------------------------------------------------------------
- *
- * from OpenBSD: rmd160hl.c,v 1.2 1999/08/17 09:13:12 millert Exp $
- */
-
-#include "rmd160.h"
-
-#ifndef lint
-/* __RCSID("$NetBSD: rmd160hl.c,v 1.1.1.1 2001/03/06 11:21:05 agc Exp $"); */
-#endif /* not lint */
-
-/* #include "namespace.h" */
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#if defined(HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#ifndef _DIAGASSERT
-#define _DIAGASSERT(cond) assert(cond)
-#endif
-
-
-char *
-RMD160_End(RMD160_CTX *ctx, char *buf)
-{
- size_t i;
- char *p = buf;
- uint8_t digest[20];
- static const char hex[]="0123456789abcdef";
-
- _DIAGASSERT(ctx != NULL);
- /* buf may be NULL */
-
- if (p == NULL && (p = malloc(41)) == NULL)
- return 0;
-
- RMD160_Final(digest,ctx);
- for (i = 0; i < 20; i++) {
- p[i + i] = hex[(uint32_t)digest[i] >> 4];
- p[i + i + 1] = hex[digest[i] & 0x0f];
- }
- p[i + i] = '\0';
- return(p);
-}
-
-char *
-RMD160_File(char *filename, char *buf)
-{
- uint8_t buffer[BUFSIZ];
- RMD160_CTX ctx;
- int fd, num, oerrno;
-
- _DIAGASSERT(filename != NULL);
- /* XXX: buf may be NULL ? */
-
- RMD160_Init(&ctx);
-
- if ((fd = open(filename, O_RDONLY)) < 0)
- return(0);
-
- while ((num = read(fd, buffer, sizeof(buffer))) > 0)
- RMD160_Update(&ctx, buffer, (size_t)num);
-
- oerrno = errno;
- close(fd);
- errno = oerrno;
- return(num < 0 ? 0 : RMD160_End(&ctx, buf));
-}
-
-char *
-RMD160_Data(const uint8_t *data, size_t len, char *buf)
-{
- RMD160_CTX ctx;
-
- _DIAGASSERT(data != NULL);
- /* XXX: buf may be NULL ? */
-
- RMD160_Init(&ctx);
- RMD160_Update(&ctx, data, len);
- return(RMD160_End(&ctx, buf));
-}
diff --git a/ext/digest/rmd160/rmd160init.c b/ext/digest/rmd160/rmd160init.c
index 3aa7847019..763867df86 100644
--- a/ext/digest/rmd160/rmd160init.c
+++ b/ext/digest/rmd160/rmd160init.c
@@ -1,5 +1,5 @@
/* $RoughId: rmd160init.c,v 1.3 2001/07/13 20:00:43 knu Exp $ */
-/* $Id: rmd160init.c,v 1.3 2002/09/26 17:26:46 knu Exp $ */
+/* $Id$ */
#include "digest.h"
#if defined(HAVE_OPENSSL_RIPEMD_H)
@@ -8,31 +8,33 @@
#include "rmd160.h"
#endif
-static algo_t rmd160 = {
+static rb_digest_metadata_t rmd160 = {
+ RUBY_DIGEST_API_VERSION,
RMD160_DIGEST_LENGTH,
+ RMD160_BLOCK_LENGTH,
sizeof(RMD160_CTX),
- (hash_init_func_t)RMD160_Init,
- (hash_update_func_t)RMD160_Update,
- (hash_end_func_t)RMD160_End,
- (hash_final_func_t)RMD160_Final,
- (hash_equal_func_t)RMD160_Equal,
+ (rb_digest_hash_init_func_t)RMD160_Init,
+ (rb_digest_hash_update_func_t)RMD160_Update,
+ (rb_digest_hash_finish_func_t)RMD160_Finish,
};
+/*
+ * A class for calculating message digests using RIPEMD-160
+ * cryptographic hash function, designed by Hans Dobbertin, Antoon
+ * Bosselaers, and Bart Preneel.
+ */
void
Init_rmd160()
{
VALUE mDigest, cDigest_Base, cDigest_RMD160;
- ID id_metadata;
- rb_require("digest.so");
+ rb_require("digest");
mDigest = rb_path2class("Digest");
cDigest_Base = rb_path2class("Digest::Base");
cDigest_RMD160 = rb_define_class_under(mDigest, "RMD160", cDigest_Base);
- id_metadata = rb_intern("metadata");
-
- rb_cvar_set(cDigest_RMD160, id_metadata,
- Data_Wrap_Struct(rb_cObject, 0, 0, &rmd160), Qtrue);
+ rb_ivar_set(cDigest_RMD160, rb_intern("metadata"),
+ Data_Wrap_Struct(rb_cObject, 0, 0, &rmd160));
}
diff --git a/ext/digest/rmd160/rmd160ossl.c b/ext/digest/rmd160/rmd160ossl.c
index 1a8436dfb8..f24e63e3d8 100644
--- a/ext/digest/rmd160/rmd160ossl.c
+++ b/ext/digest/rmd160/rmd160ossl.c
@@ -1,45 +1,8 @@
-/* $Id: rmd160ossl.c,v 1.1.2.1 2006/08/07 09:01:27 matz Exp $ */
+/* $Id$ */
#include "defs.h"
#include "rmd160ossl.h"
-#include <assert.h>
-#include <stdlib.h>
-#ifndef _DIAGASSERT
-#define _DIAGASSERT(cond) assert(cond)
-#endif
-
-char *
-RMD160_End(RMD160_CTX *ctx, char *buf)
-{
- size_t i;
- char *p = buf;
- uint8_t digest[20];
- static const char hex[]="0123456789abcdef";
-
- _DIAGASSERT(ctx != NULL);
- /* buf may be NULL */
-
- if (p == NULL && (p = malloc(41)) == NULL)
- return 0;
-
- RMD160_Final(digest,ctx);
- for (i = 0; i < 20; i++) {
- p[i + i] = hex[(uint32_t)digest[i] >> 4];
- p[i + i + 1] = hex[digest[i] & 0x0f];
- }
- p[i + i] = '\0';
- return(p);
-}
-
-int RMD160_Equal(RMD160_CTX* pctx1, RMD160_CTX* pctx2) {
- return pctx1->num == pctx2->num
- && pctx1->A == pctx2->A
- && pctx1->B == pctx2->B
- && pctx1->C == pctx2->C
- && pctx1->D == pctx2->D
- && pctx1->E == pctx2->E
- && pctx1->Nl == pctx2->Nl
- && pctx1->Nh == pctx2->Nh
- && memcmp(pctx1->data, pctx2->data, sizeof(pctx1->data)) == 0;
+void RMD160_Finish(RMD160_CTX *ctx, char *buf) {
+ RIPEMD160_Final((unsigned char *)buf, ctx);
}
diff --git a/ext/digest/rmd160/rmd160ossl.h b/ext/digest/rmd160/rmd160ossl.h
index 30840ca598..3df38a01c0 100644
--- a/ext/digest/rmd160/rmd160ossl.h
+++ b/ext/digest/rmd160/rmd160ossl.h
@@ -1,4 +1,4 @@
-/* $Id: rmd160ossl.h,v 1.1.2.1 2005/08/30 10:43:35 gotoyuzo Exp $ */
+/* $Id$ */
#ifndef RMD160OSSL_H_INCLUDED
#define RMD160OSSL_H_INCLUDED
@@ -10,12 +10,10 @@
#define RMD160_Init RIPEMD160_Init
#define RMD160_Update RIPEMD160_Update
-#define RMD160_Final RIPEMD160_Final
#define RMD160_BLOCK_LENGTH RIPEMD160_CBLOCK
#define RMD160_DIGEST_LENGTH RIPEMD160_DIGEST_LENGTH
-char *RMD160_End(RMD160_CTX *ctx, char *buf);
-int RMD160_Equal(RMD160_CTX *pctx1, RMD160_CTX *pctx2);
+void RMD160_Finish(RMD160_CTX *ctx, char *buf);
#endif
diff --git a/ext/digest/sha1/depend b/ext/digest/sha1/depend
index a159f456d3..61607844d0 100644
--- a/ext/digest/sha1/depend
+++ b/ext/digest/sha1/depend
@@ -1,7 +1,5 @@
sha1.o: sha1.c sha1.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
$(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
-sha1hl.o: sha1hl.c sha1.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
- $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
sha1init.o: sha1init.c $(srcdir)/../digest.h $(hdrdir)/ruby.h \
$(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h \
sha1.h $(srcdir)/../defs.h
diff --git a/ext/digest/sha1/extconf.rb b/ext/digest/sha1/extconf.rb
index 861c5563f9..87b74c34af 100644
--- a/ext/digest/sha1/extconf.rb
+++ b/ext/digest/sha1/extconf.rb
@@ -1,5 +1,5 @@
# $RoughId: extconf.rb,v 1.3 2001/08/14 19:54:51 knu Exp $
-# $Id: extconf.rb,v 1.5.2.1 2006/05/25 23:44:05 nobu Exp $
+# $Id$
require "mkmf"
@@ -14,7 +14,7 @@ if !with_config("bundled-sha1") &&
have_library("crypto") && have_header("openssl/sha.h")
$objs << "sha1ossl.#{$OBJEXT}"
else
- $objs << "sha1.#{$OBJEXT}" << "sha1hl.#{$OBJEXT}"
+ $objs << "sha1.#{$OBJEXT}"
end
have_header("sys/cdefs.h")
@@ -23,4 +23,6 @@ have_header("inttypes.h")
have_header("unistd.h")
+$preload = %w[digest]
+
create_makefile("digest/sha1")
diff --git a/ext/digest/sha1/sha1.c b/ext/digest/sha1/sha1.c
index ba926e1fad..6196ca6b82 100644
--- a/ext/digest/sha1/sha1.c
+++ b/ext/digest/sha1/sha1.c
@@ -1,7 +1,7 @@
/* $NetBSD: sha1.c,v 1.2 2001/03/22 09:51:48 agc Exp $ */
/* $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $ */
/* $RoughId: sha1.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */
-/* $Id: sha1.c,v 1.1 2001/07/13 20:06:14 knu Exp $ */
+/* $Id$ */
/*
* SHA-1 in C
@@ -129,9 +129,7 @@ do_R4(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, uint32_t *e, CHAR64LON
/*
* Hash a single 512-bit block. This is the core of the algorithm.
*/
-void SHA1_Transform(state, buffer)
- uint32_t state[5];
- const uint8_t buffer[64];
+void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
{
uint32_t a, b, c, d, e;
CHAR64LONG16 *block;
@@ -201,8 +199,7 @@ void SHA1_Transform(state, buffer)
/*
* SHA1_Init - Initialize new context
*/
-void SHA1_Init(context)
- SHA1_CTX *context;
+void SHA1_Init(SHA1_CTX *context)
{
_DIAGASSERT(context != 0);
@@ -220,10 +217,7 @@ void SHA1_Init(context)
/*
* Run your data through this.
*/
-void SHA1_Update(context, data, len)
- SHA1_CTX *context;
- const uint8_t *data;
- size_t len;
+void SHA1_Update(SHA1_CTX *context, const uint8_t *data, size_t len)
{
uint32_t i, j;
@@ -250,9 +244,7 @@ void SHA1_Update(context, data, len)
/*
* Add padding and return the message digest.
*/
-void SHA1_Final(digest, context)
- uint8_t digest[20];
- SHA1_CTX* context;
+void SHA1_Finish(SHA1_CTX* context, uint8_t digest[20])
{
size_t i;
uint8_t finalcount[8];
@@ -275,9 +267,3 @@ void SHA1_Final(digest, context)
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
}
-
-int SHA1_Equal(SHA1_CTX* pctx1, SHA1_CTX* pctx2) {
- return memcmp(pctx1->count, pctx2->count, sizeof(pctx1->count)) == 0
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0;
-}
diff --git a/ext/digest/sha1/sha1.h b/ext/digest/sha1/sha1.h
index 5a1143ea0d..60e3b01fe2 100644
--- a/ext/digest/sha1/sha1.h
+++ b/ext/digest/sha1/sha1.h
@@ -1,6 +1,6 @@
/* $NetBSD: sha1.h,v 1.2 1998/05/29 22:55:44 thorpej Exp $ */
/* $RoughId: sha1.h,v 1.3 2002/02/24 08:14:32 knu Exp $ */
-/* $Id: sha1.h,v 1.2 2002/02/24 08:20:22 knu Exp $ */
+/* $Id$ */
/*
* SHA-1 in C
@@ -20,28 +20,17 @@ typedef struct {
} SHA1_CTX;
#ifdef RUBY
+/* avoid name clash */
#define SHA1_Transform rb_Digest_SHA1_Transform
#define SHA1_Init rb_Digest_SHA1_Init
#define SHA1_Update rb_Digest_SHA1_Update
-#define SHA1_Final rb_Digest_SHA1_Final
-#define SHA1_Equal rb_Digest_SHA1_Equal
-#ifndef _KERNEL
-#define SHA1_End rb_Digest_SHA1_End
-#define SHA1_File rb_Digest_SHA1_File
-#define SHA1_Data rb_Digest_SHA1_Data
-#endif /* _KERNEL */
+#define SHA1_Finish rb_Digest_SHA1_Finish
#endif
void SHA1_Transform _((uint32_t state[5], const uint8_t buffer[64]));
void SHA1_Init _((SHA1_CTX *context));
void SHA1_Update _((SHA1_CTX *context, const uint8_t *data, size_t len));
-void SHA1_Final _((uint8_t digest[20], SHA1_CTX *context));
-int SHA1_Equal _((SHA1_CTX *pctx1, SHA1_CTX *pctx2));
-#ifndef _KERNEL
-char *SHA1_End _((SHA1_CTX *, char *));
-char *SHA1_File _((char *, char *));
-char *SHA1_Data _((const uint8_t *, size_t, char *));
-#endif /* _KERNEL */
+void SHA1_Finish _((SHA1_CTX *context, uint8_t digest[20]));
#define SHA1_BLOCK_LENGTH 64
#define SHA1_DIGEST_LENGTH 20
diff --git a/ext/digest/sha1/sha1hl.c b/ext/digest/sha1/sha1hl.c
deleted file mode 100644
index 47b802085d..0000000000
--- a/ext/digest/sha1/sha1hl.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/* $NetBSD: sha1hl.c,v 1.2 2001/03/10 15:55:14 tron Exp $ */
-/* $RoughId: sha1hl.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */
-/* $Id: sha1hl.c,v 1.1 2001/07/13 20:06:14 knu Exp $ */
-
-/* sha1hl.c
- * ----------------------------------------------------------------------------
- * "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
- * ----------------------------------------------------------------------------
- */
-
-/* #include "namespace.h" */
-
-#include "sha1.h"
-#include <fcntl.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#if defined(HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#if defined(LIBC_SCCS) && !defined(lint)
-/* __RCSID("$NetBSD: sha1hl.c,v 1.2 2001/03/10 15:55:14 tron Exp $"); */
-#endif /* LIBC_SCCS and not lint */
-
-#ifndef _DIAGASSERT
-#define _DIAGASSERT(cond) assert(cond)
-#endif
-
-
-/* ARGSUSED */
-char *
-SHA1_End(ctx, buf)
- SHA1_CTX *ctx;
- char *buf;
-{
- int i;
- char *p = buf;
- uint8_t digest[20];
- static const char hex[]="0123456789abcdef";
-
- _DIAGASSERT(ctx != NULL);
- /* buf may be NULL */
-
- if (p == NULL && (p = malloc(41)) == NULL)
- return 0;
-
- SHA1_Final(digest,ctx);
- for (i = 0; i < 20; i++) {
- p[i + i] = hex[((uint32_t)digest[i]) >> 4];
- p[i + i + 1] = hex[digest[i] & 0x0f];
- }
- p[i + i] = '\0';
- return(p);
-}
-
-char *
-SHA1_File (filename, buf)
- char *filename;
- char *buf;
-{
- uint8_t buffer[BUFSIZ];
- SHA1_CTX ctx;
- int fd, num, oerrno;
-
- _DIAGASSERT(filename != NULL);
- /* XXX: buf may be NULL ? */
-
- SHA1_Init(&ctx);
-
- if ((fd = open(filename,O_RDONLY)) < 0)
- return(0);
-
- while ((num = read(fd, buffer, sizeof(buffer))) > 0)
- SHA1_Update(&ctx, buffer, (size_t)num);
-
- oerrno = errno;
- close(fd);
- errno = oerrno;
- return(num < 0 ? 0 : SHA1_End(&ctx, buf));
-}
-
-char *
-SHA1_Data (data, len, buf)
- const uint8_t *data;
- size_t len;
- char *buf;
-{
- SHA1_CTX ctx;
-
- _DIAGASSERT(data != NULL);
- /* XXX: buf may be NULL ? */
-
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, data, len);
- return(SHA1_End(&ctx, buf));
-}
diff --git a/ext/digest/sha1/sha1init.c b/ext/digest/sha1/sha1init.c
index 829a363921..b2146f05a9 100644
--- a/ext/digest/sha1/sha1init.c
+++ b/ext/digest/sha1/sha1init.c
@@ -1,5 +1,5 @@
/* $RoughId: sha1init.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */
-/* $Id: sha1init.c,v 1.3 2002/09/26 17:44:33 knu Exp $ */
+/* $Id$ */
#include "digest.h"
#if defined(HAVE_OPENSSL_SHA_H)
@@ -8,31 +8,33 @@
#include "sha1.h"
#endif
-static algo_t sha1 = {
+static rb_digest_metadata_t sha1 = {
+ RUBY_DIGEST_API_VERSION,
SHA1_DIGEST_LENGTH,
+ SHA1_BLOCK_LENGTH,
sizeof(SHA1_CTX),
- (hash_init_func_t)SHA1_Init,
- (hash_update_func_t)SHA1_Update,
- (hash_end_func_t)SHA1_End,
- (hash_final_func_t)SHA1_Final,
- (hash_equal_func_t)SHA1_Equal,
+ (rb_digest_hash_init_func_t)SHA1_Init,
+ (rb_digest_hash_update_func_t)SHA1_Update,
+ (rb_digest_hash_finish_func_t)SHA1_Finish,
};
+/*
+ * A class for calculating message digests using the SHA-1 Secure Hash
+ * Algorithm by NIST (the US' National Institute of Standards and
+ * Technology), described in FIPS PUB 180-1.
+ */
void
Init_sha1()
{
VALUE mDigest, cDigest_Base, cDigest_SHA1;
- ID id_metadata;
-
- rb_require("digest.so");
-
+
+ rb_require("digest");
+
mDigest = rb_path2class("Digest");
cDigest_Base = rb_path2class("Digest::Base");
cDigest_SHA1 = rb_define_class_under(mDigest, "SHA1", cDigest_Base);
- id_metadata = rb_intern("metadata");
-
- rb_cvar_set(cDigest_SHA1, id_metadata,
- Data_Wrap_Struct(rb_cObject, 0, 0, &sha1), Qtrue);
+ rb_ivar_set(cDigest_SHA1, rb_intern("metadata"),
+ Data_Wrap_Struct(rb_cObject, 0, 0, &sha1));
}
diff --git a/ext/digest/sha1/sha1ossl.c b/ext/digest/sha1/sha1ossl.c
index 72c6eb4092..452cf35084 100644
--- a/ext/digest/sha1/sha1ossl.c
+++ b/ext/digest/sha1/sha1ossl.c
@@ -1,45 +1,10 @@
-/* $Id: sha1ossl.c,v 1.1.2.1 2006/08/07 09:01:27 matz Exp $ */
+/* $Id$ */
#include "defs.h"
#include "sha1ossl.h"
-#include <assert.h>
-#include <stdlib.h>
-#ifndef _DIAGASSERT
-#define _DIAGASSERT(cond) assert(cond)
-#endif
-
-char *
-SHA1_End(SHA1_CTX *ctx, char *buf)
+void
+SHA1_Finish(SHA1_CTX *ctx, char *buf)
{
- int i;
- char *p = buf;
- uint8_t digest[20];
- static const char hex[]="0123456789abcdef";
-
- _DIAGASSERT(ctx != NULL);
- /* buf may be NULL */
-
- if (p == NULL && (p = malloc(41)) == NULL)
- return 0;
-
- SHA1_Final(digest,ctx);
- for (i = 0; i < 20; i++) {
- p[i + i] = hex[((uint32_t)digest[i]) >> 4];
- p[i + i + 1] = hex[digest[i] & 0x0f];
- }
- p[i + i] = '\0';
- return(p);
-}
-
-int SHA1_Equal(SHA1_CTX* pctx1, SHA1_CTX* pctx2) {
- return pctx1->num == pctx2->num
- && pctx1->h0 == pctx2->h0
- && pctx1->h1 == pctx2->h1
- && pctx1->h2 == pctx2->h2
- && pctx1->h3 == pctx2->h3
- && pctx1->h4 == pctx2->h4
- && pctx1->Nl == pctx2->Nl
- && pctx1->Nh == pctx2->Nh
- && memcmp(pctx1->data, pctx2->data, sizeof(pctx1->data)) == 0;
+ SHA1_Final((unsigned char *)buf, ctx);
}
diff --git a/ext/digest/sha1/sha1ossl.h b/ext/digest/sha1/sha1ossl.h
index 24b84b4274..8f9984cc64 100644
--- a/ext/digest/sha1/sha1ossl.h
+++ b/ext/digest/sha1/sha1ossl.h
@@ -1,4 +1,4 @@
-/* $Id: sha1ossl.h,v 1.1.2.1 2005/08/30 10:43:36 gotoyuzo Exp $ */
+/* $Id$ */
#ifndef SHA1OSSL_H_INCLUDED
#define SHA1OSSL_H_INCLUDED
@@ -8,10 +8,13 @@
#define SHA1_CTX SHA_CTX
+#ifdef SHA_BLOCK_LENGTH
#define SHA1_BLOCK_LENGTH SHA_BLOCK_LENGTH
+#else
+#define SHA1_BLOCK_LENGTH SHA_CBLOCK
+#endif
#define SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH
-char *SHA1_End(SHA1_CTX *ctx, char *buf);
-int SHA1_Equal(SHA1_CTX *pctx1, SHA1_CTX *pctx2);
+void SHA1_Finish(SHA1_CTX *ctx, char *buf);
#endif
diff --git a/ext/digest/sha2/depend b/ext/digest/sha2/depend
index 2587415fdc..225d6ad52b 100644
--- a/ext/digest/sha2/depend
+++ b/ext/digest/sha2/depend
@@ -1,7 +1,5 @@
sha2.o: sha2.c sha2.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
$(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
-sha2hl.o: sha2hl.c sha2.h $(srcdir)/../defs.h $(hdrdir)/ruby.h \
- $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
sha2init.o: sha2init.c $(srcdir)/../digest.h $(hdrdir)/ruby.h \
$(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h \
sha2.h $(srcdir)/../defs.h
diff --git a/ext/digest/sha2/extconf.rb b/ext/digest/sha2/extconf.rb
index 5d078f4bd6..c084a51a64 100644
--- a/ext/digest/sha2/extconf.rb
+++ b/ext/digest/sha2/extconf.rb
@@ -1,5 +1,5 @@
# $RoughId: extconf.rb,v 1.4 2001/08/14 19:54:51 knu Exp $
-# $Id: extconf.rb,v 1.7.2.2 2006/05/25 23:44:06 nobu Exp $
+# $Id$
require "mkmf"
@@ -8,7 +8,6 @@ $INCFLAGS << " -I$(srcdir)/.."
$objs = [
"sha2.#{$OBJEXT}",
- "sha2hl.#{$OBJEXT}",
"sha2init.#{$OBJEXT}",
]
@@ -18,6 +17,8 @@ have_header("inttypes.h")
have_header("unistd.h")
+$preload = %w[digest]
+
if have_type("uint64_t", "defs.h", $defs.join(' '))
create_makefile("digest/sha2")
end
diff --git a/ext/digest/sha2/lib/sha2.rb b/ext/digest/sha2/lib/sha2.rb
new file mode 100644
index 0000000000..52dd639f9b
--- /dev/null
+++ b/ext/digest/sha2/lib/sha2.rb
@@ -0,0 +1,73 @@
+#--
+# sha2.rb - defines Digest::SHA2 class which wraps up the SHA256,
+# SHA384, and SHA512 classes.
+#++
+# Copyright (c) 2006 Akinori MUSHA <knu@iDaemons.org>
+#
+# All rights reserved. You can redistribute and/or modify it under the same
+# terms as Ruby.
+#
+# $Id$
+
+require 'digest'
+
+module Digest
+ #
+ # A meta digest provider class for SHA256, SHA384 and SHA512.
+ #
+ class SHA2 < Digest::Class
+ # call-seq:
+ # Digest::SHA2.new(bitlen = 256) -> digest_obj
+ #
+ # Creates a new SHA2 hash object with a given bit length.
+ def initialize(bitlen = 256)
+ case bitlen
+ when 256
+ @sha2 = Digest::SHA256.new
+ when 384
+ @sha2 = Digest::SHA384.new
+ when 512
+ @sha2 = Digest::SHA512.new
+ else
+ raise ArgumentError, "unsupported bit length: %s" % bitlen.inspect
+ end
+ @bitlen = bitlen
+ end
+
+ # :nodoc:
+ def reset
+ @sha2.reset
+ self
+ end
+
+ # :nodoc:
+ def update(str)
+ @sha2.update(str)
+ self
+ end
+ alias << update
+
+ def finish
+ @sha2.digest!
+ end
+ private :finish
+
+ def block_length
+ @sha2.block_length
+ end
+
+ def digest_length
+ @sha2.digest_length
+ end
+
+ # :nodoc:
+ def initialize_copy(other)
+ @sha2 = other.instance_eval { @sha2.clone }
+ end
+
+ # :nodoc:
+ def inspect
+ "#<%s:%d %s>" % [self.class.name, @bitlen, hexdigest]
+ end
+ end
+end
diff --git a/ext/digest/sha2/sha2.c b/ext/digest/sha2/sha2.c
index 22e7d59cd3..aca9ee926f 100644
--- a/ext/digest/sha2/sha2.c
+++ b/ext/digest/sha2/sha2.c
@@ -34,7 +34,7 @@
*/
/* $RoughId: sha2.c,v 1.3 2002/02/26 22:03:36 knu Exp $ */
-/* $Id: sha2.c,v 1.4.2.1 2005/12/24 09:58:56 matz Exp $ */
+/* $Id$ */
#include "sha2.h"
#include <stdio.h>
@@ -515,7 +515,7 @@ void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
usedspace = freespace = 0;
}
-void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
+void SHA256_Finish(SHA256_CTX* context, sha2_byte digest[]) {
sha2_word32 *d = (sha2_word32*)digest;
unsigned int usedspace;
@@ -578,12 +578,6 @@ void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
usedspace = 0;
}
-int SHA256_Equal(SHA256_CTX* pctx1, SHA256_CTX* pctx2) {
- return pctx1->bitcount == pctx2->bitcount
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0;
-}
-
/*** SHA-512: *********************************************************/
void SHA512_Init(SHA512_CTX* context) {
if (context == (SHA512_CTX*)0) {
@@ -852,7 +846,7 @@ void SHA512_Last(SHA512_CTX* context) {
SHA512_Transform(context, (const sha2_word64*)context->buffer);
}
-void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
+void SHA512_Finish(SHA512_CTX* context, sha2_byte digest[]) {
sha2_word64 *d = (sha2_word64*)digest;
/* Sanity check: */
@@ -881,12 +875,6 @@ void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
MEMSET_BZERO(context, sizeof(SHA512_CTX));
}
-int SHA512_Equal(SHA512_CTX* pctx1, SHA512_CTX* pctx2) {
- return memcmp(pctx1->bitcount, pctx2->bitcount, sizeof(pctx1->bitcount)) == 0
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0;
-}
-
/*** SHA-384: *********************************************************/
void SHA384_Init(SHA384_CTX* context) {
if (context == (SHA384_CTX*)0) {
@@ -901,7 +889,7 @@ void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) {
SHA512_Update((SHA512_CTX*)context, data, len);
}
-void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
+void SHA384_Finish(SHA384_CTX* context, sha2_byte digest[]) {
sha2_word64 *d = (sha2_word64*)digest;
/* Sanity check: */
@@ -929,9 +917,3 @@ void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
/* Zero out state data */
MEMSET_BZERO(context, sizeof(SHA384_CTX));
}
-
-int SHA384_Equal(SHA384_CTX* pctx1, SHA384_CTX* pctx2) {
- return memcmp(pctx1->bitcount, pctx2->bitcount, sizeof(pctx1->bitcount)) == 0
- && memcmp(pctx1->state, pctx2->state, sizeof(pctx1->state)) == 0
- && memcmp(pctx1->buffer, pctx2->buffer, sizeof(pctx1->buffer)) == 0;
-}
diff --git a/ext/digest/sha2/sha2.h b/ext/digest/sha2/sha2.h
index 7ccf012b77..917d415b73 100644
--- a/ext/digest/sha2/sha2.h
+++ b/ext/digest/sha2/sha2.h
@@ -34,7 +34,7 @@
*/
/* $RoughId: sha2.h,v 1.3 2002/02/24 08:14:32 knu Exp $ */
-/* $Id: sha2.h,v 1.2 2002/02/24 08:20:22 knu Exp $ */
+/* $Id$ */
#ifndef __SHA2_H__
#define __SHA2_H__
@@ -77,53 +77,29 @@ typedef SHA512_CTX SHA384_CTX;
#ifdef RUBY
#define SHA256_Init rb_Digest_SHA256_Init
#define SHA256_Update rb_Digest_SHA256_Update
-#define SHA256_Final rb_Digest_SHA256_Final
-#define SHA256_End rb_Digest_SHA256_End
-#define SHA256_Data rb_Digest_SHA256_Data
-#define SHA256_File rb_Digest_SHA256_File
-#define SHA256_Equal rb_Digest_SHA256_Equal
+#define SHA256_Finish rb_Digest_SHA256_Finish
#define SHA384_Init rb_Digest_SHA384_Init
#define SHA384_Update rb_Digest_SHA384_Update
-#define SHA384_Final rb_Digest_SHA384_Final
-#define SHA384_End rb_Digest_SHA384_End
-#define SHA384_Data rb_Digest_SHA384_Data
-#define SHA384_File rb_Digest_SHA384_File
-#define SHA384_Equal rb_Digest_SHA384_Equal
+#define SHA384_Finish rb_Digest_SHA384_Finish
#define SHA512_Init rb_Digest_SHA512_Init
#define SHA512_Update rb_Digest_SHA512_Update
-#define SHA512_Final rb_Digest_SHA512_Final
-#define SHA512_End rb_Digest_SHA512_End
-#define SHA512_Data rb_Digest_SHA512_Data
-#define SHA512_File rb_Digest_SHA512_File
-#define SHA512_Equal rb_Digest_SHA512_Equal
+#define SHA512_Finish rb_Digest_SHA512_Finish
#endif
/*** SHA-256/384/512 Function Prototypes ******************************/
void SHA256_Init _((SHA256_CTX *));
void SHA256_Update _((SHA256_CTX*, const uint8_t*, size_t));
-void SHA256_Final _((uint8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*));
-char* SHA256_End _((SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]));
-char* SHA256_Data _((const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]));
-char *SHA256_File _((char *, char *));
-int SHA256_Equal _((SHA256_CTX*, SHA256_CTX*));
+void SHA256_Finish _((SHA256_CTX*, uint8_t[SHA256_DIGEST_LENGTH]));
void SHA384_Init _((SHA384_CTX*));
void SHA384_Update _((SHA384_CTX*, const uint8_t*, size_t));
-void SHA384_Final _((uint8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*));
-char* SHA384_End _((SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]));
-char* SHA384_Data _((const uint8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]));
-char *SHA384_File _((char *, char *));
-int SHA384_Equal _((SHA384_CTX*, SHA384_CTX*));
+void SHA384_Finish _((SHA384_CTX*, uint8_t[SHA384_DIGEST_LENGTH]));
void SHA512_Init _((SHA512_CTX*));
void SHA512_Update _((SHA512_CTX*, const uint8_t*, size_t));
-void SHA512_Final _((uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*));
-char* SHA512_End _((SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]));
-char* SHA512_Data _((const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]));
-char *SHA512_File _((char *, char *));
-int SHA512_Equal _((SHA512_CTX*, SHA512_CTX*));
+void SHA512_Finish _((SHA512_CTX*, uint8_t[SHA512_DIGEST_LENGTH]));
#ifdef __cplusplus
}
diff --git a/ext/digest/sha2/sha2hl.c b/ext/digest/sha2/sha2hl.c
deleted file mode 100644
index 8f09bd6e5a..0000000000
--- a/ext/digest/sha2/sha2hl.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/* $NetBSD: sha2hl.c,v 1.1 2001/03/12 09:08:40 agc Exp $ */
-/* $RoughId: sha2hl.c,v 1.2 2001/07/13 19:49:10 knu Exp $ */
-/* $Id: sha2hl.c,v 1.1 2001/07/13 20:06:14 knu Exp $ */
-
-/*
- * sha2hl.c
- * This code includes some functions taken from sha2.c, hence the
- * following licence reproduction.
- *
- * This code is not a verbatim copy, since some routines have been added,
- * and some bugs have been fixed.
- *
- * Version 1.0.0beta1
- *
- * Written by Aaron D. Gifford <me@aarongifford.com>
- *
- * Copyright 2000 Aaron D. Gifford. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holder nor the names of contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include "sha2.h"
-
-#ifndef lint
-/* __RCSID("$NetBSD: sha2hl.c,v 1.1 2001/03/12 09:08:40 agc Exp $"); */
-#endif /* not lint */
-
-/* #include "namespace.h" */
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#if defined(HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#ifndef _DIAGASSERT
-#define _DIAGASSERT(cond) assert(cond)
-#endif
-
-/*
- * Constant used by SHA256/384/512_End() functions for converting the
- * digest to a readable hexadecimal character string:
- */
-static const char sha2_hex_digits[] = "0123456789abcdef";
-
-char *
-SHA256_File(char *filename, char *buf)
-{
- uint8_t buffer[BUFSIZ * 20];
- SHA256_CTX ctx;
- int fd, num, oerrno;
-
- _DIAGASSERT(filename != NULL);
- /* XXX: buf may be NULL ? */
-
- SHA256_Init(&ctx);
-
- if ((fd = open(filename, O_RDONLY)) < 0)
- return (0);
-
- while ((num = read(fd, buffer, sizeof(buffer))) > 0)
- SHA256_Update(&ctx, buffer, (size_t) num);
-
- oerrno = errno;
- close(fd);
- errno = oerrno;
- return (num < 0 ? 0 : SHA256_End(&ctx, buf));
-}
-
-
-char *
-SHA256_End(SHA256_CTX *ctx, char buffer[])
-{
- uint8_t digest[SHA256_DIGEST_LENGTH], *d = digest;
- uint8_t *ret;
- int i;
-
- /* Sanity check: */
- assert(ctx != NULL);
-
- if ((ret = buffer) != NULL) {
- SHA256_Final(digest, ctx);
-
- for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
- *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha2_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char) 0;
- } else {
- (void) memset(ctx, 0, sizeof(SHA256_CTX));
- }
- (void) memset(digest, 0, SHA256_DIGEST_LENGTH);
- return ret;
-}
-
-char *
-SHA256_Data(const uint8_t * data, size_t len, char *digest)
-{
- SHA256_CTX ctx;
-
- SHA256_Init(&ctx);
- SHA256_Update(&ctx, data, len);
- return SHA256_End(&ctx, digest);
-}
-
-char *
-SHA384_File(char *filename, char *buf)
-{
- SHA384_CTX ctx;
- uint8_t buffer[BUFSIZ * 20];
- int fd, num, oerrno;
-
- _DIAGASSERT(filename != NULL);
- /* XXX: buf may be NULL ? */
-
- SHA384_Init(&ctx);
-
- if ((fd = open(filename, O_RDONLY)) < 0)
- return (0);
-
- while ((num = read(fd, buffer, sizeof(buffer))) > 0)
- SHA384_Update(&ctx, buffer, (size_t) num);
-
- oerrno = errno;
- close(fd);
- errno = oerrno;
- return (num < 0 ? 0 : SHA384_End(&ctx, buf));
-}
-
-char *
-SHA384_End(SHA384_CTX * ctx, char buffer[])
-{
- uint8_t digest[SHA384_DIGEST_LENGTH], *d = digest;
- uint8_t *ret;
- int i;
-
- /* Sanity check: */
- assert(ctx != NULL);
-
- if ((ret = buffer) != NULL) {
- SHA384_Final(digest, ctx);
-
- for (i = 0; i < SHA384_DIGEST_LENGTH; i++) {
- *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha2_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char) 0;
- } else {
- (void) memset(ctx, 0, sizeof(SHA384_CTX));
- }
- (void) memset(digest, 0, SHA384_DIGEST_LENGTH);
- return ret;
-}
-
-char *
-SHA384_Data(const uint8_t * data, size_t len, char *digest)
-{
- SHA384_CTX ctx;
-
- SHA384_Init(&ctx);
- SHA384_Update(&ctx, data, len);
- return SHA384_End(&ctx, digest);
-}
-
-char *
-SHA512_File(char *filename, char *buf)
-{
- SHA512_CTX ctx;
- uint8_t buffer[BUFSIZ * 20];
- int fd, num, oerrno;
-
- _DIAGASSERT(filename != NULL);
- /* XXX: buf may be NULL ? */
-
- SHA512_Init(&ctx);
-
- if ((fd = open(filename, O_RDONLY)) < 0)
- return (0);
-
- while ((num = read(fd, buffer, sizeof(buffer))) > 0)
- SHA512_Update(&ctx, buffer, (size_t) num);
-
- oerrno = errno;
- close(fd);
- errno = oerrno;
- return (num < 0 ? 0 : SHA512_End(&ctx, buf));
-}
-
-char *
-SHA512_End(SHA512_CTX * ctx, char buffer[])
-{
- uint8_t digest[SHA512_DIGEST_LENGTH], *d = digest;
- uint8_t *ret;
- int i;
-
- /* Sanity check: */
- assert(ctx != NULL);
-
- if ((ret = buffer) != NULL) {
- SHA512_Final(digest, ctx);
-
- for (i = 0; i < SHA512_DIGEST_LENGTH; i++) {
- *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
- *buffer++ = sha2_hex_digits[*d & 0x0f];
- d++;
- }
- *buffer = (char) 0;
- } else {
- (void) memset(ctx, 0, sizeof(SHA512_CTX));
- }
- (void) memset(digest, 0, SHA512_DIGEST_LENGTH);
- return ret;
-}
-
-char *
-SHA512_Data(const uint8_t * data, size_t len, char *digest)
-{
- SHA512_CTX ctx;
-
- SHA512_Init(&ctx);
- SHA512_Update(&ctx, data, len);
- return SHA512_End(&ctx, digest);
-}
diff --git a/ext/digest/sha2/sha2init.c b/ext/digest/sha2/sha2init.c
index 9c0f9854fb..c83a29316a 100644
--- a/ext/digest/sha2/sha2init.c
+++ b/ext/digest/sha2/sha2init.c
@@ -1,5 +1,5 @@
/* $RoughId: sha2init.c,v 1.3 2001/07/13 20:00:43 knu Exp $ */
-/* $Id: sha2init.c,v 1.2 2002/02/17 12:43:44 nobu Exp $ */
+/* $Id$ */
#include "digest.h"
#include "sha2.h"
@@ -7,18 +7,23 @@
#define FOREACH_BITLEN(func) func(256) func(384) func(512)
#define DEFINE_ALGO_METADATA(bitlen) \
-static algo_t sha##bitlen = { \
+static rb_digest_metadata_t sha##bitlen = { \
+ RUBY_DIGEST_API_VERSION, \
SHA##bitlen##_DIGEST_LENGTH, \
+ SHA##bitlen##_BLOCK_LENGTH, \
sizeof(SHA##bitlen##_CTX), \
- (hash_init_func_t)SHA##bitlen##_Init, \
- (hash_update_func_t)SHA##bitlen##_Update, \
- (hash_end_func_t)SHA##bitlen##_End, \
- (hash_final_func_t)SHA##bitlen##_Final, \
- (hash_equal_func_t)SHA##bitlen##_Equal, \
+ (rb_digest_hash_init_func_t)SHA##bitlen##_Init, \
+ (rb_digest_hash_update_func_t)SHA##bitlen##_Update, \
+ (rb_digest_hash_finish_func_t)SHA##bitlen##_Finish, \
};
FOREACH_BITLEN(DEFINE_ALGO_METADATA)
+/*
+ * Classes for calculating message digests using the SHA-256/384/512
+ * Secure Hash Algorithm(s) by NIST (the US' National Institute of
+ * Standards and Technology), described in FIPS PUB 180-2.
+ */
void
Init_sha2()
{
@@ -30,7 +35,7 @@ Init_sha2()
FOREACH_BITLEN(DECLARE_ALGO_CLASS)
- rb_require("digest.so");
+ rb_require("digest");
id_metadata = rb_intern("metadata");
@@ -40,8 +45,8 @@ Init_sha2()
#define DEFINE_ALGO_CLASS(bitlen) \
cDigest_SHA##bitlen = rb_define_class_under(mDigest, "SHA" #bitlen, cDigest_Base); \
\
- rb_cvar_set(cDigest_SHA##bitlen, id_metadata, \
- Data_Wrap_Struct(rb_cObject, 0, 0, &sha##bitlen), Qtrue);
+ rb_ivar_set(cDigest_SHA##bitlen, id_metadata, \
+ Data_Wrap_Struct(rb_cObject, 0, 0, &sha##bitlen));
FOREACH_BITLEN(DEFINE_ALGO_CLASS)
}
diff --git a/ext/digest/test.sh b/ext/digest/test.sh
index 2ae2688e4d..328c7575e6 100644
--- a/ext/digest/test.sh
+++ b/ext/digest/test.sh
@@ -1,7 +1,7 @@
#!/bin/sh
#
# $RoughId: test.sh,v 1.5 2001/07/13 15:38:27 knu Exp $
-# $Id: test.sh,v 1.2 2002/09/26 17:55:16 knu Exp $
+# $Id$
RUBY=${RUBY:=ruby}
MAKE=${MAKE:=make}
@@ -11,8 +11,6 @@ ${RUBY} extconf.rb --with-cflags="${CFLAGS}"
${MAKE} clean
${MAKE}
-mkdir -p lib/digest
-
for algo in md5 rmd160 sha1 sha2; do
args=--with-cflags="${CFLAGS}"
@@ -27,7 +25,6 @@ for algo in md5 rmd160 sha1 sha2; do
ln -sf ../../$algo/$algo.so lib/digest/
done
-${RUBY} -I. -I./lib test.rb
+${RUBY} -I. -I./lib ../../test/digest/test_digest.rb
rm lib/digest/*.so
-rmdir lib/digest
diff --git a/ext/dl/dl.c b/ext/dl/dl.c
index 71c353bda3..f65247be86 100644
--- a/ext/dl/dl.c
+++ b/ext/dl/dl.c
@@ -1,5 +1,5 @@
/*
- * $Id: dl.c,v 1.20.2.5 2005/12/16 13:32:06 ttate Exp $
+ * $Id$
*/
#include <ruby.h>
@@ -522,12 +522,15 @@ rb_str_to_ptr(VALUE self)
{
char *ptr;
int len;
+ VALUE p;
len = RSTRING(self)->len;
ptr = (char*)dlmalloc(len + 1);
memcpy(ptr, RSTRING(self)->ptr, len);
ptr[len] = '\0';
- return rb_dlptr_new((void*)ptr,len,dlfree);
+ p = rb_dlptr_new((void*)ptr,len,dlfree);
+ OBJ_INFECT(p, self);
+ return p;
}
VALUE
@@ -545,13 +548,18 @@ rb_ary_to_ptr(int argc, VALUE argv[], VALUE self)
ptr = rb_ary2cary(0, self, &size);
break;
}
- return ptr ? rb_dlptr_new(ptr, size, dlfree) : Qnil;
+ if (ptr) {
+ VALUE p = rb_dlptr_new(ptr, size, dlfree);
+ OBJ_INFECT(p, self);
+ return p;
+ }
+ return Qnil;
}
VALUE
rb_io_to_ptr(VALUE self)
{
- OpenFile *fptr;
+ rb_io_t *fptr;
FILE *fp;
GetOpenFile(self, fptr);
@@ -563,7 +571,7 @@ rb_io_to_ptr(VALUE self)
VALUE
rb_dl_dlopen(int argc, VALUE argv[], VALUE self)
{
- rb_secure(4);
+ rb_secure(2);
return rb_class_new_instance(argc, argv, rb_cDLHandle);
}
diff --git a/ext/dl/dl.h b/ext/dl/dl.h
index 9e4e01eea5..1faa316cf1 100644
--- a/ext/dl/dl.h
+++ b/ext/dl/dl.h
@@ -1,5 +1,5 @@
/* -*- C -*-
- * $Id: dl.h,v 1.9 2003/12/01 23:02:44 ttate Exp $
+ * $Id$
*/
#ifndef RUBY_DL_H
diff --git a/ext/dl/h2rb b/ext/dl/h2rb
index d5ebd6ee2c..00fbd60c82 100644
--- a/ext/dl/h2rb
+++ b/ext/dl/h2rb
@@ -1,6 +1,6 @@
#!/usr/bin/env ruby
# -*- ruby -*-
-# $Id: h2rb,v 1.1 2002/04/02 10:56:13 ttate Exp $
+# $Id$
require 'mkmf'
require 'ftools'
diff --git a/ext/dl/handle.c b/ext/dl/handle.c
index 1e8c17e501..69d47caac0 100644
--- a/ext/dl/handle.c
+++ b/ext/dl/handle.c
@@ -1,5 +1,5 @@
/* -*- C -*-
- * $Id: handle.c,v 1.11.2.1 2005/02/28 02:45:17 matz Exp $
+ * $Id$
*/
#include <ruby.h>
@@ -66,12 +66,12 @@ rb_dlhandle_initialize(int argc, VALUE argv[], VALUE self)
ptr = dlopen(clib, cflag);
#if defined(HAVE_DLERROR)
if (!ptr && (err = dlerror())) {
- rb_raise(rb_eRuntimeError, err);
+ rb_raise(rb_eRuntimeError, "%s", err);
}
#else
if (!ptr) {
err = dlerror();
- rb_raise(rb_eRuntimeError, err);
+ rb_raise(rb_eRuntimeError, "%s", err);
}
#endif
Data_Get_Struct(self, struct dl_handle, dlhandle);
diff --git a/ext/dl/lib/dl/import.rb b/ext/dl/lib/dl/import.rb
index 63c9b2c050..01ee2490e8 100644
--- a/ext/dl/lib/dl/import.rb
+++ b/ext/dl/lib/dl/import.rb
@@ -87,7 +87,7 @@ module DL
" rs = dec.call(rs) if (dec && rs)",
" @retval = r",
" @args = rs",
- " @retval",
+ " r",
"}",
].join("\n"))
@@ -169,7 +169,7 @@ module DL
" rs = dec.call(rs) if dec",
" @retval = r",
" @args = rs",
- " return @retval",
+ " return r",
"end",
"module_function :#{mname}",
].join("\n")
diff --git a/ext/dl/ptr.c b/ext/dl/ptr.c
index 5c313fad55..01eb31da20 100644
--- a/ext/dl/ptr.c
+++ b/ext/dl/ptr.c
@@ -1,33 +1,25 @@
/* -*- C -*-
- * $Id: ptr.c,v 1.19.2.1 2006/05/25 16:37:57 ttate Exp $
+ * $Id$
*/
#include <ruby.h>
#include <ctype.h>
-#include <version.h> /* for ruby version code */
+#include "st.h"
#include "dl.h"
VALUE rb_cDLPtrData;
VALUE rb_mDLMemorySpace;
-static VALUE DLMemoryTable;
+static st_table* st_memory_table;
#ifndef T_SYMBOL
# define T_SYMBOL T_FIXNUM
#endif
-#if RUBY_VERSION_CODE < 171
-static VALUE
-rb_hash_delete(VALUE hash, VALUE key)
-{
- return rb_funcall(hash, rb_intern("delete"), 1, key);
-}
-#endif
-
static void
rb_dlmem_delete(void *ptr)
{
rb_secure(4);
- rb_hash_delete(DLMemoryTable, DLLONG2NUM(ptr));
+ st_delete(st_memory_table, (st_data_t*)&ptr, NULL);
}
static void
@@ -37,7 +29,7 @@ rb_dlmem_aset(void *ptr, VALUE obj)
rb_dlmem_delete(ptr);
}
else{
- rb_hash_aset(DLMemoryTable, DLLONG2NUM(ptr), DLLONG2NUM(obj));
+ st_insert(st_memory_table, (st_data_t)ptr, (st_data_t)obj);
}
}
@@ -46,8 +38,8 @@ rb_dlmem_aref(void *ptr)
{
VALUE val;
- val = rb_hash_aref(DLMemoryTable, DLLONG2NUM(ptr));
- return val == Qnil ? Qnil : (VALUE)DLNUM2LONG(val);
+ if(!st_lookup(st_memory_table, (st_data_t)ptr, &val)) return Qnil;
+ return val == Qundef ? Qnil : val;
}
void
@@ -344,7 +336,7 @@ rb_dlptr_to_array(int argc, VALUE argv[], VALUE self)
n = data->size / sizeof(void*);
break;
case 'S': case 's':
- for (n=0; ((void**)(data->ptr))[n]; n++) {};
+ n = data->size / sizeof(char*);
break;
default:
n = 0;
@@ -466,8 +458,9 @@ rb_dlptr_inspect(VALUE self)
char str[1024];
Data_Get_Struct(self, struct ptr_data, data);
- snprintf(str, 1023, "#<%s:0x%p ptr=0x%p size=%ld free=0x%p>",
- rb_class2name(CLASS_OF(self)), data, data->ptr, data->size, data->free);
+ snprintf(str, 1023, "#<%s:0x%lx ptr=0x%lx size=%ld free=0x%lx>",
+ rb_class2name(CLASS_OF(self)), data, data->ptr, data->size,
+ (long)data->free);
return rb_str_new2(str);
}
@@ -1009,20 +1002,18 @@ rb_dlptr_size(int argc, VALUE argv[], VALUE self)
}
}
-static VALUE
-dlmem_each_i(VALUE assoc, void *data)
+static int
+dlmem_each_i(void* key, VALUE value, void* arg)
{
- VALUE key, val;
- key = rb_ary_entry(assoc, 0);
- val = rb_ary_entry(assoc, 1);
- rb_yield(rb_assoc_new(key,(VALUE)DLNUM2LONG(val)));
+ VALUE vkey = DLLONG2NUM(key);
+ rb_yield(rb_assoc_new(vkey, value));
return Qnil;
}
VALUE
rb_dlmem_each(VALUE self)
{
- rb_iterate(rb_each, DLMemoryTable, dlmem_each_i, 0);
+ st_foreach(st_memory_table, dlmem_each_i, 0);
return Qnil;
}
@@ -1061,7 +1052,7 @@ Init_dlptr()
rb_define_method(rb_cDLPtrData, "size=", rb_dlptr_size, -1);
rb_mDLMemorySpace = rb_define_module_under(rb_mDL, "MemorySpace");
- DLMemoryTable = rb_hash_new();
- rb_define_const(rb_mDLMemorySpace, "MemoryTable", DLMemoryTable);
+ st_memory_table = st_init_numtable();
+ rb_define_const(rb_mDLMemorySpace, "MemoryTable", Qnil); /* historical */
rb_define_module_function(rb_mDLMemorySpace, "each", rb_dlmem_each, 0);
}
diff --git a/ext/dl/sym.c b/ext/dl/sym.c
index 6e4337c0b7..933fb7f4f0 100644
--- a/ext/dl/sym.c
+++ b/ext/dl/sym.c
@@ -1,5 +1,5 @@
/* -*- C -*-
- * $Id: sym.c,v 1.24.2.3 2005/06/15 23:39:27 ocean Exp $
+ * $Id$
*/
#include <ruby.h>
@@ -268,7 +268,7 @@ rb_dlsym_inspect(VALUE self)
str_size = RSTRING(proto)->len + 100;
str = dlmalloc(str_size);
snprintf(str, str_size - 1,
- "#<DL::Symbol:0x%p func=0x%p '%s'>",
+ "#<DL::Symbol:0x%lx func=0x%lx '%s'>",
sym, sym->func, RSTRING(proto)->ptr);
val = rb_tainted_str_new2(str);
dlfree(str);
@@ -492,6 +492,7 @@ rb_dlsym_call(int argc, VALUE argv[], VALUE self)
rb_raise(rb_eDLTypeError, "unexpected type of argument #%d", i);
}
}
+ rb_check_safe_obj(pval);
Data_Get_Struct(pval, struct ptr_data, data);
ANY2P(args[i]) = DLVOIDP(data->ptr);
}
diff --git a/ext/enumerator/enumerator.c b/ext/enumerator/enumerator.c
deleted file mode 100644
index 7b8f109e38..0000000000
--- a/ext/enumerator/enumerator.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/************************************************
-
- enumerator.c - provides Enumerator class
-
- $Author: matz $
-
- Copyright (C) 2001-2003 Akinori MUSHA
-
- $Idaemons: /home/cvs/rb/enumerator/enumerator.c,v 1.1.1.1 2001/07/15 10:12:48 knu Exp $
- $RoughId: enumerator.c,v 1.6 2003/07/27 11:03:24 nobu Exp $
- $Id: enumerator.c,v 1.3.2.3 2005/10/24 00:07:00 matz Exp $
-
-************************************************/
-
-#include "ruby.h"
-#include "node.h"
-
-/*
- * Document-class: Enumerable::Enumerator
- *
- * A class which provides a method `each' to be used as an Enumerable
- * object.
- */
-static VALUE rb_cEnumerator;
-static ID sym_each, sym_each_with_index, sym_each_slice, sym_each_cons;
-static ID id_new, id_enum_obj, id_enum_method, id_enum_args;
-
-/*
- * call-seq:
- * obj.to_enum(method = :each, *args)
- * obj.enum_for(method = :each, *args)
- *
- * Returns Enumerable::Enumerator.new(self, method, *args).
- *
- * e.g.:
- * str = "xyz"
- *
- * enum = str.enum_for(:each_byte)
- * a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
- *
- * # protects an array from being modified
- * a = [1, 2, 3]
- * some_method(a.to_enum)
- *
- */
-static VALUE
-obj_to_enum(obj, enum_args)
- VALUE obj, enum_args;
-{
- rb_ary_unshift(enum_args, obj);
-
- return rb_apply(rb_cEnumerator, id_new, enum_args);
-}
-
-/*
- * call-seq:
- * enum_with_index
- *
- * Returns Enumerable::Enumerator.new(self, :each_with_index).
- *
- */
-static VALUE
-enumerator_enum_with_index(obj)
- VALUE obj;
-{
- return rb_funcall(rb_cEnumerator, id_new, 2, obj, sym_each_with_index);
-}
-
-static VALUE
-each_slice_i(val, memo)
- VALUE val;
- NODE *memo;
-{
- VALUE ary = memo->u1.value;
- long size = memo->u3.cnt;
-
- rb_ary_push(ary, val);
-
- if (RARRAY(ary)->len == size) {
- rb_yield(ary);
- memo->u1.value = rb_ary_new2(size);
- }
-
- return Qnil;
-}
-
-/*
- * call-seq:
- * e.each_slice(n) {...}
- *
- * Iterates the given block for each slice of <n> elements.
- *
- * e.g.:
- * (1..10).each_slice(3) {|a| p a}
- * # outputs below
- * [1, 2, 3]
- * [4, 5, 6]
- * [7, 8, 9]
- * [10]
- *
- */
-static VALUE
-enum_each_slice(obj, n)
- VALUE obj, n;
-{
- long size = NUM2LONG(n);
- NODE *memo;
- VALUE ary;
-
- if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
-
- memo = rb_node_newnode(NODE_MEMO, rb_ary_new2(size), 0, size);
-
- rb_iterate(rb_each, obj, each_slice_i, (VALUE)memo);
-
- ary = memo->u1.value;
- if (RARRAY(ary)->len > 0) rb_yield(ary);
-
- return Qnil;
-}
-
-/*
- * call-seq:
- * e.enum_slice(n)
- *
- * Returns Enumerable::Enumerator.new(self, :each_slice, n).
- *
- */
-static VALUE
-enumerator_enum_slice(obj, n)
- VALUE obj, n;
-{
- return rb_funcall(rb_cEnumerator, id_new, 3, obj, sym_each_slice, n);
-}
-
-static VALUE
-each_cons_i(val, memo)
- VALUE val;
- NODE *memo;
-{
- VALUE ary = memo->u1.value;
- long size = memo->u3.cnt;
-
- if (RARRAY(ary)->len == size) {
- rb_ary_shift(ary);
- }
- rb_ary_push(ary, val);
- if (RARRAY(ary)->len == size) {
- rb_yield(rb_ary_dup(ary));
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * each_cons(n) {...}
- *
- * Iterates the given block for each array of consecutive <n>
- * elements.
- *
- * e.g.:
- * (1..10).each_cons(3) {|a| p a}
- * # outputs below
- * [1, 2, 3]
- * [2, 3, 4]
- * [3, 4, 5]
- * [4, 5, 6]
- * [5, 6, 7]
- * [6, 7, 8]
- * [7, 8, 9]
- * [8, 9, 10]
- *
- */
-static VALUE
-enum_each_cons(obj, n)
- VALUE obj, n;
-{
- long size = NUM2LONG(n);
- NODE *memo;
-
- if (size <= 0) rb_raise(rb_eArgError, "invalid size");
- memo = rb_node_newnode(NODE_MEMO, rb_ary_new2(size), 0, size);
-
- rb_iterate(rb_each, obj, each_cons_i, (VALUE)memo);
-
- return Qnil;
-}
-
-/*
- * call-seq:
- * e.enum_cons(n)
- *
- * Returns Enumerable::Enumerator.new(self, :each_cons, n).
- *
- */
-static VALUE
-enumerator_enum_cons(obj, n)
- VALUE obj, n;
-{
- return rb_funcall(rb_cEnumerator, id_new, 3, obj, sym_each_cons, n);
-}
-
-/*
- * call-seq:
- * Enumerable::Enumerator.new(obj, method = :each, *args)
- *
- * Creates a new Enumerable::Enumerator object, which is to be
- * used as an Enumerable object using the given object's given
- * method with the given arguments.
- *
- * e.g.:
- * str = "xyz"
- *
- * enum = Enumerable::Enumerator.new(str, :each_byte)
- * a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
- *
- */
-static VALUE
-enumerator_initialize(argc, argv, obj)
- int argc;
- VALUE *argv;
- VALUE obj;
-{
- VALUE enum_obj, enum_method, enum_args;
-
- rb_scan_args(argc, argv, "11*", &enum_obj, &enum_method, &enum_args);
-
- if (enum_method == Qnil)
- enum_method = sym_each;
-
- rb_ivar_set(obj, id_enum_obj, enum_obj);
- rb_ivar_set(obj, id_enum_method, enum_method);
- rb_ivar_set(obj, id_enum_args, enum_args);
-
- return Qnil;
-}
-
-static VALUE
-enumerator_iter(memo)
- NODE *memo;
-{
- return rb_apply(memo->u1.value, memo->u2.id, memo->u3.value);
-}
-
-/*
- * call-seq:
- * enum.each {...}
- *
- * Iterates the given block using the object and the method specified
- * in the first place.
- *
- */
-static VALUE
-enumerator_each(obj)
- VALUE obj;
-{
- VALUE val;
-
- obj = (VALUE)rb_node_newnode(NODE_MEMO,
- rb_ivar_get(obj, id_enum_obj),
- rb_to_id(rb_ivar_get(obj, id_enum_method)),
- rb_ivar_get(obj, id_enum_args));
- val = rb_iterate((VALUE (*)_((VALUE)))enumerator_iter, obj, rb_yield, 0);
- return val;
-}
-
-void
-Init_enumerator()
-{
- VALUE rb_mEnumerable;
-
- rb_define_method(rb_mKernel, "to_enum", obj_to_enum, -2);
- rb_define_method(rb_mKernel, "enum_for", obj_to_enum, -2);
-
- rb_mEnumerable = rb_path2class("Enumerable");
-
- rb_define_method(rb_mEnumerable, "enum_with_index", enumerator_enum_with_index, 0);
- rb_define_method(rb_mEnumerable, "each_slice", enum_each_slice, 1);
- rb_define_method(rb_mEnumerable, "enum_slice", enumerator_enum_slice, 1);
- rb_define_method(rb_mEnumerable, "each_cons", enum_each_cons, 1);
- rb_define_method(rb_mEnumerable, "enum_cons", enumerator_enum_cons, 1);
-
- rb_cEnumerator = rb_define_class_under(rb_mEnumerable, "Enumerator", rb_cObject);
- rb_include_module(rb_cEnumerator, rb_mEnumerable);
-
- rb_define_method(rb_cEnumerator, "initialize", enumerator_initialize, -1);
- rb_define_method(rb_cEnumerator, "each", enumerator_each, 0);
-
- sym_each = ID2SYM(rb_intern("each"));
- sym_each_with_index = ID2SYM(rb_intern("each_with_index"));
- sym_each_slice = ID2SYM(rb_intern("each_slice"));
- sym_each_cons = ID2SYM(rb_intern("each_cons"));
-
- id_new = rb_intern("new");
- id_enum_obj = rb_intern("enum_obj");
- id_enum_method = rb_intern("enum_method");
- id_enum_args = rb_intern("enum_args");
-}
diff --git a/ext/enumerator/enumerator.txt b/ext/enumerator/enumerator.txt
deleted file mode 100644
index 1b84c0c088..0000000000
--- a/ext/enumerator/enumerator.txt
+++ /dev/null
@@ -1,102 +0,0 @@
-.\" enumerator.txt - -*- Indented-Text -*-
-$Idaemons: /home/cvs/rb/enumerator/enumerator.txt,v 1.2 2001/07/15 10:19:24 knu Exp $
-$RoughId: enumerator.txt,v 1.5 2003/02/20 12:24:51 knu Exp $
-$Id: enumerator.txt,v 1.2 2003/10/17 14:09:43 knu Exp $
-
-** Enumerable::Enumerator(Class)
-
-A class which provides a method `each' to be used as an Enumerable
-object.
-
-Superclass: Object
-
-Mix-ins: Enumerable
-
-require 'enumerator'
-
-Class Methods:
-
- new(obj, method = :each, *args)
-
- Creates a new Enumerable::Enumerator object, which is to be
- used as an Enumerable object using the given object's given
- method with the given arguments.
-
- e.g.:
- str = "xyz"
-
- enum = Enumerable::Enumerator.new(str, :each_byte)
- a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
-
-Methods:
-
- each {...}
-
- Iterates the given block using the object and the method
- specified in the first place.
-
-
-Requiring this module also adds some methods to the Object class:
-
- to_enum(method = :each, *args)
- enum_for(method = :each, *args)
-
- Returns Enumerable::Enumerator.new(self, method, *args).
-
- e.g.:
- str = "xyz"
-
- enum = str.enum_for(:each_byte)
- a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
-
- # protects an array from being modified
- a = [1, 2, 3]
- some_method(a.to_enum)
-
-And the Enumerable module.
-
- each_slice(n) {...}
-
- Iterates the given block for each slice of <n> elements.
-
- e.g.:
- (1..10).each_slice(3) {|a| p a}
- # outputs below
- [1, 2, 3]
- [4, 5, 6]
- [7, 8, 9]
- [10]
-
- enum_slice(n)
-
- Returns Enumerable::Enumerator.new(self, :each_slice, n).
-
- each_cons(n) {...}
-
- Iterates the given block for each array of consecutive <n>
- elements.
-
- e.g.:
- (1..10).each_cons(3) {|a| p a}
- # outputs below
- [1, 2, 3]
- [2, 3, 4]
- [3, 4, 5]
- [4, 5, 6]
- [5, 6, 7]
- [6, 7, 8]
- [7, 8, 9]
- [8, 9, 10]
-
- enum_cons(n)
-
- Returns Enumerable::Enumerator.new(self, :each_cons, n).
-
- enum_with_index
-
- Returns Enumerable::Enumerator.new(self, :each_with_index).
-
--------------------------------------------------------
-Local variables:
-fill-column: 70
-end:
diff --git a/ext/enumerator/extconf.rb b/ext/enumerator/extconf.rb
deleted file mode 100644
index 94e2ee38b2..0000000000
--- a/ext/enumerator/extconf.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require 'mkmf'
-create_makefile('enumerator')
diff --git a/ext/etc/etc.c b/ext/etc/etc.c
index 084405408f..ecb9e16411 100644
--- a/ext/etc/etc.c
+++ b/ext/etc/etc.c
@@ -2,8 +2,8 @@
etc.c -
- $Author: shyouhei $
- $Date: 2007/01/09 12:24:20 $
+ $Author$
+ $Date$
created at: Tue Mar 22 18:39:19 JST 1994
************************************************/
@@ -35,6 +35,8 @@ char *getenv();
char *getlogin();
/* Returns the short user name of the currently logged in user.
+ * Unfortunately, it is often rather easy to fool getlogin().
+ * Avoid getlogin() for security-related purposes.
*
* e.g.
* Etc.getlogin -> 'guest'
diff --git a/ext/extmk.rb b/ext/extmk.rb
index bbcb3c09b8..64746552c1 100644
--- a/ext/extmk.rb
+++ b/ext/extmk.rb
@@ -1,13 +1,19 @@
#! /usr/local/bin/ruby
# -*- ruby -*-
+$extension = nil
+$extstatic = nil
$force_static = nil
$install = nil
$destdir = nil
+$dryrun = false
$clean = nil
$nodynamic = nil
$extinit = nil
$extobjs = nil
+$extflags = ""
+$extlibs = nil
+$extpath = nil
$ignore = nil
$message = nil
@@ -73,12 +79,14 @@ def extract_makefile(makefile, keep = true)
$static ||= m[/^EXTSTATIC[ \t]*=[ \t]*(\S+)/, 1] || false
/^STATIC_LIB[ \t]*=[ \t]*\S+/ =~ m or $static = nil
$preload = Shellwords.shellwords(m[/^preload[ \t]*=[ \t]*(.*)/, 1] || "")
- $DLDFLAGS += " " + (m[/^DLDFLAGS[ \t]*=[ \t]*(.*)/, 1] || "")
+ $DLDFLAGS += " " + (m[/^dldflags[ \t]*=[ \t]*(.*)/, 1] || "")
if s = m[/^LIBS[ \t]*=[ \t]*(.*)/, 1]
s.sub!(/^#{Regexp.quote($LIBRUBYARG)} */, "")
s.sub!(/ *#{Regexp.quote($LIBS)}$/, "")
$libs = s
end
+ $objs = (m[/^OBJS[ \t]*=[ \t](.*)/, 1] || "").split
+ $srcs = (m[/^SRCS[ \t]*=[ \t](.*)/, 1] || "").split
$LOCAL_LIBS = m[/^LOCAL_LIBS[ \t]*=[ \t]*(.*)/, 1] || ""
$LIBPATH = Shellwords.shellwords(m[/^libpath[ \t]*=[ \t]*(.*)/, 1] || "") - %w[$(libdir) $(topdir)]
true
@@ -104,31 +112,51 @@ def extmake(target)
Dir.chdir target
top_srcdir = $top_srcdir
topdir = $topdir
- mk_srcdir = CONFIG["srcdir"]
- mk_topdir = CONFIG["topdir"]
+ hdrdir = $hdrdir
prefix = "../" * (target.count("/")+1)
- $hdrdir = $top_srcdir = relative_from(top_srcdir, prefix)
+ $top_srcdir = relative_from(top_srcdir, prefix)
+ $hdrdir = relative_from(hdrdir, prefix)
$topdir = prefix + $topdir
$target = target
$mdir = target
$srcdir = File.join($top_srcdir, "ext", $mdir)
$preload = nil
+ $objs = ""
+ $srcs = ""
$compiled[target] = false
makefile = "./Makefile"
ok = File.exist?(makefile)
unless $ignore
- Config::CONFIG["hdrdir"] = $hdrdir
- Config::CONFIG["srcdir"] = $srcdir
- Config::CONFIG["topdir"] = $topdir
- CONFIG["hdrdir"] = ($hdrdir == top_srcdir) ? top_srcdir : "$(topdir)"+top_srcdir[2..-1]
- CONFIG["srcdir"] = "$(hdrdir)/ext/#{$mdir}"
- CONFIG["topdir"] = $topdir
+ rbconfig0 = Config::CONFIG
+ mkconfig0 = CONFIG
+ rbconfig = {
+ "hdrdir" => $hdrdir,
+ "srcdir" => $srcdir,
+ "topdir" => $topdir,
+ }
+ mkconfig = {
+ "hdrdir" => "$(top_srcdir)",
+ "srcdir" => "$(top_srcdir)/ext/#{$mdir}",
+ "topdir" => $topdir,
+ }
+ rbconfig0.each_pair {|key, val| rbconfig[key] ||= val.dup}
+ mkconfig0.each_pair {|key, val| mkconfig[key] ||= val.dup}
+ Config.module_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, rbconfig)
+ remove_const(:MAKEFILE_CONFIG)
+ const_set(:MAKEFILE_CONFIG, mkconfig)
+ }
+ Object.class_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, mkconfig)
+ }
begin
$extconf_h = nil
ok &&= extract_makefile(makefile)
if (($extconf_h && !File.exist?($extconf_h)) ||
!(t = modified?(makefile, MTIMES)) ||
- %W"#{$srcdir}/makefile.rb #{$srcdir}/extconf.rb #{$srcdir}/depend".any? {|f| modified?(f, [t])})
+ ["#{$srcdir}/makefile.rb", "#{$srcdir}/extconf.rb", "#{$srcdir}/depend"].any? {|f| modified?(f, [t])})
then
ok = false
init_mkmf
@@ -171,7 +199,11 @@ def extmake(target)
$ignore or $continue or return false
end
$compiled[target] = true
- if $clean and $clean != true
+ if $clean
+ FileUtils.rm_f("mkmf.log")
+ if $clean != true
+ FileUtils.rm_f([makefile, $extconf_h || "extconf.h"])
+ end
File.unlink(makefile) rescue nil
end
if $static
@@ -185,13 +217,21 @@ def extmake(target)
$extpath |= $LIBPATH
end
ensure
- Config::CONFIG["srcdir"] = $top_srcdir
- Config::CONFIG["topdir"] = topdir
- CONFIG["srcdir"] = mk_srcdir
- CONFIG["topdir"] = mk_topdir
- CONFIG.delete("hdrdir")
- $hdrdir = $top_srcdir = top_srcdir
+ unless $ignore
+ Config.module_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, rbconfig0)
+ remove_const(:MAKEFILE_CONFIG)
+ const_set(:MAKEFILE_CONFIG, mkconfig0)
+ }
+ Object.class_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, mkconfig0)
+ }
+ end
+ $top_srcdir = top_srcdir
$topdir = topdir
+ $hdrdir = hdrdir
Dir.chdir dir
end
begin
@@ -258,7 +298,7 @@ def parse_args()
$mflags.unshift(*rest) unless rest.empty?
def $mflags.set?(flag)
- grep(/\A-(?!-).*#{'%c' % flag}/i) { return true }
+ grep(/\A-(?!-).*#{flag.chr}/i) { return true }
false
end
def $mflags.defined?(var)
@@ -275,6 +315,7 @@ def parse_args()
$continue = $mflags.set?(?k)
if $extout
$extout = '$(topdir)/'+$extout
+ Config::CONFIG["extout"] = CONFIG["extout"] = $extout
$extout_prefix = $extout ? "$(extout)$(target_prefix)/" : ""
$mflags << "extout=#$extout" << "extout_prefix=#$extout_prefix"
end
@@ -284,9 +325,9 @@ parse_args()
if target = ARGV.shift and /^[a-z-]+$/ =~ target
$mflags.push(target)
- target = target.sub(/^(dist|real)(?=(?:clean)?$)/, '')
case target
- when /clean/
+ when /^(dist|real)?(clean)$/
+ target = $2
$ignore ||= true
$clean = $1 ? $1[0] : true
when /^install\b/
@@ -313,8 +354,16 @@ elsif sep = config_string('BUILD_FILE_SEPARATOR')
else
$ruby = '$(topdir)/miniruby' + EXEEXT
end
-$ruby << " -I'$(topdir)' -I'$(hdrdir)/lib'"
+$ruby << " -I'$(topdir)'"
+unless CROSS_COMPILING
+ $ruby << " -I'$(top_srcdir)/lib'"
+ $ruby << " -I'$(extout)/$(arch)' -I'$(extout)/common'" if $extout
+ $ruby << " -I./- -I'$(top_srcdir)/ext' -rpurelib.rb"
+ ENV["RUBYLIB"] = "-"
+ ENV["RUBYOPT"] = "-rpurelib.rb"
+end
$config_h = '$(topdir)/config.h'
+$mflags << "ruby=#$ruby"
MTIMES = [__FILE__, 'rbconfig.rb', srcdir+'/lib/mkmf.rb'].collect {|f| File.mtime(f)}
@@ -363,12 +412,12 @@ else
elsif (w = w.grep(String)).empty?
proc {true}
else
- w.collect {|opt| opt.split(/,/)}.flatten.method(:any?)
+ proc {|c1| w.collect {|opt| opt.split(/,/)}.flatten.any?(&c1)}
end
}
cond = proc {|ext|
cond1 = proc {|n| File.fnmatch(n, ext, File::FNM_PATHNAME)}
- withes.call(&cond1) or !withouts.call(&cond1)
+ withes.call(cond1) or !withouts.call(cond1)
}
exts |= Dir.glob("#{ext_prefix}/*/**/extconf.rb").collect {|d|
d = File.dirname(d)
@@ -380,15 +429,7 @@ else
end
if $extout
- Config.expand(extout = "#$extout", Config::CONFIG.merge("topdir"=>$topdir))
- if $install
- dest = Config.expand($rubylibdir.dup)
- unless $destdir.empty?
- dest.sub!($dest_prefix_pattern, Config.expand($destdir.dup))
- end
- FileUtils.cp_r(extout+"/.", dest, :verbose => true, :noop => $dryrun)
- exit
- end
+ extout = Config.expand("#{$extout}", Config::CONFIG.merge("topdir"=>$topdir))
unless $ignore
FileUtils.mkpath(extout)
end
@@ -398,12 +439,14 @@ dir = Dir.pwd
FileUtils::makedirs('ext')
Dir::chdir('ext')
+hdrdir = $hdrdir
$hdrdir = $top_srcdir = relative_from(srcdir, $topdir = "..")
exts.each do |d|
extmake(d) or abort
end
-$hdrdir = $top_srcdir = srcdir
+$top_srcdir = srcdir
$topdir = "."
+$hdrdir = hdrdir
extinit = Struct.new(:c, :o) {
def initialize(src)
@@ -415,14 +458,27 @@ if $ignore
Dir.chdir ".."
if $clean
Dir.rmdir('ext') rescue nil
- FileUtils.rm_rf(extout) if $extout
+ if $extout
+ FileUtils.rm_rf([extout+"/common", extout+"/include/ruby", extout+"/rdoc"])
+ FileUtils.rm_rf(extout+"/"+CONFIG["arch"])
+ if $clean != true
+ FileUtils.rm_rf(extout+"/include/"+CONFIG["arch"])
+ FileUtils.rm_f($mflags.defined?("INSTALLED_LIST")||ENV["INSTALLED_LIST"]||".installed.list")
+ Dir.rmdir(extout+"/include") rescue nil
+ Dir.rmdir(extout) rescue nil
+ end
+ end
end
exit
end
-if $extlist.size > 0
- $extinit ||= ""
- $extobjs ||= ""
+$extinit ||= ""
+$extobjs ||= ""
+$extpath ||= []
+$extflags ||= ""
+$extlibs ||= []
+unless $extlist.empty?
+ $extinit << "\n" unless $extinit.empty?
list = $extlist.dup
built = []
while e = list.shift
@@ -436,28 +492,33 @@ if $extlist.size > 0
end
f = format("%s/%s.%s", s, i, $LIBEXT)
if File.exist?(f)
- $extinit += "\tinit(Init_#{i}, \"#{t}.so\");\n"
- $extobjs += "ext/#{f} "
+ $extinit << " init(Init_#{i}, \"#{t}.so\");\n"
+ $extobjs << "ext/#{f} "
built << t
end
end
src = %{\
-extern char *ruby_sourcefile, *rb_source_filename();
-#define init(func, name) (ruby_sourcefile = src = rb_source_filename(name), func(), rb_provide(src))
-void Init_ext() {\n\tchar* src;\n#$extinit}
+#include "ruby.h"
+
+#define init(func, name) {void func _((void)); ruby_init_ext(name, func);}
+
+void ruby_init_ext _((const char *name, void (*init)(void)));
+
+void Init_ext _((void))\n{\n#$extinit}
}
if !modified?(extinit.c, MTIMES) || IO.read(extinit.c) != src
open(extinit.c, "w") {|f| f.print src}
end
- $extobjs = "ext/#{extinit.o} " + $extobjs
+ $extobjs = "ext/#{extinit.o} #{$extobjs}"
if RUBY_PLATFORM =~ /m68k-human|beos/
$extflags.delete("-L/usr/local/lib")
end
$extpath.delete("$(topdir)")
$extflags = libpathflag($extpath) << " " << $extflags.strip
conf = [
+ ['LIBRUBY_SO_UPDATE', '$(LIBRUBY_EXTS)'],
['SETUP', $setup],
[enable_config("shared", $enable_shared) ? 'DLDOBJS' : 'EXTOBJS', $extobjs],
['EXTLIBS', $extlibs.join(' ')], ['EXTLDFLAGS', $extflags]
@@ -474,7 +535,7 @@ rubies = []
%w[RUBY RUBYW STATIC_RUBY].each {|r|
n = r
if r = arg_config("--"+r.downcase) || config_string(r+"_INSTALL_NAME")
- rubies << r+EXEEXT
+ rubies << Config.expand(r+=EXEEXT)
$mflags << "#{n}=#{r}"
end
}
@@ -483,15 +544,21 @@ Dir.chdir ".."
unless $destdir.to_s.empty?
$mflags.defined?("DESTDIR") or $mflags << "DESTDIR=#{$destdir}"
end
-unless $extlist.empty?
- rm_f(Config::CONFIG["LIBRUBY_SO"])
-end
puts "making #{rubies.join(', ')}"
$stdout.flush
$mflags.concat(rubies)
if $nmake == ?b
- $mflags.collect {|flag| flag.sub!(/\A(?=\w+=)/, "-D")}
+ unless (vars = $mflags.grep(/\A\w+=/n)).empty?
+ open(mkf = "libruby.mk", "wb") do |tmf|
+ tmf.puts("!include Makefile")
+ tmf.puts
+ tmf.puts(*vars.map {|v| v.sub(/=/, " = ")})
+ tmf.puts("PRE_LIBRUBY_UPDATE = del #{mkf}")
+ end
+ $mflags.unshift("-f#{mkf}")
+ vars.each {|flag| flag.sub!(/\A/, "-D")}
+ end
end
system($make, *sysquote($mflags)) or exit($?.exitstatus)
diff --git a/ext/fcntl/fcntl.c b/ext/fcntl/fcntl.c
index 8f9cb43d0c..57cca103f4 100644
--- a/ext/fcntl/fcntl.c
+++ b/ext/fcntl/fcntl.c
@@ -2,7 +2,7 @@
fcntl.c -
- $Author: matz $
+ $Author$
created at: Mon Apr 7 18:53:05 JST 1997
Copyright (C) 1997-2001 Yukihiro Matsumoto
diff --git a/ext/gdbm/gdbm.c b/ext/gdbm/gdbm.c
index 691d512460..82109fda90 100644
--- a/ext/gdbm/gdbm.c
+++ b/ext/gdbm/gdbm.c
@@ -2,10 +2,12 @@
gdbm.c -
- $Author: usa $
- $Date: 2005/06/20 07:53:20 $
+ $Author$
+ $Date$
modified at: Mon Jan 24 15:59:52 JST 1994
+ Documentation by Peter Adolphs < futzilogik at users dot sourceforge dot net >
+
************************************************/
#include "ruby.h"
@@ -14,6 +16,62 @@
#include <fcntl.h>
#include <errno.h>
+/*
+ * Document-class: GDBM
+ *
+ * == Summary
+ *
+ * Ruby extension for GNU dbm (gdbm) -- a simple database engine for storing
+ * key-value pairs on disk.
+ *
+ * == Description
+ *
+ * GNU dbm is a library for simple databases. A database is a file that stores
+ * key-value pairs. Gdbm allows the user to store, retrieve, and delete data by
+ * key. It furthermore allows a non-sorted traversal of all key-value pairs.
+ * A gdbm database thus provides the same functionality as a hash. As
+ * with objects of the Hash class, elements can be accessed with <tt>[]</tt>.
+ * Furthermore, GDBM mixes in the Enumerable module, thus providing convenient
+ * methods such as #find, #collect, #map, etc.
+ *
+ * A process is allowed to open several different databases at the same time.
+ * A process can open a database as a "reader" or a "writer". Whereas a reader
+ * has only read-access to the database, a writer has read- and write-access.
+ * A database can be accessed either by any number of readers or by exactly one
+ * writer at the same time.
+ *
+ * == Examples
+ *
+ * 1. Opening/creating a database, and filling it with some entries:
+ *
+ * require 'gdbm'
+ *
+ * gdbm = GDBM.new("fruitstore.db")
+ * gdbm["ananas"] = "3"
+ * gdbm["banana"] = "8"
+ * gdbm["cranberry"] = "4909"
+ * gdbm.close
+ *
+ * 2. Reading out a database:
+ *
+ * require 'gdbm'
+ *
+ * gdbm = GDBM.new("fruitstore.db")
+ * gdbm.each_pair do |key, value|
+ * print "#{key}: #{value}\n"
+ * end
+ * gdbm.close
+ *
+ * produces
+ *
+ * banana: 8
+ * ananas: 3
+ * cranberry: 4909
+ *
+ * == Links
+ *
+ * * http://www.gnu.org/software/gdbm/
+ */
static VALUE rb_cGDBM, rb_eGDBMError, rb_eGDBMFatalError;
#define RUBY_GDBM_RW_BIT 0x20000000
@@ -24,7 +82,7 @@ static void
rb_gdbm_fatal(msg)
char *msg;
{
- rb_raise(rb_eGDBMFatalError, msg);
+ rb_raise(rb_eGDBMFatalError, "%s", msg);
}
struct dbmdata {
@@ -54,11 +112,17 @@ free_dbm(dbmp)
struct dbmdata *dbmp;
{
if (dbmp) {
- if (dbmp->di_dbm) gdbm_close(dbmp->di_dbm);
- free(dbmp);
+ if (dbmp->di_dbm) gdbm_close(dbmp->di_dbm);
+ free(dbmp);
}
}
+/*
+ * call-seq:
+ * gdbm.close -> nil
+ *
+ * Closes the associated database file.
+ */
static VALUE
fgdbm_close(obj)
VALUE obj;
@@ -72,6 +136,12 @@ fgdbm_close(obj)
return Qnil;
}
+/*
+ * call-seq:
+ * gdbm.closed? -> true or false
+ *
+ * Returns true if the associated database file has been closed.
+ */
static VALUE
fgdbm_closed(obj)
VALUE obj;
@@ -80,9 +150,9 @@ fgdbm_closed(obj)
Data_Get_Struct(obj, struct dbmdata, dbmp);
if (dbmp == 0)
- return Qtrue;
+ return Qtrue;
if (dbmp->di_dbm == 0)
- return Qtrue;
+ return Qtrue;
return Qfalse;
}
@@ -96,6 +166,29 @@ fgdbm_s_alloc(klass)
return Data_Wrap_Struct(klass, 0, free_dbm, 0);
}
+/*
+ * call-seq:
+ * GDBM.new(filename, mode = 0666, flags = nil)
+ *
+ * Creates a new GDBM instance by opening a gdbm file named _filename_.
+ * If the file does not exist, a new file with file mode _mode_ will be
+ * created. _flags_ may be one of the following:
+ * * *READER* - open as a reader
+ * * *WRITER* - open as a writer
+ * * *WRCREAT* - open as a writer; if the database does not exist, create a new one
+ * * *NEWDB* - open as a writer; overwrite any existing databases
+ *
+ * The values *WRITER*, *WRCREAT* and *NEWDB* may be combined with the following
+ * values by bitwise or:
+ * * *SYNC* - cause all database operations to be synchronized to the disk
+ * * *NOLOCK* - do not lock the database file
+ *
+ * If no _flags_ are specified, the GDBM object will try to open the database
+ * file as a writer and will create it if it does not already exist
+ * (cf. flag <tt>WRCREAT</tt>). If this fails (for instance, if another process
+ * has already opened the database as a reader), it will try to open the
+ * database file as a reader (cf. flag <tt>READER</tt>).
+ */
static VALUE
fgdbm_initialize(argc, argv, obj)
int argc;
@@ -108,13 +201,13 @@ fgdbm_initialize(argc, argv, obj)
int mode, flags = 0;
if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) {
- mode = 0666; /* default value */
+ mode = 0666; /* default value */
}
else if (NIL_P(vmode)) {
- mode = -1; /* return nil if DB not exist */
+ mode = -1; /* return nil if DB does not exist */
}
else {
- mode = NUM2INT(vmode);
+ mode = NUM2INT(vmode);
}
if (!NIL_P(vflags))
@@ -160,6 +253,25 @@ fgdbm_initialize(argc, argv, obj)
return obj;
}
+/*
+ * call-seq:
+ * GDBM.open(filename, mode = 0666, flags = nil)
+ * GDBM.open(filename, mode = 0666, flags = nil) { |gdbm| ... }
+ *
+ * If called without a block, this is synonymous to GDBM::new.
+ * If a block is given, the new GDBM instance will be passed to the block
+ * as a parameter, and the corresponding database file will be closed
+ * after the execution of the block code has been finished.
+ *
+ * Example for an open call with a block:
+ *
+ * require 'gdbm'
+ * GDBM.open("fruitstore.db") do |gdbm|
+ * gdbm.each_pair do |key, value|
+ * print "#{key}: #{value}\n"
+ * end
+ * end
+ */
static VALUE
fgdbm_s_open(argc, argv, klass)
int argc;
@@ -286,6 +398,12 @@ fgdbm_fetch(obj, keystr, ifnone)
return valstr;
}
+/*
+ * call-seq:
+ * gdbm[key] -> value
+ *
+ * Retrieves the _value_ corresponding to _key_.
+ */
static VALUE
fgdbm_aref(obj, keystr)
VALUE obj, keystr;
@@ -293,6 +411,13 @@ fgdbm_aref(obj, keystr)
return rb_gdbm_fetch3(obj, keystr);
}
+/*
+ * call-seq:
+ * gdbm.fetch(key [, default]) -> value
+ *
+ * Retrieves the _value_ corresponding to _key_. If there is no value
+ * associated with _key_, _default_ will be returned instead.
+ */
static VALUE
fgdbm_fetch_m(argc, argv, obj)
int argc;
@@ -304,11 +429,18 @@ fgdbm_fetch_m(argc, argv, obj)
rb_scan_args(argc, argv, "11", &keystr, &ifnone);
valstr = fgdbm_fetch(obj, keystr, ifnone);
if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
- rb_raise(rb_eIndexError, "key not found");
+ rb_raise(rb_eIndexError, "key not found");
return valstr;
}
+/*
+ * call-seq:
+ * gdbm.index(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(obj, valstr)
VALUE obj, valstr;
@@ -350,6 +482,13 @@ fgdbm_indexes(argc, argv, obj)
return new;
}
+/*
+ * call-seq:
+ * gdbm.select { |value| block } -> array
+ *
+ * Returns a new array of all values of the database for which _block_
+ * evaluates to true.
+ */
static VALUE
fgdbm_select(argc, argv, obj)
int argc;
@@ -390,6 +529,12 @@ fgdbm_select(argc, argv, obj)
return new;
}
+/*
+ * call-seq:
+ * gdbm.values_at(key, ...) -> array
+ *
+ * Returns an array of the values associated with each specified _key_.
+ */
static VALUE
fgdbm_values_at(argc, argv, obj)
int argc;
@@ -429,19 +574,26 @@ rb_gdbm_delete(obj, keystr)
GetDBM2(obj, dbmp, dbm);
if (!gdbm_exists(dbm, key)) {
- return Qnil;
+ return Qnil;
}
if (gdbm_delete(dbm, key)) {
- dbmp->di_size = -1;
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ dbmp->di_size = -1;
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
}
else if (dbmp->di_size >= 0) {
- dbmp->di_size--;
+ dbmp->di_size--;
}
return obj;
}
+/*
+ * call-seq:
+ * gdbm.delete(key) -> value or nil
+ *
+ * Removes the key-value-pair with the specified _key_ from this database and
+ * returns the corresponding _value_. Returns nil if the database is empty.
+ */
static VALUE
fgdbm_delete(obj, keystr)
VALUE obj, keystr;
@@ -453,6 +605,13 @@ fgdbm_delete(obj, keystr)
return valstr;
}
+/*
+ * call-seq:
+ * gdbm.shift -> (key, value) or nil
+ *
+ * Removes a key-value-pair from this database and returns it as a
+ * two-item array [ _key_, _value_ ]. Returns nil if the database is empty.
+ */
static VALUE
fgdbm_shift(obj)
VALUE obj;
@@ -471,6 +630,13 @@ fgdbm_shift(obj)
return rb_assoc_new(keystr, valstr);
}
+/*
+ * call-seq:
+ * gdbm.delete_if { |key, value| block } -> gdbm
+ * gdbm.reject! { |key, value| block } -> gdbm
+ *
+ * Deletes every key-value pair from _gdbm_ for which _block_ evaluates to true.
+ */
static VALUE
fgdbm_delete_if(obj)
VALUE obj;
@@ -489,11 +655,11 @@ fgdbm_delete_if(obj)
for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
keystr = rb_gdbm_nextkey(dbm, keystr)) {
- valstr = rb_gdbm_fetch2(dbm, keystr);
+ valstr = rb_gdbm_fetch2(dbm, keystr);
ret = rb_protect(rb_yield, rb_assoc_new(keystr, valstr), &status);
if (status != 0) break;
- if (RTEST(ret)) rb_ary_push(ary, keystr);
- GetDBM2(obj, dbmp, dbm);
+ if (RTEST(ret)) rb_ary_push(ary, keystr);
+ GetDBM2(obj, dbmp, dbm);
}
for (i = 0; i < RARRAY(ary)->len; i++)
@@ -504,6 +670,12 @@ fgdbm_delete_if(obj)
return obj;
}
+/*
+ * call-seq:
+ * gdbm.clear -> gdbm
+ *
+ * Removes all the key-value pairs within _gdbm_.
+ */
static VALUE
fgdbm_clear(obj)
VALUE obj;
@@ -518,11 +690,11 @@ fgdbm_clear(obj)
#if 0
while (key = gdbm_firstkey(dbm), key.dptr) {
- if (gdbm_delete(dbm, key)) {
- free(key.dptr);
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
- }
- free(key.dptr);
+ if (gdbm_delete(dbm, key)) {
+ free(key.dptr);
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ }
+ free(key.dptr);
}
#else
while (key = gdbm_firstkey(dbm), key.dptr) {
@@ -542,6 +714,13 @@ fgdbm_clear(obj)
return obj;
}
+/*
+ * call-seq:
+ * gdbm.invert -> hash
+ *
+ * Returns a hash created by using _gdbm_'s values as keys, and the keys
+ * as values.
+ */
static VALUE
fgdbm_invert(obj)
VALUE obj;
@@ -584,6 +763,14 @@ update_i(pair, dbm)
return Qnil;
}
+/*
+ * call-seq:
+ * gdbm.update(other) -> gdbm
+ *
+ * Adds the key-value pairs of _other_ to _gdbm_, overwriting entries with
+ * duplicate keys with those from _other_. _other_ must have an each_pair
+ * method.
+ */
static VALUE
fgdbm_update(obj, other)
VALUE obj, other;
@@ -592,6 +779,13 @@ fgdbm_update(obj, other)
return obj;
}
+/*
+ * call-seq:
+ * gdbm.replace(other) -> gdbm
+ *
+ * Replaces the content of _gdbm_ with the key-value pairs of _other_.
+ * _other_ must have an each_pair method.
+ */
static VALUE
fgdbm_replace(obj, other)
VALUE obj, other;
@@ -601,6 +795,13 @@ fgdbm_replace(obj, other)
return obj;
}
+/*
+ * call-seq:
+ * gdbm[key]= value -> value
+ * gdbm.store(key, value) -> value
+ *
+ * Associates the value _value_ with the specified _key_.
+ */
static VALUE
fgdbm_store(obj, keystr, valstr)
VALUE obj, keystr, valstr;
@@ -622,13 +823,20 @@ fgdbm_store(obj, keystr, valstr)
GetDBM2(obj, dbmp, dbm);
dbmp->di_size = -1;
if (gdbm_store(dbm, key, val, GDBM_REPLACE)) {
- if (errno == EPERM) rb_sys_fail(0);
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ if (errno == EPERM) rb_sys_fail(0);
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
}
return valstr;
}
+/*
+ * call-seq:
+ * gdbm.length -> fixnum
+ * gdbm.size -> fixnum
+ *
+ * Returns the number of key-value pairs in this database.
+ */
static VALUE
fgdbm_length(obj)
VALUE obj;
@@ -651,6 +859,12 @@ fgdbm_length(obj)
return INT2FIX(i);
}
+/*
+ * call-seq:
+ * gdbm.empty? -> true or false
+ *
+ * Returns true if the database is empty.
+ */
static VALUE
fgdbm_empty_p(obj)
VALUE obj;
@@ -675,6 +889,13 @@ fgdbm_empty_p(obj)
return Qfalse;
}
+/*
+ * call-seq:
+ * gdbm.each_value { |value| block } -> gdbm
+ *
+ * Executes _block_ for each key in the database, passing the corresponding
+ * _value_ as a parameter.
+ */
static VALUE
fgdbm_each_value(obj)
VALUE obj;
@@ -693,6 +914,13 @@ fgdbm_each_value(obj)
return obj;
}
+/*
+ * call-seq:
+ * gdbm.each_key { |key| block } -> gdbm
+ *
+ * Executes _block_ for each key in the database, passing the
+ * _key_ as a parameter.
+ */
static VALUE
fgdbm_each_key(obj)
VALUE obj;
@@ -711,6 +939,13 @@ fgdbm_each_key(obj)
return obj;
}
+/*
+ * call-seq:
+ * gdbm.each_pair { |key, value| block } -> gdbm
+ *
+ * Executes _block_ for each key in the database, passing the _key_ and the
+ * correspoding _value_ as a parameter.
+ */
static VALUE
fgdbm_each_pair(obj)
VALUE obj;
@@ -724,12 +959,18 @@ fgdbm_each_pair(obj)
keystr = rb_gdbm_nextkey(dbm, keystr)) {
rb_yield(rb_assoc_new(keystr, rb_gdbm_fetch2(dbm, keystr)));
- GetDBM2(obj, dbmp, dbm);
+ GetDBM2(obj, dbmp, dbm);
}
return obj;
}
+/*
+ * call-seq:
+ * gdbm.keys -> array
+ *
+ * Returns an array of all keys of this database.
+ */
static VALUE
fgdbm_keys(obj)
VALUE obj;
@@ -749,6 +990,12 @@ fgdbm_keys(obj)
return ary;
}
+/*
+ * call-seq:
+ * gdbm.values -> array
+ *
+ * Returns an array of all values of this database.
+ */
static VALUE
fgdbm_values(obj)
VALUE obj;
@@ -762,14 +1009,22 @@ fgdbm_values(obj)
ary = rb_ary_new();
for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) {
nextkey = gdbm_nextkey(dbm, key);
- valstr = rb_gdbm_fetch(dbm, key);
+ valstr = rb_gdbm_fetch(dbm, key);
free(key.dptr);
- rb_ary_push(ary, valstr);
+ rb_ary_push(ary, valstr);
}
return ary;
}
+/*
+ * call-seq:
+ * gdbm.has_key?(k) -> true or false
+ * gdbm.key?(k) -> true or false
+ *
+ * Returns true if the given key _k_ exists within the database.
+ * Returns false otherwise.
+ */
static VALUE
fgdbm_has_key(obj, keystr)
VALUE obj, keystr;
@@ -788,6 +1043,14 @@ fgdbm_has_key(obj, keystr)
return Qfalse;
}
+/*
+ * call-seq:
+ * gdbm.has_value?(v) -> true or false
+ * gdbm.value?(v) -> true or false
+ *
+ * Returns true if the given value _v_ exists within the database.
+ * Returns false otherwise.
+ */
static VALUE
fgdbm_has_value(obj, valstr)
VALUE obj, valstr;
@@ -813,6 +1076,12 @@ fgdbm_has_value(obj, valstr)
return Qfalse;
}
+/*
+ * call-seq:
+ * gdbm.to_a -> array
+ *
+ * Returns an array of all key-value pairs contained in the database.
+ */
static VALUE
fgdbm_to_a(obj)
VALUE obj;
@@ -832,6 +1101,14 @@ fgdbm_to_a(obj)
return ary;
}
+/*
+ * call-seq:
+ * gdbm.reorganize -> gdbm
+ *
+ * Reorganizes the database file. This operation removes reserved space of
+ * elements that have already been deleted. It is only useful after a lot of
+ * deletions in the database.
+ */
static VALUE
fgdbm_reorganize(obj)
VALUE obj;
@@ -845,6 +1122,16 @@ fgdbm_reorganize(obj)
return obj;
}
+/*
+ * call-seq:
+ * gdbm.sync -> gdbm
+ *
+ * Unless the _gdbm_ object has been opened with the *SYNC* flag, it is not
+ * guarenteed that database modification operations are immediately applied to
+ * the database file. This method ensures that all recent modifications
+ * to the database are written to the file. Blocks until all writing operations
+ * to the disk have been finished.
+ */
static VALUE
fgdbm_sync(obj)
VALUE obj;
@@ -858,6 +1145,12 @@ fgdbm_sync(obj)
return obj;
}
+/*
+ * call-seq:
+ * gdbm.cachesize = size -> size
+ *
+ * Sets the size of the internal bucket cache to _size_.
+ */
static VALUE
fgdbm_set_cachesize(obj, val)
VALUE obj, val;
@@ -869,11 +1162,21 @@ fgdbm_set_cachesize(obj, val)
GetDBM2(obj, dbmp, dbm);
optval = FIX2INT(val);
if (gdbm_setopt(dbm, GDBM_CACHESIZE, &optval, sizeof(optval)) == -1) {
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
}
return val;
}
+/*
+ * call-seq:
+ * gdbm.fastmode = boolean -> boolean
+ *
+ * Turns the database's fast mode on or off. If fast mode is turned on, gdbm
+ * does not wait for writes to be flushed to the disk before continuing.
+ *
+ * This option is obsolete for gdbm >= 1.8 since fast mode is turned on by
+ * default. See also: #syncmode=
+ */
static VALUE
fgdbm_set_fastmode(obj, val)
VALUE obj, val;
@@ -888,11 +1191,24 @@ fgdbm_set_fastmode(obj, val)
optval = 1;
if (gdbm_setopt(dbm, GDBM_FASTMODE, &optval, sizeof(optval)) == -1) {
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
}
return val;
}
+/*
+ * call-seq:
+ * gdbm.syncmode = boolean -> boolean
+ *
+ * Turns the database's synchronization mode on or off. If the synchronization
+ * mode is turned on, the database's in-memory state will be synchronized to
+ * disk after every database modification operation. If the synchronization
+ * mode is turned off, GDBM does not wait for writes to be flushed to the disk
+ * before continuing.
+ *
+ * This option is only available for gdbm >= 1.8 where syncmode is turned off
+ * by default. See also: #fastmode=
+ */
static VALUE
fgdbm_set_syncmode(obj, val)
VALUE obj, val;
@@ -911,12 +1227,18 @@ fgdbm_set_syncmode(obj, val)
optval = 1;
if (gdbm_setopt(dbm, GDBM_FASTMODE, &optval, sizeof(optval)) == -1) {
- rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
}
return val;
#endif
}
+/*
+ * call-seq:
+ * gdbm.to_hash -> hash
+ *
+ * Returns a hash of all key-value pairs contained in the database.
+ */
static VALUE
fgdbm_to_hash(obj)
VALUE obj;
@@ -936,6 +1258,13 @@ fgdbm_to_hash(obj)
return hash;
}
+/*
+ * call-seq:
+ * gdbm.reject { |key, value| block } -> hash
+ *
+ * Returns a hash copy of _gdbm_ where all key-value pairs from _gdbm_ for
+ * which _block_ evaluates to true are removed. See also: #delete_if
+ */
static VALUE
fgdbm_reject(obj)
VALUE obj;
@@ -981,15 +1310,15 @@ Init_gdbm()
rb_define_method(rb_cGDBM, "reject!", fgdbm_delete_if, 0);
rb_define_method(rb_cGDBM, "reject", fgdbm_reject, 0);
rb_define_method(rb_cGDBM, "clear", fgdbm_clear, 0);
- rb_define_method(rb_cGDBM,"invert", fgdbm_invert, 0);
- rb_define_method(rb_cGDBM,"update", fgdbm_update, 1);
- rb_define_method(rb_cGDBM,"replace", fgdbm_replace, 1);
- rb_define_method(rb_cGDBM,"reorganize", fgdbm_reorganize, 0);
- rb_define_method(rb_cGDBM,"sync", fgdbm_sync, 0);
- /* rb_define_method(rb_cGDBM,"setopt", fgdbm_setopt, 2); */
- rb_define_method(rb_cGDBM,"cachesize=", fgdbm_set_cachesize, 1);
- rb_define_method(rb_cGDBM,"fastmode=", fgdbm_set_fastmode, 1);
- rb_define_method(rb_cGDBM,"syncmode=", fgdbm_set_syncmode, 1);
+ rb_define_method(rb_cGDBM, "invert", fgdbm_invert, 0);
+ rb_define_method(rb_cGDBM, "update", fgdbm_update, 1);
+ rb_define_method(rb_cGDBM, "replace", fgdbm_replace, 1);
+ rb_define_method(rb_cGDBM, "reorganize", fgdbm_reorganize, 0);
+ rb_define_method(rb_cGDBM, "sync", fgdbm_sync, 0);
+ /* rb_define_method(rb_cGDBM, "setopt", fgdbm_setopt, 2); */
+ rb_define_method(rb_cGDBM, "cachesize=", fgdbm_set_cachesize, 1);
+ rb_define_method(rb_cGDBM, "fastmode=", fgdbm_set_fastmode, 1);
+ rb_define_method(rb_cGDBM, "syncmode=", fgdbm_set_syncmode, 1);
rb_define_method(rb_cGDBM, "include?", fgdbm_has_key, 1);
rb_define_method(rb_cGDBM, "has_key?", fgdbm_has_key, 1);
@@ -1001,22 +1330,29 @@ Init_gdbm()
rb_define_method(rb_cGDBM, "to_a", fgdbm_to_a, 0);
rb_define_method(rb_cGDBM, "to_hash", fgdbm_to_hash, 0);
- /* flags for gdbm_open() */
+ /* flag for #new and #open: open database as a reader */
rb_define_const(rb_cGDBM, "READER", INT2FIX(GDBM_READER|RUBY_GDBM_RW_BIT));
+ /* flag for #new and #open: open database as a writer */
rb_define_const(rb_cGDBM, "WRITER", INT2FIX(GDBM_WRITER|RUBY_GDBM_RW_BIT));
+ /* flag for #new and #open: open database as a writer; if the database does not exist, create a new one */
rb_define_const(rb_cGDBM, "WRCREAT", INT2FIX(GDBM_WRCREAT|RUBY_GDBM_RW_BIT));
+ /* flag for #new and #open: open database as a writer; overwrite any existing databases */
rb_define_const(rb_cGDBM, "NEWDB", INT2FIX(GDBM_NEWDB|RUBY_GDBM_RW_BIT));
+ /* flag for #new and #open. this flag is obsolete for gdbm >= 1.8 */
rb_define_const(rb_cGDBM, "FAST", INT2FIX(GDBM_FAST));
/* this flag is obsolete in gdbm 1.8.
On gdbm 1.8, fast mode is default behavior. */
/* gdbm version 1.8 specific */
#if defined(GDBM_SYNC)
+ /* flag for #new and #open. only for gdbm >= 1.8 */
rb_define_const(rb_cGDBM, "SYNC", INT2FIX(GDBM_SYNC));
#endif
#if defined(GDBM_NOLOCK)
+ /* flag for #new and #open */
rb_define_const(rb_cGDBM, "NOLOCK", INT2FIX(GDBM_NOLOCK));
#endif
+ /* version of the gdbm library*/
rb_define_const(rb_cGDBM, "VERSION", rb_str_new2(gdbm_version));
}
diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c
index 918dd51630..d989b97df2 100644
--- a/ext/iconv/iconv.c
+++ b/ext/iconv/iconv.c
@@ -3,8 +3,8 @@
iconv.c -
- $Author: matz $
- $Date: 2005/12/12 00:36:51 $
+ $Author$
+ $Date$
created at: Wed Dec 1 20:28:09 JST 1999
All the files in this distribution are covered under the Ruby's
@@ -43,7 +43,11 @@
*
* == Examples
*
- * 1. Instantiate a new Iconv and use method Iconv#iconv.
+ * 1. Simple conversion between two charsets.
+ *
+ * converted_text = Iconv.conv('iso-8859-15', 'utf-8', text)
+ *
+ * 2. Instantiate a new Iconv and use method Iconv#iconv.
*
* cd = Iconv.new(to, from)
* begin
@@ -53,20 +57,16 @@
* cd.close
* end
*
- * 2. Invoke Iconv.open with a block.
+ * 3. Invoke Iconv.open with a block.
*
* Iconv.open(to, from) do |cd|
* input.each { |s| output << cd.iconv(s) }
* output << cd.iconv(nil)
* end
*
- * 3. Shorthand for (2).
+ * 4. Shorthand for (3).
*
* Iconv.iconv(to, from, *input.to_a)
- *
- * 4. Simple conversion between two charsets.
- *
- * converted_text = Iconv.new('iso-8859-15', 'utf-8').iconv(text)
*/
/* Invalid value for iconv_t is -1 but 0 for VALUE, I hope VALUE is
@@ -101,7 +101,7 @@ static void iconv_dfree _((void *cd));
static VALUE iconv_free _((VALUE cd));
static VALUE iconv_try _((iconv_t cd, const char **inptr, size_t *inlen, char **outptr, size_t *outlen));
static VALUE rb_str_derive _((VALUE str, const char* ptr, int len));
-static VALUE iconv_convert _((iconv_t cd, VALUE str, int start, int length, struct iconv_env_t* env));
+static VALUE iconv_convert _((iconv_t cd, VALUE str, long start, long length, struct iconv_env_t* env));
static VALUE iconv_s_allocate _((VALUE klass));
static VALUE iconv_initialize _((VALUE self, VALUE to, VALUE from));
static VALUE iconv_s_open _((VALUE self, VALUE to, VALUE from));
@@ -170,7 +170,7 @@ iconv_create
}
if (cd == (iconv_t)-1) {
int inval = errno == EINVAL;
- char *s = inval ? "invalid encoding " : "iconv";
+ const char *s = inval ? "invalid encoding " : "iconv";
volatile VALUE msg = rb_str_new(0, strlen(s) + RSTRING(to)->len +
RSTRING(from)->len + 8);
@@ -362,13 +362,13 @@ rb_str_derive
static VALUE
iconv_convert
#ifdef HAVE_PROTOTYPES
- (iconv_t cd, VALUE str, int start, int length, struct iconv_env_t* env)
+ (iconv_t cd, VALUE str, long start, long length, struct iconv_env_t* env)
#else /* HAVE_PROTOTYPES */
(cd, str, start, length, env)
iconv_t cd;
VALUE str;
- int start;
- int length;
+ long start;
+ long length;
struct iconv_env_t *env;
#endif /* HAVE_PROTOTYPES */
{
@@ -417,14 +417,9 @@ iconv_convert
slen = RSTRING(str)->len;
inptr = RSTRING(str)->ptr;
- if (start < 0 ? (start += slen) < 0 : start >= slen)
- length = 0;
- else if (length < 0 && (length += slen + 1) < 0)
- length = 0;
- else if ((length -= start) < 0)
- length = 0;
- else
- inptr += start;
+ inptr += start;
+ if (length < 0 || length > start + slen)
+ length = slen - start;
}
instart = inptr;
inlen = length;
@@ -606,7 +601,7 @@ iconv_s_convert
}
/*
- * Document-method: iconv
+ * Document-method: Iconv::iconv
* call-seq: Iconv.iconv(to, from, *strs)
*
* Shorthand for
@@ -649,7 +644,7 @@ iconv_s_iconv
/*
* Document-method: Iconv::conv
- * call-seq: Iconv.iconv(to, from, *strs)
+ * call-seq: Iconv.conv(to, from, str)
*
* Shorthand for
* Iconv.iconv(to, from, str).join
@@ -715,7 +710,7 @@ iconv_finish
}
/*
- * Document-method: iconv
+ * Document-method: Iconv#iconv
* call-seq: iconv(str, start=0, length=-1)
*
* Converts string and returns the result.
@@ -754,14 +749,22 @@ iconv_iconv
{
VALUE str, n1, n2;
VALUE cd = check_iconv(self);
+ long start = 0, length = 0, slen = 0;
- n1 = n2 = Qnil;
rb_scan_args(argc, argv, "12", &str, &n1, &n2);
+ if (!NIL_P(str)) slen = RSTRING_LEN(StringValue(str));
+ if (argc != 2 || !RTEST(rb_range_beg_len(n1, &start, &length, slen, 0))) {
+ if (NIL_P(n1) || ((start = NUM2LONG(n1)) < 0 ? (start += slen) >= 0 : start < slen)) {
+ if (NIL_P(n2)) {
+ length = -1;
+ }
+ else if ((length = NUM2LONG(n2)) >= slen - start) {
+ length = slen - start;
+ }
+ }
+ }
- return iconv_convert(VALUE2ICONV(cd), str,
- NIL_P(n1) ? 0 : NUM2INT(n1),
- NIL_P(n2) ? -1 : NUM2INT(n2),
- NULL);
+ return iconv_convert(VALUE2ICONV(cd), str, start, length, NULL);
}
/*
@@ -825,7 +828,7 @@ iconv_failure_inspect
VALUE self;
#endif /* HAVE_PROTOTYPES */
{
- char *cname = rb_class2name(CLASS_OF(self));
+ const char *cname = rb_class2name(CLASS_OF(self));
VALUE success = rb_attr_get(self, rb_success);
VALUE failed = rb_attr_get(self, rb_failed);
VALUE str = rb_str_buf_cat2(rb_str_new2("#<"), cname);
diff --git a/ext/io/wait/extconf.rb b/ext/io/wait/extconf.rb
index 1352ef202e..e8181d25f5 100644
--- a/ext/io/wait/extconf.rb
+++ b/ext/io/wait/extconf.rb
@@ -3,7 +3,7 @@ target = "io/wait"
unless macro_defined?("DOSISH", "#include <ruby.h>")
fionread = %w[sys/ioctl.h sys/filio.h].find do |h|
- checking_for("FIONREAD") {have_macro("FIONREAD", h)}
+ have_macro("FIONREAD", h)
end
if fionread
$defs << "-DFIONREAD_HEADER=\"<#{fionread}>\""
diff --git a/ext/io/wait/wait.c b/ext/io/wait/wait.c
index 0e48f705d2..02cb54a014 100644
--- a/ext/io/wait/wait.c
+++ b/ext/io/wait/wait.c
@@ -2,8 +2,8 @@
io/wait.c -
- $Author: nobu $
- $Date: 2005/07/18 03:24:04 $
+ $Author$
+ $Date$
created at: Tue Aug 28 09:08:06 JST 2001
All the files in this distribution are covered under the Ruby's
@@ -56,7 +56,7 @@ static VALUE
io_ready_p(io)
VALUE io;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
FILE *fp;
ioctl_arg n;
@@ -84,7 +84,7 @@ io_wait(argc, argv, io)
VALUE *argv;
VALUE io;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
fd_set rd;
FILE *fp;
int fd;
diff --git a/ext/nkf/lib/kconv.rb b/ext/nkf/lib/kconv.rb
index 711a3c10a1..4ffe8d984e 100644
--- a/ext/nkf/lib/kconv.rb
+++ b/ext/nkf/lib/kconv.rb
@@ -1,7 +1,7 @@
#
# kconv.rb - Kanji Converter.
#
-# $Id: kconv.rb,v 1.3.6.6 2006/06/19 14:52:54 naruse Exp $
+# $Id$
#
# ----
#
@@ -49,7 +49,7 @@ module Kconv
#
# Revision of kconv.rb
- REVISION = %q$Revision: 1.3.6.6 $
+ REVISION = %q$Revision$
#Regexp of Encoding
@@ -63,8 +63,8 @@ module Kconv
RegexpEucjp = /\A(?:
[\x00-\x7f] |
\x8e [\xa1-\xdf] |
- \x8f [\xa1-\xdf] [\xa1-\xfe] |
- [\xa1-\xdf] [\xa1-\xfe]
+ \x8f [\xa1-\xfe] [\xa1-\xfe] |
+ [\xa1-\xfe] [\xa1-\xfe]
)*\z/nx
# Regexp of UTF-8 string (private constant)
@@ -156,7 +156,7 @@ module Kconv
# convert halfwidth katakana to fullwidth katakana.
# If you don't want it, use NKF.nkf('-exm0', str).
def toeuc(str)
- ::NKF::nkf('-em0', str)
+ ::NKF::nkf('-em', str)
end
module_function :toeuc
diff --git a/ext/nkf/nkf-utf8/nkf.c b/ext/nkf/nkf-utf8/nkf.c
index 0d82562326..3cd1b160da 100644
--- a/ext/nkf/nkf-utf8/nkf.c
+++ b/ext/nkf/nkf-utf8/nkf.c
@@ -39,9 +39,9 @@
** E-Mail: furukawa@tcp-ip.or.jp
** $B$^$G8fO"Mm$r$*4j$$$7$^$9!#(B
***********************************************************************/
-/* $Id: nkf.c,v 1.2.2.11 2006/06/19 14:52:55 naruse Exp $ */
-#define NKF_VERSION "2.0.7"
-#define NKF_RELEASE_DATE "2006-06-13"
+/* $Id$ */
+#define NKF_VERSION "2.0.8"
+#define NKF_RELEASE_DATE "2007-01-28"
#include "config.h"
#include "utf8tbl.h"
@@ -62,7 +62,7 @@
**
** t no operation
**
-** j Outout code is JIS 7 bit (DEFAULT SELECT)
+** j Output code is JIS 7 bit (DEFAULT SELECT)
** s Output code is MS Kanji (DEFAULT SELECT)
** e Output code is AT&T JIS (DEFAULT SELECT)
** w Output code is AT&T JIS (DEFAULT SELECT)
@@ -219,6 +219,7 @@ void djgpp_setbinmode(FILE *fp)
/* Input Assumption */
#define JIS_INPUT 4
+#define EUC_INPUT 16
#define SJIS_INPUT 5
#define LATIN1_INPUT 6
#define FIXED_MIME 7
@@ -232,8 +233,15 @@ void djgpp_setbinmode(FILE *fp)
#define UTF8 12
#define UTF8_INPUT 13
-#define UTF16BE_INPUT 14
-#define UTF16LE_INPUT 15
+#define UTF16_INPUT 1015
+#define UTF32_INPUT 1017
+
+/* byte order */
+
+#define ENDIAN_BIG 1234
+#define ENDIAN_LITTLE 4321
+#define ENDIAN_2143 2143
+#define ENDIAN_3412 3412
#define WISH_TRUE 15
@@ -353,8 +361,8 @@ static int ms_ucs_map_f = UCS_MAP_ASCII;
/* no NEC special, NEC-selected IBM extended and IBM extended characters */
static int no_cp932ext_f = FALSE;
/* ignore ZERO WIDTH NO-BREAK SPACE */
-static int ignore_zwnbsp_f = TRUE;
static int no_best_fit_chars_f = FALSE;
+static int input_endian = ENDIAN_BIG;
static nkf_char unicode_subchar = '?'; /* the regular substitution character */
static void nkf_each_char_to_hex(void (*f)(nkf_char c2,nkf_char c1), nkf_char c);
static void encode_fallback_html(nkf_char c);
@@ -366,18 +374,21 @@ static void (*encode_fallback)(nkf_char c) = NULL;
static nkf_char w2e_conv(nkf_char c2,nkf_char c1,nkf_char c0,nkf_char *p2,nkf_char *p1);
static nkf_char w_iconv(nkf_char c2,nkf_char c1,nkf_char c0);
static nkf_char w_iconv16(nkf_char c2,nkf_char c1,nkf_char c0);
+static nkf_char w_iconv32(nkf_char c2,nkf_char c1,nkf_char c0);
static nkf_char unicode_to_jis_common(nkf_char c2,nkf_char c1,nkf_char c0,nkf_char *p2,nkf_char *p1);
static nkf_char w_iconv_common(nkf_char c1,nkf_char c0,const unsigned short *const *pp,nkf_char psize,nkf_char *p2,nkf_char *p1);
static void w16w_conv(nkf_char val, nkf_char *p2, nkf_char *p1, nkf_char *p0);
static nkf_char ww16_conv(nkf_char c2, nkf_char c1, nkf_char c0);
static nkf_char w16e_conv(nkf_char val,nkf_char *p2,nkf_char *p1);
+static void w_status(struct input_code *, nkf_char);
#endif
#ifdef UTF8_OUTPUT_ENABLE
-static int unicode_bom_f= 0; /* Output Unicode BOM */
-static int w_oconv16_LE = 0; /* utf-16 little endian */
+static int output_bom_f = FALSE;
+static int output_endian = ENDIAN_BIG;
static nkf_char e2w_conv(nkf_char c2,nkf_char c1);
static void w_oconv(nkf_char c2,nkf_char c1);
static void w_oconv16(nkf_char c2,nkf_char c1);
+static void w_oconv32(nkf_char c2,nkf_char c1);
#endif
static void e_oconv(nkf_char c2,nkf_char c1);
static nkf_char e2s_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1);
@@ -437,7 +448,7 @@ static unsigned char stdibuf[IOBUF_SIZE];
static unsigned char stdobuf[IOBUF_SIZE];
#endif
static unsigned char hold_buf[HOLD_SIZE*2];
-static int hold_count;
+static int hold_count = 0;
/* MIME preprocessor fifo */
@@ -501,10 +512,10 @@ static nkf_char url_ungetc(nkf_char c,FILE *f);
#endif
#define PREFIX_EUCG3 NKF_INT32_C(0x8F00)
#define CLASS_MASK NKF_INT32_C(0xFF000000)
-#define CLASS_UTF16 NKF_INT32_C(0x01000000)
+#define CLASS_UNICODE NKF_INT32_C(0x01000000)
#define VALUE_MASK NKF_INT32_C(0x00FFFFFF)
#define UNICODE_MAX NKF_INT32_C(0x0010FFFF)
-#define is_unicode_capsule(c) ((c & CLASS_MASK) == CLASS_UTF16)
+#define is_unicode_capsule(c) ((c & CLASS_MASK) == CLASS_UNICODE)
#define is_unicode_bmp(c) ((c & VALUE_MASK) <= NKF_INT32_C(0xFFFF))
#ifdef NUMCHAR_OPTION
@@ -537,7 +548,7 @@ static int exec_f = 0;
#ifdef SHIFTJIS_CP932
/* invert IBM extended characters to others */
-static int cp51932_f = TRUE;
+static int cp51932_f = FALSE;
/* invert NEC-selected IBM extended characters to IBM extended characters */
static int cp932inv_f = TRUE;
@@ -565,18 +576,13 @@ static void status_check(struct input_code *ptr, nkf_char c);
static void e_status(struct input_code *, nkf_char);
static void s_status(struct input_code *, nkf_char);
-#ifdef UTF8_INPUT_ENABLE
-static void w_status(struct input_code *, nkf_char);
-static void w16_status(struct input_code *, nkf_char);
-static int utf16_mode = UTF16BE_INPUT;
-#endif
-
struct input_code input_code_list[] = {
{"EUC-JP", 0, 0, 0, {0, 0, 0}, e_status, e_iconv, 0},
{"Shift_JIS", 0, 0, 0, {0, 0, 0}, s_status, s_iconv, 0},
#ifdef UTF8_INPUT_ENABLE
{"UTF-8", 0, 0, 0, {0, 0, 0}, w_status, w_iconv, 0},
- {"UTF-16", 0, 0, 0, {0, 0, 0}, w16_status, w_iconv16, 0},
+ {"UTF-16", 0, 0, 0, {0, 0, 0}, NULL, w_iconv16, 0},
+ {"UTF-32", 0, 0, 0, {0, 0, 0}, NULL, w_iconv32, 0},
#endif
{0}
};
@@ -848,6 +854,7 @@ int main(int argc, char **argv)
}
} else {
int nfiles = argc;
+ int is_argument_error = FALSE;
while (argc--) {
is_inputcode_mixed = FALSE;
is_inputcode_set = FALSE;
@@ -857,7 +864,9 @@ int main(int argc, char **argv)
#endif
if ((fin = fopen((origfname = *argv++), "r")) == NULL) {
perror(*--argv);
- return(-1);
+ *argv++;
+ is_argument_error = TRUE;
+ continue;
} else {
#ifdef OVERWRITE
int fd = 0;
@@ -1005,6 +1014,8 @@ int main(int argc, char **argv)
#endif
}
}
+ if (is_argument_error)
+ return(-1);
}
#ifdef EASYWIN /*Easy Win */
if (file_out_f == FALSE)
@@ -1185,13 +1196,19 @@ void options(unsigned char *cp)
codeset[i] = nkf_toupper(p[i]);
}
codeset[i] = 0;
- if(strcmp(codeset, "ISO-2022-JP") == 0 ||
- strcmp(codeset, "X-ISO2022JP-CP932") == 0 ||
+ if(strcmp(codeset, "ISO-2022-JP") == 0){
+ input_f = JIS_INPUT;
+ }else if(strcmp(codeset, "X-ISO2022JP-CP932") == 0 ||
strcmp(codeset, "CP50220") == 0 ||
strcmp(codeset, "CP50221") == 0 ||
- strcmp(codeset, "CP50222") == 0 ||
- strcmp(codeset, "ISO-2022-JP-MS") == 0){
+ strcmp(codeset, "CP50222") == 0){
input_f = JIS_INPUT;
+#ifdef SHIFTJIS_CP932
+ cp51932_f = TRUE;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_CP932;
+#endif
}else if(strcmp(codeset, "ISO-2022-JP-1") == 0){
input_f = JIS_INPUT;
#ifdef X0212_ENABLE
@@ -1205,13 +1222,11 @@ void options(unsigned char *cp)
x0213_f = TRUE;
}else if(strcmp(codeset, "SHIFT_JIS") == 0){
input_f = SJIS_INPUT;
- if (x0201_f==NO_X0201) x0201_f=TRUE;
}else if(strcmp(codeset, "WINDOWS-31J") == 0 ||
strcmp(codeset, "CSWINDOWS31J") == 0 ||
strcmp(codeset, "CP932") == 0 ||
strcmp(codeset, "MS932") == 0){
input_f = SJIS_INPUT;
- x0201_f = FALSE;
#ifdef SHIFTJIS_CP932
cp51932_f = TRUE;
#endif
@@ -1220,10 +1235,9 @@ void options(unsigned char *cp)
#endif
}else if(strcmp(codeset, "EUCJP") == 0 ||
strcmp(codeset, "EUC-JP") == 0){
- input_f = JIS_INPUT;
+ input_f = EUC_INPUT;
}else if(strcmp(codeset, "CP51932") == 0){
- input_f = JIS_INPUT;
- x0201_f = FALSE;
+ input_f = EUC_INPUT;
#ifdef SHIFTJIS_CP932
cp51932_f = TRUE;
#endif
@@ -1233,8 +1247,7 @@ void options(unsigned char *cp)
}else if(strcmp(codeset, "EUC-JP-MS") == 0 ||
strcmp(codeset, "EUCJP-MS") == 0 ||
strcmp(codeset, "EUCJPMS") == 0){
- input_f = JIS_INPUT;
- x0201_f = FALSE;
+ input_f = EUC_INPUT;
#ifdef SHIFTJIS_CP932
cp51932_f = FALSE;
#endif
@@ -1243,8 +1256,7 @@ void options(unsigned char *cp)
#endif
}else if(strcmp(codeset, "EUC-JP-ASCII") == 0 ||
strcmp(codeset, "EUCJP-ASCII") == 0){
- input_f = JIS_INPUT;
- x0201_f = FALSE;
+ input_f = EUC_INPUT;
#ifdef SHIFTJIS_CP932
cp51932_f = FALSE;
#endif
@@ -1257,17 +1269,13 @@ void options(unsigned char *cp)
x0213_f = TRUE;
#ifdef SHIFTJIS_CP932
cp51932_f = FALSE;
- cp932inv_f = FALSE;
#endif
- if (x0201_f==NO_X0201) x0201_f=TRUE;
}else if(strcmp(codeset, "EUC-JISX0213") == 0 ||
strcmp(codeset, "EUC-JIS-2004") == 0){
- input_f = JIS_INPUT;
- x0201_f = FALSE;
+ input_f = EUC_INPUT;
x0213_f = TRUE;
#ifdef SHIFTJIS_CP932
cp51932_f = FALSE;
- cp932inv_f = FALSE;
#endif
#ifdef UTF8_INPUT_ENABLE
}else if(strcmp(codeset, "UTF-8") == 0 ||
@@ -1280,61 +1288,78 @@ void options(unsigned char *cp)
input_f = UTF8_INPUT;
nfc_f = TRUE;
#endif
- }else if(strcmp(codeset, "UTF-16") == 0){
- input_f = UTF16BE_INPUT;
- utf16_mode = UTF16BE_INPUT;
- }else if(strcmp(codeset, "UTF-16BE") == 0 ||
+ }else if(strcmp(codeset, "UTF-16") == 0 ||
+ strcmp(codeset, "UTF-16BE") == 0 ||
strcmp(codeset, "UTF-16BE-BOM") == 0){
- input_f = UTF16BE_INPUT;
- utf16_mode = UTF16BE_INPUT;
+ input_f = UTF16_INPUT;
+ input_endian = ENDIAN_BIG;
}else if(strcmp(codeset, "UTF-16LE") == 0 ||
strcmp(codeset, "UTF-16LE-BOM") == 0){
- input_f = UTF16LE_INPUT;
- utf16_mode = UTF16LE_INPUT;
+ input_f = UTF16_INPUT;
+ input_endian = ENDIAN_LITTLE;
+ }else if(strcmp(codeset, "UTF-32") == 0 ||
+ strcmp(codeset, "UTF-32BE") == 0 ||
+ strcmp(codeset, "UTF-32BE-BOM") == 0){
+ input_f = UTF32_INPUT;
+ input_endian = ENDIAN_BIG;
+ }else if(strcmp(codeset, "UTF-32LE") == 0 ||
+ strcmp(codeset, "UTF-32LE-BOM") == 0){
+ input_f = UTF32_INPUT;
+ input_endian = ENDIAN_LITTLE;
#endif
}
continue;
}
if (strcmp(long_option[i].name, "oc=") == 0){
+ x0201_f = FALSE;
for (i=0; i < 16 && SPACE < p[i] && p[i] < DEL; i++){
codeset[i] = nkf_toupper(p[i]);
}
codeset[i] = 0;
- if(strcmp(codeset, "ISO-2022-JP") == 0 ||
- strcmp(codeset, "CP50220") == 0){
+ if(strcmp(codeset, "ISO-2022-JP") == 0){
output_conv = j_oconv;
}else if(strcmp(codeset, "X-ISO2022JP-CP932") == 0){
output_conv = j_oconv;
no_cp932ext_f = TRUE;
- }else if(strcmp(codeset, "CP50221") == 0 ||
- strcmp(codeset, "ISO-2022-JP-MS") == 0){
- output_conv = j_oconv;
- x0201_f = FALSE;
- }else if(strcmp(codeset, "ISO-2022-JP-1") == 0){
+#ifdef SHIFTJIS_CP932
+ cp932inv_f = FALSE;
+#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_CP932;
+#endif
+ }else if(strcmp(codeset, "CP50220") == 0){
output_conv = j_oconv;
-#ifdef X0212_ENABLE
- x0212_f = TRUE;
+ x0201_f = TRUE;
+#ifdef SHIFTJIS_CP932
+ cp932inv_f = FALSE;
#endif
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_CP932;
+#endif
+ }else if(strcmp(codeset, "CP50221") == 0){
+ output_conv = j_oconv;
#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
+ cp932inv_f = FALSE;
#endif
- }else if(strcmp(codeset, "ISO-2022-JP-3") == 0){
+#ifdef UTF8_OUTPUT_ENABLE
+ ms_ucs_map_f = UCS_MAP_CP932;
+#endif
+ }else if(strcmp(codeset, "ISO-2022-JP-1") == 0){
output_conv = j_oconv;
#ifdef X0212_ENABLE
x0212_f = TRUE;
#endif
- x0213_f = TRUE;
#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
+ cp932inv_f = FALSE;
#endif
- }else if(strcmp(codeset, "ISO-2022-JP-MS") == 0){
+ }else if(strcmp(codeset, "ISO-2022-JP-3") == 0){
output_conv = j_oconv;
- x0201_f = FALSE;
#ifdef X0212_ENABLE
x0212_f = TRUE;
#endif
+ x0213_f = TRUE;
#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
+ cp932inv_f = FALSE;
#endif
}else if(strcmp(codeset, "SHIFT_JIS") == 0){
output_conv = s_oconv;
@@ -1343,11 +1368,6 @@ void options(unsigned char *cp)
strcmp(codeset, "CP932") == 0 ||
strcmp(codeset, "MS932") == 0){
output_conv = s_oconv;
- x0201_f = FALSE;
-#ifdef SHIFTJIS_CP932
- cp51932_f = TRUE;
- cp932inv_f = TRUE;
-#endif
#ifdef UTF8_OUTPUT_ENABLE
ms_ucs_map_f = UCS_MAP_CP932;
#endif
@@ -1356,9 +1376,8 @@ void options(unsigned char *cp)
output_conv = e_oconv;
}else if(strcmp(codeset, "CP51932") == 0){
output_conv = e_oconv;
- x0201_f = FALSE;
#ifdef SHIFTJIS_CP932
- cp51932_f = TRUE;
+ cp932inv_f = FALSE;
#endif
#ifdef UTF8_OUTPUT_ENABLE
ms_ucs_map_f = UCS_MAP_CP932;
@@ -1367,26 +1386,18 @@ void options(unsigned char *cp)
strcmp(codeset, "EUCJP-MS") == 0 ||
strcmp(codeset, "EUCJPMS") == 0){
output_conv = e_oconv;
- x0201_f = FALSE;
#ifdef X0212_ENABLE
x0212_f = TRUE;
#endif
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
-#endif
#ifdef UTF8_OUTPUT_ENABLE
ms_ucs_map_f = UCS_MAP_MS;
#endif
}else if(strcmp(codeset, "EUC-JP-ASCII") == 0 ||
strcmp(codeset, "EUCJP-ASCII") == 0){
output_conv = e_oconv;
- x0201_f = FALSE;
#ifdef X0212_ENABLE
x0212_f = TRUE;
#endif
-#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
-#endif
#ifdef UTF8_OUTPUT_ENABLE
ms_ucs_map_f = UCS_MAP_ASCII;
#endif
@@ -1405,32 +1416,42 @@ void options(unsigned char *cp)
#endif
x0213_f = TRUE;
#ifdef SHIFTJIS_CP932
- cp51932_f = FALSE;
+ cp932inv_f = FALSE;
#endif
#ifdef UTF8_OUTPUT_ENABLE
}else if(strcmp(codeset, "UTF-8") == 0){
output_conv = w_oconv;
}else if(strcmp(codeset, "UTF-8N") == 0){
output_conv = w_oconv;
- unicode_bom_f=1;
}else if(strcmp(codeset, "UTF-8-BOM") == 0){
output_conv = w_oconv;
- unicode_bom_f=2;
+ output_bom_f = TRUE;
}else if(strcmp(codeset, "UTF-16BE") == 0){
- output_conv = w_oconv16;
- unicode_bom_f=1;
+ output_conv = w_oconv16;
}else if(strcmp(codeset, "UTF-16") == 0 ||
strcmp(codeset, "UTF-16BE-BOM") == 0){
- output_conv = w_oconv16;
- unicode_bom_f=2;
+ output_conv = w_oconv16;
+ output_bom_f = TRUE;
}else if(strcmp(codeset, "UTF-16LE") == 0){
- output_conv = w_oconv16;
- w_oconv16_LE = 1;
- unicode_bom_f=1;
+ output_conv = w_oconv16;
+ output_endian = ENDIAN_LITTLE;
}else if(strcmp(codeset, "UTF-16LE-BOM") == 0){
- output_conv = w_oconv16;
- w_oconv16_LE = 1;
- unicode_bom_f=2;
+ output_conv = w_oconv16;
+ output_endian = ENDIAN_LITTLE;
+ output_bom_f = TRUE;
+ }else if(strcmp(codeset, "UTF-32") == 0 ||
+ strcmp(codeset, "UTF-32BE") == 0){
+ output_conv = w_oconv32;
+ }else if(strcmp(codeset, "UTF-32BE-BOM") == 0){
+ output_conv = w_oconv32;
+ output_bom_f = TRUE;
+ }else if(strcmp(codeset, "UTF-32LE") == 0){
+ output_conv = w_oconv32;
+ output_endian = ENDIAN_LITTLE;
+ }else if(strcmp(codeset, "UTF-32LE-BOM") == 0){
+ output_conv = w_oconv32;
+ output_endian = ENDIAN_LITTLE;
+ output_bom_f = TRUE;
#endif
}
continue;
@@ -1649,6 +1670,7 @@ void options(unsigned char *cp)
continue;
case 'e': /* AT&T EUC output */
output_conv = e_oconv;
+ cp932inv_f = FALSE;
continue;
case 's': /* SJIS output */
output_conv = s_oconv;
@@ -1695,57 +1717,72 @@ void options(unsigned char *cp)
#endif
#ifdef UTF8_OUTPUT_ENABLE
case 'w': /* UTF-8 output */
- if ('1'== cp[0] && '6'==cp[1]) {
- output_conv = w_oconv16; cp+=2;
+ if (cp[0] == '8') {
+ output_conv = w_oconv; cp++;
+ if (cp[0] == '0'){
+ cp++;
+ } else {
+ output_bom_f = TRUE;
+ }
+ } else {
+ if ('1'== cp[0] && '6'==cp[1]) {
+ output_conv = w_oconv16; cp+=2;
+ } else if ('3'== cp[0] && '2'==cp[1]) {
+ output_conv = w_oconv32; cp+=2;
+ } else {
+ output_conv = w_oconv;
+ continue;
+ }
if (cp[0]=='L') {
- unicode_bom_f=2; cp++;
- w_oconv16_LE = 1;
- if (cp[0] == '0'){
- unicode_bom_f=1; cp++;
- }
+ cp++;
+ output_endian = ENDIAN_LITTLE;
} else if (cp[0] == 'B') {
- unicode_bom_f=2; cp++;
- if (cp[0] == '0'){
- unicode_bom_f=1; cp++;
- }
- }
- } else if (cp[0] == '8') {
- output_conv = w_oconv; cp++;
- unicode_bom_f=2;
+ cp++;
+ } else {
+ continue;
+ }
if (cp[0] == '0'){
- unicode_bom_f=1; cp++;
+ cp++;
+ } else {
+ output_bom_f = TRUE;
}
- } else
- output_conv = w_oconv;
+ }
continue;
#endif
#ifdef UTF8_INPUT_ENABLE
- case 'W': /* UTF-8 input */
- if ('1'== cp[0] && '6'==cp[1]) {
- input_f = UTF16BE_INPUT;
- utf16_mode = UTF16BE_INPUT;
- cp += 2;
+ case 'W': /* UTF input */
+ if (cp[0] == '8') {
+ cp++;
+ input_f = UTF8_INPUT;
+ }else{
+ if ('1'== cp[0] && '6'==cp[1]) {
+ cp += 2;
+ input_f = UTF16_INPUT;
+ input_endian = ENDIAN_BIG;
+ } else if ('3'== cp[0] && '2'==cp[1]) {
+ cp += 2;
+ input_f = UTF32_INPUT;
+ input_endian = ENDIAN_BIG;
+ } else {
+ input_f = UTF8_INPUT;
+ continue;
+ }
if (cp[0]=='L') {
cp++;
- input_f = UTF16LE_INPUT;
- utf16_mode = UTF16LE_INPUT;
+ input_endian = ENDIAN_LITTLE;
} else if (cp[0] == 'B') {
cp++;
- input_f = UTF16BE_INPUT;
- utf16_mode = UTF16BE_INPUT;
}
- } else if (cp[0] == '8') {
- cp++;
- input_f = UTF8_INPUT;
- } else
- input_f = UTF8_INPUT;
+ }
continue;
#endif
/* Input code assumption */
case 'J': /* JIS input */
- case 'E': /* AT&T EUC input */
input_f = JIS_INPUT;
continue;
+ case 'E': /* AT&T EUC input */
+ input_f = EUC_INPUT;
+ continue;
case 'S': /* MS Kanji input */
input_f = SJIS_INPUT;
if (x0201_f==NO_X0201) x0201_f=TRUE;
@@ -1874,12 +1911,7 @@ void options(unsigned char *cp)
}
}
-#ifdef ANSI_C_PROTOTYPE
struct input_code * find_inputcode_byfunc(nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
-#else
-struct input_code * find_inputcode_byfunc(iconv_func)
- nkf_char (*iconv_func)();
-#endif
{
if (iconv_func){
struct input_code *p = input_code_list;
@@ -2135,52 +2167,6 @@ void e_status(struct input_code *ptr, nkf_char c)
}
#ifdef UTF8_INPUT_ENABLE
-void w16_status(struct input_code *ptr, nkf_char c)
-{
- switch (ptr->stat){
- case -1:
- break;
- case 0:
- if (ptr->_file_stat == 0){
- if (c == 0xfe || c == 0xff){
- ptr->stat = c;
- status_push_ch(ptr, c);
- ptr->_file_stat = 1;
- }else{
- status_disable(ptr);
- ptr->_file_stat = -1;
- }
- }else if (ptr->_file_stat > 0){
- ptr->stat = 1;
- status_push_ch(ptr, c);
- }else if (ptr->_file_stat < 0){
- status_disable(ptr);
- }
- break;
-
- case 1:
- if (c == EOF){
- status_disable(ptr);
- ptr->_file_stat = -1;
- }else{
- status_push_ch(ptr, c);
- status_clear(ptr);
- }
- break;
-
- case 0xfe:
- case 0xff:
- if (ptr->stat != c && (c == 0xfe || c == 0xff)){
- status_push_ch(ptr, c);
- status_clear(ptr);
- }else{
- status_disable(ptr);
- ptr->_file_stat = -1;
- }
- break;
- }
-}
-
void w_status(struct input_code *ptr, nkf_char c)
{
switch (ptr->stat){
@@ -2200,6 +2186,9 @@ void w_status(struct input_code *ptr, nkf_char c)
}else if (0xe0 <= c && c <= 0xef){
ptr->stat = 2;
status_push_ch(ptr, c);
+ }else if (0xf0 <= c && c <= 0xf4){
+ ptr->stat = 3;
+ status_push_ch(ptr, c);
}else{
status_disable(ptr);
}
@@ -2222,6 +2211,17 @@ void w_status(struct input_code *ptr, nkf_char c)
status_disable(ptr);
}
break;
+ case 3:
+ if (0x80 <= c && c <= 0xbf){
+ if (ptr->index < ptr->stat){
+ status_push_ch(ptr, c);
+ } else {
+ status_clear(ptr);
+ }
+ }else{
+ status_disable(ptr);
+ }
+ break;
}
}
#endif
@@ -2232,6 +2232,12 @@ void code_status(nkf_char c)
struct input_code *result = 0;
struct input_code *p = input_code_list;
while (p->name){
+ if (!p->status_func) {
+ ++p;
+ continue;
+ }
+ if (!p->status_func)
+ continue;
(p->status_func)(p, c);
if (p->stat > 0){
action_flag = 0;
@@ -2374,17 +2380,17 @@ void module_connection(void)
i_bgetc = i_getc; i_getc = broken_getc;
i_bungetc = i_ungetc; i_ungetc = broken_ungetc;
}
- if (input_f == JIS_INPUT || input_f == LATIN1_INPUT) {
+ if (input_f == JIS_INPUT || input_f == EUC_INPUT || input_f == LATIN1_INPUT) {
set_iconv(-TRUE, e_iconv);
} else if (input_f == SJIS_INPUT) {
set_iconv(-TRUE, s_iconv);
#ifdef UTF8_INPUT_ENABLE
} else if (input_f == UTF8_INPUT) {
set_iconv(-TRUE, w_iconv);
- } else if (input_f == UTF16BE_INPUT) {
- set_iconv(-TRUE, w_iconv16);
- } else if (input_f == UTF16LE_INPUT) {
+ } else if (input_f == UTF16_INPUT) {
set_iconv(-TRUE, w_iconv16);
+ } else if (input_f == UTF32_INPUT) {
+ set_iconv(-TRUE, w_iconv32);
#endif
} else {
set_iconv(FALSE, e_iconv);
@@ -2399,27 +2405,133 @@ void module_connection(void)
}
/*
+ * Check and Ignore BOM
+ */
+void check_bom(FILE *f)
+{
+ int c2;
+ switch(c2 = (*i_getc)(f)){
+ case 0x00:
+ if((c2 = (*i_getc)(f)) == 0x00){
+ if((c2 = (*i_getc)(f)) == 0xFE){
+ if((c2 = (*i_getc)(f)) == 0xFF){
+ if(!input_f){
+ set_iconv(TRUE, w_iconv32);
+ }
+ if (iconv == w_iconv32) {
+ input_endian = ENDIAN_BIG;
+ return;
+ }
+ (*i_ungetc)(0xFF,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0xFE,f);
+ }else if(c2 == 0xFF){
+ if((c2 = (*i_getc)(f)) == 0xFE){
+ if(!input_f){
+ set_iconv(TRUE, w_iconv32);
+ }
+ if (iconv == w_iconv32) {
+ input_endian = ENDIAN_2143;
+ return;
+ }
+ (*i_ungetc)(0xFF,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0xFF,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0x00,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0x00,f);
+ break;
+ case 0xEF:
+ if((c2 = (*i_getc)(f)) == 0xBB){
+ if((c2 = (*i_getc)(f)) == 0xBF){
+ if(!input_f){
+ set_iconv(TRUE, w_iconv);
+ }
+ if (iconv == w_iconv) {
+ return;
+ }
+ (*i_ungetc)(0xBF,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0xBB,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0xEF,f);
+ break;
+ case 0xFE:
+ if((c2 = (*i_getc)(f)) == 0xFF){
+ if((c2 = (*i_getc)(f)) == 0x00){
+ if((c2 = (*i_getc)(f)) == 0x00){
+ if(!input_f){
+ set_iconv(TRUE, w_iconv32);
+ }
+ if (iconv == w_iconv32) {
+ input_endian = ENDIAN_3412;
+ return;
+ }
+ (*i_ungetc)(0x00,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0x00,f);
+ }else (*i_ungetc)(c2,f);
+ if(!input_f){
+ set_iconv(TRUE, w_iconv16);
+ }
+ if (iconv == w_iconv16) {
+ input_endian = ENDIAN_BIG;
+ return;
+ }
+ (*i_ungetc)(0xFF,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0xFE,f);
+ break;
+ case 0xFF:
+ if((c2 = (*i_getc)(f)) == 0xFE){
+ if((c2 = (*i_getc)(f)) == 0x00){
+ if((c2 = (*i_getc)(f)) == 0x00){
+ if(!input_f){
+ set_iconv(TRUE, w_iconv32);
+ }
+ if (iconv == w_iconv32) {
+ input_endian = ENDIAN_LITTLE;
+ return;
+ }
+ (*i_ungetc)(0x00,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0x00,f);
+ }else (*i_ungetc)(c2,f);
+ if(!input_f){
+ set_iconv(TRUE, w_iconv16);
+ }
+ if (iconv == w_iconv16) {
+ input_endian = ENDIAN_LITTLE;
+ return;
+ }
+ (*i_ungetc)(0xFE,f);
+ }else (*i_ungetc)(c2,f);
+ (*i_ungetc)(0xFF,f);
+ break;
+ default:
+ (*i_ungetc)(c2,f);
+ break;
+ }
+}
+
+/*
Conversion main loop. Code detection only.
*/
nkf_char kanji_convert(FILE *f)
{
- nkf_char c1,
- c2, c3;
+ nkf_char c3, c2=0, c1, c0=0;
int is_8bit = FALSE;
- module_connection();
- c2 = 0;
-
- if(input_f == SJIS_INPUT
+ if(input_f == SJIS_INPUT || input_f == EUC_INPUT
#ifdef UTF8_INPUT_ENABLE
- || input_f == UTF8_INPUT || input_f == UTF16BE_INPUT || input_f == UTF16LE_INPUT
+ || input_f == UTF8_INPUT || input_f == UTF16_INPUT
#endif
){
is_8bit = TRUE;
}
-
input_mode = ASCII;
output_mode = ASCII;
shift_mode = FALSE;
@@ -2428,6 +2540,9 @@ nkf_char kanji_convert(FILE *f)
#define SEND ; /* output c1 and c2, get next */
#define LAST break /* end of loop, go closing */
+ module_connection();
+ check_bom(f);
+
while ((c1 = (*i_getc)(f)) != EOF) {
#ifdef INPUT_CODE_FIX
if (!input_f)
@@ -2435,7 +2550,7 @@ nkf_char kanji_convert(FILE *f)
code_status(c1);
if (c2) {
/* second byte */
- if (c2 > DEL) {
+ if (c2 > ((input_f == JIS_INPUT && ms_ucs_map_f) ? 0x92 : DEL)) {
/* in case of 8th bit is on */
if (!estab_f&&!mime_decode_mode) {
/* in case of not established yet */
@@ -2445,14 +2560,16 @@ nkf_char kanji_convert(FILE *f)
else
c2 = 0;
NEXT;
- } else
- /* in case of already established */
- if (c1 < AT) {
- /* ignore bogus code */
- c2 = 0;
- NEXT;
- } else
- SEND;
+ } else {
+ /* in case of already established */
+ if (c1 < AT) {
+ /* ignore bogus code and not CP5022x UCD */
+ c2 = 0;
+ NEXT;
+ } else {
+ SEND;
+ }
+ }
} else
/* second byte, 7 bit code */
/* it might be kanji shitfted */
@@ -2464,25 +2581,68 @@ nkf_char kanji_convert(FILE *f)
SEND;
} else {
/* first byte */
- if (
#ifdef UTF8_INPUT_ENABLE
- iconv == w_iconv16
-#else
- 0
-#endif
- ) {
- c2 = c1;
- c1 = (*i_getc)(f);
+ if (iconv == w_iconv16) {
+ if (input_endian == ENDIAN_BIG) {
+ c2 = c1;
+ if ((c1 = (*i_getc)(f)) != EOF) {
+ if (0xD8 <= c2 && c2 <= 0xDB) {
+ if ((c0 = (*i_getc)(f)) != EOF) {
+ c0 <<= 8;
+ if ((c3 = (*i_getc)(f)) != EOF) {
+ c0 |= c3;
+ } else c2 = EOF;
+ } else c2 = EOF;
+ }
+ } else c2 = EOF;
+ } else {
+ if ((c2 = (*i_getc)(f)) != EOF) {
+ if (0xD8 <= c2 && c2 <= 0xDB) {
+ if ((c3 = (*i_getc)(f)) != EOF) {
+ if ((c0 = (*i_getc)(f)) != EOF) {
+ c0 <<= 8;
+ c0 |= c3;
+ } else c2 = EOF;
+ } else c2 = EOF;
+ }
+ } else c2 = EOF;
+ }
SEND;
+ } else if(iconv == w_iconv32){
+ int c3 = c1;
+ if((c2 = (*i_getc)(f)) != EOF &&
+ (c1 = (*i_getc)(f)) != EOF &&
+ (c0 = (*i_getc)(f)) != EOF){
+ switch(input_endian){
+ case ENDIAN_BIG:
+ c1 = (c2&0xFF)<<16 | (c1&0xFF)<<8 | (c0&0xFF);
+ break;
+ case ENDIAN_LITTLE:
+ c1 = (c3&0xFF) | (c2&0xFF)<<8 | (c1&0xFF)<<16;
+ break;
+ case ENDIAN_2143:
+ c1 = (c3&0xFF)<<16 | (c1&0xFF) | (c0&0xFF)<<8;
+ break;
+ case ENDIAN_3412:
+ c1 = (c3&0xFF)<<8 | (c2&0xFF) | (c0&0xFF)<<16;
+ break;
+ }
+ c2 = 0;
+ }else{
+ c2 = EOF;
+ }
+ SEND;
+ } else
+#endif
#ifdef NUMCHAR_OPTION
- } else if (is_unicode_capsule(c1)){
+ if (is_unicode_capsule(c1)){
SEND;
+ } else
#endif
- } else if (c1 > DEL) {
+ if (c1 > ((input_f == JIS_INPUT && ms_ucs_map_f) ? 0x92 : DEL)) {
/* 8 bit code */
if (!estab_f && !iso8859_f) {
/* not established yet */
- if (!is_8bit) is_8bit = TRUE;
c2 = c1;
NEXT;
} else { /* estab_f==TRUE */
@@ -2573,13 +2733,13 @@ nkf_char kanji_convert(FILE *f)
/* normal ASCII code */
SEND;
}
- } else if (!is_8bit && c1 == SI) {
+ } else if (c1 == SI && (!is_8bit || mime_decode_mode)) {
shift_mode = FALSE;
NEXT;
- } else if (!is_8bit && c1 == SO) {
+ } else if (c1 == SO && (!is_8bit || mime_decode_mode)) {
shift_mode = TRUE;
NEXT;
- } else if (!is_8bit && c1 == ESC ) {
+ } else if (c1 == ESC && (!is_8bit || mime_decode_mode)) {
if ((c1 = (*i_getc)(f)) == EOF) {
/* (*oconv)(0, ESC); don't send bogus code */
LAST;
@@ -2687,6 +2847,44 @@ nkf_char kanji_convert(FILE *f)
(*oconv)(0, ESC);
SEND;
}
+ } else if (c1 == ESC && iconv == s_iconv) {
+ /* ESC in Shift_JIS */
+ if ((c1 = (*i_getc)(f)) == EOF) {
+ /* (*oconv)(0, ESC); don't send bogus code */
+ LAST;
+ } else if (c1 == '$') {
+ /* J-PHONE emoji */
+ if ((c1 = (*i_getc)(f)) == EOF) {
+ /*
+ (*oconv)(0, ESC); don't send bogus code
+ (*oconv)(0, '$'); */
+ LAST;
+ } else {
+ if (('E' <= c1 && c1 <= 'G') ||
+ ('O' <= c1 && c1 <= 'Q')) {
+ /*
+ NUM : 0 1 2 3 4 5
+ BYTE: G E F O P Q
+ C%7 : 1 6 0 2 3 4
+ 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] = {2, 0, 3, 4, 5, 0, 1};
+ c0 = (jphone_emoji_first_table[c1 % 7] << 8) - SPACE + 0xE000 + CLASS_UNICODE;
+ while ((c1 = (*i_getc)(f)) != EOF) {
+ if (SPACE <= c1 && c1 <= 'z') {
+ (*oconv)(0, c1 + c0);
+ } else break; /* c1 == SO */
+ }
+ }
+ }
+ if (c1 == EOF) LAST;
+ NEXT;
+ } else {
+ /* lonely ESC */
+ (*oconv)(0, ESC);
+ SEND;
+ }
} else if ((c1 == NL || c1 == CR) && broken_f&4) {
input_mode = ASCII; set_iconv(FALSE, 0);
SEND;
@@ -2716,22 +2914,47 @@ nkf_char kanji_convert(FILE *f)
}
c1 = CR;
SEND;
+ } else if (c1 == DEL && input_mode == X0208 ) {
+ /* CP5022x */
+ c2 = c1;
+ NEXT;
} else
SEND;
}
/* send: */
switch(input_mode){
case ASCII:
- if ((*iconv)(c2, c1, 0) < 0){ /* can be EUC/SJIS */
- nkf_char c0 = (*i_getc)(f);
- if (c0 != EOF){
+ switch ((*iconv)(c2, c1, c0)) { /* can be EUC / SJIS / UTF-8 / UTF-16 */
+ case -2:
+ /* 4 bytes UTF-8 */
+ if ((c0 = (*i_getc)(f)) != EOF) {
+ code_status(c0);
+ c0 <<= 8;
+ if ((c3 = (*i_getc)(f)) != EOF) {
+ code_status(c3);
+ (*iconv)(c2, c1, c0|c3);
+ }
+ }
+ break;
+ case -1:
+ /* 3 bytes EUC or UTF-8 */
+ if ((c0 = (*i_getc)(f)) != EOF) {
code_status(c0);
(*iconv)(c2, c1, c0);
}
+ break;
}
break;
case X0208:
case X0213_1:
+ if (ms_ucs_map_f &&
+ 0x7F <= c2 && c2 <= 0x92 &&
+ 0x21 <= c1 && c1 <= 0x7E) {
+ /* CP932 UDC */
+ if(c1 == 0x7F) return 0;
+ c1 = (c2 - 0x7F) * 94 + c1 - 0x21 + 0xE000 + CLASS_UNICODE;
+ c2 = 0;
+ }
(*oconv)(c2, c1); /* this is JIS, not SJIS/EUC case */
break;
#ifdef X0212_ENABLE
@@ -2747,6 +2970,7 @@ nkf_char kanji_convert(FILE *f)
}
c2 = 0;
+ c0 = 0;
continue;
/* goto next_word */
}
@@ -2771,7 +2995,8 @@ nkf_char kanji_convert(FILE *f)
nkf_char
h_conv(FILE *f, nkf_char c2, nkf_char c1)
{
- nkf_char wc,c3;
+ nkf_char ret, c3, c0;
+ int hold_index;
/** it must NOT be in the kanji shifte sequence */
@@ -2818,10 +3043,10 @@ h_conv(FILE *f, nkf_char c2, nkf_char c1)
** Kanji codes by oconv and leave estab_f unchanged.
**/
- c3=c1;
- wc = 0;
- while (wc < hold_count){
- c2 = hold_buf[wc++];
+ ret = c1;
+ hold_index = 0;
+ while (hold_index < hold_count){
+ c2 = hold_buf[hold_index++];
if (c2 <= DEL
#ifdef NUMCHAR_OPTION
|| is_unicode_capsule(c2)
@@ -2833,8 +3058,8 @@ h_conv(FILE *f, nkf_char c2, nkf_char c1)
(*iconv)(X0201, c2, 0);
continue;
}
- if (wc < hold_count){
- c1 = hold_buf[wc++];
+ if (hold_index < hold_count){
+ c1 = hold_buf[hold_index++];
}else{
c1 = (*i_getc)(f);
if (c1 == EOF){
@@ -2843,28 +3068,48 @@ h_conv(FILE *f, nkf_char c2, nkf_char c1)
}
code_status(c1);
}
- if ((*iconv)(c2, c1, 0) < 0){
- nkf_char c0;
- if (wc < hold_count){
- c0 = hold_buf[wc++];
- }else{
- c0 = (*i_getc)(f);
- if (c0 == EOF){
- c3 = EOF;
- break;
- }
+ c0 = 0;
+ switch ((*iconv)(c2, c1, 0)) { /* can be EUC/SJIS/UTF-8 */
+ case -2:
+ /* 4 bytes UTF-8 */
+ if (hold_index < hold_count){
+ c0 = hold_buf[hold_index++];
+ } else if ((c0 = (*i_getc)(f)) == EOF) {
+ ret = EOF;
+ break;
+ } else {
+ code_status(c0);
+ c0 <<= 8;
+ if (hold_index < hold_count){
+ c3 = hold_buf[hold_index++];
+ } else if ((c3 = (*i_getc)(f)) == EOF) {
+ c0 = ret = EOF;
+ break;
+ } else {
+ code_status(c3);
+ (*iconv)(c2, c1, c0|c3);
+ }
+ }
+ break;
+ case -1:
+ /* 3 bytes EUC or UTF-8 */
+ if (hold_index < hold_count){
+ c0 = hold_buf[hold_index++];
+ } else if ((c0 = (*i_getc)(f)) == EOF) {
+ ret = EOF;
+ break;
+ } else {
code_status(c0);
}
(*iconv)(c2, c1, c0);
- }
+ break;
+ }
+ if (c0 == EOF) break;
}
- return c3;
+ return ret;
}
-
-
-nkf_char
-push_hold_buf(nkf_char c2)
+nkf_char push_hold_buf(nkf_char c2)
{
if (hold_count >= HOLD_SIZE*2)
return (EOF);
@@ -2879,7 +3124,7 @@ nkf_char s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
#endif
static const nkf_char shift_jisx0213_s1a3_table[5][2] ={ { 1, 8}, { 3, 4}, { 5,12}, {13,14}, {15, 0} };
#ifdef SHIFTJIS_CP932
- if (cp51932_f && is_ibmext_in_sjis(c2)){
+ if (!cp932inv_f && is_ibmext_in_sjis(c2)){
#if 0
extern const unsigned short shiftjis_cp932[3][189];
#endif
@@ -2889,6 +3134,17 @@ nkf_char s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
c1 = val & 0xff;
}
}
+ if (cp932inv_f
+ && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
+#if 0
+ extern const unsigned short cp932inv[2][189];
+#endif
+ nkf_char c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
+ if (c){
+ c2 = c >> 8;
+ c1 = c & 0xff;
+ }
+ }
#endif /* SHIFTJIS_CP932 */
#ifdef X0212_ENABLE
if (!x0213_f && is_ibmext_in_sjis(c2)){
@@ -2898,7 +3154,7 @@ nkf_char s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
val = shiftjis_x0212[c2 - 0xfa][c1 - 0x40];
if (val){
if (val > 0x7FFF){
- c2 = PREFIX_EUCG3 | (val >> 8);
+ c2 = PREFIX_EUCG3 | ((val >> 8) & 0x7f);
c1 = val & 0xff;
}else{
c2 = val >> 8;
@@ -2943,6 +3199,11 @@ nkf_char s_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
c1 &= 0x7f;
} else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
/* NOP */
+ } else if (!x0213_f && 0xF0 <= c2 && c2 <= 0xF9 && 0x40 <= c1 && c1 <= 0xFC) {
+ /* CP932 UDC */
+ if(c1 == 0x7F) return 0;
+ c1 = (c2 - 0xF0) * 188 + (c1 - 0x40 - (0x7E < c1)) + 0xE000 + CLASS_UNICODE;
+ c2 = 0;
} else {
nkf_char ret = s2e_conv(c2, c1, &c2, &c1);
if (ret) return ret;
@@ -2960,20 +3221,26 @@ nkf_char e_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
if (c0 == 0){
return -1;
}
- c2 = (c2 << 8) | (c1 & 0x7f);
- c1 = c0 & 0x7f;
+ if (!cp51932_f && !x0213_f && 0xF5 <= c1 && c1 <= 0xFE && 0xA1 <= c0 && c0 <= 0xFE) {
+ /* encoding is eucJP-ms, so invert to Unicode Private User Area */
+ c1 = (c1 - 0xF5) * 94 + c0 - 0xA1 + 0xE3AC + CLASS_UNICODE;
+ c2 = 0;
+ } else {
+ c2 = (c2 << 8) | (c1 & 0x7f);
+ c1 = c0 & 0x7f;
#ifdef SHIFTJIS_CP932
- if (cp51932_f){
- nkf_char s2, s1;
- if (e2s_conv(c2, c1, &s2, &s1) == 0){
- s2e_conv(s2, s1, &c2, &c1);
- if (c2 < 0x100){
- c1 &= 0x7f;
- c2 &= 0x7f;
- }
- }
- }
+ if (cp51932_f){
+ nkf_char s2, s1;
+ if (e2s_conv(c2, c1, &s2, &s1) == 0){
+ s2e_conv(s2, s1, &c2, &c1);
+ if (c2 < 0x100){
+ c1 &= 0x7f;
+ c2 &= 0x7f;
+ }
+ }
+ }
#endif /* SHIFTJIS_CP932 */
+ }
#endif /* X0212_ENABLE */
} else if (c2 == SSO){
c2 = X0201;
@@ -2981,8 +3248,26 @@ nkf_char e_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
} else if ((c2 == EOF) || (c2 == 0) || c2 < SPACE) {
/* NOP */
} else {
- c1 &= 0x7f;
- c2 &= 0x7f;
+ if (!cp51932_f && ms_ucs_map_f && 0xF5 <= c2 && c2 <= 0xFE && 0xA1 <= c1 && c1 <= 0xFE) {
+ /* encoding is eucJP-ms, so invert to Unicode Private User Area */
+ c1 = (c2 - 0xF5) * 94 + c1 - 0xA1 + 0xE000 + CLASS_UNICODE;
+ c2 = 0;
+ } else {
+ c1 &= 0x7f;
+ c2 &= 0x7f;
+#ifdef SHIFTJIS_CP932
+ if (cp51932_f && 0x79 <= c2 && c2 <= 0x7c){
+ nkf_char s2, s1;
+ if (e2s_conv(c2, c1, &s2, &s1) == 0){
+ s2e_conv(s2, s1, &c2, &c1);
+ if (c2 < 0x100){
+ c1 &= 0x7f;
+ c2 &= 0x7f;
+ }
+ }
+ }
+#endif /* SHIFTJIS_CP932 */
+ }
}
(*oconv)(c2, c1);
return 0;
@@ -3001,7 +3286,7 @@ nkf_char w2e_conv(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char
#ifdef NUMCHAR_OPTION
if (ret > 0){
if (p2) *p2 = 0;
- if (p1) *p1 = CLASS_UTF16 | ww16_conv(c2, c1, c0);
+ if (p1) *p1 = CLASS_UNICODE | ww16_conv(c2, c1, c0);
ret = 0;
}
#endif
@@ -3012,43 +3297,63 @@ nkf_char w2e_conv(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char
nkf_char w_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
{
nkf_char ret = 0;
+ static const int w_iconv_utf8_1st_byte[] =
+ { /* 0xC0 - 0xFF */
+ 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 33, 33,
+ 40, 41, 41, 41, 42, 43, 43, 43, 50, 50, 50, 50, 60, 60, 70, 70};
- /* throw away ZERO WIDTH NO-BREAK SPACE (U+FEFF) */
- if(ignore_zwnbsp_f){
- ignore_zwnbsp_f = FALSE;
- if(c2 == 0xef && c1 == 0xbb && c0 == 0xbf)
- return 0;
- }
-
- if (c2 == 0) /* 0x00-0x7f */
- c1 &= 0x7F; /* 1byte */
- else if (c0 == 0){
- if ((c2 & 0xe0) == 0xc0){ /* 0xc0-0xdf */
- /* 2ytes */
- if((c2 & 0xFE) == 0xC0 || c1 < 0x80 || 0xBF < c1) return 0;
- }else if ((c2 & 0xf0) == 0xe0) /* 0xe0-0xef */
- return -1; /* 3bytes */
-#ifdef __COMMENT__
- else if (0xf0 <= c2)
- return 0; /* 4,5,6bytes */
- else if ((c2 & 0xc0) == 0x80) /* 0x80-0xbf */
- return 0; /* trail byte */
-#endif
- else return 0;
- }else{
- /* must be 3bytes */
- if(c2 == 0xE0){
- if(c1 < 0xA0 || 0xBF < c1 || c0 < 0x80 || 0xBF < c0)
+ if (c2 < 0 || 0xff < c2) {
+ }else if (c2 == 0) { /* 0 : 1 byte*/
+ c0 = 0;
+ } else if ((c2 & 0xc0) == 0x80) { /* 0x80-0xbf : trail byte */
+ return 0;
+ } else{
+ switch (w_iconv_utf8_1st_byte[c2 - 0xC0]) {
+ case 21:
+ if (c1 < 0x80 || 0xBF < c1) return 0;
+ break;
+ case 30:
+ if (c0 == 0) return -1;
+ if (c1 < 0xA0 || 0xBF < c1 || (c0 & 0xc0) != 0x80)
+ return 0;
+ break;
+ case 31:
+ case 33:
+ if (c0 == 0) return -1;
+ if ((c1 & 0xc0) != 0x80 || (c0 & 0xc0) != 0x80)
+ return 0;
+ break;
+ case 32:
+ if (c0 == 0) return -1;
+ if (c1 < 0x80 || 0x9F < c1 || (c0 & 0xc0) != 0x80)
+ return 0;
+ break;
+ case 40:
+ if (c0 == 0) return -2;
+ if (c1 < 0x90 || 0xBF < c1 || (c0 & 0xc0c0) != 0x8080)
return 0;
- }else if(c2 == 0xED){
- if(c1 < 0x80 || 0x9F < c1 || c0 < 0x80 || 0xBF < c0)
+ break;
+ case 41:
+ if (c0 == 0) return -2;
+ if (c1 < 0x80 || 0xBF < c1 || (c0 & 0xc0c0) != 0x8080)
return 0;
- }else if((c2 & 0xf0) == 0xe0){
- if(c1 < 0x80 || 0xBF < c1 || c0 < 0x80 || 0xBF < c0)
+ break;
+ case 42:
+ if (c0 == 0) return -2;
+ if (c1 < 0x80 || 0x8F < c1 || (c0 & 0xc0c0) != 0x8080)
return 0;
- }else return 0;
+ break;
+ default:
+ return 0;
+ break;
+ }
}
if (c2 == 0 || c2 == EOF){
+ } else if ((c2 & 0xf8) == 0xf0) { /* 4 bytes */
+ c1 = CLASS_UNICODE | ww16_conv(c2, c1, c0);
+ c2 = 0;
} else {
ret = w2e_conv(c2, c1, c0, &c2, &c1);
}
@@ -3075,6 +3380,10 @@ void w16w_conv(nkf_char val, nkf_char *p2, nkf_char *p1, nkf_char *p0)
*p2 = 0xe0 | (val >> 12);
*p1 = 0x80 | ((val >> 6) & 0x3f);
*p0 = 0x80 | (val & 0x3f);
+ } else if (val <= NKF_INT32_C(0x10FFFF)) {
+ *p2 = 0xe0 | (val >> 16);
+ *p1 = 0x80 | ((val >> 12) & 0x3f);
+ *p0 = 0x8080 | ((val << 2) & 0x3f00)| (val & 0x3f);
} else {
*p2 = 0;
*p1 = 0;
@@ -3087,8 +3396,14 @@ void w16w_conv(nkf_char val, nkf_char *p2, nkf_char *p1, nkf_char *p0)
nkf_char ww16_conv(nkf_char c2, nkf_char c1, nkf_char c0)
{
nkf_char val;
- if (c2 >= 0xf0){
+ if (c2 >= 0xf8) {
val = -1;
+ } else if (c2 >= 0xf0){
+ /* c2: 1st, c1: 2nd, c0: 3rd/4th */
+ val = (c2 & 0x0f) << 18;
+ val |= (c1 & 0x3f) << 12;
+ val |= (c0 & 0x3f00) >> 2;
+ val |= (c0 & 0x3f);
}else if (c2 >= 0xe0){
val = (c2 & 0x0f) << 12;
val |= (c1 & 0x3f) << 6;
@@ -3116,7 +3431,7 @@ nkf_char w16e_conv(nkf_char val, nkf_char *p2, nkf_char *p1)
#ifdef NUMCHAR_OPTION
if (ret > 0){
*p2 = 0;
- *p1 = CLASS_UTF16 | val;
+ *p1 = CLASS_UNICODE | val;
ret = 0;
}
#endif
@@ -3128,27 +3443,19 @@ nkf_char w16e_conv(nkf_char val, nkf_char *p2, nkf_char *p1)
#ifdef UTF8_INPUT_ENABLE
nkf_char w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0)
{
- nkf_char ret;
-
- /* throw away ZERO WIDTH NO-BREAK SPACE (U+FEFF) */
- if(ignore_zwnbsp_f){
- ignore_zwnbsp_f = FALSE;
- if (c2==0376 && c1==0377){
- utf16_mode = UTF16BE_INPUT;
- return 0;
- }else if(c2==0377 && c1==0376){
- utf16_mode = UTF16LE_INPUT;
- return 0;
- }
- }
- if (c2 != EOF && utf16_mode == UTF16LE_INPUT) {
- nkf_char tmp;
- tmp=c1; c1=c2; c2=tmp;
- }
+ nkf_char ret = 0;
if ((c2==0 && c1 < 0x80) || c2==EOF) {
(*oconv)(c2, c1);
return 0;
- }else if((c2>>3)==27){ /* surrogate pair */
+ }else if (0xD8 <= c2 && c2 <= 0xDB) {
+ if (c0 < NKF_INT32_C(0xDC00) || NKF_INT32_C(0xDFFF) < c0)
+ return -2;
+ c1 = CLASS_UNICODE | ((c2 << 18) + (c1 << 10) + c0 - NKF_INT32_C(0x35FDC00));
+ c2 = 0;
+ }else if ((c2>>3) == 27) { /* unpaired surrogate */
+ /*
+ return 2;
+ */
return 1;
}else ret = w16e_conv(((c2 & 0xff)<<8) + c1, &c2, &c1);
if (ret) return ret;
@@ -3156,6 +3463,22 @@ nkf_char w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0)
return 0;
}
+nkf_char w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0)
+{
+ int ret = 0;
+
+ if ((c2 == 0 && c1 < 0x80) || c2==EOF) {
+ } else if (is_unicode_bmp(c1)) {
+ ret = w16e_conv(c1, &c2, &c1);
+ } else {
+ c2 = 0;
+ c1 = CLASS_UNICODE | c1;
+ }
+ if (ret) return ret;
+ (*oconv)(c2, c1);
+ return 0;
+}
+
nkf_char unicode_to_jis_common(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
{
#if 0
@@ -3204,7 +3527,7 @@ nkf_char unicode_to_jis_common(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *
if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1;
break;
}
- }else if(cp51932_f){
+ }else if(!cp932inv_f){
switch(c2){
case 0xC2:
if(no_best_fit_chars_table_C2[c1&0x3F]) return 1;
@@ -3260,7 +3583,7 @@ nkf_char unicode_to_jis_common(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *
if(c0 == 0x8D) return 1;
break;
case 0xBD:
- if(c0 == 0x9E && cp51932_f) return 1;
+ if(c0 == 0x9E && !cp932inv_f) return 1;
break;
case 0xBF:
if(0xA0 <= c0 && c0 <= 0xA5) return 1;
@@ -3277,7 +3600,7 @@ nkf_char unicode_to_jis_common(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *
ret = w_iconv_common(c1, c0, ppp[c2 - 0xE0], sizeof_utf8_to_euc_C2, p2, p1);
}else return -1;
#ifdef SHIFTJIS_CP932
- if (!ret && cp51932_f && is_eucg3(*p2)) {
+ if (!ret && !cp932inv_f && is_eucg3(*p2)) {
nkf_char s2, s1;
if (e2s_conv(*p2, *p1, &s2, &s1) == 0) {
s2e_conv(s2, s1, p2, p1);
@@ -3456,16 +3779,17 @@ void w_oconv(nkf_char c2, nkf_char c1)
{
nkf_char c0;
nkf_char val;
- if (c2 == EOF) {
- (*o_putc)(EOF);
- return;
- }
- if (unicode_bom_f==2) {
- (*o_putc)('\357');
+ if (output_bom_f) {
+ output_bom_f = FALSE;
+ (*o_putc)('\357');
(*o_putc)('\273');
(*o_putc)('\277');
- unicode_bom_f=1;
+ }
+
+ if (c2 == EOF) {
+ (*o_putc)(EOF);
+ return;
}
#ifdef NUMCHAR_OPTION
@@ -3481,7 +3805,7 @@ void w_oconv(nkf_char c2, nkf_char c1)
(*o_putc)(0x80 | ((val >> 6) & 0x3f));
(*o_putc)(0x80 | (val & 0x3f));
} else if (val <= NKF_INT32_C(0x10FFFF)) {
- (*o_putc)(0xE0 | ( val>>18));
+ (*o_putc)(0xF0 | ( val>>18));
(*o_putc)(0x80 | ((val>>12) & 0x3f));
(*o_putc)(0x80 | ((val>> 6) & 0x3f));
(*o_putc)(0x80 | ( val & 0x3f));
@@ -3512,20 +3836,20 @@ void w_oconv(nkf_char c2, nkf_char c1)
void w_oconv16(nkf_char c2, nkf_char c1)
{
- if (c2 == EOF) {
- (*o_putc)(EOF);
- return;
- }
-
- if (unicode_bom_f==2) {
- if (w_oconv16_LE){
+ if (output_bom_f) {
+ output_bom_f = FALSE;
+ if (output_endian == ENDIAN_LITTLE){
(*o_putc)((unsigned char)'\377');
(*o_putc)('\376');
}else{
(*o_putc)('\376');
(*o_putc)((unsigned char)'\377');
}
- unicode_bom_f=1;
+ }
+
+ if (c2 == EOF) {
+ (*o_putc)(EOF);
+ return;
}
if (c2 == ISO8859_1) {
@@ -3541,7 +3865,7 @@ void w_oconv16(nkf_char c2, nkf_char c1)
if (c1 <= UNICODE_MAX) {
c2 = (c1 >> 10) + NKF_INT32_C(0xD7C0); /* high surrogate */
c1 = (c1 & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */
- if (w_oconv16_LE){
+ if (output_endian == ENDIAN_LITTLE){
(*o_putc)(c2 & 0xff);
(*o_putc)((c2 >> 8) & 0xff);
(*o_putc)(c1 & 0xff);
@@ -3560,8 +3884,9 @@ void w_oconv16(nkf_char c2, nkf_char c1)
nkf_char val = e2w_conv(c2, c1);
c2 = (val >> 8) & 0xff;
c1 = val & 0xff;
+ if (!val) return;
}
- if (w_oconv16_LE){
+ if (output_endian == ENDIAN_LITTLE){
(*o_putc)(c1);
(*o_putc)(c2);
}else{
@@ -3570,6 +3895,50 @@ void w_oconv16(nkf_char c2, nkf_char c1)
}
}
+void w_oconv32(nkf_char c2, nkf_char c1)
+{
+ if (output_bom_f) {
+ output_bom_f = FALSE;
+ if (output_endian == ENDIAN_LITTLE){
+ (*o_putc)((unsigned char)'\377');
+ (*o_putc)('\376');
+ (*o_putc)('\000');
+ (*o_putc)('\000');
+ }else{
+ (*o_putc)('\000');
+ (*o_putc)('\000');
+ (*o_putc)('\376');
+ (*o_putc)((unsigned char)'\377');
+ }
+ }
+
+ if (c2 == EOF) {
+ (*o_putc)(EOF);
+ return;
+ }
+
+ if (c2 == ISO8859_1) {
+ c1 |= 0x80;
+#ifdef NUMCHAR_OPTION
+ } else if (c2 == 0 && is_unicode_capsule(c1)) {
+ c1 &= VALUE_MASK;
+#endif
+ } else if (c2) {
+ c1 = e2w_conv(c2, c1);
+ if (!c1) return;
+ }
+ if (output_endian == ENDIAN_LITTLE){
+ (*o_putc)( c1 & NKF_INT32_C(0x000000FF));
+ (*o_putc)((c1 & NKF_INT32_C(0x0000FF00)) >> 8);
+ (*o_putc)((c1 & NKF_INT32_C(0x00FF0000)) >> 16);
+ (*o_putc)('\000');
+ }else{
+ (*o_putc)('\000');
+ (*o_putc)((c1 & NKF_INT32_C(0x00FF0000)) >> 16);
+ (*o_putc)((c1 & NKF_INT32_C(0x0000FF00)) >> 8);
+ (*o_putc)( c1 & NKF_INT32_C(0x000000FF));
+ }
+}
#endif
void e_oconv(nkf_char c2, nkf_char c1)
@@ -3578,8 +3947,26 @@ void e_oconv(nkf_char c2, nkf_char c1)
if (c2 == 0 && is_unicode_capsule(c1)){
w16e_conv(c1, &c2, &c1);
if (c2 == 0 && is_unicode_capsule(c1)){
- if(encode_fallback)(*encode_fallback)(c1);
- return;
+ c2 = c1 & VALUE_MASK;
+ if (x0212_f && 0xE000 <= c2 && c2 <= 0xE757) {
+ /* eucJP-ms UDC */
+ c1 &= 0xFFF;
+ c2 = c1 / 94;
+ c2 += c2 < 10 ? 0x75 : 0x8FEB;
+ c1 = 0x21 + c1 % 94;
+ if (is_eucg3(c2)){
+ (*o_putc)(0x8f);
+ (*o_putc)((c2 & 0x7f) | 0x080);
+ (*o_putc)(c1 | 0x080);
+ }else{
+ (*o_putc)((c2 & 0x7f) | 0x080);
+ (*o_putc)(c1 | 0x080);
+ }
+ return;
+ } else {
+ if (encode_fallback) (*encode_fallback)(c1);
+ return;
+ }
}
}
#endif
@@ -3599,7 +3986,7 @@ void e_oconv(nkf_char c2, nkf_char c1)
} else if (is_eucg3(c2)){
output_mode = JAPANESE_EUC;
#ifdef SHIFTJIS_CP932
- if (cp51932_f){
+ if (!cp932inv_f){
nkf_char s2, s1;
if (e2s_conv(c2, c1, &s2, &s1) == 0){
s2e_conv(s2, s1, &c2, &c1);
@@ -3665,7 +4052,7 @@ nkf_char e2s_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
{
nkf_char ndx;
if (is_eucg3(c2)){
- ndx = c2 & 0xff;
+ ndx = c2 & 0x7f;
if (x0213_f){
if((0x21 <= ndx && ndx <= 0x2F)){
if (p2) *p2 = ((ndx - 1) >> 1) + 0xec - ndx / 8 * 3;
@@ -3712,9 +4099,21 @@ void s_oconv(nkf_char c2, nkf_char c1)
if (c2 == 0 && is_unicode_capsule(c1)){
w16e_conv(c1, &c2, &c1);
if (c2 == 0 && is_unicode_capsule(c1)){
- if(encode_fallback)(*encode_fallback)(c1);
- return;
- }
+ c2 = c1 & VALUE_MASK;
+ if (!x0213_f && 0xE000 <= c2 && c2 <= 0xE757) {
+ /* CP932 UDC */
+ c1 &= 0xFFF;
+ c2 = c1 / 188 + 0xF0;
+ c1 = c1 % 188;
+ c1 += 0x40 + (c1 > 0x3e);
+ (*o_putc)(c2);
+ (*o_putc)(c1);
+ return;
+ } else {
+ if(encode_fallback)(*encode_fallback)(c1);
+ return;
+ }
+ }
}
#endif
if (c2 == EOF) {
@@ -3773,8 +4172,16 @@ void j_oconv(nkf_char c2, nkf_char c1)
if (c2 == 0 && is_unicode_capsule(c1)){
w16e_conv(c1, &c2, &c1);
if (c2 == 0 && is_unicode_capsule(c1)){
- if(encode_fallback)(*encode_fallback)(c1);
- return;
+ c2 = c1 & VALUE_MASK;
+ if (ms_ucs_map_f && 0xE000 <= c2 && c2 <= 0xE757) {
+ /* CP5022x UDC */
+ c1 &= 0xFFF;
+ c2 = 0x7F + c1 / 94;
+ c1 = 0x21 + c1 % 94;
+ } else {
+ if (encode_fallback) (*encode_fallback)(c1);
+ return;
+ }
}
}
#endif
@@ -3831,7 +4238,9 @@ void j_oconv(nkf_char c2, nkf_char c1)
}
(*o_putc)(c1);
} else {
- if(c2<0x20 || 0x7e<c2 || c1<0x20 || 0x7e<c1) return;
+ if(ms_ucs_map_f
+ ? c2<0x20 || 0x92<c2 || c1<0x20 || 0x7e<c1
+ : c2<0x20 || 0x7e<c2 || c1<0x20 || 0x7e<c1) return;
if(x0213_f){
if (output_mode!=X0213_1) {
output_mode = X0213_1;
@@ -4235,7 +4644,7 @@ void hira_conv(nkf_char c2, nkf_char c1)
return;
} else if (c1 == 0x74 && (output_conv == w_oconv || output_conv == w_oconv16)) {
c2 = 0;
- c1 = CLASS_UTF16 | 0x3094;
+ c1 = CLASS_UNICODE | 0x3094;
(*o_hira_conv)(c2,c1);
return;
}
@@ -4246,7 +4655,7 @@ void hira_conv(nkf_char c2, nkf_char c1)
}
}
if (hira_f & 2) {
- if (c2 == 0 && c1 == (CLASS_UTF16 | 0x3094)) {
+ if (c2 == 0 && c1 == (CLASS_UNICODE | 0x3094)) {
c2 = 0x25;
c1 = 0x74;
} else if (c2 == 0x24 && 0x20 < c1 && c1 < 0x74) {
@@ -4634,7 +5043,7 @@ nkf_char numchar_getc(FILE *f)
}
}
if (c != -1){
- return CLASS_UTF16 | c;
+ return CLASS_UNICODE | c;
}
while (i > 0){
(*u)(buf[i], f);
@@ -5409,14 +5818,14 @@ void reinit(void)
#endif
#ifdef UTF8_INPUT_ENABLE
no_cp932ext_f = FALSE;
- ignore_zwnbsp_f = TRUE;
no_best_fit_chars_f = FALSE;
encode_fallback = NULL;
unicode_subchar = '?';
+ input_endian = ENDIAN_BIG;
#endif
#ifdef UTF8_OUTPUT_ENABLE
- unicode_bom_f = 0;
- w_oconv16_LE = 0;
+ output_bom_f = FALSE;
+ output_endian = ENDIAN_BIG;
#endif
#ifdef UNICODE_NORMALIZATION
nfc_f = FALSE;
@@ -5450,9 +5859,7 @@ void reinit(void)
prefix_table[i] = 0;
}
}
-#ifdef UTF8_INPUT_ENABLE
- utf16_mode = UTF16BE_INPUT;
-#endif
+ hold_count = 0;
mimeout_buf_count = 0;
mimeout_mode = 0;
base64_count = 0;
@@ -5525,16 +5932,16 @@ void usage(void)
fprintf(stderr,"Flags:\n");
fprintf(stderr,"b,u Output is buffered (DEFAULT),Output is unbuffered\n");
#ifdef DEFAULT_CODE_SJIS
- fprintf(stderr,"j,s,e,w Outout code is JIS 7 bit, Shift_JIS (DEFAULT), EUC-JP, UTF-8N\n");
+ fprintf(stderr,"j,s,e,w Output code is JIS 7 bit, Shift_JIS (DEFAULT), EUC-JP, UTF-8N\n");
#endif
#ifdef DEFAULT_CODE_JIS
- fprintf(stderr,"j,s,e,w Outout code is JIS 7 bit (DEFAULT), Shift JIS, EUC-JP, UTF-8N\n");
+ fprintf(stderr,"j,s,e,w Output code is JIS 7 bit (DEFAULT), Shift JIS, EUC-JP, UTF-8N\n");
#endif
#ifdef DEFAULT_CODE_EUC
- fprintf(stderr,"j,s,e,w Outout code is JIS 7 bit, Shift JIS, EUC-JP (DEFAULT), UTF-8N\n");
+ fprintf(stderr,"j,s,e,w Output code is JIS 7 bit, Shift JIS, EUC-JP (DEFAULT), UTF-8N\n");
#endif
#ifdef DEFAULT_CODE_UTF8
- fprintf(stderr,"j,s,e,w Outout code is JIS 7 bit, Shift JIS, EUC-JP, UTF-8N (DEFAULT)\n");
+ fprintf(stderr,"j,s,e,w Output code is JIS 7 bit, Shift JIS, EUC-JP, UTF-8N (DEFAULT)\n");
#endif
#ifdef UTF8_OUTPUT_ENABLE
fprintf(stderr," After 'w' you can add more options. -w[ 8 [0], 16 [[BL] [0]] ]\n");
diff --git a/ext/nkf/nkf-utf8/utf8tbl.c b/ext/nkf/nkf-utf8/utf8tbl.c
index 9e59956a0a..e43ad553d6 100644
--- a/ext/nkf/nkf-utf8/utf8tbl.c
+++ b/ext/nkf/nkf-utf8/utf8tbl.c
@@ -7544,7 +7544,7 @@ const unsigned short cp932inv[2][189] = {
0xFBFC, 0xFC40, 0xFC41, 0xFC42, 0xFC43, 0xFC44, 0xFC45, 0xFC46,
0xFC47, 0xFC48, 0xFC49, 0xFC4A, 0xFC4B, 0, 0, 0xFA40,
0xFA41, 0xFA42, 0xFA43, 0xFA44, 0xFA45, 0xFA46, 0xFA47, 0xFA48,
- 0xFA49, 0, 0xFA55, 0xFA56, 0xFA57,
+ 0xFA49, 0x81CA, 0xFA55, 0xFA56, 0xFA57,
},
};
#endif /* SHIFTJIS_CP932 */
diff --git a/ext/nkf/nkf.c b/ext/nkf/nkf.c
index 8bcb6d15f7..2bb0340a64 100644
--- a/ext/nkf/nkf.c
+++ b/ext/nkf/nkf.c
@@ -3,11 +3,11 @@
*
* original nkf2.x is maintained at http://sourceforge.jp/projects/nkf/
*
- * $Id: nkf.c,v 1.9.2.4 2006/03/27 13:28:14 naruse Exp $
+ * $Id$
*
*/
-#define RUBY_NKF_REVISION "$Revision: 1.9.2.4 $"
+#define RUBY_NKF_REVISION "$Revision$"
#define RUBY_NKF_VERSION NKF_VERSION " (" NKF_RELEASE_DATE ")"
#include "ruby.h"
@@ -63,7 +63,7 @@ rb_nkf_putchar(c)
o_len += incsize;
rb_str_resize(result, o_len);
incsize *= 2;
- output = RSTRING(result)->ptr;
+ output = (unsigned char *)RSTRING(result)->ptr;
}
output[output_ctr++] = c;
@@ -158,13 +158,13 @@ rb_nkf_kconv(obj, opt, src)
input_ctr = 0;
StringValue(src);
- input = RSTRING(src)->ptr;
+ input = (unsigned char *)RSTRING(src)->ptr;
i_len = RSTRING(src)->len;
result = rb_str_new(0, i_len*3 + 10);
v = result;
output_ctr = 0;
- output = RSTRING(result)->ptr;
+ output = (unsigned char *)RSTRING(result)->ptr;
o_len = RSTRING(result)->len;
*output = '\0';
@@ -213,7 +213,7 @@ rb_nkf_guess1(obj, src)
int sequence_counter = 0;
StringValue(src);
- p = RSTRING(src)->ptr;
+ p = (unsigned char *)RSTRING(src)->ptr;
pend = p + RSTRING(src)->len;
if (p == pend) return INT2FIX(_UNKNOWN);
@@ -328,7 +328,7 @@ rb_nkf_guess2(obj, src)
input_ctr = 0;
StringValue(src);
- input = RSTRING(src)->ptr;
+ input = (unsigned char *)RSTRING(src)->ptr;
i_len = RSTRING(src)->len;
if(x0201_f == WISH_TRUE)
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
index b2c5ca5ef8..02e06b7149 100644
--- a/ext/openssl/extconf.rb
+++ b/ext/openssl/extconf.rb
@@ -1,5 +1,5 @@
=begin
-= $RCSfile: extconf.rb,v $ -- Generator for Makefile
+= $RCSfile$ -- Generator for Makefile
= Info
'OpenSSL for Ruby 2' project
@@ -11,7 +11,7 @@
(See the file 'LICENCE'.)
= Version
- $Id: extconf.rb,v 1.21.2.9 2006/06/20 11:18:15 gotoyuzo Exp $
+ $Id$
=end
require "mkmf"
@@ -36,8 +36,6 @@ end
message "=== Checking for system dependent stuff... ===\n"
have_library("nsl", "t_open")
have_library("socket", "socket")
-have_header("unistd.h")
-have_header("sys/time.h")
have_header("assert.h")
message "=== Checking for required stuff... ===\n"
@@ -61,6 +59,8 @@ unless have_header("openssl/conf_api.h")
exit 1
end
+%w"rb_str_set_len rb_block_call".each {|func| have_func(func, "ruby.h")}
+
message "=== Checking for OpenSSL features... ===\n"
have_func("ERR_peek_last_error")
have_func("BN_mod_add")
@@ -83,6 +83,8 @@ have_func("HMAC_CTX_cleanup")
have_func("HMAC_CTX_copy")
have_func("HMAC_CTX_init")
have_func("PEM_def_callback")
+have_func("PKCS5_PBKDF2_HMAC")
+have_func("PKCS5_PBKDF2_HMAC_SHA1")
have_func("X509V3_set_nconf")
have_func("X509V3_EXT_nconf_nid")
have_func("X509_CRL_add0_revoked")
@@ -92,6 +94,7 @@ have_func("X509_CRL_sort")
have_func("X509_STORE_get_ex_data")
have_func("X509_STORE_set_ex_data")
have_func("OBJ_NAME_do_all_sorted")
+have_func("SSL_SESSION_get_id")
have_func("OPENSSL_cleanse")
if try_compile("#define FOO(a, ...) foo(a, ##__VA_ARGS__)\n int x(){FOO(1);FOO(1,2);FOO(1,2,3);}\n")
$defs.push("-DHAVE_VA_ARGS_MACRO")
diff --git a/ext/openssl/lib/net/ftptls.rb b/ext/openssl/lib/net/ftptls.rb
index 43cc136bf6..a21c1f6c3c 100644
--- a/ext/openssl/lib/net/ftptls.rb
+++ b/ext/openssl/lib/net/ftptls.rb
@@ -1,5 +1,5 @@
=begin
-= $RCSfile: ftptls.rb,v $ -- SSL/TLS enhancement for Net::HTTP.
+= $RCSfile$ -- SSL/TLS enhancement for Net::HTTP.
= Info
'OpenSSL for Ruby 2' project
@@ -13,7 +13,7 @@
= Requirements
= Version
- $Id: ftptls.rb,v 1.1 2003/07/23 16:11:30 gotoyuzo Exp $
+ $Id$
= Notes
Tested on FreeBSD 5-CURRENT and 4-STABLE
@@ -29,13 +29,23 @@ require 'net/ftp'
module Net
class FTPTLS < FTP
+ def connect(host, port=FTP_PORT)
+ @hostname = host
+ super
+ end
+
def login(user = "anonymous", passwd = nil, acct = nil)
+ store = OpenSSL::X509::Store.new
+ store.set_default_paths
ctx = OpenSSL::SSL::SSLContext.new('SSLv23')
+ ctx.cert_store = store
+ ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
ctx.key = nil
ctx.cert = nil
voidcmd("AUTH TLS")
@sock = OpenSSL::SSL::SSLSocket.new(@sock, ctx)
@sock.connect
+ @sock.post_connection_check(@hostname)
super(user, passwd, acct)
voidcmd("PBSZ 0")
end
diff --git a/ext/openssl/lib/net/telnets.rb b/ext/openssl/lib/net/telnets.rb
index d277a5c2a6..2b69280432 100644
--- a/ext/openssl/lib/net/telnets.rb
+++ b/ext/openssl/lib/net/telnets.rb
@@ -1,5 +1,5 @@
=begin
-= $RCSfile: telnets.rb,v $ -- SSL/TLS enhancement for Net::Telnet.
+= $RCSfile$ -- SSL/TLS enhancement for Net::Telnet.
= Info
'OpenSSL for Ruby 2' project
@@ -11,7 +11,7 @@
(See the file 'LICENCE'.)
= Version
- $Id: telnets.rb,v 1.1.2.1 2004/12/20 03:49:16 gotoyuzo Exp $
+ $Id$
2001/11/06: Contiributed to Ruby/OpenSSL project.
@@ -134,6 +134,9 @@ module Net
@sock.verify_callback = @options['VerifyCallback']
@sock.verify_depth = @options['VerifyDepth']
@sock.connect
+ if @options['VerifyMode'] != OpenSSL::SSL::VERIFY_NONE
+ @sock.post_connection_check(@options['Host'])
+ end
@ssl = true
end
''
diff --git a/ext/openssl/lib/openssl.rb b/ext/openssl/lib/openssl.rb
index 58fd3887e3..f10985ed2c 100644
--- a/ext/openssl/lib/openssl.rb
+++ b/ext/openssl/lib/openssl.rb
@@ -1,5 +1,5 @@
=begin
-= $RCSfile: openssl.rb,v $ -- Loader for all OpenSSL C-space and Ruby-space definitions
+= $RCSfile$ -- Loader for all OpenSSL C-space and Ruby-space definitions
= Info
'OpenSSL for Ruby 2' project
@@ -11,7 +11,7 @@
(See the file 'LICENCE'.)
= Version
- $Id: openssl.rb,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $
+ $Id$
=end
require 'openssl.so'
@@ -19,6 +19,7 @@ require 'openssl.so'
require 'openssl/bn'
require 'openssl/cipher'
require 'openssl/digest'
+require 'openssl/pkcs7'
require 'openssl/ssl'
require 'openssl/x509'
diff --git a/ext/openssl/lib/openssl/bn.rb b/ext/openssl/lib/openssl/bn.rb
index 4a1595c7ab..e7cbf2cfaf 100644
--- a/ext/openssl/lib/openssl/bn.rb
+++ b/ext/openssl/lib/openssl/bn.rb
@@ -1,5 +1,5 @@
=begin
-= $RCSfile: bn.rb,v $ -- Ruby-space definitions that completes C-space funcs for BN
+= $RCSfile$ -- Ruby-space definitions that completes C-space funcs for BN
= Info
'OpenSSL for Ruby 2' project
@@ -11,7 +11,7 @@
(See the file 'LICENCE'.)
= Version
- $Id: bn.rb,v 1.1 2003/07/23 16:11:30 gotoyuzo Exp $
+ $Id$
=end
##
diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb
index 9eeb19d959..761a017487 100644
--- a/ext/openssl/lib/openssl/buffering.rb
+++ b/ext/openssl/lib/openssl/buffering.rb
@@ -1,5 +1,5 @@
=begin
-= $RCSfile: buffering.rb,v $ -- Buffering mix-in module.
+= $RCSfile$ -- Buffering mix-in module.
= Info
'OpenSSL for Ruby 2' project
@@ -11,7 +11,7 @@
(See the file 'LICENCE'.)
= Version
- $Id: buffering.rb,v 1.5.2.4 2005/09/04 22:03:24 gotoyuzo Exp $
+ $Id$
=end
module Buffering
diff --git a/ext/openssl/lib/openssl/cipher.rb b/ext/openssl/lib/openssl/cipher.rb
index 7825e5e9e6..290e9c1d2d 100644
--- a/ext/openssl/lib/openssl/cipher.rb
+++ b/ext/openssl/lib/openssl/cipher.rb
@@ -1,5 +1,5 @@
=begin
-= $RCSfile: cipher.rb,v $ -- Ruby-space predefined Cipher subclasses
+= $RCSfile$ -- Ruby-space predefined Cipher subclasses
= Info
'OpenSSL for Ruby 2' project
@@ -11,7 +11,7 @@
(See the file 'LICENCE'.)
= Version
- $Id: cipher.rb,v 1.1.2.2 2006/06/20 11:18:15 gotoyuzo Exp $
+ $Id$
=end
##
@@ -19,7 +19,7 @@
#require 'openssl'
module OpenSSL
- module Cipher
+ class Cipher
%w(AES CAST5 BF DES IDEA RC2 RC4 RC5).each{|name|
klass = Class.new(Cipher){
define_method(:initialize){|*args|
@@ -41,18 +41,25 @@ module OpenSSL
const_set("AES#{keylen}", klass)
}
- class Cipher
- def random_key
- str = OpenSSL::Random.random_bytes(self.key_len)
- self.key = str
- return str
- end
-
- def random_iv
- str = OpenSSL::Random.random_bytes(self.iv_len)
- self.iv = str
- return str
- end
+ # Generate, set, and return a random key.
+ # You must call cipher.encrypt or cipher.decrypt before calling this method.
+ def random_key
+ str = OpenSSL::Random.random_bytes(self.key_len)
+ self.key = str
+ return str
+ end
+
+ # Generate, set, and return a random iv.
+ # You must call cipher.encrypt or cipher.decrypt before calling this method.
+ def random_iv
+ str = OpenSSL::Random.random_bytes(self.iv_len)
+ self.iv = str
+ return str
+ end
+
+ # This class is only provided for backwards compatibility. Use OpenSSL::Digest in the future.
+ class Cipher < Cipher
+ # add warning
end
end # Cipher
end # OpenSSL
diff --git a/ext/openssl/lib/openssl/digest.rb b/ext/openssl/lib/openssl/digest.rb
index 6f2c998ff6..4810f0121b 100644
--- a/ext/openssl/lib/openssl/digest.rb
+++ b/ext/openssl/lib/openssl/digest.rb
@@ -1,5 +1,5 @@
=begin
-= $RCSfile: digest.rb,v $ -- Ruby-space predefined Digest subclasses
+= $RCSfile$ -- Ruby-space predefined Digest subclasses
= Info
'OpenSSL for Ruby 2' project
@@ -11,7 +11,7 @@
(See the file 'LICENCE'.)
= Version
- $Id: digest.rb,v 1.1.2.2 2006/06/20 11:18:15 gotoyuzo Exp $
+ $Id$
=end
##
@@ -19,13 +19,17 @@
#require 'openssl'
module OpenSSL
- module Digest
+ class Digest
alg = %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1)
if OPENSSL_VERSION_NUMBER > 0x00908000
alg += %w(SHA224 SHA256 SHA384 SHA512)
end
+ def self.digest(name, data)
+ super(data, name)
+ end
+
alg.each{|name|
klass = Class.new(Digest){
define_method(:initialize){|*data|
@@ -44,6 +48,14 @@ module OpenSSL
const_set(name, klass)
}
+ # This class is only provided for backwards compatibility. Use OpenSSL::Digest in the future.
+ class Digest < Digest
+ def initialize(*args)
+ # add warning
+ super(*args)
+ end
+ end
+
end # Digest
end # OpenSSL
diff --git a/ext/openssl/lib/openssl/pkcs7.rb b/ext/openssl/lib/openssl/pkcs7.rb
new file mode 100644
index 0000000000..1f88c1de5e
--- /dev/null
+++ b/ext/openssl/lib/openssl/pkcs7.rb
@@ -0,0 +1,25 @@
+=begin
+= $RCSfile$ -- PKCS7
+
+= Licence
+ This program is licenced under the same licence as Ruby.
+ (See the file 'LICENCE'.)
+
+= Version
+ $Id: digest.rb 12148 2007-04-05 05:59:22Z technorama $
+=end
+
+module OpenSSL
+ class PKCS7
+ # This class is only provided for backwards compatibility. Use OpenSSL::PKCS7 in the future.
+ class PKCS7 < PKCS7
+ def initialize(*args)
+ super(*args)
+
+ warn("Warning: OpenSSL::PKCS7::PKCS7 is deprecated after Ruby 1.9; use OpenSSL::PKCS7 instead")
+ end
+ end
+
+ end # PKCS7
+end # OpenSSL
+
diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb
index abef21d823..f722cb0c45 100644
--- a/ext/openssl/lib/openssl/ssl.rb
+++ b/ext/openssl/lib/openssl/ssl.rb
@@ -1,5 +1,5 @@
=begin
-= $RCSfile: ssl.rb,v $ -- Ruby-space definitions that completes C-space funcs for SSL
+= $RCSfile$ -- Ruby-space definitions that completes C-space funcs for SSL
= Info
'OpenSSL for Ruby 2' project
@@ -11,7 +11,7 @@
(See the file 'LICENCE'.)
= Version
- $Id: ssl.rb,v 1.5.2.6 2006/05/23 18:14:05 gotoyuzo Exp $
+ $Id$
=end
require "openssl"
@@ -20,6 +20,33 @@ require "fcntl"
module OpenSSL
module SSL
+ class SSLContext
+ DEFAULT_PARAMS = {
+ :ssl_version => "SSLv23",
+ :verify_mode => OpenSSL::SSL::VERIFY_PEER,
+ :ciphers => "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW",
+ :options => OpenSSL::SSL::OP_ALL,
+ }
+
+ DEFAULT_CERT_STORE = OpenSSL::X509::Store.new
+ DEFAULT_CERT_STORE.set_default_paths
+ if defined?(OpenSSL::X509::V_FLAG_CRL_CHECK_ALL)
+ DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
+ end
+
+ def set_params(params={})
+ params = DEFAULT_PARAMS.merge(params)
+ self.ssl_version = params.delete(:ssl_version)
+ params.each{|name, value| self.__send__("#{name}=", value) }
+ if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
+ unless self.ca_file or self.ca_path or self.cert_store
+ self.cert_store = DEFAULT_CERT_STORE
+ end
+ end
+ return params
+ end
+ end
+
module SocketForwarder
def addr
to_io.addr
@@ -59,36 +86,49 @@ module OpenSSL
end
end
+ def verify_certificate_identity(cert, hostname)
+ should_verify_common_name = true
+ cert.extensions.each{|ext|
+ next if ext.oid != "subjectAltName"
+ ext.value.split(/,\s+/).each{|general_name|
+ if /\ADNS:(.*)/ =~ general_name
+ should_verify_common_name = false
+ reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
+ return true if /\A#{reg}\z/i =~ hostname
+ elsif /\AIP Address:(.*)/ =~ general_name
+ should_verify_common_name = false
+ return true if $1 == hostname
+ end
+ }
+ }
+ if should_verify_common_name
+ cert.subject.to_a.each{|oid, value|
+ if oid == "CN"
+ reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
+ return true if /\A#{reg}\z/i =~ hostname
+ end
+ }
+ end
+ return false
+ end
+ module_function :verify_certificate_identity
+
class SSLSocket
include Buffering
include SocketForwarder
include Nonblock
def post_connection_check(hostname)
- check_common_name = true
- cert = peer_cert
- cert.extensions.each{|ext|
- next if ext.oid != "subjectAltName"
- ext.value.split(/,\s+/).each{|general_name|
- if /\ADNS:(.*)/ =~ general_name
- check_common_name = false
- reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
- return true if /\A#{reg}\z/i =~ hostname
- elsif /\AIP Address:(.*)/ =~ general_name
- check_common_name = false
- return true if $1 == hostname
- end
- }
- }
- if check_common_name
- cert.subject.to_a.each{|oid, value|
- if oid == "CN"
- reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
- return true if /\A#{reg}\z/i =~ hostname
- end
- }
+ unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
+ raise SSLError, "hostname was not match with the server certificate"
end
- raise SSLError, "hostname not match"
+ return true
+ end
+
+ def session
+ SSL::Session.new(self)
+ rescue SSL::Session::SessionError
+ nil
end
end
@@ -114,6 +154,10 @@ module OpenSSL
@svr.listen(backlog)
end
+ def shutdown(how=Socket::SHUT_RDWR)
+ @svr.shutdown(how)
+ end
+
def accept
sock = @svr.accept
begin
diff --git a/ext/openssl/lib/openssl/x509.rb b/ext/openssl/lib/openssl/x509.rb
index 2ad3f8e96e..e711bda39c 100644
--- a/ext/openssl/lib/openssl/x509.rb
+++ b/ext/openssl/lib/openssl/x509.rb
@@ -1,5 +1,5 @@
=begin
-= $RCSfile: x509.rb,v $ -- Ruby-space definitions that completes C-space funcs for X509 and subclasses
+= $RCSfile$ -- Ruby-space definitions that completes C-space funcs for X509 and subclasses
= Info
'OpenSSL for Ruby 2' project
@@ -11,7 +11,7 @@
(See the file 'LICENCE'.)
= Version
- $Id: x509.rb,v 1.4.2.2 2004/12/19 08:28:33 gotoyuzo Exp $
+ $Id$
=end
require "openssl"
diff --git a/ext/openssl/openssl_missing.c b/ext/openssl/openssl_missing.c
index 2c005f41e5..724f36b8ae 100644
--- a/ext/openssl/openssl_missing.c
+++ b/ext/openssl/openssl_missing.c
@@ -1,5 +1,5 @@
/*
- * $Id: openssl_missing.c,v 1.2.2.4 2006/06/02 10:02:56 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -22,17 +22,15 @@
#include "openssl_missing.h"
#if !defined(HAVE_HMAC_CTX_COPY)
-int
+void
HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in)
{
- if (!out || !in) return 0;
+ if (!out || !in) return;
memcpy(out, in, sizeof(HMAC_CTX));
- if (!EVP_MD_CTX_copy(&out->md_ctx, &in->md_ctx)
- || !EVP_MD_CTX_copy(&out->i_ctx, &in->i_ctx)
- || !EVP_MD_CTX_copy(&out->o_ctx, &in->o_ctx))
- return 0;
- return 1;
+ EVP_MD_CTX_copy(&out->md_ctx, &in->md_ctx);
+ EVP_MD_CTX_copy(&out->i_ctx, &in->i_ctx);
+ EVP_MD_CTX_copy(&out->o_ctx, &in->o_ctx);
}
#endif /* HAVE_HMAC_CTX_COPY */
#endif /* NO_HMAC */
diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
index 8d580f5ee8..5a71f73c64 100644
--- a/ext/openssl/openssl_missing.h
+++ b/ext/openssl/openssl_missing.h
@@ -1,5 +1,5 @@
/*
- * $Id: openssl_missing.h,v 1.2.2.2 2005/04/15 19:16:18 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -15,6 +15,10 @@
extern "C" {
#endif
+#ifndef TYPEDEF_D2I_OF
+typedef char *d2i_of_void();
+#endif
+
/*
* These functions are not included in headers of OPENSSL <= 0.9.6b
*/
@@ -56,14 +60,33 @@ extern "C" {
(char *(*)())d2i_PKCS7_RECIP_INFO, (char *)ri)
#endif
+#if !defined(HAVE_EVP_MD_CTX_INIT)
void HMAC_CTX_init(HMAC_CTX *ctx);
-int HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in);
+#endif
+
+#if !defined(HAVE_HMAC_CTX_COPY)
+void HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in);
+#endif
+
+#if !defined(HAVE_HMAC_CTX_CLEANUP)
void HMAC_CTX_cleanup(HMAC_CTX *ctx);
+#endif
+#if !defined(HAVE_EVP_MD_CTX_CREATE)
EVP_MD_CTX *EVP_MD_CTX_create(void);
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_INIT)
void EVP_MD_CTX_init(EVP_MD_CTX *ctx);
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_CLEANUP)
int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx);
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_DESTROY)
void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx);
+#endif
#if !defined(HAVE_EVP_CIPHER_CTX_COPY)
int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in);
@@ -107,19 +130,54 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in);
#define OPENSSL_cleanse(p, l) memset(p, 0, l)
#endif
+#if !defined(HAVE_X509_STORE_SET_EX_DATA)
void *X509_STORE_get_ex_data(X509_STORE *str, int idx);
int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data);
+#endif
+
+#if !defined(HAVE_X509_CRL_SET_VERSION)
int X509_CRL_set_version(X509_CRL *x, long version);
+#endif
+
+#if !defined(HAVE_X509_CRL_SET_ISSUER_NAME)
int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name);
+#endif
+
+#if !defined(HAVE_X509_CRL_SORT)
int X509_CRL_sort(X509_CRL *c);
+#endif
+
+#if !defined(HAVE_X509_CRL_ADD0_REVOKED)
int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
+#endif
+
+#if !defined(HAVE_BN_MOD_SQR)
int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
+#endif
+
+#if !defined(HAVE_BN_MOD_ADD)
int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
+#endif
+
+#if !defined(HAVE_BN_MOD_SUB)
int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
+#endif
+
+#if !defined(HAVE_BN_RAND_RANGE)
int BN_rand_range(BIGNUM *r, BIGNUM *range);
+#endif
+
+#if !defined(HAVE_BN_PSEUDO_RAND_RANGE)
int BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range);
+#endif
+
+#if !defined(HAVE_CONF_GET1_DEFAULT_CONFIG_FILE)
char *CONF_get1_default_config_file(void);
+#endif
+
+#if !defined(HAVE_PEM_DEF_CALLBACK)
int PEM_def_callback(char *buf, int num, int w, void *key);
+#endif
#if defined(__cplusplus)
}
diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c
index 01c5ca2a04..53f476fd65 100644
--- a/ext/openssl/ossl.c
+++ b/ext/openssl/ossl.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl.c,v 1.11.2.6 2005/11/01 01:52:13 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -59,7 +59,7 @@ ossl_x509_ary2sk0(VALUE ary)
sk = sk_X509_new_null();
if (!sk) ossl_raise(eOSSLError, NULL);
- for (i = 0; i < RARRAY(ary)->len; i++) {
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
val = rb_ary_entry(ary, i);
if (!rb_obj_is_kind_of(val, cX509Cert)) {
sk_X509_pop_free(sk, X509_free);
@@ -131,7 +131,7 @@ ossl_buf2str(char *buf, int len)
int status = 0;
str = rb_protect((VALUE(*)_((VALUE)))ossl_str_new, len, &status);
- if(!NIL_P(str)) memcpy(RSTRING(str)->ptr, buf, len);
+ if(!NIL_P(str)) memcpy(RSTRING_PTR(str), buf, len);
OPENSSL_free(buf);
if(status) rb_jump_tag(status);
@@ -170,7 +170,7 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
rflag = flag ? Qtrue : Qfalse;
pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status);
if (status) return -1; /* exception was raised. */
- len = RSTRING(pass)->len;
+ len = RSTRING_LEN(pass);
if (len < 4) { /* 4 is OpenSSL hardcoded limit */
rb_warning("password must be longer than 4 bytes");
continue;
@@ -179,7 +179,7 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
rb_warning("password must be shorter then %d bytes", max_len-1);
continue;
}
- memcpy(buf, RSTRING(pass)->ptr, len);
+ memcpy(buf, RSTRING_PTR(pass), len);
break;
}
return len;
@@ -310,6 +310,14 @@ ossl_raise(VALUE exc, const char *fmt, ...)
rb_exc_raise(rb_exc_new(exc, buf, len));
}
+/*
+ * call-seq:
+ * OpenSSL.errors -> [String...]
+ *
+ * See any remaining errors held in queue.
+ *
+ * Any errors you see here are probably due to a bug in ruby's OpenSSL implementation.
+ */
VALUE
ossl_get_errors()
{
@@ -345,12 +353,23 @@ ossl_debug(const char *fmt, ...)
}
#endif
+/*
+ * call-seq:
+ * OpenSSL.debug -> true | false
+ */
static VALUE
ossl_debug_get(VALUE self)
{
return dOSSL;
}
+/*
+ * call-seq:
+ * OpenSSL.debug = boolean -> boolean
+ *
+ * Turns on or off CRYPTO_MEM_CHECK.
+ * Also shows some debugging message on stderr.
+ */
static VALUE
ossl_debug_set(VALUE self, VALUE val)
{
@@ -427,8 +446,8 @@ Init_openssl()
/*
* Verify callback Proc index for ext-data
*/
- ossl_verify_cb_idx =
- X509_STORE_CTX_get_ex_new_index(0, "ossl_verify_cb_idx", 0, 0, 0);
+ if ((ossl_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, "ossl_verify_cb_idx", 0, 0, 0)) < 0)
+ ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");
/*
* Init debug core
@@ -454,6 +473,7 @@ Init_openssl()
Init_ossl_ns_spki();
Init_ossl_pkcs12();
Init_ossl_pkcs7();
+ Init_ossl_pkcs5();
Init_ossl_pkey();
Init_ossl_rand();
Init_ossl_ssl();
diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h
index eaa1fe6eb2..3cc30ae2e8 100644
--- a/ext/openssl/ossl.h
+++ b/ext/openssl/ossl.h
@@ -1,5 +1,5 @@
/*
- * $Id: ossl.h,v 1.14.2.4.2.1 2006/12/25 11:16:49 shyouhei Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -17,11 +17,19 @@
extern "C" {
#endif
+#if 0
+ mOSSL = rb_define_module("OpenSSL");
+ mX509 = rb_define_module_under(mOSSL, "X509");
+#endif
+
/*
- *_FILE_OFFSET_BITS needs to be defined before some system headers on
- * Solaris.
- */
-#include "config.h"
+* OpenSSL has defined RFILE and Ruby has defined RFILE - so undef it!
+*/
+#if defined(RFILE) /*&& !defined(OSSL_DEBUG)*/
+# undef RFILE
+#endif
+#include <ruby.h>
+#include <rubyio.h>
/*
* Check the OpenSSL version
@@ -37,8 +45,12 @@ extern "C" {
#endif
#if defined(_WIN32)
-# define OpenFile WINAPI_OpenFile
# define OSSL_NO_CONF_API 1
+# ifdef USE_WINSOCK2
+# include <winsock2.h>
+# else
+# include <winsock.h>
+# endif
#endif
#include <errno.h>
#include <openssl/err.h>
@@ -61,18 +73,6 @@ extern "C" {
# define OSSL_OCSP_ENABLED
# include <openssl/ocsp.h>
#endif
-#if defined(_WIN32)
-# undef OpenFile
-#endif
-
-/*
- * OpenSSL has defined RFILE and Ruby has defined RFILE - so undef it!
- */
-#if defined(RFILE) /*&& !defined(OSSL_DEBUG)*/
-# undef RFILE
-#endif
-#include <ruby.h>
-#include <rubyio.h>
/*
* Common Module
@@ -123,11 +123,10 @@ VALUE ossl_x509crl_sk2ary(STACK_OF(X509_CRL) *crl);
VALUE ossl_buf2str(char *buf, int len);
#define ossl_str_adjust(str, p) \
do{\
- int len = RSTRING(str)->len;\
- int newlen = (p) - (unsigned char*)RSTRING(str)->ptr;\
+ int len = RSTRING_LEN(str);\
+ int newlen = (p) - (unsigned char*)RSTRING_PTR(str);\
assert(newlen <= len);\
- RSTRING(str)->len = newlen;\
- RSTRING(str)->ptr[newlen] = 0;\
+ rb_str_set_len(str, newlen);\
}while(0)
/*
@@ -208,6 +207,7 @@ void ossl_debug(const char *, ...);
#include "ossl_ocsp.h"
#include "ossl_pkcs12.h"
#include "ossl_pkcs7.h"
+#include "ossl_pkcs5.h"
#include "ossl_pkey.h"
#include "ossl_rand.h"
#include "ossl_ssl.h"
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index 6bc5b88e8f..8ceea95021 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_asn1.c,v 1.5.2.9 2006/04/29 13:52:15 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' team members
* Copyright (C) 2003
* All rights reserved.
@@ -214,7 +214,7 @@ obj_to_asn1bstr(VALUE obj, long unused_bits)
StringValue(obj);
if(!(bstr = ASN1_BIT_STRING_new()))
ossl_raise(eASN1Error, NULL);
- ASN1_BIT_STRING_set(bstr, RSTRING(obj)->ptr, RSTRING(obj)->len);
+ ASN1_BIT_STRING_set(bstr, RSTRING_PTR(obj), RSTRING_LEN(obj));
bstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT|(unused_bits&0x07);
@@ -229,7 +229,7 @@ obj_to_asn1str(VALUE obj)
StringValue(obj);
if(!(str = ASN1_STRING_new()))
ossl_raise(eASN1Error, NULL);
- ASN1_STRING_set(str, RSTRING(obj)->ptr, RSTRING(obj)->len);
+ ASN1_STRING_set(str, RSTRING_PTR(obj), RSTRING_LEN(obj));
return str;
}
@@ -253,8 +253,8 @@ obj_to_asn1obj(VALUE obj)
ASN1_OBJECT *a1obj;
StringValue(obj);
- a1obj = OBJ_txt2obj(RSTRING(obj)->ptr, 0);
- if(!a1obj) a1obj = OBJ_txt2obj(RSTRING(obj)->ptr, 1);
+ a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 0);
+ if(!a1obj) a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 1);
if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID");
return a1obj;
@@ -295,7 +295,7 @@ obj_to_asn1derstr(VALUE obj)
str = ossl_to_der(obj);
if(!(a1str = ASN1_STRING_new()))
ossl_raise(eASN1Error, NULL);
- ASN1_STRING_set(a1str, RSTRING(str)->ptr, RSTRING(str)->len);
+ ASN1_STRING_set(a1str, RSTRING_PTR(str), RSTRING_LEN(str));
return a1str;
}
@@ -445,7 +445,7 @@ decode_time(unsigned char* der, int length)
/********/
typedef struct {
- char *name;
+ const char *name;
VALUE *klass;
} ossl_asn1_info_t;
@@ -678,7 +678,7 @@ static VALUE
join_der(VALUE enumerable)
{
VALUE str = rb_str_new(0, 0);
- rb_iterate(rb_each, enumerable, join_der_i, str);
+ rb_block_call(enumerable, rb_intern("each"), 0, 0, join_der_i, str);
return str;
}
@@ -699,13 +699,13 @@ ossl_asn1data_to_der(VALUE self)
tag = ossl_asn1_tag(self);
tag_class = ossl_asn1_tag_class(self);
- if((length = ASN1_object_size(1, RSTRING(value)->len, tag)) <= 0)
+ if((length = ASN1_object_size(1, RSTRING_LEN(value), tag)) <= 0)
ossl_raise(eASN1Error, NULL);
der = rb_str_new(0, length);
- p = RSTRING(der)->ptr;
- ASN1_put_object(&p, is_cons, RSTRING(value)->len, tag, tag_class);
- memcpy(p, RSTRING(value)->ptr, RSTRING(value)->len);
- p += RSTRING(value)->len;
+ p = RSTRING_PTR(der);
+ ASN1_put_object(&p, is_cons, RSTRING_LEN(value), tag, tag_class);
+ memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
+ p += RSTRING_LEN(value);
ossl_str_adjust(der, p);
return der;
@@ -824,8 +824,8 @@ ossl_asn1_traverse(VALUE self, VALUE obj)
obj = ossl_to_der_if_possible(obj);
tmp = rb_str_new4(StringValue(obj));
- p = RSTRING(tmp)->ptr;
- ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 0, 1);
+ p = RSTRING_PTR(tmp);
+ ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 0, 1);
return Qnil;
}
@@ -840,8 +840,8 @@ ossl_asn1_decode(VALUE self, VALUE obj)
obj = ossl_to_der_if_possible(obj);
tmp = rb_str_new4(StringValue(obj));
- p = RSTRING(tmp)->ptr;
- ary = ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 1, 0);
+ p = RSTRING_PTR(tmp);
+ ary = ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 1, 0);
ret = rb_ary_entry(ary, 0);
return ret;
@@ -857,8 +857,8 @@ ossl_asn1_decode_all(VALUE self, VALUE obj)
obj = ossl_to_der_if_possible(obj);
tmp = rb_str_new4(StringValue(obj));
- p = RSTRING(tmp)->ptr;
- ret = ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 0, 0);
+ p = RSTRING_PTR(tmp);
+ ret = ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 0, 0);
return ret;
}
@@ -973,21 +973,21 @@ ossl_asn1cons_to_der(VALUE self)
explicit = ossl_asn1_is_explicit(self);
value = join_der(ossl_asn1_get_value(self));
- seq_len = ASN1_object_size(1, RSTRING(value)->len, tag);
+ seq_len = ASN1_object_size(1, RSTRING_LEN(value), tag);
length = ASN1_object_size(1, seq_len, tn);
str = rb_str_new(0, length);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(tc == V_ASN1_UNIVERSAL)
- ASN1_put_object(&p, 1, RSTRING(value)->len, tn, tc);
+ ASN1_put_object(&p, 1, RSTRING_LEN(value), tn, tc);
else{
if(explicit){
ASN1_put_object(&p, 1, seq_len, tn, tc);
- ASN1_put_object(&p, 1, RSTRING(value)->len, tag, V_ASN1_UNIVERSAL);
+ ASN1_put_object(&p, 1, RSTRING_LEN(value), tag, V_ASN1_UNIVERSAL);
}
- else ASN1_put_object(&p, 1, RSTRING(value)->len, tn, tc);
+ else ASN1_put_object(&p, 1, RSTRING_LEN(value), tn, tc);
}
- memcpy(p, RSTRING(value)->ptr, RSTRING(value)->len);
- p += RSTRING(value)->len;
+ memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value));
+ p += RSTRING_LEN(value);
ossl_str_adjust(str, p);
return str;
@@ -1007,7 +1007,7 @@ ossl_asn1obj_s_register(VALUE self, VALUE oid, VALUE sn, VALUE ln)
StringValue(sn);
StringValue(ln);
- if(!OBJ_create(RSTRING(oid)->ptr, RSTRING(sn)->ptr, RSTRING(ln)->ptr))
+ if(!OBJ_create(RSTRING_PTR(oid), RSTRING_PTR(sn), RSTRING_PTR(ln)))
ossl_raise(eASN1Error, NULL);
return Qtrue;
@@ -1087,6 +1087,10 @@ Init_ossl_asn1()
VALUE ary;
int i;
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+#endif
+
sUNIVERSAL = rb_intern("UNIVERSAL");
sCONTEXT_SPECIFIC = rb_intern("CONTEXT_SPECIFIC");
sAPPLICATION = rb_intern("APPLICATION");
@@ -1108,9 +1112,9 @@ Init_ossl_asn1()
}
cASN1Data = rb_define_class_under(mASN1, "ASN1Data", rb_cObject);
- rb_attr(cASN1Data, rb_intern("value"), 1, 1, Qtrue);
- rb_attr(cASN1Data, rb_intern("tag"), 1, 1, Qtrue);
- rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, Qtrue);
+ rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0);
+ rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0);
+ rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0);
rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3);
rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0);
@@ -1162,5 +1166,5 @@ do{\
rb_define_method(cASN1ObjectId, "oid", ossl_asn1obj_get_oid, 0);
rb_define_alias(cASN1ObjectId, "short_name", "sn");
rb_define_alias(cASN1ObjectId, "long_name", "ln");
- rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, Qtrue);
+ rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0);
}
diff --git a/ext/openssl/ossl_asn1.h b/ext/openssl/ossl_asn1.h
index 6a1c97b902..8aad9f970d 100644
--- a/ext/openssl/ossl_asn1.h
+++ b/ext/openssl/ossl_asn1.h
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_asn1.h,v 1.3.2.1 2005/09/10 01:17:00 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' team members
* Copyright (C) 2003
* All rights reserved.
diff --git a/ext/openssl/ossl_bio.c b/ext/openssl/ossl_bio.c
index 4e3248eb1d..6db1fb9a62 100644
--- a/ext/openssl/ossl_bio.c
+++ b/ext/openssl/ossl_bio.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_bio.c,v 1.2.2.1 2005/06/19 16:29:17 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' team members
* Copyright (C) 2003
* All rights reserved.
@@ -19,16 +19,29 @@ ossl_obj2bio(VALUE obj)
BIO *bio;
if (TYPE(obj) == T_FILE) {
- OpenFile *fptr;
+ rb_io_t *fptr;
+ FILE *fp;
+ int fd;
+
GetOpenFile(obj, fptr);
rb_io_check_readable(fptr);
- bio = BIO_new_fp(fptr->f, BIO_NOCLOSE);
- }
+ if ((fd = dup(FPTR_TO_FD(fptr))) < 0){
+ rb_sys_fail(0);
+ }
+ if (!(fp = fdopen(fd, "r"))){
+ close(fd);
+ rb_sys_fail(0);
+ }
+ if (!(bio = BIO_new_fp(fp, BIO_CLOSE))){
+ fclose(fp);
+ ossl_raise(eOSSLError, NULL);
+ }
+ }
else {
StringValue(obj);
- bio = BIO_new_mem_buf(RSTRING(obj)->ptr, RSTRING(obj)->len);
+ bio = BIO_new_mem_buf(RSTRING_PTR(obj), RSTRING_LEN(obj));
+ if (!bio) ossl_raise(eOSSLError, NULL);
}
- if (!bio) ossl_raise(eOSSLError, NULL);
return bio;
}
diff --git a/ext/openssl/ossl_bio.h b/ext/openssl/ossl_bio.h
index ca312679fa..2d8f675c5b 100644
--- a/ext/openssl/ossl_bio.h
+++ b/ext/openssl/ossl_bio.h
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_bio.h,v 1.2 2003/09/17 09:05:01 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' team members
* Copyright (C) 2003
* All rights reserved.
diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c
index fb86c8721c..6856476261 100644
--- a/ext/openssl/ossl_bn.c
+++ b/ext/openssl/ossl_bn.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_bn.c,v 1.5.2.1 2004/12/15 01:54:39 matz Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Technorama team <oss-ruby@technorama.net>
* All rights reserved.
@@ -40,7 +40,7 @@ VALUE eBNError;
* Public
*/
VALUE
-ossl_bn_new(BIGNUM *bn)
+ossl_bn_new(const BIGNUM *bn)
{
BIGNUM *newbn;
VALUE obj;
@@ -100,6 +100,13 @@ ossl_bn_alloc(VALUE klass)
return obj;
}
+/*
+ * call-seq:
+ * BN.new => aBN
+ * BN.new(bn) => aBN
+ * BN.new(string) => aBN
+ * BN.new(string, 0 | 2 | 10 | 16) => aBN
+ */
static VALUE
ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -124,22 +131,22 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
switch (base) {
case 0:
- if (!BN_mpi2bn(RSTRING(str)->ptr, RSTRING(str)->len, bn)) {
+ if (!BN_mpi2bn(RSTRING_PTR(str), RSTRING_LEN(str), bn)) {
ossl_raise(eBNError, NULL);
}
break;
case 2:
- if (!BN_bin2bn(RSTRING(str)->ptr, RSTRING(str)->len, bn)) {
+ if (!BN_bin2bn(RSTRING_PTR(str), RSTRING_LEN(str), bn)) {
ossl_raise(eBNError, NULL);
}
break;
case 10:
- if (!BN_dec2bn(&bn, RSTRING(str)->ptr)) {
+ if (!BN_dec2bn(&bn, RSTRING_PTR(str))) {
ossl_raise(eBNError, NULL);
}
break;
case 16:
- if (!BN_hex2bn(&bn, RSTRING(str)->ptr)) {
+ if (!BN_hex2bn(&bn, RSTRING_PTR(str))) {
ossl_raise(eBNError, NULL);
}
break;
@@ -149,6 +156,19 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/*
+ * call-seq:
+ * bn.to_s => string
+ * bn.to_s(base) => string
+ *
+ * === Parameters
+ * * +base+ - integer
+ * * * Valid values:
+ * * * * 0 - MPI
+ * * * * 2 - binary
+ * * * * 10 - the default
+ * * * * 16 - hex
+ */
static VALUE
ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
{
@@ -165,13 +185,13 @@ ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
case 0:
len = BN_bn2mpi(bn, NULL);
str = rb_str_new(0, len);
- if (BN_bn2mpi(bn, RSTRING(str)->ptr) != len)
+ if (BN_bn2mpi(bn, RSTRING_PTR(str)) != len)
ossl_raise(eBNError, NULL);
break;
case 2:
len = BN_num_bytes(bn);
str = rb_str_new(0, len);
- if (BN_bn2bin(bn, RSTRING(str)->ptr) != len)
+ if (BN_bn2bin(bn, RSTRING_PTR(str)) != len)
ossl_raise(eBNError, NULL);
break;
case 10:
@@ -189,6 +209,10 @@ ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
return str;
}
+/*
+ * call-seq:
+ * bn.to_i => integer
+ */
static VALUE
ossl_bn_to_i(VALUE self)
{
@@ -233,6 +257,11 @@ ossl_bn_coerce(VALUE self, VALUE other)
}
#define BIGNUM_BOOL1(func) \
+ /* \
+ * call-seq: \
+ * bn.##func -> true | false \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self) \
{ \
@@ -248,6 +277,11 @@ BIGNUM_BOOL1(is_one);
BIGNUM_BOOL1(is_odd);
#define BIGNUM_1c(func) \
+ /* \
+ * call-seq: \
+ * bn.##func -> aBN \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self) \
{ \
@@ -267,6 +301,11 @@ BIGNUM_BOOL1(is_odd);
BIGNUM_1c(sqr);
#define BIGNUM_2(func) \
+ /* \
+ * call-seq: \
+ * bn.##func(bn2) -> aBN \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self, VALUE other) \
{ \
@@ -287,6 +326,11 @@ BIGNUM_2(add);
BIGNUM_2(sub);
#define BIGNUM_2c(func) \
+ /* \
+ * call-seq: \
+ * bn.##func(bn2) -> aBN \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self, VALUE other) \
{ \
@@ -310,6 +354,10 @@ BIGNUM_2c(gcd);
BIGNUM_2c(mod_sqr);
BIGNUM_2c(mod_inverse);
+/*
+ * call-seq:
+ * bn1 / bn2 => [result, remainder]
+ */
static VALUE
ossl_bn_div(VALUE self, VALUE other)
{
@@ -337,6 +385,11 @@ ossl_bn_div(VALUE self, VALUE other)
}
#define BIGNUM_3c(func) \
+ /* \
+ * call-seq: \
+ * bn.##func(bn1, bn2) -> aBN \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self, VALUE other1, VALUE other2) \
{ \
@@ -360,6 +413,11 @@ BIGNUM_3c(mod_mul);
BIGNUM_3c(mod_exp);
#define BIGNUM_BIT(func) \
+ /* \
+ * call-seq: \
+ * bn.##func(bit) -> self \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self, VALUE bit) \
{ \
@@ -374,6 +432,10 @@ BIGNUM_BIT(set_bit);
BIGNUM_BIT(clear_bit);
BIGNUM_BIT(mask_bits);
+/*
+ * call-seq:
+ * bn.bit_set?(bit) => true | false
+ */
static VALUE
ossl_bn_is_bit_set(VALUE self, VALUE bit)
{
@@ -389,6 +451,11 @@ ossl_bn_is_bit_set(VALUE self, VALUE bit)
}
#define BIGNUM_SHIFT(func) \
+ /* \
+ * call-seq: \
+ * bn.##func(bits) -> aBN \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self, VALUE bits) \
{ \
@@ -410,7 +477,32 @@ ossl_bn_is_bit_set(VALUE self, VALUE bit)
BIGNUM_SHIFT(lshift);
BIGNUM_SHIFT(rshift);
+#define BIGNUM_SELF_SHIFT(func) \
+ /* \
+ * call-seq: \
+ * bn.##func!(bits) -> self \
+ * \
+ */ \
+ static VALUE \
+ ossl_bn_self_##func(VALUE self, VALUE bits) \
+ { \
+ BIGNUM *bn; \
+ int b; \
+ b = NUM2INT(bits); \
+ GetBN(self, bn); \
+ if (!BN_##func(bn, bn, b)) \
+ ossl_raise(eBNError, NULL); \
+ return self; \
+ }
+BIGNUM_SELF_SHIFT(lshift);
+BIGNUM_SELF_SHIFT(rshift);
+
#define BIGNUM_RAND(func) \
+ /* \
+ * call-seq: \
+ * BN.##func(bits [, fill [, odd]]) -> aBN \
+ * \
+ */ \
static VALUE \
ossl_bn_s_##func(int argc, VALUE *argv, VALUE klass) \
{ \
@@ -423,7 +515,7 @@ BIGNUM_SHIFT(rshift);
bottom = (odd == Qtrue) ? 1 : 0; \
/* FALLTHROUGH */ \
case 2: \
- top = FIX2INT(fill); \
+ top = NUM2INT(fill); \
} \
b = NUM2INT(bits); \
if (!(result = BN_new())) { \
@@ -440,6 +532,11 @@ BIGNUM_RAND(rand);
BIGNUM_RAND(pseudo_rand);
#define BIGNUM_RAND_RANGE(func) \
+ /* \
+ * call-seq: \
+ * BN.##func(range) -> aBN \
+ * \
+ */ \
static VALUE \
ossl_bn_s_##func##_range(VALUE klass, VALUE range) \
{ \
@@ -458,6 +555,16 @@ BIGNUM_RAND(pseudo_rand);
BIGNUM_RAND_RANGE(rand);
BIGNUM_RAND_RANGE(pseudo_rand);
+/*
+ * call-seq:
+ * BN.generate_prime(bits, [, safe [, add [, rem]]]) => bn
+ *
+ * === Parameters
+ * * +bits+ - integer
+ * * +safe+ - boolean
+ * * +add+ - BN
+ * * +rem+ - BN
+ */
static VALUE
ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
{
@@ -473,12 +580,8 @@ ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
safe = 0;
}
if (!NIL_P(vadd)) {
- if (NIL_P(vrem)) {
- ossl_raise(rb_eArgError,
- "if ADD is specified, REM must be also given");
- }
add = GetBNPtr(vadd);
- rem = GetBNPtr(vrem);
+ rem = NIL_P(vrem) ? NULL : GetBNPtr(vrem);
}
if (!(result = BN_new())) {
ossl_raise(eBNError, NULL);
@@ -489,10 +592,15 @@ ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
}
WrapBN(klass, obj, result);
- return obj;
+ return obj;
}
#define BIGNUM_NUM(func) \
+ /* \
+ * call-seq: \
+ * bn.##func -> integer \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self) \
{ \
@@ -522,6 +630,11 @@ ossl_bn_copy(VALUE self, VALUE other)
}
#define BIGNUM_CMP(func) \
+ /* \
+ * call-seq: \
+ * bn.##func(bn2) -> integer \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self, VALUE other) \
{ \
@@ -541,6 +654,14 @@ ossl_bn_eql(VALUE self, VALUE other)
return Qfalse;
}
+/*
+ * call-seq:
+ * bn.prime? => true | false
+ * bn.prime?(checks) => true | false
+ *
+ * === Parameters
+ * * +checks+ - integer
+ */
static VALUE
ossl_bn_is_prime(int argc, VALUE *argv, VALUE self)
{
@@ -564,6 +685,16 @@ ossl_bn_is_prime(int argc, VALUE *argv, VALUE self)
return Qnil;
}
+/*
+ * call-seq:
+ * bn.prime_fasttest? => true | false
+ * bn.prime_fasttest?(checks) => true | false
+ * bn.prime_fasttest?(checks, trial_div) => true | false
+ *
+ * === Parameters
+ * * +checks+ - integer
+ * * +trial_div+ - boolean
+ */
static VALUE
ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self)
{
@@ -600,6 +731,10 @@ ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self)
void
Init_ossl_bn()
{
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+#endif
+
if (!(ossl_bn_ctx = BN_CTX_new())) {
ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX");
}
@@ -672,8 +807,10 @@ Init_ossl_bn()
rb_define_method(cBN, "bit_set?", ossl_bn_is_bit_set, 1);
rb_define_method(cBN, "mask_bits!", ossl_bn_mask_bits, 1);
rb_define_method(cBN, "<<", ossl_bn_lshift, 1);
- /* lshift1 - DON'T IMPL. */
rb_define_method(cBN, ">>", ossl_bn_rshift, 1);
+ rb_define_method(cBN, "lshift!", ossl_bn_self_lshift, 1);
+ rb_define_method(cBN, "rshift!", ossl_bn_self_rshift, 1);
+ /* lshift1 - DON'T IMPL. */
/* rshift1 - DON'T IMPL. */
/*
diff --git a/ext/openssl/ossl_bn.h b/ext/openssl/ossl_bn.h
index bccdbc0cd6..d6c396227b 100644
--- a/ext/openssl/ossl_bn.h
+++ b/ext/openssl/ossl_bn.h
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_bn.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -14,9 +14,12 @@
extern VALUE cBN;
extern VALUE eBNError;
-VALUE ossl_bn_new(BIGNUM *);
+extern BN_CTX *ossl_bn_ctx;
+
+VALUE ossl_bn_new(const BIGNUM *);
BIGNUM *GetBNPtr(VALUE);
void Init_ossl_bn(void);
+
#endif /* _OSS_BN_H_ */
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index 8d96d0b35a..b680dc6e64 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_cipher.c,v 1.4.2.6 2006/06/20 11:18:15 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -26,7 +26,6 @@
/*
* Classes
*/
-VALUE mCipher;
VALUE cCipher;
VALUE eCipherError;
@@ -84,6 +83,14 @@ ossl_cipher_alloc(VALUE klass)
return obj;
}
+/*
+ * call-seq:
+ * Cipher.new(string) -> cipher
+ *
+ * The string must contain a valid cipher name like "AES-128-CBC" or "3DES".
+ *
+ * A list of cipher names is available by calling OpenSSL::Cipher.ciphers.
+ */
static VALUE
ossl_cipher_initialize(VALUE self, VALUE str)
{
@@ -124,6 +131,12 @@ add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary)
return NULL;
}
+/*
+ * call-seq:
+ * Cipher.ciphers -> array[string...]
+ *
+ * Returns the names of all available ciphers in an array.
+ */
static VALUE
ossl_s_ciphers(VALUE self)
{
@@ -141,6 +154,12 @@ ossl_s_ciphers(VALUE self)
#endif
}
+/*
+ * call-seq:
+ * cipher.reset -> self
+ *
+ * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1).
+ */
static VALUE
ossl_cipher_reset(VALUE self)
{
@@ -167,22 +186,23 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
* We deprecated the arguments for this method, but we decided
* keeping this behaviour for backward compatibility.
*/
+ char *cname = rb_class2name(rb_obj_class(self));
+ rb_warn("argumtents for %s#encrypt and %s#decrypt were deprecated; "
+ "use %s#pkcs5_keyivgen to derive key and IV",
+ cname, cname, cname);
StringValue(pass);
GetCipher(self, ctx);
if (NIL_P(init_v)) memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv));
else{
- char *cname = rb_class2name(rb_obj_class(self));
- rb_warning("key derivation by %s#encrypt is deprecated; "
- "use %s::pkcs5_keyivgen instead", cname, cname);
StringValue(init_v);
- if (EVP_MAX_IV_LENGTH > RSTRING(init_v)->len) {
+ if (EVP_MAX_IV_LENGTH > RSTRING_LEN(init_v)) {
memset(iv, 0, EVP_MAX_IV_LENGTH);
- memcpy(iv, RSTRING(init_v)->ptr, RSTRING(init_v)->len);
+ memcpy(iv, RSTRING_PTR(init_v), RSTRING_LEN(init_v));
}
- else memcpy(iv, RSTRING(init_v)->ptr, sizeof(iv));
+ else memcpy(iv, RSTRING_PTR(init_v), sizeof(iv));
}
EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv,
- RSTRING(pass)->ptr, RSTRING(pass)->len, 1, key, NULL);
+ RSTRING_PTR(pass), RSTRING_LEN(pass), 1, key, NULL);
p_key = key;
p_iv = iv;
}
@@ -196,18 +216,54 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
return self;
}
+/*
+ * call-seq:
+ * cipher.encrypt -> self
+ *
+ * Make sure to call .encrypt or .decrypt before using any of the following methods:
+ * * [key=, iv=, random_key, random_iv, pkcs5_keyivgen]
+ *
+ * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 1).
+ */
static VALUE
ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self)
{
return ossl_cipher_init(argc, argv, self, 1);
}
+/*
+ * call-seq:
+ * cipher.decrypt -> self
+ *
+ * Make sure to call .encrypt or .decrypt before using any of the following methods:
+ * * [key=, iv=, random_key, random_iv, pkcs5_keyivgen]
+ *
+ * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 0).
+ */
static VALUE
ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self)
{
return ossl_cipher_init(argc, argv, self, 0);
}
+/*
+ * call-seq:
+ * cipher.pkcs5_keyivgen(pass [, salt [, iterations [, digest]]] ) -> nil
+ *
+ * Generates and sets the key/iv based on a password.
+ *
+ * WARNING: This method is only PKCS5 v1.5 compliant when using RC2, RC4-40, or DES
+ * with MD5 or SHA1. Using anything else (like AES) will generate the key/iv using an
+ * OpenSSL specific method. Use a PKCS5 v2 key generation method instead.
+ *
+ * === Parameters
+ * +salt+ must be an 8 byte string if provided.
+ * +iterations+ is a integer with a default of 2048.
+ * +digest+ is a Digest object that defaults to 'MD5'
+ *
+ * A minimum of 1000 iterations is recommended.
+ *
+ */
static VALUE
ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
{
@@ -221,15 +277,15 @@ ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
StringValue(vpass);
if(!NIL_P(vsalt)){
StringValue(vsalt);
- if(RSTRING(vsalt)->len != PKCS5_SALT_LEN)
+ if(RSTRING_LEN(vsalt) != PKCS5_SALT_LEN)
rb_raise(eCipherError, "salt must be an 8-octet string");
- salt = RSTRING(vsalt)->ptr;
+ salt = RSTRING_PTR(vsalt);
}
iter = NIL_P(viter) ? 2048 : NUM2INT(viter);
digest = NIL_P(vdigest) ? EVP_md5() : GetDigestPtr(vdigest);
GetCipher(self, ctx);
EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), digest, salt,
- RSTRING(vpass)->ptr, RSTRING(vpass)->len, iter, key, iv);
+ RSTRING_PTR(vpass), RSTRING_LEN(vpass), iter, key, iv);
if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, -1) != 1)
ossl_raise(eCipherError, NULL);
OPENSSL_cleanse(key, sizeof key);
@@ -238,39 +294,75 @@ ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
return Qnil;
}
+
+/*
+ * call-seq:
+ * cipher << data -> string
+ *
+ * === Parameters
+ * +data+ is a nonempty string.
+ *
+ * This method is deprecated and not available in 1.9.x or later.
+ */
+static VALUE
+ossl_cipher_update_deprecated(VALUE self, VALUE data)
+{
+ char *cname;
+
+ cname = rb_class2name(rb_obj_class(self));
+ rb_warning("%s#<< is deprecated; use %s#update instead", cname, cname);
+ return rb_funcall(self, rb_intern("update"), 1, data);
+}
+
+
+/*
+ * call-seq:
+ * cipher.update(data [, buffer]) -> string or buffer
+ *
+ * === Parameters
+ * +data+ is a nonempty string.
+ * +buffer+ is an optional string to store the result.
+ */
static VALUE
-ossl_cipher_update(VALUE self, VALUE data)
+ossl_cipher_update(int argc, VALUE *argv, VALUE self)
{
EVP_CIPHER_CTX *ctx;
char *in;
int in_len, out_len;
- VALUE str;
+ VALUE data, str;
+
+ rb_scan_args(argc, argv, "11", &data, &str);
StringValue(data);
- in = RSTRING(data)->ptr;
- if ((in_len = RSTRING(data)->len) == 0)
+ in = RSTRING_PTR(data);
+ if ((in_len = RSTRING_LEN(data)) == 0)
rb_raise(rb_eArgError, "data must not be empty");
GetCipher(self, ctx);
- str = rb_str_new(0, in_len+EVP_CIPHER_CTX_block_size(ctx));
- if (!EVP_CipherUpdate(ctx, RSTRING(str)->ptr, &out_len, in, in_len))
- ossl_raise(eCipherError, NULL);
- assert(out_len < RSTRING(str)->len);
- RSTRING(str)->len = out_len;
- RSTRING(str)->ptr[out_len] = 0;
+ out_len = in_len+EVP_CIPHER_CTX_block_size(ctx);
- return str;
-}
+ if (NIL_P(str)) {
+ str = rb_str_new(0, out_len);
+ } else {
+ StringValue(str);
+ rb_str_resize(str, out_len);
+ }
-static VALUE
-ossl_cipher_update_deprecated(VALUE self, VALUE data)
-{
- char *cname;
+ if (!EVP_CipherUpdate(ctx, RSTRING_PTR(str), &out_len, in, in_len))
+ ossl_raise(eCipherError, NULL);
+ assert(out_len < RSTRING_LEN(str));
+ rb_str_set_len(str, out_len);
- cname = rb_class2name(rb_obj_class(self));
- rb_warning("%s#<< is deprecated; use %s#update instead", cname, cname);
- return ossl_cipher_update(self, data);
+ return str;
}
+/*
+ * call-seq:
+ * cipher.final -> aString
+ *
+ * Returns the remaining data held in the cipher object. Further calls to update() or final() will return garbage.
+ *
+ * See EVP_CipherFinal_ex for further information.
+ */
static VALUE
ossl_cipher_final(VALUE self)
{
@@ -280,15 +372,20 @@ ossl_cipher_final(VALUE self)
GetCipher(self, ctx);
str = rb_str_new(0, EVP_CIPHER_CTX_block_size(ctx));
- if (!EVP_CipherFinal_ex(ctx, RSTRING(str)->ptr, &out_len))
+ if (!EVP_CipherFinal_ex(ctx, RSTRING_PTR(str), &out_len))
ossl_raise(eCipherError, NULL);
- assert(out_len <= RSTRING(str)->len);
- RSTRING(str)->len = out_len;
- RSTRING(str)->ptr[out_len] = 0;
+ assert(out_len <= RSTRING_LEN(str));
+ rb_str_set_len(str, out_len);
return str;
}
+/*
+ * call-seq:
+ * cipher.name -> string
+ *
+ * Returns the name of the cipher which may differ slightly from the original name provided.
+ */
static VALUE
ossl_cipher_name(VALUE self)
{
@@ -299,6 +396,14 @@ ossl_cipher_name(VALUE self)
return rb_str_new2(EVP_CIPHER_name(EVP_CIPHER_CTX_cipher(ctx)));
}
+/*
+ * call-seq:
+ * cipher.key = string -> string
+ *
+ * Sets the cipher key.
+ *
+ * Only call this method after calling cipher.encrypt or cipher.decrypt.
+ */
static VALUE
ossl_cipher_set_key(VALUE self, VALUE key)
{
@@ -307,15 +412,23 @@ ossl_cipher_set_key(VALUE self, VALUE key)
StringValue(key);
GetCipher(self, ctx);
- if (RSTRING(key)->len < EVP_CIPHER_CTX_key_length(ctx))
+ if (RSTRING_LEN(key) < EVP_CIPHER_CTX_key_length(ctx))
ossl_raise(eCipherError, "key length too short");
- if (EVP_CipherInit_ex(ctx, NULL, NULL, RSTRING(key)->ptr, NULL, -1) != 1)
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, RSTRING_PTR(key), NULL, -1) != 1)
ossl_raise(eCipherError, NULL);
return key;
}
+/*
+ * call-seq:
+ * cipher.iv = string -> string
+ *
+ * Sets the cipher iv.
+ *
+ * Only call this method after calling cipher.encrypt or cipher.decrypt.
+ */
static VALUE
ossl_cipher_set_iv(VALUE self, VALUE iv)
{
@@ -324,20 +437,32 @@ ossl_cipher_set_iv(VALUE self, VALUE iv)
StringValue(iv);
GetCipher(self, ctx);
- if (RSTRING(iv)->len < EVP_CIPHER_CTX_iv_length(ctx))
+ if (RSTRING_LEN(iv) < EVP_CIPHER_CTX_iv_length(ctx))
ossl_raise(eCipherError, "iv length too short");
- if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, RSTRING(iv)->ptr, -1) != 1)
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, RSTRING_PTR(iv), -1) != 1)
ossl_raise(eCipherError, NULL);
return iv;
}
+
+/*
+ * call-seq:
+ * cipher.key_length = integer -> integer
+ *
+ * Sets the key length of the cipher. If the cipher is a fixed length cipher then attempting to set the key
+ * length to any value other than the fixed value is an error.
+ *
+ * Under normal circumstances you do not need to call this method (and probably shouldn't).
+ *
+ * See EVP_CIPHER_CTX_set_key_length for further information.
+ */
static VALUE
ossl_cipher_set_key_length(VALUE self, VALUE key_length)
{
- EVP_CIPHER_CTX *ctx;
int len = NUM2INT(key_length);
+ EVP_CIPHER_CTX *ctx;
GetCipher(self, ctx);
if (EVP_CIPHER_CTX_set_key_length(ctx, len) != 1)
@@ -346,6 +471,16 @@ ossl_cipher_set_key_length(VALUE self, VALUE key_length)
return key_length;
}
+/*
+ * call-seq:
+ * cipher.padding = integer -> integer
+ *
+ * Enables or disables padding. By default encryption operations are padded using standard block padding and the
+ * padding is checked and removed when decrypting. If the pad parameter is zero then no padding is performed, the
+ * total amount of data encrypted or decrypted must then be a multiple of the block size or an error will occur.
+ *
+ * See EVP_CIPHER_CTX_set_padding for further information.
+ */
static VALUE
ossl_cipher_set_padding(VALUE self, VALUE padding)
{
@@ -374,26 +509,51 @@ CIPHER_0ARG_INT(key_length)
CIPHER_0ARG_INT(iv_length)
CIPHER_0ARG_INT(block_size)
+#if 0
+/*
+ * call-seq:
+ * cipher.key_length -> integer
+ *
+ */
+static VALUE ossl_cipher_key_length() { }
+/*
+ * call-seq:
+ * cipher.iv_length -> integer
+ *
+ */
+static VALUE ossl_cipher_iv_length() { }
+/*
+ * call-seq:
+ * cipher.block_size -> integer
+ *
+ */
+static VALUE ossl_cipher_block_size() { }
+#endif
+
/*
* INIT
*/
void
Init_ossl_cipher(void)
{
- mCipher = rb_define_module_under(mOSSL, "Cipher");
- eCipherError = rb_define_class_under(mOSSL, "CipherError", eOSSLError);
- cCipher = rb_define_class_under(mCipher, "Cipher", rb_cObject);
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+#endif
+ cCipher = rb_define_class_under(mOSSL, "Cipher", rb_cObject);
+ eCipherError = rb_define_class_under(cCipher, "CipherError", eOSSLError);
rb_define_alloc_func(cCipher, ossl_cipher_alloc);
rb_define_copy_func(cCipher, ossl_cipher_copy);
- rb_define_module_function(mCipher, "ciphers", ossl_s_ciphers, 0);
+ rb_define_module_function(cCipher, "ciphers", ossl_s_ciphers, 0);
rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1);
rb_define_method(cCipher, "reset", ossl_cipher_reset, 0);
rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, -1);
rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, -1);
rb_define_method(cCipher, "pkcs5_keyivgen", ossl_cipher_pkcs5_keyivgen, -1);
- rb_define_method(cCipher, "update", ossl_cipher_update, 1);
+ rb_define_method(cCipher, "update", ossl_cipher_update, -1);
+#if RUBY_VERSION_CODE < 190
rb_define_method(cCipher, "<<", ossl_cipher_update_deprecated, 1);
+#endif
rb_define_method(cCipher, "final", ossl_cipher_final, 0);
rb_define_method(cCipher, "name", ossl_cipher_name, 0);
rb_define_method(cCipher, "key=", ossl_cipher_set_key, 1);
@@ -404,3 +564,4 @@ Init_ossl_cipher(void)
rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0);
rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
}
+
diff --git a/ext/openssl/ossl_cipher.h b/ext/openssl/ossl_cipher.h
index 870927c37c..bed4fa853b 100644
--- a/ext/openssl/ossl_cipher.h
+++ b/ext/openssl/ossl_cipher.h
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_cipher.h,v 1.2 2003/09/05 09:08:40 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -11,7 +11,6 @@
#if !defined(_OSSL_CIPHER_H_)
#define _OSSL_CIPHER_H_
-extern VALUE mCipher;
extern VALUE cCipher;
extern VALUE eCipherError;
diff --git a/ext/openssl/ossl_config.c b/ext/openssl/ossl_config.c
index 1844022506..cc8e324029 100644
--- a/ext/openssl/ossl_config.c
+++ b/ext/openssl/ossl_config.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_config.c,v 1.8.2.3 2004/12/15 01:54:39 matz Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -171,16 +171,16 @@ ossl_config_add_value(VALUE self, VALUE section, VALUE name, VALUE value)
StringValue(name);
StringValue(value);
GetConfig(self, conf);
- if(!(sv = _CONF_get_section(conf, RSTRING(section)->ptr))){
- if(!(sv = _CONF_new_section(conf, RSTRING(section)->ptr))){
+ if(!(sv = _CONF_get_section(conf, RSTRING_PTR(section)))){
+ if(!(sv = _CONF_new_section(conf, RSTRING_PTR(section)))){
ossl_raise(eConfigError, NULL);
}
}
if(!(cv = OPENSSL_malloc(sizeof(CONF_VALUE)))){
ossl_raise(eConfigError, NULL);
}
- cv->name = BUF_strdup(RSTRING(name)->ptr);
- cv->value = BUF_strdup(RSTRING(value)->ptr);
+ cv->name = BUF_strdup(RSTRING_PTR(name));
+ cv->value = BUF_strdup(RSTRING_PTR(value));
if(!cv->name || !cv->value || !_CONF_add_string(conf, sv, cv)){
OPENSSL_free(cv->name);
OPENSSL_free(cv->value);
@@ -201,7 +201,7 @@ ossl_config_get_value(VALUE self, VALUE section, VALUE name)
StringValue(section);
StringValue(name);
GetConfig(self, conf);
- str = NCONF_get_string(conf, RSTRING(section)->ptr, RSTRING(name)->ptr);
+ str = NCONF_get_string(conf, RSTRING_PTR(section), RSTRING_PTR(name));
if(!str){
ERR_clear_error();
return Qnil;
@@ -245,8 +245,11 @@ set_conf_section_i(VALUE i, VALUE *arg)
static VALUE
ossl_config_set_section(VALUE self, VALUE section, VALUE hash)
{
- VALUE arg[2] = { self, section };
- rb_iterate(rb_each, hash, set_conf_section_i, (VALUE)arg);
+ VALUE arg[2];
+
+ arg[0] = self;
+ arg[1] = section;
+ rb_block_call(hash, rb_intern("each"), 0, 0, set_conf_section_i, (VALUE)arg);
return hash;
}
diff --git a/ext/openssl/ossl_config.h b/ext/openssl/ossl_config.h
index 452d430b5e..cb226b27e5 100644
--- a/ext/openssl/ossl_config.h
+++ b/ext/openssl/ossl_config.h
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_config.h,v 1.2 2003/09/08 10:31:38 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c
index 8b9c273f4d..879d399fe7 100644
--- a/ext/openssl/ossl_digest.c
+++ b/ext/openssl/ossl_digest.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_digest.c,v 1.4.2.2 2004/12/15 01:54:39 matz Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -24,7 +24,6 @@
/*
* Classes
*/
-VALUE mDigest;
VALUE cDigest;
VALUE eDigestError;
@@ -36,11 +35,23 @@ static VALUE ossl_digest_alloc(VALUE klass);
const EVP_MD *
GetDigestPtr(VALUE obj)
{
- EVP_MD_CTX *ctx;
+ const EVP_MD *md;
+
+ if (TYPE(obj) == T_STRING) {
+ const char *name = STR2CSTR(obj);
+
+ md = EVP_get_digestbyname(name);
+ if (!md)
+ ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name);
+ } else {
+ EVP_MD_CTX *ctx;
- SafeGetDigest(obj, ctx);
+ SafeGetDigest(obj, ctx);
- return EVP_MD_CTX_md(ctx); /*== ctx->digest*/
+ md = EVP_MD_CTX_md(ctx);
+ }
+
+ return md;
}
VALUE
@@ -51,7 +62,6 @@ ossl_digest_new(const EVP_MD *md)
ret = ossl_digest_alloc(cDigest);
GetDigest(ret, ctx);
- EVP_MD_CTX_init(ctx);
EVP_DigestInit_ex(ctx, md, NULL);
return ret;
@@ -69,14 +79,18 @@ ossl_digest_alloc(VALUE klass)
ctx = EVP_MD_CTX_create();
if (ctx == NULL)
ossl_raise(rb_eRuntimeError, "EVP_MD_CTX_create() failed");
- EVP_MD_CTX_init(ctx);
obj = Data_Wrap_Struct(klass, 0, EVP_MD_CTX_destroy, ctx);
-
+
return obj;
}
VALUE ossl_digest_update(VALUE, VALUE);
+/*
+ * call-seq:
+ * Digest.new(string) -> digest
+ *
+ */
static VALUE
ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -86,14 +100,9 @@ ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
VALUE type, data;
rb_scan_args(argc, argv, "11", &type, &data);
- StringValue(type);
+ md = GetDigestPtr(type);
if (!NIL_P(data)) StringValue(data);
- name = StringValuePtr(type);
-
- md = EVP_get_digestbyname(name);
- if (!md) {
- ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name);
- }
+
GetDigest(self, ctx);
EVP_DigestInit_ex(ctx, md, NULL);
@@ -118,6 +127,11 @@ ossl_digest_copy(VALUE self, VALUE other)
return self;
}
+/*
+ * call-seq:
+ * digest.reset -> self
+ *
+ */
static VALUE
ossl_digest_reset(VALUE self)
{
@@ -129,6 +143,11 @@ ossl_digest_reset(VALUE self)
return self;
}
+/*
+ * call-seq:
+ * digest.update(string) -> aString
+ *
+ */
VALUE
ossl_digest_update(VALUE self, VALUE data)
{
@@ -136,126 +155,77 @@ ossl_digest_update(VALUE self, VALUE data)
StringValue(data);
GetDigest(self, ctx);
- EVP_DigestUpdate(ctx, RSTRING(data)->ptr, RSTRING(data)->len);
+ EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data));
return self;
}
-static void
-digest_final(EVP_MD_CTX *ctx, char **buf, int *buf_len)
-{
- EVP_MD_CTX final;
-
- if (!EVP_MD_CTX_copy(&final, ctx)) {
- ossl_raise(eDigestError, NULL);
- }
- if (!(*buf = OPENSSL_malloc(EVP_MD_CTX_size(&final)))) {
- EVP_MD_CTX_cleanup(&final);
- ossl_raise(eDigestError, "Cannot allocate mem for digest");
- }
- EVP_DigestFinal_ex(&final, *buf, buf_len);
- EVP_MD_CTX_cleanup(&final);
-}
-
+/*
+ * call-seq:
+ * digest.finish -> aString
+ *
+ */
static VALUE
-ossl_digest_digest(VALUE self)
+ossl_digest_finish(int argc, VALUE *argv, VALUE self)
{
EVP_MD_CTX *ctx;
- char *buf;
- int buf_len;
- VALUE digest;
-
- GetDigest(self, ctx);
- digest_final(ctx, &buf, &buf_len);
- digest = ossl_buf2str(buf, buf_len);
-
- return digest;
-}
+ VALUE str;
-static VALUE
-ossl_digest_hexdigest(VALUE self)
-{
- EVP_MD_CTX *ctx;
- char *buf, *hexbuf;
- int buf_len;
- VALUE hexdigest;
+ rb_scan_args(argc, argv, "01", &str);
GetDigest(self, ctx);
- digest_final(ctx, &buf, &buf_len);
- if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) {
- OPENSSL_free(buf);
- ossl_raise(eDigestError, "Memory alloc error");
- }
- OPENSSL_free(buf);
- hexdigest = ossl_buf2str(hexbuf, 2 * buf_len);
-
- return hexdigest;
-}
-
-static VALUE
-ossl_digest_s_digest(VALUE klass, VALUE str, VALUE data)
-{
- VALUE obj = rb_class_new_instance(1, &str, klass);
-
- ossl_digest_update(obj, data);
- return ossl_digest_digest(obj);
-}
-
-static VALUE
-ossl_digest_s_hexdigest(VALUE klass, VALUE str, VALUE data)
-{
- VALUE obj = rb_class_new_instance(1, &str, klass);
+ if (NIL_P(str)) {
+ str = rb_str_new(NULL, EVP_MD_CTX_size(ctx));
+ } else {
+ StringValue(str);
+ rb_str_resize(str, EVP_MD_CTX_size(ctx));
+ }
- ossl_digest_update(obj, data);
+ EVP_DigestFinal_ex(ctx, RSTRING_PTR(str), NULL);
- return ossl_digest_hexdigest(obj);
+ return str;
}
+/*
+ * call-seq:
+ * digest.name -> string
+ *
+ */
static VALUE
-ossl_digest_equal(VALUE self, VALUE other)
+ossl_digest_name(VALUE self)
{
EVP_MD_CTX *ctx;
- VALUE str1, str2;
- if (rb_obj_is_kind_of(other, cDigest) == Qtrue) {
- str2 = ossl_digest_digest(other);
- } else {
- StringValue(other);
- str2 = other;
- }
GetDigest(self, ctx);
- if (RSTRING(str2)->len == EVP_MD_CTX_size(ctx)) {
- str1 = ossl_digest_digest(self);
- } else {
- str1 = ossl_digest_hexdigest(self);
- }
- if (RSTRING(str1)->len == RSTRING(str2)->len
- && rb_str_cmp(str1, str2) == 0) {
- return Qtrue;
- }
- return Qfalse;
+ return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx)));
}
+/*
+ * call-seq:
+ * digest.digest_size -> integer
+ *
+ * Returns the output size of the digest.
+ */
static VALUE
-ossl_digest_name(VALUE self)
+ossl_digest_size(VALUE self)
{
EVP_MD_CTX *ctx;
GetDigest(self, ctx);
- return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx)));
+ return INT2NUM(EVP_MD_CTX_size(ctx));
}
static VALUE
-ossl_digest_size(VALUE self)
+ossl_digest_block_length(VALUE self)
{
EVP_MD_CTX *ctx;
GetDigest(self, ctx);
- return INT2NUM(EVP_MD_CTX_size(ctx));
+ return INT2NUM(EVP_MD_CTX_block_size(ctx));
}
/*
@@ -264,31 +234,26 @@ ossl_digest_size(VALUE self)
void
Init_ossl_digest()
{
- mDigest = rb_define_module_under(mOSSL, "Digest");
-
- eDigestError = rb_define_class_under(mDigest, "DigestError", eOSSLError);
-
- cDigest = rb_define_class_under(mDigest, "Digest", rb_cObject);
+ rb_require("openssl");
+ rb_require("digest");
+
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+#endif
+
+ cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class"));
+ eDigestError = rb_define_class_under(cDigest, "DigestError", eOSSLError);
rb_define_alloc_func(cDigest, ossl_digest_alloc);
- rb_define_singleton_method(cDigest, "digest", ossl_digest_s_digest, 2);
- rb_define_singleton_method(cDigest, "hexdigest", ossl_digest_s_hexdigest, 2);
-
+
rb_define_method(cDigest, "initialize", ossl_digest_initialize, -1);
- rb_define_method(cDigest, "reset", ossl_digest_reset, 0);
-
rb_define_copy_func(cDigest, ossl_digest_copy);
-
- rb_define_method(cDigest, "digest", ossl_digest_digest, 0);
- rb_define_method(cDigest, "hexdigest", ossl_digest_hexdigest, 0);
- rb_define_alias(cDigest, "inspect", "hexdigest");
- rb_define_alias(cDigest, "to_s", "hexdigest");
-
+ rb_define_method(cDigest, "reset", ossl_digest_reset, 0);
rb_define_method(cDigest, "update", ossl_digest_update, 1);
rb_define_alias(cDigest, "<<", "update");
-
- rb_define_method(cDigest, "==", ossl_digest_equal, 1);
-
+ rb_define_private_method(cDigest, "finish", ossl_digest_finish, -1);
+ rb_define_method(cDigest, "digest_length", ossl_digest_size, 0);
+ rb_define_method(cDigest, "block_length", ossl_digest_block_length, 0);
+
rb_define_method(cDigest, "name", ossl_digest_name, 0);
- rb_define_method(cDigest, "size", ossl_digest_size, 0);
}
diff --git a/ext/openssl/ossl_digest.h b/ext/openssl/ossl_digest.h
index b35bd217b3..8cc5b1bc56 100644
--- a/ext/openssl/ossl_digest.h
+++ b/ext/openssl/ossl_digest.h
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_digest.h,v 1.2 2003/09/05 09:08:40 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -11,7 +11,6 @@
#if !defined(_OSSL_DIGEST_H_)
#define _OSSL_DIGEST_H_
-extern VALUE mDigest;
extern VALUE cDigest;
extern VALUE eDigestError;
diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c
index 6cc0183c0e..cd835d1237 100644
--- a/ext/openssl/ossl_engine.c
+++ b/ext/openssl/ossl_engine.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_engine.c,v 1.4.2.6 2005/09/18 22:56:11 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
* All rights reserved.
@@ -40,7 +40,7 @@ VALUE eEngineError;
*/
#define OSSL_ENGINE_LOAD_IF_MATCH(x) \
do{\
- if(!strcmp(#x, RSTRING(name)->ptr)){\
+ if(!strcmp(#x, RSTRING_PTR(name))){\
ENGINE_load_##x();\
return Qtrue;\
}\
@@ -75,7 +75,7 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto);
#endif
OSSL_ENGINE_LOAD_IF_MATCH(openssl);
- rb_warning("no such builtin loader for `%s'", RSTRING(name)->ptr);
+ rb_warning("no such builtin loader for `%s'", RSTRING_PTR(name));
return Qnil;
#endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
}
@@ -112,7 +112,7 @@ ossl_engine_s_by_id(VALUE klass, VALUE id)
StringValue(id);
ossl_engine_s_load(1, &id, klass);
- if(!(e = ENGINE_by_id(RSTRING(id)->ptr)))
+ if(!(e = ENGINE_by_id(RSTRING_PTR(id))))
ossl_raise(eEngineError, NULL);
WrapEngine(klass, obj, e);
if(rb_block_given_p()) rb_yield(obj);
@@ -281,8 +281,8 @@ ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "11", &cmd, &val);
StringValue(cmd);
if (!NIL_P(val)) StringValue(val);
- ret = ENGINE_ctrl_cmd_string(e, RSTRING(cmd)->ptr,
- NIL_P(val) ? NULL : RSTRING(val)->ptr, 0);
+ ret = ENGINE_ctrl_cmd_string(e, RSTRING_PTR(cmd),
+ NIL_P(val) ? NULL : RSTRING_PTR(val), 0);
if (!ret) ossl_raise(eEngineError, NULL);
return self;
diff --git a/ext/openssl/ossl_engine.h b/ext/openssl/ossl_engine.h
index ccc426481a..ea2f256912 100644
--- a/ext/openssl/ossl_engine.h
+++ b/ext/openssl/ossl_engine.h
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_engine.h,v 1.1 2003/10/02 08:47:11 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2003 Michal Rokos <m.rokos@sh.cvut.cz>
* Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c
index cd66ab6e2c..ef77d6c427 100644
--- a/ext/openssl/ossl_hmac.c
+++ b/ext/openssl/ossl_hmac.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_hmac.c,v 1.4.2.2 2004/12/15 01:54:39 matz Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -57,6 +57,12 @@ ossl_hmac_alloc(VALUE klass)
return obj;
}
+
+/*
+ * call-seq:
+ * HMAC.new(key, digest) -> hmac
+ *
+ */
static VALUE
ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
{
@@ -64,7 +70,7 @@ ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
StringValue(key);
GetHMAC(self, ctx);
- HMAC_Init_ex(ctx, RSTRING(key)->ptr, RSTRING(key)->len,
+ HMAC_Init_ex(ctx, RSTRING_PTR(key), RSTRING_LEN(key),
GetDigestPtr(digest), NULL);
return self;
@@ -81,12 +87,15 @@ ossl_hmac_copy(VALUE self, VALUE other)
GetHMAC(self, ctx1);
SafeGetHMAC(other, ctx2);
- if (!HMAC_CTX_copy(ctx1, ctx2)) {
- ossl_raise(eHMACError, NULL);
- }
+ HMAC_CTX_copy(ctx1, ctx2);
return self;
}
+/*
+ * call-seq:
+ * hmac.update(string) -> self
+ *
+ */
static VALUE
ossl_hmac_update(VALUE self, VALUE data)
{
@@ -94,7 +103,7 @@ ossl_hmac_update(VALUE self, VALUE data)
StringValue(data);
GetHMAC(self, ctx);
- HMAC_Update(ctx, RSTRING(data)->ptr, RSTRING(data)->len);
+ HMAC_Update(ctx, RSTRING_PTR(data), RSTRING_LEN(data));
return self;
}
@@ -104,9 +113,7 @@ hmac_final(HMAC_CTX *ctx, char **buf, int *buf_len)
{
HMAC_CTX final;
- if (!HMAC_CTX_copy(&final, ctx)) {
- ossl_raise(eHMACError, NULL);
- }
+ HMAC_CTX_copy(&final, ctx);
if (!(*buf = OPENSSL_malloc(HMAC_size(&final)))) {
HMAC_CTX_cleanup(&final);
OSSL_Debug("Allocating %d mem", HMAC_size(&final));
@@ -116,6 +123,11 @@ hmac_final(HMAC_CTX *ctx, char **buf, int *buf_len)
HMAC_CTX_cleanup(&final);
}
+/*
+ * call-seq:
+ * hmac.digest -> aString
+ *
+ */
static VALUE
ossl_hmac_digest(VALUE self)
{
@@ -131,6 +143,11 @@ ossl_hmac_digest(VALUE self)
return digest;
}
+/*
+ * call-seq:
+ * hmac.hexdigest -> aString
+ *
+ */
static VALUE
ossl_hmac_hexdigest(VALUE self)
{
@@ -151,6 +168,27 @@ ossl_hmac_hexdigest(VALUE self)
return hexdigest;
}
+/*
+ * call-seq:
+ * hmac.reset -> self
+ *
+ */
+static VALUE
+ossl_hmac_reset(VALUE self)
+{
+ HMAC_CTX *ctx;
+
+ GetHMAC(self, ctx);
+ HMAC_Init_ex(ctx, NULL, 0, NULL, NULL);
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * HMAC.digest(digest, key, data) -> aString
+ *
+ */
static VALUE
ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
{
@@ -159,12 +197,17 @@ ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data)
StringValue(key);
StringValue(data);
- buf = HMAC(GetDigestPtr(digest), RSTRING(key)->ptr, RSTRING(key)->len,
- RSTRING(data)->ptr, RSTRING(data)->len, NULL, &buf_len);
+ buf = HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LEN(key),
+ RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len);
return rb_str_new(buf, buf_len);
}
+/*
+ * call-seq:
+ * HMAC.digest(digest, key, data) -> aString
+ *
+ */
static VALUE
ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
{
@@ -175,8 +218,8 @@ ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
StringValue(key);
StringValue(data);
- buf = HMAC(GetDigestPtr(digest), RSTRING(key)->ptr, RSTRING(key)->len,
- RSTRING(data)->ptr, RSTRING(data)->len, NULL, &buf_len);
+ buf = HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LEN(key),
+ RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len);
if (string2hex(buf, buf_len, &hexbuf, NULL) != 2 * buf_len) {
ossl_raise(eHMACError, "Cannot convert buf to hexbuf");
}
@@ -191,6 +234,10 @@ ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data)
void
Init_ossl_hmac()
{
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+#endif
+
eHMACError = rb_define_class_under(mOSSL, "HMACError", eOSSLError);
cHMAC = rb_define_class_under(mOSSL, "HMAC", rb_cObject);
@@ -202,6 +249,7 @@ Init_ossl_hmac()
rb_define_method(cHMAC, "initialize", ossl_hmac_initialize, 2);
rb_define_copy_func(cHMAC, ossl_hmac_copy);
+ rb_define_method(cHMAC, "reset", ossl_hmac_reset, 0);
rb_define_method(cHMAC, "update", ossl_hmac_update, 1);
rb_define_alias(cHMAC, "<<", "update");
rb_define_method(cHMAC, "digest", ossl_hmac_digest, 0);
diff --git a/ext/openssl/ossl_hmac.h b/ext/openssl/ossl_hmac.h
index 2c8d69c177..1a2978b39a 100644
--- a/ext/openssl/ossl_hmac.h
+++ b/ext/openssl/ossl_hmac.h
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_hmac.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
diff --git a/ext/openssl/ossl_ns_spki.c b/ext/openssl/ossl_ns_spki.c
index bd8c59faf9..738a203d93 100644
--- a/ext/openssl/ossl_ns_spki.c
+++ b/ext/openssl/ossl_ns_spki.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_ns_spki.c,v 1.3.2.5 2006/03/17 10:10:53 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -62,14 +62,15 @@ ossl_spki_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
StringValue(buffer);
- if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING(buffer)->ptr, -1))) {
- p = RSTRING(buffer)->ptr;
- if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING(buffer)->len))) {
+ if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING_PTR(buffer), -1))) {
+ p = RSTRING_PTR(buffer);
+ if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING_LEN(buffer)))) {
ossl_raise(eSPKIError, NULL);
}
}
NETSCAPE_SPKI_free(DATA_PTR(self));
DATA_PTR(self) = spki;
+ ERR_clear_error();
return self;
}
@@ -86,7 +87,7 @@ ossl_spki_to_der(VALUE self)
if ((len = i2d_NETSCAPE_SPKI(spki, NULL)) <= 0)
ossl_raise(eX509CertError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if (i2d_NETSCAPE_SPKI(spki, &p) <= 0)
ossl_raise(eX509CertError, NULL);
ossl_str_adjust(str, p);
@@ -182,8 +183,8 @@ ossl_spki_set_challenge(VALUE self, VALUE str)
StringValue(str);
GetSPKI(self, spki);
- if (!ASN1_STRING_set(spki->spkac->challenge, RSTRING(str)->ptr,
- RSTRING(str)->len)) {
+ if (!ASN1_STRING_set(spki->spkac->challenge, RSTRING_PTR(str),
+ RSTRING_LEN(str))) {
ossl_raise(eSPKIError, NULL);
}
diff --git a/ext/openssl/ossl_ns_spki.h b/ext/openssl/ossl_ns_spki.h
index 2ca1fdcd62..9977035a9c 100644
--- a/ext/openssl/ossl_ns_spki.h
+++ b/ext/openssl/ossl_ns_spki.h
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_ns_spki.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c
index f2097b967e..1e8e5903bd 100644
--- a/ext/openssl/ossl_ocsp.c
+++ b/ext/openssl/ossl_ocsp.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_ocsp.c,v 1.4.2.2 2005/01/22 20:28:02 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2003 Michal Rokos <m.rokos@sh.cvut.cz>
* Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
@@ -109,9 +109,9 @@ ossl_ocspreq_initialize(int argc, VALUE *argv, VALUE self)
if(!NIL_P(arg)){
arg = ossl_to_der_if_possible(arg);
StringValue(arg);
- p = (unsigned char*)RSTRING(arg)->ptr;
+ p = (unsigned char*)RSTRING_PTR(arg);
if(!d2i_OCSP_REQUEST((OCSP_REQUEST**)&DATA_PTR(self), &p,
- RSTRING(arg)->len)){
+ RSTRING_LEN(arg))){
ossl_raise(eOCSPError, "cannot load DER encoded request");
}
}
@@ -134,7 +134,7 @@ ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self)
else{
StringValue(val);
GetOCSPReq(self, req);
- ret = OCSP_request_add1_nonce(req, RSTRING(val)->ptr, RSTRING(val)->len);
+ ret = OCSP_request_add1_nonce(req, RSTRING_PTR(val), RSTRING_LEN(val));
}
if(!ret) ossl_raise(eOCSPError, NULL);
@@ -265,7 +265,7 @@ ossl_ocspreq_to_der(VALUE self)
if((len = i2d_OCSP_REQUEST(req, NULL)) <= 0)
ossl_raise(eOCSPError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_OCSP_REQUEST(req, &p) <= 0)
ossl_raise(eOCSPError, NULL);
ossl_str_adjust(str, p);
@@ -316,9 +316,9 @@ ossl_ocspres_initialize(int argc, VALUE *argv, VALUE self)
if(!NIL_P(arg)){
arg = ossl_to_der_if_possible(arg);
StringValue(arg);
- p = RSTRING(arg)->ptr;
+ p = RSTRING_PTR(arg);
if(!d2i_OCSP_RESPONSE((OCSP_RESPONSE**)&DATA_PTR(self), &p,
- RSTRING(arg)->len)){
+ RSTRING_LEN(arg))){
ossl_raise(eOCSPError, "cannot load DER encoded response");
}
}
@@ -377,7 +377,7 @@ ossl_ocspres_to_der(VALUE self)
if((len = i2d_OCSP_RESPONSE(res, NULL)) <= 0)
ossl_raise(eOCSPError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_OCSP_RESPONSE(res, NULL) <= 0)
ossl_raise(eOCSPError, NULL);
ossl_str_adjust(str, p);
@@ -436,7 +436,7 @@ ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self)
else{
StringValue(val);
GetOCSPBasicRes(self, bs);
- ret = OCSP_basic_add1_nonce(bs, RSTRING(val)->ptr, RSTRING(val)->len);
+ ret = OCSP_basic_add1_nonce(bs, RSTRING_PTR(val), RSTRING_LEN(val));
}
if(!ret) ossl_raise(eOCSPError, NULL);
@@ -461,8 +461,8 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
if(!NIL_P(ext)){
/* All ary's members should be X509Extension */
Check_Type(ext, T_ARRAY);
- for (i = 0; i < RARRAY(ext)->len; i++)
- OSSL_Check_Kind(RARRAY(ext)->ptr[i], cX509Ext);
+ for (i = 0; i < RARRAY_LEN(ext); i++)
+ OSSL_Check_Kind(RARRAY_PTR(ext)[i], cX509Ext);
}
error = 0;
@@ -490,8 +490,8 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
X509_EXTENSION *x509ext;
sk_X509_EXTENSION_pop_free(single->singleExtensions, X509_EXTENSION_free);
single->singleExtensions = NULL;
- for(i = 0; i < RARRAY(ext)->len; i++){
- x509ext = DupX509ExtPtr(RARRAY(ext)->ptr[i]);
+ for(i = 0; i < RARRAY_LEN(ext); i++){
+ x509ext = DupX509ExtPtr(RARRAY_PTR(ext)[i]);
if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){
X509_EXTENSION_free(x509ext);
error = 1;
@@ -681,7 +681,7 @@ Init_ossl_ocsp()
{
mOCSP = rb_define_module_under(mOSSL, "OCSP");
- eOCSPError = rb_define_class_under(mOCSP, "OCSPError", rb_cObject);
+ eOCSPError = rb_define_class_under(mOCSP, "OCSPError", eOSSLError);
cOCSPReq = rb_define_class_under(mOCSP, "Request", rb_cObject);
rb_define_alloc_func(cOCSPReq, ossl_ocspreq_alloc);
diff --git a/ext/openssl/ossl_ocsp.h b/ext/openssl/ossl_ocsp.h
index 244fbb2a74..65b4f2e23f 100644
--- a/ext/openssl/ossl_ocsp.h
+++ b/ext/openssl/ossl_ocsp.h
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_ocsp.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2003 Michal Rokos <m.rokos@sh.cvut.cz>
* Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c
index e4b334c67e..2ec69ba8db 100644
--- a/ext/openssl/ossl_pkcs12.c
+++ b/ext/openssl/ossl_pkcs12.c
@@ -1,7 +1,7 @@
/*
* This program is licenced under the same licence as Ruby.
* (See the file 'LICENCE'.)
- * $Id: ossl_pkcs12.c,v 1.2 2003/12/15 00:30:12 usa Exp $
+ * $Id$
*/
#include "ossl.h"
@@ -30,7 +30,6 @@
/*
* Classes
*/
-VALUE mPKCS12;
VALUE cPKCS12;
VALUE ePKCS12Error;
@@ -49,32 +48,85 @@ ossl_pkcs12_s_allocate(VALUE klass)
return obj;
}
+/*
+ * call-seq:
+ * PKCS12.create(pass, name, key, cert [, ca, [, key_pbe [, cert_pbe [, key_iter [, mac_iter [, keytype]]]]]])
+ *
+ * === Parameters
+ * * +pass+ - string
+ * * +name+ - A string describing the key.
+ * * +key+ - Any PKey.
+ * * +cert+ - A X509::Certificate.
+ * * * The public_key portion of the certificate must contain a valid public key.
+ * * * The not_before and not_after fields must be filled in.
+ * * +ca+ - An optional array of X509::Certificate's.
+ * * +key_pbe+ - string
+ * * +cert_pbe+ - string
+ * * +key_iter+ - integer
+ * * +mac_iter+ - integer
+ * * +keytype+ - An integer representing an MSIE specific extension.
+ *
+ * Any optional arguments may be supplied as nil to preserve the OpenSSL defaults.
+ *
+ * See the OpenSSL documentation for PKCS12_create().
+ */
static VALUE
ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
{
- VALUE pass, name, pkey, cert, ca;
+ VALUE pass, name, pkey, cert, ca, key_nid, cert_nid, key_iter, mac_iter, keytype;
VALUE obj;
char *passphrase, *friendlyname;
EVP_PKEY *key;
X509 *x509;
STACK_OF(X509) *x509s;
+ int nkey = 0, ncert = 0, kiter = 0, miter = 0, ktype = 0;
PKCS12 *p12;
- rb_scan_args(argc, argv, "41", &pass, &name, &pkey, &cert, &ca);
+ rb_scan_args(argc, argv, "46", &pass, &name, &pkey, &cert, &ca, &key_nid, &cert_nid, &key_iter, &mac_iter, &keytype);
passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass);
friendlyname = NIL_P(name) ? NULL : StringValuePtr(name);
key = GetPKeyPtr(pkey);
x509 = GetX509CertPtr(cert);
x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca);
+/* TODO: make a VALUE to nid function */
+ if (!NIL_P(key_nid)) {
+ if ((nkey = OBJ_txt2nid(StringValuePtr(key_nid))) == NID_undef)
+ rb_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(key_nid));
+ }
+ if (!NIL_P(cert_nid)) {
+ if ((ncert = OBJ_txt2nid(StringValuePtr(cert_nid))) == NID_undef)
+ rb_raise(rb_eArgError, "Unknown PBE algorithm %s", StringValuePtr(cert_nid));
+ }
+ if (!NIL_P(key_iter))
+ kiter = NUM2INT(key_iter);
+ if (!NIL_P(mac_iter))
+ miter = NUM2INT(mac_iter);
+ if (!NIL_P(keytype))
+ ktype = NUM2INT(keytype);
+
p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s,
- 0, 0, 0, 0, 0);
+ nkey, ncert, kiter, miter, ktype);
sk_X509_pop_free(x509s, X509_free);
if(!p12) ossl_raise(ePKCS12Error, NULL);
WrapPKCS12(cPKCS12, obj, p12);
+ ossl_pkcs12_set_key(obj, pkey);
+ ossl_pkcs12_set_cert(obj, cert);
+ ossl_pkcs12_set_ca_certs(obj, ca);
+
return obj;
}
+/*
+ * call-seq:
+ * PKCS12.new -> pkcs12
+ * PKCS12.new(str) -> pkcs12
+ * PKCS12.new(str, pass) -> pkcs12
+ *
+ * === Parameters
+ * * +str+ - Must be a DER encoded PKCS12 string.
+ * * +pass+ - string
+ */
static VALUE
ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -94,7 +146,7 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
pkey = cert = ca = Qnil;
if(!PKCS12_parse((PKCS12*)DATA_PTR(self), passphrase, &key, &x509, &x509s))
- ossl_raise(ePKCS12Error, NULL);
+ ossl_raise(ePKCS12Error, "PKCS12_parse");
pkey = rb_protect((VALUE(*)_((VALUE)))ossl_pkey_new, (VALUE)key,
&st); /* NO DUP */
if(st) goto err;
@@ -129,7 +181,7 @@ ossl_pkcs12_to_der(VALUE self)
if((len = i2d_PKCS12(p12, NULL)) <= 0)
ossl_raise(ePKCS12Error, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_PKCS12(p12, &p) <= 0)
ossl_raise(ePKCS12Error, NULL);
ossl_str_adjust(str, p);
@@ -140,10 +192,14 @@ ossl_pkcs12_to_der(VALUE self)
void
Init_ossl_pkcs12()
{
- mPKCS12 = rb_define_module_under(mOSSL, "PKCS12");
- cPKCS12 = rb_define_class_under(mPKCS12, "PKCS12", rb_cObject);
- ePKCS12Error = rb_define_class_under(mPKCS12, "PKCS12Error", eOSSLError);
- rb_define_module_function(mPKCS12, "create", ossl_pkcs12_s_create, -1);
+ /*
+ * Defines a file format commonly used to store private keys with
+ * accompanying public key certificates, protected with a password-based
+ * symmetric key.
+ */
+ cPKCS12 = rb_define_class_under(mOSSL, "PKCS12", rb_cObject);
+ ePKCS12Error = rb_define_class_under(cPKCS12, "PKCS12Error", eOSSLError);
+ rb_define_singleton_method(cPKCS12, "create", ossl_pkcs12_s_create, -1);
rb_define_alloc_func(cPKCS12, ossl_pkcs12_s_allocate);
rb_attr(cPKCS12, rb_intern("key"), 1, 0, Qfalse);
diff --git a/ext/openssl/ossl_pkcs12.h b/ext/openssl/ossl_pkcs12.h
index 95b29de9b5..24d25d00bb 100644
--- a/ext/openssl/ossl_pkcs12.h
+++ b/ext/openssl/ossl_pkcs12.h
@@ -1,12 +1,11 @@
/*
* This program is licenced under the same licence as Ruby.
* (See the file 'LICENCE'.)
- * $Id: ossl_pkcs12.h,v 1.1.2.1 2005/06/19 16:29:17 gotoyuzo Exp $
+ * $Id$
*/
#if !defined(_OSSL_PKCS12_H_)
#define _OSSL_PKCS12_H_
-extern VALUE mPKCS12;
extern VALUE cPKCS12;
extern VALUE ePKCS12Error;
diff --git a/ext/openssl/ossl_pkcs5.c b/ext/openssl/ossl_pkcs5.c
new file mode 100644
index 0000000000..007889fc94
--- /dev/null
+++ b/ext/openssl/ossl_pkcs5.c
@@ -0,0 +1,96 @@
+/*
+ * $Id$
+ * Copyright (C) 2007 Technorama Ltd. <oss-ruby@technorama.net>
+ */
+#include "ossl.h"
+
+VALUE mPKCS5;
+VALUE ePKCS5;
+
+/*
+ * call-seq:
+ * PKCS5.pbkdf2_hmac(pass, salt, iter, keylen, digest) => string
+ *
+ * === Parameters
+ * * +pass+ - string
+ * * +salt+ - string
+ * * +iter+ - integer - should be greater than 1000. 2000 is better.
+ * * +keylen+ - integer
+ * * +digest+ - a string or OpenSSL::Digest object.
+ *
+ * Available in OpenSSL 0.9.9?.
+ *
+ * Digests other than SHA1 may not be supported by other cryptography libraries.
+ */
+static VALUE
+ossl_pkcs5_pbkdf2_hmac(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen, VALUE digest)
+{
+#ifdef HAVE_PKCS5_PBKDF2_HMAC
+ VALUE str;
+ const EVP_MD *md;
+ int len = NUM2INT(keylen);
+
+ StringValue(pass);
+ StringValue(salt);
+ md = GetDigestPtr(digest);
+
+ str = rb_str_new(0, len);
+
+ if (PKCS5_PBKDF2_HMAC(RSTRING_PTR(pass), RSTRING_LEN(pass), RSTRING_PTR(salt), RSTRING_LEN(salt), NUM2INT(iter), md, len, RSTRING_PTR(str)) != 1)
+ ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC");
+
+ return str;
+#else
+ rb_notimplement();
+#endif
+}
+
+
+/*
+ * call-seq:
+ * PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, keylen) => string
+ *
+ * === Parameters
+ * * +pass+ - string
+ * * +salt+ - string
+ * * +iter+ - integer - should be greater than 1000. 2000 is better.
+ * * +keylen+ - integer
+ *
+ * This method is available almost any version OpenSSL.
+ *
+ * Conforms to rfc2898.
+ */
+static VALUE
+ossl_pkcs5_pbkdf2_hmac_sha1(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen)
+{
+#ifdef HAVE_PKCS5_PBKDF2_HMAC_SHA1
+ VALUE str;
+ int len = NUM2INT(keylen);
+
+ StringValue(pass);
+ StringValue(salt);
+
+ str = rb_str_new(0, len);
+
+ if (PKCS5_PBKDF2_HMAC_SHA1(RSTRING_PTR(pass), RSTRING_LEN(pass), RSTRING_PTR(salt), RSTRING_LEN(salt), NUM2INT(iter), len, RSTRING_PTR(str)) != 1)
+ ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC_SHA1");
+
+ return str;
+#else
+ rb_notimplement();
+#endif
+}
+
+void
+Init_ossl_pkcs5()
+{
+ /*
+ * Password-based Encryption
+ *
+ */
+ mPKCS5 = rb_define_module_under(mOSSL, "PKCS5");
+ ePKCS5 = rb_define_class_under(mPKCS5, "PKCS5Error", eOSSLError);
+
+ rb_define_module_function(mPKCS5, "pbkdf2_hmac", ossl_pkcs5_pbkdf2_hmac, 5);
+ rb_define_module_function(mPKCS5, "pbkdf2_hmac_sha1", ossl_pkcs5_pbkdf2_hmac_sha1, 4);
+}
diff --git a/ext/openssl/ossl_pkcs5.h b/ext/openssl/ossl_pkcs5.h
new file mode 100644
index 0000000000..a3b132bc50
--- /dev/null
+++ b/ext/openssl/ossl_pkcs5.h
@@ -0,0 +1,6 @@
+#if !defined(_OSSL_PKCS5_H_)
+#define _OSSL_PKCS5_H_
+
+void Init_ossl_pkcs5(void);
+
+#endif /* _OSSL_PKCS5_H_ */
diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c
index 0fa85299aa..6918844779 100644
--- a/ext/openssl/ossl_pkcs7.c
+++ b/ext/openssl/ossl_pkcs7.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_pkcs7.c,v 1.5.2.3 2005/09/10 01:11:15 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -71,7 +71,6 @@
/*
* Classes
*/
-VALUE mPKCS7;
VALUE cPKCS7;
VALUE cPKCS7Signer;
VALUE cPKCS7Recipient;
@@ -134,7 +133,8 @@ DupPKCS7RecipientPtr(VALUE obj)
}
/*
- * Private
+ * call-seq:
+ * PKCS7.read_smime(string) => pkcs7
*/
static VALUE
ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
@@ -156,6 +156,10 @@ ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
return ret;
}
+/*
+ * call-seq:
+ * PKCS7.write_smime(pkcs7 [, data [, flags]]) => string
+ */
static VALUE
ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass)
{
@@ -187,6 +191,10 @@ ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass)
return str;
}
+/*
+ * call-seq:
+ * PKCS7.sign(cert, key, data, [, certs [, flags]]) => pkcs7
+ */
static VALUE
ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass)
{
@@ -226,6 +234,10 @@ ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass)
return ret;
}
+/*
+ * call-seq:
+ * PKCS7.encrypt(certs, data, [, cipher [, flags]]) => pkcs7
+ */
static VALUE
ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass)
{
@@ -287,6 +299,13 @@ ossl_pkcs7_alloc(VALUE klass)
return obj;
}
+/*
+ * call-seq:
+ * PKCS7.new => pkcs7
+ * PKCS7.new(string) => pkcs7
+ *
+ * Many methods in this class aren't documented.
+ */
static VALUE
ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -335,7 +354,7 @@ static int
ossl_pkcs7_sym2typeid(VALUE sym)
{
int i, ret = Qnil;
- char *s;
+ const char *s;
static struct {
const char *name;
@@ -364,6 +383,10 @@ ossl_pkcs7_sym2typeid(VALUE sym)
return ret;
}
+/*
+ * call-seq:
+ * pkcs7.type = type => type
+ */
static VALUE
ossl_pkcs7_set_type(VALUE self, VALUE type)
{
@@ -376,6 +399,10 @@ ossl_pkcs7_set_type(VALUE self, VALUE type)
return type;
}
+/*
+ * call-seq:
+ * pkcs7.type => string or nil
+ */
static VALUE
ossl_pkcs7_get_type(VALUE self)
{
@@ -583,7 +610,7 @@ ossl_pkcs7_set_certificates(VALUE self, VALUE ary)
certs = pkcs7_get_certs_or_crls(self, 1);
while((cert = sk_X509_pop(certs))) X509_free(cert);
- rb_iterate(rb_each, ary, ossl_pkcs7_set_certs_i, self);
+ rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_certs_i, self);
return ary;
}
@@ -623,7 +650,7 @@ ossl_pkcs7_set_crls(VALUE self, VALUE ary)
crls = pkcs7_get_certs_or_crls(self, 0);
while((crl = sk_X509_CRL_pop(crls))) X509_CRL_free(crl);
- rb_iterate(rb_each, ary, ossl_pkcs7_set_crls_i, self);
+ rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_crls_i, self);
return ary;
}
@@ -667,8 +694,10 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
}
ok = PKCS7_verify(p7, x509s, x509st, in, out, flg);
BIO_free(in);
+ if (ok < 0) ossl_raise(ePKCS7Error, NULL);
msg = ERR_reason_error_string(ERR_get_error());
ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil);
+ ERR_clear_error();
data = ossl_membio2str(out);
ossl_pkcs7_set_data(self, data);
sk_X509_pop_free(x509s, X509_free);
@@ -749,7 +778,7 @@ ossl_pkcs7_to_der(VALUE self)
if((len = i2d_PKCS7(pkcs7, NULL)) <= 0)
ossl_raise(ePKCS7Error, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_PKCS7(pkcs7, &p) <= 0)
ossl_raise(ePKCS7Error, NULL);
ossl_str_adjust(str, p);
@@ -924,15 +953,12 @@ ossl_pkcs7ri_get_enc_key(VALUE self)
void
Init_ossl_pkcs7()
{
- mPKCS7 = rb_define_module_under(mOSSL, "PKCS7");
-
- ePKCS7Error = rb_define_class_under(mPKCS7, "PKCS7Error", eOSSLError);
-
- cPKCS7 = rb_define_class_under(mPKCS7, "PKCS7", rb_cObject);
- rb_define_singleton_method(mPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1);
- rb_define_singleton_method(mPKCS7, "write_smime", ossl_pkcs7_s_write_smime, -1);
- rb_define_singleton_method(mPKCS7, "sign", ossl_pkcs7_s_sign, -1);
- rb_define_singleton_method(mPKCS7, "encrypt", ossl_pkcs7_s_encrypt, -1);
+ cPKCS7 = rb_define_class_under(mOSSL, "PKCS7", rb_cObject);
+ ePKCS7Error = rb_define_class_under(cPKCS7, "PKCS7Error", eOSSLError);
+ rb_define_singleton_method(cPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1);
+ rb_define_singleton_method(cPKCS7, "write_smime", ossl_pkcs7_s_write_smime, -1);
+ rb_define_singleton_method(cPKCS7, "sign", ossl_pkcs7_s_sign, -1);
+ rb_define_singleton_method(cPKCS7, "encrypt", ossl_pkcs7_s_encrypt, -1);
rb_attr(cPKCS7, rb_intern("data"), 1, 0, Qfalse);
rb_attr(cPKCS7, rb_intern("error_string"), 1, 1, Qfalse);
rb_define_alloc_func(cPKCS7, ossl_pkcs7_alloc);
@@ -962,8 +988,8 @@ Init_ossl_pkcs7()
rb_define_alias(cPKCS7, "to_s", "to_pem");
rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0);
- cPKCS7Signer = rb_define_class_under(mPKCS7, "SignerInfo", rb_cObject);
- rb_define_const(mPKCS7, "Signer", cPKCS7Signer);
+ cPKCS7Signer = rb_define_class_under(cPKCS7, "SignerInfo", rb_cObject);
+ rb_define_const(cPKCS7, "Signer", cPKCS7Signer);
rb_define_alloc_func(cPKCS7Signer, ossl_pkcs7si_alloc);
rb_define_method(cPKCS7Signer, "initialize", ossl_pkcs7si_initialize,3);
rb_define_method(cPKCS7Signer, "issuer", ossl_pkcs7si_get_issuer, 0);
@@ -971,14 +997,14 @@ Init_ossl_pkcs7()
rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0);
rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0);
- cPKCS7Recipient = rb_define_class_under(mPKCS7,"RecipientInfo",rb_cObject);
+ cPKCS7Recipient = rb_define_class_under(cPKCS7,"RecipientInfo",rb_cObject);
rb_define_alloc_func(cPKCS7Recipient, ossl_pkcs7ri_alloc);
rb_define_method(cPKCS7Recipient, "initialize", ossl_pkcs7ri_initialize,1);
rb_define_method(cPKCS7Recipient, "issuer", ossl_pkcs7ri_get_issuer,0);
rb_define_method(cPKCS7Recipient, "serial", ossl_pkcs7ri_get_serial,0);
rb_define_method(cPKCS7Recipient, "enc_key", ossl_pkcs7ri_get_enc_key,0);
-#define DefPKCS7Const(x) rb_define_const(mPKCS7, #x, INT2NUM(PKCS7_##x))
+#define DefPKCS7Const(x) rb_define_const(cPKCS7, #x, INT2NUM(PKCS7_##x))
DefPKCS7Const(TEXT);
DefPKCS7Const(NOCERTS);
diff --git a/ext/openssl/ossl_pkcs7.h b/ext/openssl/ossl_pkcs7.h
index fdf0d9fb34..371c421103 100644
--- a/ext/openssl/ossl_pkcs7.h
+++ b/ext/openssl/ossl_pkcs7.h
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_pkcs7.h,v 1.1.2.1 2005/09/10 01:17:00 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -11,7 +11,6 @@
#if !defined(_OSSL_PKCS7_H_)
#define _OSSL_PKCS7_H_
-extern VALUE mPKCS7;
extern VALUE cPKCS7;
extern VALUE cPKCS7Signer;
extern VALUE cPKCS7Recipient;
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
index 5a061597f6..b295cfc25e 100644
--- a/ext/openssl/ossl_pkey.c
+++ b/ext/openssl/ossl_pkey.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_pkey.c,v 1.4.2.2 2005/04/08 09:26:54 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -55,6 +55,10 @@ ossl_pkey_new(EVP_PKEY *pkey)
case EVP_PKEY_DH:
return ossl_dh_new(pkey);
#endif
+#if !defined(OPENSSL_NO_EC) && (OPENSSL_VERSION_NUMBER >= 0x0090802fL)
+ case EVP_PKEY_EC:
+ return ossl_ec_new(pkey);
+#endif
default:
ossl_raise(ePKeyError, "unsupported key type");
}
@@ -68,7 +72,7 @@ ossl_pkey_new_from_file(VALUE filename)
EVP_PKEY *pkey;
SafeStringValue(filename);
- if (!(fp = fopen(RSTRING(filename)->ptr, "r"))) {
+ if (!(fp = fopen(RSTRING_PTR(filename), "r"))) {
ossl_raise(ePKeyError, "%s", strerror(errno));
}
@@ -108,7 +112,7 @@ EVP_PKEY *
DupPKeyPtr(VALUE obj)
{
EVP_PKEY *pkey;
-
+
SafeGetPKey(obj, pkey);
CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
@@ -169,13 +173,12 @@ ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
GetPKey(self, pkey);
EVP_SignInit(&ctx, GetDigestPtr(digest));
StringValue(data);
- EVP_SignUpdate(&ctx, RSTRING(data)->ptr, RSTRING(data)->len);
+ EVP_SignUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data));
str = rb_str_new(0, EVP_PKEY_size(pkey)+16);
- if (!EVP_SignFinal(&ctx, RSTRING(str)->ptr, &buf_len, pkey))
+ if (!EVP_SignFinal(&ctx, RSTRING_PTR(str), &buf_len, pkey))
ossl_raise(ePKeyError, NULL);
- assert(buf_len <= RSTRING(str)->len);
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
+ assert(buf_len <= RSTRING_LEN(str));
+ rb_str_set_len(str, buf_len);
return str;
}
@@ -190,8 +193,8 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
EVP_VerifyInit(&ctx, GetDigestPtr(digest));
StringValue(sig);
StringValue(data);
- EVP_VerifyUpdate(&ctx, RSTRING(data)->ptr, RSTRING(data)->len);
- switch (EVP_VerifyFinal(&ctx, RSTRING(sig)->ptr, RSTRING(sig)->len, pkey)) {
+ EVP_VerifyUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data));
+ switch (EVP_VerifyFinal(&ctx, RSTRING_PTR(sig), RSTRING_LEN(sig), pkey)) {
case 0:
return Qfalse;
case 1:
@@ -208,6 +211,10 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
void
Init_ossl_pkey()
{
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+#endif
+
mPKey = rb_define_module_under(mOSSL, "PKey");
ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
@@ -223,10 +230,11 @@ Init_ossl_pkey()
id_private_q = rb_intern("private?");
/*
- * INIT rsa, dsa
+ * INIT rsa, dsa, dh, ec
*/
Init_ossl_rsa();
Init_ossl_dsa();
Init_ossl_dh();
+ Init_ossl_ec();
}
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
index 224f0f4634..67ff1fddd0 100644
--- a/ext/openssl/ossl_pkey.h
+++ b/ext/openssl/ossl_pkey.h
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_pkey.h,v 1.2.2.2 2005/09/18 22:56:11 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -77,7 +77,24 @@ extern DH *OSSL_DEFAULT_DH_1024;
VALUE ossl_dh_new(EVP_PKEY *);
void Init_ossl_dh(void);
+/*
+ * EC
+ */
+extern VALUE cEC;
+extern VALUE eECError;
+extern VALUE cEC_GROUP;
+extern VALUE eEC_GROUP;
+extern VALUE cEC_POINT;
+extern VALUE eEC_POINT;
+VALUE ossl_ec_new(EVP_PKEY *);
+void Init_ossl_ec(void);
+
+
#define OSSL_PKEY_BN(keytype, name) \
+/* \
+ * call-seq: \
+ * key.##name -> aBN \
+ */ \
static VALUE ossl_##keytype##_get_##name(VALUE self) \
{ \
EVP_PKEY *pkey; \
@@ -89,6 +106,10 @@ static VALUE ossl_##keytype##_get_##name(VALUE self) \
return Qnil; \
return ossl_bn_new(bn); \
} \
+/* \
+ * call-seq: \
+ * key.##name = bn -> bn \
+ */ \
static VALUE ossl_##keytype##_set_##name(VALUE self, VALUE bignum) \
{ \
EVP_PKEY *pkey; \
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
index 79692f2f47..02c3d99ed8 100644
--- a/ext/openssl/ossl_pkey_dh.c
+++ b/ext/openssl/ossl_pkey_dh.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_pkey_dh.c,v 1.4.2.3 2005/04/08 09:26:54 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -99,6 +99,15 @@ dh_generate(int size, int gen)
return dh;
}
+/*
+ * call-seq:
+ * DH.generate(size [, generator]) -> dh
+ *
+ * === Parameters
+ * * +size+ is an integer representing the desired key size. Keys smaller than 1024 should be considered insecure.
+ * * +generator+ is a small number > 1, typically 2 or 5.
+ *
+ */
static VALUE
ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
{
@@ -107,9 +116,9 @@ ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
VALUE size, gen, obj;
if (rb_scan_args(argc, argv, "11", &size, &gen) == 2) {
- g = FIX2INT(gen);
+ g = NUM2INT(gen);
}
- dh = dh_generate(FIX2INT(size), g);
+ dh = dh_generate(NUM2INT(size), g);
obj = dh_instance(klass, dh);
if (obj == Qfalse) {
DH_free(dh);
@@ -119,6 +128,21 @@ ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
return obj;
}
+/*
+ * call-seq:
+ * DH.new([size [, generator] | string]) -> dh
+ *
+ * === Parameters
+ * * +size+ is an integer representing the desired key size. Keys smaller than 1024 should be considered insecure.
+ * * +generator+ is a small number > 1, typically 2 or 5.
+ * * +string+ contains the DER or PEM encoded key.
+ *
+ * === Examples
+ * * DH.new -> dh
+ * * DH.new(1024) -> dh
+ * * DH.new(1024, 5) -> dh
+ * * DH.new(File.read('key.pem')) -> dh
+ */
static VALUE
ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -134,7 +158,7 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
}
else if (FIXNUM_P(arg)) {
if (!NIL_P(gen)) {
- g = FIX2INT(gen);
+ g = NUM2INT(gen);
}
if (!(dh = dh_generate(FIX2INT(arg), g))) {
ossl_raise(eDHError, NULL);
@@ -158,19 +182,26 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/*
+ * call-seq:
+ * dh.public? -> true | false
+ *
+ */
static VALUE
ossl_dh_is_public(VALUE self)
{
EVP_PKEY *pkey;
GetPKeyDH(self, pkey);
- /*
- * Do we need to check dhp->dh->public_pkey?
- * return Qtrue;
- */
+
return (pkey->pkey.dh->pub_key) ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * dh.private? -> true | false
+ *
+ */
static VALUE
ossl_dh_is_private(VALUE self)
{
@@ -181,6 +212,11 @@ ossl_dh_is_private(VALUE self)
return (DH_PRIVATE(pkey->pkey.dh)) ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * dh.to_pem -> aString
+ *
+ */
static VALUE
ossl_dh_export(VALUE self)
{
@@ -201,6 +237,11 @@ ossl_dh_export(VALUE self)
return str;
}
+/*
+ * call-seq:
+ * dh.to_der -> aString
+ *
+ */
static VALUE
ossl_dh_to_der(VALUE self)
{
@@ -213,7 +254,7 @@ ossl_dh_to_der(VALUE self)
if((len = i2d_DHparams(pkey->pkey.dh, NULL)) <= 0)
ossl_raise(eDHError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_DHparams(pkey->pkey.dh, &p) < 0)
ossl_raise(eDHError, NULL);
ossl_str_adjust(str, p);
@@ -222,6 +263,9 @@ ossl_dh_to_der(VALUE self)
}
/*
+ * call-seq:
+ * dh.params -> hash
+ *
* Stores all parameters of key to the hash
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
* Don't use :-)) (I's up to you)
@@ -245,6 +289,9 @@ ossl_dh_get_params(VALUE self)
}
/*
+ * call-seq:
+ * dh.to_text -> aString
+ *
* Prints all parameters of key to buffer
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
* Don't use :-)) (I's up to you)
@@ -270,7 +317,10 @@ ossl_dh_to_text(VALUE self)
}
/*
- * Makes new instance DH PUBLIC_KEY from PRIVATE_KEY
+ * call-seq:
+ * dh.public_key -> aDH
+ *
+ * Makes new instance DH PUBLIC_KEY from PRIVATE_KEY
*/
static VALUE
ossl_dh_to_public_key(VALUE self)
@@ -290,6 +340,11 @@ ossl_dh_to_public_key(VALUE self)
return obj;
}
+/*
+ * call-seq:
+ * dh.check_params -> true | false
+ *
+ */
static VALUE
ossl_dh_check_params(VALUE self)
{
@@ -307,6 +362,11 @@ ossl_dh_check_params(VALUE self)
return codes == 0 ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * dh.generate_key -> self
+ *
+ */
static VALUE
ossl_dh_generate_key(VALUE self)
{
@@ -321,6 +381,18 @@ ossl_dh_generate_key(VALUE self)
return self;
}
+/*
+ * call-seq:
+ * dh.compute_key(pub_bn) -> aString
+ *
+ * === Parameters
+ * * +pub_bn+ is a OpenSSL::BN.
+ *
+ * Returns aString containing a shared secret computed from the other parties public value.
+ *
+ * See DH_compute_key() for further information.
+ *
+ */
static VALUE
ossl_dh_compute_key(VALUE self, VALUE pub)
{
@@ -335,11 +407,10 @@ ossl_dh_compute_key(VALUE self, VALUE pub)
pub_key = GetBNPtr(pub);
len = DH_size(dh);
str = rb_str_new(0, len);
- if ((len = DH_compute_key(RSTRING(str)->ptr, pub_key, dh)) < 0) {
+ if ((len = DH_compute_key(RSTRING_PTR(str), pub_key, dh)) < 0) {
ossl_raise(eDHError, NULL);
}
- RSTRING(str)->len = len;
- RSTRING(str)->ptr[len] = 0;
+ rb_str_set_len(str, len);
return str;
}
@@ -367,7 +438,7 @@ static unsigned char DEFAULT_DH_512_PRIM[] = {
};
static unsigned char DEFAULT_DH_512_GEN[] = { 0x02 };
DH *OSSL_DEFAULT_DH_512 = NULL;
-
+
/*
* -----BEGIN DH PARAMETERS-----
* MIGHAoGBAJ0lOVy0VIr/JebWn0zDwY2h+rqITFOpdNr6ugsgvkDXuucdcChhYExJ
@@ -406,7 +477,7 @@ ossl_create_dh(unsigned char *p, size_t plen, unsigned char *g, size_t glen)
dh->g = BN_bin2bn(g, glen, NULL);
if (dh->p == NULL || dh->g == NULL){
DH_free(dh);
- ossl_raise(eDHError, NULL);
+ ossl_raise(eDHError, NULL);
}
return dh;
@@ -418,6 +489,11 @@ ossl_create_dh(unsigned char *p, size_t plen, unsigned char *g, size_t glen)
void
Init_ossl_dh()
{
+#if 0 /* let rdoc know about mOSSL and mPKey */
+ mOSSL = rb_define_module("OpenSSL");
+ mPKey = rb_define_module_under(mOSSL, "PKey");
+#endif
+
eDHError = rb_define_class_under(mPKey, "DHError", ePKeyError);
cDH = rb_define_class_under(mPKey, "DH", cPKey);
rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1);
@@ -448,11 +524,9 @@ Init_ossl_dh()
}
#else /* defined NO_DH */
-# warning >>> OpenSSL is compiled without DH support <<<
void
Init_ossl_dh()
{
- rb_warning("OpenSSL is compiled without DH support");
}
#endif /* NO_DH */
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
index 2a6060fe77..d9c7fcbe78 100644
--- a/ext/openssl/ossl_pkey_dsa.c
+++ b/ext/openssl/ossl_pkey_dsa.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_pkey_dsa.c,v 1.5.2.3 2005/09/18 22:56:11 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -99,10 +99,18 @@ dsa_generate(int size)
return dsa;
}
+/*
+ * call-seq:
+ * DSA.generate(size) -> dsa
+ *
+ * === Parameters
+ * * +size+ is an integer representing the desired key size.
+ *
+ */
static VALUE
ossl_dsa_s_generate(VALUE klass, VALUE size)
{
- DSA *dsa = dsa_generate(FIX2INT(size)); /* err handled by dsa_instance */
+ DSA *dsa = dsa_generate(NUM2INT(size)); /* err handled by dsa_instance */
VALUE obj = dsa_instance(klass, dsa);
if (obj == Qfalse) {
@@ -113,6 +121,22 @@ ossl_dsa_s_generate(VALUE klass, VALUE size)
return obj;
}
+/*
+ * call-seq:
+ * DSA.new([size | string [, pass]) -> dsa
+ *
+ * === Parameters
+ * * +size+ is an integer representing the desired key size.
+ * * +string+ contains a DER or PEM encoded key.
+ * * +pass+ is a string that contains a optional password.
+ *
+ * === Examples
+ * * DSA.new -> dsa
+ * * DSA.new(1024) -> dsa
+ * * DSA.new(File.read('dsa.pem')) -> dsa
+ * * DSA.new(File.read('dsa.pem'), 'mypassword') -> dsa
+ *
+ */
static VALUE
ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -163,6 +187,11 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/*
+ * call-seq:
+ * dsa.public? -> true | false
+ *
+ */
static VALUE
ossl_dsa_is_public(VALUE self)
{
@@ -170,13 +199,14 @@ ossl_dsa_is_public(VALUE self)
GetPKeyDSA(self, pkey);
- /*
- * Do we need to check dsap->dsa->public_pkey?
- * return Qtrue;
- */
return (pkey->pkey.dsa->pub_key) ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * dsa.private? -> true | false
+ *
+ */
static VALUE
ossl_dsa_is_private(VALUE self)
{
@@ -187,6 +217,19 @@ ossl_dsa_is_private(VALUE self)
return (DSA_PRIVATE(self, pkey->pkey.dsa)) ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * dsa.to_pem([cipher, password]) -> aString
+ *
+ * === Parameters
+ * +cipher+ is an OpenSSL::Cipher.
+ * +password+ is a string containing your password.
+ *
+ * === Examples
+ * * DSA.to_pem -> aString
+ * * DSA.to_pem(cipher, 'mypassword') -> aString
+ *
+ */
static VALUE
ossl_dsa_export(int argc, VALUE *argv, VALUE self)
{
@@ -224,6 +267,11 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self)
return str;
}
+/*
+ * call-seq:
+ * dsa.to_der -> aString
+ *
+ */
static VALUE
ossl_dsa_to_der(VALUE self)
{
@@ -241,7 +289,7 @@ ossl_dsa_to_der(VALUE self)
if((len = i2d_func(pkey->pkey.dsa, NULL)) <= 0)
ossl_raise(eDSAError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_func(pkey->pkey.dsa, &p) < 0)
ossl_raise(eDSAError, NULL);
ossl_str_adjust(str, p);
@@ -250,6 +298,9 @@ ossl_dsa_to_der(VALUE self)
}
/*
+ * call-seq:
+ * dsa.params -> hash
+ *
* Stores all parameters of key to the hash
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
* Don't use :-)) (I's up to you)
@@ -274,6 +325,9 @@ ossl_dsa_get_params(VALUE self)
}
/*
+ * call-seq:
+ * dsa.to_text -> aString
+ *
* Prints all parameters of key to buffer
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
* Don't use :-)) (I's up to you)
@@ -299,6 +353,9 @@ ossl_dsa_to_text(VALUE self)
}
/*
+ * call-seq:
+ * dsa.public_key -> aDSA
+ *
* Makes new instance DSA PUBLIC_KEY from PRIVATE_KEY
*/
static VALUE
@@ -321,6 +378,11 @@ ossl_dsa_to_public_key(VALUE self)
#define ossl_dsa_buf_size(pkey) (DSA_size((pkey)->pkey.dsa)+16)
+/*
+ * call-seq:
+ * dsa.syssign(string) -> aString
+ *
+ */
static VALUE
ossl_dsa_sign(VALUE self, VALUE data)
{
@@ -334,16 +396,20 @@ ossl_dsa_sign(VALUE self, VALUE data)
ossl_raise(eDSAError, "Private DSA key needed!");
}
str = rb_str_new(0, ossl_dsa_buf_size(pkey));
- if (!DSA_sign(0, RSTRING(data)->ptr, RSTRING(data)->len, RSTRING(str)->ptr,
+ if (!DSA_sign(0, RSTRING_PTR(data), RSTRING_LEN(data), RSTRING_PTR(str),
&buf_len, pkey->pkey.dsa)) { /* type is ignored (0) */
ossl_raise(eDSAError, NULL);
}
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
+ rb_str_set_len(str, buf_len);
return str;
}
+/*
+ * call-seq:
+ * dsa.sysverify(digest, sig) -> true | false
+ *
+ */
static VALUE
ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
{
@@ -354,8 +420,8 @@ ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
StringValue(digest);
StringValue(sig);
/* type is ignored (0) */
- ret = DSA_verify(0, RSTRING(digest)->ptr, RSTRING(digest)->len,
- RSTRING(sig)->ptr, RSTRING(sig)->len, pkey->pkey.dsa);
+ ret = DSA_verify(0, RSTRING_PTR(digest), RSTRING_LEN(digest),
+ RSTRING_PTR(sig), RSTRING_LEN(sig), pkey->pkey.dsa);
if (ret < 0) {
ossl_raise(eDSAError, NULL);
}
@@ -378,6 +444,11 @@ OSSL_PKEY_BN(dsa, priv_key);
void
Init_ossl_dsa()
{
+#if 0 /* let rdoc know about mOSSL and mPKey */
+ mOSSL = rb_define_module("OpenSSL");
+ mPKey = rb_define_module_under(mOSSL, "PKey");
+#endif
+
eDSAError = rb_define_class_under(mPKey, "DSAError", ePKeyError);
cDSA = rb_define_class_under(mPKey, "DSA", cPKey);
@@ -406,12 +477,8 @@ Init_ossl_dsa()
}
#else /* defined NO_DSA */
-# warning >>> OpenSSL is compiled without DSA support <<<
-
void
Init_ossl_dsa()
{
- rb_warning("OpenSSL is compiled without DSA support");
}
-
#endif /* NO_DSA */
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
new file mode 100644
index 0000000000..210054121d
--- /dev/null
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -0,0 +1,1582 @@
+/*
+ * Copyright (C) 2006-2007 Technorama Ltd. <oss-ruby@technorama.net>
+ */
+
+#include "ossl.h"
+
+#if !defined(OPENSSL_NO_EC) && (OPENSSL_VERSION_NUMBER >= 0x0090802fL)
+
+typedef struct {
+ EC_GROUP *group;
+ int dont_free;
+} ossl_ec_group;
+
+typedef struct {
+ EC_POINT *point;
+ int dont_free;
+} ossl_ec_point;
+
+
+#define EXPORT_PEM 0
+#define EXPORT_DER 1
+
+
+#define GetPKeyEC(obj, pkey) do { \
+ GetPKey(obj, pkey); \
+ if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) { \
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A EC PKEY!"); \
+ } \
+} while (0)
+
+#define SafeGet_ec_group(obj, group) do { \
+ OSSL_Check_Kind(obj, cEC_GROUP); \
+ Data_Get_Struct(obj, ossl_ec_group, group); \
+} while(0)
+
+#define Get_EC_KEY(obj, key) do { \
+ EVP_PKEY *pkey; \
+ GetPKeyEC(obj, pkey); \
+ key = pkey->pkey.ec; \
+} while(0)
+
+#define Require_EC_KEY(obj, key) do { \
+ Get_EC_KEY(obj, key); \
+ if (key == NULL) \
+ rb_raise(eECError, "EC_KEY is not initialized"); \
+} while(0)
+
+#define SafeRequire_EC_KEY(obj, key) do { \
+ OSSL_Check_Kind(obj, cEC); \
+ Require_EC_KEY(obj, key); \
+} while (0)
+
+#define Get_EC_GROUP(obj, g) do { \
+ ossl_ec_group *ec_group; \
+ Data_Get_Struct(obj, ossl_ec_group, ec_group); \
+ if (ec_group == NULL) \
+ rb_raise(eEC_GROUP, "missing ossl_ec_group structure"); \
+ g = ec_group->group; \
+} while(0)
+
+#define Require_EC_GROUP(obj, group) do { \
+ Get_EC_GROUP(obj, group); \
+ if (group == NULL) \
+ rb_raise(eEC_GROUP, "EC_GROUP is not initialized"); \
+} while(0)
+
+#define SafeRequire_EC_GROUP(obj, group) do { \
+ OSSL_Check_Kind(obj, cEC_GROUP); \
+ Require_EC_GROUP(obj, group); \
+} while(0)
+
+#define Get_EC_POINT(obj, p) do { \
+ ossl_ec_point *ec_point; \
+ Data_Get_Struct(obj, ossl_ec_point, ec_point); \
+ if (ec_point == NULL) \
+ rb_raise(eEC_POINT, "missing ossl_ec_point structure"); \
+ p = ec_point->point; \
+} while(0)
+
+#define Require_EC_POINT(obj, point) do { \
+ Get_EC_POINT(obj, point); \
+ if (point == NULL) \
+ rb_raise(eEC_POINT, "EC_POINT is not initialized"); \
+} while(0)
+
+#define SafeRequire_EC_POINT(obj, point) do { \
+ OSSL_Check_Kind(obj, cEC_POINT); \
+ Require_EC_POINT(obj, point); \
+} while(0)
+
+VALUE cEC;
+VALUE eECError;
+VALUE cEC_GROUP;
+VALUE eEC_GROUP;
+VALUE cEC_POINT;
+VALUE eEC_POINT;
+
+static ID s_GFp;
+static ID s_GFp_simple;
+static ID s_GFp_mont;
+static ID s_GFp_nist;
+static ID s_GF2m;
+static ID s_GF2m_simple;
+
+static ID ID_uncompressed;
+static ID ID_compressed;
+static ID ID_hybrid;
+
+static VALUE ec_instance(VALUE klass, EC_KEY *ec)
+{
+ EVP_PKEY *pkey;
+ VALUE obj;
+
+ if (!ec) {
+ return Qfalse;
+ }
+ if (!(pkey = EVP_PKEY_new())) {
+ return Qfalse;
+ }
+ if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
+ EVP_PKEY_free(pkey);
+ return Qfalse;
+ }
+ WrapPKey(klass, obj, pkey);
+
+ return obj;
+}
+
+VALUE ossl_ec_new(EVP_PKEY *pkey)
+{
+ VALUE obj;
+
+ if (!pkey) {
+ obj = ec_instance(cEC, EC_KEY_new());
+ } else {
+ if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) {
+ ossl_raise(rb_eTypeError, "Not a EC key!");
+ }
+ WrapPKey(cEC, obj, pkey);
+ }
+ if (obj == Qfalse) {
+ ossl_raise(eECError, NULL);
+ }
+
+ return obj;
+}
+
+
+/* call-seq:
+ * OpenSSL::PKey::EC.new()
+ * OpenSSL::PKey::EC.new(ec_key)
+ * OpenSSL::PKey::EC.new(ec_group)
+ * OpenSSL::PKey::EC.new("secp112r1")
+ * OpenSSL::PKey::EC.new(pem_string)
+ * OpenSSL::PKey::EC.new(der_string)
+ *
+ * See the OpenSSL documentation for:
+ * EC_KEY_*
+ */
+static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
+{
+ EVP_PKEY *pkey;
+ EC_KEY *ec = NULL;
+ VALUE arg, pass;
+ VALUE group = Qnil;
+
+ GetPKey(self, pkey);
+ if (pkey->pkey.ec)
+ rb_raise(eECError, "EC_KEY already initialized");
+
+ rb_scan_args(argc, argv, "02", &arg, &pass);
+
+ if (NIL_P(arg)) {
+ ec = EC_KEY_new();
+ } else {
+ if (rb_obj_is_kind_of(arg, cEC)) {
+ EC_KEY *other_ec = NULL;
+
+ SafeRequire_EC_KEY(arg, other_ec);
+ ec = EC_KEY_dup(other_ec);
+ } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
+ ec = EC_KEY_new();
+ group = arg;
+ } else {
+ BIO *in = ossl_obj2bio(arg);
+
+ ec = PEM_read_bio_ECPrivateKey(in, NULL, NULL, NULL);
+ if (!ec) {
+ BIO_reset(in);
+ ec = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, NULL);
+ }
+ if (!ec) {
+ BIO_reset(in);
+ ec = d2i_ECPrivateKey_bio(in, NULL);
+ }
+ if (!ec) {
+ BIO_reset(in);
+ ec = d2i_EC_PUBKEY_bio(in, NULL);
+ }
+
+ BIO_free(in);
+
+ if (ec == NULL) {
+ const char *name = STR2CSTR(arg);
+ int nid = OBJ_sn2nid(name);
+
+ if (nid == NID_undef)
+ ossl_raise(eECError, "unknown curve name (%s)\n", name);
+
+ if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL)
+ ossl_raise(eECError, "unable to create curve (%s)\n", name);
+
+ EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
+ EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
+ }
+ }
+ }
+
+ if (ec == NULL)
+ ossl_raise(eECError, NULL);
+
+ if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
+ EC_KEY_free(ec);
+ ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
+ }
+
+ rb_iv_set(self, "@group", Qnil);
+
+ if (!NIL_P(group))
+ rb_funcall(self, rb_intern("group="), 1, arg);
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * key.group => group
+ *
+ * Returns a constant <code>OpenSSL::EC::Group</code> that is tied to the key.
+ * Modifying the returned group can make the key invalid.
+ */
+static VALUE ossl_ec_key_get_group(VALUE self)
+{
+ VALUE group_v;
+ EC_KEY *ec;
+ ossl_ec_group *ec_group;
+ EC_GROUP *group;
+
+ Require_EC_KEY(self, ec);
+
+ group_v = rb_iv_get(self, "@group");
+ if (!NIL_P(group_v))
+ return group_v;
+
+ if ((group = (EC_GROUP *)EC_KEY_get0_group(ec)) != NULL) {
+ group_v = rb_obj_alloc(cEC_GROUP);
+ SafeGet_ec_group(group_v, ec_group);
+ ec_group->group = group;
+ ec_group->dont_free = 1;
+ rb_iv_set(group_v, "@key", self);
+ rb_iv_set(self, "@group", group_v);
+ return group_v;
+ }
+
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * key.group = group => group
+ *
+ * Returns the same object passed, not the group object associated with the key.
+ * If you wish to access the group object tied to the key call key.group after setting
+ * the group.
+ *
+ * Setting the group will immediately destroy any previously assigned group object.
+ * The group is internally copied by OpenSSL. Modifying the original group after
+ * assignment will not effect the internal key structure.
+ * (your changes may be lost). BE CAREFUL.
+ *
+ * EC_KEY_set_group calls EC_GROUP_free(key->group) then EC_GROUP_dup(), not EC_GROUP_copy.
+ * This documentation is accurate for OpenSSL 0.9.8b.
+ */
+static VALUE ossl_ec_key_set_group(VALUE self, VALUE group_v)
+{
+ VALUE old_group_v;
+ EC_KEY *ec;
+ EC_GROUP *group;
+
+ Require_EC_KEY(self, ec);
+ SafeRequire_EC_GROUP(group_v, group);
+
+ old_group_v = rb_iv_get(self, "@group");
+ if (!NIL_P(old_group_v)) {
+ ossl_ec_group *old_ec_group;
+ SafeGet_ec_group(old_group_v, old_ec_group);
+
+ old_ec_group->group = NULL;
+ old_ec_group->dont_free = 0;
+ rb_iv_set(old_group_v, "@key", Qnil);
+ }
+
+ rb_iv_set(self, "@group", Qnil);
+
+ if (EC_KEY_set_group(ec, group) != 1)
+ ossl_raise(eECError, "EC_KEY_set_group");
+
+ return group_v;
+}
+
+/*
+ * call-seq:
+ * key.private_key => OpenSSL::BN
+ *
+ * See the OpenSSL documentation for EC_KEY_get0_private_key()
+ */
+static VALUE ossl_ec_key_get_private_key(VALUE self)
+{
+ EC_KEY *ec;
+ const BIGNUM *bn;
+
+ Require_EC_KEY(self, ec);
+
+ if ((bn = EC_KEY_get0_private_key(ec)) == NULL)
+ return Qnil;
+
+ return ossl_bn_new(bn);
+}
+
+/*
+ * call-seq:
+ * key.private_key = openssl_bn
+ *
+ * See the OpenSSL documentation for EC_KEY_set_private_key()
+ */
+static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
+{
+ EC_KEY *ec;
+ BIGNUM *bn = NULL;
+
+ Require_EC_KEY(self, ec);
+ if (!NIL_P(private_key))
+ bn = GetBNPtr(private_key);
+
+ switch (EC_KEY_set_private_key(ec, bn)) {
+ case 1:
+ break;
+ case 0:
+ if (bn == NULL)
+ break;
+ default:
+ ossl_raise(eECError, "EC_KEY_set_private_key");
+ }
+
+ return private_key;
+}
+
+
+static VALUE ossl_ec_point_dup(const EC_POINT *point, VALUE group_v)
+{
+ VALUE obj;
+ const EC_GROUP *group;
+ ossl_ec_point *new_point;
+
+ obj = rb_obj_alloc(cEC_POINT);
+ Data_Get_Struct(obj, ossl_ec_point, new_point);
+
+ SafeRequire_EC_GROUP(group_v, group);
+
+ new_point->point = EC_POINT_dup(point, group);
+ if (new_point->point == NULL)
+ ossl_raise(eEC_POINT, "EC_POINT_dup");
+ rb_iv_set(obj, "@group", group_v);
+
+ return obj;
+}
+
+/*
+ * call-seq:
+ * key.public_key => OpenSSL::PKey::EC::Point
+ *
+ * See the OpenSSL documentation for EC_KEY_get0_public_key()
+ */
+static VALUE ossl_ec_key_get_public_key(VALUE self)
+{
+ EC_KEY *ec;
+ const EC_POINT *point;
+ VALUE group;
+
+ Require_EC_KEY(self, ec);
+
+ if ((point = EC_KEY_get0_public_key(ec)) == NULL)
+ return Qnil;
+
+ group = rb_funcall(self, rb_intern("group"), 0);
+ if (NIL_P(group))
+ ossl_raise(eECError, "EC_KEY_get0_get0_group (has public_key but no group???");
+
+ return ossl_ec_point_dup(point, group);
+}
+
+/*
+ * call-seq:
+ * key.public_key = ec_point
+ *
+ * See the OpenSSL documentation for EC_KEY_set_public_key()
+ */
+static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
+{
+ EC_KEY *ec;
+ EC_POINT *point = NULL;
+
+ Require_EC_KEY(self, ec);
+ if (!NIL_P(public_key))
+ SafeRequire_EC_POINT(public_key, point);
+
+ switch (EC_KEY_set_public_key(ec, point)) {
+ case 1:
+ break;
+ case 0:
+ if (point == NULL)
+ break;
+ default:
+ ossl_raise(eECError, "EC_KEY_set_public_key");
+ }
+
+ return public_key;
+}
+
+/*
+ * call-seq:
+ * key.public_key? => true or false
+ *
+ * Both public_key? and private_key? may return false at the same time unlike other PKey classes.
+ */
+static VALUE ossl_ec_key_is_public_key(VALUE self)
+{
+ EC_KEY *ec;
+
+ Require_EC_KEY(self, ec);
+
+ return (EC_KEY_get0_public_key(ec) ? Qtrue : Qfalse);
+}
+
+/*
+ * call-seq:
+ * key.private_key? => true or false
+ *
+ * Both public_key? and private_key? may return false at the same time unlike other PKey classes.
+ */
+static VALUE ossl_ec_key_is_private_key(VALUE self)
+{
+ EC_KEY *ec;
+
+ Require_EC_KEY(self, ec);
+
+ return (EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse);
+}
+
+static VALUE ossl_ec_key_to_string(VALUE self, int format)
+{
+ EC_KEY *ec;
+ BIO *out;
+ int i = -1;
+ int private = 0;
+ EVP_CIPHER *cipher = NULL;
+ char *password = NULL;
+ VALUE str;
+
+ Require_EC_KEY(self, ec);
+
+ if (EC_KEY_get0_public_key(ec) == NULL)
+ rb_raise(eECError, "can't export - no public key set");
+
+ if (EC_KEY_check_key(ec) != 1)
+ ossl_raise(eECError, "can't export - EC_KEY_check_key failed");
+
+ if (EC_KEY_get0_private_key(ec))
+ private = 1;
+
+ if (!(out = BIO_new(BIO_s_mem())))
+ ossl_raise(eECError, "BIO_new(BIO_s_mem())");
+
+ switch(format) {
+ case EXPORT_PEM:
+ if (private) {
+ if (cipher || password)
+/* BUG: finish cipher/password key export */
+ rb_notimplement();
+ i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, NULL, password);
+ } else {
+ if (cipher || password)
+ rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
+
+ i = PEM_write_bio_EC_PUBKEY(out, ec);
+ }
+
+ break;
+ case EXPORT_DER:
+ if (private) {
+ if (cipher || password)
+ rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
+
+ i = i2d_ECPrivateKey_bio(out, ec);
+ } else {
+ if (cipher || password)
+ rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
+
+ i = i2d_EC_PUBKEY_bio(out, ec);
+ }
+
+ break;
+ default:
+ BIO_free(out);
+ rb_raise(rb_eRuntimeError, "unknown format (internal error)");
+ }
+
+ if (i != 1) {
+ BIO_free(out);
+ ossl_raise(eECError, "outlen=%d", i);
+ }
+
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+/*
+ * call-seq:
+ * key.to_pem => String
+ *
+ * See the OpenSSL documentation for PEM_write_bio_ECPrivateKey()
+ */
+static VALUE ossl_ec_key_to_pem(VALUE self)
+{
+ return ossl_ec_key_to_string(self, EXPORT_PEM);
+}
+
+/*
+ * call-seq:
+ * key.to_der => String
+ *
+ * See the OpenSSL documentation for i2d_ECPrivateKey_bio()
+ */
+static VALUE ossl_ec_key_to_der(VALUE self)
+{
+ return ossl_ec_key_to_string(self, EXPORT_DER);
+}
+
+/*
+ * call-seq:
+ * key.to_text => String
+ *
+ * See the OpenSSL documentation for EC_KEY_print()
+ */
+static VALUE ossl_ec_key_to_text(VALUE self)
+{
+ EC_KEY *ec;
+ BIO *out;
+ VALUE str;
+
+ Require_EC_KEY(self, ec);
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eECError, "BIO_new(BIO_s_mem())");
+ }
+ if (!EC_KEY_print(out, ec, 0)) {
+ BIO_free(out);
+ ossl_raise(eECError, "EC_KEY_print");
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+/*
+ * call-seq:
+ * key.generate_key => self
+ *
+ * See the OpenSSL documentation for EC_KEY_generate_key()
+ */
+static VALUE ossl_ec_key_generate_key(VALUE self)
+{
+ EC_KEY *ec;
+
+ Require_EC_KEY(self, ec);
+
+ if (EC_KEY_generate_key(ec) != 1)
+ ossl_raise(eECError, "EC_KEY_generate_key");
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * key.check_key => true
+ *
+ * Raises an exception if the key is invalid.
+ *
+ * See the OpenSSL documentation for EC_KEY_check_key()
+ */
+static VALUE ossl_ec_key_check_key(VALUE self)
+{
+ EC_KEY *ec;
+
+ Require_EC_KEY(self, ec);
+
+ if (EC_KEY_check_key(ec) != 1)
+ ossl_raise(eECError, "EC_KEY_check_key");
+
+ return Qtrue;
+}
+
+/*
+ * call-seq:
+ * key.dh_compute_key(pubkey) => String
+ *
+ * See the OpenSSL documentation for ECDH_compute_key()
+ */
+static VALUE ossl_ec_key_dh_compute_key(VALUE self, VALUE pubkey)
+{
+ EC_KEY *ec;
+ EC_POINT *point;
+ int buf_len;
+ VALUE str;
+
+ Require_EC_KEY(self, ec);
+ SafeRequire_EC_POINT(pubkey, point);
+
+/* BUG: need a way to figure out the maximum string size */
+ buf_len = 1024;
+ str = rb_str_new(0, buf_len);
+/* BUG: take KDF as a block */
+ buf_len = ECDH_compute_key(RSTRING_PTR(str), buf_len, point, ec, NULL);
+ if (buf_len < 0)
+ ossl_raise(eECError, "ECDH_compute_key");
+
+ rb_str_resize(str, buf_len);
+
+ return str;
+}
+
+/* sign_setup */
+
+/*
+ * call-seq:
+ * key.dsa_sign_asn1(data) => String
+ *
+ * See the OpenSSL documentation for ECDSA_sign()
+ */
+static VALUE ossl_ec_key_dsa_sign_asn1(VALUE self, VALUE data)
+{
+ EC_KEY *ec;
+ unsigned int buf_len;
+ VALUE str;
+
+ Require_EC_KEY(self, ec);
+ StringValue(data);
+
+ if (EC_KEY_get0_private_key(ec) == NULL)
+ ossl_raise(eECError, "Private EC key needed!");
+
+ str = rb_str_new(0, ECDSA_size(ec) + 16);
+ if (ECDSA_sign(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LEN(data), (unsigned char *) RSTRING_PTR(str), &buf_len, ec) != 1)
+ ossl_raise(eECError, "ECDSA_sign");
+
+ rb_str_resize(str, buf_len);
+
+ return str;
+}
+
+/*
+ * call-seq:
+ * key.dsa_verify(data, sig) => true or false
+ *
+ * See the OpenSSL documentation for ECDSA_verify()
+ */
+static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
+{
+ EC_KEY *ec;
+
+ Require_EC_KEY(self, ec);
+ StringValue(data);
+ StringValue(sig);
+
+ switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LEN(data), (unsigned char *) RSTRING_PTR(sig), RSTRING_LEN(sig), ec)) {
+ case 1: return Qtrue;
+ case 0: return Qfalse;
+ default: break;
+ }
+
+ ossl_raise(eECError, "ECDSA_verify");
+}
+
+static void ossl_ec_group_free(ossl_ec_group *ec_group)
+{
+ if (!ec_group->dont_free && ec_group->group)
+ EC_GROUP_clear_free(ec_group->group);
+ free(ec_group);
+}
+
+static VALUE ossl_ec_group_alloc(VALUE klass)
+{
+ ossl_ec_group *ec_group;
+ VALUE obj;
+
+ obj = Data_Make_Struct(klass, ossl_ec_group, 0, ossl_ec_group_free, ec_group);
+
+ return obj;
+}
+
+/* call-seq:
+ * OpenSSL::PKey::EC::Group.new("secp112r1")
+ * OpenSSL::PKey::EC::Group.new(ec_group)
+ * OpenSSL::PKey::EC::Group.new(pem_string)
+ * OpenSSL::PKey::EC::Group.new(der_string)
+ * OpenSSL::PKey::EC::Group.new(pem_file)
+ * OpenSSL::PKey::EC::Group.new(der_file)
+ * OpenSSL::PKey::EC::Group.new(:GFp_simple)
+ * OpenSSL::PKey::EC::Group.new(:GFp_mult)
+ * OpenSSL::PKey::EC::Group.new(:GFp_nist)
+ * OpenSSL::PKey::EC::Group.new(:GF2m_simple)
+ * OpenSSL::PKey::EC::Group.new(:GFp, bignum_p, bignum_a, bignum_b)
+ * OpenSSL::PKey::EC::Group.new(:GF2m, bignum_p, bignum_a, bignum_b)
+ *
+ * See the OpenSSL documentation for EC_GROUP_*
+ */
+static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE arg1, arg2, arg3, arg4;
+ ossl_ec_group *ec_group;
+ EC_GROUP *group = NULL;
+
+ Data_Get_Struct(self, ossl_ec_group, ec_group);
+ if (ec_group->group != NULL)
+ rb_raise(rb_eRuntimeError, "EC_GROUP is already initialized");
+
+ switch (rb_scan_args(argc, argv, "13", &arg1, &arg2, &arg3, &arg4)) {
+ case 1:
+ if (SYMBOL_P(arg1)) {
+ const EC_METHOD *method = NULL;
+ ID id = SYM2ID(arg1);
+
+ if (id == s_GFp_simple) {
+ method = EC_GFp_simple_method();
+ } else if (id == s_GFp_mont) {
+ method = EC_GFp_mont_method();
+ } else if (id == s_GFp_nist) {
+ method = EC_GFp_nist_method();
+ } else if (id == s_GF2m_simple) {
+ method = EC_GF2m_simple_method();
+ }
+
+ if (method) {
+ if ((group = EC_GROUP_new(method)) == NULL)
+ ossl_raise(eEC_GROUP, "EC_GROUP_new");
+ } else {
+ rb_raise(rb_eArgError, "unknown symbol, must be :GFp_simple, :GFp_mont, :GFp_nist or :GF2m_simple");
+ }
+ } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
+ const EC_GROUP *arg1_group;
+
+ SafeRequire_EC_GROUP(arg1, arg1_group);
+ if ((group = EC_GROUP_dup(arg1_group)) == NULL)
+ ossl_raise(eEC_GROUP, "EC_GROUP_dup");
+ } else {
+ BIO *in = ossl_obj2bio(arg1);
+
+ group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
+ if (!group) {
+ BIO_reset(in);
+ group = d2i_ECPKParameters_bio(in, NULL);
+ }
+
+ BIO_free(in);
+
+ if (!group) {
+ const char *name = STR2CSTR(arg1);
+ int nid = OBJ_sn2nid(name);
+
+ if (nid == NID_undef)
+ ossl_raise(eEC_GROUP, "unknown curve name (%s)", name);
+
+ group = EC_GROUP_new_by_curve_name(nid);
+ if (group == NULL)
+ ossl_raise(eEC_GROUP, "unable to create curve (%s)", name);
+
+ EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
+ EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
+ }
+ }
+
+ break;
+ case 4:
+ if (SYMBOL_P(arg1)) {
+ ID id = SYM2ID(arg1);
+ EC_GROUP *(*new_curve)(const BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *) = NULL;
+ const BIGNUM *p = GetBNPtr(arg2);
+ const BIGNUM *a = GetBNPtr(arg3);
+ const BIGNUM *b = GetBNPtr(arg4);
+
+ if (id == s_GFp) {
+ new_curve = EC_GROUP_new_curve_GFp;
+ } else if (id == s_GF2m) {
+ new_curve = EC_GROUP_new_curve_GF2m;
+ } else {
+ rb_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m");
+ }
+
+ if ((group = new_curve(p, a, b, ossl_bn_ctx)) == NULL)
+ ossl_raise(eEC_GROUP, "EC_GROUP_new_by_GF*");
+ } else {
+ rb_raise(rb_eArgError, "unknown argument, must be :GFp or :GF2m");
+ }
+
+ break;
+ default:
+ rb_raise(rb_eArgError, "wrong number of arguments");
+ }
+
+ if (group == NULL)
+ ossl_raise(eEC_GROUP, "");
+
+ ec_group->group = group;
+
+ return self;
+}
+
+/* call-seq:
+ * group1 == group2 => true | false
+ *
+ */
+static VALUE ossl_ec_group_eql(VALUE a, VALUE b)
+{
+ EC_GROUP *group1 = NULL, *group2 = NULL;
+
+ Require_EC_GROUP(a, group1);
+ SafeRequire_EC_GROUP(b, group2);
+
+ if (EC_GROUP_cmp(group1, group2, ossl_bn_ctx) == 1)
+ return Qfalse;
+
+ return Qtrue;
+}
+
+/* call-seq:
+ * group.generator => ec_point
+ *
+ * See the OpenSSL documentation for EC_GROUP_get0_generator()
+ */
+static VALUE ossl_ec_group_get_generator(VALUE self)
+{
+ VALUE point_obj;
+ EC_GROUP *group = NULL;
+
+ Require_EC_GROUP(self, group);
+
+ point_obj = ossl_ec_point_dup(EC_GROUP_get0_generator(group), self);
+
+ return point_obj;
+}
+
+/* call-seq:
+ * group.set_generator(generator, order, cofactor) => self
+ *
+ * See the OpenSSL documentation for EC_GROUP_set_generator()
+ */
+static VALUE ossl_ec_group_set_generator(VALUE self, VALUE generator, VALUE order, VALUE cofactor)
+{
+ EC_GROUP *group = NULL;
+ const EC_POINT *point;
+ const BIGNUM *o, *co;
+
+ Require_EC_GROUP(self, group);
+ SafeRequire_EC_POINT(generator, point);
+ o = GetBNPtr(order);
+ co = GetBNPtr(cofactor);
+
+ if (EC_GROUP_set_generator(group, point, o, co) != 1)
+ ossl_raise(eEC_GROUP, "EC_GROUP_set_generator");
+
+ return self;
+}
+
+/* call-seq:
+ * group.get_order => order_bn
+ *
+ * See the OpenSSL documentation for EC_GROUP_get_order()
+ */
+static VALUE ossl_ec_group_get_order(VALUE self)
+{
+ VALUE bn_obj;
+ BIGNUM *bn;
+ EC_GROUP *group = NULL;
+
+ Require_EC_GROUP(self, group);
+
+ bn_obj = ossl_bn_new(NULL);
+ bn = GetBNPtr(bn_obj);
+
+ if (EC_GROUP_get_order(group, bn, ossl_bn_ctx) != 1)
+ ossl_raise(eEC_GROUP, "EC_GROUP_get_order");
+
+ return bn_obj;
+}
+
+/* call-seq:
+ * group.get_cofactor => cofactor_bn
+ *
+ * See the OpenSSL documentation for EC_GROUP_get_cofactor()
+ */
+static VALUE ossl_ec_group_get_cofactor(VALUE self)
+{
+ VALUE bn_obj;
+ BIGNUM *bn;
+ EC_GROUP *group = NULL;
+
+ Require_EC_GROUP(self, group);
+
+ bn_obj = ossl_bn_new(NULL);
+ bn = GetBNPtr(bn_obj);
+
+ if (EC_GROUP_get_cofactor(group, bn, ossl_bn_ctx) != 1)
+ ossl_raise(eEC_GROUP, "EC_GROUP_get_cofactor");
+
+ return bn_obj;
+}
+
+/* call-seq:
+ * group.curve_name => String
+ *
+ * See the OpenSSL documentation for EC_GROUP_get_curve_name()
+ */
+static VALUE ossl_ec_group_get_curve_name(VALUE self)
+{
+ EC_GROUP *group = NULL;
+ int nid;
+
+ Get_EC_GROUP(self, group);
+ if (group == NULL)
+ return Qnil;
+
+ nid = EC_GROUP_get_curve_name(group);
+
+/* BUG: an nid or asn1 object should be returned, maybe. */
+ return rb_str_new2(OBJ_nid2sn(nid));
+}
+
+/* call-seq:
+ * EC.builtin_curves => [[name, comment], ...]
+ *
+ * See the OpenSSL documentation for EC_builtin_curves()
+ */
+static VALUE ossl_s_builtin_curves(VALUE self)
+{
+ EC_builtin_curve *curves = NULL;
+ int n;
+ int crv_len = EC_get_builtin_curves(NULL, 0);
+ VALUE ary, ret;
+
+ curves = ALLOCA_N(EC_builtin_curve, crv_len);
+ if (curves == NULL)
+ return Qnil;
+ if (!EC_get_builtin_curves(curves, crv_len))
+ ossl_raise(rb_eRuntimeError, "EC_get_builtin_curves");
+
+ ret = rb_ary_new2(crv_len);
+
+ for (n = 0; n < crv_len; n++) {
+ const char *sname = OBJ_nid2sn(curves[n].nid);
+ const char *comment = curves[n].comment;
+
+ ary = rb_ary_new2(2);
+ rb_ary_push(ary, rb_str_new2(sname));
+ rb_ary_push(ary, comment ? rb_str_new2(comment) : Qnil);
+ rb_ary_push(ret, ary);
+ }
+
+ return ret;
+}
+
+/* call-seq:
+ * group.asn1_flag => Fixnum
+ *
+ * See the OpenSSL documentation for EC_GROUP_get_asn1_flag()
+ */
+static VALUE ossl_ec_group_get_asn1_flag(VALUE self)
+{
+ EC_GROUP *group = NULL;
+ int flag;
+
+ Require_EC_GROUP(self, group);
+
+ flag = EC_GROUP_get_asn1_flag(group);
+
+ return INT2FIX(flag);
+}
+
+/* call-seq:
+ * group.asn1_flag = Fixnum => Fixnum
+ *
+ * See the OpenSSL documentation for EC_GROUP_set_asn1_flag()
+ */
+static VALUE ossl_ec_group_set_asn1_flag(VALUE self, VALUE flag_v)
+{
+ EC_GROUP *group = NULL;
+
+ Require_EC_GROUP(self, group);
+
+ EC_GROUP_set_asn1_flag(group, NUM2INT(flag_v));
+
+ return flag_v;
+}
+
+/* call-seq:
+ * group.point_conversion_form => :uncompressed | :compressed | :hybrid
+ *
+ * See the OpenSSL documentation for EC_GROUP_get_point_conversion_form()
+ */
+static VALUE ossl_ec_group_get_point_conversion_form(VALUE self)
+{
+ EC_GROUP *group = NULL;
+ point_conversion_form_t form;
+ VALUE ret;
+
+ Require_EC_GROUP(self, group);
+
+ form = EC_GROUP_get_point_conversion_form(group);
+
+ switch (form) {
+ case POINT_CONVERSION_UNCOMPRESSED: ret = ID_uncompressed; break;
+ case POINT_CONVERSION_COMPRESSED: ret = ID_compressed; break;
+ case POINT_CONVERSION_HYBRID: ret = ID_hybrid; break;
+ default: rb_raise(eEC_GROUP, "unsupported point conversion form: %d, this module should be updated", form);
+ }
+
+ return ID2SYM(ret);
+}
+
+/* call-seq:
+ * group.point_conversion_form = form => form
+ *
+ * See the OpenSSL documentation for EC_GROUP_set_point_conversion_form()
+ */
+static VALUE ossl_ec_group_set_point_conversion_form(VALUE self, VALUE form_v)
+{
+ EC_GROUP *group = NULL;
+ point_conversion_form_t form;
+ ID form_id = SYM2ID(form_v);
+
+ Require_EC_GROUP(self, group);
+
+ if (form_id == ID_uncompressed) {
+ form = POINT_CONVERSION_UNCOMPRESSED;
+ } else if (form_id == ID_compressed) {
+ form = POINT_CONVERSION_COMPRESSED;
+ } else if (form_id == ID_hybrid) {
+ form = POINT_CONVERSION_HYBRID;
+ } else {
+ rb_raise(rb_eArgError, "form must be :compressed, :uncompressed, or :hybrid");
+ }
+
+ EC_GROUP_set_point_conversion_form(group, form);
+
+ return form_v;
+}
+
+/* call-seq:
+ * group.seed => String or nil
+ *
+ * See the OpenSSL documentation for EC_GROUP_get0_seed()
+ */
+static VALUE ossl_ec_group_get_seed(VALUE self)
+{
+ EC_GROUP *group = NULL;
+ size_t seed_len;
+
+ Require_EC_GROUP(self, group);
+
+ seed_len = EC_GROUP_get_seed_len(group);
+
+ if (seed_len == 0)
+ return Qnil;
+
+ return rb_str_new(EC_GROUP_get0_seed(group), seed_len);
+}
+
+/* call-seq:
+ * group.seed = seed => seed
+ *
+ * See the OpenSSL documentation for EC_GROUP_set_seed()
+ */
+static VALUE ossl_ec_group_set_seed(VALUE self, VALUE seed)
+{
+ EC_GROUP *group = NULL;
+
+ Require_EC_GROUP(self, group);
+ StringValue(seed);
+
+ if (EC_GROUP_set_seed(group, RSTRING_PTR(seed), RSTRING_LEN(seed)) != RSTRING_LEN(seed))
+ ossl_raise(eEC_GROUP, "EC_GROUP_set_seed");
+
+ return seed;
+}
+
+/* get/set curve GFp, GF2m */
+
+/* call-seq:
+ * group.degree => Fixnum
+ *
+ * See the OpenSSL documentation for EC_GROUP_get_degree()
+ */
+static VALUE ossl_ec_group_get_degree(VALUE self)
+{
+ EC_GROUP *group = NULL;
+
+ Require_EC_GROUP(self, group);
+
+ return INT2NUM(EC_GROUP_get_degree(group));
+}
+
+static VALUE ossl_ec_group_to_string(VALUE self, int format)
+{
+ EC_GROUP *group;
+ BIO *out;
+ int i = -1;
+ VALUE str;
+
+ Get_EC_GROUP(self, group);
+
+ if (!(out = BIO_new(BIO_s_mem())))
+ ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())");
+
+ switch(format) {
+ case EXPORT_PEM:
+ i = PEM_write_bio_ECPKParameters(out, group);
+ break;
+ case EXPORT_DER:
+ i = i2d_ECPKParameters_bio(out, group);
+ break;
+ default:
+ BIO_free(out);
+ rb_raise(rb_eRuntimeError, "unknown format (internal error)");
+ }
+
+ if (i != 1) {
+ BIO_free(out);
+ ossl_raise(eECError, NULL);
+ }
+
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+/* call-seq:
+ * group.to_pem => String
+ *
+ * See the OpenSSL documentation for PEM_write_bio_ECPKParameters()
+ */
+static VALUE ossl_ec_group_to_pem(VALUE self)
+{
+ return ossl_ec_group_to_string(self, EXPORT_PEM);
+}
+
+/* call-seq:
+ * group.to_der => String
+ *
+ * See the OpenSSL documentation for i2d_ECPKParameters_bio()
+ */
+static VALUE ossl_ec_group_to_der(VALUE self)
+{
+ return ossl_ec_group_to_string(self, EXPORT_DER);
+}
+
+/* call-seq:
+ * group.to_text => String
+ *
+ * See the OpenSSL documentation for ECPKParameters_print()
+ */
+static VALUE ossl_ec_group_to_text(VALUE self)
+{
+ EC_GROUP *group;
+ BIO *out;
+ VALUE str;
+
+ Require_EC_GROUP(self, group);
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())");
+ }
+ if (!ECPKParameters_print(out, group, 0)) {
+ BIO_free(out);
+ ossl_raise(eEC_GROUP, NULL);
+ }
+ str = ossl_membio2str(out);
+
+ return str;
+}
+
+
+static void ossl_ec_point_free(ossl_ec_point *ec_point)
+{
+ if (!ec_point->dont_free && ec_point->point)
+ EC_POINT_clear_free(ec_point->point);
+ free(ec_point);
+}
+
+static VALUE ossl_ec_point_alloc(VALUE klass)
+{
+ ossl_ec_point *ec_point;
+ VALUE obj;
+
+ obj = Data_Make_Struct(klass, ossl_ec_point, 0, ossl_ec_point_free, ec_point);
+
+ return obj;
+}
+
+/*
+ * call-seq:
+ * OpenSSL::PKey::EC::Point.new(point)
+ * OpenSSL::PKey::EC::Point.new(group)
+ * OpenSSL::PKey::EC::Point.new(group, bn)
+ *
+ * See the OpenSSL documentation for EC_POINT_*
+ */
+static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
+{
+ ossl_ec_point *ec_point;
+ EC_POINT *point = NULL;
+ VALUE arg1, arg2;
+ VALUE group_v = Qnil;
+ const EC_GROUP *group = NULL;
+
+ Data_Get_Struct(self, ossl_ec_point, ec_point);
+ if (ec_point->point)
+ rb_raise(eEC_POINT, "EC_POINT already initialized");
+
+ switch (rb_scan_args(argc, argv, "11", &arg1, &arg2)) {
+ case 1:
+ if (rb_obj_is_kind_of(arg1, cEC_POINT)) {
+ const EC_POINT *arg_point;
+
+ group_v = rb_iv_get(arg1, "@group");
+ SafeRequire_EC_GROUP(group_v, group);
+ SafeRequire_EC_POINT(arg1, arg_point);
+
+ point = EC_POINT_dup(arg_point, group);
+ } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
+ group_v = arg1;
+ SafeRequire_EC_GROUP(group_v, group);
+
+ point = EC_POINT_new(group);
+ } else {
+ rb_raise(eEC_POINT, "wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group");
+ }
+
+ break;
+ case 2:
+ if (!rb_obj_is_kind_of(arg1, cEC_GROUP))
+ rb_raise(rb_eArgError, "1st argument must be OpenSSL::PKey::EC::Group");
+ group_v = arg1;
+ SafeRequire_EC_GROUP(group_v, group);
+
+ if (rb_obj_is_kind_of(arg2, cBN)) {
+ const BIGNUM *bn = GetBNPtr(arg2);
+
+ point = EC_POINT_bn2point(group, bn, NULL, ossl_bn_ctx);
+ } else {
+ BIO *in = ossl_obj2bio(arg1);
+
+/* BUG: finish me */
+
+ BIO_free(in);
+
+ if (point == NULL) {
+ ossl_raise(eEC_POINT, "unknown type for 2nd arg");
+ }
+ }
+ break;
+ default:
+ rb_raise(rb_eArgError, "wrong number of arguments");
+ }
+
+ if (point == NULL)
+ ossl_raise(eEC_POINT, NULL);
+
+ if (NIL_P(group_v))
+ rb_raise(rb_eRuntimeError, "missing group (internal error)");
+
+ ec_point->point = point;
+
+ rb_iv_set(self, "@group", group_v);
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * point1 == point2 => true | false
+ *
+ */
+static VALUE ossl_ec_point_eql(VALUE a, VALUE b)
+{
+ EC_POINT *point1, *point2;
+ VALUE group_v1 = rb_iv_get(a, "@group");
+ VALUE group_v2 = rb_iv_get(b, "@group");
+ const EC_GROUP *group;
+
+ if (ossl_ec_group_eql(group_v1, group_v2) == Qfalse)
+ return Qfalse;
+
+ Require_EC_POINT(a, point1);
+ SafeRequire_EC_POINT(b, point2);
+ SafeRequire_EC_GROUP(group_v1, group);
+
+ if (EC_POINT_cmp(group, point1, point2, ossl_bn_ctx) == 1)
+ return Qfalse;
+
+ return Qtrue;
+}
+
+/*
+ * call-seq:
+ * point.infinity? => true | false
+ *
+ */
+static VALUE ossl_ec_point_is_at_infinity(VALUE self)
+{
+ EC_POINT *point;
+ VALUE group_v = rb_iv_get(self, "@group");
+ const EC_GROUP *group;
+
+ Require_EC_POINT(self, point);
+ SafeRequire_EC_GROUP(group_v, group);
+
+ switch (EC_POINT_is_at_infinity(group, point)) {
+ case 1: return Qtrue;
+ case 0: return Qfalse;
+ default: ossl_raise(cEC_POINT, "EC_POINT_is_at_infinity");
+ }
+}
+
+/*
+ * call-seq:
+ * point.on_curve? => true | false
+ *
+ */
+static VALUE ossl_ec_point_is_on_curve(VALUE self)
+{
+ EC_POINT *point;
+ VALUE group_v = rb_iv_get(self, "@group");
+ const EC_GROUP *group;
+
+ Require_EC_POINT(self, point);
+ SafeRequire_EC_GROUP(group_v, group);
+
+ switch (EC_POINT_is_on_curve(group, point, ossl_bn_ctx)) {
+ case 1: return Qtrue;
+ case 0: return Qfalse;
+ default: ossl_raise(cEC_POINT, "EC_POINT_is_on_curve");
+ }
+}
+
+/*
+ * call-seq:
+ * point.make_affine! => self
+ *
+ */
+static VALUE ossl_ec_point_make_affine(VALUE self)
+{
+ EC_POINT *point;
+ VALUE group_v = rb_iv_get(self, "@group");
+ const EC_GROUP *group;
+
+ Require_EC_POINT(self, point);
+ SafeRequire_EC_GROUP(group_v, group);
+
+ if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1)
+ ossl_raise(cEC_POINT, "EC_POINT_make_affine");
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * point.invert! => self
+ *
+ */
+static VALUE ossl_ec_point_invert(VALUE self)
+{
+ EC_POINT *point;
+ VALUE group_v = rb_iv_get(self, "@group");
+ const EC_GROUP *group;
+
+ Require_EC_POINT(self, point);
+ SafeRequire_EC_GROUP(group_v, group);
+
+ if (EC_POINT_invert(group, point, ossl_bn_ctx) != 1)
+ ossl_raise(cEC_POINT, "EC_POINT_invert");
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * point.set_to_infinity! => self
+ *
+ */
+static VALUE ossl_ec_point_set_to_infinity(VALUE self)
+{
+ EC_POINT *point;
+ VALUE group_v = rb_iv_get(self, "@group");
+ const EC_GROUP *group;
+
+ Require_EC_POINT(self, point);
+ SafeRequire_EC_GROUP(group_v, group);
+
+ if (EC_POINT_set_to_infinity(group, point) != 1)
+ ossl_raise(cEC_POINT, "EC_POINT_set_to_infinity");
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * point.to_bn => OpenSSL::BN
+ *
+ * See the OpenSSL documentation for EC_POINT_point2bn()
+ */
+static VALUE ossl_ec_point_to_bn(VALUE self)
+{
+ EC_POINT *point;
+ VALUE bn_obj;
+ VALUE group_v = rb_iv_get(self, "@group");
+ const EC_GROUP *group;
+ point_conversion_form_t form;
+ BIGNUM *bn;
+
+ Require_EC_POINT(self, point);
+ SafeRequire_EC_GROUP(group_v, group);
+
+ form = EC_GROUP_get_point_conversion_form(group);
+
+ bn_obj = rb_obj_alloc(cBN);
+ bn = GetBNPtr(bn_obj);
+
+ if (EC_POINT_point2bn(group, point, form, bn, ossl_bn_ctx) == NULL)
+ ossl_raise(eEC_POINT, "EC_POINT_point2bn");
+
+ return bn_obj;
+}
+
+static void no_copy(VALUE klass)
+{
+ rb_undef_method(klass, "copy");
+ rb_undef_method(klass, "clone");
+ rb_undef_method(klass, "dup");
+ rb_undef_method(klass, "initialize_copy");
+}
+
+void Init_ossl_ec()
+{
+#ifdef DONT_NEED_RDOC_WORKAROUND
+ mOSSL = rb_define_module("OpenSSL");
+ mPKey = rb_define_module_under(mOSSL, "PKey");
+#endif
+
+ eECError = rb_define_class_under(mPKey, "ECError", ePKeyError);
+
+ cEC = rb_define_class_under(mPKey, "EC", cPKey);
+ cEC_GROUP = rb_define_class_under(cEC, "Group", rb_cObject);
+ cEC_POINT = rb_define_class_under(cEC, "Point", rb_cObject);
+ eEC_GROUP = rb_define_class_under(cEC_GROUP, "Error", eOSSLError);
+ eEC_POINT = rb_define_class_under(cEC_POINT, "Error", eOSSLError);
+
+ s_GFp = rb_intern("GFp");
+ s_GF2m = rb_intern("GF2m");
+ s_GFp_simple = rb_intern("GFp_simple");
+ s_GFp_mont = rb_intern("GFp_mont");
+ s_GFp_nist = rb_intern("GFp_nist");
+ s_GF2m_simple = rb_intern("GF2m_simple");
+
+ ID_uncompressed = rb_intern("uncompressed");
+ ID_compressed = rb_intern("compressed");
+ ID_hybrid = rb_intern("hybrid");
+
+#ifdef OPENSSL_EC_NAMED_CURVE
+ rb_define_const(cEC, "NAMED_CURVE", ULONG2NUM(OPENSSL_EC_NAMED_CURVE));
+#endif
+
+ rb_define_singleton_method(cEC, "builtin_curves", ossl_s_builtin_curves, 0);
+
+ rb_define_method(cEC, "initialize", ossl_ec_key_initialize, -1);
+/* copy/dup/cmp */
+
+ rb_define_method(cEC, "group", ossl_ec_key_get_group, 0);
+ rb_define_method(cEC, "group=", ossl_ec_key_set_group, 1);
+ rb_define_method(cEC, "private_key", ossl_ec_key_get_private_key, 0);
+ rb_define_method(cEC, "private_key=", ossl_ec_key_set_private_key, 1);
+ rb_define_method(cEC, "public_key", ossl_ec_key_get_public_key, 0);
+ rb_define_method(cEC, "public_key=", ossl_ec_key_set_public_key, 1);
+ rb_define_method(cEC, "private_key?", ossl_ec_key_is_private_key, 0);
+ rb_define_method(cEC, "public_key?", ossl_ec_key_is_public_key, 0);
+/* rb_define_method(cEC, "", ossl_ec_key_get_, 0);
+ rb_define_method(cEC, "=", ossl_ec_key_set_ 1);
+ set/get enc_flags
+ set/get _conv_from
+ set/get asn1_flag (can use ruby to call self.group.asn1_flag)
+ set/get precompute_mult
+*/
+ rb_define_method(cEC, "generate_key", ossl_ec_key_generate_key, 0);
+ rb_define_method(cEC, "check_key", ossl_ec_key_check_key, 0);
+
+ rb_define_method(cEC, "dh_compute_key", ossl_ec_key_dh_compute_key, 1);
+ rb_define_method(cEC, "dsa_sign_asn1", ossl_ec_key_dsa_sign_asn1, 1);
+ rb_define_method(cEC, "dsa_verify_asn1", ossl_ec_key_dsa_verify_asn1, 2);
+/* do_sign/do_verify */
+
+ rb_define_method(cEC, "to_pem", ossl_ec_key_to_pem, 0);
+ rb_define_method(cEC, "to_der", ossl_ec_key_to_der, 0);
+ rb_define_method(cEC, "to_text", ossl_ec_key_to_text, 0);
+
+
+ rb_define_alloc_func(cEC_GROUP, ossl_ec_group_alloc);
+ rb_define_method(cEC_GROUP, "initialize", ossl_ec_group_initialize, -1);
+ rb_define_method(cEC_GROUP, "eql?", ossl_ec_group_eql, 1);
+ rb_define_alias(cEC_GROUP, "==", "eql?");
+/* copy/dup/cmp */
+
+ rb_define_method(cEC_GROUP, "generator", ossl_ec_group_get_generator, 0);
+ rb_define_method(cEC_GROUP, "set_generator", ossl_ec_group_set_generator, 3);
+ rb_define_method(cEC_GROUP, "order", ossl_ec_group_get_order, 0);
+ rb_define_method(cEC_GROUP, "cofactor", ossl_ec_group_get_cofactor, 0);
+
+ rb_define_method(cEC_GROUP, "curve_name", ossl_ec_group_get_curve_name, 0);
+/* rb_define_method(cEC_GROUP, "curve_name=", ossl_ec_group_set_curve_name, 1); */
+
+ rb_define_method(cEC_GROUP, "asn1_flag", ossl_ec_group_get_asn1_flag, 0);
+ rb_define_method(cEC_GROUP, "asn1_flag=", ossl_ec_group_set_asn1_flag, 1);
+
+ rb_define_method(cEC_GROUP, "point_conversion_form", ossl_ec_group_get_point_conversion_form, 0);
+ rb_define_method(cEC_GROUP, "point_conversion_form=", ossl_ec_group_set_point_conversion_form, 1);
+
+ rb_define_method(cEC_GROUP, "seed", ossl_ec_group_get_seed, 0);
+ rb_define_method(cEC_GROUP, "seed=", ossl_ec_group_set_seed, 1);
+
+/* get/set GFp, GF2m */
+
+ rb_define_method(cEC_GROUP, "degree", ossl_ec_group_get_degree, 0);
+
+/* check* */
+
+
+ rb_define_method(cEC_GROUP, "to_pem", ossl_ec_group_to_pem, 0);
+ rb_define_method(cEC_GROUP, "to_der", ossl_ec_group_to_der, 0);
+ rb_define_method(cEC_GROUP, "to_text", ossl_ec_group_to_text, 0);
+
+
+ rb_define_alloc_func(cEC_POINT, ossl_ec_point_alloc);
+ rb_define_method(cEC_POINT, "initialize", ossl_ec_point_initialize, -1);
+ rb_attr(cEC_POINT, rb_intern("group"), 1, 0, 0);
+ rb_define_method(cEC_POINT, "eql?", ossl_ec_point_eql, 1);
+ rb_define_alias(cEC_POINT, "==", "eql?");
+
+ rb_define_method(cEC_POINT, "infinity?", ossl_ec_point_is_at_infinity, 0);
+ rb_define_method(cEC_POINT, "on_curve?", ossl_ec_point_is_on_curve, 0);
+ rb_define_method(cEC_POINT, "make_affine!", ossl_ec_point_make_affine, 0);
+ rb_define_method(cEC_POINT, "invert!", ossl_ec_point_invert, 0);
+ rb_define_method(cEC_POINT, "set_to_infinity!", ossl_ec_point_set_to_infinity, 0);
+/* all the other methods */
+
+ rb_define_method(cEC_POINT, "to_bn", ossl_ec_point_to_bn, 0);
+
+ no_copy(cEC);
+ no_copy(cEC_GROUP);
+ no_copy(cEC_POINT);
+}
+
+#else /* defined NO_EC */
+void Init_ossl_ec()
+{
+}
+#endif /* NO_EC */
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
index 69d69c76f4..9ac69e7ded 100644
--- a/ext/openssl/ossl_pkey_rsa.c
+++ b/ext/openssl/ossl_pkey_rsa.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_pkey_rsa.c,v 1.5.2.4 2005/09/18 22:56:11 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -84,9 +84,19 @@ rsa_generate(int size, int exp)
NULL);
}
+/*
+ * call-seq:
+ * RSA.generate(size [, exponent]) -> rsa
+ *
+ * === Parameters
+ * * +size+ is an integer representing the desired key size. Keys smaller than 1024 should be considered insecure.
+ * * +exponent+ is an odd number normally 3, 17, or 65537.
+ *
+ */
static VALUE
ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass)
{
+/* why does this method exist? why can't initialize take an optional exponent? */
RSA *rsa;
VALUE size, exp;
VALUE obj;
@@ -104,6 +114,20 @@ ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass)
return obj;
}
+/*
+ * call-seq:
+ * RSA.new([size | encoded_key] [, pass]) -> rsa
+ *
+ * === Parameters
+ * * +size+ is an integer representing the desired key size.
+ * * +encoded_key+ is a string containing PEM or DER encoded key.
+ * * +pass+ is an optional string with the password to decrypt the encoded key.
+ *
+ * === Examples
+ * * RSA.new(2048) -> rsa
+ * * RSA.new(File.read("rsa.pem")) -> rsa
+ * * RSA.new(File.read("rsa.pem"), "mypassword") -> rsa
+ */
static VALUE
ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -157,6 +181,13 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/*
+ * call-seq:
+ * rsa.public? -> true
+ *
+ * The return value is always true since every private key is also a public key.
+ *
+ */
static VALUE
ossl_rsa_is_public(VALUE self)
{
@@ -164,12 +195,16 @@ ossl_rsa_is_public(VALUE self)
GetPKeyRSA(self, pkey);
/*
- * SURPRISE! :-))
- * Every key is public at the same time!
+ * This method should check for n and e. BUG.
*/
return Qtrue;
}
+/*
+ * call-seq:
+ * rsa.private? -> true | false
+ *
+ */
static VALUE
ossl_rsa_is_private(VALUE self)
{
@@ -180,6 +215,18 @@ ossl_rsa_is_private(VALUE self)
return (RSA_PRIVATE(self, pkey->pkey.rsa)) ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * rsa.to_pem([cipher, pass]) -> aString
+ *
+ * === Parameters
+ * * +cipher+ is a Cipher object.
+ * * +pass+ is a string.
+ *
+ * === Examples
+ * * rsa.to_pem -> aString
+ * * rsa.to_pem(cipher, pass) -> aString
+ */
static VALUE
ossl_rsa_export(int argc, VALUE *argv, VALUE self)
{
@@ -219,6 +266,11 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self)
return str;
}
+/*
+ * call-seq:
+ * rsa.to_der -> aString
+ *
+ */
static VALUE
ossl_rsa_to_der(VALUE self)
{
@@ -236,7 +288,7 @@ ossl_rsa_to_der(VALUE self)
if((len = i2d_func(pkey->pkey.rsa, NULL)) <= 0)
ossl_raise(eRSAError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_func(pkey->pkey.rsa, &p) < 0)
ossl_raise(eRSAError, NULL);
ossl_str_adjust(str, p);
@@ -246,6 +298,11 @@ ossl_rsa_to_der(VALUE self)
#define ossl_rsa_buf_size(pkey) (RSA_size((pkey)->pkey.rsa)+16)
+/*
+ * call-seq:
+ * rsa.public_encrypt(string [, padding]) -> aString
+ *
+ */
static VALUE
ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self)
{
@@ -258,16 +315,20 @@ ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self)
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
str = rb_str_new(0, ossl_rsa_buf_size(pkey));
- buf_len = RSA_public_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
- RSTRING(str)->ptr, pkey->pkey.rsa,
+ buf_len = RSA_public_encrypt(RSTRING_LEN(buffer), RSTRING_PTR(buffer),
+ RSTRING_PTR(str), pkey->pkey.rsa,
pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
+ rb_str_set_len(str, buf_len);
return str;
}
+/*
+ * call-seq:
+ * rsa.public_decrypt(string [, padding]) -> aString
+ *
+ */
static VALUE
ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self)
{
@@ -280,16 +341,20 @@ ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self)
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
str = rb_str_new(0, ossl_rsa_buf_size(pkey));
- buf_len = RSA_public_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
- RSTRING(str)->ptr, pkey->pkey.rsa,
+ buf_len = RSA_public_decrypt(RSTRING_LEN(buffer), RSTRING_PTR(buffer),
+ RSTRING_PTR(str), pkey->pkey.rsa,
pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
+ rb_str_set_len(str, buf_len);
return str;
}
+/*
+ * call-seq:
+ * rsa.private_encrypt(string [, padding]) -> aString
+ *
+ */
static VALUE
ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
{
@@ -305,16 +370,21 @@ ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
str = rb_str_new(0, ossl_rsa_buf_size(pkey));
- buf_len = RSA_private_encrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
- RSTRING(str)->ptr, pkey->pkey.rsa,
+ buf_len = RSA_private_encrypt(RSTRING_LEN(buffer), RSTRING_PTR(buffer),
+ RSTRING_PTR(str), pkey->pkey.rsa,
pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
+ rb_str_set_len(str, buf_len);
return str;
}
+
+/*
+ * call-seq:
+ * rsa.private_decrypt(string [, padding]) -> aString
+ *
+ */
static VALUE
ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
{
@@ -330,17 +400,19 @@ ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
StringValue(buffer);
str = rb_str_new(0, ossl_rsa_buf_size(pkey));
- buf_len = RSA_private_decrypt(RSTRING(buffer)->len, RSTRING(buffer)->ptr,
- RSTRING(str)->ptr, pkey->pkey.rsa,
+ buf_len = RSA_private_decrypt(RSTRING_LEN(buffer), RSTRING_PTR(buffer),
+ RSTRING_PTR(str), pkey->pkey.rsa,
pad);
if (buf_len < 0) ossl_raise(eRSAError, NULL);
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
+ rb_str_set_len(str, buf_len);
return str;
}
/*
+ * call-seq:
+ * rsa.params -> hash
+ *
* Stores all parameters of key to the hash
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
* Don't use :-)) (I's up to you)
@@ -368,6 +440,9 @@ ossl_rsa_get_params(VALUE self)
}
/*
+ * call-seq:
+ * rsa.to_text -> aString
+ *
* Prints all parameters of key to buffer
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
* Don't use :-)) (It's up to you)
@@ -393,6 +468,9 @@ ossl_rsa_to_text(VALUE self)
}
/*
+ * call-seq:
+ * rsa.public_key -> aRSA
+ *
* Makes new instance RSA PUBLIC_KEY from PRIVATE_KEY
*/
static VALUE
@@ -415,7 +493,6 @@ ossl_rsa_to_public_key(VALUE self)
/*
* TODO: Test me
-extern BN_CTX *ossl_bn_ctx;
static VALUE
ossl_rsa_blinding_on(VALUE self)
@@ -459,6 +536,11 @@ OSSL_PKEY_BN(rsa, iqmp);
void
Init_ossl_rsa()
{
+#if 0 /* let rdoc know about mOSSL and mPKey */
+ mOSSL = rb_define_module("OpenSSL");
+ mPKey = rb_define_module_under(mOSSL, "PKey");
+#endif
+
eRSAError = rb_define_class_under(mPKey, "RSAError", ePKeyError);
cRSA = rb_define_class_under(mPKey, "RSA", cPKey);
@@ -503,11 +585,9 @@ Init_ossl_rsa()
}
#else /* defined NO_RSA */
-# warning >>> OpenSSL is compiled without RSA support <<<
void
Init_ossl_rsa()
{
- rb_warning("OpenSSL is compiled without RSA support");
}
#endif /* NO_RSA */
diff --git a/ext/openssl/ossl_rand.c b/ext/openssl/ossl_rand.c
index ffd68966ca..ad830fbc98 100644
--- a/ext/openssl/ossl_rand.c
+++ b/ext/openssl/ossl_rand.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_rand.c,v 1.2 2003/09/17 09:05:02 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -27,84 +27,150 @@ VALUE eRandomError;
/*
* Private
*/
+
+/*
+ * call-seq:
+ * seed(str) -> str
+ *
+ */
static VALUE
ossl_rand_seed(VALUE self, VALUE str)
{
StringValue(str);
- RAND_seed(RSTRING(str)->ptr, RSTRING(str)->len);
+ RAND_seed(RSTRING_PTR(str), RSTRING_LEN(str));
return str;
}
+/*
+ * call-seq:
+ * add(str, entropy) -> self
+ *
+ */
+static VALUE
+ossl_rand_add(VALUE self, VALUE str, VALUE entropy)
+{
+ StringValue(str);
+ RAND_add(RSTRING_PTR(str), RSTRING_LEN(str), NUM2DBL(entropy));
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * load_random_file(filename) -> true
+ *
+ */
static VALUE
ossl_rand_load_file(VALUE self, VALUE filename)
{
SafeStringValue(filename);
- if(!RAND_load_file(RSTRING(filename)->ptr, -1)) {
+ if(!RAND_load_file(RSTRING_PTR(filename), -1)) {
ossl_raise(eRandomError, NULL);
}
return Qtrue;
}
+/*
+ * call-seq:
+ * write_random_file(filename) -> true
+ *
+ */
static VALUE
ossl_rand_write_file(VALUE self, VALUE filename)
{
SafeStringValue(filename);
- if (RAND_write_file(RSTRING(filename)->ptr) == -1) {
+ if (RAND_write_file(RSTRING_PTR(filename)) == -1) {
ossl_raise(eRandomError, NULL);
}
return Qtrue;
}
+/*
+ * call-seq:
+ * random_bytes(length) -> aString
+ *
+ */
static VALUE
ossl_rand_bytes(VALUE self, VALUE len)
{
VALUE str;
-
- str = rb_str_new(0, FIX2INT(len));
- if (!RAND_bytes(RSTRING(str)->ptr, FIX2INT(len))) {
+ int n = NUM2INT(len);
+
+ str = rb_str_new(0, n);
+ if (!RAND_bytes(RSTRING_PTR(str), n)) {
ossl_raise(eRandomError, NULL);
}
return str;
}
+/*
+ * call-seq:
+ * pseudo_bytes(length) -> aString
+ *
+ */
static VALUE
ossl_rand_pseudo_bytes(VALUE self, VALUE len)
{
VALUE str;
+ int n = NUM2INT(len);
- str = rb_str_new(0, FIX2INT(len));
- if (!RAND_pseudo_bytes(RSTRING(str)->ptr, FIX2INT(len))) {
+ str = rb_str_new(0, n);
+ if (!RAND_pseudo_bytes(RSTRING_PTR(str), n)) {
ossl_raise(eRandomError, NULL);
}
return str;
}
+/*
+ * call-seq:
+ * egd(filename) -> true
+ *
+ */
static VALUE
ossl_rand_egd(VALUE self, VALUE filename)
{
SafeStringValue(filename);
- if(!RAND_egd(RSTRING(filename)->ptr)) {
+ if(!RAND_egd(RSTRING_PTR(filename))) {
ossl_raise(eRandomError, NULL);
}
return Qtrue;
}
+/*
+ * call-seq:
+ * egd_bytes(filename, length) -> true
+ *
+ */
static VALUE
ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
{
+ long n = NUM2INT(len);
+
SafeStringValue(filename);
- if (!RAND_egd_bytes(RSTRING(filename)->ptr, FIX2INT(len))) {
+ if (!RAND_egd_bytes(RSTRING_PTR(filename), n)) {
ossl_raise(eRandomError, NULL);
}
return Qtrue;
}
+/*
+ * call-seq:
+ * status? => true | false
+ *
+ * Return true if the PRNG has been seeded with enough data, false otherwise.
+ */
+static VALUE
+ossl_rand_status(VALUE self)
+{
+ return RAND_status() ? Qtrue : Qfalse;
+}
+
#define DEFMETH(class, name, func, argc) \
rb_define_method(class, name, func, argc); \
rb_define_singleton_method(class, name, func, argc);
@@ -115,16 +181,22 @@ ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
void
Init_ossl_rand()
{
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+#endif
+
mRandom = rb_define_module_under(mOSSL, "Random");
eRandomError = rb_define_class_under(mRandom, "RandomError", eOSSLError);
DEFMETH(mRandom, "seed", ossl_rand_seed, 1);
+ DEFMETH(mRandom, "random_add", ossl_rand_add, 2);
DEFMETH(mRandom, "load_random_file", ossl_rand_load_file, 1);
DEFMETH(mRandom, "write_random_file", ossl_rand_write_file, 1);
DEFMETH(mRandom, "random_bytes", ossl_rand_bytes, 1);
DEFMETH(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1);
DEFMETH(mRandom, "egd", ossl_rand_egd, 1);
DEFMETH(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2);
+ DEFMETH(mRandom, "status?", ossl_rand_status, 0)
}
diff --git a/ext/openssl/ossl_rand.h b/ext/openssl/ossl_rand.h
index 4895267fb6..ce2ae0d129 100644
--- a/ext/openssl/ossl_rand.h
+++ b/ext/openssl/ossl_rand.h
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_rand.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index e4889d6d3f..01b86fec27 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -1,8 +1,9 @@
/*
- * $Id: ossl_ssl.c,v 1.13.2.11 2006/03/17 10:10:53 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2000-2002 GOTOU Yuuzou <gotoyuzo@notwork.org>
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
+ * Copyright (C) 2001-2007 Technorama Ltd. <oss-ruby@technorama.net>
* All rights reserved.
*/
/*
@@ -30,9 +31,6 @@ VALUE eSSLError;
VALUE cSSLContext;
VALUE cSSLSocket;
-/*
- * SSLContext class
- */
#define ossl_sslctx_set_cert(o,v) rb_iv_set((o),"@cert",(v))
#define ossl_sslctx_set_key(o,v) rb_iv_set((o),"@key",(v))
#define ossl_sslctx_set_client_ca(o,v) rb_iv_set((o),"@client_ca",(v))
@@ -65,11 +63,12 @@ VALUE cSSLSocket;
#define ossl_sslctx_get_tmp_dh_cb(o) rb_iv_get((o),"@tmp_dh_callback")
#define ossl_sslctx_get_sess_id_ctx(o) rb_iv_get((o),"@session_id_context")
-static char *ossl_sslctx_attrs[] = {
+static const char *ossl_sslctx_attrs[] = {
"cert", "key", "client_ca", "ca_file", "ca_path",
"timeout", "verify_mode", "verify_depth",
"verify_callback", "options", "cert_store", "extra_chain_cert",
"client_cert_cb", "tmp_dh_callback", "session_id_context",
+ "session_get_cb", "session_new_cb", "session_remove_cb",
};
#define ossl_ssl_get_io(o) rb_iv_get((o),"@io")
@@ -86,8 +85,10 @@ static char *ossl_sslctx_attrs[] = {
#define ossl_ssl_set_key(o,v) rb_iv_set((o),"@key",(v))
#define ossl_ssl_set_tmp_dh(o,v) rb_iv_set((o),"@tmp_dh",(v))
-static char *ossl_ssl_attr_readers[] = { "io", "context", };
-static char *ossl_ssl_attrs[] = { "sync_close", };
+static const char *ossl_ssl_attr_readers[] = { "io", "context", };
+static const char *ossl_ssl_attrs[] = { "sync_close", };
+
+ID ID_callback_state;
/*
* SSLContext class
@@ -141,22 +142,13 @@ ossl_sslctx_s_alloc(VALUE klass)
}
static VALUE
-ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
+ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
{
- VALUE ssl_method;
SSL_METHOD *method = NULL;
- SSL_CTX *ctx;
+ const char *s;
int i;
- char *s;
- for(i = 0; i < numberof(ossl_sslctx_attrs); i++){
- char buf[32];
- snprintf(buf, sizeof(buf), "@%s", ossl_sslctx_attrs[i]);
- rb_iv_set(self, buf, Qnil);
- }
- if (rb_scan_args(argc, argv, "01", &ssl_method) == 0){
- return self;
- }
+ SSL_CTX *ctx;
if(TYPE(ssl_method) == T_SYMBOL)
s = rb_id2name(SYM2ID(ssl_method));
else
@@ -175,6 +167,33 @@ ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
ossl_raise(eSSLError, "SSL_CTX_set_ssl_version:");
}
+ return ssl_method;
+}
+
+/*
+ * call-seq:
+ * SSLContext.new => ctx
+ * SSLContext.new(:TLSv1) => ctx
+ * SSLContext.new("SSLv23_client") => ctx
+ *
+ * You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS
+ */
+static VALUE
+ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE ssl_method;
+ int i;
+
+ for(i = 0; i < numberof(ossl_sslctx_attrs); i++){
+ char buf[32];
+ snprintf(buf, sizeof(buf), "@%s", ossl_sslctx_attrs[i]);
+ rb_iv_set(self, buf, Qnil);
+ }
+ if (rb_scan_args(argc, argv, "01", &ssl_method) == 0){
+ return self;
+ }
+ ossl_sslctx_set_ssl_version(self, ssl_method);
+
return self;
}
@@ -251,6 +270,8 @@ ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
static DH*
ossl_default_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
{
+ rb_warning("using default DH parameters.");
+
switch(keylength){
case 512:
return OSSL_DEFAULT_DH_512;
@@ -274,6 +295,143 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
}
static VALUE
+ossl_call_session_get_cb(VALUE ary)
+{
+ VALUE ssl_obj, sslctx_obj, cb, ret;
+
+ Check_Type(ary, T_ARRAY);
+ ssl_obj = rb_ary_entry(ary, 0);
+
+ sslctx_obj = rb_iv_get(ssl_obj, "@context");
+ if (NIL_P(sslctx_obj)) return Qnil;
+ cb = rb_iv_get(sslctx_obj, "@session_get_cb");
+ if (NIL_P(cb)) return Qnil;
+
+ return rb_funcall(cb, rb_intern("call"), 1, ary);
+}
+
+/* this method is currently only called for servers (in OpenSSL <= 0.9.8e) */
+static SSL_SESSION *
+ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
+{
+ VALUE ary, ssl_obj, ret_obj;
+ SSL_SESSION *sess;
+ void *ptr;
+ int state = 0;
+
+ OSSL_Debug("SSL SESSION get callback entered");
+ if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL)
+ return NULL;
+ ssl_obj = (VALUE)ptr;
+ ary = rb_ary_new2(2);
+ rb_ary_push(ary, ssl_obj);
+ rb_ary_push(ary, rb_str_new(buf, len));
+
+ ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_get_cb, ary, &state);
+ if (state) {
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
+ return NULL;
+ }
+ if (!rb_obj_is_instance_of(ret_obj, cSSLSession))
+ return NULL;
+
+ SafeGetSSLSession(ret_obj, sess);
+ *copy = 1;
+
+ return sess;
+}
+
+static VALUE
+ossl_call_session_new_cb(VALUE ary)
+{
+ VALUE ssl_obj, sslctx_obj, cb, ret;
+
+ Check_Type(ary, T_ARRAY);
+ ssl_obj = rb_ary_entry(ary, 0);
+
+ sslctx_obj = rb_iv_get(ssl_obj, "@context");
+ if (NIL_P(sslctx_obj)) return Qnil;
+ cb = rb_iv_get(sslctx_obj, "@session_new_cb");
+ if (NIL_P(cb)) return Qnil;
+
+ return rb_funcall(cb, rb_intern("call"), 1, ary);
+}
+
+/* return 1 normal. return 0 removes the session */
+static int
+ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess)
+{
+ VALUE ary, ssl_obj, sess_obj, ret_obj;
+ void *ptr;
+ int state = 0;
+
+ OSSL_Debug("SSL SESSION new callback entered");
+
+ if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL)
+ return 1;
+ ssl_obj = (VALUE)ptr;
+ sess_obj = rb_obj_alloc(cSSLSession);
+ CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION);
+ DATA_PTR(sess_obj) = sess;
+
+ ary = rb_ary_new2(2);
+ rb_ary_push(ary, ssl_obj);
+ rb_ary_push(ary, sess_obj);
+
+ ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_new_cb, ary, &state);
+ if (state) {
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
+ return 0; /* what should be returned here??? */
+ }
+
+ return RTEST(ret_obj) ? 1 : 0;
+}
+
+static VALUE
+ossl_call_session_remove_cb(VALUE ary)
+{
+ VALUE sslctx_obj, cb, ret;
+
+ Check_Type(ary, T_ARRAY);
+ sslctx_obj = rb_ary_entry(ary, 0);
+
+ cb = rb_iv_get(sslctx_obj, "@session_remove_cb");
+ if (NIL_P(cb)) return Qnil;
+
+ return rb_funcall(cb, rb_intern("call"), 1, ary);
+}
+
+static void
+ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
+{
+ VALUE ary, sslctx_obj, sess_obj, ret_obj;
+ void *ptr;
+ int state = 0;
+
+ OSSL_Debug("SSL SESSION remove callback entered");
+
+ if ((ptr = SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_ptr_idx)) == NULL)
+ return;
+ sslctx_obj = (VALUE)ptr;
+ sess_obj = rb_obj_alloc(cSSLSession);
+ CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION);
+ DATA_PTR(sess_obj) = sess;
+
+ ary = rb_ary_new2(2);
+ rb_ary_push(ary, sslctx_obj);
+ rb_ary_push(ary, sess_obj);
+
+ ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_new_cb, ary, &state);
+ if (state) {
+/*
+ the SSL_CTX is frozen, nowhere to save state.
+ there is no common accessor method to check it either.
+ rb_ivar_set(sslctx_obj, ID_callback_state, INT2NUM(state));
+*/
+ }
+}
+
+static VALUE
ossl_sslctx_add_extra_chain_cert_i(VALUE i, VALUE arg)
{
X509 *x509;
@@ -288,6 +446,14 @@ ossl_sslctx_add_extra_chain_cert_i(VALUE i, VALUE arg)
return i;
}
+/*
+ * call-seq:
+ * ctx.setup => Qtrue # first time
+ * ctx.setup => nil # thereafter
+ *
+ * This method is called automatically when a new SSLSocket is created.
+ * Normally you do not need to call this method (unless you are writing an extension in C).
+ */
static VALUE
ossl_sslctx_setup(VALUE self)
{
@@ -307,10 +473,10 @@ ossl_sslctx_setup(VALUE self)
SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
}
else{
- rb_warning("using default DH parameters.");
SSL_CTX_set_tmp_dh_callback(ctx, ossl_default_tmp_dh_callback);
}
#endif
+ SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)self);
val = ossl_sslctx_get_cert_store(self);
if(!NIL_P(val)){
@@ -327,7 +493,7 @@ ossl_sslctx_setup(VALUE self)
val = ossl_sslctx_get_extra_cert(self);
if(!NIL_P(val)){
- rb_iterate(rb_each, val, ossl_sslctx_add_extra_chain_cert_i, self);
+ rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self);
}
/* private key may be bundled in certificate file. */
@@ -352,8 +518,8 @@ ossl_sslctx_setup(VALUE self)
val = ossl_sslctx_get_client_ca(self);
if(!NIL_P(val)){
if(TYPE(val) == T_ARRAY){
- for(i = 0; i < RARRAY(val)->len; i++){
- client_ca = GetX509CertPtr(RARRAY(val)->ptr[i]);
+ for(i = 0; i < RARRAY_LEN(val); i++){
+ client_ca = GetX509CertPtr(RARRAY_PTR(val)[i]);
if (!SSL_CTX_add_client_CA(ctx, client_ca)){
/* Copies X509_NAME => FREE it. */
ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
@@ -397,12 +563,24 @@ ossl_sslctx_setup(VALUE self)
val = ossl_sslctx_get_sess_id_ctx(self);
if (!NIL_P(val)){
StringValue(val);
- if (!SSL_CTX_set_session_id_context(ctx, RSTRING(val)->ptr,
- RSTRING(val)->len)){
- ossl_raise(eSSLError, "SSL_CTX_set_session_id_context:");
+ if (!SSL_CTX_set_session_id_context(ctx, RSTRING_PTR(val),
+ RSTRING_LEN(val))){
+ ossl_raise(eSSLError, "SSL_CTX_set_session_id_context:");
}
}
+ if (RTEST(rb_iv_get(self, "@session_get_cb"))) {
+ SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb);
+ OSSL_Debug("SSL SESSION get callback added");
+ }
+ if (RTEST(rb_iv_get(self, "@session_new_cb"))) {
+ SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb);
+ OSSL_Debug("SSL SESSION new callback added");
+ }
+ if (RTEST(rb_iv_get(self, "@session_remove_cb"))) {
+ SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb);
+ OSSL_Debug("SSL SESSION remove callback added");
+ }
return Qtrue;
}
@@ -422,6 +600,10 @@ ossl_ssl_cipher_to_ary(SSL_CIPHER *cipher)
return ary;
}
+/*
+ * call-seq:
+ * ctx.ciphers => [[name, version, bits, alg_bits], ...]
+ */
static VALUE
ossl_sslctx_get_ciphers(VALUE self)
{
@@ -450,6 +632,12 @@ ossl_sslctx_get_ciphers(VALUE self)
return ary;
}
+/*
+ * call-seq:
+ * ctx.ciphers = "cipher1:cipher2:..."
+ * ctx.ciphers = [name, ...]
+ * ctx.ciphers = [[name, version, bits, alg_bits], ...]
+ */
static VALUE
ossl_sslctx_set_ciphers(VALUE self, VALUE v)
{
@@ -462,12 +650,12 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
return v;
else if (TYPE(v) == T_ARRAY) {
str = rb_str_new(0, 0);
- for (i = 0; i < RARRAY(v)->len; i++) {
+ for (i = 0; i < RARRAY_LEN(v); i++) {
elem = rb_ary_entry(v, i);
if (TYPE(elem) == T_ARRAY) elem = rb_ary_entry(elem, 0);
elem = rb_String(elem);
rb_str_append(str, elem);
- if (i < RARRAY(v)->len-1) rb_str_cat2(str, ":");
+ if (i < RARRAY_LEN(v)-1) rb_str_cat2(str, ":");
}
} else {
str = v;
@@ -479,13 +667,173 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
ossl_raise(eSSLError, "SSL_CTX is not initialized.");
return Qnil;
}
- if (!SSL_CTX_set_cipher_list(ctx, RSTRING(str)->ptr)) {
+ if (!SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(str))) {
ossl_raise(eSSLError, "SSL_CTX_set_cipher_list:");
}
return v;
}
+
+/*
+ * call-seq:
+ * ctx.session_add(session) -> true | false
+ *
+ */
+static VALUE
+ossl_sslctx_session_add(VALUE self, VALUE arg)
+{
+ SSL_CTX *ctx;
+ SSL_SESSION *sess;
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+ SafeGetSSLSession(arg, sess);
+
+ return SSL_CTX_add_session(ctx, sess) == 1 ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ * ctx.session_remove(session) -> true | false
+ *
+ */
+static VALUE
+ossl_sslctx_session_remove(VALUE self, VALUE arg)
+{
+ SSL_CTX *ctx;
+ SSL_SESSION *sess;
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+ SafeGetSSLSession(arg, sess);
+
+ return SSL_CTX_remove_session(ctx, sess) == 1 ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ * ctx.session_cache_mode -> integer
+ *
+ */
+static VALUE
+ossl_sslctx_get_session_cache_mode(VALUE self)
+{
+ SSL_CTX *ctx;
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+
+ return LONG2NUM(SSL_CTX_get_session_cache_mode(ctx));
+}
+
+/*
+ * call-seq:
+ * ctx.session_cache_mode=(integer) -> integer
+ *
+ */
+static VALUE
+ossl_sslctx_set_session_cache_mode(VALUE self, VALUE arg)
+{
+ SSL_CTX *ctx;
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+
+ SSL_CTX_set_session_cache_mode(ctx, NUM2LONG(arg));
+
+ return arg;
+}
+
+/*
+ * call-seq:
+ * ctx.session_cache_size -> integer
+ *
+ */
+static VALUE
+ossl_sslctx_get_session_cache_size(VALUE self)
+{
+ SSL_CTX *ctx;
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+
+ return LONG2NUM(SSL_CTX_sess_get_cache_size(ctx));
+}
+
+/*
+ * call-seq:
+ * ctx.session_cache_size=(integer) -> integer
+ *
+ */
+static VALUE
+ossl_sslctx_set_session_cache_size(VALUE self, VALUE arg)
+{
+ SSL_CTX *ctx;
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+
+ SSL_CTX_sess_set_cache_size(ctx, NUM2LONG(arg));
+
+ return arg;
+}
+
+/*
+ * call-seq:
+ * ctx.session_cache_stats -> Hash
+ *
+ */
+static VALUE
+ossl_sslctx_get_session_cache_stats(VALUE self)
+{
+ SSL_CTX *ctx;
+ VALUE hash;
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+
+ hash = rb_hash_new();
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_num")), LONG2NUM(SSL_CTX_sess_number(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect")), LONG2NUM(SSL_CTX_sess_connect(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect_good")), LONG2NUM(SSL_CTX_sess_connect_good(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect_renegotiate")), LONG2NUM(SSL_CTX_sess_connect_renegotiate(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept")), LONG2NUM(SSL_CTX_sess_accept(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept_good")), LONG2NUM(SSL_CTX_sess_accept_good(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept_renegotiate")), LONG2NUM(SSL_CTX_sess_accept_renegotiate(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_hits")), LONG2NUM(SSL_CTX_sess_hits(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("cb_hits")), LONG2NUM(SSL_CTX_sess_cb_hits(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_misses")), LONG2NUM(SSL_CTX_sess_misses(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_full")), LONG2NUM(SSL_CTX_sess_cache_full(ctx)));
+ rb_hash_aset(hash, ID2SYM(rb_intern("timeouts")), LONG2NUM(SSL_CTX_sess_timeouts(ctx)));
+
+ return hash;
+}
+
+
+/*
+ * call-seq:
+ * ctx.flush_sessions(time | nil) -> self
+ *
+ */
+static VALUE
+ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
+{
+ VALUE arg1;
+ SSL_CTX *ctx;
+ time_t tm = 0;
+ int cb_state;
+
+ rb_scan_args(argc, argv, "01", &arg1);
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+
+ if (NIL_P(arg1)) {
+ tm = time(0);
+ } else if (rb_obj_is_instance_of(arg1, rb_cTime)) {
+ tm = NUM2LONG(rb_funcall(arg1, rb_intern("to_i"), 0));
+ } else {
+ rb_raise(rb_eArgError, "arg must be Time or nil");
+ }
+
+ SSL_CTX_flush_sessions(ctx, tm);
+
+ return self;
+}
+
/*
* SSLSocket class
*/
@@ -511,6 +859,20 @@ ossl_ssl_s_alloc(VALUE klass)
return Data_Wrap_Struct(klass, 0, ossl_ssl_free, NULL);
}
+/*
+ * call-seq:
+ * SSLSocket.new(io) => aSSLSocket
+ * SSLSocket.new(io, ctx) => aSSLSocket
+ *
+ * === Parameters
+ * * +io+ is a real ruby IO object. Not an IO like object that responds to read/write.
+ * * +ctx+ is an OpenSSLSSL::SSLContext.
+ *
+ * The OpenSSL::Buffering module provides additional IO methods.
+ *
+ * This method will freeze the SSLContext if one is provided;
+ * however, session management is still allowed in the frozen SSLContext.
+ */
static VALUE
ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -536,7 +898,7 @@ ossl_ssl_setup(VALUE self)
VALUE io, v_ctx, cb;
SSL_CTX *ctx;
SSL *ssl;
- OpenFile *fptr;
+ rb_io_t *fptr;
Data_Get_Struct(self, SSL, ssl);
if(!ssl){
@@ -553,7 +915,7 @@ ossl_ssl_setup(VALUE self)
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
rb_io_check_writable(fptr);
- SSL_set_fd(ssl, TO_SOCKET(fileno(fptr->f)));
+ SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr)));
SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self);
cb = ossl_sslctx_get_verify_cb(v_ctx);
SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb);
@@ -567,61 +929,85 @@ ossl_ssl_setup(VALUE self)
}
#ifdef _WIN32
-#define ssl_get_error(ssl, ret) \
- (errno = WSAGetLastError(), SSL_get_error(ssl, ret))
+#define ssl_get_error(ssl, ret) (errno = WSAGetLastError(), SSL_get_error(ssl, ret))
#else
#define ssl_get_error(ssl, ret) SSL_get_error(ssl, ret)
#endif
static VALUE
-ossl_start_ssl(VALUE self, int (*func)())
+ossl_start_ssl(VALUE self, int (*func)(), const char *funcname)
{
SSL *ssl;
- OpenFile *fptr;
- int ret;
+ rb_io_t *fptr;
+ int ret, ret2;
+ VALUE cb_state;
+
+ rb_ivar_set(self, ID_callback_state, Qnil);
Data_Get_Struct(self, SSL, ssl);
GetOpenFile(ossl_ssl_get_io(self), fptr);
for(;;){
if((ret = func(ssl)) > 0) break;
- switch(ssl_get_error(ssl, ret)){
+ switch((ret2 = ssl_get_error(ssl, ret))){
case SSL_ERROR_WANT_WRITE:
- rb_io_wait_writable(fileno(fptr->f));
+ rb_io_wait_writable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_WANT_READ:
- rb_io_wait_readable(fileno(fptr->f));
+ rb_io_wait_readable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_SYSCALL:
- if (errno) rb_sys_fail(0);
+ if (errno) rb_sys_fail(funcname);
+ ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
default:
- ossl_raise(eSSLError, NULL);
+ ossl_raise(eSSLError, "%s returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
}
}
+ cb_state = rb_ivar_get(self, ID_callback_state);
+ if (!NIL_P(cb_state))
+ rb_jump_tag(NUM2INT(cb_state));
+
return self;
}
+/*
+ * call-seq:
+ * ssl.connect => self
+ */
static VALUE
ossl_ssl_connect(VALUE self)
{
ossl_ssl_setup(self);
- return ossl_start_ssl(self, SSL_connect);
+ return ossl_start_ssl(self, SSL_connect, "SSL_connect");
}
+/*
+ * call-seq:
+ * ssl.accept => self
+ */
static VALUE
ossl_ssl_accept(VALUE self)
{
ossl_ssl_setup(self);
- return ossl_start_ssl(self, SSL_accept);
+ return ossl_start_ssl(self, SSL_accept, "SSL_accept");
}
+/*
+ * call-seq:
+ * ssl.sysread(length) => string
+ * ssl.sysread(length, buffer) => buffer
+ *
+ * === Parameters
+ * * +length+ is a positive integer.
+ * * +buffer+ is a string used to store the result.
+ */
static VALUE
ossl_ssl_read(int argc, VALUE *argv, VALUE self)
{
SSL *ssl;
int ilen, nread = 0;
VALUE len, str;
- OpenFile *fptr;
+ rb_io_t *fptr;
rb_scan_args(argc, argv, "11", &len, &str);
ilen = NUM2INT(len);
@@ -637,19 +1023,19 @@ ossl_ssl_read(int argc, VALUE *argv, VALUE self)
GetOpenFile(ossl_ssl_get_io(self), fptr);
if (ssl) {
if(SSL_pending(ssl) <= 0)
- rb_thread_wait_fd(fileno(fptr->f));
+ rb_thread_wait_fd(FPTR_TO_FD(fptr));
for (;;){
- nread = SSL_read(ssl, RSTRING(str)->ptr, RSTRING(str)->len);
+ nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LEN(str));
switch(ssl_get_error(ssl, nread)){
case SSL_ERROR_NONE:
goto end;
case SSL_ERROR_ZERO_RETURN:
rb_eof_error();
case SSL_ERROR_WANT_WRITE:
- rb_io_wait_writable(fileno(fptr->f));
+ rb_io_wait_writable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_WANT_READ:
- rb_io_wait_readable(fileno(fptr->f));
+ rb_io_wait_readable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_SYSCALL:
if(ERR_peek_error() == 0 && nread == 0) rb_eof_error();
@@ -666,19 +1052,22 @@ ossl_ssl_read(int argc, VALUE *argv, VALUE self)
}
end:
- RSTRING(str)->len = nread;
- RSTRING(str)->ptr[nread] = 0;
+ rb_str_set_len(str, nread);
OBJ_TAINT(str);
return str;
}
+/*
+ * call-seq:
+ * ssl.syswrite(string) => integer
+ */
static VALUE
ossl_ssl_write(VALUE self, VALUE str)
{
SSL *ssl;
int nwrite = 0;
- OpenFile *fptr;
+ rb_io_t *fptr;
StringValue(str);
Data_Get_Struct(self, SSL, ssl);
@@ -686,15 +1075,15 @@ ossl_ssl_write(VALUE self, VALUE str)
if (ssl) {
for (;;){
- nwrite = SSL_write(ssl, RSTRING(str)->ptr, RSTRING(str)->len);
+ nwrite = SSL_write(ssl, RSTRING_PTR(str), RSTRING_LEN(str));
switch(ssl_get_error(ssl, nwrite)){
case SSL_ERROR_NONE:
goto end;
case SSL_ERROR_WANT_WRITE:
- rb_io_wait_writable(fileno(fptr->f));
+ rb_io_wait_writable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_WANT_READ:
- rb_io_wait_readable(fileno(fptr->f));
+ rb_io_wait_readable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_SYSCALL:
if (errno) rb_sys_fail(0);
@@ -713,6 +1102,10 @@ ossl_ssl_write(VALUE self, VALUE str)
return INT2NUM(nwrite);
}
+/*
+ * call-seq:
+ * ssl.sysclose => nil
+ */
static VALUE
ossl_ssl_close(VALUE self)
{
@@ -726,6 +1119,10 @@ ossl_ssl_close(VALUE self)
return Qnil;
}
+/*
+ * call-seq:
+ * ssl.cert => cert or nil
+ */
static VALUE
ossl_ssl_get_cert(VALUE self)
{
@@ -750,6 +1147,10 @@ ossl_ssl_get_cert(VALUE self)
return ossl_x509_new(cert);
}
+/*
+ * call-seq:
+ * ssl.peer_cert => cert or nil
+ */
static VALUE
ossl_ssl_get_peer_cert(VALUE self)
{
@@ -775,6 +1176,10 @@ ossl_ssl_get_peer_cert(VALUE self)
return obj;
}
+/*
+ * call-seq:
+ * ssl.peer_cert_chain => [cert, ...] or nil
+ */
static VALUE
ossl_ssl_get_peer_cert_chain(VALUE self)
{
@@ -801,6 +1206,10 @@ ossl_ssl_get_peer_cert_chain(VALUE self)
return ary;
}
+/*
+ * call-seq:
+ * ssl.cipher => [name, version, bits, alg_bits]
+ */
static VALUE
ossl_ssl_get_cipher(VALUE self)
{
@@ -817,6 +1226,10 @@ ossl_ssl_get_cipher(VALUE self)
return ossl_ssl_cipher_to_ary(cipher);
}
+/*
+ * call-seq:
+ * ssl.state => string
+ */
static VALUE
ossl_ssl_get_state(VALUE self)
{
@@ -836,6 +1249,10 @@ ossl_ssl_get_state(VALUE self)
return ret;
}
+/*
+ * call-seq:
+ * ssl.pending => integer
+ */
static VALUE
ossl_ssl_pending(VALUE self)
{
@@ -850,10 +1267,82 @@ ossl_ssl_pending(VALUE self)
return INT2NUM(SSL_pending(ssl));
}
+/*
+ * call-seq:
+ * ssl.session_reused? -> true | false
+ *
+ */
+static VALUE
+ossl_ssl_session_reused(VALUE self)
+{
+ SSL *ssl;
+
+ Data_Get_Struct(self, SSL, ssl);
+ if (!ssl) {
+ rb_warning("SSL session is not started yet.");
+ return Qnil;
+ }
+
+ switch(SSL_session_reused(ssl)) {
+ case 1: return Qtrue;
+ case 0: return Qfalse;
+ default: ossl_raise(eSSLError, "SSL_session_reused");
+ }
+}
+
+/*
+ * call-seq:
+ * ssl.session = session -> session
+ *
+ */
+static VALUE
+ossl_ssl_set_session(VALUE self, VALUE arg1)
+{
+ SSL *ssl;
+ SSL_SESSION *sess;
+
+/* why is ossl_ssl_setup delayed? */
+ ossl_ssl_setup(self);
+
+ Data_Get_Struct(self, SSL, ssl);
+ if (!ssl) {
+ rb_warning("SSL session is not started yet.");
+ return Qnil;
+ }
+
+ SafeGetSSLSession(arg1, sess);
+
+ if (SSL_set_session(ssl, sess) != 1)
+ ossl_raise(eSSLError, "SSL_set_session");
+
+ return arg1;
+}
+
+static VALUE
+ossl_ssl_get_verify_result(VALUE self)
+{
+ SSL *ssl;
+
+ Data_Get_Struct(self, SSL, ssl);
+ if (!ssl) {
+ rb_warning("SSL session is not started yet.");
+ return Qnil;
+ }
+
+ return INT2FIX(SSL_get_verify_result(ssl));
+}
+
void
Init_ossl_ssl()
{
int i;
+ VALUE ary;
+
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+#endif
+
+ ID_callback_state = rb_intern("@callback_state");
ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0,"ossl_ssl_ex_vcb_idx",0,0,0);
ossl_ssl_ex_store_p = SSL_get_ex_new_index(0,"ossl_ssl_ex_store_p",0,0,0);
@@ -866,16 +1355,60 @@ Init_ossl_ssl()
mSSL = rb_define_module_under(mOSSL, "SSL");
eSSLError = rb_define_class_under(mSSL, "SSLError", eOSSLError);
- /* class SSLContext */
+ Init_ossl_ssl_session();
+
+ /* class SSLContext
+ *
+ * The following attributes are available but don't show up in rdoc.
+ * All attributes must be set before calling SSLSocket.new(io, ctx).
+ * * ssl_version, cert, key, client_ca, ca_file, ca_path, timeout,
+ * * verify_mode, verify_depth client_cert_cb, tmp_dh_callback,
+ * * session_id_context, session_add_cb, session_new_cb, session_remove_cb
+ */
cSSLContext = rb_define_class_under(mSSL, "SSLContext", rb_cObject);
rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc);
for(i = 0; i < numberof(ossl_sslctx_attrs); i++)
rb_attr(cSSLContext, rb_intern(ossl_sslctx_attrs[i]), 1, 1, Qfalse);
+ rb_define_alias(cSSLContext, "ssl_timeout", "timeout");
rb_define_method(cSSLContext, "initialize", ossl_sslctx_initialize, -1);
+ rb_define_method(cSSLContext, "ssl_version=", ossl_sslctx_set_ssl_version, 1);
rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
- /* class SSLSocket */
+ rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
+
+
+ rb_define_const(cSSLContext, "SESSION_CACHE_OFF", LONG2FIX(SSL_SESS_CACHE_OFF));
+ rb_define_const(cSSLContext, "SESSION_CACHE_CLIENT", LONG2FIX(SSL_SESS_CACHE_CLIENT)); /* doesn't actually do anything in 0.9.8e */
+ rb_define_const(cSSLContext, "SESSION_CACHE_SERVER", LONG2FIX(SSL_SESS_CACHE_SERVER));
+ rb_define_const(cSSLContext, "SESSION_CACHE_BOTH", LONG2FIX(SSL_SESS_CACHE_BOTH)); /* no different than CACHE_SERVER in 0.9.8e */
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_AUTO_CLEAR", LONG2FIX(SSL_SESS_CACHE_NO_AUTO_CLEAR));
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_LOOKUP", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP));
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_STORE", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_STORE));
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL));
+ rb_define_method(cSSLContext, "session_add", ossl_sslctx_session_add, 1);
+ rb_define_method(cSSLContext, "session_remove", ossl_sslctx_session_remove, 1);
+ rb_define_method(cSSLContext, "session_cache_mode", ossl_sslctx_get_session_cache_mode, 0);
+ rb_define_method(cSSLContext, "session_cache_mode=", ossl_sslctx_set_session_cache_mode, 1);
+ rb_define_method(cSSLContext, "session_cache_size", ossl_sslctx_get_session_cache_size, 0);
+ rb_define_method(cSSLContext, "session_cache_size=", ossl_sslctx_set_session_cache_size, 1);
+ rb_define_method(cSSLContext, "session_cache_stats", ossl_sslctx_get_session_cache_stats, 0);
+ rb_define_method(cSSLContext, "flush_sessions", ossl_sslctx_flush_sessions, -1);
+
+ ary = rb_ary_new2(numberof(ossl_ssl_method_tab));
+ for (i = 0; i < numberof(ossl_ssl_method_tab); i++) {
+ rb_ary_push(ary, ID2SYM(rb_intern(ossl_ssl_method_tab[i].name)));
+ }
+ rb_obj_freeze(ary);
+ /* holds a list of available SSL/TLS methods */
+ rb_define_const(cSSLContext, "METHODS", ary);
+
+ /* class SSLSocket
+ *
+ * The following attributes are available but don't show up in rdoc.
+ * * io, context, sync_close
+ *
+ */
cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject);
rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc);
for(i = 0; i < numberof(ossl_ssl_attr_readers); i++)
@@ -895,6 +1428,9 @@ Init_ossl_ssl()
rb_define_method(cSSLSocket, "cipher", ossl_ssl_get_cipher, 0);
rb_define_method(cSSLSocket, "state", ossl_ssl_get_state, 0);
rb_define_method(cSSLSocket, "pending", ossl_ssl_pending, 0);
+ rb_define_method(cSSLSocket, "session_reused?", ossl_ssl_session_reused, 0);
+ rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1);
+ rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0);
#define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, INT2FIX(SSL_##x))
@@ -930,6 +1466,9 @@ Init_ossl_ssl()
ossl_ssl_def_const(OP_NO_SSLv2);
ossl_ssl_def_const(OP_NO_SSLv3);
ossl_ssl_def_const(OP_NO_TLSv1);
+#if defined(SSL_OP_NO_TICKET)
+ ossl_ssl_def_const(OP_NO_TICKET);
+#endif
ossl_ssl_def_const(OP_PKCS1_CHECK_1);
ossl_ssl_def_const(OP_PKCS1_CHECK_2);
ossl_ssl_def_const(OP_NETSCAPE_CA_DN_BUG);
diff --git a/ext/openssl/ossl_ssl.h b/ext/openssl/ossl_ssl.h
index ba9ddb1985..487f41216c 100644
--- a/ext/openssl/ossl_ssl.h
+++ b/ext/openssl/ossl_ssl.h
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_ssl.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -11,11 +11,26 @@
#if !defined(_OSSL_SSL_H_)
#define _OSSL_SSL_H_
+#define GetSSLSession(obj, sess) do { \
+ Data_Get_Struct(obj, SSL_SESSION, sess); \
+ if (!sess) { \
+ ossl_raise(rb_eRuntimeError, "SSL Session wasn't initialized."); \
+ } \
+} while (0)
+
+#define SafeGetSSLSession(obj, sess) do { \
+ OSSL_Check_Kind(obj, cSSLSession); \
+ GetSSLSession(obj, sess); \
+} while (0)
+
extern VALUE mSSL;
extern VALUE eSSLError;
extern VALUE cSSLSocket;
extern VALUE cSSLContext;
+extern VALUE cSSLSession;
void Init_ossl_ssl(void);
+void Init_ossl_ssl_session(void);
#endif /* _OSSL_SSL_H_ */
+
diff --git a/ext/openssl/ossl_ssl_session.c b/ext/openssl/ossl_ssl_session.c
new file mode 100644
index 0000000000..63c2bbb87a
--- /dev/null
+++ b/ext/openssl/ossl_ssl_session.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2004-2007 Technorama Ltd. <oss-ruby@technorama.net>
+ */
+
+#include "ossl.h"
+
+#define GetSSLSession(obj, sess) do { \
+ Data_Get_Struct(obj, SSL_SESSION, sess); \
+ if (!sess) { \
+ ossl_raise(rb_eRuntimeError, "SSL Session wasn't initialized."); \
+ } \
+} while (0)
+
+#define SafeGetSSLSession(obj, sess) do { \
+ OSSL_Check_Kind(obj, cSSLSession); \
+ GetSSLSession(obj, sess); \
+} while (0)
+
+
+VALUE cSSLSession;
+static VALUE eSSLSession;
+
+static VALUE ossl_ssl_session_alloc(VALUE klass)
+{
+ return Data_Wrap_Struct(klass, 0, SSL_SESSION_free, NULL);
+}
+
+/*
+ * call-seq:
+ * Session.new(SSLSocket | string) => session
+ *
+ * === Parameters
+ * +SSLSocket+ is an OpenSSL::SSL::SSLSocket
+ * +string+ must be a DER or PEM encoded Session.
+*/
+static VALUE ossl_ssl_session_initialize(VALUE self, VALUE arg1)
+{
+ SSL_SESSION *ctx = NULL;
+ VALUE obj;
+ unsigned char *p;
+
+ if (RDATA(self)->data)
+ ossl_raise(eSSLSession, "SSL Session already initialized");
+
+ if (rb_obj_is_instance_of(arg1, cSSLSocket)) {
+ SSL *ssl;
+
+ Data_Get_Struct(arg1, SSL, ssl);
+
+ if (!ssl || (ctx = SSL_get1_session(ssl)) == NULL)
+ ossl_raise(eSSLSession, "no session available");
+ } else {
+ BIO *in = ossl_obj2bio(arg1);
+
+ ctx = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL);
+
+ if (!ctx) {
+ BIO_reset(in);
+ ctx = d2i_SSL_SESSION_bio(in, NULL);
+ }
+
+ BIO_free(in);
+
+ if (!ctx)
+ ossl_raise(rb_eArgError, "unknown type");
+ }
+
+ /* should not happen */
+ if (ctx == NULL)
+ ossl_raise(eSSLSession, "ctx not set - internal error");
+
+ RDATA(self)->data = ctx;
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * session1 == session2 -> boolean
+ *
+*/
+static VALUE ossl_ssl_session_eq(VALUE val1, VALUE val2)
+{
+ SSL_SESSION *ctx1, *ctx2;
+
+ GetSSLSession(val1, ctx1);
+ SafeGetSSLSession(val2, ctx2);
+
+ switch (SSL_SESSION_cmp(ctx1, ctx2)) {
+ case 0: return Qtrue;
+ default: return Qfalse;
+ }
+}
+
+/*
+ * call-seq:
+ * session.time -> Time
+ *
+*/
+static VALUE ossl_ssl_session_get_time(VALUE self)
+{
+ SSL_SESSION *ctx;
+ time_t t;
+
+ GetSSLSession(self, ctx);
+
+ t = SSL_SESSION_get_time(ctx);
+
+ if (t == 0)
+ return Qnil;
+
+ return rb_funcall(rb_cTime, rb_intern("at"), 1, LONG2NUM(t));
+}
+
+/*
+ * call-seq:
+ * session.timeout -> integer
+ *
+ * How long until the session expires in seconds.
+ *
+*/
+static VALUE ossl_ssl_session_get_timeout(VALUE self)
+{
+ SSL_SESSION *ctx;
+ time_t t;
+
+ GetSSLSession(self, ctx);
+
+ t = SSL_SESSION_get_timeout(ctx);
+
+ return ULONG2NUM(t);
+}
+
+#define SSLSESSION_SET_TIME(func) \
+ static VALUE ossl_ssl_session_set_##func(VALUE self, VALUE time_v) \
+ { \
+ SSL_SESSION *ctx; \
+ time_t t; \
+ \
+ GetSSLSession(self, ctx); \
+ \
+ if (rb_obj_is_instance_of(time_v, rb_cTime)) { \
+ time_v = rb_funcall(time_v, rb_intern("to_i"), 0); \
+ } else if (FIXNUM_P(time_v)) { \
+ ; \
+ } else { \
+ rb_raise(rb_eArgError, "unknown type"); \
+ } \
+ \
+ t = NUM2ULONG(time_v); \
+ \
+ SSL_SESSION_set_##func(ctx, t); \
+ \
+ return ossl_ssl_session_get_##func(self); \
+ }
+
+SSLSESSION_SET_TIME(time)
+SSLSESSION_SET_TIME(timeout)
+
+#ifdef HAVE_SSL_SESSION_GET_ID
+/*
+ * call-seq:
+ * session.id -> aString
+ *
+ * Returns the Session ID.
+*/
+static VALUE ossl_ssl_session_get_id(VALUE self)
+{
+ SSL_SESSION *ctx;
+ const unsigned char *p = NULL;
+ unsigned int i = 0;
+
+ GetSSLSession(self, ctx);
+
+ p = SSL_SESSION_get_id(ctx, &i);
+
+ return rb_str_new((const char *) p, i);
+}
+#endif
+
+/*
+ * call-seq:
+ * session.to_der -> aString
+ *
+ * Returns an ASN1 encoded String that contains the Session object.
+*/
+static VALUE ossl_ssl_session_to_der(VALUE self)
+{
+ SSL_SESSION *ctx;
+ unsigned char buf[1024*10], *p;
+ int len;
+
+ GetSSLSession(self, ctx);
+
+ p = buf;
+ len = i2d_SSL_SESSION(ctx, &p);
+
+ if (len <= 0)
+ ossl_raise(eSSLSession, "i2d_SSL_SESSION");
+ else if (len >= sizeof(buf))
+ ossl_raise(eSSLSession, "i2d_SSL_SESSION too large");
+
+ return rb_str_new((const char *) p, len);
+}
+
+/*
+ * call-seq:
+ * session.to_pem -> String
+ *
+ * Returns a PEM encoded String that contains the Session object.
+*/
+static VALUE ossl_ssl_session_to_pem(VALUE self)
+{
+ SSL_SESSION *ctx;
+ BIO *out;
+ BUF_MEM *buf;
+ VALUE str;
+ int i;
+
+ GetSSLSession(self, ctx);
+
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eSSLSession, "BIO_s_mem()");
+ }
+
+ if (!(i=PEM_write_bio_SSL_SESSION(out, ctx))) {
+ BIO_free(out);
+ ossl_raise(eSSLSession, "SSL_SESSION_print()");
+ }
+
+ BIO_get_mem_ptr(out, &buf);
+ str = rb_str_new(buf->data, buf->length);
+ BIO_free(out);
+
+ return str;
+}
+
+
+/*
+ * call-seq:
+ * session.to_text -> String
+ *
+ * Shows everything in the Session object.
+*/
+static VALUE ossl_ssl_session_to_text(VALUE self)
+{
+ SSL_SESSION *ctx;
+ BIO *out;
+ BUF_MEM *buf;
+ VALUE str;
+
+ GetSSLSession(self, ctx);
+
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eSSLSession, "BIO_s_mem()");
+ }
+
+ if (!SSL_SESSION_print(out, ctx)) {
+ BIO_free(out);
+ ossl_raise(eSSLSession, "SSL_SESSION_print()");
+ }
+
+ BIO_get_mem_ptr(out, &buf);
+ str = rb_str_new(buf->data, buf->length);
+ BIO_free(out);
+
+ return str;
+}
+
+
+void Init_ossl_ssl_session(void)
+{
+#if 0 /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+ mSSL = rb_define_module_under(mOSSL, "SSL");
+#endif
+ cSSLSession = rb_define_class_under(mSSL, "Session", rb_cObject);
+ eSSLSession = rb_define_class_under(cSSLSession, "SessionError", eOSSLError);
+
+ rb_define_alloc_func(cSSLSession, ossl_ssl_session_alloc);
+ rb_define_method(cSSLSession, "initialize", ossl_ssl_session_initialize, 1);
+
+ rb_define_method(cSSLSession, "==", ossl_ssl_session_eq, 1);
+
+ rb_define_method(cSSLSession, "time", ossl_ssl_session_get_time, 0);
+ rb_define_method(cSSLSession, "time=", ossl_ssl_session_set_time, 1);
+ rb_define_method(cSSLSession, "timeout", ossl_ssl_session_get_timeout, 0);
+ rb_define_method(cSSLSession, "timeout=", ossl_ssl_session_set_timeout, 1);
+
+#ifdef HAVE_SSL_SESSION_GET_ID
+ rb_define_method(cSSLSession, "id", ossl_ssl_session_get_id, 0);
+#else
+ rb_undef_method(cSSLSession, "id");
+#endif
+ rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0);
+ rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0);
+ rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0);
+}
diff --git a/ext/openssl/ossl_version.h b/ext/openssl/ossl_version.h
index 6d43cdccbf..63878e0d8e 100644
--- a/ext/openssl/ossl_version.h
+++ b/ext/openssl/ossl_version.h
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_version.h,v 1.1 2003/07/23 16:11:29 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
diff --git a/ext/openssl/ossl_x509.c b/ext/openssl/ossl_x509.c
index fa90e92d11..fd1d9b6c7e 100644
--- a/ext/openssl/ossl_x509.c
+++ b/ext/openssl/ossl_x509.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_x509.c,v 1.2 2003/09/08 10:31:38 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
diff --git a/ext/openssl/ossl_x509.h b/ext/openssl/ossl_x509.h
index 8d1f77b302..1a43569073 100644
--- a/ext/openssl/ossl_x509.h
+++ b/ext/openssl/ossl_x509.h
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_x509.h,v 1.2 2003/11/01 09:24:55 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
diff --git a/ext/openssl/ossl_x509attr.c b/ext/openssl/ossl_x509attr.c
index 91a0795209..ca1c59aba9 100644
--- a/ext/openssl/ossl_x509attr.c
+++ b/ext/openssl/ossl_x509attr.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_x509attr.c,v 1.4.2.2 2004/12/15 01:54:38 matz Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -84,6 +84,10 @@ ossl_x509attr_alloc(VALUE klass)
return obj;
}
+/*
+ * call-seq:
+ * Attribute.new(oid [, value]) => attr
+ */
static VALUE
ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -95,9 +99,9 @@ ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
if(rb_scan_args(argc, argv, "11", &oid, &value) == 1){
oid = ossl_to_der_if_possible(oid);
StringValue(oid);
- p = RSTRING(oid)->ptr;
+ p = RSTRING_PTR(oid);
if(!d2i_X509_ATTRIBUTE((X509_ATTRIBUTE**)&DATA_PTR(self),
- &p, RSTRING(oid)->len)){
+ &p, RSTRING_LEN(oid))){
ossl_raise(eX509AttrError, NULL);
}
return self;
@@ -108,6 +112,10 @@ ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/*
+ * call-seq:
+ * attr.oid = string => string
+ */
static VALUE
ossl_x509attr_set_oid(VALUE self, VALUE oid)
{
@@ -125,6 +133,10 @@ ossl_x509attr_set_oid(VALUE self, VALUE oid)
return oid;
}
+/*
+ * call-seq:
+ * attr.oid => string
+ */
static VALUE
ossl_x509attr_get_oid(VALUE self)
{
@@ -156,6 +168,10 @@ ossl_x509attr_get_oid(VALUE self)
# define OSSL_X509ATTR_SET_SINGLE(attr) ((attr)->set = 0)
#endif
+/*
+ * call-seq:
+ * attr.value = asn1 => asn1
+ */
static VALUE
ossl_x509attr_set_value(VALUE self, VALUE value)
{
@@ -179,6 +195,10 @@ ossl_x509attr_set_value(VALUE self, VALUE value)
return value;
}
+/*
+ * call-seq:
+ * attr.value => asn1
+ */
static VALUE
ossl_x509attr_get_value(VALUE self)
{
@@ -192,7 +212,7 @@ ossl_x509attr_get_value(VALUE self)
if(OSSL_X509ATTR_IS_SINGLE(attr)){
length = i2d_ASN1_TYPE(attr->value.single, NULL);
str = rb_str_new(0, length);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
i2d_ASN1_TYPE(attr->value.single, &p);
ossl_str_adjust(str, p);
}
@@ -200,7 +220,7 @@ ossl_x509attr_get_value(VALUE self)
length = i2d_ASN1_SET_OF_ASN1_TYPE(attr->value.set, NULL,
i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0);
str = rb_str_new(0, length);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
i2d_ASN1_SET_OF_ASN1_TYPE(attr->value.set, &p,
i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0);
ossl_str_adjust(str, p);
@@ -210,6 +230,10 @@ ossl_x509attr_get_value(VALUE self)
return asn1;
}
+/*
+ * call-seq:
+ * attr.to_der => string
+ */
static VALUE
ossl_x509attr_to_der(VALUE self)
{
@@ -222,10 +246,10 @@ ossl_x509attr_to_der(VALUE self)
if((len = i2d_X509_ATTRIBUTE(attr, NULL)) <= 0)
ossl_raise(eX509AttrError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_X509_ATTRIBUTE(attr, &p) <= 0)
ossl_raise(eX509AttrError, NULL);
- RSTRING(str)->len = p - (unsigned char*)RSTRING(str)->ptr;
+ rb_str_set_len(str, p - (unsigned char*)RSTRING_PTR(str));
return str;
}
diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c
index 3ac9c894da..b97f27ffa9 100644
--- a/ext/openssl/ossl_x509cert.c
+++ b/ext/openssl/ossl_x509cert.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_x509cert.c,v 1.3.2.1 2004/12/15 01:54:38 matz Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -63,7 +63,7 @@ ossl_x509_new_from_file(VALUE filename)
VALUE obj;
SafeStringValue(filename);
- if (!(fp = fopen(RSTRING(filename)->ptr, "r"))) {
+ if (!(fp = fopen(RSTRING_PTR(filename), "r"))) {
ossl_raise(eX509CertError, "%s", strerror(errno));
}
x509 = PEM_read_X509(fp, NULL, NULL, NULL);
@@ -125,6 +125,11 @@ ossl_x509_alloc(VALUE klass)
return obj;
}
+/*
+ * call-seq:
+ * Certificate.new => cert
+ * Certificate.new(string) => cert
+ */
static VALUE
ossl_x509_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -169,6 +174,10 @@ ossl_x509_copy(VALUE self, VALUE other)
return self;
}
+/*
+ * call-seq:
+ * cert.to_der => string
+ */
static VALUE
ossl_x509_to_der(VALUE self)
{
@@ -181,7 +190,7 @@ ossl_x509_to_der(VALUE self)
if ((len = i2d_X509(x509, NULL)) <= 0)
ossl_raise(eX509CertError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if (i2d_X509(x509, &p) <= 0)
ossl_raise(eX509CertError, NULL);
ossl_str_adjust(str, p);
@@ -189,6 +198,10 @@ ossl_x509_to_der(VALUE self)
return str;
}
+/*
+ * call-seq:
+ * cert.to_pem => string
+ */
static VALUE
ossl_x509_to_pem(VALUE self)
{
@@ -209,6 +222,10 @@ ossl_x509_to_pem(VALUE self)
return str;
}
+/*
+ * call-seq:
+ * cert.to_text => string
+ */
static VALUE
ossl_x509_to_text(VALUE self)
{
@@ -252,6 +269,10 @@ ossl_x509_to_req(VALUE self)
}
#endif
+/*
+ * call-seq:
+ * cert.version => integer
+ */
static VALUE
ossl_x509_get_version(VALUE self)
{
@@ -262,6 +283,10 @@ ossl_x509_get_version(VALUE self)
return LONG2NUM(X509_get_version(x509));
}
+/*
+ * call-seq:
+ * cert.version = integer => integer
+ */
static VALUE
ossl_x509_set_version(VALUE self, VALUE version)
{
@@ -279,6 +304,10 @@ ossl_x509_set_version(VALUE self, VALUE version)
return version;
}
+/*
+ * call-seq:
+ * cert.serial => integer
+ */
static VALUE
ossl_x509_get_serial(VALUE self)
{
@@ -289,6 +318,10 @@ ossl_x509_get_serial(VALUE self)
return asn1integer_to_num(X509_get_serialNumber(x509));
}
+/*
+ * call-seq:
+ * cert.serial = integer => integer
+ */
static VALUE
ossl_x509_set_serial(VALUE self, VALUE num)
{
@@ -302,6 +335,10 @@ ossl_x509_set_serial(VALUE self, VALUE num)
return num;
}
+/*
+ * call-seq:
+ * cert.signature_algorithm => string
+ */
static VALUE
ossl_x509_get_signature_algorithm(VALUE self)
{
@@ -322,6 +359,10 @@ ossl_x509_get_signature_algorithm(VALUE self)
return str;
}
+/*
+ * call-seq:
+ * cert.subject => name
+ */
static VALUE
ossl_x509_get_subject(VALUE self)
{
@@ -336,6 +377,10 @@ ossl_x509_get_subject(VALUE self)
return ossl_x509name_new(name);
}
+/*
+ * call-seq:
+ * cert.subject = name => name
+ */
static VALUE
ossl_x509_set_subject(VALUE self, VALUE subject)
{
@@ -349,6 +394,10 @@ ossl_x509_set_subject(VALUE self, VALUE subject)
return subject;
}
+/*
+ * call-seq:
+ * cert.issuer => name
+ */
static VALUE
ossl_x509_get_issuer(VALUE self)
{
@@ -363,6 +412,10 @@ ossl_x509_get_issuer(VALUE self)
return ossl_x509name_new(name);
}
+/*
+ * call-seq:
+ * cert.issuer = name => name
+ */
static VALUE
ossl_x509_set_issuer(VALUE self, VALUE issuer)
{
@@ -376,6 +429,10 @@ ossl_x509_set_issuer(VALUE self, VALUE issuer)
return issuer;
}
+/*
+ * call-seq:
+ * cert.not_before => time
+ */
static VALUE
ossl_x509_get_not_before(VALUE self)
{
@@ -390,6 +447,10 @@ ossl_x509_get_not_before(VALUE self)
return asn1time_to_time(asn1time);
}
+/*
+ * call-seq:
+ * cert.not_before = time => time
+ */
static VALUE
ossl_x509_set_not_before(VALUE self, VALUE time)
{
@@ -405,6 +466,10 @@ ossl_x509_set_not_before(VALUE self, VALUE time)
return time;
}
+/*
+ * call-seq:
+ * cert.not_after => time
+ */
static VALUE
ossl_x509_get_not_after(VALUE self)
{
@@ -419,6 +484,10 @@ ossl_x509_get_not_after(VALUE self)
return asn1time_to_time(asn1time);
}
+/*
+ * call-seq:
+ * cert.not_before = time => time
+ */
static VALUE
ossl_x509_set_not_after(VALUE self, VALUE time)
{
@@ -434,6 +503,10 @@ ossl_x509_set_not_after(VALUE self, VALUE time)
return time;
}
+/*
+ * call-seq:
+ * cert.public_key => key
+ */
static VALUE
ossl_x509_get_public_key(VALUE self)
{
@@ -448,6 +521,10 @@ ossl_x509_get_public_key(VALUE self)
return ossl_pkey_new(pkey); /* NO DUP - OK */
}
+/*
+ * call-seq:
+ * cert.public_key = key => key
+ */
static VALUE
ossl_x509_set_public_key(VALUE self, VALUE key)
{
@@ -461,6 +538,10 @@ ossl_x509_set_public_key(VALUE self, VALUE key)
return key;
}
+/*
+ * call-seq:
+ * cert.sign(key, digest) => self
+ */
static VALUE
ossl_x509_sign(VALUE self, VALUE key, VALUE digest)
{
@@ -479,6 +560,9 @@ ossl_x509_sign(VALUE self, VALUE key, VALUE digest)
}
/*
+ * call-seq:
+ * cert.verify(key) => true | false
+ *
* Checks that cert signature is made with PRIVversion of this PUBLIC 'key'
*/
static VALUE
@@ -501,6 +585,9 @@ ossl_x509_verify(VALUE self, VALUE key)
}
/*
+ * call-seq:
+ * cert.check_private_key(key)
+ *
* Checks if 'key' is PRIV key for this cert
*/
static VALUE
@@ -521,7 +608,8 @@ ossl_x509_check_private_key(VALUE self, VALUE key)
}
/*
- * Gets X509v3 extensions as array of X509Ext objects
+ * call-seq:
+ * cert.extensions => [extension...]
*/
static VALUE
ossl_x509_get_extensions(VALUE self)
@@ -546,7 +634,8 @@ ossl_x509_get_extensions(VALUE self)
}
/*
- * Sets X509_EXTENSIONs
+ * call-seq:
+ * cert.extensions = [ext...] => [ext...]
*/
static VALUE
ossl_x509_set_extensions(VALUE self, VALUE ary)
@@ -557,14 +646,14 @@ ossl_x509_set_extensions(VALUE self, VALUE ary)
Check_Type(ary, T_ARRAY);
/* All ary's members should be X509Extension */
- for (i=0; i<RARRAY(ary)->len; i++) {
- OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Ext);
}
GetX509(self, x509);
sk_X509_EXTENSION_pop_free(x509->cert_info->extensions, X509_EXTENSION_free);
x509->cert_info->extensions = NULL;
- for (i=0; i<RARRAY(ary)->len; i++) {
- ext = DupX509ExtPtr(RARRAY(ary)->ptr[i]);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ ext = DupX509ExtPtr(RARRAY_PTR(ary)[i]);
if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */
X509_EXTENSION_free(ext);
@@ -576,6 +665,10 @@ ossl_x509_set_extensions(VALUE self, VALUE ary)
return ary;
}
+/*
+ * call-seq:
+ * cert.add_extension(extension) => extension
+ */
static VALUE
ossl_x509_add_extension(VALUE self, VALUE extension)
{
diff --git a/ext/openssl/ossl_x509crl.c b/ext/openssl/ossl_x509crl.c
index 62d27fe7a4..be9ddacf48 100644
--- a/ext/openssl/ossl_x509crl.c
+++ b/ext/openssl/ossl_x509crl.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_x509crl.c,v 1.3.2.1 2004/12/15 01:54:38 matz Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -287,14 +287,14 @@ ossl_x509crl_set_revoked(VALUE self, VALUE ary)
Check_Type(ary, T_ARRAY);
/* All ary members should be X509 Revoked */
- for (i=0; i<RARRAY(ary)->len; i++) {
- OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Rev);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Rev);
}
GetX509CRL(self, crl);
sk_X509_REVOKED_pop_free(crl->crl->revoked, X509_REVOKED_free);
crl->crl->revoked = NULL;
- for (i=0; i<RARRAY(ary)->len; i++) {
- rev = DupX509RevokedPtr(RARRAY(ary)->ptr[i]);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ rev = DupX509RevokedPtr(RARRAY_PTR(ary)[i]);
if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */
ossl_raise(eX509CRLError, NULL);
}
@@ -461,14 +461,14 @@ ossl_x509crl_set_extensions(VALUE self, VALUE ary)
Check_Type(ary, T_ARRAY);
/* All ary members should be X509 Extensions */
- for (i=0; i<RARRAY(ary)->len; i++) {
- OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Ext);
}
GetX509CRL(self, crl);
sk_X509_EXTENSION_pop_free(crl->crl->extensions, X509_EXTENSION_free);
crl->crl->extensions = NULL;
- for (i=0; i<RARRAY(ary)->len; i++) {
- ext = DupX509ExtPtr(RARRAY(ary)->ptr[i]);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ ext = DupX509ExtPtr(RARRAY_PTR(ary)[i]);
if(!X509_CRL_add_ext(crl, ext, -1)) { /* DUPs ext - FREE it */
X509_EXTENSION_free(ext);
ossl_raise(eX509CRLError, NULL);
diff --git a/ext/openssl/ossl_x509ext.c b/ext/openssl/ossl_x509ext.c
index 219f30d7e3..aa9366f901 100644
--- a/ext/openssl/ossl_x509ext.c
+++ b/ext/openssl/ossl_x509ext.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_x509ext.c,v 1.8.2.3 2005/11/22 22:28:51 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -229,23 +229,23 @@ ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self)
StringValue(value);
if(NIL_P(critical)) critical = Qfalse;
- nid = OBJ_ln2nid(RSTRING(oid)->ptr);
- if(!nid) nid = OBJ_sn2nid(RSTRING(oid)->ptr);
- if(!nid) ossl_raise(eX509ExtError, "unknown OID `%s'", RSTRING(oid)->ptr);
+ nid = OBJ_ln2nid(RSTRING_PTR(oid));
+ if(!nid) nid = OBJ_sn2nid(RSTRING_PTR(oid));
+ if(!nid) ossl_raise(eX509ExtError, "unknown OID `%s'", RSTRING_PTR(oid));
valstr = rb_str_new2(RTEST(critical) ? "critical," : "");
rb_str_append(valstr, value);
GetX509ExtFactory(self, ctx);
#ifdef HAVE_X509V3_EXT_NCONF_NID
rconf = rb_iv_get(self, "@config");
conf = NIL_P(rconf) ? NULL : GetConfigPtr(rconf);
- ext = X509V3_EXT_nconf_nid(conf, ctx, nid, RSTRING(valstr)->ptr);
+ ext = X509V3_EXT_nconf_nid(conf, ctx, nid, RSTRING_PTR(valstr));
#else
if (!empty_lhash) empty_lhash = lh_new(NULL, NULL);
- ext = X509V3_EXT_conf_nid(empty_lhash, ctx, nid, RSTRING(valstr)->ptr);
+ ext = X509V3_EXT_conf_nid(empty_lhash, ctx, nid, RSTRING_PTR(valstr));
#endif
if (!ext){
ossl_raise(eX509ExtError, "%s = %s",
- RSTRING(oid)->ptr, RSTRING(value)->ptr);
+ RSTRING_PTR(oid), RSTRING_PTR(value));
}
WrapX509Ext(cX509Ext, obj, ext);
@@ -280,9 +280,9 @@ ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self)
if(rb_scan_args(argc, argv, "12", &oid, &value, &critical) == 1){
oid = ossl_to_der_if_possible(oid);
StringValue(oid);
- p = RSTRING(oid)->ptr;
+ p = RSTRING_PTR(oid);
if(!d2i_X509_EXTENSION((X509_EXTENSION**)&DATA_PTR(self),
- &p, RSTRING(oid)->len))
+ &p, RSTRING_LEN(oid)))
ossl_raise(eX509ExtError, NULL);
return self;
}
@@ -319,14 +319,14 @@ ossl_x509ext_set_value(VALUE self, VALUE data)
data = ossl_to_der_if_possible(data);
StringValue(data);
- if(!(s = OPENSSL_malloc(RSTRING(data)->len)))
+ if(!(s = OPENSSL_malloc(RSTRING_LEN(data))))
ossl_raise(eX509ExtError, "malloc error");
- memcpy(s, RSTRING(data)->ptr, RSTRING(data)->len);
+ memcpy(s, RSTRING_PTR(data), RSTRING_LEN(data));
if(!(asn1s = ASN1_OCTET_STRING_new())){
free(s);
ossl_raise(eX509ExtError, NULL);
}
- if(!M_ASN1_OCTET_STRING_set(asn1s, s, RSTRING(data)->len)){
+ if(!M_ASN1_OCTET_STRING_set(asn1s, s, RSTRING_LEN(data))){
free(s);
ASN1_OCTET_STRING_free(asn1s);
ossl_raise(eX509ExtError, NULL);
@@ -409,7 +409,7 @@ ossl_x509ext_to_der(VALUE obj)
if((len = i2d_X509_EXTENSION(ext, NULL)) <= 0)
ossl_raise(eX509ExtError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_X509_EXTENSION(ext, &p) < 0)
ossl_raise(eX509ExtError, NULL);
ossl_str_adjust(str, p);
diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c
index 5c7e6e89a2..b4434d2a34 100644
--- a/ext/openssl/ossl_x509name.c
+++ b/ext/openssl/ossl_x509name.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_x509name.c,v 1.4.2.8 2004/12/27 07:55:56 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -109,6 +109,13 @@ ossl_x509name_init_i(VALUE i, VALUE args)
return Qnil;
}
+/*
+ * call-seq:
+ * X509::Name.new => name
+ * X509::Name.new(string) => name
+ * X509::Name.new(dn) => name
+ * X509::Name.new(dn, template) => name
+ */
static VALUE
ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -125,14 +132,14 @@ ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
VALUE args;
if(NIL_P(template)) template = OBJECT_TYPE_TEMPLATE;
args = rb_ary_new3(2, self, template);
- rb_iterate(rb_each, tmp, ossl_x509name_init_i, args);
+ rb_block_call(tmp, rb_intern("each"), 0, 0, ossl_x509name_init_i, args);
}
else{
unsigned char *p;
VALUE str = ossl_to_der_if_possible(arg);
StringValue(str);
- p = RSTRING(str)->ptr;
- if(!d2i_X509_NAME((X509_NAME**)&DATA_PTR(self), &p, RSTRING(str)->len)){
+ p = RSTRING_PTR(str);
+ if(!d2i_X509_NAME((X509_NAME**)&DATA_PTR(self), &p, RSTRING_LEN(str))){
ossl_raise(eX509NameError, NULL);
}
}
@@ -141,6 +148,10 @@ ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/*
+ * call-seq:
+ * name.add_entry(oid, value [, type]) => self
+ */
static
VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self)
{
@@ -152,8 +163,8 @@ VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self)
StringValue(value);
if(NIL_P(type)) type = rb_aref(OBJECT_TYPE_TEMPLATE, oid);
GetX509Name(self, name);
- if (!X509_NAME_add_entry_by_txt(name, RSTRING(oid)->ptr, NUM2INT(type),
- RSTRING(value)->ptr, RSTRING(value)->len, -1, 0)) {
+ if (!X509_NAME_add_entry_by_txt(name, RSTRING_PTR(oid), NUM2INT(type),
+ RSTRING_PTR(value), RSTRING_LEN(value), -1, 0)) {
ossl_raise(eX509NameError, NULL);
}
@@ -175,9 +186,14 @@ ossl_x509name_to_s_old(VALUE self)
return str;
}
+/*
+ * call-seq:
+ * name.to_s => string
+ * name.to_s(integer) => string
+ */
static VALUE
ossl_x509name_to_s(int argc, VALUE *argv, VALUE self)
-{
+{
X509_NAME *name;
VALUE flag, str;
BIO *out;
@@ -188,17 +204,21 @@ ossl_x509name_to_s(int argc, VALUE *argv, VALUE self)
return ossl_x509name_to_s_old(self);
else iflag = NUM2ULONG(flag);
if (!(out = BIO_new(BIO_s_mem())))
- rb_raise(eX509NameError, NULL);
+ ossl_raise(eX509NameError, NULL);
GetX509Name(self, name);
if (!X509_NAME_print_ex(out, name, 0, iflag)){
BIO_free(out);
- rb_raise(eX509NameError, NULL);
+ ossl_raise(eX509NameError, NULL);
}
str = ossl_membio2str(out);
return str;
}
+/*
+ * call-seq:
+ * name.to_a => [[name, data, type], ...]
+ */
static VALUE
ossl_x509name_to_a(VALUE self)
{
@@ -266,6 +286,10 @@ ossl_x509name_eql(VALUE self, VALUE other)
return (result == 0) ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * name.hash => integer
+ */
static VALUE
ossl_x509name_hash(VALUE self)
{
@@ -279,6 +303,10 @@ ossl_x509name_hash(VALUE self)
return ULONG2NUM(hash);
}
+/*
+ * call-seq:
+ * name.to_der => string
+ */
static VALUE
ossl_x509name_to_der(VALUE self)
{
@@ -291,7 +319,7 @@ ossl_x509name_to_der(VALUE self)
if((len = i2d_X509_NAME(name, NULL)) <= 0)
ossl_raise(eX509NameError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_X509_NAME(name, &p) <= 0)
ossl_raise(eX509NameError, NULL);
ossl_str_adjust(str, p);
diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c
index c1b1a3e619..13a42dddaf 100644
--- a/ext/openssl/ossl_x509req.c
+++ b/ext/openssl/ossl_x509req.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_x509req.c,v 1.5.2.2 2005/09/10 00:54:29 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -171,7 +171,7 @@ ossl_x509req_to_der(VALUE self)
if ((len = i2d_X509_REQ(req, NULL)) <= 0)
ossl_raise(eX509CertError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if (i2d_X509_REQ(req, &p) <= 0)
ossl_raise(eX509ReqError, NULL);
ossl_str_adjust(str, p);
@@ -403,14 +403,14 @@ ossl_x509req_set_attributes(VALUE self, VALUE ary)
VALUE item;
Check_Type(ary, T_ARRAY);
- for (i=0;i<RARRAY(ary)->len; i++) {
- OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Attr);
+ for (i=0;i<RARRAY_LEN(ary); i++) {
+ OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Attr);
}
GetX509Req(self, req);
sk_X509_ATTRIBUTE_pop_free(req->req_info->attributes, X509_ATTRIBUTE_free);
req->req_info->attributes = NULL;
- for (i=0;i<RARRAY(ary)->len; i++) {
- item = RARRAY(ary)->ptr[i];
+ for (i=0;i<RARRAY_LEN(ary); i++) {
+ item = RARRAY_PTR(ary)[i];
attr = DupX509AttrPtr(item);
if (!X509_REQ_add1_attr(req, attr)) {
ossl_raise(eX509ReqError, NULL);
diff --git a/ext/openssl/ossl_x509revoked.c b/ext/openssl/ossl_x509revoked.c
index a0f2f00aa5..d0f816bad4 100644
--- a/ext/openssl/ossl_x509revoked.c
+++ b/ext/openssl/ossl_x509revoked.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_x509revoked.c,v 1.2.2.1 2004/12/15 01:54:38 matz Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -175,14 +175,14 @@ ossl_x509revoked_set_extensions(VALUE self, VALUE ary)
VALUE item;
Check_Type(ary, T_ARRAY);
- for (i=0; i<RARRAY(ary)->len; i++) {
- OSSL_Check_Kind(RARRAY(ary)->ptr[i], cX509Ext);
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Ext);
}
GetX509Rev(self, rev);
sk_X509_EXTENSION_pop_free(rev->extensions, X509_EXTENSION_free);
rev->extensions = NULL;
- for (i=0; i<RARRAY(ary)->len; i++) {
- item = RARRAY(ary)->ptr[i];
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ item = RARRAY_PTR(ary)[i];
ext = DupX509ExtPtr(item);
if(!X509_REVOKED_add_ext(rev, ext, -1)) {
ossl_raise(eX509RevError, NULL);
diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c
index 360769e612..769ce8a91a 100644
--- a/ext/openssl/ossl_x509store.c
+++ b/ext/openssl/ossl_x509store.c
@@ -1,5 +1,5 @@
/*
- * $Id: ossl_x509store.c,v 1.2.2.5 2005/09/10 00:54:29 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -118,11 +118,18 @@ ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
return cb;
}
+
+/*
+ * call-seq:
+ * X509::Store.new => store
+ *
+ */
static VALUE
ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
{
X509_STORE *store;
+/* BUG: This method takes any number of arguments but appears to ignore them. */
GetX509Store(self, store);
X509_STORE_set_verify_cb_func(store, ossl_verify_cb);
ossl_x509store_set_vfy_cb(self, Qnil);
@@ -206,7 +213,7 @@ ossl_x509store_add_file(VALUE self, VALUE file)
if(file != Qnil){
Check_SafeStr(file);
- path = RSTRING(file)->ptr;
+ path = RSTRING_PTR(file);
}
GetX509Store(self, store);
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
@@ -227,7 +234,7 @@ ossl_x509store_add_path(VALUE self, VALUE dir)
if(dir != Qnil){
Check_SafeStr(dir);
- path = RSTRING(dir)->ptr;
+ path = RSTRING_PTR(dir);
}
GetX509Store(self, store);
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
@@ -451,7 +458,7 @@ ossl_x509stctx_set_error(VALUE self, VALUE err)
X509_STORE_CTX *ctx;
GetX509StCtx(self, ctx);
- X509_STORE_CTX_set_error(ctx, FIX2INT(err));
+ X509_STORE_CTX_set_error(ctx, NUM2INT(err));
return err;
}
@@ -550,6 +557,10 @@ ossl_x509stctx_set_trust(VALUE self, VALUE trust)
return trust;
}
+/*
+ * call-seq:
+ * storectx.time = time => time
+ */
static VALUE
ossl_x509stctx_set_time(VALUE self, VALUE time)
{
diff --git a/ext/openssl/ruby_missing.h b/ext/openssl/ruby_missing.h
index f673bb157a..64b76f26b4 100644
--- a/ext/openssl/ruby_missing.h
+++ b/ext/openssl/ruby_missing.h
@@ -1,5 +1,5 @@
/*
- * $Id: ruby_missing.h,v 1.3 2003/09/06 08:56:57 gotoyuzo Exp $
+ * $Id$
* 'OpenSSL for Ruby' project
* Copyright (C) 2001-2003 Michal Rokos <m.rokos@sh.cvut.cz>
* All rights reserved.
@@ -9,10 +9,33 @@
* (See the file 'LICENCE'.)
*/
#if !defined(_OSSL_RUBY_MISSING_H_)
-#define _OSS_RUBY_MISSING_H_
+#define _OSSL_RUBY_MISSING_H_
#define rb_define_copy_func(klass, func) \
rb_define_method(klass, "initialize_copy", func, 1)
-#endif /* _OSS_RUBY_MISSING_H_ */
+#ifndef GetReadFile
+#define FPTR_TO_FD(fptr) (fptr->fd)
+#else
+#define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr)))
+#endif
+
+#ifndef HAVE_RB_IO_T
+#define rb_io_t OpenFile
+#endif
+
+#ifndef HAVE_RB_STR_SET_LEN
+/* these methods should probably be backported to 1.8 */
+#define rb_str_set_len(str, length) do { \
+ RSTRING(str)->ptr[length] = 0; \
+ RSTRING(str)->len = length; \
+} while(0)
+#endif /* ! HAVE_RB_STR_SET_LEN */
+
+#ifndef HAVE_RB_BLOCK_CALL
+/* the openssl module doesn't use arg[3-4] and arg2 is always rb_each */
+#define rb_block_call(arg1, arg2, arg3, arg4, arg5, arg6) rb_iterate(rb_each, arg1, arg5, arg6)
+#endif /* ! HAVE_RB_BLOCK_CALL */
+
+#endif /* _OSSL_RUBY_MISSING_H_ */
diff --git a/ext/pty/expect_sample.rb b/ext/pty/expect_sample.rb
index bf8a2352fe..2a2e29f866 100644
--- a/ext/pty/expect_sample.rb
+++ b/ext/pty/expect_sample.rb
@@ -15,10 +15,6 @@ PTY.spawn("ftp ftp.ruby-lang.org") do |r_f,w_f,pid|
$expect_verbose = false
- r_f.expect(/^Name.*: /) do
- w_f.print "ftp\n"
- end
-
if !ENV['USER'].nil?
username = ENV['USER']
elsif !ENV['LOGNAME'].nil?
@@ -27,19 +23,16 @@ PTY.spawn("ftp ftp.ruby-lang.org") do |r_f,w_f,pid|
username = 'guest'
end
- r_f.expect('word:') do
- w_f.print username+"@\n"
- end
- r_f.expect("> ") do
- w_f.print "cd pub/ruby\n"
+ r_f.expect(/^(Name).*: |(word):|> /) do
+ w_f.puts($1 ? "ftp" : $2 ? "#{username}@" : "cd pub/ruby")
end
r_f.expect("> ") do
w_f.print "dir\n"
end
- r_f.expect("> ") do |output|
+ r_f.expect(/[^\-]> /) do |output|
for x in output[0].split("\n")
- if x =~ /(ruby.*\.tar\.gz)/ then
+ if x =~ /(ruby.*?\.tar\.gz)/ then
fnames.push $1
end
end
diff --git a/ext/pty/lib/expect.rb b/ext/pty/lib/expect.rb
index aa9ab895d3..08191b05b9 100644
--- a/ext/pty/lib/expect.rb
+++ b/ext/pty/lib/expect.rb
@@ -10,7 +10,7 @@ class IO
e_pat = pat
end
while true
- if IO.select([self],nil,nil,timeout).nil? then
+ if !IO.select([self],nil,nil,timeout) or eof? then
result = nil
break
end
diff --git a/ext/pty/pty.c b/ext/pty/pty.c
index 626898ae76..939335242f 100644
--- a/ext/pty/pty.c
+++ b/ext/pty/pty.c
@@ -39,10 +39,10 @@
#if !defined(HAVE_OPENPTY)
#if defined(__hpux)
-static
-char *MasterDevice = "/dev/ptym/pty%s",
- *SlaveDevice = "/dev/pty/tty%s",
- *deviceNo[] = {
+static const
+char MasterDevice[] = "/dev/ptym/pty%s",
+ SlaveDevice[] = "/dev/pty/tty%s",
+ *const deviceNo[] = {
"p0","p1","p2","p3","p4","p5","p6","p7",
"p8","p9","pa","pb","pc","pd","pe","pf",
"q0","q1","q2","q3","q4","q5","q6","q7",
@@ -62,10 +62,10 @@ char *MasterDevice = "/dev/ptym/pty%s",
0,
};
#elif defined(_IBMESA) /* AIX/ESA */
-static
-char *MasterDevice = "/dev/ptyp%s",
- *SlaveDevice = "/dev/ttyp%s",
- *deviceNo[] = {
+static const
+char MasterDevice[] = "/dev/ptyp%s",
+ SlaveDevice[] = "/dev/ttyp%s",
+ *const deviceNo[] = {
"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f",
"10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f",
"20","21","22","23","24","25","26","27","28","29","2a","2b","2c","2d","2e","2f",
@@ -84,10 +84,10 @@ char *MasterDevice = "/dev/ptyp%s",
"f0","f1","f2","f3","f4","f5","f6","f7","f8","f9","fa","fb","fc","fd","fe","ff",
};
#elif !defined(HAVE_PTSNAME)
-static
-char *MasterDevice = "/dev/pty%s",
- *SlaveDevice = "/dev/tty%s",
- *deviceNo[] = {
+static const
+char MasterDevice[] = "/dev/pty%s",
+ SlaveDevice[] = "/dev/tty%s",
+ *const deviceNo[] = {
"p0","p1","p2","p3","p4","p5","p6","p7",
"p8","p9","pa","pb","pc","pd","pe","pf",
"q0","q1","q2","q3","q4","q5","q6","q7",
@@ -101,8 +101,6 @@ char *MasterDevice = "/dev/pty%s",
#endif
#endif /* !defined(HAVE_OPENPTY) */
-static char SlaveName[DEVICELEN];
-
#ifndef HAVE_SETEUID
# ifdef HAVE_SETREUID
# define seteuid(e) setreuid(-1, (e))
@@ -139,7 +137,7 @@ raise_from_wait(state, info)
char buf[1024];
VALUE exc;
- snprintf(buf, sizeof(buf), "pty - %s: %d", state, info->child_pid);
+ snprintf(buf, sizeof(buf), "pty - %s: %ld", state, (long)info->child_pid);
exc = rb_exc_new2(eChildExited, buf);
rb_iv_set(exc, "status", rb_last_status);
rb_funcall(info->thread, rb_intern("raise"), 1, exc);
@@ -155,17 +153,15 @@ pty_syswait(info)
cpid = rb_waitpid(info->child_pid, &status, WUNTRACED);
if (cpid == -1) return Qnil;
-#if defined(IF_STOPPED)
- if (IF_STOPPED(status)) { /* suspend */
- raise_from_wait("stopped", info);
- }
-#elif defined(WIFSTOPPED)
- if (WIFSTOPPED(status)) { /* suspend */
- raise_from_wait("stopped", info);
- }
+#if defined(WIFSTOPPED)
+#elif defined(IF_STOPPED)
+#define WIFSTOPPED(status) IF_STOPPED(status)
#else
---->> Either IF_STOPPED or WIFSTOPPED is needed <<----
#endif /* WIFSTOPPED | IF_STOPPED */
+ if (WIFSTOPPED(status)) { /* suspend */
+ raise_from_wait("stopped", info);
+ }
else if (kill(info->child_pid, 0) == 0) {
raise_from_wait("changed", info);
}
@@ -176,28 +172,32 @@ pty_syswait(info)
}
}
-static void getDevice _((int*, int*));
+static void getDevice _((int*, int*, char [DEVICELEN]));
struct exec_info {
int argc;
VALUE *argv;
};
+static VALUE pty_exec _((VALUE v));
+
static VALUE
-pty_exec(arg)
- struct exec_info *arg;
+pty_exec(v)
+ VALUE v;
{
+ struct exec_info *arg = (struct exec_info *)v;
return rb_f_exec(arg->argc, arg->argv);
}
static void
-establishShell(argc, argv, info)
+establishShell(argc, argv, info, SlaveName)
int argc;
VALUE *argv;
struct pty_info *info;
-{
- static int i,master,slave,currentPid;
- char *p,*getenv();
+ char SlaveName[DEVICELEN];
+{
+ int i,master,slave;
+ char *p, tmp, *getenv();
struct passwd *pwent;
VALUE v;
struct exec_info arg;
@@ -220,10 +220,9 @@ establishShell(argc, argv, info)
argc = 1;
argv = &v;
}
- getDevice(&master,&slave);
+ getDevice(&master, &slave, SlaveName);
info->thread = rb_thread_current();
- currentPid = getpid();
if((i = fork()) < 0) {
close(master);
close(slave);
@@ -231,8 +230,6 @@ establishShell(argc, argv, info)
}
if(i == 0) { /* child */
- currentPid = getpid();
-
/*
* Set free from process group and controlling terminal
*/
@@ -244,7 +241,7 @@ establishShell(argc, argv, info)
if (setpgrp() == -1)
perror("setpgrp()");
# else /* SETGRP_VOID */
- if (setpgrp(0, currentPid) == -1)
+ if (setpgrp(0, getpid()) == -1)
rb_sys_fail("setpgrp()");
if ((i = open("/dev/tty", O_RDONLY)) < 0)
rb_sys_fail("/dev/tty");
@@ -273,6 +270,7 @@ establishShell(argc, argv, info)
}
close(master);
#endif
+ write(slave, "", 1);
dup2(slave,0);
dup2(slave,1);
dup2(slave,2);
@@ -288,6 +286,7 @@ establishShell(argc, argv, info)
_exit(1);
}
+ read(master, &tmp, 1);
close(slave);
info->child_pid = i;
@@ -305,8 +304,9 @@ pty_finalize_syswait(info)
}
static int
-get_device_once(master, slave, fail)
+get_device_once(master, slave, SlaveName, fail)
int *master, *slave, fail;
+ char SlaveName[DEVICELEN];
{
#if defined HAVE_OPENPTY
/*
@@ -329,10 +329,9 @@ get_device_once(master, slave, fail)
}
*slave = open(name, O_RDWR);
- strcpy(SlaveName, name);
+ strncpy(SlaveName, name, sizeof SlaveName);
return 0;
-}
#else /* HAVE__GETPTY */
int i,j;
@@ -354,10 +353,11 @@ get_device_once(master, slave, fail)
#if defined I_PUSH && !defined linux
if(ioctl(j, I_PUSH, "ptem") != -1) {
if(ioctl(j, I_PUSH, "ldterm") != -1) {
+ ioctl(j, I_PUSH, "ttcompat");
#endif
*master = i;
*slave = j;
- strcpy(SlaveName, pn);
+ strncpy(SlaveName, pn, sizeof SlaveName);
return 0;
#if defined I_PUSH && !defined linux
}
@@ -376,10 +376,10 @@ get_device_once(master, slave, fail)
char MasterName[DEVICELEN];
for (p = deviceNo; *p != NULL; p++) {
- sprintf(MasterName,MasterDevice,*p);
+ snprintf(MasterName, sizeof MasterName, MasterDevice, *p);
if ((i = open(MasterName,O_RDWR,0)) >= 0) {
*master = i;
- sprintf(SlaveName,SlaveDevice,*p);
+ snprintf(SlaveName, sizeof SlaveName, SlaveDevice, *p);
if ((j = open(SlaveName,O_RDWR,0)) >= 0) {
*slave = j;
chown(SlaveName, getuid(), getgid());
@@ -396,22 +396,16 @@ get_device_once(master, slave, fail)
}
static void
-getDevice(master, slave)
+getDevice(master, slave, slavename)
int *master, *slave;
+ char slavename[DEVICELEN];
{
- if (get_device_once(master, slave, 0)) {
+ if (get_device_once(master, slave, slavename, 0)) {
rb_gc();
- get_device_once(master, slave, 1);
+ get_device_once(master, slave, slavename, 1);
}
}
-static void
-freeDevice()
-{
- chmod(SlaveName, 0666);
- chown(SlaveName, 0, 0);
-}
-
/* ruby function: getpty */
static VALUE
pty_getpty(argc, argv, self)
@@ -422,14 +416,15 @@ pty_getpty(argc, argv, self)
VALUE res;
struct pty_info info;
struct pty_info thinfo;
- OpenFile *wfptr,*rfptr;
+ rb_io_t *wfptr,*rfptr;
VALUE rport = rb_obj_alloc(rb_cFile);
VALUE wport = rb_obj_alloc(rb_cFile);
-
+ char SlaveName[DEVICELEN];
+
MakeOpenFile(rport, rfptr);
MakeOpenFile(wport, wfptr);
- establishShell(argc, argv, &info);
+ establishShell(argc, argv, &info, SlaveName);
rfptr->mode = rb_io_mode_flags("r");
rfptr->f = fdopen(info.fd, "r");
diff --git a/ext/purelib.rb b/ext/purelib.rb
new file mode 100644
index 0000000000..dbe514c34a
--- /dev/null
+++ b/ext/purelib.rb
@@ -0,0 +1,10 @@
+nul = nil
+$:.each_with_index {|path, index|
+ if /\A(?:\.\/)*-\z/ =~ path
+ nul = index
+ break
+ end
+}
+if nul
+ $:[nul..-1] = ["."]
+end
diff --git a/ext/racc/cparse/cparse.c b/ext/racc/cparse/cparse.c
index 197a0eb40b..18a26f670f 100644
--- a/ext/racc/cparse/cparse.c
+++ b/ext/racc/cparse/cparse.c
@@ -393,10 +393,6 @@ cparse_params_mark(void *ptr)
rb_gc_mark(v->goto_check);
rb_gc_mark(v->goto_default);
rb_gc_mark(v->goto_pointer);
- rb_gc_mark(v->goto_pointer);
- rb_gc_mark(v->goto_pointer);
- rb_gc_mark(v->goto_pointer);
- rb_gc_mark(v->goto_pointer);
rb_gc_mark(v->reduce_table);
rb_gc_mark(v->token_table);
rb_gc_mark(v->state);
diff --git a/ext/racc/cparse/extconf.rb b/ext/racc/cparse/extconf.rb
index 8516c2998a..dd953a7e15 100644
--- a/ext/racc/cparse/extconf.rb
+++ b/ext/racc/cparse/extconf.rb
@@ -1,4 +1,4 @@
-# $Id: extconf.rb,v 1.1 2002/03/22 07:20:31 aamine Exp $
+# $Id$
require 'mkmf'
create_makefile 'racc/cparse'
diff --git a/ext/readline/extconf.rb b/ext/readline/extconf.rb
index b67a443dad..b820c0b32f 100644
--- a/ext/readline/extconf.rb
+++ b/ext/readline/extconf.rb
@@ -42,7 +42,9 @@ else
end
end
-have_readline_var("rl_filename_completion_function")
+have_func("rl_filename_completion_function")
+have_func("rl_username_completion_function")
+have_func("rl_completion_matches")
have_readline_var("rl_deprep_term_function")
have_readline_var("rl_completion_append_character")
have_readline_var("rl_basic_word_break_characters")
@@ -57,7 +59,6 @@ have_func("rl_cleanup_after_signal")
have_func("rl_clear_signals")
have_func("rl_vi_editing_mode")
have_func("rl_emacs_editing_mode")
-have_func("rl_clear_signals")
have_func("replace_history_entry")
have_func("remove_history")
create_makefile("readline")
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
index 4f840ee2c0..c9acaadac9 100644
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -34,21 +34,40 @@ static ID completion_proc, completion_case_fold;
#ifndef HAVE_RL_FILENAME_COMPLETION_FUNCTION
# define rl_filename_completion_function filename_completion_function
+#endif
+#ifndef HAVE_RL_USERNAME_COMPLETION_FUNCTION
# define rl_username_completion_function username_completion_function
+#endif
+#ifndef HAVE_RL_COMPLETION_MATCHES
# define rl_completion_matches completion_matches
#endif
-static int readline_event(void);
static char **readline_attempted_completion_function(const char *text,
int start, int end);
+#ifdef HAVE_RL_EVENT_HOOK
+#ifdef DOSISH
+#define BUSY_WAIT 1
+#else
+#define BUSY_WAIT 0
+#endif
+
+static int readline_event(void);
static int
readline_event()
{
- CHECK_INTS;
+#if BUSY_WAIT
rb_thread_schedule();
+#else
+ fd_set rset;
+
+ FD_ZERO(&rset);
+ FD_SET(fileno(rl_instream), &rset);
+ rb_thread_select(fileno(rl_instream) + 1, &rset, NULL, NULL, NULL);
return 0;
+#endif
}
+#endif
static VALUE
readline_readline(argc, argv, self)
@@ -60,7 +79,7 @@ readline_readline(argc, argv, self)
char *prompt = NULL;
char *buff;
int status;
- OpenFile *ofp, *ifp;
+ rb_io_t *ofp, *ifp;
rb_secure(4);
if (rb_scan_args(argc, argv, "02", &tmp, &add_hist) > 0) {
diff --git a/ext/sdbm/_sdbm.c b/ext/sdbm/_sdbm.c
index 11353e2345..5b34824afc 100644
--- a/ext/sdbm/_sdbm.c
+++ b/ext/sdbm/_sdbm.c
@@ -8,7 +8,7 @@
*/
#ifndef lint
-/*char sdbm_rcsid[] = "$Id: _sdbm.c,v 1.5.2.1 2005/09/08 05:59:41 matz Exp $";*/
+/*char sdbm_rcsid[] = "$Id$";*/
#endif
#include "sdbm.h"
@@ -71,7 +71,7 @@ static int duppair proto((char *, datum));
#include <stdio.h>
#include <stdlib.h>
-#ifdef MSDOS
+#ifdef DOSISH
#include <io.h>
#endif
#include <sys/types.h>
@@ -626,7 +626,7 @@ register DBM *db;
*/
#ifndef lint
-/*char pair_rcsid[] = "$Id: _sdbm.c,v 1.5.2.1 2005/09/08 05:59:41 matz Exp $";*/
+/*char pair_rcsid[] = "$Id$";*/
#endif
#ifndef BSD42
diff --git a/ext/sdbm/init.c b/ext/sdbm/init.c
index ef4fb8ffbf..acadc9b26a 100644
--- a/ext/sdbm/init.c
+++ b/ext/sdbm/init.c
@@ -2,8 +2,8 @@
sdbminit.c -
- $Author: ocean $
- $Date: 2005/06/25 05:42:41 $
+ $Author$
+ $Date$
created at: Fri May 7 08:34:24 JST 1999
Copyright (C) 1995-2001 Yukihiro Matsumoto
diff --git a/ext/socket/addrinfo.h b/ext/socket/addrinfo.h
index a22615ee00..e93adafba6 100644
--- a/ext/socket/addrinfo.h
+++ b/ext/socket/addrinfo.h
@@ -61,10 +61,15 @@
#undef NI_NUMERICSERV
#undef NI_DGRAM
+#undef addrinfo
#define addrinfo addrinfo__compat
+#undef getaddrinfo
#define getaddrinfo getaddrinfo__compat
+#undef getnameinfo
#define getnameinfo getnameinfo__compat
+#undef freehostent
#define freehostent freehostent__compat
+#undef freeaddrinfo
#define freeaddrinfo freeaddrinfo__compat
#ifndef __P
diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb
index 41b715e0af..8a13ddba73 100644
--- a/ext/socket/extconf.rb
+++ b/ext/socket/extconf.rb
@@ -33,6 +33,9 @@ if /solaris/ =~ RUBY_PLATFORM and !try_compile("")
# bug of gcc 3.0 on Solaris 8 ?
headers << "sys/feature_tests.h"
end
+if have_header("arpa/inet.h")
+ headers << "arpa/inet.h"
+end
ipv6 = false
default_ipv6 = /cygwin/ !~ RUBY_PLATFORM
@@ -153,6 +156,10 @@ main()
if (ai->ai_addr == NULL)
goto bad;
#if defined(_AIX)
+ if (ai->ai_family == AF_INET6 && passive) {
+ inet6++;
+ continue;
+ }
ai->ai_addr->sa_len = ai->ai_addrlen;
ai->ai_addr->sa_family = ai->ai_family;
#endif
@@ -252,7 +259,6 @@ unless getaddr_info_ok and have_func("getnameinfo", "netdb.h") and have_func("ge
have_func("inet_ntop") or have_func("inet_ntoa")
have_func("inet_pton") or have_func("inet_aton")
have_func("getservbyport")
- have_header("arpa/inet.h")
have_header("arpa/nameser.h")
have_header("resolv.h")
end
diff --git a/ext/socket/getnameinfo.c b/ext/socket/getnameinfo.c
index 4c9c8f03c4..66f7e8818a 100644
--- a/ext/socket/getnameinfo.c
+++ b/ext/socket/getnameinfo.c
@@ -35,6 +35,7 @@
*/
#include "config.h"
+#include <stdio.h>
#include <sys/types.h>
#ifndef _WIN32
#if defined(__BEOS__)
@@ -51,15 +52,11 @@
#endif
#include <netdb.h>
#if defined(HAVE_RESOLV_H)
-#ifdef _SX
-#include <stdio.h>
-#endif
#include <resolv.h>
#endif
#endif
#ifdef _WIN32
#include <winsock2.h>
-#include <stdio.h>
#define snprintf _snprintf
#endif
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index 5c91c390ec..491823ad44 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -2,8 +2,8 @@
socket.c -
- $Author: matz $
- $Date: 2006/08/07 07:50:28 $
+ $Author$
+ $Date$
created at: Thu Mar 31 12:21:29 JST 1994
Copyright (C) 1993-2001 Yukihiro Matsumoto
@@ -42,6 +42,9 @@
#ifdef HAVE_NETINET_UDP_H
# include <netinet/udp.h>
#endif
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
#include <netdb.h>
#endif
#include <errno.h>
@@ -195,6 +198,34 @@ ruby_getaddrinfo__aix(nodename, servname, hints, res)
}
#undef getaddrinfo
#define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__aix((node),(serv),(hints),(res))
+static int
+ruby_getnameinfo__aix(sa, salen, host, hostlen, serv, servlen, flags)
+ const struct sockaddr *sa;
+ size_t salen;
+ char *host;
+ size_t hostlen;
+ char *serv;
+ size_t servlen;
+ int flags;
+{
+ struct sockaddr_in6 *sa6;
+ u_int32_t *a6;
+
+ if (sa->sa_family == AF_INET6) {
+ sa6 = (struct sockaddr_in6 *)sa;
+ a6 = sa6->sin6_addr.u6_addr.u6_addr32;
+
+ if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) {
+ strncpy(host, "::", hostlen);
+ snprintf(serv, servlen, "%d", sa6->sin6_port);
+ return 0;
+ }
+ }
+ return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+}
+#undef getnameinfo
+#define getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) \
+ ruby_getnameinfo__aix((sa), (salen), (host), (hostlen), (serv), (servlen), (flags))
#ifndef CMSG_SPACE
# define CMSG_SPACE(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + _CMSG_ALIGN(len))
#endif
@@ -213,7 +244,7 @@ init_sock(sock, fd)
VALUE sock;
int fd;
{
- OpenFile *fp;
+ rb_io_t *fp;
MakeOpenFile(sock, fp);
fp->f = rb_fdopen(fd, "r");
@@ -228,7 +259,7 @@ static VALUE
bsock_s_for_fd(klass, fd)
VALUE klass, fd;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
VALUE sock = init_sock(rb_obj_alloc(klass), NUM2INT(fd));
GetOpenFile(sock, fptr);
@@ -244,7 +275,7 @@ bsock_shutdown(argc, argv, sock)
{
VALUE howto;
int how;
- OpenFile *fptr;
+ rb_io_t *fptr;
if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
rb_raise(rb_eSecurityError, "Insecure: can't shutdown socket");
@@ -269,7 +300,7 @@ static VALUE
bsock_close_read(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
rb_raise(rb_eSecurityError, "Insecure: can't close socket");
@@ -288,7 +319,7 @@ static VALUE
bsock_close_write(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
rb_raise(rb_eSecurityError, "Insecure: can't close socket");
@@ -353,7 +384,7 @@ bsock_setsockopt(sock, lev, optname, val)
VALUE sock, lev, optname, val;
{
int level, option;
- OpenFile *fptr;
+ rb_io_t *fptr;
int i;
char *v;
int vlen;
@@ -436,7 +467,7 @@ bsock_getsockopt(sock, lev, optname)
int level, option;
socklen_t len;
char *buf;
- OpenFile *fptr;
+ rb_io_t *fptr;
level = NUM2INT(lev);
option = NUM2INT(optname);
@@ -460,7 +491,7 @@ bsock_getsockname(sock)
{
char buf[1024];
socklen_t len = sizeof buf;
- OpenFile *fptr;
+ rb_io_t *fptr;
GetOpenFile(sock, fptr);
if (getsockname(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
@@ -474,7 +505,7 @@ bsock_getpeername(sock)
{
char buf[1024];
socklen_t len = sizeof buf;
- OpenFile *fptr;
+ rb_io_t *fptr;
GetOpenFile(sock, fptr);
if (getpeername(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
@@ -490,7 +521,7 @@ bsock_send(argc, argv, sock)
{
VALUE mesg, to;
VALUE flags;
- OpenFile *fptr;
+ rb_io_t *fptr;
FILE *f;
int fd, n;
@@ -543,7 +574,7 @@ s_recvfrom(sock, argc, argv, from)
VALUE *argv;
enum sock_recv_type from;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
VALUE str;
char buf[1024];
socklen_t alen = sizeof buf;
@@ -613,7 +644,7 @@ s_recvfrom(sock, argc, argv, from)
static VALUE
s_recvfrom_nonblock(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
{
- OpenFile *fptr;
+ rb_io_t *fptr;
VALUE str;
char buf[1024];
socklen_t alen = sizeof buf;
@@ -809,7 +840,7 @@ host_str(host, hbuf, 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;
@@ -862,10 +893,10 @@ port_str(port, pbuf, len)
}
#ifndef NI_MAXHOST
-# define 1025
+# define NI_MAXHOST 1025
#endif
#ifndef NI_MAXSERV
-# define 32
+# define NI_MAXSERV 32
#endif
static struct addrinfo*
@@ -1054,7 +1085,8 @@ ruby_connect(fd, sockaddr, len, socks)
int mode;
#if WAIT_IN_PROGRESS > 0
int wait_in_progress = -1;
- int sockerr, sockerrlen;
+ int sockerr;
+ socklen_t sockerrlen;
#endif
#if defined(HAVE_FCNTL)
@@ -1274,6 +1306,14 @@ init_inetsock(sock, remote_host, remote_serv, local_host, local_serv, type)
inetsock_cleanup, (VALUE)&arg);
}
+/*
+ * call-seq:
+ * TCPSocket.new(remote_host, remote_port, local_host=nil, local_port=nil)
+ *
+ * Opens a TCP connection to +remote_host+ on +remote_port+. If +local_host+
+ * and +local_port+ are specified, then those parameters are used on the local
+ * end to establish the connection.
+ */
static VALUE
tcp_init(argc, argv, sock)
int argc;
@@ -1310,7 +1350,7 @@ static VALUE
socks_s_close(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
rb_raise(rb_eSecurityError, "Insecure: can't close socket");
@@ -1424,8 +1464,26 @@ tcp_svr_init(argc, argv, sock)
return init_inetsock(sock, Qnil, arg1, Qnil, Qnil, INET_SERVER);
}
+static void
+make_fd_nonblock(int fd)
+{
+ int flags;
+#ifdef F_GETFL
+ flags = fcntl(fd, F_GETFL);
+ if (flags == -1) {
+ rb_sys_fail(0);
+ }
+#else
+ flags = 0;
+#endif
+ flags |= O_NONBLOCK;
+ if (fcntl(fd, F_SETFL, flags) == -1) {
+ rb_sys_fail(0);
+ }
+}
+
static VALUE
-s_accept_nonblock(VALUE klass, OpenFile *fptr, struct sockaddr *sockaddr, socklen_t *len)
+s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len)
{
int fd2;
@@ -1435,6 +1493,7 @@ s_accept_nonblock(VALUE klass, OpenFile *fptr, struct sockaddr *sockaddr, sockle
if (fd2 < 0) {
rb_sys_fail("accept(2)");
}
+ make_fd_nonblock(fd2);
return init_sock(rb_obj_alloc(klass), fd2);
}
@@ -1483,7 +1542,7 @@ static VALUE
tcp_accept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_storage from;
socklen_t fromlen;
@@ -1506,7 +1565,7 @@ tcp_accept(sock)
* serv = TCPServer.new(2202)
* begin
* sock = serv.accept_nonblock
- * rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
+ * rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
* IO.select([serv])
* retry
* end
@@ -1526,7 +1585,7 @@ static VALUE
tcp_accept_nonblock(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_storage from;
socklen_t fromlen;
@@ -1540,7 +1599,7 @@ static VALUE
tcp_sysaccept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_storage from;
socklen_t fromlen;
@@ -1571,7 +1630,7 @@ init_unixsock(sock, path, server)
{
struct sockaddr_un sockaddr;
int fd, status;
- OpenFile *fptr;
+ rb_io_t *fptr;
SafeStringValue(path);
fd = ruby_socket(AF_UNIX, SOCK_STREAM, 0);
@@ -1623,7 +1682,7 @@ static VALUE
ip_addr(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_storage addr;
socklen_t len = sizeof addr;
@@ -1638,7 +1697,7 @@ static VALUE
ip_peeraddr(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_storage addr;
socklen_t len = sizeof addr;
@@ -1719,7 +1778,7 @@ static VALUE
udp_connect(sock, host, port)
VALUE sock, host, port;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct udp_arg arg;
VALUE ret;
@@ -1737,7 +1796,7 @@ static VALUE
udp_bind(sock, host, port)
VALUE sock, host, port;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct addrinfo *res0, *res;
rb_secure(3);
@@ -1762,7 +1821,7 @@ udp_send(argc, argv, sock)
VALUE sock;
{
VALUE mesg, flags, host, port;
- OpenFile *fptr;
+ rb_io_t *fptr;
FILE *f;
int n;
struct addrinfo *res0, *res;
@@ -1861,7 +1920,7 @@ static VALUE
unix_path(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
GetOpenFile(sock, fptr);
if (fptr->path == 0) {
@@ -1908,7 +1967,7 @@ unix_send_io(sock, val)
{
#if defined(HAVE_SENDMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
int fd;
- OpenFile *fptr;
+ rb_io_t *fptr;
struct msghdr msg;
struct iovec vec[1];
char buf[1];
@@ -1916,12 +1975,12 @@ unix_send_io(sock, val)
#if FD_PASSING_BY_MSG_CONTROL
struct {
struct cmsghdr hdr;
- int fd;
+ char pad[8+sizeof(int)+8];
} cmsg;
#endif
if (rb_obj_is_kind_of(val, rb_cIO)) {
- OpenFile *valfptr;
+ rb_io_t *valfptr;
GetOpenFile(val, valfptr);
fd = fileno(valfptr->f);
}
@@ -1946,12 +2005,13 @@ unix_send_io(sock, val)
#if FD_PASSING_BY_MSG_CONTROL
msg.msg_control = (caddr_t)&cmsg;
- msg.msg_controllen = CMSG_SPACE(sizeof(int));
+ msg.msg_controllen = CMSG_LEN(sizeof(int));
msg.msg_flags = 0;
+ MEMZERO((char*)&cmsg, char, sizeof(cmsg));
cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int));
cmsg.hdr.cmsg_level = SOL_SOCKET;
cmsg.hdr.cmsg_type = SCM_RIGHTS;
- cmsg.fd = fd;
+ *(int *)CMSG_DATA(&cmsg.hdr) = fd;
#else
msg.msg_accrights = (caddr_t)&fd;
msg.msg_accrightslen = sizeof(fd);
@@ -1988,7 +2048,7 @@ unix_recv_io(argc, argv, sock)
{
#if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
VALUE klass, mode;
- OpenFile *fptr;
+ rb_io_t *fptr;
struct msghdr msg;
struct iovec vec[2];
char buf[1];
@@ -1997,7 +2057,7 @@ unix_recv_io(argc, argv, sock)
#if FD_PASSING_BY_MSG_CONTROL
struct {
struct cmsghdr hdr;
- int fd;
+ char pad[8+sizeof(int)+8];
} cmsg;
#endif
@@ -2026,7 +2086,7 @@ unix_recv_io(argc, argv, sock)
cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int));
cmsg.hdr.cmsg_level = SOL_SOCKET;
cmsg.hdr.cmsg_type = SCM_RIGHTS;
- cmsg.fd = -1;
+ *(int *)CMSG_DATA(&cmsg.hdr) = -1;
#else
msg.msg_accrights = (caddr_t)&fd;
msg.msg_accrightslen = sizeof(fd);
@@ -2039,22 +2099,22 @@ unix_recv_io(argc, argv, sock)
#if FD_PASSING_BY_MSG_CONTROL
if (msg.msg_controllen != CMSG_SPACE(sizeof(int))) {
rb_raise(rb_eSocket,
- "file descriptor was not passed (msg_controllen : %d != %d)",
+ "file descriptor was not passed (msg_controllen=%d, %d expected)",
msg.msg_controllen, CMSG_SPACE(sizeof(int)));
}
- if (cmsg.hdr.cmsg_len != CMSG_SPACE(0) + sizeof(int)) {
+ if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) {
rb_raise(rb_eSocket,
- "file descriptor was not passed (cmsg_len : %d != %d)",
- cmsg.hdr.cmsg_len, CMSG_SPACE(0) + sizeof(int));
+ "file descriptor was not passed (cmsg_len=%d, %d expected)",
+ cmsg.hdr.cmsg_len, CMSG_LEN(sizeof(int)));
}
if (cmsg.hdr.cmsg_level != SOL_SOCKET) {
rb_raise(rb_eSocket,
- "file descriptor was not passed (cmsg_level : %d != %d)",
+ "file descriptor was not passed (cmsg_level=%d, %d expected)",
cmsg.hdr.cmsg_level, SOL_SOCKET);
}
if (cmsg.hdr.cmsg_type != SCM_RIGHTS) {
rb_raise(rb_eSocket,
- "file descriptor was not passed (cmsg_type : %d != %d)",
+ "file descriptor was not passed (cmsg_type=%d, %d expected)",
cmsg.hdr.cmsg_type, SCM_RIGHTS);
}
#else
@@ -2066,7 +2126,7 @@ unix_recv_io(argc, argv, sock)
#endif
#if FD_PASSING_BY_MSG_CONTROL
- fd = cmsg.fd;
+ fd = *(int *)CMSG_DATA(&cmsg.hdr);
#endif
if (klass == Qnil)
@@ -2092,7 +2152,7 @@ static VALUE
unix_accept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_un from;
socklen_t fromlen;
@@ -2115,7 +2175,7 @@ unix_accept(sock)
* serv = UNIXServer.new("/tmp/sock")
* begin
* sock = serv.accept_nonblock
- * rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
+ * rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
* IO.select([serv])
* retry
* end
@@ -2135,7 +2195,7 @@ static VALUE
unix_accept_nonblock(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_un from;
socklen_t fromlen;
@@ -2149,7 +2209,7 @@ static VALUE
unix_sysaccept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_un from;
socklen_t fromlen;
@@ -2171,7 +2231,7 @@ static VALUE
unix_addr(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_un addr;
socklen_t len = sizeof addr;
@@ -2186,14 +2246,14 @@ static VALUE
unix_peeraddr(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_un addr;
socklen_t len = sizeof addr;
GetOpenFile(sock, fptr);
if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
- rb_sys_fail("getsockname(2)");
+ rb_sys_fail("getpeername(2)");
return unixaddr(&addr, len);
}
#endif
@@ -2466,7 +2526,7 @@ static VALUE
sock_connect(sock, addr)
VALUE sock, addr;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
int fd;
StringValue(addr);
@@ -2522,7 +2582,7 @@ static VALUE
sock_connect_nonblock(sock, addr)
VALUE sock, addr;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
int n;
StringValue(addr);
@@ -2620,7 +2680,7 @@ static VALUE
sock_bind(sock, addr)
VALUE sock, addr;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
StringValue(addr);
GetOpenFile(sock, fptr);
@@ -2704,7 +2764,7 @@ static VALUE
sock_listen(sock, log)
VALUE sock, log;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
int backlog;
rb_secure(4);
@@ -2861,7 +2921,7 @@ sock_recvfrom(argc, argv, sock)
* client, client_sockaddr = socket.accept
* begin
* pair = client.recvfrom_nonblock(20)
- * rescue Errno::EAGAIN
+ * rescue Errno::EAGAIN, Errno::EWOULDBLOCK
* IO.select([client])
* retry
* end
@@ -2911,7 +2971,7 @@ sock_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
* socket.bind( sockaddr )
* socket.listen( 5 )
* client, client_sockaddr = socket.accept
- * puts "The client said, '#{socket.readline.chomp}'"
+ * puts "The client said, '#{client.readline.chomp}'"
* client.puts "Hello from script one!"
* socket.close
*
@@ -2980,7 +3040,7 @@ static VALUE
sock_accept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
VALUE sock2;
char buf[1024];
socklen_t len = sizeof buf;
@@ -3012,11 +3072,11 @@ sock_accept(sock)
* socket.listen(5)
* begin
* client_socket, client_sockaddr = socket.accept_nonblock
- * rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
+ * rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
* IO.select([socket])
* retry
* end
- * puts "The client said, '#{socket.readline.chomp}'"
+ * puts "The client said, '#{client_socket.readline.chomp}'"
* client_socket.puts "Hello from script one!"
* socket.close
*
@@ -3043,7 +3103,7 @@ static VALUE
sock_accept_nonblock(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
VALUE sock2;
char buf[1024];
socklen_t len = sizeof buf;
@@ -3071,8 +3131,8 @@ sock_accept_nonblock(sock)
* socket.bind( sockaddr )
* socket.listen( 5 )
* client_fd, client_sockaddr = socket.sysaccept
- * puts "The client said, '#{socket.readline.chomp}'"
* client_socket = Socket.for_fd( client_fd )
+ * puts "The client said, '#{client_socket.readline.chomp}'"
* client_socket.puts "Hello from script one!"
* socket.close
*
@@ -3096,7 +3156,7 @@ static VALUE
sock_sysaccept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
VALUE sock2;
char buf[1024];
socklen_t len = sizeof buf;
diff --git a/ext/socket/sockport.h b/ext/socket/sockport.h
index 8c7bebf558..e1cddf53f4 100644
--- a/ext/socket/sockport.h
+++ b/ext/socket/sockport.h
@@ -2,8 +2,8 @@
sockport.h -
- $Author: eban $
- $Date: 2000/08/24 06:29:30 $
+ $Author$
+ $Date$
created at: Fri Apr 30 23:19:34 JST 1999
************************************************/
diff --git a/ext/stringio/README b/ext/stringio/README
index 190052309c..c4031f7e97 100644
--- a/ext/stringio/README
+++ b/ext/stringio/README
@@ -1,6 +1,6 @@
-*- rd -*-
-$Author: nobu $
-$Date: 2002/02/19 13:16:24 $
+$Author$
+$Date$
=begin
diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c
index 09867009b5..537fc19a4e 100644
--- a/ext/stringio/stringio.c
+++ b/ext/stringio/stringio.c
@@ -2,8 +2,8 @@
stringio.c -
- $Author: nobu $
- $Date: 2005/08/13 09:36:12 $
+ $Author$
+ $Date$
$RoughId: stringio.c,v 1.13 2002/03/14 03:24:18 nobu Exp $
created at: Tue Feb 19 04:10:38 JST 2002
@@ -14,6 +14,7 @@
#include "ruby.h"
#include "rubyio.h"
+#include "re.h"
#if defined(HAVE_FCNTL_H) || defined(_WIN32)
#include <fcntl.h>
#elif defined(HAVE_SYS_FCNTL_H)
@@ -136,6 +137,7 @@ check_modifiable(ptr)
static VALUE strio_s_allocate _((VALUE));
static VALUE strio_s_open _((int, VALUE *, VALUE));
+static void strio_init _((int, VALUE *, struct StringIO *));
static VALUE strio_initialize _((int, VALUE *, VALUE));
static VALUE strio_finalize _((VALUE));
static VALUE strio_self _((VALUE));
@@ -161,6 +163,7 @@ static VALUE strio_rewind _((VALUE));
static VALUE strio_seek _((int, VALUE *, VALUE));
static VALUE strio_get_sync _((VALUE));
static VALUE strio_each_byte _((VALUE));
+static VALUE strio_each_char _((VALUE));
static VALUE strio_getc _((VALUE));
static VALUE strio_ungetc _((VALUE, VALUE));
static VALUE strio_readchar _((VALUE));
@@ -217,13 +220,24 @@ strio_initialize(argc, argv, self)
VALUE self;
{
struct StringIO *ptr = check_strio(self);
- VALUE string, mode;
- int trunc = Qfalse;
if (!ptr) {
DATA_PTR(self) = ptr = strio_alloc();
}
rb_call_super(0, 0);
+ strio_init(argc, argv, ptr);
+ return self;
+}
+
+static void
+strio_init(argc, argv, ptr)
+ int argc;
+ VALUE *argv;
+ struct StringIO *ptr;
+{
+ VALUE string, mode;
+ int trunc = Qfalse;
+
switch (rb_scan_args(argc, argv, "02", &string, &mode)) {
case 2:
if (FIXNUM_P(mode)) {
@@ -255,7 +269,6 @@ strio_initialize(argc, argv, self)
break;
}
ptr->string = string;
- return self;
}
static VALUE
@@ -570,7 +583,8 @@ strio_reopen(argc, argv, self)
if (argc == 1 && TYPE(*argv) != T_STRING) {
return strio_copy(self, *argv);
}
- return strio_initialize(argc, argv, self);
+ strio_init(argc, argv, StringIO(self));
+ return self;
}
/*
@@ -645,6 +659,9 @@ strio_seek(argc, argv, self)
rb_scan_args(argc, argv, "11", NULL, &whence);
offset = NUM2LONG(argv[0]);
+ if (CLOSED(ptr)) {
+ rb_raise(rb_eIOError, "closed stream");
+ }
switch (NIL_P(whence) ? 0 : NUM2LONG(whence)) {
case 0:
break;
@@ -655,7 +672,7 @@ strio_seek(argc, argv, self)
offset += RSTRING(ptr->string)->len;
break;
default:
- rb_raise(rb_eArgError, "invalid whence %ld", NUM2LONG(whence));
+ error_inval("invalid whence");
}
if (offset < 0) {
error_inval(0);
@@ -695,11 +712,14 @@ strio_each_byte(self)
VALUE self;
{
struct StringIO *ptr = readable(StringIO(self));
- while (ptr->pos < RSTRING(ptr->string)->len) {
- char c = RSTRING(ptr->string)->ptr[ptr->pos++];
+
+ RETURN_ENUMERATOR(self, 0, 0);
+
+ while (ptr->pos < RSTRING_LEN(ptr->string)) {
+ char c = RSTRING_PTR(ptr->string)[ptr->pos++];
rb_yield(CHR2FIX(c));
}
- return Qnil;
+ return self;
}
/*
@@ -788,6 +808,41 @@ strio_readchar(self)
return c;
}
+/*
+ * call-seq:
+ * strio.each_char {|char| block } -> strio
+ *
+ * See IO#each_char.
+ */
+static VALUE
+strio_each_char(self)
+ VALUE self;
+{
+ struct StringIO *sio;
+ VALUE str;
+ const char *ptr;
+ size_t len;
+
+ RETURN_ENUMERATOR(self, 0, 0);
+
+ sio = readable(StringIO(self));
+ str = sio->string;
+ ptr = RSTRING_PTR(str);
+ len = RSTRING_LEN(str);
+
+ while (sio->pos < len) {
+ int pos = sio->pos;
+ char c = ptr[pos];
+ int n = mbclen(c);
+
+ if (len < pos + n) n = len - pos;
+
+ sio->pos += n;
+ rb_yield(rb_str_substr(str, pos, n));
+ }
+ return self;
+}
+
static void
bm_init_skip(skip, pat, m)
long *skip;
@@ -935,7 +990,7 @@ strio_readline(argc, argv, self)
VALUE *argv;
VALUE self;
{
- VALUE line = strio_getline(argc, argv, readable(StringIO(self)));
+ VALUE line = strio_gets(argc, argv, self);
if (NIL_P(line)) rb_eof_error();
return line;
}
@@ -956,6 +1011,8 @@ strio_each(argc, argv, self)
struct StringIO *ptr = StringIO(self);
VALUE line;
+ RETURN_ENUMERATOR(self, argc, argv);
+
while (!NIL_P(line = strio_getline(argc, argv, readable(ptr)))) {
rb_yield(line);
}
@@ -1279,11 +1336,17 @@ Init_stringio()
rb_define_method(StringIO, "path", strio_path, 0);
rb_define_method(StringIO, "each", strio_each, -1);
- rb_define_method(StringIO, "each_byte", strio_each_byte, 0);
rb_define_method(StringIO, "each_line", strio_each, -1);
+ rb_define_method(StringIO, "lines", strio_each, -1);
+ rb_define_method(StringIO, "each_byte", strio_each_byte, 0);
+ rb_define_method(StringIO, "bytes", strio_each_byte, 0);
+ rb_define_method(StringIO, "each_char", strio_each_char, 0);
+ rb_define_method(StringIO, "chars", strio_each_char, 0);
rb_define_method(StringIO, "getc", strio_getc, 0);
+ rb_define_method(StringIO, "getbyte", strio_getc, 0);
rb_define_method(StringIO, "ungetc", strio_ungetc, 1);
rb_define_method(StringIO, "readchar", strio_readchar, 0);
+ rb_define_method(StringIO, "readbyte", strio_readchar, 0);
rb_define_method(StringIO, "gets", strio_gets, -1);
rb_define_method(StringIO, "readline", strio_readline, -1);
rb_define_method(StringIO, "readlines", strio_readlines, -1);
diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c
index 5e5ab5db1f..b5ee20282c 100644
--- a/ext/strscan/strscan.c
+++ b/ext/strscan/strscan.c
@@ -1,5 +1,5 @@
/*
- $Id: strscan.c,v 1.7.2.8 2006/07/26 09:37:00 aamine Exp $
+ $Id$
Copyright (c) 1999-2006 Minero Aoki
@@ -403,6 +403,7 @@ strscan_do_scan(VALUE self, VALUE regex, int succptr, int getstr, int headonly)
if (S_RESTLEN(p) < 0) {
return Qnil;
}
+ rb_kcode_set_option(regex);
if (headonly) {
ret = re_match(RREGEXP(regex)->ptr,
CURPTR(p), S_RESTLEN(p),
@@ -416,6 +417,7 @@ strscan_do_scan(VALUE self, VALUE regex, int succptr, int getstr, int headonly)
S_RESTLEN(p),
&(p->regs));
}
+ rb_kcode_reset_option();
if (ret == -2) rb_raise(ScanError, "regexp buffer overflow");
if (ret < 0) {
@@ -1256,7 +1258,7 @@ Init_strscan(void)
tmp = rb_str_new2(STRSCAN_VERSION);
rb_obj_freeze(tmp);
rb_const_set(StringScanner, rb_intern("Version"), tmp);
- tmp = rb_str_new2("$Id: strscan.c,v 1.7.2.8 2006/07/26 09:37:00 aamine Exp $");
+ tmp = rb_str_new2("$Id$");
rb_obj_freeze(tmp);
rb_const_set(StringScanner, rb_intern("Id"), tmp);
diff --git a/ext/syck/bytecode.c b/ext/syck/bytecode.c
index acda3b15a4..567aaf52a8 100644
--- a/ext/syck/bytecode.c
+++ b/ext/syck/bytecode.c
@@ -3,8 +3,8 @@
/*
* bytecode.re
*
- * $Author: why $
- * $Date: 2005/09/20 06:46:43 $
+ * $Author$
+ * $Date$
*
* Copyright (C) 2003 why the lucky stiff
*/
diff --git a/ext/syck/emitter.c b/ext/syck/emitter.c
index 8d32784cd5..9c8ab8d49b 100644
--- a/ext/syck/emitter.c
+++ b/ext/syck/emitter.c
@@ -1,8 +1,8 @@
/*
* emitter.c
*
- * $Author: matz $
- * $Date: 2006/05/03 17:29:34 $
+ * $Author$
+ * $Date$
*
* Copyright (C) 2003 why the lucky stiff
*
diff --git a/ext/syck/handler.c b/ext/syck/handler.c
index 26fb258318..56fe838fbd 100644
--- a/ext/syck/handler.c
+++ b/ext/syck/handler.c
@@ -1,8 +1,8 @@
/*
* handler.c
*
- * $Author: why $
- * $Date: 2005/09/20 06:46:43 $
+ * $Author$
+ * $Date$
*
* Copyright (C) 2003 why the lucky stiff
*/
diff --git a/ext/syck/implicit.c b/ext/syck/implicit.c
index 0f922f4d1b..d356faf7d9 100644
--- a/ext/syck/implicit.c
+++ b/ext/syck/implicit.c
@@ -3,8 +3,8 @@
/*
* implicit.re
*
- * $Author: ocean $
- * $Date: 2005/10/26 00:28:39 $
+ * $Author$
+ * $Date$
*
* Copyright (C) 2003 why the lucky stiff
*/
diff --git a/ext/syck/node.c b/ext/syck/node.c
index 724f747e99..28fc78c077 100644
--- a/ext/syck/node.c
+++ b/ext/syck/node.c
@@ -1,8 +1,8 @@
/*
* node.c
*
- * $Author: matz $
- * $Date: 2005/09/16 09:35:23 $
+ * $Author$
+ * $Date$
*
* Copyright (C) 2003 why the lucky stiff
*/
diff --git a/ext/syck/rubyext.c b/ext/syck/rubyext.c
index e2de4bbfd0..76e8279601 100644
--- a/ext/syck/rubyext.c
+++ b/ext/syck/rubyext.c
@@ -2,8 +2,8 @@
/*
* rubyext.c
*
- * $Author: ocean $
- * $Date: 2006/01/30 15:11:57 $
+ * $Author$
+ * $Date$
*
* Copyright (C) 2003-2005 why the lucky stiff
*/
@@ -268,9 +268,13 @@ rb_syck_mktime(str, len)
{
char padded[] = "000000";
char *end = ptr + 1;
+ char *p = end;
while ( isdigit( *end ) ) end++;
- MEMCPY(padded, ptr + 1, char, end - (ptr + 1));
- usec = strtol(padded, NULL, 10);
+ if (end - p < sizeof(padded)) {
+ MEMCPY(padded, ptr + 1, char, end - (ptr + 1));
+ p = padded;
+ }
+ usec = strtol(p, NULL, 10);
}
else
{
@@ -913,7 +917,6 @@ static VALUE
syck_resolver_initialize( self )
VALUE self;
{
- VALUE tags = rb_hash_new();
rb_ivar_set(self, s_tags, rb_hash_new());
return self;
}
@@ -948,7 +951,6 @@ VALUE
syck_resolver_detect_implicit( self, val )
VALUE self, val;
{
- char *type_id;
return rb_str_new2( "" );
}
@@ -1304,7 +1306,6 @@ syck_genericresolver_node_import( self, node )
break;
case syck_seq_kind:
- rb_iv_set(obj, "@kind", sym_seq);
v = rb_ary_new2( syck_seq_count( n ) );
for ( i = 0; i < syck_seq_count( n ); i++ )
{
@@ -1315,10 +1316,10 @@ syck_genericresolver_node_import( self, node )
style = sym_inline;
}
obj = rb_funcall( cSeq, s_new, 3, t, v, style );
+ rb_iv_set(obj, "@kind", sym_seq);
break;
case syck_map_kind:
- rb_iv_set(obj, "@kind", sym_map);
v = rb_hash_new();
for ( i = 0; i < syck_map_count( n ); i++ )
{
@@ -1329,6 +1330,7 @@ syck_genericresolver_node_import( self, node )
style = sym_inline;
}
obj = rb_funcall( cMap, s_new, 3, t, v, style );
+ rb_iv_set(obj, "@kind", sym_map);
break;
}
@@ -2024,7 +2026,6 @@ syck_emitter_emit( argc, argv, self )
VALUE self;
{
VALUE oid, proc;
- char *anchor_name;
SyckEmitter *emitter;
struct emitter_xtra *bonus;
SYMID symple;
@@ -2280,7 +2281,6 @@ Init_syck()
*/
cScalar = rb_define_class_under( rb_syck, "Scalar", cNode );
rb_define_alloc_func( cScalar, syck_scalar_alloc );
- rb_define_attr( cNode, "value", 1, 0 );
rb_define_method( cScalar, "initialize", syck_scalar_initialize, 3 );
rb_define_method( cScalar, "value=", syck_scalar_value_set, 1 );
rb_define_method( cScalar, "style=", syck_scalar_style_set, 1 );
diff --git a/ext/syck/syck.c b/ext/syck/syck.c
index ac5427bc1b..a83c8813c1 100644
--- a/ext/syck/syck.c
+++ b/ext/syck/syck.c
@@ -1,8 +1,8 @@
/*
* syck.c
*
- * $Author: matz $
- * $Date: 2006/08/07 08:09:34 $
+ * $Author$
+ * $Date$
*
* Copyright (C) 2003 why the lucky stiff
*/
diff --git a/ext/syck/syck.h b/ext/syck/syck.h
index 51a0f0aa9c..e7d07e9c0d 100644
--- a/ext/syck/syck.h
+++ b/ext/syck/syck.h
@@ -1,8 +1,8 @@
/*
* syck.h
*
- * $Author: ocean $
- * $Date: 2005/12/20 04:13:26 $
+ * $Author$
+ * $Date$
*
* Copyright (C) 2003 why the lucky stiff
*/
@@ -17,6 +17,7 @@
#define YAML_DOMAIN "yaml.org,2002"
#include <stdio.h>
+#include <stdlib.h>
#include <ctype.h>
#include "st.h"
@@ -399,6 +400,7 @@ int syck_scan_scalar( int, char *, long );
void syck_parser_handler( SyckParser *, SyckNodeHandler );
void syck_parser_error_handler( SyckParser *, SyckErrorHandler );
void syck_parser_bad_anchor_handler( SyckParser *, SyckBadAnchorHandler );
+void syck_parser_set_input_type( SyckParser *, enum syck_parser_input );
void syck_parser_file( SyckParser *, FILE *, SyckIoFileRead );
void syck_parser_str( SyckParser *, char *, long, SyckIoStrRead );
void syck_parser_str_auto( SyckParser *, char *, SyckIoStrRead );
diff --git a/ext/syck/token.c b/ext/syck/token.c
index e7b0414f74..3c6cd1a9cf 100644
--- a/ext/syck/token.c
+++ b/ext/syck/token.c
@@ -3,8 +3,8 @@
/*
* token.re
*
- * $Author: why $
- * $Date: 2005/09/20 23:56:24 $
+ * $Author$
+ * $Date$
*
* Copyright (C) 2003 why the lucky stiff
*/
diff --git a/ext/syck/yaml2byte.c b/ext/syck/yaml2byte.c
index 01a3aaf652..821a3cd5b5 100644
--- a/ext/syck/yaml2byte.c
+++ b/ext/syck/yaml2byte.c
@@ -1,8 +1,8 @@
/*
* yaml2byte.c
*
- * $Author: matz $
- * $Date: 2006/05/03 17:41:10 $
+ * $Author$
+ * $Date$
*
* Copyright (C) 2003 why the lucky stiff, clark evans
*
diff --git a/ext/syslog/extconf.rb b/ext/syslog/extconf.rb
index d47ed8fd61..0fa0bc339b 100644
--- a/ext/syslog/extconf.rb
+++ b/ext/syslog/extconf.rb
@@ -1,5 +1,5 @@
# $RoughId: extconf.rb,v 1.3 2001/11/24 17:49:26 knu Exp $
-# $Id: extconf.rb,v 1.1 2001/11/26 12:00:40 knu Exp $
+# $Id$
require 'mkmf'
diff --git a/ext/syslog/syslog.c b/ext/syslog/syslog.c
index 99e4215a95..ecc49318f7 100644
--- a/ext/syslog/syslog.c
+++ b/ext/syslog/syslog.c
@@ -4,7 +4,7 @@
* <amos+ruby@utdallas.edu>
*
* $RoughId: syslog.c,v 1.21 2002/02/25 12:21:17 knu Exp $
- * $Id: syslog.c,v 1.8.2.1 2004/04/05 07:45:24 matz Exp $
+ * $Id$
*/
#include "ruby.h"
@@ -22,6 +22,7 @@ static void syslog_write(int pri, int argc, VALUE *argv)
{
VALUE str;
+ rb_secure(4);
if (argc < 1) {
rb_raise(rb_eArgError, "no log message supplied");
}
@@ -38,6 +39,7 @@ static void syslog_write(int pri, int argc, VALUE *argv)
/* Syslog module methods */
static VALUE mSyslog_close(VALUE self)
{
+ rb_secure(4);
if (!syslog_opened) {
rb_raise(rb_eRuntimeError, "syslog not opened");
}
@@ -132,6 +134,7 @@ static VALUE mSyslog_get_mask(VALUE self)
static VALUE mSyslog_set_mask(VALUE self, VALUE mask)
{
+ rb_secure(4);
if (!syslog_opened) {
rb_raise(rb_eRuntimeError, "must open syslog before setting log mask");
}
diff --git a/ext/syslog/syslog.txt b/ext/syslog/syslog.txt
index b134ed2a40..35bd4cb057 100644
--- a/ext/syslog/syslog.txt
+++ b/ext/syslog/syslog.txt
@@ -1,13 +1,16 @@
.\" syslog.txt - -*- Indented-Text -*-
$RoughId: syslog.txt,v 1.18 2002/02/25 08:20:14 knu Exp $
-$Id: syslog.txt,v 1.2 2002/02/25 12:13:30 knu Exp $
+$Id$
UNIX Syslog extension for Ruby
Amos Gouaux, University of Texas at Dallas
<amos+ruby@utdallas.edu>
&
Akinori MUSHA
-<knu@ruby-lang.org>
+<knu@iDaemons.org>
+
+Contact:
+ - Akinori MUSHA <knu@iDaemons.org> (current maintainer)
** Syslog(Module)
diff --git a/ext/syslog/test.rb b/ext/syslog/test.rb
index 907602c21d..cfa33eff8f 100644
--- a/ext/syslog/test.rb
+++ b/ext/syslog/test.rb
@@ -1,6 +1,6 @@
#!/usr/bin/env ruby
# $RoughId: test.rb,v 1.9 2002/02/25 08:20:14 knu Exp $
-# $Id: test.rb,v 1.4 2002/11/27 08:36:22 knu Exp $
+# $Id$
# Please only run this test on machines reasonable for testing.
# If in doubt, ask your admin.
diff --git a/ext/thread/extconf.rb b/ext/thread/extconf.rb
new file mode 100644
index 0000000000..2f984efc6d
--- /dev/null
+++ b/ext/thread/extconf.rb
@@ -0,0 +1,9 @@
+require 'mkmf'
+
+enable_config('fastthread', true) or exit
+
+if with_config('mem-pools', true)
+ $CPPFLAGS << ' -DUSE_MEM_POOLS'
+end
+
+create_makefile("thread")
diff --git a/ext/thread/lib/thread.rb b/ext/thread/lib/thread.rb
new file mode 100644
index 0000000000..6c533aba39
--- /dev/null
+++ b/ext/thread/lib/thread.rb
@@ -0,0 +1,5 @@
+unless defined? Thread
+ fail "Thread not available for this ruby interpreter"
+end
+
+require 'thread.so'
diff --git a/ext/thread/thread.c b/ext/thread/thread.c
new file mode 100644
index 0000000000..68f172220a
--- /dev/null
+++ b/ext/thread/thread.c
@@ -0,0 +1,1182 @@
+/*
+ * Optimized Ruby Mutex implementation, loosely based on thread.rb by
+ * Yukihiro Matsumoto <matz@ruby-lang.org>
+ *
+ * Copyright 2006-2007 MenTaLguY <mental@rydia.net>
+ *
+ * RDoc taken from original.
+ *
+ * This file is made available under the same terms as Ruby.
+ */
+
+#include <ruby.h>
+#include <intern.h>
+#include <rubysig.h>
+
+static VALUE rb_cMutex;
+static VALUE rb_cConditionVariable;
+static VALUE rb_cQueue;
+static VALUE rb_cSizedQueue;
+
+static VALUE set_critical(VALUE value);
+
+static VALUE
+thread_exclusive(VALUE (*func)(ANYARGS), VALUE arg)
+{
+ VALUE critical = rb_thread_critical;
+
+ rb_thread_critical = 1;
+ return rb_ensure(func, arg, set_critical, (VALUE)critical);
+}
+
+/*
+ * call-seq:
+ * Thread.exclusive { block } => obj
+ *
+ * Wraps a block in Thread.critical, restoring the original value
+ * upon exit from the critical section, and returns the value of the
+ * block.
+ */
+
+static VALUE
+rb_thread_exclusive(void)
+{
+ return thread_exclusive(rb_yield, Qundef);
+}
+
+typedef struct _Entry {
+ VALUE value;
+ struct _Entry *next;
+} Entry;
+
+typedef struct _List {
+ Entry *entries;
+ Entry *last_entry;
+ Entry *entry_pool;
+ unsigned long size;
+} List;
+
+static void
+init_list(List *list)
+{
+ list->entries = NULL;
+ list->last_entry = NULL;
+ list->entry_pool = NULL;
+ list->size = 0;
+}
+
+static void
+mark_list(List *list)
+{
+ Entry *entry;
+ for (entry = list->entries; entry; entry = entry->next) {
+ rb_gc_mark(entry->value);
+ }
+}
+
+static void
+free_entries(Entry *first)
+{
+ Entry *next;
+ while (first) {
+ next = first->next;
+ xfree(first);
+ first = next;
+ }
+}
+
+static void
+finalize_list(List *list)
+{
+ free_entries(list->entries);
+ free_entries(list->entry_pool);
+}
+
+static void
+push_list(List *list, VALUE value)
+{
+ Entry *entry;
+
+ if (list->entry_pool) {
+ entry = list->entry_pool;
+ list->entry_pool = entry->next;
+ } else {
+ entry = ALLOC(Entry);
+ }
+
+ entry->value = value;
+ entry->next = NULL;
+
+ if (list->last_entry) {
+ list->last_entry->next = entry;
+ } else {
+ list->entries = entry;
+ }
+ list->last_entry = entry;
+
+ ++list->size;
+}
+
+static void
+push_multiple_list(List *list, VALUE *values, unsigned count)
+{
+ unsigned i;
+ for (i = 0; i < count; i++) {
+ push_list(list, values[i]);
+ }
+}
+
+static void
+recycle_entries(List *list, Entry *first_entry, Entry *last_entry)
+{
+#ifdef USE_MEM_POOLS
+ last_entry->next = list->entry_pool;
+ list->entry_pool = first_entry;
+#else
+ last_entry->next = NULL;
+ free_entries(first_entry);
+#endif
+}
+
+static VALUE
+shift_list(List *list)
+{
+ Entry *entry;
+ VALUE value;
+
+ entry = list->entries;
+ if (!entry) return Qnil;
+
+ list->entries = entry->next;
+ if (entry == list->last_entry) {
+ list->last_entry = NULL;
+ }
+
+ --list->size;
+
+ value = entry->value;
+ recycle_entries(list, entry, entry);
+
+ return value;
+}
+
+static void
+remove_one(List *list, VALUE value)
+{
+ Entry **ref;
+ Entry *prev;
+ Entry *entry;
+
+ for (ref = &list->entries, prev = NULL, entry = list->entries;
+ entry != NULL;
+ ref = &entry->next, prev = entry, entry = entry->next) {
+ if (entry->value == value) {
+ *ref = entry->next;
+ list->size--;
+ if (!entry->next) {
+ list->last_entry = prev;
+ }
+ recycle_entries(list, entry, entry);
+ break;
+ }
+ }
+}
+
+static void
+clear_list(List *list)
+{
+ if (list->last_entry) {
+ recycle_entries(list, list->entries, list->last_entry);
+ list->entries = NULL;
+ list->last_entry = NULL;
+ list->size = 0;
+ }
+}
+
+static VALUE
+array_from_list(List const *list)
+{
+ VALUE ary;
+ Entry *entry;
+ ary = rb_ary_new();
+ for (entry = list->entries; entry; entry = entry->next) {
+ rb_ary_push(ary, entry->value);
+ }
+ return ary;
+}
+
+static VALUE
+wake_thread(VALUE thread)
+{
+ return rb_thread_wakeup_alive(thread);
+}
+
+static VALUE
+run_thread(VALUE thread)
+{
+ thread = wake_thread(thread);
+ if (RTEST(thread) && !rb_thread_critical)
+ rb_thread_schedule();
+ return thread;
+}
+
+static VALUE
+wake_one(List *list)
+{
+ VALUE waking;
+
+ waking = Qnil;
+ while (list->entries && !RTEST(waking)) {
+ waking = wake_thread(shift_list(list));
+ }
+
+ return waking;
+}
+
+static VALUE
+wake_all(List *list)
+{
+ while (list->entries) {
+ wake_one(list);
+ }
+ return Qnil;
+}
+
+static VALUE
+wait_list_inner(List *list)
+{
+ push_list(list, rb_thread_current());
+ rb_thread_stop();
+ return Qnil;
+}
+
+static VALUE
+wait_list_cleanup(List *list)
+{
+ /* cleanup in case of spurious wakeups */
+ remove_one(list, rb_thread_current());
+ return Qnil;
+}
+
+static VALUE
+wait_list(List *list)
+{
+ return rb_ensure(wait_list_inner, (VALUE)list, wait_list_cleanup, (VALUE)list);
+}
+
+static void
+kill_waiting_threads(List *waiting)
+{
+ Entry *entry;
+
+ for (entry = waiting->entries; entry; entry = entry->next) {
+ rb_thread_kill(entry->value);
+ }
+}
+
+/*
+ * Document-class: Mutex
+ *
+ * Mutex implements a simple semaphore that can be used to coordinate access to
+ * shared data from multiple concurrent threads.
+ *
+ * Example:
+ *
+ * require 'thread'
+ * semaphore = Mutex.new
+ *
+ * a = Thread.new {
+ * semaphore.synchronize {
+ * # access shared resource
+ * }
+ * }
+ *
+ * b = Thread.new {
+ * semaphore.synchronize {
+ * # access shared resource
+ * }
+ * }
+ *
+ */
+
+typedef struct _Mutex {
+ VALUE owner;
+ List waiting;
+} Mutex;
+
+#define MUTEX_LOCKED_P(mutex) (RTEST((mutex)->owner) && rb_thread_alive_p((mutex)->owner))
+
+static void
+mark_mutex(Mutex *mutex)
+{
+ rb_gc_mark(mutex->owner);
+ mark_list(&mutex->waiting);
+}
+
+static void
+finalize_mutex(Mutex *mutex)
+{
+ finalize_list(&mutex->waiting);
+}
+
+static void
+free_mutex(Mutex *mutex)
+{
+ kill_waiting_threads(&mutex->waiting);
+ finalize_mutex(mutex);
+ xfree(mutex);
+}
+
+static void
+init_mutex(Mutex *mutex)
+{
+ mutex->owner = Qnil;
+ init_list(&mutex->waiting);
+}
+
+/*
+ * Document-method: new
+ * call-seq: Mutex.new
+ *
+ * Creates a new Mutex
+ *
+ */
+
+static VALUE
+rb_mutex_alloc(VALUE klass)
+{
+ Mutex *mutex;
+ mutex = ALLOC(Mutex);
+ init_mutex(mutex);
+ return Data_Wrap_Struct(klass, mark_mutex, free_mutex, mutex);
+}
+
+/*
+ * Document-method: locked?
+ * call-seq: locked?
+ *
+ * Returns +true+ if this lock is currently held by some thread.
+ *
+ */
+
+static VALUE
+rb_mutex_locked_p(VALUE self)
+{
+ Mutex *mutex;
+ Data_Get_Struct(self, Mutex, mutex);
+ return MUTEX_LOCKED_P(mutex) ? Qtrue : Qfalse;
+}
+
+/*
+ * Document-method: try_lock
+ * call-seq: try_lock
+ *
+ * Attempts to obtain the lock and returns immediately. Returns +true+ if the
+ * lock was granted.
+ *
+ */
+
+static VALUE
+rb_mutex_try_lock(VALUE self)
+{
+ Mutex *mutex;
+
+ Data_Get_Struct(self, Mutex, mutex);
+
+ if (MUTEX_LOCKED_P(mutex))
+ return Qfalse;
+
+ mutex->owner = rb_thread_current();
+ return Qtrue;
+}
+
+/*
+ * Document-method: lock
+ * call-seq: lock
+ *
+ * Attempts to grab the lock and waits if it isn't available.
+ *
+ */
+
+static VALUE
+lock_mutex(Mutex *mutex)
+{
+ VALUE current;
+ current = rb_thread_current();
+
+ rb_thread_critical = 1;
+
+ if (!MUTEX_LOCKED_P(mutex)) {
+ mutex->owner = current;
+ }
+ else {
+ do {
+ wait_list(&mutex->waiting);
+ rb_thread_critical = 1;
+ if (!MUTEX_LOCKED_P(mutex)) {
+ mutex->owner = current;
+ break;
+ }
+ } while (mutex->owner != current);
+ }
+
+ rb_thread_critical = 0;
+ return Qnil;
+}
+
+static VALUE
+rb_mutex_lock(VALUE self)
+{
+ Mutex *mutex;
+ Data_Get_Struct(self, Mutex, mutex);
+ lock_mutex(mutex);
+ return self;
+}
+
+/*
+ * Document-method: unlock
+ *
+ * Releases the lock. Returns +nil+ if ref wasn't locked.
+ *
+ */
+
+static VALUE
+unlock_mutex_inner(Mutex *mutex)
+{
+ VALUE waking;
+
+ if (mutex->owner != rb_thread_current()) {
+ rb_raise(rb_eThreadError, "not owner");
+ }
+
+ waking = wake_one(&mutex->waiting);
+ mutex->owner = waking;
+
+ return waking;
+}
+
+static VALUE
+set_critical(VALUE value)
+{
+ rb_thread_critical = (int)value;
+ return Qundef;
+}
+
+static VALUE
+unlock_mutex(Mutex *mutex)
+{
+ VALUE waking = thread_exclusive(unlock_mutex_inner, (VALUE)mutex);
+
+ if (!RTEST(waking)) {
+ return Qfalse;
+ }
+
+ run_thread(waking);
+
+ return Qtrue;
+}
+
+static VALUE
+rb_mutex_unlock(VALUE self)
+{
+ Mutex *mutex;
+ Data_Get_Struct(self, Mutex, mutex);
+
+ if (RTEST(unlock_mutex(mutex))) {
+ return self;
+ } else {
+ return Qnil;
+ }
+}
+
+/*
+ * Document-method: exclusive_unlock
+ * call-seq: exclusive_unlock { ... }
+ *
+ * If the mutex is locked, unlocks the mutex, wakes one waiting thread, and
+ * yields in a critical section.
+ *
+ */
+
+static VALUE
+rb_mutex_exclusive_unlock_inner(Mutex *mutex)
+{
+ VALUE waking;
+ waking = unlock_mutex_inner(mutex);
+ rb_yield(Qundef);
+ return waking;
+}
+
+static VALUE
+rb_mutex_exclusive_unlock(VALUE self)
+{
+ Mutex *mutex;
+ VALUE waking;
+ Data_Get_Struct(self, Mutex, mutex);
+
+ waking = thread_exclusive(rb_mutex_exclusive_unlock_inner, (VALUE)mutex);
+
+ if (!RTEST(waking)) {
+ return Qnil;
+ }
+
+ run_thread(waking);
+
+ return self;
+}
+
+/*
+ * Document-method: synchronize
+ * call-seq: synchronize { ... }
+ *
+ * Obtains a lock, runs the block, and releases the lock when the block
+ * completes. See the example under Mutex.
+ *
+ */
+
+static VALUE
+rb_mutex_synchronize(VALUE self)
+{
+ rb_mutex_lock(self);
+ return rb_ensure(rb_yield, Qundef, rb_mutex_unlock, self);
+}
+
+/*
+ * Document-class: ConditionVariable
+ *
+ * ConditionVariable objects augment class Mutex. Using condition variables,
+ * it is possible to suspend while in the middle of a critical section until a
+ * resource becomes available.
+ *
+ * Example:
+ *
+ * require 'thread'
+ *
+ * mutex = Mutex.new
+ * resource = ConditionVariable.new
+ *
+ * a = Thread.new {
+ * mutex.synchronize {
+ * # Thread 'a' now needs the resource
+ * resource.wait(mutex)
+ * # 'a' can now have the resource
+ * }
+ * }
+ *
+ * b = Thread.new {
+ * mutex.synchronize {
+ * # Thread 'b' has finished using the resource
+ * resource.signal
+ * }
+ * }
+ *
+ */
+
+typedef struct _ConditionVariable {
+ List waiting;
+} ConditionVariable;
+
+static void
+mark_condvar(ConditionVariable *condvar)
+{
+ mark_list(&condvar->waiting);
+}
+
+static void
+finalize_condvar(ConditionVariable *condvar)
+{
+ finalize_list(&condvar->waiting);
+}
+
+static void
+free_condvar(ConditionVariable *condvar)
+{
+ kill_waiting_threads(&condvar->waiting);
+ finalize_condvar(condvar);
+ xfree(condvar);
+}
+
+static void
+init_condvar(ConditionVariable *condvar)
+{
+ init_list(&condvar->waiting);
+}
+
+/*
+ * Document-method: new
+ * call-seq: ConditionVariable.new
+ *
+ * Creates a new ConditionVariable
+ *
+ */
+
+static VALUE
+rb_condvar_alloc(VALUE klass)
+{
+ ConditionVariable *condvar;
+
+ condvar = ALLOC(ConditionVariable);
+ init_condvar(condvar);
+
+ return Data_Wrap_Struct(klass, mark_condvar, free_condvar, condvar);
+}
+
+/*
+ * Document-method: wait
+ * call-seq: wait
+ *
+ * Releases the lock held in +mutex+ and waits; reacquires the lock on wakeup.
+ *
+ */
+
+static void
+wait_condvar(ConditionVariable *condvar, Mutex *mutex)
+{
+ VALUE waking;
+
+ rb_thread_critical = 1;
+ if (rb_thread_current() != mutex->owner) {
+ rb_thread_critical = 0;
+ rb_raise(rb_eThreadError, "not owner of the synchronization mutex");
+ }
+ waking = unlock_mutex_inner(mutex);
+ if (RTEST(waking)) {
+ wake_thread(waking);
+ }
+ rb_ensure(wait_list, (VALUE)&condvar->waiting, lock_mutex, (VALUE)mutex);
+}
+
+static VALUE
+legacy_exclusive_unlock(VALUE mutex)
+{
+ return rb_funcall(mutex, rb_intern("exclusive_unlock"), 0);
+}
+
+typedef struct {
+ ConditionVariable *condvar;
+ VALUE mutex;
+} legacy_wait_args;
+
+static VALUE
+legacy_wait(VALUE unused, legacy_wait_args *args)
+{
+ wait_list(&args->condvar->waiting);
+ rb_funcall(args->mutex, rb_intern("lock"), 0);
+ return Qnil;
+}
+
+static VALUE
+rb_condvar_wait(VALUE self, VALUE mutex_v)
+{
+ ConditionVariable *condvar;
+ Data_Get_Struct(self, ConditionVariable, condvar);
+
+ if (CLASS_OF(mutex_v) != rb_cMutex) {
+ /* interoperate with legacy mutex */
+ legacy_wait_args args;
+ args.condvar = condvar;
+ args.mutex = mutex_v;
+ rb_iterate(legacy_exclusive_unlock, mutex_v, legacy_wait, (VALUE)&args);
+ } else {
+ Mutex *mutex;
+ Data_Get_Struct(mutex_v, Mutex, mutex);
+ wait_condvar(condvar, mutex);
+ }
+
+ return self;
+}
+
+/*
+ * Document-method: broadcast
+ * call-seq: broadcast
+ *
+ * Wakes up all threads waiting for this condition.
+ *
+ */
+
+static VALUE
+rb_condvar_broadcast(VALUE self)
+{
+ ConditionVariable *condvar;
+
+ Data_Get_Struct(self, ConditionVariable, condvar);
+
+ thread_exclusive(wake_all, (VALUE)&condvar->waiting);
+ rb_thread_schedule();
+
+ return self;
+}
+
+/*
+ * Document-method: signal
+ * call-seq: signal
+ *
+ * Wakes up the first thread in line waiting for this condition.
+ *
+ */
+
+static void
+signal_condvar(ConditionVariable *condvar)
+{
+ VALUE waking = thread_exclusive(wake_one, (VALUE)&condvar->waiting);
+
+ if (RTEST(waking)) {
+ run_thread(waking);
+ }
+}
+
+static VALUE
+rb_condvar_signal(VALUE self)
+{
+ ConditionVariable *condvar;
+ Data_Get_Struct(self, ConditionVariable, condvar);
+ signal_condvar(condvar);
+ return self;
+}
+
+/*
+ * Document-class: Queue
+ *
+ * This class provides a way to synchronize communication between threads.
+ *
+ * Example:
+ *
+ * require 'thread'
+ *
+ * queue = Queue.new
+ *
+ * producer = Thread.new do
+ * 5.times do |i|
+ * sleep rand(i) # simulate expense
+ * queue << i
+ * puts "#{i} produced"
+ * end
+ * end
+ *
+ * consumer = Thread.new do
+ * 5.times do |i|
+ * value = queue.pop
+ * sleep rand(i/2) # simulate expense
+ * puts "consumed #{value}"
+ * end
+ * end
+ *
+ * consumer.join
+ *
+ */
+
+typedef struct _Queue {
+ Mutex mutex;
+ ConditionVariable value_available;
+ ConditionVariable space_available;
+ List values;
+ unsigned long capacity;
+} Queue;
+
+static void
+mark_queue(Queue *queue)
+{
+ mark_mutex(&queue->mutex);
+ mark_condvar(&queue->value_available);
+ mark_condvar(&queue->space_available);
+ mark_list(&queue->values);
+}
+
+static void
+finalize_queue(Queue *queue)
+{
+ finalize_mutex(&queue->mutex);
+ finalize_condvar(&queue->value_available);
+ finalize_condvar(&queue->space_available);
+ finalize_list(&queue->values);
+}
+
+static void
+free_queue(Queue *queue)
+{
+ kill_waiting_threads(&queue->mutex.waiting);
+ kill_waiting_threads(&queue->space_available.waiting);
+ kill_waiting_threads(&queue->value_available.waiting);
+ finalize_queue(queue);
+ xfree(queue);
+}
+
+static void
+init_queue(Queue *queue)
+{
+ init_mutex(&queue->mutex);
+ init_condvar(&queue->value_available);
+ init_condvar(&queue->space_available);
+ init_list(&queue->values);
+ queue->capacity = 0;
+}
+
+/*
+ * Document-method: new
+ * call-seq: new
+ *
+ * Creates a new queue.
+ *
+ */
+
+static VALUE
+rb_queue_alloc(VALUE klass)
+{
+ Queue *queue;
+ queue = ALLOC(Queue);
+ init_queue(queue);
+ return Data_Wrap_Struct(klass, mark_queue, free_queue, queue);
+}
+
+static VALUE
+rb_queue_marshal_load(VALUE self, VALUE data)
+{
+ Queue *queue;
+ VALUE array;
+ Data_Get_Struct(self, Queue, queue);
+
+ array = rb_marshal_load(data);
+ if (TYPE(array) != T_ARRAY) {
+ rb_raise(rb_eTypeError, "expected Array of queue data");
+ }
+ if (RARRAY(array)->len < 1) {
+ rb_raise(rb_eArgError, "missing capacity value");
+ }
+ queue->capacity = NUM2ULONG(rb_ary_shift(array));
+ push_multiple_list(&queue->values, RARRAY(array)->ptr, (unsigned)RARRAY(array)->len);
+
+ return self;
+}
+
+static VALUE
+rb_queue_marshal_dump(VALUE self)
+{
+ Queue *queue;
+ VALUE array;
+ Data_Get_Struct(self, Queue, queue);
+
+ array = array_from_list(&queue->values);
+ rb_ary_unshift(array, ULONG2NUM(queue->capacity));
+ return rb_marshal_dump(array, Qnil);
+}
+
+/*
+ * Document-method: clear
+ * call-seq: clear
+ *
+ * Removes all objects from the queue.
+ *
+ */
+
+static VALUE
+rb_queue_clear(VALUE self)
+{
+ Queue *queue;
+ Data_Get_Struct(self, Queue, queue);
+
+ lock_mutex(&queue->mutex);
+ clear_list(&queue->values);
+ signal_condvar(&queue->space_available);
+ unlock_mutex(&queue->mutex);
+
+ return self;
+}
+
+/*
+ * Document-method: empty?
+ * call-seq: empty?
+ *
+ * Returns +true+ if the queue is empty.
+ *
+ */
+
+static VALUE
+rb_queue_empty_p(VALUE self)
+{
+ Queue *queue;
+ VALUE result;
+ Data_Get_Struct(self, Queue, queue);
+
+ lock_mutex(&queue->mutex);
+ result = queue->values.size == 0 ? Qtrue : Qfalse;
+ unlock_mutex(&queue->mutex);
+
+ return result;
+}
+
+/*
+ * Document-method: length
+ * call-seq: length
+ *
+ * Returns the length of the queue.
+ *
+ */
+
+static VALUE
+rb_queue_length(VALUE self)
+{
+ Queue *queue;
+ VALUE result;
+ Data_Get_Struct(self, Queue, queue);
+
+ lock_mutex(&queue->mutex);
+ result = ULONG2NUM(queue->values.size);
+ unlock_mutex(&queue->mutex);
+
+ return result;
+}
+
+/*
+ * Document-method: num_waiting
+ * call-seq: num_waiting
+ *
+ * Returns the number of threads waiting on the queue.
+ *
+ */
+
+static VALUE
+rb_queue_num_waiting(VALUE self)
+{
+ Queue *queue;
+ VALUE result;
+ Data_Get_Struct(self, Queue, queue);
+
+ lock_mutex(&queue->mutex);
+ result = ULONG2NUM(queue->value_available.waiting.size +
+ queue->space_available.waiting.size);
+ unlock_mutex(&queue->mutex);
+
+ return result;
+}
+
+/*
+ * Document-method: pop
+ * call_seq: pop(non_block=false)
+ *
+ * Retrieves data from the queue. If the queue is empty, the calling thread is
+ * suspended until data is pushed onto the queue. If +non_block+ is true, the
+ * thread isn't suspended, and an exception is raised.
+ *
+ */
+
+static VALUE
+rb_queue_pop(int argc, VALUE *argv, VALUE self)
+{
+ Queue *queue;
+ int should_block;
+ VALUE result;
+ Data_Get_Struct(self, Queue, queue);
+
+ if (argc == 0) {
+ should_block = 1;
+ } else if (argc == 1) {
+ should_block = !RTEST(argv[0]);
+ } else {
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
+ }
+
+ lock_mutex(&queue->mutex);
+ if (!queue->values.entries && !should_block) {
+ unlock_mutex(&queue->mutex);
+ rb_raise(rb_eThreadError, "queue empty");
+ }
+
+ while (!queue->values.entries) {
+ wait_condvar(&queue->value_available, &queue->mutex);
+ }
+
+ result = shift_list(&queue->values);
+ if (queue->capacity && queue->values.size < queue->capacity) {
+ signal_condvar(&queue->space_available);
+ }
+ unlock_mutex(&queue->mutex);
+
+ return result;
+}
+
+/*
+ * Document-method: push
+ * call-seq: push(obj)
+ *
+ * Pushes +obj+ to the queue.
+ *
+ */
+
+static VALUE
+rb_queue_push(VALUE self, VALUE value)
+{
+ Queue *queue;
+ Data_Get_Struct(self, Queue, queue);
+
+ lock_mutex(&queue->mutex);
+ while (queue->capacity && queue->values.size >= queue->capacity) {
+ wait_condvar(&queue->space_available, &queue->mutex);
+ }
+ push_list(&queue->values, value);
+ signal_condvar(&queue->value_available);
+ unlock_mutex(&queue->mutex);
+
+ return self;
+}
+
+/*
+ * Document-class: SizedQueue
+ *
+ * This class represents queues of specified size capacity. The push operation
+ * may be blocked if the capacity is full.
+ *
+ * See Queue for an example of how a SizedQueue works.
+ *
+ */
+
+/*
+ * Document-method: new
+ * call-seq: new
+ *
+ * Creates a fixed-length queue with a maximum size of +max+.
+ *
+ */
+
+/*
+ * Document-method: max
+ * call-seq: max
+ *
+ * Returns the maximum size of the queue.
+ *
+ */
+
+static VALUE
+rb_sized_queue_max(VALUE self)
+{
+ Queue *queue;
+ VALUE result;
+ Data_Get_Struct(self, Queue, queue);
+
+ lock_mutex(&queue->mutex);
+ result = ULONG2NUM(queue->capacity);
+ unlock_mutex(&queue->mutex);
+
+ return result;
+}
+
+/*
+ * Document-method: max=
+ * call-seq: max=(size)
+ *
+ * Sets the maximum size of the queue.
+ *
+ */
+
+static VALUE
+rb_sized_queue_max_set(VALUE self, VALUE value)
+{
+ Queue *queue;
+ unsigned long new_capacity;
+ unsigned long difference;
+ Data_Get_Struct(self, Queue, queue);
+
+ new_capacity = NUM2ULONG(value);
+
+ if (new_capacity < 1) {
+ rb_raise(rb_eArgError, "value must be positive");
+ }
+
+ lock_mutex(&queue->mutex);
+ if (queue->capacity && new_capacity > queue->capacity) {
+ difference = new_capacity - queue->capacity;
+ } else {
+ difference = 0;
+ }
+ queue->capacity = new_capacity;
+ for (; difference > 0; --difference) {
+ signal_condvar(&queue->space_available);
+ }
+ unlock_mutex(&queue->mutex);
+
+ return self;
+}
+
+/*
+ * Document-method: push
+ * call-seq: push(obj)
+ *
+ * Pushes +obj+ to the queue. If there is no space left in the queue, waits
+ * until space becomes available.
+ *
+ */
+
+/*
+ * Document-method: pop
+ * call-seq: pop(non_block=false)
+ *
+ * Retrieves data from the queue and runs a waiting thread, if any.
+ *
+ */
+
+/* for marshalling mutexes and condvars */
+
+static VALUE
+dummy_load(VALUE self, VALUE string)
+{
+ return Qnil;
+}
+
+static VALUE
+dummy_dump(VALUE self)
+{
+ return rb_str_new2("");
+}
+
+void
+Init_thread(void)
+{
+ rb_define_singleton_method(rb_cThread, "exclusive", rb_thread_exclusive, 0);
+
+ rb_cMutex = rb_define_class("Mutex", rb_cObject);
+ rb_define_alloc_func(rb_cMutex, rb_mutex_alloc);
+ rb_define_method(rb_cMutex, "marshal_load", dummy_load, 1);
+ rb_define_method(rb_cMutex, "marshal_dump", dummy_dump, 0);
+ rb_define_method(rb_cMutex, "locked?", rb_mutex_locked_p, 0);
+ rb_define_method(rb_cMutex, "try_lock", rb_mutex_try_lock, 0);
+ rb_define_method(rb_cMutex, "lock", rb_mutex_lock, 0);
+ rb_define_method(rb_cMutex, "unlock", rb_mutex_unlock, 0);
+ rb_define_method(rb_cMutex, "exclusive_unlock", rb_mutex_exclusive_unlock, 0);
+ rb_define_method(rb_cMutex, "synchronize", rb_mutex_synchronize, 0);
+
+ rb_cConditionVariable = rb_define_class("ConditionVariable", rb_cObject);
+ rb_define_alloc_func(rb_cConditionVariable, rb_condvar_alloc);
+ rb_define_method(rb_cConditionVariable, "marshal_load", dummy_load, 1);
+ rb_define_method(rb_cConditionVariable, "marshal_dump", dummy_dump, 0);
+ rb_define_method(rb_cConditionVariable, "wait", rb_condvar_wait, 1);
+ rb_define_method(rb_cConditionVariable, "broadcast", rb_condvar_broadcast, 0);
+ rb_define_method(rb_cConditionVariable, "signal", rb_condvar_signal, 0);
+
+ rb_cQueue = rb_define_class("Queue", rb_cObject);
+ rb_define_alloc_func(rb_cQueue, rb_queue_alloc);
+ rb_define_method(rb_cQueue, "marshal_load", rb_queue_marshal_load, 1);
+ rb_define_method(rb_cQueue, "marshal_dump", rb_queue_marshal_dump, 0);
+ rb_define_method(rb_cQueue, "clear", rb_queue_clear, 0);
+ rb_define_method(rb_cQueue, "empty?", rb_queue_empty_p, 0);
+ rb_define_method(rb_cQueue, "length", rb_queue_length, 0);
+ rb_define_method(rb_cQueue, "num_waiting", rb_queue_num_waiting, 0);
+ rb_define_method(rb_cQueue, "pop", rb_queue_pop, -1);
+ rb_define_method(rb_cQueue, "push", rb_queue_push, 1);
+ rb_alias(rb_cQueue, rb_intern("enq"), rb_intern("push"));
+ rb_alias(rb_cQueue, rb_intern("<<"), rb_intern("push"));
+ rb_alias(rb_cQueue, rb_intern("deq"), rb_intern("pop"));
+ rb_alias(rb_cQueue, rb_intern("shift"), rb_intern("pop"));
+ rb_alias(rb_cQueue, rb_intern("size"), rb_intern("length"));
+
+ rb_cSizedQueue = rb_define_class("SizedQueue", rb_cQueue);
+ rb_define_method(rb_cSizedQueue, "initialize", rb_sized_queue_max_set, 1);
+ rb_define_method(rb_cSizedQueue, "num_waiting", rb_queue_num_waiting, 0);
+ rb_define_method(rb_cSizedQueue, "pop", rb_queue_pop, -1);
+ rb_define_method(rb_cSizedQueue, "push", rb_queue_push, 1);
+ rb_define_method(rb_cSizedQueue, "max", rb_sized_queue_max, 0);
+ rb_define_method(rb_cSizedQueue, "max=", rb_sized_queue_max_set, 1);
+ rb_alias(rb_cSizedQueue, rb_intern("enq"), rb_intern("push"));
+ rb_alias(rb_cSizedQueue, rb_intern("<<"), rb_intern("push"));
+ rb_alias(rb_cSizedQueue, rb_intern("deq"), rb_intern("pop"));
+ rb_alias(rb_cSizedQueue, rb_intern("shift"), rb_intern("pop"));
+}
+
diff --git a/ext/tk/ChangeLog.tkextlib b/ext/tk/ChangeLog.tkextlib
index fa5524da01..8c5d01a954 100644
--- a/ext/tk/ChangeLog.tkextlib
+++ b/ext/tk/ChangeLog.tkextlib
@@ -1,3 +1,69 @@
+2008-05-12 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tkextlib/tkDND/shape.rb: wrong package name.
+
+--------------< ... some changes ... >------------------
+
+2007-05-26 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tkextlib/tcllib/tablelist.rb: fix typo.
+
+ * ext/tk/lib/tkextlib/tile/dialog.rb: forget to give an argument.
+
+ * ext/tk/lib/tkextlib/version.rb: update RELEASE_DATE.
+
+2007-01-26 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tkextlib/iwidgets/checkbox.rb: wrong number of arguments
+ [ruby-Bugs-7776].
+
+ * ext/tk/lib/tkextlib/iwidgets/radiobox.rb: ditto.
+
+ * ext/tk/lib/tkextlib/blt/tile/checkbutton.rb: change primary name
+ of class [ruby-dev:30080].
+
+ * ext/tk/lib/tkextlib/blt/tile/radiobutton.rb: ditto.
+
+2006-11-07 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/tile/treeview.rb : minor bug fix.
+
+ * lib/tkextlib/blt/table.rb: fix bugs which forbade use of
+ '::blt::table' command. Now, probably, it'll works properly.
+
+2006-11-06 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/version.rb: keep release date of tkextlib on
+ "Tk::Tkextlib_RELEASE_DATE".
+
+ * lib/tkextlib/tile/treeview.rb : support Tile 0.7.8.
+ Now, you can handle tree items as objects.
+
+2006-10-04 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/tile.rb, lib/tkextlib/tile/* : support Tile 0.7.6.
+
+2006-10-03 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/SUPPORT_STATUS: [ruby-talk:211939] check links
+ of extensions.
+
+ * lib/tkextlib/blt/container.rb: define instance methods properly.
+
+ * lib/tkextlib/tile/tcombobox.rb: bug fix [ruby-talk:213003].
+
+ * lib/tkextlib/tile/tnotebook.rb: ditto.
+
+ * lib/tkextlib/tile/treeview.rb: ditto.
+
+ * lib/tkextlib/tile/sizegrip.rb: [new] add 'ttk::sizegrip' widget.
+
+2006-08-31 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * lib/tkextlib/blt.rb: double dashes (--) option doesn't work
+ properly on some versions of BLT (wrong description on the
+ manual of `blt::bgexec'?).
+
2005-12-11 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* lib/tkextlib/SUPPORT_STATUS: update to support libraries in
diff --git a/ext/tk/MANUAL_tcltklib.eng b/ext/tk/MANUAL_tcltklib.eng
index 1db61f228e..6fa775b7de 100644
--- a/ext/tk/MANUAL_tcltklib.eng
+++ b/ext/tk/MANUAL_tcltklib.eng
@@ -125,7 +125,24 @@ module TclTklib
: Tcl7.6 doesn't have this flag. So PARSE_VARNAME is
: defined as 0.
+ module TclTkLib::RELEASE_TYPE
+ : Defines release type number of Tcl/Tk
+
+ ALPHA
+ : ALPHA release
+
+ BETA
+ : BETA release
+
+ FINAL
+ : FINAL release
+
[module methods]
+ get_version()
+ : return an array of major, minor, release-type number,
+ : number, release-type name, and patchlevel of current
+ : Tcl/Tk library.
+
mainloop(check_root = true)
: Starts the eventloop. If 'check_root' is true, this method
: doesn't return when a root widget exists.
@@ -431,6 +448,10 @@ class TclTkIp
: slave interpreter, same to the TclTkLib module method with
: the same name.
+ encoding_table
+ : For Ruby m17n. Return encoding relation table between Ruby's
+ : Encoding object and Tcl's encoding name.
+
class TkCallbackBreak < StandardError
class TkCallbackContinue < StandardError
: They are exception classes to break or continue the Tk callback
@@ -441,5 +462,8 @@ class TkCallbackContinue < StandardError
: If raise TkCallbackContinue, returns 'continue' code (Then the Tk
: interpreter will break the operateion for the current bindtag and
: starts the operation for the next buindtag for the current event).
+ : However, current tcltklib supports Ruby's 'break' and 'next' to
+ : get the same effect. That is, those classes are obsolete. Those
+ : exist for backward compatibility.
(eof)
diff --git a/ext/tk/MANUAL_tcltklib.eucj b/ext/tk/MANUAL_tcltklib.eucj
index 5dd36726ba..7df42997b4 100644
--- a/ext/tk/MANUAL_tcltklib.eucj
+++ b/ext/tk/MANUAL_tcltklib.eucj
@@ -221,7 +221,23 @@ require "tcltklib" , ʲΥ⥸塼, 饹ѲǽǤ.
: ФϤǤ뤫顤index_name nil
: ͤФʤʤ
+ ⥸塼 TclTkLib::RELEASE_TYPE
+ : Tcl/Tk Υ꡼ֹ
+
+ ALPHA
+ : ALPHA ꡼
+
+ BETA
+ : BETA ꡼
+
+ FINAL
+ : FINAL ꡼
+
⥸塼᥽å
+ get_version()
+ : Tcl/Tk major, minor, release-type ֹ, release-type ̾,
+ : patchlevel ˤ֤
+
mainloop(check_root = true)
: ٥ȥ롼פư롥check_root true ǤС
: root widget ¸ߤ¤ꡤΥ᥽åɤϽλʤ
@@ -543,6 +559,9 @@ require "tcltklib" , ʲΥ⥸塼, 饹ѲǽǤ.
: 졼 IP ξˤ꤬ͤʤ (̵뤵)
: ʳǤϰޤ TclTkLib Ʊ̾᥽åɤƱ
+ encoding_table
+ : Ruby m17n Ѥ Ruby Tk Ȥδ֤ encoding бɽ֤
+
饹 TkCallbackBreak < StandardError
饹 TkCallbackContinue < StandardError
: ϥ٥ȥХåˤơХåŬڤ
@@ -553,5 +572,8 @@ require "tcltklib" , ʲΥ⥸塼, 饹ѲǽǤ.
: ɤ֤ɬפ롥Ruby μ³̤֤ͤΤǤϡ줬
: ̤ͤǤΤݤ̤Ǥʤᡤ㳰ȯѤ
: ԤäƤ롥
+ : ߤǤϡХå³ Ruby break, next ǽλ
+ : 뤳ȤƱη̤뤳ȤǤ褦ˤʤäƤ롥椨
+ : ɬפʤΤǤϤ뤬ߴΤ˻ĤƤ롥
(eof)
diff --git a/ext/tk/README.1st b/ext/tk/README.1st
index df6c819d26..fce5b0242b 100644
--- a/ext/tk/README.1st
+++ b/ext/tk/README.1st
@@ -1,7 +1,6 @@
If you want to use Ruby/Tk (tk.rb and so on), you must have tcltklib.so
-which is working correctly. If you fail to call 'require "tcltklib"',
-you may not have tcltklib.so. When you have some troubles on compiling
-tcltklib, please read README files on tcltklib.
+which is working correctly. When you have some troubles on compiling,
+please read README.tcltklib and README.ActiveTcl.
Even if there is a tcltklib.so on your Ruby library directry, it will not
work without Tcl/Tk libraries (e.g. libtcl8.4.so) on your environment.
You must also check that your Tcl/Tk is installed properly.
@@ -9,11 +8,9 @@ You must also check that your Tcl/Tk is installed properly.
--------------------------------------------
( the following is written in EUC-JP )
-Ruby/Tk (tk.rb ʤ) Ȥˤϡtcltklib.so ư
-ʤФʤޤ󡥤⤷ 'require "tcltklib"' ˼Ԥ褦ʤ顤
-tcltklib.so 󥹥ȡ뤵ƤʤΤ⤷ޤtcltklib
-ѥ˲꤬Ƥϡtcltklib README ե
-򸫤Ƥ
+Ruby/Tk (tk.rb ʤ) Ȥˤϡtcltklib.so ưƤ
+Фʤޤ󡥥ѥ˲꤬ϡREADME.tcltklib
+ README.ActiveTcl 򸫤Ƥ
Ȥ Ruby Υ饤֥ǥ쥯ȥ tcltklib.so ¸ߤƤȤ
⡤¹ԴĶ Tcl/Tk 饤֥ (libtcl8.4.so ʤ) ʤеǽ
Tcl/Tk 󥹥ȡ뤵Ƥ뤫åƤ
diff --git a/ext/tk/README.tcltklib b/ext/tk/README.tcltklib
index 5d1da48a45..8c6dd5178f 100644
--- a/ext/tk/README.tcltklib
+++ b/ext/tk/README.tcltklib
@@ -5,10 +5,14 @@ Tcl/Tk libraries or header files are installed but are not found, you can
give the information by arguments of the 'configure' script. Please give
some or all of the following options.
+ --with-tcltkversion=<version>
+ force version of Tcl/Tk libaray
+ (e.g. libtcl8.4g.so ==> --with-tcltkversion=8.4g)
+
--with-tcllib=<libname> (e.g. libtcl8.4.so ==> --with-tcllib=tcl8.4)
--with-tklib=<libname> (e.g. libtk8.4.so ==> --with-tklib=tk8.4)
- --enable-tcltk_stubs (if you force to enable stubs)
+ --enable-tcltk-stubs (if you force to enable stubs)
--with-tcl-dir=<path>
equal to "--with-tcl-include=<path>/include --with-tcl-lib=<path>/lib"
@@ -16,18 +20,18 @@ some or all of the following options.
--with-tk-dir=<path>
equal to "--with-tk-include=<path>/include --with-tk-lib=<path>/lib"
- --with-tcl-include=<dir> the directry containts 'tcl.h'
- --with-tk-include=<dir> the directry containts 'tk.h'
+ --with-tcl-include=<dir> the directry contains 'tcl.h'
+ --with-tk-include=<dir> the directry contains 'tk.h'
- --with-tcl-lib=<dir> the directry containts 'libtcl<version>.so'
- --with-tk-lib=<dir> the directry containts 'libtk<version>.so'
+ --with-tcl-lib=<dir> the directry contains 'libtcl<version>.so'
+ --with-tk-lib=<dir> the directry contains 'libtk<version>.so'
--enable-mac-tcltk-framework (MacOS X) use Tcl/Tk framework
(Obsolete. Please use '--enable-tcltk-framework'.)
--enable-tcltk-framework use Tcl/Tk framework
- --with-tcltk-framework=<dir> the directory containts Tcl/Tk framework;
+ --with-tcltk-framework=<dir> the directory contains Tcl/Tk framework;
"<dir>/Tcl.framework" and "<dir>/Tk.framework".
When this option is given, it is assumed that
--enable-tcltk-framework option is given also.
@@ -41,6 +45,15 @@ some or all of the following options.
(e.g. "/Library/Frameworks/Tk.framework/Headers")
+ --with-X11 / --without-X11 use / not use the X Window System
+
+ --with-X11-dir=<path>
+ equal to "--with-X11-include=<path>/include --with-X11-lib=<path>/lib"
+
+ --with-X11-include=<dir> the directry contais X11 header files
+ --with-X11-lib=<dir> the directry contais X11 libraries
+
+
If you forgot to give the options when do 'configure' on toplevel
directry of Ruby sources, please try something like as the followings.
diff --git a/ext/tk/extconf.rb b/ext/tk/extconf.rb
index 8c8d833481..4807ea7b40 100644
--- a/ext/tk/extconf.rb
+++ b/ext/tk/extconf.rb
@@ -2,7 +2,8 @@
require 'mkmf'
-is_win32 = (/mswin32|mingw|cygwin|bccwin32/ =~ RUBY_PLATFORM)
+#is_win32 = (/mswin32|mingw|cygwin|bccwin32/ =~ RUBY_PLATFORM)
+is_win32 = (/mswin|mingw|cygwin|bccwin|wince/ =~ RUBY_PLATFORM)
#is_macosx = (/darwin/ =~ RUBY_PLATFORM)
def find_framework(tcl_hdr, tk_hdr)
@@ -39,16 +40,68 @@ unless is_win32
have_library("m", "log")
end
-dir_config("tk")
-dir_config("tcl")
-dir_config("X11")
+tk_idir, tk_ldir = dir_config("tk")
+tcl_idir, tcl_ldir = dir_config("tcl")
+x11_idir, x11_ldir = dir_config("X11")
+
+tk_ldir2 = with_config("tk-lib")
+tcl_ldir2 = with_config("tcl-lib")
+x11_ldir2 = with_config("X11-lib")
+
+tk_ldir_list = [tk_ldir2, tk_ldir]
+tcl_ldir_list = [tcl_ldir2, tcl_ldir]
tklib = with_config("tklib")
tcllib = with_config("tcllib")
stubs = enable_config("tcltk_stubs") || with_config("tcltk_stubs")
-def find_tcl(tcllib, stubs)
- paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"]
+tcltk_version = with_config("tcltkversion")
+
+use_X = with_config("X11", (! is_win32))
+
+def check_tcltk_version(version)
+ return [nil, nil] unless version
+
+ version = version.strip
+
+ tclver = version.dup
+ tkver = version.dup
+
+ major = dot = minor = dot = plvl = ext = nil
+
+ if version =~ /^(\d)(\.?)(\d)(\.?)(\d*)(.*)$/
+ major = $1; minor_dot = $2; minor = $3; plvl_dot = $4; plvl = $5; ext = $6
+ dot = ! minor_dot.empty?
+ if plvl_dot.empty? && ! plvl.empty?
+ minor << plvl
+ end
+ elsif version =~ /^(\d)(\.?)(\d?)(.*)$/
+ major = $1; minor_dot = $2; minor = $3; ext = $4
+ dot = ! minor_dot.empty?
+ else # unknown -> believe user
+ return [tclver, tkver]
+ end
+
+ # check Tcl7.6 / Tk4.2 ?
+ if major == "7" # Tcl7.6 ( not support Tclversion < 7.6 )
+ # Tk4.2
+ tkver = "4" + ((dot)? ".": "") + ((minor.empty)? "": "2") + ext
+ elsif major == "4" # Tk4.2 ( not support Tkversion < 4.2 )
+ # Tcl7.6
+ tclver = "7" + ((dot)? ".": "") + ((minor.empty)? "": "6") + ext
+ end
+
+ [tclver, tkver]
+end
+
+def find_tcl(tcllib, stubs, version, *opt_paths)
+ default_paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"]
+ default_paths << "/Tcl/lib" # default for ActiveTcl
+
+ if (paths = opt_paths.compact).empty?
+ paths = default_paths
+ end
+
if stubs
func = "Tcl_InitStubs"
lib = "tclstub"
@@ -56,22 +109,42 @@ def find_tcl(tcllib, stubs)
func = "Tcl_FindExecutable"
lib = "tcl"
end
+
+ 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]
+ end
+
if tcllib
- find_library(tcllib, func, *paths)
- elsif find_library(lib, func, *paths)
- true
+ st = find_library(tcllib, func, *paths)
else
- %w[8.5 8.4 8.3 8.2 8.1 8.0 7.6].find { |ver|
- find_library("#{lib}#{ver}", func, *paths) or
- find_library("#{lib}#{ver.delete('.')}", func, *paths) or
- find_library("tcl#{ver}", func, *paths) or
- find_library("tcl#{ver.delete('.')}", func, *paths)
- }
+ st = versions.find { |ver|
+ find_library("#{lib}#{ver}", func, *paths) or
+ find_library("#{lib}#{ver.delete('.')}", func, *paths) or
+ find_library("#{lib}#{ver}g", func, *paths) or
+ find_library("#{lib}#{ver.delete('.')}g", func, *paths) or
+ find_library("tcl#{ver}", func, *paths) or
+ find_library("tcl#{ver.delete('.')}", func, *paths) or
+ find_library("tcl#{ver}g", func, *paths) or
+ find_library("tcl#{ver.delete('.')}g", func, *paths)
+ } || (!version && find_library(lib, func, *paths))
+ end
+
+ unless st
+ puts("Warning:: cannot find Tcl library. tcltklib will not be compiled (tcltklib is disabled on your Ruby == Ruby/Tk will not work). Please check configure options.")
end
+ st
end
-def find_tk(tklib, stubs)
- paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"]
+def find_tk(tklib, stubs, version, *opt_paths)
+ default_paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"]
+ default_paths << "/Tcl/lib" # default for ActiveTcl
+
+ if (paths = opt_paths.compact).empty?
+ paths = default_paths
+ end
+
if stubs
func = "Tk_InitStubs"
lib = "tkstub"
@@ -79,20 +152,45 @@ def find_tk(tklib, stubs)
func = "Tk_Init"
lib = "tk"
end
+
+ 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]
+ end
+
if tklib
- find_library(tklib, func, *paths)
- elsif find_library(lib, func, *paths)
- true
+ st = find_library(tklib, func, *paths)
else
- %w[8.5 8.4 8.3 8.2 8.1 8.0 4.2].find { |ver|
- find_library("#{lib}#{ver}", func, *paths) or
- find_library("#{lib}#{ver.delete('.')}", func, *paths) or
- find_library("tk#{ver}", func, *paths) or
- find_library("tk#{ver.delete('.')}", func, *paths)
- }
+ st = versions.find { |ver|
+ find_library("#{lib}#{ver}", func, *paths) or
+ find_library("#{lib}#{ver.delete('.')}", func, *paths) or
+ find_library("#{lib}#{ver}g", func, *paths) or
+ find_library("#{lib}#{ver.delete('.')}g", func, *paths) or
+ find_library("tk#{ver}", func, *paths) or
+ find_library("tk#{ver.delete('.')}", func, *paths) or
+ find_library("tk#{ver}g", func, *paths) or
+ find_library("tk#{ver.delete('.')}g", func, *paths)
+ } || (!version && find_library(lib, func, *paths))
+ end
+
+ unless st
+ puts("Warning:: cannot find Tk library. tcltklib will not be compiled (tcltklib is disabled on your Ruby == Ruby/Tk will not work). Please check configure options.")
end
+ st
end
+def find_X11(*opt_paths)
+ default_paths =
+ [ "/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib" ]
+ paths = opt_paths.compact.concat(default_paths)
+ st = find_library("X11", "XOpenDisplay", *paths)
+ unless st
+ puts("Warning:: cannot find X11 library. tcltklib will not be compiled (tcltklib is disabled on your Ruby == Ruby/Tk will not work). Please check configure options. If your Tcl/Tk don't require X11, please try --without-X11.")
+ end
+ st
+end
+
def pthread_check()
tcl_major_ver = nil
tcl_minor_ver = nil
@@ -271,12 +369,13 @@ EOF
end
end
-if tcltk_framework ||
- (have_header("tcl.h") && have_header("tk.h") &&
- (is_win32 || find_library("X11", "XOpenDisplay",
- "/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib")) &&
- find_tcl(tcllib, stubs) &&
- find_tk(tklib, stubs))
+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) ) )
$CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' if stubs
$CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM
@@ -303,7 +402,11 @@ if tcltk_framework ||
$INSTALLFILES ||= []
$INSTALLFILES << ["lib/tkextlib/SUPPORT_STATUS", "$(RUBYLIBDIR)", "lib"]
+ have_func("rb_hash_lookup", "ruby.h")
+
# create
+ $defs << %[-DRUBY_VERSION=\\"#{RUBY_VERSION}\\"]
+ $defs << %[-DRUBY_RELEASE_DATE=\\"#{RUBY_RELEASE_DATE}\\"]
create_makefile("tcltklib")
end
end
diff --git a/ext/tk/lib/multi-tk.rb b/ext/tk/lib/multi-tk.rb
index 78ed1aa6ee..ec718678f0 100644
--- a/ext/tk/lib/multi-tk.rb
+++ b/ext/tk/lib/multi-tk.rb
@@ -114,7 +114,14 @@ MultiTkIp_OK.freeze
class MultiTkIp
BASE_DIR = File.dirname(__FILE__)
- @@SLAVE_IP_ID = ['slave'.freeze, '0'.taint].freeze
+ WITH_RUBY_VM = Object.const_defined?(:VM) && ::VM.class == Class
+ WITH_ENCODING = Object.const_defined?(:Encoding) && ::Encoding.class == Class
+
+ (@@SLAVE_IP_ID = ['slave'.freeze, '0'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
@@IP_TABLE = {}.taint unless defined?(@@IP_TABLE)
@@ -126,14 +133,18 @@ class MultiTkIp
unless defined?(@@TK_CMD_TBL)
@@TK_CMD_TBL = Object.new.taint
- @@TK_CMD_TBL.instance_variable_set('@tbl', {}.taint)
+ # @@TK_CMD_TBL.instance_variable_set('@tbl', {}.taint)
+ @@TK_CMD_TBL.instance_variable_set('@tbl', Hash.new{|hash,key|
+ fail IndexError,
+ "unknown command ID '#{key}'"
+ }.taint)
class << @@TK_CMD_TBL
allow = [
- '__send__', '__id__', 'freeze', 'inspect', 'kind_of?',
+ '__send__', '__id__', 'freeze', 'inspect', 'kind_of?', 'object_id',
'[]', '[]=', 'delete', 'each', 'has_key?'
]
- instance_methods.each{|m| undef_method(m) unless allow.index(m)}
+ instance_methods.each{|m| undef_method(m) unless allow.index(m.to_s)}
def kind_of?(klass)
@tbl.kind_of?(klass)
@@ -206,7 +217,7 @@ class MultiTkIp
def initialize(ip, cmd)
@ip = ip
@cmd = cmd
- freeze
+ self.freeze
end
attr_reader :ip, :cmd
def inspect
@@ -573,7 +584,11 @@ class MultiTkIp
# raise exception
begin
bt = _toUTF8(e.backtrace.join("\n"))
- bt.instance_variable_set(:@encoding, 'utf-8')
+ if MultiTkIp::WITH_ENCODING
+ bt.force_encoding('utf-8')
+ else
+ bt.instance_variable_set(:@encoding, 'utf-8')
+ end
rescue Exception
bt = e.backtrace.join("\n")
end
@@ -695,6 +710,11 @@ class MultiTkIp
######################################
+ unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD
+ ### Ruby 1.9 !!!!!!!!!!!!!!!!!!!!!!!!!!
+ RUN_EVENTLOOP_ON_MAIN_THREAD = false
+ end
+
if self.const_defined? :DEFAULT_MASTER_NAME
name = DEFAULT_MASTER_NAME.to_s
else
@@ -723,7 +743,41 @@ class MultiTkIp
fail ArgumentError, "expecting a Hash object for the 2nd argument"
end
- @interp = TclTkIp.new(name, _keys2opts(keys))
+ if !WITH_RUBY_VM || RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!!
+ @interp = TclTkIp.new(name, _keys2opts(keys))
+ else ### Ruby 1.9 !!!!!!!!!!!
+ @interp_thread = Thread.new{
+ current = Thread.current
+ current[:interp] = interp = TclTkIp.new(name, _keys2opts(keys))
+ #sleep
+ current[:mutex] = mutex = Mutex.new
+ current[:root_check] = cond_var = ConditionVariable.new
+
+ begin
+ current[:status] = interp.mainloop(true)
+ rescue Exception=>e
+ current[:status] = e
+ ensure
+ mutex.synchronize{ cond_var.broadcast }
+ end
+ current[:status] = interp.mainloop(false)
+ }
+ until @interp_thread[:interp]
+ Thread.pass
+ end
+ # INTERP_THREAD.run
+ @interp = @interp_thread[:interp]
+
+ def self.mainloop(check_root = true)
+ begin
+ TclTkLib.set_eventloop_window_mode(true)
+ @interp_thread.value
+ ensure
+ TclTkLib.set_eventloop_window_mode(false)
+ end
+ end
+ end
+
@ip_name = nil
@callback_status = [].taint
@@ -853,22 +907,26 @@ class MultiTkIp
Thread.new{
current = Thread.current
loop {
- mtx, ret, table, script = @init_ip_env_queue.deq
- begin
+ mtx, cond, ret, table, script = @init_ip_env_queue.deq
+ begin
ret[0] = table.each{|tg, ip| ip._init_ip_env(script) }
rescue Exception => e
ret[0] = e
ensure
- mtx.unlock
+ mtx.synchronize{ cond.signal }
end
+ mtx = cond = ret = table = script = nil # clear variables for GC
}
}
def self.__init_ip_env__(table, script)
ret = []
- mtx = Mutex.new.lock
- @init_ip_env_queue.enq([mtx, ret, table, script])
- mtx.lock
+ mtx = (Thread.current[:MultiTk_ip_Mutex] ||= Mutex.new)
+ cond = (Thread.current[:MultiTk_ip_CondVar] ||= ConditionVariable.new)
+ mtx.synchronize{
+ @init_ip_env_queue.enq([mtx, cond, ret, table, script])
+ cond.wait(mtx)
+ }
if ret[0].kind_of?(Exception)
raise ret[0]
else
@@ -947,9 +1005,11 @@ class MultiTkIp
private :_parse_slaveopts
def _create_slave_ip_name
- name = @@SLAVE_IP_ID.join('')
- @@SLAVE_IP_ID[1].succ!
- name.freeze
+ @@SLAVE_IP_ID.mutex.synchronize{
+ name = @@SLAVE_IP_ID.join('')
+ @@SLAVE_IP_ID[1].succ!
+ name.freeze
+ }
end
private :_create_slave_ip_name
@@ -1206,7 +1266,20 @@ class MultiTkIp
if safeip == nil
# create master-ip
- @interp = TclTkIp.new(name, _keys2opts(tk_opts))
+ unless WITH_RUBY_VM
+ @interp = TclTkIp.new(name, _keys2opts(tk_opts))
+ else ### Ruby 1.9 !!!!!!!!!!!
+ @interp_thread = Thread.new{
+ Thread.current[:interp] = interp = TclTkIp.new(name, _keys2opts(tk_opts))
+ #sleep
+ TclTkLib.mainloop(true)
+ }
+ until @interp_thread[:interp]
+ Thread.pass
+ end
+ # INTERP_THREAD.run
+ @interp = @interp_thread[:interp]
+ end
@ip_name = nil
if safe
@@ -1221,6 +1294,8 @@ class MultiTkIp
@safe_base = true
@interp, @ip_name = master.__create_safe_slave_obj(safe_opts,
name, tk_opts)
+ # @interp_thread = nil if RUBY_VERSION < '1.9.0' ### !!!!!!!!!!!
+ @interp_thread = nil unless WITH_RUBY_VM ### Ruby 1.9 !!!!!!!!!!!
if safe
safe = master.safe_level if safe < master.safe_level
@safe_level = [safe]
@@ -1229,6 +1304,8 @@ class MultiTkIp
end
else
@interp, @ip_name = master.__create_trusted_slave_obj(name, tk_opts)
+ # @interp_thread = nil if RUBY_VERSION < '1.9.0' ### !!!!!!!!!!!
+ @interp_thread = nil unless WITH_RUBY_VM ### Ruby 1.9 !!!!!!!!!!!
if safe
safe = master.safe_level if safe < master.safe_level
@safe_level = [safe]
@@ -1263,11 +1340,11 @@ class MultiTkIp
@@DEFAULT_MASTER.assign_receiver_and_watchdog(self)
@@IP_TABLE[@threadgroup] = self
- _init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS)
@@TK_TABLE_LIST.size.times{
(tbl = {}).tainted? || tbl.taint
@tk_table_list << tbl
}
+ _init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS)
class << self
undef :instance_eval
@@ -1345,8 +1422,13 @@ class << MultiTkIp
alias __new new
private :__new
-
def new_master(safe=nil, keys={})
+ if MultiTkIp::WITH_RUBY_VM
+ #### TODO !!!!!!
+ fail RuntimeError,
+ 'sorry, still not support multiple master-interpreters on Ruby VM'
+ end
+
if safe.kind_of?(Hash)
keys = safe
elsif safe.kind_of?(Integer)
@@ -1563,8 +1645,13 @@ class MultiTkIp
return if slave?
names.each{|name|
name = name.to_s
+
+ return if @interp.deleted?
@interp._invoke('rename', name, '')
+
+ return if @interp.deleted?
@interp._invoke('interp', 'slaves').split.each{|slave|
+ return if @interp.deleted?
@interp._invoke('interp', 'alias', slave, name, '') rescue nil
}
}
@@ -1614,11 +1701,16 @@ class MultiTkIp
id = @@TK_TABLE_LIST.size
obj = Object.new
@@TK_TABLE_LIST << obj
- obj.instance_eval <<-EOD
+ obj.instance_variable_set(:@id, id)
+ obj.instance_variable_set(:@mutex, Mutex.new)
+ obj.instance_eval{
+ def self.mutex
+ @mutex
+ end
def self.method_missing(m, *args)
- MultiTkIp.tk_object_table(#{id}).__send__(m, *args)
+ MultiTkIp.tk_object_table(@id).__send__(m, *args)
end
- EOD
+ }
obj.freeze
@@IP_TABLE.each{|tg, ip| ip._add_new_tables }
return obj
@@ -2338,6 +2430,11 @@ end
class MultiTkIp
def mainloop(check_root = true, restart_on_dead = true)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
+
+ if WITH_RUBY_VM ### Ruby 1.9 !!!!!!!!!!!
+ return @interp_thread.value if @interp_thread
+ end
+
#return self if self.slave?
#return self if self != @@DEFAULT_MASTER
if self != @@DEFAULT_MASTER
@@ -2746,9 +2843,10 @@ class MultiTkIp
i = -1
brace = 1
str.each_byte {|c|
+ c = c.chr
i += 1
- brace += 1 if c == ?{
- brace -= 1 if c == ?}
+ brace += 1 if c == '{'
+ brace -= 1 if c == '}'
break if brace == 0
}
if i == 0
@@ -3187,15 +3285,44 @@ end
# encoding convert
+class << MultiTkIp
+ def encoding_table
+ __getip.encoding_table
+ end
+end
class MultiTkIp
- def encoding
+ def encoding_table
+ @interp.encoding_table
+ end
+
+ def force_default_encoding=(mode)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp.encoding
+ @interp.force_default_encoding = mode
end
+ def force_default_encoding?
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.force_default_encoding?
+ end
+
+ def default_encoding=(enc)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.default_encoding = enc
+ end
+
def encoding=(enc)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.encoding = enc
end
+ def encoding_name
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.encoding_name
+ end
+ def encoding_obj
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.encoding_obj
+ end
+ alias encoding encoding_name
+ alias default_encoding encoding_name
def encoding_convertfrom(str, enc=None)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@@ -3212,13 +3339,30 @@ end
# remove methods for security
+if MultiTkIp::WITH_RUBY_VM &&
+ ! MultiTkIp::RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!!
+ class MultiTkIp
+ INTERP_THREAD = @@DEFAULT_MASTER.instance_variable_get('@interp_thread')
+ INTERP_MUTEX = INTERP_THREAD[:mutex]
+ INTERP_ROOT_CHECK = INTERP_THREAD[:root_check]
+ end
+ module TkCore
+ INTERP_THREAD = MultiTkIp::INTERP_THREAD
+ INTERP_MUTEX = MultiTkIp::INTERP_MUTEX
+ INTERP_ROOT_CHECK = MultiTkIp::INTERP_ROOT_CHECK
+ end
+ class MultiTkIp
+ remove_const(:INTERP_THREAD)
+ remove_const(:INTERP_MUTEX)
+ remove_const(:INTERP_ROOT_CHECK)
+ end
+end
+
class MultiTkIp
# undef_method :instance_eval
undef_method :instance_variable_get
undef_method :instance_variable_set
end
-
-
# end of MultiTkIp definition
# defend against modification
diff --git a/ext/tk/lib/tcltk.rb b/ext/tk/lib/tcltk.rb
index 1a6694dbff..7f6f41605d 100644
--- a/ext/tk/lib/tcltk.rb
+++ b/ext/tk/lib/tcltk.rb
@@ -265,7 +265,7 @@ class TclTkWidget < TclTkCommand
# (used in TclTkInterpreter#initialize())
# need two arguments
- fail("illegal # of parameter") if args.size != 2
+ fail("invalid # of parameter") if args.size != 2
# ip: interpreter(TclTkIp)
# exp: tcl/tk representation
diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb
index eba2f72f29..c5d5b804d2 100644
--- a/ext/tk/lib/tk.rb
+++ b/ext/tk/lib/tk.rb
@@ -1,6 +1,5 @@
#
# tk.rb - Tk interface module using tcltklib
-# $Date: 2006/07/14 04:10:49 $
# by Yukihiro Matsumoto <matz@netlab.jp>
# use Shigehiro's tcltklib
@@ -10,6 +9,9 @@ require 'tkutil'
# autoload
require 'tk/autoload'
+# for Mutex
+require 'thread'
+
class TclTkIp
# backup original (without encoding) _eval and _invoke
alias _eval_without_enc _eval
@@ -37,7 +39,12 @@ module TkComm
#Tk_CMDTBL = {}
#Tk_WINDOWS = {}
- Tk_IDs = ["00000".taint, "00000".taint].freeze # [0]-cmdid, [1]-winid
+ Tk_IDs = ["00000".taint, "00000".taint] # [0]-cmdid, [1]-winid
+ Tk_IDs.instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
# for backward compatibility
Tk_CMDTBL = Object.new
@@ -218,7 +225,9 @@ module TkComm
TkCore::INTERP.tk_windows[val]?
TkCore::INTERP.tk_windows[val] : _genobj_for_tkwidget(val)
when /\Ai(_\d+_)?\d+\z/
- TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
+ TkImage::Tk_IMGTBL.mutex.synchronize{
+ TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
+ }
when /\A-?\d+\.?\d*(e[-+]?\d+)?\z/
val.to_f
when /\\ /
@@ -335,6 +344,8 @@ if USE_TCLs_LIST_FUNCTIONS
if dst_enc != true && dst_enc != false
if (s_enc = s.instance_variable_get(:@encoding))
s_enc = s_enc.to_s
+ elsif TkCore::WITH_ENCODING
+ s_enc = s.encoding.name
else
s_enc = sys_enc
end
@@ -347,11 +358,20 @@ if USE_TCLs_LIST_FUNCTIONS
if sys_enc && dst_enc
dst.map!{|s| _toUTF8(s)}
ret = TkCore::INTERP._merge_tklist(*dst)
- if dst_enc.kind_of?(String)
- ret = _fromUTF8(ret, dst_enc)
- ret.instance_variable_set(:@encoding, dst_enc)
- else
- ret.instance_variable_set(:@encoding, 'utf-8')
+ if TkCore::WITH_ENCODING
+ if dst_enc.kind_of?(String)
+ ret = _fromUTF8(ret, dst_enc)
+ ret.force_encoding(dst_enc)
+ else
+ ret.force_encoding('utf-8')
+ end
+ else # without encoding
+ if dst_enc.kind_of?(String)
+ ret = _fromUTF8(ret, dst_enc)
+ ret.instance_variable_set(:@encoding, dst_enc)
+ else
+ ret.instance_variable_set(:@encoding, 'utf-8')
+ end
end
ret
else
@@ -411,46 +431,6 @@ else
tk_split_sublist(token, depth - 1)
}
end
-=begin
- def tk_split_list(str)
- return [] if str == ""
- idx = str.index('{')
- while idx and idx > 0 and str[idx-1] == ?\\
- idx = str.index('{', idx+1)
- end
- unless idx
- list = tk_tcl2ruby(str)
- unless Array === list
- list = [list]
- end
- return list
- end
-
- list = tk_tcl2ruby(str[0,idx])
- list = [] if list == ""
- str = str[idx+1..-1]
- i = -1
- escape = false
- brace = 1
- str.each_byte {|c|
- i += 1
- brace += 1 if c == ?{ && !escape
- brace -= 1 if c == ?} && !escape
- escape = (c == ?\\)
- break if brace == 0
- }
- if str.size == i + 1
- return tk_split_list(str[0, i])
- end
- if str[0, i] == ' '
- list.push ' '
- else
- list.push tk_split_list(str[0, i])
- end
- list += tk_split_list(str[i+1..-1])
- list
- end
-=end
def tk_split_simplelist(str, src_enc=true, dst_enc=true)
return [] if str == ""
@@ -601,7 +581,9 @@ end
end
def image_obj(val)
if val =~ /^i(_\d+_)?\d+$/
- TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
+ TkImage::Tk_IMGTBL.mutex.synchronize{
+ TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
+ }
else
val
end
@@ -783,15 +765,17 @@ end
id = "c" + TkCore::INTERP._ip_id_ + TkComm::Tk_IDs[0]
end
def _next_cmd_id
- id = _curr_cmd_id
- #Tk_IDs[0] += 1
- TkComm::Tk_IDs[0].succ!
- id
+ TkComm::Tk_IDs.mutex.synchronize{
+ id = _curr_cmd_id
+ #Tk_IDs[0] += 1
+ TkComm::Tk_IDs[0].succ!
+ id
+ }
end
private :_curr_cmd_id, :_next_cmd_id
module_function :_curr_cmd_id, :_next_cmd_id
- def install_cmd(cmd)
+ def TkComm.install_cmd(cmd, local_cmdtbl=nil)
return '' if cmd == ''
begin
ns = TkCore::INTERP._invoke_without_enc('namespace', 'current')
@@ -810,6 +794,15 @@ end
@cmdtbl = [] unless defined? @cmdtbl
@cmdtbl.taint unless @cmdtbl.tainted?
@cmdtbl.push id
+
+ if local_cmdtbl && local_cmdtbl.kind_of?(Array)
+ begin
+ local_cmdtbl << id
+ rescue Exception
+ # ignore
+ end
+ end
+
#return Kernel.format("rb_out %s", id);
if ns
'rb_out' << TkCore::INTERP._ip_id_ << ' ' << ns << ' ' << id
@@ -817,14 +810,30 @@ end
'rb_out' << TkCore::INTERP._ip_id_ << ' ' << id
end
end
- def uninstall_cmd(id)
+ def TkComm.uninstall_cmd(id, local_cmdtbl=nil)
#id = $1 if /rb_out\S* (c(_\d+_)?\d+)/ =~ id
id = $4 if id =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
+
+ if local_cmdtbl && local_cmdtbl.kind_of?(Array)
+ begin
+ local_cmdtbl.delete(id)
+ rescue Exception
+ # ignore
+ end
+ end
+ @cmdtbl.delete(id)
+
#Tk_CMDTBL.delete(id)
TkCore::INTERP.tk_cmd_tbl.delete(id)
end
# private :install_cmd, :uninstall_cmd
- module_function :install_cmd, :uninstall_cmd
+ # module_function :install_cmd, :uninstall_cmd
+ def install_cmd(cmd)
+ TkComm.install_cmd(cmd, @cmdtbl)
+ end
+ def uninstall_cmd(id)
+ TkComm.uninstall_cmd(id, @cmdtbl)
+ end
=begin
def install_win(ppath,name=nil)
@@ -856,8 +865,10 @@ end
return TkCore::INTERP.tk_windows[@path] = self
end
else
- name = "w" + TkCore::INTERP._ip_id_ + Tk_IDs[1]
- Tk_IDs[1].succ!
+ Tk_IDs.mutex.synchronize{
+ name = "w" + TkCore::INTERP._ip_id_ + Tk_IDs[1]
+ Tk_IDs[1].succ!
+ }
end
if !ppath or ppath == '.'
@path = '.' + name
@@ -936,7 +947,12 @@ module TkComm
def _bindinfo(what, context=nil)
if context
- tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"]) .collect {|cmdline|
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ enum_obj = tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"]).each_line
+ else
+ enum_obj = tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"])
+ end
+ enum_obj.collect {|cmdline|
=begin
if cmdline =~ /^rb_out\S* (c(?:_\d+_)?\d+)\s+(.*)$/
#[Tk_CMDTBL[$1], $2]
@@ -1082,6 +1098,14 @@ module TkCore
include TkComm
extend TkComm
+ WITH_RUBY_VM = Object.const_defined?(:VM) && ::VM.class == Class
+ WITH_ENCODING = Object.const_defined?(:Encoding) && ::Encoding.class == Class
+
+ unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD
+ ### Ruby 1.9 !!!!!!!!!!!!!!!!!!!!!!!!!!
+ RUN_EVENTLOOP_ON_MAIN_THREAD = false
+ end
+
unless self.const_defined? :INTERP
if self.const_defined? :IP_NAME
name = IP_NAME.to_s
@@ -1099,14 +1123,49 @@ module TkCore
opts = ''
end
- INTERP = TclTkIp.new(name, opts)
+ if !WITH_RUBY_VM || RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!!
+ INTERP = TclTkIp.new(name, opts)
+ else
+ INTERP_MUTEX = Mutex.new
+ INTERP_ROOT_CHECK = ConditionVariable.new
+ INTERP_THREAD = Thread.new{
+ begin
+ Thread.current[:interp] = interp = TclTkIp.new(name, opts)
+ rescue => e
+ Thread.current[:interp] = e
+ raise e
+ end
+ Thread.current[:status] = nil
+ #sleep
+
+ begin
+ Thread.current[:status] = TclTkLib.mainloop(true)
+ rescue Exception=>e
+ Thread.current[:status] = e
+ ensure
+ INTERP_MUTEX.synchronize{ INTERP_ROOT_CHECK.broadcast }
+ end
+ Thread.current[:status] = TclTkLib.mainloop(false)
+ }
+
+ until INTERP_THREAD[:interp]
+ Thread.pass
+ end
+ # INTERP_THREAD.run
+ raise INTERP_THREAD[:interp] if INTERP_THREAD[:interp].kind_of? Exception
+
+ INTERP = INTERP_THREAD[:interp]
+ end
def INTERP.__getip
self
end
INTERP.instance_eval{
- @tk_cmd_tbl = {}.taint
+ # @tk_cmd_tbl = {}.taint
+ @tk_cmd_tbl = Hash.new{|hash, key|
+ fail IndexError, "unknown command ID '#{key}'"
+ }.taint
def @tk_cmd_tbl.[]=(idx,val)
if self.has_key?(idx) && Thread.current.group != ThreadGroup::Default
fail SecurityError,"cannot change the entried command"
@@ -1157,6 +1216,10 @@ module TkCore
class Tk_OBJECT_TABLE
def initialize(id)
@id = id
+ @mutex = Mutex.new
+ end
+ def mutex
+ @mutex
end
def method_missing(m, *args, &b)
TkCore::INTERP.tk_object_table(@id).__send__(m, *args, &b)
@@ -1235,7 +1298,7 @@ module TkCore
}) << ' %W')
INTERP.add_tk_procs(TclTkLib::FINALIZE_PROC_NAME, '',
- "bind all <#{WIDGET_DESTROY_HOOK}> {}")
+ "catch { bind all <#{WIDGET_DESTROY_HOOK}> {} }")
INTERP.add_tk_procs('rb_out', 'ns args', <<-'EOL')
if [regexp {^::} $ns] {
@@ -1342,7 +1405,11 @@ module TkCore
"\n---< backtrace of Ruby side >-----\n" +
_toUTF8(e.backtrace.join("\n")) +
"\n---< backtrace of Tk side >-------"
- msg.instance_variable_set(:@encoding, 'utf-8')
+ if TkCore::WITH_ENCODING
+ msg.force_encoding('utf-8')
+ else
+ msg.instance_variable_set(:@encoding, 'utf-8')
+ end
rescue Exception
msg = e.class.inspect + ': ' + e.message + "\n" +
"\n---< backtrace of Ruby side >-----\n" +
@@ -1398,6 +1465,13 @@ module TkCore
end
def after(ms, cmd=Proc.new)
+ cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(cmdid); ret})
+ after_id = tk_call_without_enc("after",ms,cmdid)
+ after_id.instance_variable_set('@cmdid', cmdid)
+ after_id
+ end
+=begin
+ def after(ms, cmd=Proc.new)
crit_bup = Thread.critical
Thread.critical = true
@@ -1420,8 +1494,16 @@ module TkCore
# tk_call("after",ms,cmdid)
# end
end
+=end
def after_idle(cmd=Proc.new)
+ cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(cmdid); ret})
+ after_id = tk_call_without_enc('after','idle',cmdid)
+ after_id.instance_variable_set('@cmdid', cmdid)
+ after_id
+ end
+=begin
+ def after_idle(cmd=Proc.new)
crit_bup = Thread.critical
Thread.critical = true
@@ -1432,9 +1514,15 @@ module TkCore
tk_call_without_enc('after','idle',cmdid)
end
+=end
def after_cancel(afterId)
tk_call_without_enc('after','cancel',afterId)
+ if (cmdid = afterId.instance_variable_get('@cmdid'))
+ afterId.instance_variable_set('@cmdid', nil)
+ uninstall_cmd(cmdid)
+ end
+ afterId
end
def windowingsystem
@@ -1554,7 +1642,27 @@ module TkCore
end
def mainloop(check_root = true)
- TclTkLib.mainloop(check_root)
+ if !TkCore::WITH_RUBY_VM || TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD
+ TclTkLib.mainloop(check_root)
+ else ### Ruby 1.9 !!!!!
+ begin
+ TclTkLib.set_eventloop_window_mode(true)
+ if check_root
+ INTERP_MUTEX.synchronize{
+ INTERP_ROOT_CHECK.wait(INTERP_MUTEX)
+ status = INTERP_THREAD[:status]
+ if status
+ INTERP_THREAD[:status] = nil
+ raise status if status.kind_of?(Exception)
+ end
+ }
+ else
+ INTERP_THREAD.value
+ end
+ ensure
+ TclTkLib.set_eventloop_window_mode(false)
+ end
+ end
end
def mainloop_thread?
@@ -1562,7 +1670,12 @@ module TkCore
# nil : there is no mainloop
# false : mainloop is running on the other thread
# ( At then, it is dangerous to call Tk interpreter directly. )
- TclTkLib.mainloop_thread?
+ if !TkCore::WITH_RUBY_VM || TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD
+ ### Ruby 1.9 !!!!!!!!!!!
+ TclTkLib.mainloop_thread?
+ else
+ Thread.current == INTERP_THREAD
+ end
end
def mainloop_exist?
@@ -1914,7 +2027,7 @@ module Tk
end
def root
- TkRoot.new
+ Tk::Root.new
end
def Tk.load_tclscript(file, enc=nil)
@@ -2030,6 +2143,27 @@ module Tk
tk_call_without_enc('destroy', '.')
end
+ ################################################
+
+ def Tk.sleep(ms = nil, id = nil)
+ if id
+ var = (id.kind_of?(TkVariable))? id: TkVarAccess.new(id.to_s)
+ else
+ var = TkVariable.new
+ end
+
+ var.value = tk_call_without_enc('after', ms, proc{ var.value = 0 }) if ms
+ var.thread_wait
+ ms
+ end
+
+ def Tk.wakeup(id)
+ ((id.kind_of?(TkVariable))? id: TkVarAccess.new(id.to_s)).value = 0
+ nil
+ end
+
+ ################################################
+
def Tk.pack(*args)
TkPack.configure(*args)
end
@@ -2205,16 +2339,432 @@ end
# convert kanji string to/from utf-8
###########################################
if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
+ module Tk
+ module Encoding
+ extend Encoding
+
+ TkCommandNames = ['encoding'.freeze].freeze
+
+ #############################################
+
+ if TkCore::WITH_ENCODING ### Ruby 1.9
+ RubyEncoding = ::Encoding
+
+ # for saving GC cost
+ #ENCNAMES_CMD = ['encoding'.freeze, 'names'.freeze]
+ BINARY_NAME = 'binary'.freeze
+ UTF8_NAME = 'utf-8'.freeze
+ DEFAULT_EXTERNAL_NAME = RubyEncoding.default_external.name.freeze
+
+ BINARY = RubyEncoding.find(BINARY_NAME)
+ UNKNOWN = RubyEncoding.find('ASCII-8BIT')
+
+ ### start of creating ENCODING_TABLE
+ ENCODING_TABLE = TkCore::INTERP.encoding_table
+=begin
+ ENCODING_TABLE = {
+ 'binary' => BINARY,
+ # 'UNKNOWN-8BIT' => UNKNOWN,
+ }
+
+ list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0],
+ ENCNAMES_CMD[1])
+ TkCore::INTERP._split_tklist(list).each{|name|
+ begin
+ enc = RubyEncoding.find(name)
+ rescue ArgumentError
+ case name
+ when 'identity'
+ enc = BINARY
+ when 'shiftjis'
+ enc = RubyEncoding.find('Shift_JIS')
+ when 'unicode'
+ enc = RubyEncoding.find('UTF-8')
+ #if Tk.tk_call('set', 'tcl_platform(byteOrder)') =='littleEndian'
+ # enc = RubyEncoding.find('UTF-16LE')
+ #else
+ # enc = RubyEncoding.find('UTF-16BE')
+ #end
+ when 'symbol'
+ # single byte data
+ enc = RubyEncoding.find('ASCII-8BIT') ### ???
+ else
+ # unsupported on Ruby, but supported on Tk
+ enc = TkCore::INTERP.create_dummy_encoding_for_tk(name)
+ end
+ end
+ ENCODING_TABLE[name.freeze] = enc
+ }
+=end
+=begin
+ def ENCODING_TABLE.get_name(enc)
+ orig_enc = enc
+
+ # unles enc, use system default
+ # 1st: Ruby/Tk default encoding
+ # 2nd: Tcl/Tk default encoding
+ # 3rd: Ruby's default_external
+ enc ||= TkCore::INTERP.encoding
+ enc ||= TclTkLib.encoding_system
+ enc ||= DEFAULT_EXTERNAL_NAME
+
+ if enc.kind_of?(RubyEncoding)
+ # Ruby's Encoding object
+ if (name = self.key(enc))
+ return name
+ end
+
+ # Is it new ?
+ list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0],
+ ENCNAMES_CMD[1])
+ TkComm.simplelist(list).each{|name|
+ if ((enc == RubyEncoding.find(name)) rescue false)
+ # new relation!! update table
+ self[name.freeze] = enc
+ return name
+ end
+ }
+ else
+ # String or Symbol ?
+ if self[name = enc.to_s]
+ return name
+ end
+
+ # Is it new ?
+ if (enc_obj = (RubyEncoding.find(name) rescue false))
+ list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0],
+ ENCNAMES_CMD[1])
+ if TkComm.simplelist(list).index(name)
+ # Tk's encoding name ?
+ self[name.freeze] = enc_obj # new relation!! update table
+ return name
+ else
+ # Ruby's encoding name ?
+ if (name = self.key(enc_obj))
+ return name
+ end
+ end
+ end
+ end
+
+ fail ArgumentError, "unsupported Tk encoding '#{orig_enc}'"
+ end
+
+ def ENCODING_TABLE.get_obj(enc)
+ # returns the encoding object.
+ # If 'enc' is the encoding name on Tk only, it returns nil.
+ ((obj = self[self.get_name(enc)]).kind_of?(RubyEncoding))? obj: nil
+ end
+=end
+ ### end of creating ENCODING_TABLE
+
+ end
+
+ #############################################
+
+ if TkCore::WITH_ENCODING
+ ################################
+ ### Ruby 1.9
+ ################################
+ def force_default_encoding(mode)
+ TkCore::INTERP.force_default_encoding = mode
+ end
+
+ def force_default_encoding?
+ TkCore::INTERP.force_default_encoding?
+ end
+
+ def default_encoding=(enc)
+ TkCore::INTERP.default_encoding = Tk::Encoding::ENCODING_TABLE.get_name(enc)
+ end
+
+ def encoding=(enc)
+ TkCore::INTERP.encoding = Tk::Encoding::ENCODING_TABLE.get_name(enc)
+ end
+
+ def encoding_name
+ Tk::Encoding::ENCODING_TABLE.get_name(TkCore::INTERP.encoding)
+ end
+ def encoding_obj
+ Tk::Encoding::ENCODING_TABLE.get_obj(TkCore::INTERP.encoding)
+ end
+ alias encoding encoding_name
+ alias default_encoding encoding_name
+
+ def tk_encoding_names
+ TkComm.simplelist(TkCore::INTERP._invoke_without_enc(Tk::Encoding::ENCNAMES_CMD[0], Tk::Encoding::ENCNAMES_CMD[1]))
+ end
+ def encoding_names
+ self.tk_encoding_names.find_all{|name|
+ Tk::Encoding::ENCODING_TABLE.get_name(name) rescue false
+ }
+ end
+ def encoding_objs
+ self.tk_encoding_names.map!{|name|
+ Tk::Encoding::ENCODING_TABLE.get_obj(name) rescue nil
+ }.compact
+ end
+
+ def encoding_system=(enc)
+ TclTkLib.encoding_system = Tk::Encoding::ENCODING_TABLE.get_name(enc)
+ end
+
+ def encoding_system_name
+ Tk::Encoding::ENCODING_TABLE.get_name(TclTkLib.encoding_system)
+ end
+ def encoding_system_obj
+ Tk::Encoding::ENCODING_TABLE.get_obj(TclTkLib.encoding_system)
+ end
+ alias encoding_system encoding_system_name
+
+ ################################
+ else
+ ################################
+ ### Ruby 1.8-
+ ################################
+ def force_default_encoding=(mode)
+ true
+ end
+
+ def force_default_encoding?
+ true
+ end
+
+ def default_encoding=(enc)
+ TkCore::INTERP.default_encoding = enc
+ end
+
+ def encoding=(enc)
+ TkCore::INTERP.encoding = enc
+ end
+
+ def encoding_obj
+ TkCore::INTERP.encoding
+ end
+ def encoding_name
+ TkCore::INTERP.encoding
+ end
+ alias encoding encoding_name
+ alias default_encoding encoding_name
+
+ def tk_encoding_names
+ TkComm.simplelist(Tk.tk_call('encoding', 'names'))
+ end
+ def encoding_objs
+ self.tk_encoding_names
+ end
+ def encoding_names
+ self.tk_encoding_names
+ end
+
+ def encoding_system=(enc)
+ TclTkLib.encoding_system = enc
+ end
+
+ def encoding_system_name
+ TclTkLib.encoding_system
+ end
+ def encoding_system_obj
+ TclTkLib.encoding_system
+ end
+ alias encoding_system encoding_system_name
+
+ ################################
+ end
+
+ def encoding_convertfrom(str, enc=nil)
+ enc = encoding_system_name unless enc
+ str = str.dup
+ if TkCore::WITH_ENCODING
+ if str.kind_of?(Tk::EncodedString)
+ str.__instance_variable_set('@encoding', nil)
+ else
+ str.instance_variable_set('@encoding', nil)
+ end
+ str.force_encoding('binary')
+ else
+ str.instance_variable_set('@encoding', 'binary')
+ end
+ ret = TkCore::INTERP._invoke_without_enc('encoding', 'convertfrom',
+ enc, str)
+ if TkCore::WITH_ENCODING
+ ret.force_encoding('utf-8')
+ else
+ Tk::UTF8_String.new(ret)
+ end
+ ret
+ end
+ alias encoding_convert_from encoding_convertfrom
+
+ def encoding_convertto(str, enc=nil)
+ # str must be a UTF-8 string
+ enc = encoding_system_name unless enc
+ ret = TkCore::INTERP._invoke_without_enc('encoding', 'convertto',
+ enc, str)
+ #ret.instance_variable_set('@encoding', 'binary')
+ if TkCore::WITH_ENCODING
+ #ret.force_encoding(Tk::Encoding::ENCODING_TABLE.get_obj('binary'))
+ ret.force_encoding(Tk::Encoding::ENCODING_TABLE.get_obj(enc))
+ end
+ ret
+ end
+ alias encoding_convert_to encoding_convertto
+
+ def encoding_dirs
+ # Tcl8.5 feature
+ TkComm.simplelist(Tk.tk_call_without_enc('encoding', 'dirs'))
+ end
+
+ def encoding_dirs=(dir_list) # an array or a Tcl's list string
+ # Tcl8.5 feature
+ Tk.tk_call_without_enc('encoding', 'dirs', dir_list)
+ end
+ end
+
+ extend Encoding
+ end
+
class TclTkIp
+ def force_default_encoding=(mode)
+ @force_default_encoding = (mode)? true: false
+ end
+
+ def force_default_encoding?
+ @force_default_encoding ||= false
+ end
+
+ def default_encoding=(name)
+ name = name.name if name.kind_of?(::Encoding) if Tk::WITH_ENCODING
+ @encoding = name
+ end
+
# from tkencoding.rb by ttate@jaist.ac.jp
- attr_accessor :encoding
+ #attr_accessor :encoding
+ def encoding=(name)
+ self.force_default_encoding = true # for comaptibility
+ self.default_encoding = name
+ end
- alias __eval _eval
- alias __invoke _invoke
+ def encoding_name
+ (@encoding)? @encoding.dup: nil
+ end
+ alias encoding encoding_name
+ alias default_encoding encoding_name
+
+ def encoding_obj
+ if Tk::WITH_ENCODING
+ Tk::Encoding.tcl2rb_encoding(@encoding)
+ else
+ (@encoding)? @encoding.dup: nil
+ end
+ end
alias __toUTF8 _toUTF8
alias __fromUTF8 _fromUTF8
+ if Object.const_defined?(:Encoding) && ::Encoding.class == Class
+ # with Encoding (Ruby 1.9+)
+ #
+ # use functions on Tcl as default.
+ # but when unsupported encoding on Tcl, use methods on Ruby.
+ #
+ def _toUTF8(str, enc = nil)
+ if enc
+ # use given encoding
+ begin
+ enc_name = Tk::Encoding::ENCODING_TABLE.get_name(enc)
+ rescue
+ # unknown encoding for Tk -> try to convert encoding on Ruby
+ str = str.dup.force_encoding(enc)
+ str.encode!(Tk::Encoding::UTF8_NAME) # modify self !!
+ return str # if no error, probably succeed converting
+ end
+ end
+
+ enc_name ||= str.instance_variable_get(:@encoding)
+
+ enc_name ||=
+ Tk::Encoding::ENCODING_TABLE.get_name(str.encoding) rescue nil
+
+ unless enc_name
+ # str.encoding isn't supported by Tk -> try to convert on Ruby
+ begin
+ return str.encode(Tk::Encoding::UTF8_NAME) # new string
+ rescue
+ # error -> ignore, try to use default encoding of Ruby/Tk
+ end
+ end
+
+ #enc_name ||=
+ # Tk::Encoding::ENCODING_TABLE.get_name(Tk.encoding) rescue nil
+ enc_name ||= Tk::Encoding::ENCODING_TABLE.get_name(nil)
+
+ # is 'binary' encoding?
+ if enc_name == Tk::Encoding::BINARY_NAME
+ return str.dup.force_encoding(Tk::Encoding::BINARY_NAME)
+ end
+
+ # force default encoding?
+ if ! str.kind_of?(Tk::EncodedString) && self.force_default_encoding?
+ enc_name = Tk::Encoding::ENCODING_TABLE.get_name(Tk.default_encoding)
+ end
+
+ encstr = __toUTF8(str, enc_name)
+ encstr.force_encoding(Tk::Encoding::UTF8_NAME)
+ encstr
+ end
+ def _fromUTF8(str, enc = nil)
+ # str must be UTF-8 or binary.
+ enc_name = str.instance_variable_get(:@encoding)
+ enc_name ||=
+ Tk::Encoding::ENCODING_TABLE.get_name(str.encoding) rescue nil
+
+ # is 'binary' encoding?
+ if enc_name == Tk::Encoding::BINARY_NAME
+ return str.dup.force_encoding(Tk::Encoding::BINARY_NAME)
+ end
+
+ # get target encoding name (if enc == nil, use default encoding)
+ begin
+ enc_name = Tk::Encoding::ENCODING_TABLE.get_name(enc)
+ rescue
+ # then, enc != nil
+ # unknown encoding for Tk -> try to convert encoding on Ruby
+ str = str.dup.force_encoding(Tk::Encoding::UTF8_NAME)
+ str.encode!(enc) # modify self !!
+ return str # if no error, probably succeed converting
+ end
+
+ encstr = __fromUTF8(str, enc_name)
+ encstr.force_encoding(Tk::Encoding::ENCODING_TABLE.get_obj(enc_name))
+ encstr
+ end
+ ###
+ else
+ # without Encoding (Ruby 1.8)
+ def _toUTF8(str, encoding = nil)
+ __toUTF8(str, encoding)
+ end
+ def _fromUTF8(str, encoding = nil)
+ __fromUTF8(str, encoding)
+ end
+ ###
+ end
+
+ alias __eval _eval
+ alias __invoke _invoke
+
+ def _eval(cmd)
+ _fromUTF8(__eval(_toUTF8(cmd)))
+ end
+
+ def _invoke(*cmds)
+ _fromUTF8(__invoke(*(cmds.collect{|cmd| _toUTF8(cmd)})))
+ end
+
+ alias _eval_with_enc _eval
+ alias _invoke_with_enc _invoke
+
=begin
#### --> definition is moved to TclTkIp module
@@ -2264,17 +2814,6 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
end
=end
- def _eval(cmd)
- _fromUTF8(__eval(_toUTF8(cmd)))
- end
-
- def _invoke(*cmds)
- _fromUTF8(__invoke(*(cmds.collect{|cmd| _toUTF8(cmd)})))
- end
-
- alias _eval_with_enc _eval
- alias _invoke_with_enc _invoke
-
=begin
def _eval(cmd)
if defined?(@encoding) && @encoding != 'utf-8'
@@ -2331,127 +2870,214 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
module TclTkLib
class << self
- alias _encoding encoding
- alias _encoding= encoding=
- def encoding=(name)
- TkCore::INTERP.encoding = name
+ def force_default_encoding=(mode)
+ TkCore::INTERP.force_default_encoding = mode
end
- def encoding
- TkCore::INTERP.encoding
- end
- end
- end
- module Tk
- module Encoding
- extend Encoding
+ def force_default_encoding?
+ TkCore::INTERP.force_default_encoding?
+ end
- TkCommandNames = ['encoding'.freeze].freeze
+ def default_encoding=(name)
+ TkCore::INTERP.default_encoding = name
+ end
+ alias _encoding encoding
+ alias _encoding= encoding=
def encoding=(name)
+ name = name.name if name.kind_of?(::Encoding) if Tk::WITH_ENCODING
TkCore::INTERP.encoding = name
end
- def encoding
+ def encoding_name
TkCore::INTERP.encoding
end
+ alias encoding encoding_name
+ alias default_encoding encoding_name
- def encoding_names
- TkComm.simplelist(Tk.tk_call('encoding', 'names'))
+ def encoding_obj
+ if Tk::WITH_ENCODING
+ Tk::Encoding.tcl2rb_encoding(TkCore::INTERP.encoding)
+ else
+ TkCore::INTERP.encoding
+ end
end
+ end
+ end
- def encoding_system
- Tk.tk_call('encoding', 'system')
+ # estimate encoding
+ unless TkCore::WITH_ENCODING
+ case $KCODE
+ when /^e/i # EUC
+ Tk.encoding = 'euc-jp'
+ Tk.encoding_system = 'euc-jp'
+ when /^s/i # SJIS
+ begin
+ if Tk.encoding_system == 'cp932'
+ Tk.encoding = 'cp932'
+ else
+ Tk.encoding = 'shiftjis'
+ Tk.encoding_system = 'shiftjis'
+ end
+ rescue StandardError, NameError
+ Tk.encoding = 'shiftjis'
+ Tk.encoding_system = 'shiftjis'
end
-
- def encoding_system=(enc)
- Tk.tk_call('encoding', 'system', enc)
+ when /^u/i # UTF8
+ Tk.encoding = 'utf-8'
+ Tk.encoding_system = 'utf-8'
+ else # NONE
+ if defined? DEFAULT_TK_ENCODING
+ Tk.encoding_system = DEFAULT_TK_ENCODING
end
-
- def encoding_convertfrom(str, enc=nil)
- # str is an usual enc string or a Tcl's internal string expression
- # in enc (which is returned from 'encoding_convertto' method).
- # the return value is a UTF-8 string.
- enc = encoding_system unless enc
- ret = TkCore::INTERP.__invoke('encoding', 'convertfrom', enc, str)
- ret.instance_variable_set('@encoding', 'utf-8')
- ret
+ begin
+ Tk.encoding = Tk.encoding_system
+ rescue StandardError, NameError
+ Tk.encoding = 'utf-8'
+ Tk.encoding_system = 'utf-8'
end
- alias encoding_convert_from encoding_convertfrom
+ end
- def encoding_convertto(str, enc=nil)
- # str must be a UTF-8 string.
- # The return value is a Tcl's internal string expression in enc.
- # To get an usual enc string, use Tk.fromUTF8(ret_val, enc).
- enc = encoding_system unless enc
- ret = TkCore::INTERP.__invoke('encoding', 'convertto', enc, str)
- ret.instance_variable_set('@encoding', 'binary')
- ret
- end
- alias encoding_convert_to encoding_convertto
+ else ### Ruby 1.9 !!!!!!!!!!!!
+ loc_enc_obj = ::Encoding.find(::Encoding.locale_charmap)
+ ext_enc_obj = ::Encoding.default_external
+ tksys_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(Tk.encoding_system)
+ # p [Tk.encoding, Tk.encoding_system, loc_enc_obj, ext_enc_obj]
- def encoding_dirs
- # Tcl8.5 feature
- TkComm.simplelist(Tk.tk_call_without_enc('encoding', 'dirs'))
+=begin
+ if ext_enc_obj == Tk::Encoding::UNKNOWN
+ if defind? DEFAULT_TK_ENCODING
+ if DEFAULT_TK_ENCODING.kind_of?(::Encoding)
+ tk_enc_name = DEFAULT_TK_ENCODING.name
+ tksys_enc_name = DEFAULT_TK_ENCODING.name
+ else
+ tk_enc_name = DEFAULT_TK_ENCODING
+ tksys_enc_name = DEFAULT_TK_ENCODING
+ end
+ else
+ tk_enc_name = loc_enc_obj.name
+ tksys_enc_name = loc_enc_obj.name
end
+ else
+ tk_enc_name = ext_enc_obj.name
+ tksys_enc_name = ext_enc_obj.name
+ end
- def encoding_dirs=(dir_list) # an array or a Tcl's list string
- # Tcl8.5 feature
- Tk.tk_call_without_enc('encoding', 'dirs', dir_list)
+ # Tk.encoding = tk_enc_name
+ Tk.default_encoding = tk_enc_name
+ Tk.encoding_system = tksys_enc_name
+=end
+
+ if ext_enc_obj == Tk::Encoding::UNKNOWN
+ if loc_enc_obj == Tk::Encoding::UNKNOWN
+ # use Tk.encoding_system
+ else
+ # 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
+ # use locale_charmap
+ Tk.encoding_system = loc_enc_name
+ else
+ # use Tk.encoding_system
+ end
+ rescue ArgumentError
+ # unsupported encoding on Tk -> use Tk.encoding_system
+ end
+ 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
+ # use default_external
+ Tk.encoding_system = ext_enc_name
+ else
+ # use Tk.encoding_system
+ end
+ rescue ArgumentError
+ # unsupported encoding on Tk -> use Tk.encoding_system
end
end
- extend Encoding
- end
+ # setup Tk.encoding
+ enc_name = nil
- # estimate encoding
- case $KCODE
- when /^e/i # EUC
- Tk.encoding = 'euc-jp'
- Tk.encoding_system = 'euc-jp'
- when /^s/i # SJIS
begin
- if Tk.encoding_system == 'cp932'
- Tk.encoding = 'cp932'
- else
- Tk.encoding = 'shiftjis'
- Tk.encoding_system = 'shiftjis'
+ default_def = DEFAULT_TK_ENCODING
+ if ::Encoding.find(default_def.to_s) != Tk::Encoding::UNKNOWN
+ enc_name = Tk::Encoding::ENCODING_TABLE.get_name(default_def)
end
- rescue StandardError, NameError
- Tk.encoding = 'shiftjis'
- Tk.encoding_system = 'shiftjis'
- end
- when /^u/i # UTF8
- Tk.encoding = 'utf-8'
- Tk.encoding_system = 'utf-8'
- else # NONE
- if defined? DEFAULT_TK_ENCODING
- Tk.encoding_system = DEFAULT_TK_ENCODING
+ rescue NameError
+ # ignore
+ enc_name = nil
+ rescue ArgumentError
+ enc_name = nil
+ fail ArgumentError,
+ "DEFAULT_TK_ENCODING has an unknown encoding #{default_def}"
end
- begin
- Tk.encoding = Tk.encoding_system
- rescue StandardError, NameError
- Tk.encoding = 'utf-8'
- Tk.encoding_system = 'utf-8'
+
+ unless enc_name
+ if ext_enc_obj == Tk::Encoding::UNKNOWN
+ if loc_enc_obj == Tk::Encoding::UNKNOWN
+ # use Tk.encoding_system
+ enc_name = tksys_enc_name
+ else
+ # 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
+ # use locale_charmap
+ enc_name = loc_enc_name
+ else
+ # use Tk.encoding_system
+ enc_name = tksys_enc_name
+ end
+ rescue ArgumentError
+ # unsupported encoding on Tk -> use Tk.encoding_system
+ enc_name = tksys_enc_name
+ end
+ 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
+ # use default_external
+ enc_name = ext_enc_name
+ else
+ # use Tk.encoding_system
+ enc_name = tksys_enc_name
+ end
+ rescue ArgumentError
+ # unsupported encoding on Tk -> use Tk.encoding_system
+ enc_name = tksys_enc_name
+ end
+ end
end
+
+ Tk.default_encoding = (enc_name)? enc_name: tksys_enc_name
end
else
# dummy methods
- class TclTkIp
- attr_accessor :encoding
-
- alias __eval _eval
- alias __invoke _invoke
-
- alias _eval_with_enc _eval
- alias _invoke_with_enc _invoke
- end
-
module Tk
module Encoding
extend Encoding
+ def force_default_encoding=(mode)
+ nil
+ end
+
+ def force_default_encoding?
+ nil
+ end
+
+ def default_encoding=(enc)
+ nil
+ end
+ def default_encoding
+ nil
+ end
+
def encoding=(name)
nil
end
@@ -2487,6 +3113,16 @@ else
extend Encoding
end
+
+ class TclTkIp
+ attr_accessor :encoding
+
+ alias __eval _eval
+ alias __invoke _invoke
+
+ alias _eval_with_enc _eval
+ alias _invoke_with_enc _invoke
+ end
end
@@ -2609,7 +3245,15 @@ module TkTreatFont
next
else
fnt = hash_kv(fnt) if fnt.kind_of?(Hash)
- tk_call(*(__config_cmd << "-#{optkey}" << fnt))
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ tk_call(*(__config_cmd << "-#{optkey}" << fnt))
+ else
+ begin
+ tk_call(*(__config_cmd << "-#{optkey}" << fnt))
+ rescue
+ # ignore
+ end
+ end
end
end
next
@@ -2663,7 +3307,15 @@ module TkTreatFont
fobj = fontobj # create a new TkFont object
else
ltn = hash_kv(ltn) if ltn.kind_of?(Hash)
- tk_call(*(__config_cmd << "-#{optkey}" << ltn))
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ tk_call(*(__config_cmd << "-#{optkey}" << ltn))
+ else
+ begin
+ tk_call(*(__config_cmd << "-#{optkey}" << ltn))
+ rescue => e
+ # ignore
+ end
+ end
next
end
@@ -2715,7 +3367,15 @@ module TkTreatFont
fobj = fontobj # create a new TkFont object
else
knj = hash_kv(knj) if knj.kind_of?(Hash)
- tk_call(*(__config_cmd << "-#{optkey}" << knj))
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ tk_call(*(__config_cmd << "-#{optkey}" << knj))
+ else
+ begin
+ tk_call(*(__config_cmd << "-#{optkey}" << knj))
+ rescue => e
+ # ignore
+ end
+ end
next
end
@@ -2816,6 +3476,14 @@ module TkConfigMethod
include TkUtil
include TkTreatFont
+ def TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ @mode || false
+ end
+ def TkConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode)
+ fail SecurityError, "can't change the mode" if $SAFE>=4
+ @mode = (mode)? true: false
+ end
+
def __cget_cmd
[self.path, 'cget']
end
@@ -2829,7 +3497,7 @@ module TkConfigMethod
def __confinfo_cmd
__config_cmd
end
- private :__config_cmd
+ private :__confinfo_cmd
def __configinfo_struct
{:key=>0, :alias=>1, :db_name=>1, :db_class=>2,
@@ -2837,6 +3505,11 @@ module TkConfigMethod
end
private :__configinfo_struct
+ def __optkey_aliases
+ {}
+ end
+ private :__optkey_aliases
+
def __numval_optkeys
[]
end
@@ -2926,6 +3599,7 @@ module TkConfigMethod
}
keys2
end
+ private :__conv_keyonly_opts
def config_hash_kv(keys, enc_mode = nil, conf = nil)
hash_kv(__conv_keyonly_opts(keys), enc_mode, conf)
@@ -2942,7 +3616,7 @@ module TkConfigMethod
val
end
- def cget(slot)
+ def __cget_core(slot)
orig_slot = slot
slot = slot.to_s
@@ -2950,6 +3624,11 @@ module TkConfigMethod
fail ArgumentError, "Invalid option `#{orig_slot.inspect}'"
end
+ alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
if ( method = _symbolkey2str(__val2ruby_optkeys())[slot] )
optval = tk_call_without_enc(*(__cget_cmd << "-#{slot}"))
begin
@@ -3018,11 +3697,41 @@ module TkConfigMethod
tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{slot}")), true)
end
end
+ private :__cget_core
- def configure(slot, value=None)
+ def cget(slot)
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ __cget_core(slot)
+ else
+ begin
+ __cget_core(slot)
+ rescue => e
+ if current_configinfo.has_key?(slot.to_s)
+ # error on known option
+ fail e
+ else
+ # unknown option
+ nil
+ end
+ end
+ end
+ end
+ def cget_strict(slot)
+ # never use TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ __cget_core(slot)
+ end
+
+ def __configure_core(slot, value=None)
if slot.kind_of? Hash
slot = _symbolkey2str(slot)
+ __optkey_aliases.each{|alias_name, real_name|
+ alias_name = alias_name.to_s
+ if slot.has_key?(alias_name)
+ slot[real_name.to_s] = slot.delete(alias_name)
+ end
+ }
+
__methodcall_optkeys.each{|key, method|
value = slot.delete(key.to_s)
self.__send__(method, value) if value
@@ -3059,6 +3768,11 @@ module TkConfigMethod
fail ArgumentError, "Invalid option `#{orig_slot.inspect}'"
end
+ alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
if ( conf = __keyonly_optkeys.find{|k, v| k.to_s == slot} )
defkey, undefkey = conf
if value
@@ -3082,12 +3796,55 @@ module TkConfigMethod
end
self
end
+ private :__configure_core
+
+ def __check_available_configure_options(keys)
+ availables = self.current_configinfo.keys
+
+ # add non-standard keys
+ availables |= __font_optkeys.map{|k|
+ [k.to_s, "latin#{k}", "ascii#{k}", "kanji#{k}"]
+ }.flatten
+ availables |= __methodcall_optkeys.keys.map{|k| k.to_s}
+ availables |= __keyonly_optkeys.keys.map{|k| k.to_s}
+
+ keys = _symbolkey2str(keys)
+ keys.delete_if{|k, v| !(availables.include?(k))}
+ end
+
+ def configure(slot, value=None)
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ __configure_core(slot, value)
+ else
+ if slot.kind_of?(Hash)
+ begin
+ __configure_core(slot)
+ rescue
+ slot = __check_available_configure_options(slot)
+ __configure_core(slot) unless slot.empty?
+ end
+ else
+ begin
+ __configure_core(slot, value)
+ rescue => e
+ if current_configinfo.has_key?(slot.to_s)
+ # error on known option
+ fail e
+ else
+ # unknown option
+ nil
+ end
+ end
+ end
+ end
+ self
+ end
def configure_cmd(slot, value)
configure(slot, install_cmd(value))
end
- def configinfo(slot = nil)
+ def __configinfo_core(slot = nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
if (slot &&
slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/)
@@ -3098,6 +3855,10 @@ module TkConfigMethod
conf[__configinfo_struct[:key]][1..-1]
if ( ! __configinfo_struct[:alias] \
|| conf.size > __configinfo_struct[:alias] + 1 )
+ fnt = conf[__configinfo_struct[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ conf[__configinfo_struct[:default_value]] = TkNamedFont.new(fnt)
+ end
conf[__configinfo_struct[:current_value]] = fontobj(fontkey)
elsif ( __configinfo_struct[:alias] \
&& conf.size == __configinfo_struct[:alias] + 1 \
@@ -3109,6 +3870,12 @@ module TkConfigMethod
else
if slot
slot = slot.to_s
+
+ alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
case slot
when /^(#{__val2ruby_optkeys().keys.join('|')})$/
method = _symbolkey2str(__val2ruby_optkeys())[slot]
@@ -3434,6 +4201,11 @@ module TkConfigMethod
fontconf = ret.assoc(optkey)
if fontconf && fontconf.size > 2
ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/}
+ fnt = fontconf[__configinfo_struct[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ fontconf[__configinfo_struct[:default_value]] \
+ = TkNamedFont.new(fnt)
+ end
fontconf[__configinfo_struct[:current_value]] = fontobj(optkey)
ret.push(fontconf)
end
@@ -3458,6 +4230,10 @@ module TkConfigMethod
if ( ! __configinfo_struct[:alias] \
|| conf.size > __configinfo_struct[:alias] + 1 )
+ fnt = conf[__configinfo_struct[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ conf[__configinfo_struct[:default_value]] = TkNamedFont.new(fnt)
+ end
conf[__configinfo_struct[:current_value]] = fontobj(fontkey)
{ conf.shift => conf }
elsif ( __configinfo_struct[:alias] \
@@ -3473,6 +4249,12 @@ module TkConfigMethod
else
if slot
slot = slot.to_s
+
+ alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
case slot
when /^(#{__val2ruby_optkeys().keys.join('|')})$/
method = _symbolkey2str(__val2ruby_optkeys())[slot]
@@ -3805,6 +4587,11 @@ module TkConfigMethod
ret.delete('latin' << optkey)
ret.delete('ascii' << optkey)
ret.delete('kanji' << optkey)
+ fnt = fontconf[__configinfo_struct[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ fontconf[__configinfo_struct[:default_value]] \
+ = TkNamedFont.new(fnt)
+ end
fontconf[__configinfo_struct[:current_value]] = fontobj(optkey)
ret[optkey] = fontconf
end
@@ -3819,6 +4606,19 @@ module TkConfigMethod
end
end
end
+ private :__configinfo_core
+
+ def configinfo(slot = nil)
+ if slot && TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ begin
+ __configinfo_core(slot)
+ rescue
+ Array.new(__configinfo_struct.values.max).unshift(slot.to_s)
+ end
+ else
+ __configinfo_core(slot)
+ end
+ end
def current_configinfo(slot = nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
@@ -3918,7 +4718,12 @@ class TkObject<TkKernel
begin
cget(name)
rescue
- super(id, *args)
+ if self.kind_of?(TkWindow)
+ fail NameError,
+ "unknown option '#{id}' for #{self.inspect} (deleted widget?)"
+ else
+ super(id, *args)
+ end
# fail NameError,
# "undefined local variable or method `#{name}' for #{self.to_s}",
# error_at
@@ -3973,6 +4778,15 @@ end
class TkWindow<TkObject
include TkWinfo
extend TkBindCore
+ include Tk::Wm_for_General
+
+ @@WIDGET_INSPECT_FULL = false
+ def TkWindow._widget_inspect_full_?
+ @@WIDGET_INSPECT_FULL
+ end
+ def TkWindow._widget_inspect_full_=(mode)
+ @@WIDGET_INSPECT_FULL = (mode && true) || false
+ end
TkCommandNames = [].freeze
## ==> If TkCommandNames[0] is a string (not a null string),
@@ -4036,6 +4850,13 @@ class TkWindow<TkObject
fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
}
+ __optkey_aliases.each{|alias_name, real_name|
+ alias_name = alias_name.to_s
+ if keys.has_key?(alias_name)
+ keys[real_name.to_s] = keys.delete(alias_name)
+ end
+ }
+
__methodcall_optkeys.each{|key|
key = key.to_s
methodkeys[key] = keys.delete(key) if keys.key?(key)
@@ -4068,13 +4889,48 @@ class TkWindow<TkObject
end
if keys and keys != None
- tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
+ else
+ begin
+ tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
+ rescue => e
+ tk_call_without_enc(cmd, @path)
+ keys = __check_available_configure_options(keys)
+ unless keys.empty?
+ begin
+ # try to configure
+ configure(keys)
+ rescue
+ # fail => includes options adaptable when creattion only?
+ begin
+ tk_call_without_enc('destroy', @path)
+ rescue
+ # cannot rescue options error
+ fail e
+ else
+ # re-create widget
+ tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
+ end
+ end
+ end
+ end
+ end
else
tk_call_without_enc(cmd, @path)
end
end
private :create_self
+ def inspect
+ if @@WIDGET_INSPECT_FULL
+ super
+ else
+ str = super
+ str[0..(str.index(' '))] << '@path=' << @path.inspect << '>'
+ end
+ end
+
def exist?
TkWinfo.exist?(self)
end
@@ -4196,6 +5052,15 @@ class TkWindow<TkObject
self
end
+ def grid_anchor(anchor=None)
+ if anchor == None
+ TkGrid.anchor(self)
+ else
+ TkGrid.anchor(self, anchor)
+ self
+ end
+ end
+
def grid_forget
#tk_call('grid', 'forget', epath)
TkGrid.forget(self)
@@ -4227,12 +5092,14 @@ class TkWindow<TkObject
TkGrid.columnconfigure(self, index, keys)
end
alias grid_columnconfigure grid_columnconfig
+ alias grid_column grid_columnconfig
def grid_rowconfig(index, keys)
#tk_call('grid', 'rowconfigure', epath, index, *hash_kv(keys))
TkGrid.rowconfigure(self, index, keys)
end
alias grid_rowconfigure grid_rowconfig
+ alias grid_row grid_rowconfig
def grid_columnconfiginfo(index, slot=nil)
#if slot
@@ -4475,11 +5342,13 @@ class TkWindow<TkObject
end
children.each{|path, obj|
- if defined?(@cmdtbl)
- for id in @cmdtbl
- uninstall_cmd id
+ obj.instance_eval{
+ if defined?(@cmdtbl)
+ for id in @cmdtbl
+ uninstall_cmd id
+ end
end
- end
+ }
TkCore::INTERP.tk_windows.delete(path)
}
@@ -4584,7 +5453,7 @@ class TkWindow<TkObject
bindtags(bindtags().unshift(tag))
end
end
-
+TkWidget = TkWindow
# freeze core modules
#TclTkLib.freeze
@@ -4597,7 +5466,7 @@ end
#Tk.freeze
module Tk
- RELEASE_DATE = '2006-07-14'.freeze
+ RELEASE_DATE = '2008-05-23'.freeze
autoload :AUTO_PATH, 'tk/variable'
autoload :TCL_PACKAGE_PATH, 'tk/variable'
@@ -4609,6 +5478,7 @@ end
# call setup script for Tk extension libraries (base configuration)
begin
+ require 'tkextlib/version.rb'
require 'tkextlib/setup.rb'
rescue LoadError
# ignore
diff --git a/ext/tk/lib/tk/after.rb b/ext/tk/lib/tk/after.rb
index 24a048ee32..8c58210331 100644
--- a/ext/tk/lib/tk/after.rb
+++ b/ext/tk/lib/tk/after.rb
@@ -1,6 +1,6 @@
#
# tk/after.rb : methods for Tcl/Tk after command
#
-# $Id: after.rb,v 1.1.2.1 2004/05/01 16:09:49 nagai Exp $
+# $Id$
#
require 'tk/timer'
diff --git a/ext/tk/lib/tk/autoload.rb b/ext/tk/lib/tk/autoload.rb
index 6b3773f4ea..0773f7708d 100644
--- a/ext/tk/lib/tk/autoload.rb
+++ b/ext/tk/lib/tk/autoload.rb
@@ -1,9 +1,19 @@
#
# autoload
#
-
-#######################
+############################################
# geometry manager
+module Tk
+ autoload :Grid, 'tk/grid'
+ def Grid(*args); TkGrid.configure(*args); end
+
+ autoload :Pack, 'tk/pack'
+ def Pack(*args); TkPack.configure(*args); end
+
+ autoload :Place, 'tk/place'
+ def Place(*args); TkPlace.configure(*args); end
+end
+
autoload :TkGrid, 'tk/grid'
def TkGrid(*args); TkGrid.configure(*args); end
@@ -14,19 +24,117 @@ autoload :TkPlace, 'tk/place'
def TkPlace(*args); TkPlace.configure(*args); end
-#######################
-# others
+############################################
+# classes on Tk module
+module Tk
+ autoload :Button, 'tk/button'
+
+ autoload :Canvas, 'tk/canvas'
+
+ autoload :CheckButton, 'tk/checkbutton'
+ autoload :Checkbutton, 'tk/checkbutton'
+
+ autoload :Entry, 'tk/entry'
+
+ autoload :Frame, 'tk/frame'
+
+ autoload :Label, 'tk/label'
+
+ autoload :LabelFrame, 'tk/labelframe'
+ autoload :Labelframe, 'tk/labelframe'
+
+ autoload :Listbox, 'tk/listbox'
+
+ autoload :Menu, 'tk/menu'
+ autoload :MenuClone, 'tk/menu'
+ autoload :CloneMenu, 'tk/menu'
+ autoload :SystemMenu, 'tk/menu'
+ autoload :SysMenu_Help, 'tk/menu'
+ autoload :SysMenu_System, 'tk/menu'
+ autoload :SysMenu_Apple, 'tk/menu'
+ autoload :Menubutton, 'tk/menu'
+ autoload :MenuButton, 'tk/menu'
+ autoload :OptionMenubutton, 'tk/menu'
+ autoload :OptionMenBbutton, 'tk/menu'
+
+ autoload :Message, 'tk/message'
+
+ autoload :PanedWindow, 'tk/panedwindow'
+ autoload :Panedwindow, 'tk/panedwindow'
+
+ autoload :RadioButton, 'tk/radiobutton'
+ autoload :Radiobutton, 'tk/radiobutton'
+
+ autoload :Root, 'tk/root'
+
+ autoload :Scale, 'tk/scale'
+
+ autoload :Scrollbar, 'tk/scrollbar'
+ autoload :XScrollbar, 'tk/scrollbar'
+ autoload :YScrollbar, 'tk/scrollbar'
+
+ autoload :Spinbox, 'tk/spinbox'
+
+ autoload :Text, 'tk/text'
+
+ autoload :Toplevel, 'tk/toplevel'
+end
+
+
+############################################
+# sub-module of Tk
+module Tk
+ autoload :Clock, 'tk/clock'
+
+ autoload :OptionObj, 'tk/optionobj'
+
+ autoload :X_Scrollable, 'tk/scrollable'
+ autoload :Y_Scrollable, 'tk/scrollable'
+ autoload :Scrollable, 'tk/scrollable'
+
+ autoload :Wm, 'tk/wm'
+ autoload :Wm_for_General, 'tk/wm'
+
+ autoload :MacResource, 'tk/macpkg'
+
+ autoload :WinDDE, 'tk/winpkg'
+ autoload :WinRegistry, 'tk/winpkg'
+
+ autoload :ValidateConfigure, 'tk/validation'
+ autoload :ItemValidateConfigure, 'tk/validation'
+
+ autoload :EncodedString, 'tk/encodedstr'
+ def Tk.EncodedString(str, enc = nil); Tk::EncodedString.new(str, enc); end
+
+ autoload :BinaryString, 'tk/encodedstr'
+ def Tk.BinaryString(str); Tk::BinaryString.new(str); end
+
+ autoload :UTF8_String, 'tk/encodedstr'
+ def Tk.UTF8_String(str); Tk::UTF8_String.new(str); end
+
+end
+
+
+############################################
+# toplevel classes/modules (fixed)
autoload :TkBgError, 'tk/bgerror'
autoload :TkBindTag, 'tk/bindtag'
autoload :TkBindTagAll, 'tk/bindtag'
autoload :TkDatabaseClass, 'tk/bindtag'
-autoload :TkButton, 'tk/button'
-
autoload :TkConsole, 'tk/console'
-autoload :TkCanvas, 'tk/canvas'
+autoload :TkcItem, 'tk/canvas'
+autoload :TkcArc, 'tk/canvas'
+autoload :TkcBitmap, 'tk/canvas'
+autoload :TkcImage, 'tk/canvas'
+autoload :TkcLine, 'tk/canvas'
+autoload :TkcOval, 'tk/canvas'
+autoload :TkcPolygon, 'tk/canvas'
+autoload :TkcRectangle, 'tk/canvas'
+autoload :TkcText, 'tk/canvas'
+autoload :TkcWindow, 'tk/canvas'
autoload :TkcTagAccess, 'tk/canvastag'
autoload :TkcTag, 'tk/canvastag'
@@ -36,9 +144,6 @@ autoload :TkcTagAll, 'tk/canvastag'
autoload :TkcTagCurrent, 'tk/canvastag'
autoload :TkcTagGroup, 'tk/canvastag'
-autoload :TkCheckButton, 'tk/checkbutton'
-autoload :TkCheckbutton, 'tk/checkbutton'
-
autoload :TkClipboard, 'tk/clipboard'
autoload :TkComposite, 'tk/composite'
@@ -52,14 +157,10 @@ autoload :TkWarning, 'tk/dialog'
autoload :TkWarning2, 'tk/dialog'
autoload :TkWarningObj, 'tk/dialog'
-autoload :TkEntry, 'tk/entry'
-
autoload :TkEvent, 'tk/event'
autoload :TkFont, 'tk/font'
-autoload :TkTreatTagFont, 'tk/font'
-
-autoload :TkFrame, 'tk/frame'
+autoload :TkNamedFont, 'tk/font'
autoload :TkImage, 'tk/image'
autoload :TkBitmapImage, 'tk/image'
@@ -71,30 +172,12 @@ autoload :TkTreatItemFont, 'tk/itemfont'
autoload :TkKinput, 'tk/kinput'
-autoload :TkLabel, 'tk/label'
-
-autoload :TkLabelFrame, 'tk/labelframe'
-autoload :TkLabelframe, 'tk/labelframe'
-
-autoload :TkListbox, 'tk/listbox'
-
-autoload :TkMacResource, 'tk/macpkg'
-
-autoload :TkMenu, 'tk/menu'
-autoload :TkMenuClone, 'tk/menu'
autoload :TkSystemMenu, 'tk/menu'
-autoload :TkSysMenu_Help, 'tk/menu'
-autoload :TkSysMenu_System, 'tk/menu'
-autoload :TkSysMenu_Apple, 'tk/menu'
-autoload :TkMenubutton, 'tk/menu'
-autoload :TkOptionMenubutton, 'tk/menu'
autoload :TkMenubar, 'tk/menubar'
autoload :TkMenuSpec, 'tk/menuspec'
-autoload :TkMessage, 'tk/message'
-
autoload :TkManageFocus, 'tk/mngfocus'
autoload :TkMsgCatalog, 'tk/msgcat'
@@ -110,53 +193,46 @@ autoload :TkPackage, 'tk/package'
autoload :TkPalette, 'tk/palette'
-autoload :TkPanedWindow, 'tk/panedwindow'
-autoload :TkPanedwindow, 'tk/panedwindow'
-
-autoload :TkRadioButton, 'tk/radiobutton'
-autoload :TkRadiobutton, 'tk/radiobutton'
-
autoload :TkRoot, 'tk/root'
-autoload :TkScale, 'tk/scale'
-
-autoload :TkScrollbar, 'tk/scrollbar'
-autoload :TkXScrollbar, 'tk/scrollbar'
-autoload :TkYScrollbar, 'tk/scrollbar'
-
autoload :TkScrollbox, 'tk/scrollbox'
autoload :TkSelection, 'tk/selection'
-autoload :TkSpinbox, 'tk/spinbox'
-
autoload :TkTreatTagFont, 'tk/tagfont'
-autoload :TkText, 'tk/text'
-
autoload :TkTextImage, 'tk/textimage'
+autoload :TktImage, 'tk/textimage'
autoload :TkTextMark, 'tk/textmark'
autoload :TkTextNamedMark, 'tk/textmark'
autoload :TkTextMarkInsert, 'tk/textmark'
autoload :TkTextMarkCurrent, 'tk/textmark'
autoload :TkTextMarkAnchor, 'tk/textmark'
+autoload :TktMark, 'tk/textmark'
+autoload :TktNamedMark, 'tk/textmark'
+autoload :TktMarkInsert, 'tk/textmark'
+autoload :TktMarkCurrent, 'tk/textmark'
+autoload :TktMarkAnchor, 'tk/textmark'
autoload :TkTextTag, 'tk/texttag'
autoload :TkTextNamedTag, 'tk/texttag'
autoload :TkTextTagSel, 'tk/texttag'
+autoload :TktTag, 'tk/texttag'
+autoload :TktNamedTag, 'tk/texttag'
+autoload :TktTagSel, 'tk/texttag'
autoload :TkTextWindow, 'tk/textwindow'
+autoload :TktWindow, 'tk/textwindow'
autoload :TkAfter, 'tk/timer'
autoload :TkTimer, 'tk/timer'
autoload :TkRTTimer, 'tk/timer'
-autoload :TkToplevel, 'tk/toplevel'
-
autoload :TkTextWin, 'tk/txtwin_abst'
autoload :TkValidation, 'tk/validation'
+autoload :TkValidateCommand, 'tk/validation'
autoload :TkVariable, 'tk/variable'
autoload :TkVarAccess, 'tk/variable'
@@ -166,31 +242,173 @@ autoload :TkNamedVirtualEvent,'tk/virtevent'
autoload :TkWinfo, 'tk/winfo'
-autoload :TkWinDDE, 'tk/winpkg'
-autoload :TkWinRegistry, 'tk/winpkg'
-
autoload :TkXIM, 'tk/xim'
-#######################
-# sub-module of Tk
+############################################
+# toplevel classes/modules (switchable)
module Tk
- autoload :Clock, 'tk/clock'
- autoload :OptionObj, 'tk/optionobj'
- autoload :X_Scrollable, 'tk/scrollable'
- autoload :Y_Scrollable, 'tk/scrollable'
- autoload :Scrollable, 'tk/scrollable'
- autoload :Wm, 'tk/wm'
+ @TOPLEVEL_ALIAS_TABLE = {}
+ @TOPLEVEL_ALIAS_TABLE[:Tk] = {
+ :TkButton => 'tk/button',
- autoload :ValidateConfigure, 'tk/validation'
- autoload :ItemValidateConfigure, 'tk/validation'
+ :TkCanvas => 'tk/canvas',
- autoload :EncodedString, 'tk/encodedstr'
- def Tk.EncodedString(str, enc = nil); Tk::EncodedString.new(str, enc); end
+ :TkCheckButton => 'tk/checkbutton',
+ :TkCheckbutton => 'tk/checkbutton',
- autoload :BinaryString, 'tk/encodedstr'
- def Tk.BinaryString(str); Tk::BinaryString.new(str); end
+ # :TkDialog => 'tk/dialog',
+ # :TkDialog2 => 'tk/dialog',
+ # :TkDialogObj => 'tk/dialog',
+ # :TkWarning => 'tk/dialog',
+ # :TkWarning2 => 'tk/dialog',
+ # :TkWarningObj => 'tk/dialog',
- autoload :UTF8_String, 'tk/encodedstr'
- def Tk.UTF8_String(str); Tk::UTF8_String.new(str); end
+ :TkEntry => 'tk/entry',
+
+ :TkFrame => 'tk/frame',
+
+ :TkLabel => 'tk/label',
+
+ :TkLabelFrame => 'tk/labelframe',
+ :TkLabelframe => 'tk/labelframe',
+
+ :TkListbox => 'tk/listbox',
+
+ :TkMacResource => 'tk/macpkg',
+
+ :TkMenu => 'tk/menu',
+ :TkMenuClone => 'tk/menu',
+ :TkCloneMenu => 'tk/menu',
+ # :TkSystemMenu => 'tk/menu',
+ :TkSysMenu_Help => 'tk/menu',
+ :TkSysMenu_System => 'tk/menu',
+ :TkSysMenu_Apple => 'tk/menu',
+ :TkMenubutton => 'tk/menu',
+ :TkMenuButton => 'tk/menu',
+ :TkOptionMenubutton => 'tk/menu',
+ :TkOptionMenuButton => 'tk/menu',
+
+ :TkMessage => 'tk/message',
+
+ :TkPanedWindow => 'tk/panedwindow',
+ :TkPanedwindow => 'tk/panedwindow',
+
+ :TkRadioButton => 'tk/radiobutton',
+ :TkRadiobutton => 'tk/radiobutton',
+
+ # :TkRoot => 'tk/root',
+
+ :TkScale => 'tk/scale',
+
+ :TkScrollbar => 'tk/scrollbar',
+ :TkXScrollbar => 'tk/scrollbar',
+ :TkYScrollbar => 'tk/scrollbar',
+
+ :TkSpinbox => 'tk/spinbox',
+
+ :TkText => 'tk/text',
+
+ :TkToplevel => 'tk/toplevel',
+
+ :TkWinDDE => 'tk/winpkg',
+ :TkWinRegistry => 'tk/winpkg',
+ }
+
+ @TOPLEVEL_ALIAS_OWNER = {}
+
+ @TOPLEVEL_ALIAS_SETUP_PROC = {}
+
+ @current_default_widget_set = nil
+end
+
+
+############################################
+# methods to control default widget set
+############################################
+
+class << Tk
+ def default_widget_set
+ @current_default_widget_set
+ end
+
+ def default_widget_set=(target)
+ target = target.to_sym
+ return target if target == @current_default_widget_set
+
+ if (cmd = @TOPLEVEL_ALIAS_SETUP_PROC[target])
+ cmd.call(target)
+ end
+
+ _replace_toplevel_aliases(target)
+ end
+
+ def __set_toplevel_aliases__(target, obj, *symbols)
+ @TOPLEVEL_ALIAS_TABLE[target = target.to_sym] ||= {}
+ symbols.each{|sym|
+ @TOPLEVEL_ALIAS_TABLE[target][sym = sym.to_sym] = obj
+ # if @current_default_widget_set == target
+ if @TOPLEVEL_ALIAS_OWNER[sym] == target
+ Object.class_eval{remove_const sym} if Object.const_defined?(sym)
+ Object.const_set(sym, obj)
+ end
+ }
+ end
+
+ ###################################
+ private
+ def _replace_toplevel_aliases(target)
+ # check already autoloaded
+ if (table = @TOPLEVEL_ALIAS_TABLE[current = @current_default_widget_set])
+ table.each{|sym, file|
+ if !Object.autoload?(sym) && Object.const_defined?(sym) &&
+ @TOPLEVEL_ALIAS_TABLE[current][sym].kind_of?(String)
+ # autoload -> class
+ @TOPLEVEL_ALIAS_TABLE[current][sym] = Object.const_get(sym)
+ end
+ }
+ end
+
+ # setup autoloads
+ @TOPLEVEL_ALIAS_TABLE[target].each{|sym, file|
+ Object.class_eval{remove_const sym} if Object.const_defined?(sym)
+ if file.kind_of?(String)
+ # file => autoload target file
+ Object.autoload(sym, file)
+ else
+ # file => loaded class object
+ Object.const_set(sym, file)
+ end
+ @TOPLEVEL_ALIAS_OWNER[sym] = target
+ }
+
+ # update current alias
+ @current_default_widget_set = target
+ end
+end
+
+############################################
+# setup default widget set => :Tk
+Tk.default_widget_set = :Tk
+
+
+############################################
+# depend on the version of Tcl/Tk
+# major, minor, type, type_name, patchlevel = TclTkLib.get_version
+
+############################################
+# Ttk (Tile) support
+=begin
+if major > 8 ||
+ (major == 8 && minor > 5) ||
+ (major == 8 && minor == 5 && type >= TclTkLib::RELEASE_TYPE::BETA)
+ # Tcl/Tk 8.5 beta or later
+ Object.autoload :Ttk, 'tkextlib/tile'
+ Tk.autoload :Tile, 'tkextlib/tile'
+
+ require 'tk/ttk_selector'
end
+=end
+Object.autoload :Ttk, 'tkextlib/tile'
+Tk.autoload :Tile, 'tkextlib/tile'
+require 'tk/ttk_selector'
diff --git a/ext/tk/lib/tk/bindtag.rb b/ext/tk/lib/tk/bindtag.rb
index 9023a08e06..88c8367a88 100644
--- a/ext/tk/lib/tk/bindtag.rb
+++ b/ext/tk/lib/tk/bindtag.rb
@@ -8,30 +8,64 @@ class TkBindTag
#BTagID_TBL = {}
BTagID_TBL = TkCore::INTERP.create_table
- Tk_BINDTAG_ID = ["btag".freeze, "00000".taint].freeze
- TkCore::INTERP.init_ip_env{ BTagID_TBL.clear }
+ (Tk_BINDTAG_ID = ["btag".freeze, "00000".taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ BTagID_TBL.mutex.synchronize{ BTagID_TBL.clear }
+ }
def TkBindTag.id2obj(id)
- BTagID_TBL[id]? BTagID_TBL[id]: id
+ BTagID_TBL.mutex.synchronize{
+ (BTagID_TBL[id])? BTagID_TBL[id]: id
+ }
end
+=begin
def TkBindTag.new_by_name(name, *args, &b)
- return BTagID_TBL[name] if BTagID_TBL[name]
+ BTagID_TBL.mutex.synchronize{
+ return BTagID_TBL[name] if BTagID_TBL[name]
+ }
+
self.new.instance_eval{
- BTagID_TBL.delete @id
- @id = name
- BTagID_TBL[@id] = self
+ BTagID_TBL.mutex.synchronize{
+ BTagID_TBL.delete @id
+ @id = name
+ BTagID_TBL[@id] = self
+ }
bind(*args, &b) if args != []
self
}
end
+=end
+ def TkBindTag.new_by_name(name, *args, &b)
+ obj = nil
+ BTagID_TBL.mutex.synchronize{
+ if BTagID_TBL[name]
+ obj = BTagID_TBL[name]
+ else
+ (obj = BTagID_TBL[name] = self.allocate).instance_eval{
+ @id = name
+ }
+ end
+ }
+ bind(*args, &b) if obj && args != []
+ obj
+ end
def initialize(*args, &b)
- # @id = Tk_BINDTAG_ID.join('')
- @id = Tk_BINDTAG_ID.join(TkCore::INTERP._ip_id_)
- Tk_BINDTAG_ID[1].succ!
- BTagID_TBL[@id] = self
+ Tk_BINDTAG_ID.mutex.synchronize{
+ # @id = Tk_BINDTAG_ID.join('')
+ @id = Tk_BINDTAG_ID.join(TkCore::INTERP._ip_id_)
+ Tk_BINDTAG_ID[1].succ!
+ }
+ BTagID_TBL.mutex.synchronize{
+ BTagID_TBL[@id] = self
+ }
bind(*args, &b) if args != []
end
@@ -63,14 +97,37 @@ end
class TkDatabaseClass<TkBindTag
+=begin
def self.new(name, *args, &b)
- return BTagID_TBL[name] if BTagID_TBL[name]
+ BTagID_TBL.mutex.synchronize{
+ return BTagID_TBL[name] if BTagID_TBL[name]
+ }
super(name, *args, &b)
end
def initialize(name, *args, &b)
@id = name
- BTagID_TBL[@id] = self
+ BTagID_TBL.mutex.synchronize{
+ BTagID_TBL[@id] = self
+ }
+ bind(*args, &b) if args != []
+ end
+=end
+ def self.new(name, *args, &b)
+ BTagID_TBL.mutex.synchronize{
+ if BTagID_TBL[name]
+ BTagID_TBL[name]
+ else
+ BTagID_TBL[name] = self.allocate.instance_eval{
+ initialize(name, *args, &b)
+ self
+ }
+ end
+ }
+ end
+
+ def initialize(name, *args, &b)
+ @id = name
bind(*args, &b) if args != []
end
diff --git a/ext/tk/lib/tk/button.rb b/ext/tk/lib/tk/button.rb
index 407a47c400..770a5785bb 100644
--- a/ext/tk/lib/tk/button.rb
+++ b/ext/tk/lib/tk/button.rb
@@ -4,7 +4,7 @@
require 'tk'
require 'tk/label'
-class TkButton<TkLabel
+class Tk::Button<Tk::Label
TkCommandNames = ['button'.freeze].freeze
WidgetClassName = 'Button'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -25,3 +25,6 @@ class TkButton<TkLabel
self
end
end
+
+#TkButton = Tk::Button unless Object.const_defined? :TkButton
+Tk.__set_toplevel_aliases__(:Tk, Tk::Button, :TkButton)
diff --git a/ext/tk/lib/tk/canvas.rb b/ext/tk/lib/tk/canvas.rb
index 0f55bff4ed..36ea008a17 100644
--- a/ext/tk/lib/tk/canvas.rb
+++ b/ext/tk/lib/tk/canvas.rb
@@ -1,6 +1,5 @@
#
# tk/canvas.rb - Tk canvas classes
-# $Date: 2005/10/24 00:07:00 $
# by Yukihiro Matsumoto <matz@caelum.co.jp>
#
require 'tk'
@@ -40,9 +39,9 @@ module TkCanvasItemConfig
private :__item_pathname
end
-class TkCanvas<TkWindow
+class Tk::Canvas<TkWindow
include TkCanvasItemConfig
- include Scrollable
+ include Tk::Scrollable
TkCommandNames = ['canvas'.freeze].freeze
WidgetClassName = 'Canvas'.freeze
@@ -169,6 +168,8 @@ class TkCanvas<TkWindow
#tk_tcl2ruby(tk_send_without_enc('canvasy', screen_y, *args))
number(tk_send_without_enc('canvasy', screen_y, *args))
end
+ alias canvas_x canvasx
+ alias canvas_y canvasy
def coords(tag, *args)
if args == []
@@ -186,11 +187,17 @@ class TkCanvas<TkWindow
end
def delete(*args)
- if TkcItem::CItemID_TBL[self.path]
+ tbl = nil
+ TkcItem::CItemID_TBL.mutex.synchronize{
+ tbl = TkcItem::CItemID_TBL[self.path]
+ }
+ if tbl
args.each{|tag|
find('withtag', tag).each{|item|
if item.kind_of?(TkcItem)
- TkcItem::CItemID_TBL[self.path].delete(item.id)
+ TkcItem::CItemID_TBL.mutex.synchronize{
+ tbl.delete(item.id)
+ }
end
}
}
@@ -543,8 +550,8 @@ class TkCanvas<TkWindow
tk_send_without_enc('scan', 'mark', x, y)
self
end
- def scan_dragto(x, y)
- tk_send_without_enc('scan', 'dragto', x, y)
+ def scan_dragto(x, y, gain=None)
+ tk_send_without_enc('scan', 'dragto', x, y, gain)
self
end
@@ -573,6 +580,10 @@ class TkCanvas<TkWindow
end
end
+#TkCanvas = Tk::Canvas unless Object.const_defined? :TkCanvas
+Tk.__set_toplevel_aliases__(:Tk, Tk::Canvas, :TkCanvas)
+
+
class TkcItem<TkObject
extend Tk
include TkcTagAccess
@@ -581,9 +592,12 @@ class TkcItem<TkObject
CItemTypeName = nil
CItemTypeToClass = {}
+
CItemID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ CItemID_TBL.clear }
+ TkCore::INTERP.init_ip_env{
+ CItemID_TBL.mutex.synchronize{ CItemID_TBL.clear }
+ }
def TkcItem.type2class(type)
CItemTypeToClass[type]
@@ -591,8 +605,13 @@ class TkcItem<TkObject
def TkcItem.id2obj(canvas, id)
cpath = canvas.path
- return id unless CItemID_TBL[cpath]
- CItemID_TBL[cpath][id]? CItemID_TBL[cpath][id]: id
+ CItemID_TBL.mutex.synchronize{
+ if CItemID_TBL[cpath]
+ CItemID_TBL[cpath][id]? CItemID_TBL[cpath][id]: id
+ else
+ id
+ end
+ }
end
########################################
@@ -625,6 +644,13 @@ class TkcItem<TkObject
fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
}
+ __item_optkey_aliases(nil).each{|alias_name, real_name|
+ alias_name = alias_name.to_s
+ if keys.has_key?(alias_name)
+ keys[real_name.to_s] = keys.delete(alias_name)
+ end
+ }
+
__item_methodcall_optkeys(nil).each{|key|
key = key.to_s
methodkeys[key] = keys.delete(key) if keys.key?(key)
@@ -658,15 +684,17 @@ class TkcItem<TkObject
########################################
def initialize(parent, *args)
- #unless parent.kind_of?(TkCanvas)
- # fail ArgumentError, "expect TkCanvas for 1st argument"
+ #unless parent.kind_of?(Tk::Canvas)
+ # fail ArgumentError, "expect Tk::Canvas for 1st argument"
#end
@parent = @c = parent
@path = parent.path
@id = create_self(*args) # an integer number as 'canvas item id'
- CItemID_TBL[@path] = {} unless CItemID_TBL[@path]
- CItemID_TBL[@path][@id] = self
+ CItemID_TBL.mutex.synchronize{
+ CItemID_TBL[@path] = {} unless CItemID_TBL[@path]
+ CItemID_TBL[@path][@id] = self
+ }
end
def create_self(*args)
self.class.create(@c, *args) # return an integer number as 'canvas item id'
@@ -687,7 +715,9 @@ class TkcItem<TkObject
def delete
@c.delete @id
- CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ CItemID_TBL.mutex.synchronize{
+ CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ }
self
end
alias remove delete
diff --git a/ext/tk/lib/tk/canvastag.rb b/ext/tk/lib/tk/canvastag.rb
index a5650ee68b..49796d80b2 100644
--- a/ext/tk/lib/tk/canvastag.rb
+++ b/ext/tk/lib/tk/canvastag.rb
@@ -63,6 +63,9 @@ module TkcTagAccess
def cget(option)
@c.itemcget(@id, option)
end
+ def cget_strict(option)
+ @c.itemcget_strict(@id, option)
+ end
def configure(key, value=None)
@c.itemconfigure(@id, key, value)
@@ -199,14 +202,26 @@ class TkcTag<TkObject
include TkcTagAccess
CTagID_TBL = TkCore::INTERP.create_table
- Tk_CanvasTag_ID = ['ctag'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ CTagID_TBL.clear }
+ (Tk_CanvasTag_ID = ['ctag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ CTagID_TBL.mutex.synchronize{ CTagID_TBL.clear }
+ }
def TkcTag.id2obj(canvas, id)
cpath = canvas.path
- return id unless CTagID_TBL[cpath]
- CTagID_TBL[cpath][id]? CTagID_TBL[cpath][id]: id
+ CTagID_TBL.mutex.synchronize{
+ if CTagID_TBL[cpath]
+ CTagID_TBL[cpath][id]? CTagID_TBL[cpath][id]: id
+ else
+ id
+ end
+ }
end
def initialize(parent, mode=nil, *args)
@@ -215,11 +230,15 @@ class TkcTag<TkObject
#end
@c = parent
@cpath = parent.path
- # @path = @id = Tk_CanvasTag_ID.join('')
- @path = @id = Tk_CanvasTag_ID.join(TkCore::INTERP._ip_id_)
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
- Tk_CanvasTag_ID[1].succ!
+ Tk_CanvasTag_ID.mutex.synchronize{
+ # @path = @id = Tk_CanvasTag_ID.join('')
+ @path = @id = Tk_CanvasTag_ID.join(TkCore::INTERP._ip_id_)
+ Tk_CanvasTag_ID[1].succ!
+ }
+ CTagID_TBL.mutex.synchronize{
+ CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
+ CTagID_TBL[@cpath][@id] = self
+ }
if mode
tk_call_without_enc(@c.path, "addtag", @id, mode, *args)
end
@@ -238,7 +257,9 @@ class TkcTag<TkObject
def delete
@c.delete @id
- CTagID_TBL[@cpath].delete(@id) if CTagID_TBL[@cpath]
+ CTagID_TBL.mutex.synchronize{
+ CTagID_TBL[@cpath].delete(@id) if CTagID_TBL[@cpath]
+ }
self
end
alias remove delete
@@ -288,23 +309,38 @@ class TkcTag<TkObject
end
class TkcTagString<TkcTag
- def self.new(parent, name, *args)
- if CTagID_TBL[parent.path] && CTagID_TBL[parent.path][name]
- return CTagID_TBL[parent.path][name]
- else
- super(parent, name, *args)
+ def self.new(parent, name, mode=nil, *args)
+ obj = nil
+ CTagID_TBL.mutex.synchronize{
+ if CTagID_TBL[parent.path] && CTagID_TBL[parent.path][name]
+ obj = CTagID_TBL[parent.path][name]
+ else
+ # super(parent, name, *args)
+ (obj = self.allocate).instance_eval{
+ @c = parent
+ @cpath = parent.path
+ @path = @id = name
+ CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
+ CTagID_TBL[@cpath][@id] = self
+ }
+ end
+ }
+ if obj && mode
+ tk_call_without_enc(@c.path, "addtag", @id, mode, *args)
end
+ obj
end
def initialize(parent, name, mode=nil, *args)
+ # dummy:: not called by 'new' method
+
#unless parent.kind_of?(TkCanvas)
# fail ArgumentError, "expect TkCanvas for 1st argument"
#end
@c = parent
@cpath = parent.path
@path = @id = name
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
+
if mode
tk_call_without_enc(@c.path, "addtag", @id, mode, *args)
end
@@ -312,7 +348,11 @@ class TkcTagString<TkcTag
end
TkcNamedTag = TkcTagString
-class TkcTagAll<TkcTag
+class TkcTagAll<TkcTagString
+ def self.new(parent)
+ super(parent, 'all')
+ end
+=begin
def initialize(parent)
#unless parent.kind_of?(TkCanvas)
# fail ArgumentError, "expect TkCanvas for 1st argument"
@@ -320,12 +360,19 @@ class TkcTagAll<TkcTag
@c = parent
@cpath = parent.path
@path = @id = 'all'
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
+ CTagID_TBL.mutex.synchronize{
+ CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
+ CTagID_TBL[@cpath][@id] = self
+ }
end
+=end
end
-class TkcTagCurrent<TkcTag
+class TkcTagCurrent<TkcTagString
+ def self.new(parent)
+ super(parent, 'current')
+ end
+=begin
def initialize(parent)
#unless parent.kind_of?(TkCanvas)
# fail ArgumentError, "expect TkCanvas for 1st argument"
@@ -333,13 +380,21 @@ class TkcTagCurrent<TkcTag
@c = parent
@cpath = parent.path
@path = @id = 'current'
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
+ CTagID_TBL.mutex.synchronize{
+ CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
+ CTagID_TBL[@cpath][@id] = self
+ }
end
+=end
end
class TkcGroup<TkcTag
- Tk_cGroup_ID = ['tkcg'.freeze, '00000'.taint].freeze
+ (Tk_cGroup_ID = ['tkcg'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
#def create_self(parent, *args)
def initialize(parent, *args)
#unless parent.kind_of?(TkCanvas)
@@ -347,11 +402,15 @@ class TkcGroup<TkcTag
#end
@c = parent
@cpath = parent.path
- # @path = @id = Tk_cGroup_ID.join('')
- @path = @id = Tk_cGroup_ID.join(TkCore::INTERP._ip_id_)
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
- Tk_cGroup_ID[1].succ!
+ Tk_cGroup_ID.mutex.synchronize{
+ # @path = @id = Tk_cGroup_ID.join('')
+ @path = @id = Tk_cGroup_ID.join(TkCore::INTERP._ip_id_)
+ Tk_cGroup_ID[1].succ!
+ }
+ CTagID_TBL.mutex.synchronize{
+ CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
+ CTagID_TBL[@cpath][@id] = self
+ }
include(*args) if args != []
end
#private :create_self
diff --git a/ext/tk/lib/tk/checkbutton.rb b/ext/tk/lib/tk/checkbutton.rb
index d76d99c0f2..b1186a87ed 100644
--- a/ext/tk/lib/tk/checkbutton.rb
+++ b/ext/tk/lib/tk/checkbutton.rb
@@ -4,7 +4,7 @@
require 'tk'
require 'tk/radiobutton'
-class TkCheckButton<TkRadioButton
+class Tk::CheckButton<Tk::RadioButton
TkCommandNames = ['checkbutton'.freeze].freeze
WidgetClassName = 'Checkbutton'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -22,4 +22,9 @@ class TkCheckButton<TkRadioButton
self
end
end
-TkCheckbutton = TkCheckButton
+
+Tk::Checkbutton = Tk::CheckButton
+#TkCheckButton = Tk::CheckButton unless Object.const_defined? :TkCheckButton
+#TkCheckbutton = Tk::Checkbutton unless Object.const_defined? :TkCheckbutton
+Tk.__set_toplevel_aliases__(:Tk, Tk::CheckButton,
+ :TkCheckButton, :TkCheckbutton)
diff --git a/ext/tk/lib/tk/composite.rb b/ext/tk/lib/tk/composite.rb
index eaed8ed363..883d43c3ea 100644
--- a/ext/tk/lib/tk/composite.rb
+++ b/ext/tk/lib/tk/composite.rb
@@ -34,7 +34,8 @@ module TkComposite
if klass
# WidgetClassName is a known class
- if klass <= TkFrame || klass < TkComposite
+ #if klass <= TkFrame || klass < TkComposite
+ if klass <= TkFrame || klass < Tk::Frame || klass < TkComposite
# klass is valid for the base frame
if self.class <= klass
# use my classname
@@ -50,7 +51,8 @@ module TkComposite
else
# klass is invalid for the base frame
- if self.class < TkFrame || self.class.superclass < TkComposite
+ #if self.class < TkFrame || self.class.superclass < TkComposite
+ if self.class < TkFrame || self.class.superclass < Tk::Frame || self.class.superclass < TkComposite
# my class name is valid for the base frame -> use my classname
base_class_name = self.class.name
if base_class_name == ''
@@ -69,7 +71,8 @@ module TkComposite
else
# no valid WidgetClassName
- if self.class < TkFrame || self.class.superclass < TkComposite
+ #if self.class < TkFrame || self.class.superclass < TkComposite
+ if self.class < TkFrame || self.class.superclass < Tk::Frame || self.class.superclass < TkComposite
# my class name is valid for the base frame -> use my classname
base_class_name = self.class.name
if base_class_name == ''
@@ -108,8 +111,12 @@ module TkComposite
end
if base_class_name
+ # @frame = Tk::Frame.new(parent, :class=>base_class_name)
+ # --> use current TkFrame class
@frame = TkFrame.new(parent, :class=>base_class_name)
else
+ # @frame = Tk::Frame.new(parent)
+ # --> use current TkFrame class
@frame = TkFrame.new(parent)
end
@path = @epath = @frame.path
@@ -133,6 +140,11 @@ module TkComposite
def initialize_composite(*args) end
private :initialize_composite
+ def inspect
+ str = super
+ str.chop << ' @epath=' << @epath.inspect << '>'
+ end
+
def option_methods(*opts)
opts.each{|m_set, m_cget, m_info|
m_set = m_set.to_s
@@ -169,6 +181,57 @@ module TkComposite
delegate_alias(option, option, *wins)
end
+ def __cget_delegates(slot)
+ slot = slot.to_s
+
+ if @option_methods.include?(slot)
+ if @option_methods[slot][:cget]
+ return self.__send__(@option_methods[slot][:cget])
+ else
+ if @option_setting[slot]
+ return @option_setting[slot]
+ else
+ return ''
+ end
+ end
+ end
+
+ tbl = @delegates[slot]
+ tbl = @delegates['DEFAULT'] unless tbl
+
+ begin
+ if tbl
+ opt, wins = tbl[-1]
+ opt = slot if opt == 'DEFAULT'
+ if wins && wins[-1]
+ # return wins[-1].cget(opt)
+ return wins[-1].cget_strict(opt)
+ end
+ end
+ rescue
+ end
+
+ return None
+ end
+ private :__cget_delegates
+
+ def cget(slot)
+ if (ret = __cget_delegates(slot)) == None
+ super(slot)
+ else
+ ret
+ end
+ end
+
+ def cget_strict(slot)
+ if (ret = __cget_delegates(slot)) == None
+ super(slot)
+ else
+ ret
+ end
+ end
+
+=begin
def cget(slot)
slot = slot.to_s
@@ -200,6 +263,7 @@ module TkComposite
super(slot)
end
+=end
def configure(slot, value=None)
if slot.kind_of? Hash
diff --git a/ext/tk/lib/tk/encodedstr.rb b/ext/tk/lib/tk/encodedstr.rb
index 797e514a4c..02de0b0d85 100644
--- a/ext/tk/lib/tk/encodedstr.rb
+++ b/ext/tk/lib/tk/encodedstr.rb
@@ -70,13 +70,89 @@ module Tk
# @encoding = ( enc ||
# ((self.class::Encoding)?
# self.class::Encoding : Tk.encoding_system) )
- @encoding = ( enc ||
- ((self.class::Encoding)?
+ enc ||= (self.class::Encoding)?
self.class::Encoding :
- ((Tk.encoding)? Tk.encoding : Tk.encoding_system) ) )
+ ((Tk.encoding)? Tk.encoding : Tk.encoding_system)
+ if TkCore::WITH_ENCODING
+ unless encobj = Tk::Encoding::ENCODING_TABLE.get_obj(enc)
+ fail ArgumentError, "unsupported Tk encoding '#{enc}'"
+ end
+ self.force_encoding(encobj)
+ else
+ @encoding = enc
+ end
+ end
+
+ if TkCore::WITH_ENCODING
+ alias encoding_obj encoding
+ alias __encoding encoding
+ def encoding
+ Tk::Encoding::ENCODING_TABLE.get_name(super())
+ end
+ else
+ def encoding
+ @encoding
+ end
+ alias encoding_obj encoding
end
- attr_reader :encoding
+ if TkCore::WITH_ENCODING
+ # wrapper methods for compatibility
+ alias __instance_variable_get instance_variable_get
+ alias __instance_variable_set instance_variable_set
+ alias __instance_eval instance_eval
+ alias __instance_variables instance_variables
+
+ def instance_variable_get(key)
+ if (key.to_s == '@encoding')
+ self.encoding
+ else
+ super(key)
+ end
+ end
+
+ def instance_variable_set(key, value)
+ if (key.to_s == '@encoding')
+ if value
+ self.force_encoding(value)
+ else
+ self.force_encoding(Tk::Encoding::UNKNOWN)
+ end
+ value
+ else
+ super(key, value)
+ end
+ end
+
+ def instance_eval(*args, &b)
+ old_enc = @encoding = self.encoding
+
+ ret = super(*args, &b)
+
+ if @encoding
+ if @encoding != old_enc
+ # modified by user
+ self.force_encoding(@encoding)
+ end
+ remove_instance_variable(:@encoding)
+ else
+ begin
+ remove_instance_variable(:@encoding)
+ # user sets to nil -> use current default
+ self.force_encoding(Tk.encoding)
+ rescue NameError
+ # removed by user -> ignore, because user don't use @encoding
+ end
+ end
+ ret
+ end
+ end
+
+ def instance_variables
+ ret = super()
+ ret << :@encoding # fake !!
+ ret
+ end
end
# def Tk.EncodedString(str, enc = nil)
# Tk::EncodedString.new(str, enc)
diff --git a/ext/tk/lib/tk/entry.rb b/ext/tk/lib/tk/entry.rb
index e4d69eb7bf..8ce8def1e7 100644
--- a/ext/tk/lib/tk/entry.rb
+++ b/ext/tk/lib/tk/entry.rb
@@ -1,6 +1,5 @@
#
# tk/entry.rb - Tk entry classes
-# $Date: 2005/10/22 22:16:24 $
# by Yukihiro Matsumoto <matz@caelum.co.jp>
require 'tk'
@@ -8,7 +7,7 @@ require 'tk/label'
require 'tk/scrollable'
require 'tk/validation'
-class TkEntry<TkLabel
+class Tk::Entry<Tk::Label
include X_Scrollable
include TkValidation
@@ -115,3 +114,6 @@ class TkEntry<TkLabel
val
end
end
+
+#TkEntry = Tk::Entry unless Object.const_defined? :TkEntry
+Tk.__set_toplevel_aliases__(:Tk, Tk::Entry, :TkEntry)
diff --git a/ext/tk/lib/tk/event.rb b/ext/tk/lib/tk/event.rb
index 70a1e38bbe..d8aad6248b 100644
--- a/ext/tk/lib/tk/event.rb
+++ b/ext/tk/lib/tk/event.rb
@@ -39,7 +39,9 @@ module TkEvent
RESIZEREQ = 0x200000
CIRCREQ = 0x400000
- MWHEEL = 0x10000000
+ MWHEEL = KEY
+
+ STRING_DATA = 0x80000000 # special flag for 'data' field
ALL = 0xFFFFFFFF
@@ -155,7 +157,7 @@ module TkEvent
'borderwidth' => (Grp::CREATE|Grp::CONFIG),
'button' => Grp::BUTTON,
'count' => Grp::EXPOSE,
- 'data' => Grp::VIRTUAL,
+ 'data' => (Grp::VIRTUAL|Grp::STRING_DATA),
'delta' => Grp::MWHEEL,
'detail' => (Grp::FOCUS|Grp::CROSSING),
'focus' => Grp::CROSSING,
@@ -223,7 +225,8 @@ module TkEvent
rescue
next
end
- next if !val || val == '??'
+ # next if !val || val == '??'
+ next if !val || (val == '??' && (flag & Grp::STRING_DATA))
fields[key] = val
}
@@ -298,34 +301,65 @@ module TkEvent
[ ?b, ?n, :num ],
[ ?c, ?n, :count ],
[ ?d, ?s, :detail ],
+ # ?e
[ ?f, ?b, :focus ],
+ # ?g
[ ?h, ?n, :height ],
[ ?i, ?s, :win_hex ],
+ # ?j
[ ?k, ?n, :keycode ],
+ # ?l
[ ?m, ?s, :mode ],
+ # ?n
[ ?o, ?b, :override ],
[ ?p, ?s, :place ],
+ # ?q
+ # ?r
[ ?s, ?x, :state ],
[ ?t, ?n, :time ],
+ # ?u
+ [ ?v, ?n, :value_mask ],
[ ?w, ?n, :width ],
[ ?x, ?n, :x ],
[ ?y, ?n, :y ],
+ # ?z
[ ?A, ?s, :char ],
[ ?B, ?n, :borderwidth ],
+ # ?C
[ ?D, ?n, :wheel_delta ],
[ ?E, ?b, :send_event ],
+ # ?F
+ # ?G
+ # ?H
+ # ?I
+ # ?J
[ ?K, ?s, :keysym ],
+ # ?L
+ # ?M
[ ?N, ?n, :keysym_num ],
+ # ?O
[ ?P, ?s, :property ],
+ # ?Q
[ ?R, ?s, :rootwin_id ],
[ ?S, ?s, :subwindow ],
[ ?T, ?n, :type ],
+ # ?U
+ # ?V
[ ?W, ?w, :widget ],
[ ?X, ?n, :x_root ],
[ ?Y, ?n, :y_root ],
+ # ?Z
nil
]
+ # [ <'%' subst-key str>, <proc type char>, <instance var (accessor) name>]
+ # the subst-key string will be converted to a bytecode (128+idx).
+ LONGKEY_TBL = [
+ # for example, for %CTT and %CST subst-key on tkdnd-2.0
+ # ['CTT', ?l, :drop_target_type],
+ # ['CST', ?l, :drop_source_type],
+ ]
+
# [ <proc type char>, <proc/method to convert tcl-str to ruby-obj>]
PROC_TBL = [
[ ?n, TkComm.method(:num_or_str) ],
@@ -345,6 +379,24 @@ module TkEvent
nil
]
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
# setup tables to be used by scan_args, _get_subst_key, _get_all_subst_keys
#
# _get_subst_key() and _get_all_subst_keys() generates key-string
@@ -357,7 +409,8 @@ module TkEvent
# ( which are Tcl strings ) to ruby objects based on the key string
# that is generated by _get_subst_key() or _get_all_subst_keys().
#
- _setup_subst_table(KEY_TBL, PROC_TBL);
+ _setup_subst_table(KEY_TBL, PROC_TBL)
+ # _setup_subst_table(KEY_TBL, LONGKEY_TBL, PROC_TBL) # if use longname-keys
#
# NOTE: The order of parameters which passed to callback procedure is
@@ -405,6 +458,7 @@ module TkEvent
extra_args_tbl = klass._get_extra_args_tbl
if args.compact.size > 0
+ args.map!{|arg| klass._sym2subst(arg)}
args = args.join(' ')
keys = klass._get_subst_key(args)
diff --git a/ext/tk/lib/tk/font.rb b/ext/tk/lib/tk/font.rb
index de02d4957c..62d628c132 100644
--- a/ext/tk/lib/tk/font.rb
+++ b/ext/tk/lib/tk/font.rb
@@ -11,13 +11,18 @@ class TkFont
TkCommandNames = ['font'.freeze].freeze
- Tk_FontID = ["@font".freeze, "00000".taint].freeze
+ (Tk_FontID = ["@font".freeze, "00000".taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
Tk_FontNameTBL = TkCore::INTERP.create_table
Tk_FontUseTBL = TkCore::INTERP.create_table
TkCore::INTERP.init_ip_env{
- Tk_FontNameTBL.clear
- Tk_FontUseTBL.clear
+ Tk_FontNameTBL.mutex.synchronize{ Tk_FontNameTBL.clear }
+ Tk_FontUseTBL.mutex.synchronize{ Tk_FontUseTBL.clear }
}
# option_type : default => string
@@ -31,13 +36,26 @@ class TkFont
MetricType = Hash.new(?n)
MetricType['fixed'] = ?b
+ # system font names
+ SYSTEM_FONT_NAMES = []
+ def SYSTEM_FONT_NAMES.add(font_names)
+ (@mutex ||= Mutex.new).synchronize{
+ self.replace(self | font_names.map{|name| name.to_s})
+ }
+ end
+ def SYSTEM_FONT_NAMES.include?(name)
+ (@mutex ||= Mutex.new).synchronize{
+ super(name.to_s)
+ }
+ end
+
# set default font
case Tk::TK_VERSION
- when /^4\.*/
+ when /^4\..*/
DEFAULT_LATIN_FONT_NAME = 'a14'.freeze
DEFAULT_KANJI_FONT_NAME = 'k14'.freeze
- when /^8\.*/
+ when /^8\.[0-4]/
if JAPANIZED_TK
begin
fontnames = tk_call('font', 'names')
@@ -103,6 +121,15 @@ class TkFont
DEFAULT_LATIN_FONT_NAME = ltn.freeze
DEFAULT_KANJI_FONT_NAME = knj.freeze
+ when /^8\.[5-9]/, /^9\..*/
+ if tk_call('font', 'names') =~ /\bTkDefaultFont\b/
+ DEFAULT_LATIN_FONT_NAME = 'TkDefaultFont'.freeze
+ DEFAULT_KANJI_FONT_NAME = 'TkDefaultFont'.freeze
+ else
+ DEFAULT_LATIN_FONT_NAME = 'Helvetica'.freeze
+ DEFAULT_KANJI_FONT_NAME = 'mincho'.freeze
+ end
+
else # unknown version
DEFAULT_LATIN_FONT_NAME = 'Helvetica'.freeze
DEFAULT_KANJI_FONT_NAME = 'mincho'.freeze
@@ -121,6 +148,7 @@ class TkFont
unless compound.kind_of?(TkFont)
fail ArgumentError, "a TkFont object is expected for the 1st argument"
end
+
@compound = compound
case type
when 'kanji', 'latin', 'ascii'
@@ -145,6 +173,9 @@ class TkFont
def font
@compound.__send__(@type + '_font_id')
end
+ alias font_id font
+ alias name font
+ alias to_s font
def [](slot)
@compound.__send__(@type + '_configinfo', slot)
@@ -163,6 +194,14 @@ class TkFont
###################################
# class methods
###################################
+ def TkFont.is_system_font?(fnt)
+ # true --> system font which is available on the current system
+ # false --> not system font (or unknown system font)
+ # nil --> system font name, but not available on the current system
+ fnt = fnt.to_s
+ SYSTEM_FONT_NAMES.include?(fnt) && self.names.index(fnt) && true
+ end
+
def TkFont.actual(fnt, option=nil)
fnt = '{}' if fnt == ''
if fnt.kind_of?(TkFont)
@@ -171,6 +210,9 @@ class TkFont
actual_core(fnt, nil, option)
end
end
+ def TkFont.actual_hash(fnt, option=nil)
+ Hash[TkFont.actual_hash(fnt, option)]
+ end
def TkFont.actual_displayof(fnt, win, option=nil)
fnt = '{}' if fnt == ''
@@ -181,6 +223,9 @@ class TkFont
actual_core(fnt, win, option)
end
end
+ def TkFont.actual_hash_displayof(fnt, option=nil)
+ Hash[TkFont.actual_hash_displayof(fnt, option)]
+ end
def TkFont.configure(fnt, slot, value=None)
if fnt.kind_of?(TkFont)
@@ -234,6 +279,33 @@ class TkFont
metrics_core(fnt, nil, option)
end
end
+ def TkFont.metrics_hash(fnt, option=nil)
+ if option
+ val = TkFont.metrics(fnt, option)
+ case TkFont::MetricsType[option.to_s]
+ when ?n
+ val = TkComm::num_or_str(val)
+ when ?b
+ val = TkComm::bool(val)
+ else
+ # do nothing
+ end
+ return val
+ end
+
+ h = Hash[TkFont.metrics(fnt)]
+ h.keys.each{|k|
+ case TkFont::MetricsType[k.to_s]
+ when ?n
+ h[k] = TkComm::num_or_str(h[k])
+ when ?b
+ h[k] = TkComm::bool(h[k])
+ else
+ # do nothing
+ end
+ }
+ h
+ end
def TkFont.metrics_displayof(fnt, win, option=nil)
fnt = '{}' if fnt == ''
@@ -244,13 +316,40 @@ class TkFont
metrics_core(fnt, win, option)
end
end
+ def TkFont.metrics_hash_displayof(fnt, win, option=nil)
+ if option
+ val = TkFont.metrics_displayof(fnt, win, option)
+ case TkFont::MetricsType[option.to_s]
+ when ?n
+ val = TkComm::num_or_str(val)
+ when ?b
+ val = TkComm::bool(val)
+ else
+ # do nothing
+ end
+ return val
+ end
+
+ h = Hash[TkFont.metrics_displayof(fnt, win, option)]
+ h.keys.each{|k|
+ case TkFont::MetricsType[k.to_s]
+ when ?n
+ h[k] = TkComm::num_or_str(h[k])
+ when ?b
+ h[k] = TkComm::bool(h[k])
+ else
+ # do nothing
+ end
+ }
+ h
+ end
def TkFont.families(win=nil)
case (Tk::TK_VERSION)
- when /^4\.*/
+ when /^4\..*/
['fixed']
- when /^8\.*/
+ when /^8\..*/
if win
tk_split_simplelist(tk_call('font', 'families', '-displayof', win))
else
@@ -261,13 +360,16 @@ class TkFont
def TkFont.names
case (Tk::TK_VERSION)
- when /^4\.*/
+ when /^4\..*/
r = ['fixed']
r += ['a14', 'k14'] if JAPANIZED_TK
- Tk_FontNameTBL.each_value{|obj| r.push(obj)}
- r | []
+ Tk_FontNameTBL.mutex.synchronize{
+ Tk_FontNameTBL.each_value{|obj| r.push(obj)}
+ }
+ #r | []
+ r.uniq
- when /^8\.*/
+ when /^8\..*/
tk_split_simplelist(tk_call('font', 'names'))
end
@@ -285,10 +387,15 @@ class TkFont
end
def TkFont.get_obj(name)
+ name = name.to_s
if name =~ /^(@font[0-9]+)(|c|l|k)$/
- Tk_FontNameTBL[$1]
+ Tk_FontNameTBL.mutex.synchronize{
+ Tk_FontNameTBL[$1]
+ }
else
- nil
+ Tk_FontNameTBL.mutex.synchronize{
+ Tk_FontNameTBL[name]
+ }
end
end
@@ -298,7 +405,7 @@ class TkFont
path = [win, tag, key].join(';')
case (Tk::TK_VERSION)
- when /^4\.*/
+ when /^4\..*/
regexp = /^-(|kanji)#{key} /
conf_list = tk_split_simplelist(tk_call(*args)).
@@ -324,7 +431,7 @@ class TkFont
TkFont.new(ltn, knj).call_font_configure([path, key], *args)
- when /^8\.*/
+ when /^8\.[0-4]/
regexp = /^-#{key} /
conf_list = tk_split_simplelist(tk_call(*args)).
@@ -360,26 +467,66 @@ class TkFont
compound = []
end
if compound == []
- TkFont.new(fnt).call_font_configure([path, key], *args)
+ if TkFont.is_system_font?(fnt)
+ TkNamedFont.new(fnt).call_font_configure([path, key], *args)
+ else
+ TkFont.new(fnt).call_font_configure([path, key], *args)
+ end
else
TkFont.new(compound[0],
compound[1]).call_font_configure([path, key], *args)
end
end
+
+ when /^8\.[5-9]/, /^9\..*/
+ regexp = /^-#{key} /
+
+ conf_list = tk_split_simplelist(tk_call(*args)).
+ find_all{|prop| prop =~ regexp}.
+ collect{|prop| tk_split_simplelist(prop)}
+
+ if conf_list.size == 0
+ raise RuntimeError, "the widget may not support 'font' option"
+ end
+
+ args << {}
+
+ optkey = "-#{key}"
+
+ info = conf_list.find{|conf| conf[0] == optkey}
+ fnt = info[-1]
+ fnt = nil if fnt == [] || fnt == ""
+
+ unless fnt
+ # create dummy
+ # TkFont.new(nil, nil).call_font_configure([path, key], *args)
+ dummy_fnt = TkFont.allocate
+ dummy_fnt.instance_eval{ init_dummy_fontobj() }
+ dummy_fnt
+ else
+ if TkFont.is_system_font?(fnt)
+ TkNamedFont.new(fnt).call_font_configure([path, key], *args)
+ else
+ TkFont.new(fnt).call_font_configure([path, key], *args)
+ end
+ end
end
end
def TkFont.used_on(path=nil)
- if path
- Tk_FontUseTBL[path]
- else
- Tk_FontUseTBL.values | []
- end
+ Tk_FontUseTBL.mutex.synchronize{
+ if path
+ Tk_FontUseTBL[path]
+ else
+ # Tk_FontUseTBL.values | []
+ Tk_FontUseTBL.values.uniq
+ end
+ }
end
def TkFont.failsafe(font)
begin
- if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
+ if /^8\..*/ === Tk::TK_VERSION && JAPANIZED_TK
tk_call('font', 'failsafe', font)
end
rescue
@@ -392,15 +539,20 @@ class TkFont
private
###################################
def init_dummy_fontobj
- @id = Tk_FontID.join(TkCore::INTERP._ip_id_)
- Tk_FontID[1].succ!
- Tk_FontNameTBL[@id] = self
+ Tk_FontID.mutex.synchronize{
+ @id = Tk_FontID.join(TkCore::INTERP._ip_id_)
+ Tk_FontID[1].succ!
+ }
+ Tk_FontNameTBL.mutex.synchronize{
+ Tk_FontNameTBL[@id] = self
+ }
- @latin_desscendant = nil
- @kanji_desscendant = nil
+ # @latin_desscendant = nil
+ # @kanji_desscendant = nil
+ @descendant = [nil, nil] # [latin, kanji]
case (Tk::TK_VERSION)
- when /^4\.*/
+ when /^4\..*/
@latinfont = ""
@kanjifont = ""
if JAPANIZED_TK
@@ -436,13 +588,23 @@ class TkFont
ltn = '{}' if ltn == ''
knj = '{}' if knj == ''
- # @id = Tk_FontID.join('')
- @id = Tk_FontID.join(TkCore::INTERP._ip_id_)
- Tk_FontID[1].succ!
- Tk_FontNameTBL[@id] = self
+ Tk_FontID.mutex.synchronize{
+ # @id = Tk_FontID.join('')
+ @id = Tk_FontID.join(TkCore::INTERP._ip_id_)
+ Tk_FontID[1].succ!
+ }
+ Tk_FontNameTBL.mutex.synchronize{
+ Tk_FontNameTBL[@id] = self
+ }
+
+ # @latin_desscendant = nil
+ # @kanji_desscendant = nil
+ @descendant = [nil, nil] # [latin, kanji]
- @latin_desscendant = nil
- @kanji_desscendant = nil
+ # @latinfont = @id + 'l'
+ # @kanjifont = @id + 'k'
+ # @compoundfont = @id + 'c'
+ # @fontslot = {}
if knj.kind_of?(Hash) && !keys
keys = knj
@@ -474,7 +636,7 @@ class TkFont
if ltn
if JAPANIZED_TK && !knj
- if Tk::TK_VERSION =~ /^4.*/
+ if Tk::TK_VERSION =~ /^4..*/
knj = DEFAULT_KANJI_FONT_NAME
else
knj = ltn
@@ -625,9 +787,14 @@ class TkFont
if JAPANIZED_TK
@compoundfont = [[@latinfont], [@kanjifont]]
@fontslot = {'font'=>@latinfont, 'kanjifont'=>@kanjifont}
+ # @fontslot.clear
+ # @fontslot['font'] = @latinfont
+ # @fontslot['kanjifont'] = @kanjifont
else
@compoundfont = @latinfont
@fontslot = {'font'=>@latinfont}
+ # @fontslot.clear
+ # @fontslot['font'] = @latinfont
end
end
@@ -753,6 +920,7 @@ class TkFont
end
@fontslot = {'font'=>@compoundfont}
+ # @fontslot['font'] = @compoundfont
begin
tk_call('font', 'create', @compoundfont,
'-compound', [@latinfont, @kanjifont], *hash_kv(keys))
@@ -833,6 +1001,7 @@ class TkFont
end
@fontslot = {'font'=>@compoundfont}
+ # @fontslot['font'] = @compoundfont
tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
end
end
@@ -887,25 +1056,39 @@ class TkFont
keys = _symbolkey2str(args.pop).update(fontslot)
args.concat(hash_kv(keys))
- tk_call(*args)
- Tk_FontUseTBL[[win, tag, optkey].join(';')] = self
+ begin
+ tk_call(*args)
+ rescue => e
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ fail e
+ end
+ end
+ Tk_FontUseTBL.mutex.synchronize{
+ Tk_FontUseTBL[[win, tag, optkey].join(';')] = self
+ }
self
end
def used
ret = []
- Tk_FontUseTBL.each{|key,value|
+ table = nil
+ Tk_FontUseTBL.mutex.synchronize{
+ table = Tk_FontUseTBL.clone # to avoid deadlock
+ }
+ table.each{|key,value|
next unless self == value
if key.include?(';')
win, tag, optkey = key.split(';')
winobj = tk_tcl2ruby(win)
- if winobj.kind_of? TkText
+ #if winobj.kind_of? TkText
+ if winobj.kind_of?(TkText) || winobj.kind_of?(Tk::Text)
if optkey
ret.push([winobj, winobj.tagid2obj(tag), optkey])
else
ret.push([winobj, winobj.tagid2obj(tag)])
end
- elsif winobj.kind_of? TkCanvas
+ #elsif winobj.kind_of? TkCanvas
+ elsif winobj.kind_of?(TkCanvas) || winobj.kind_of?(Tk::Canvas)
if (tagobj = TkcTag.id2obj(winobj, tag)).kind_of? TkcTag
if optkey
ret.push([winobj, tagobj, optkey])
@@ -925,7 +1108,8 @@ class TkFont
ret.push([winobj, tag])
end
end
- elsif winobj.kind_of? TkMenu
+ #elsif winobj.kind_of? TkMenu
+ elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu)
if optkey
ret.push([winobj, tag, optkey])
else
@@ -957,6 +1141,8 @@ class TkFont
@compoundfont
end
alias font_id font
+ alias name font
+ alias to_s font
def latin_font_id
@latinfont
@@ -964,11 +1150,18 @@ class TkFont
def latin_font
# @latinfont
+ if @descendant[0] # [0] -> latin
+ @descendant[0]
+ else
+ @descendant[0] = DescendantFont.new(self, 'latin')
+ end
+=begin
if @latin_descendant
@latin_descendant
else
@latin_descendant = DescendantFont.new(self, 'latin')
end
+=end
end
alias latinfont latin_font
@@ -978,50 +1171,87 @@ class TkFont
def kanji_font
# @kanjifont
+ if @descendant[1] # [1] -> kanji
+ @descendant[1]
+ else
+ @descendant[1] = DescendantFont.new(self, 'kanji')
+ end
+=begin
if @kanji_descendant
@kanji_descendant
else
@kanji_descendant = DescendantFont.new(self, 'kanji')
end
+=end
end
alias kanjifont kanji_font
def actual(option=nil)
actual_core(@compoundfont, nil, option)
end
+ def actual_hash(option=nil)
+ Hash[actual(option)]
+ end
def actual_displayof(win, option=nil)
win = '.' unless win
actual_core(@compoundfont, win, option)
end
+ def actual_hash_displayof(win, option=nil)
+ Hash[actual_displayof(win, option)]
+ end
def latin_actual(option=nil)
- actual_core(@latinfont, nil, option)
+ if @latinfont == nil
+ actual_core(@compoundfont, nil, option) # use @compoundfont
+ else
+ actual_core(@latinfont, nil, option)
+ end
+ end
+ def latin_actual_hash(option=nil)
+ Hash[latin_actual(option)]
end
def latin_actual_displayof(win, option=nil)
win = '.' unless win
- actual_core(@latinfont, win, option)
+ if @latinfont == nil
+ actual_core(@compoundfont, win, option) # use @compoundfont
+ else
+ actual_core(@latinfont, win, option)
+ end
+ end
+ def latin_actual_hash_displayof(win, option=nil)
+ Hash[latin_actual_displayof(win, option)]
end
def kanji_actual(option=nil)
#if JAPANIZED_TK
- if @kanjifont != ""
+ if @kanjifont == nil
+ actual_core(@compoundfont, nil, option) # use @compoundfont
+ elsif @kanjifont != ""
actual_core(@kanjifont, nil, option)
else
actual_core_tk4x(nil, nil, option)
end
end
+ def kanji_actual_hash(option=nil)
+ Hash[kanji_actual(option)]
+ end
def kanji_actual_displayof(win, option=nil)
#if JAPANIZED_TK
- if @kanjifont != ""
+ if @kanjifont == nil
+ actual_core(@compoundfont, nil, option) # use @compoundfont
+ elsif @kanjifont != ""
win = '.' unless win
actual_core(@kanjifont, win, option)
else
actual_core_tk4x(nil, win, option)
end
end
+ def kanji_actual_hash_displayof(win, option=nil)
+ Hash[kanji_actual_displayof(win, option)]
+ end
def [](slot)
configinfo slot
@@ -1065,10 +1295,15 @@ class TkFont
configinfo(slot)
end
end
+ def latin_current_configinfo(slot=nil)
+ Hash[latin_configinfo(slot)]
+ end
def kanji_configure(slot, value=None)
#if JAPANIZED_TK
- if @kanjifont != ""
+ if @kanjifont == nil
+ configure_core(@compoundfont, slot, value) # use @compoundfont
+ elsif @kanjifont != ""
configure_core(@kanjifont, slot, value)
configure('size'=>configinfo('size')) # to reflect new configuration
else
@@ -1080,13 +1315,18 @@ class TkFont
def kanji_configinfo(slot=nil)
#if JAPANIZED_TK
- if @kanjifont != ""
+ if @kanjifont == nil
+ configure_core(@compoundfont, slot) # use @compoundfont
+ elsif @kanjifont != ""
configinfo_core(@kanjifont, slot)
else
#[]
configinfo(slot)
end
end
+ def kanji_current_configinfo(slot=nil)
+ Hash[kanji_configinfo(slot)]
+ end
def replace(ltn, knj=None)
knj = ltn if knj == None
@@ -1096,12 +1336,30 @@ class TkFont
end
def latin_replace(ltn)
- latin_replace_core(ltn)
- reset_pointadjust
+ if @latinfont
+ latin_replace_core(ltn)
+ reset_pointadjust
+ else
+ # not compound font -> copy properties of ltn
+ latinkeys = {}
+ begin
+ actual_core(ltn).each{|key,val| latinkeys[key] = val}
+ rescue
+ latinkeys = {}
+ end
+ begin
+ tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys))
+ rescue
+ # not exist? (deleted?) -> create font
+ tk_call('font', 'create', @compoundfont, *hash_kv(latinkeys))
+ end
+ end
+
self
end
def kanji_replace(knj)
+ return self unless @kanjifont # ignore
kanji_replace_core(knj)
reset_pointadjust
self
@@ -1119,41 +1377,215 @@ class TkFont
def metrics(option=nil)
metrics_core(@compoundfont, nil, option)
end
+ def metrics_hash(option=nil)
+ if option
+ val = metrics(option)
+ case TkFont::MetricsType[option.to_s]
+ when ?n
+ val = TkComm::num_or_str(val)
+ when ?b
+ val = TkComm::bool(val)
+ else
+ # do nothing
+ end
+ return val
+ end
+
+ h = Hash[metrics(option)]
+ h.keys.each{|k|
+ case TkFont::MetricsType[k.to_s]
+ when ?n
+ h[k] = TkComm::num_or_str(h[k])
+ when ?b
+ h[k] = TkComm::bool(h[k])
+ else
+ # do nothing
+ end
+ }
+ h
+ end
def metrics_displayof(win, option=nil)
win = '.' unless win
metrics_core(@compoundfont, win, option)
end
+ def metrics_hash_displayof(win, option=nil)
+ if option
+ val = metrics_displayof(win, option)
+ case TkFont::MetricsType[option.to_s]
+ when ?n
+ val = TkComm::num_or_str(val)
+ when ?b
+ val = TkComm::bool(val)
+ else
+ # do nothing
+ end
+ return val
+ end
+
+ h = Hash[metrics_displayof(win, option)]
+ h.keys.each{|k|
+ case TkFont::MetricsType[k.to_s]
+ when ?n
+ h[k] = TkComm::num_or_str(h[k])
+ when ?b
+ h[k] = TkComm::bool(h[k])
+ else
+ # do nothing
+ end
+ }
+ h
+ end
def latin_metrics(option=nil)
- metrics_core(@latinfont, nil, option)
+ if @latinfont == nil
+ metrics_core(@compoundfont, nil, option) # use @compoundfont
+ else
+ metrics_core(@latinfont, nil, option)
+ end
+ end
+ def latin_metrics_hash(option=nil)
+ if option
+ val = latin_metrics(option)
+ case TkFont::MetricsType[option.to_s]
+ when ?n
+ val = TkComm::num_or_str(val)
+ when ?b
+ val = TkComm::bool(val)
+ else
+ # do nothing
+ end
+ return val
+ end
+
+ h = Hash[latin_metrics(option)]
+ h.keys.each{|k|
+ case TkFont::MetricsType[k.to_s]
+ when ?n
+ h[k] = TkComm::num_or_str(h[k])
+ when ?b
+ h[k] = TkComm::bool(h[k])
+ else
+ # do nothing
+ end
+ }
+ h
end
def latin_metrics_displayof(win, option=nil)
win = '.' unless win
- metrics_core(@latinfont, win, option)
+ if @latinfont == nil
+ metrics_core(@compoundfont, win, option) # use @compoundfont
+ else
+ metrics_core(@latinfont, win, option)
+ end
+ end
+ def latin_metrics_hash_displayof(win, option=nil)
+ if option
+ val = latin_metrics_displayof(win, option)
+ case TkFont::MetricsType[option.to_s]
+ when ?n
+ val = TkComm::num_or_str(val)
+ when ?b
+ val = TkComm::bool(val)
+ else
+ # do nothing
+ end
+ return val
+ end
+
+ h = Hash[latin_metrics_displayof(win, option)]
+ h.keys.each{|k|
+ case TkFont::MetricsType[k.to_s]
+ when ?n
+ h[k] = TkComm::num_or_str(h[k])
+ when ?b
+ h[k] = TkComm::bool(h[k])
+ else
+ # do nothing
+ end
+ }
+ h
end
def kanji_metrics(option=nil)
- if JAPANIZED_TK
+ if @latinfont == nil
+ metrics_core(@compoundfont, nil, option) # use @compoundfont
+ elsif JAPANIZED_TK
metrics_core(@kanjifont, nil, option)
else
metrics_core_tk4x(nil, nil, option)
end
end
+ def kanji_metrics_hash(option=nil)
+ if option
+ val = kanji_metrics(option)
+ case TkFont::MetricsType[option.to_s]
+ when ?n
+ val = TkComm::num_or_str(val)
+ when ?b
+ val = TkComm::bool(val)
+ else
+ # do nothing
+ end
+ return val
+ end
+
+ h = Hash[kanji_metrics(option)]
+ h.keys.each{|k|
+ case TkFont::MetricsType[k.to_s]
+ when ?n
+ h[k] = TkComm::num_or_str(h[k])
+ when ?b
+ h[k] = TkComm::bool(h[k])
+ else
+ # do nothing
+ end
+ }
+ h
+ end
def kanji_metrics_displayof(win, option=nil)
- if JAPANIZED_TK
- win = '.' unless win
+ win = '.' unless win
+ if @latinfont == nil
+ metrics_core(@compoundfont, win, option) # use @compoundfont
+ elsif JAPANIZED_TK
metrics_core(@kanjifont, win, option)
else
metrics_core_tk4x(nil, win, option)
end
end
+ def kanji_metrics_hash_displayof(win, option=nil)
+ if option
+ val = kanji_metrics_displayof(win, option)
+ case TkFont::MetricsType[option.to_s]
+ when ?n
+ val = TkComm::num_or_str(val)
+ when ?b
+ val = TkComm::bool(val)
+ else
+ # do nothing
+ end
+ return val
+ end
+
+ h = Hash[kanji_metrics_displayof(win, option)]
+ h.keys.each{|k|
+ case TkFont::MetricsType[k.to_s]
+ when ?n
+ h[k] = TkComm::num_or_str(h[k])
+ when ?b
+ h[k] = TkComm::bool(h[k])
+ else
+ # do nothing
+ end
+ }
+ h
+ end
def reset_pointadjust
begin
- if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK
+ if /^8\..*/ === Tk::TK_VERSION && JAPANIZED_TK
configure('pointadjust' => latin_actual.assoc('size')[1].to_f /
kanji_actual.assoc('size')[1].to_f )
end
@@ -1166,7 +1598,7 @@ class TkFont
# private alias
###################################
case (Tk::TK_VERSION)
- when /^4\.*/
+ when /^4\..*/
alias create_latinfont create_latinfont_tk4x
alias create_kanjifont create_kanjifont_tk4x
alias create_compoundfont create_compoundfont_tk4x
@@ -1449,7 +1881,7 @@ module TkFont::CoreMethods
end
else
l = tk_split_simplelist(tk_call('font', 'configure', font))
- r = {}
+ h = {}
while key=l.shift
if key == '-compound'
l.shift
@@ -1458,45 +1890,57 @@ module TkFont::CoreMethods
val = l.shift
case TkFont::OptionType[key]
when ?n
- r.push [key, num_or_str(val)]
+ h[key] = num_or_str(val)
when ?b
- r.push [key, bool(val)]
+ h[key] = bool(val)
else
- r.push [key, val]
+ h[key] = val
end
end
end
- r
+ h
end
end
def delete_core_tk4x
- TkFont::Tk_FontNameTBL.delete(@id)
- TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self}
+ TkFont::Tk_FontNameTBL.mutex.synchronize{
+ TkFont::Tk_FontNameTBL.delete(@id)
+ }
+ TkFont::Tk_FontUseTBL.mutex.synchronize{
+ TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self}
+ }
end
def delete_core_tk8x
begin
- tk_call('font', 'delete', @latinfont)
+ tk_call('font', 'delete', @latinfont) if @latinfont
rescue
end
begin
- tk_call('font', 'delete', @kanjifont)
+ tk_call('font', 'delete', @kanjifont) if @kanjifont
rescue
end
begin
- tk_call('font', 'delete', @compoundfont)
+ tk_call('font', 'delete', @compoundfont) if @compoundfont
rescue
end
- TkFont::Tk_FontNameTBL.delete(@id)
- TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self}
+ TkFont::Tk_FontNameTBL.mutex.synchronize{
+ TkFont::Tk_FontNameTBL.delete(@id)
+ }
+ TkFont::Tk_FontUseTBL.mutex.synchronize{
+ TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self}
+ }
end
def latin_replace_core_tk4x(ltn)
create_latinfont_tk4x(ltn)
@compoundfont[0] = [@latinfont] if JAPANIZED_TK
@fontslot['font'] = @latinfont
- TkFont::Tk_FontUseTBL.dup.each{|w, fobj|
+ table = nil
+ TkFont::Tk_FontUseTBL.mutex.synchronize{
+ table = TkFont::Tk_FontUseTBL.clone
+ }
+ table.each{|w, fobj|
if self == fobj
begin
if w.include?(';')
@@ -1504,11 +1948,14 @@ module TkFont::CoreMethods
optkey = 'font' if optkey == nil || optkey == ''
winobj = tk_tcl2ruby(win)
# winobj.tagfont_configure(tag, {'font'=>@latinfont})
- if winobj.kind_of? TkText
+ #if winobj.kind_of? TkText
+ if winobj.kind_of?(TkText) || winobj.kind_of?(Tk::Text)
tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @latinfont)
- elsif winobj.kind_of? TkCanvas
+ #elsif winobj.kind_of? TkCanvas
+ elsif winobj.kind_of?(TkCanvas) || winobj.kind_of?(Tk::Canvas)
tk_call(win, 'itemconfigure', tag, "-#{optkey}", @latinfont)
- elsif winobj.kind_of? TkMenu
+ #elsif winobj.kind_of? TkMenu
+ elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu)
tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont)
else
raise RuntimeError, "unknown widget type"
@@ -1518,7 +1965,9 @@ module TkFont::CoreMethods
tk_call(w, 'configure', '-font', @latinfont)
end
rescue
- TkFont::Tk_FontUseTBL.delete(w)
+ TkFont::Tk_FontUseTBL.mutex.synchronize{
+ TkFont::Tk_FontUseTBL.delete(w)
+ }
end
end
}
@@ -1531,7 +1980,11 @@ module TkFont::CoreMethods
create_kanjifont_tk4x(knj)
@compoundfont[1] = [@kanjifont]
@fontslot['kanjifont'] = @kanjifont
- TkFont::Tk_FontUseTBL.dup.each{|w, fobj|
+ table = nil
+ TkFont::Tk_FontUseTBL.mutex.synchronize{
+ table = TkFont::Tk_FontUseTBL.clone
+ }
+ table.dup.each{|w, fobj|
if self == fobj
begin
if w.include?(';')
@@ -1539,11 +1992,14 @@ module TkFont::CoreMethods
optkey = 'kanjifont' unless optkey
winobj = tk_tcl2ruby(win)
# winobj.tagfont_configure(tag, {'kanjifont'=>@kanjifont})
- if winobj.kind_of? TkText
+ #if winobj.kind_of? TkText
+ if winobj.kind_of?(TkText) || winobj.kind_of?(Tk::Text)
tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @kanjifont)
- elsif winobj.kind_of? TkCanvas
+ #elsif winobj.kind_of? TkCanvas
+ elsif winobj.kind_of?(TkCanvas) || winobj.kind_of?(Tk::Canvas)
tk_call(win, 'itemconfigure', tag, "-#{optkey}", @kanjifont)
- elsif winobj.kind_of? TkMenu
+ #elsif winobj.kind_of? TkMenu
+ elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu)
tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont)
else
raise RuntimeError, "unknown widget type"
@@ -1553,7 +2009,9 @@ module TkFont::CoreMethods
tk_call(w, 'configure', '-kanjifont', @kanjifont)
end
rescue
- TkFont::Tk_FontUseTBL.delete(w)
+ Tk_FontUseTBL.mutex.synchronize{
+ TkFont::Tk_FontUseTBL.delete(w)
+ }
end
end
}
@@ -1618,8 +2076,11 @@ module TkFont::CoreMethods
rescue
latinkeys = {}
end
- if latinkeys != {}
+ begin
tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys))
+ rescue
+ # not exist? (deleted?) -> create font
+ tk_call('font', 'create', @compoundfont, *hash_kv(latinkeys))
end
end
self
@@ -1711,6 +2172,13 @@ module TkFont::CoreMethods
r = []
while key=l.shift
r.push [key[1..-1], l.shift.to_i]
+=begin
+ if key == '-fixed' # boolean value
+ r.push [key[1..-1], bool(l.shift)]
+ else
+ r.push [key[1..-1], l.shift.to_i]
+ end
+=end
end
r
end
@@ -1720,7 +2188,7 @@ module TkFont::CoreMethods
# private alias
###################################
case (Tk::TK_VERSION)
- when /^4\.*/
+ when /^4\..*/
alias actual_core actual_core_tk4x
alias configure_core configure_core_tk4x
alias configinfo_core configinfo_core_tk4x
@@ -1760,3 +2228,117 @@ class TkFont
include TkFont::CoreMethods
extend TkFont::CoreMethods
end
+
+class TkNamedFont < TkFont
+ # for built-in named fonts
+ def TkNamedFont.find(name)
+ name = name.to_s
+ unless (obj = Tk_FontNameTBL[name])
+ obj = self.new(name) if TkFont.is_system_font?(name)
+ end
+ obj
+ end
+
+ def TkNamedFont.new(name, keys=nil)
+ name = name.to_s
+ obj = nil
+ Tk_FontNameTBL.mutex.synchronize{
+ unless (obj = Tk_FontNameTBL[name])
+ (obj = self.allocate).instance_eval{
+ @id = @compoundfont = name.to_s
+ @latinfont = nil
+ @kanjifont = nil
+ @descendant = [self, self] # [latin, kanji] : dummy
+ Tk_FontNameTBL[@id] = self
+ }
+ end
+ }
+ obj.instance_eval{ initialize(name, keys) }
+ obj
+ end
+
+ ###########################
+ private
+ ###########################
+ def initialize(name, keys=nil)
+ @id = @compoundfont = name.to_s
+
+ # if not exist named font, create it.
+ begin
+ if keys
+ tk_call('font', 'configure', @compoundfont, keys)
+ else
+ tk_call('font', 'configure', @compoundfont)
+ end
+ rescue
+ # the named font doesn't exist -> create
+ if keys
+ tk_call('font', 'create', @compoundfont, keys)
+ else
+ tk_call('font', 'create', @compoundfont)
+ end
+ end
+ end
+
+ def create_latinfont(fnt)
+ # ignore
+ end
+ def create_kanjifont(fnt)
+ # ignore
+ end
+ def create_compoundfont(ltn, knj, keys)
+ # ignore
+ end
+
+ ###########################
+ public
+ ###########################
+ def latin_font_id
+ @compoundfont
+ end
+ def kanji_font_id
+ @compoundfont
+ end
+end
+
+#######################################
+# define system font names
+#######################################
+if Tk::TCL_MAJOR_VERSION > 8 ||
+ (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5)
+ # add standard fonts of Tcl/Tk 8.5+
+ TkFont::SYSTEM_FONT_NAMES.add [
+ 'TkDefaultFont', 'TkTextFont', 'TkFixedFont', 'TkMenuFont',
+ 'TkHeadingFont', 'TkCaptionFont', 'TkSmallCaptionFont',
+ 'TkIconFont', 'TkTooltipFont'
+ ]
+end
+
+# platform-specific fonts
+# -- windows
+TkFont::SYSTEM_FONT_NAMES.add [
+ 'ansifixed', 'ansi', 'device', 'oemfixed', 'systemfixed', 'system'
+]
+
+# -- macintosh, macosx
+TkFont::SYSTEM_FONT_NAMES.add ['system', 'application']
+
+if Tk::TCL_MAJOR_VERSION > 8 ||
+ (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5)
+ TkFont::SYSTEM_FONT_NAMES.add ['menu']
+end
+
+# -- macosx (Aqua theme)
+if Tk::TCL_MAJOR_VERSION > 8 ||
+ (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5)
+ TkFont::SYSTEM_FONT_NAMES.add [
+ 'systemSystemFont', 'systemEmphasizedSystemFont',
+ 'systemSmallSystemFont', 'systemSmallEmphasizedSystemFont',
+ 'systemApplicationFont', 'systemLabelFont', 'systemViewsFont',
+ 'systemMenuTitleFont', 'systemMenuItemFont', 'systemMenuItemMarkFont',
+ 'systemMenuItemCmdKeyFont', 'systemWindowTitleFont',
+ 'systemPushButtonFont', 'systemUtilityWindowTitleFont',
+ 'systemAlertHeaderFont', 'systemToolbarFont', 'systemMiniSystemFont',
+ 'systemDetailSystemFont', 'systemDetailEmphasizedSystemFont'
+ ]
+end
diff --git a/ext/tk/lib/tk/frame.rb b/ext/tk/lib/tk/frame.rb
index 6636fef5b5..263b160f29 100644
--- a/ext/tk/lib/tk/frame.rb
+++ b/ext/tk/lib/tk/frame.rb
@@ -3,7 +3,7 @@
#
require 'tk'
-class TkFrame<TkWindow
+class Tk::Frame<TkWindow
TkCommandNames = ['frame'.freeze].freeze
WidgetClassName = 'Frame'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -126,3 +126,6 @@ class TkFrame<TkWindow
end
end
end
+
+#TkFrame = Tk::Frame unless Object.const_defined? :TkFrame
+Tk.__set_toplevel_aliases__(:Tk, Tk::Frame, :TkFrame)
diff --git a/ext/tk/lib/tk/grid.rb b/ext/tk/lib/tk/grid.rb
index 10fdf3569b..0dfd7263a7 100644
--- a/ext/tk/lib/tk/grid.rb
+++ b/ext/tk/lib/tk/grid.rb
@@ -22,6 +22,7 @@ module TkGrid
list(tk_call_without_enc('grid', 'bbox', *args))
end
+=begin
def configure(win, *args)
if args[-1].kind_of?(Hash)
opts = args.pop
@@ -53,6 +54,48 @@ module TkGrid
tk_call_without_enc('grid', 'configure', *params)
end
end
+=end
+ def configure(*args)
+ if args[-1].kind_of?(Hash)
+ opts = args.pop
+ else
+ opts = {}
+ end
+ fail ArgumentError, 'no widget is given' if args.empty?
+ params = []
+ args.flatten(1).each{|win|
+ case win
+ when '-', ?- # RELATIVE PLACEMENT (increase columnspan)
+ params.push('-')
+ when /^-+$/ # RELATIVE PLACEMENT (increase columnspan)
+ params.concat(win.to_s.split(//))
+ when '^', ?^ # RELATIVE PLACEMENT (increase rowspan)
+ params.push('^')
+ when /^\^+$/ # RELATIVE PLACEMENT (increase rowspan)
+ params.concat(win.to_s.split(//))
+ when 'x', :x, ?x, nil, '' # RELATIVE PLACEMENT (empty column)
+ params.push('x')
+ when /^x+$/ # RELATIVE PLACEMENT (empty column)
+ params.concat(win.to_s.split(//))
+ else
+ params.push(_epath(win))
+ end
+ }
+ opts.each{|k, v|
+ params.push("-#{k}")
+ params.push(_epath(v)) # have to use 'epath' (hash_kv() is unavailable)
+ }
+ if Tk::TCL_MAJOR_VERSION < 8 ||
+ (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION <= 3)
+ if params[0] == '-' || params[0] == 'x' || params[0] == '^'
+ tk_call_without_enc('grid', *params)
+ else
+ tk_call_without_enc('grid', 'configure', *params)
+ end
+ else
+ tk_call_without_enc('grid', 'configure', *params)
+ end
+ end
alias grid configure
def columnconfigure(master, index, args)
@@ -61,12 +104,14 @@ module TkGrid
tk_call_without_enc("grid", 'columnconfigure',
master, index, *hash_kv(args))
end
+ alias column columnconfigure
def rowconfigure(master, index, args)
# master = master.epath if master.kind_of?(TkObject)
master = _epath(master)
tk_call_without_enc("grid", 'rowconfigure', master, index, *hash_kv(args))
end
+ alias row rowconfigure
def columnconfiginfo(master, index, slot=nil)
# master = master.epath if master.kind_of?(TkObject)
@@ -189,10 +234,10 @@ module TkGrid
list(tk_call_without_enc('grid', 'slaves', master, *hash_kv(args)))
end
- module_function :bbox, :forget, :propagate, :info
+ module_function :anchor, :bbox, :add, :forget, :propagate, :info
module_function :remove, :size, :slaves, :location
module_function :grid, :configure, :columnconfigure, :rowconfigure
- module_function :columnconfiginfo, :rowconfiginfo
+ module_function :column, :row, :columnconfiginfo, :rowconfiginfo
end
=begin
def TkGrid(win, *args)
diff --git a/ext/tk/lib/tk/image.rb b/ext/tk/lib/tk/image.rb
index 35e2c4e394..dffdc19644 100644
--- a/ext/tk/lib/tk/image.rb
+++ b/ext/tk/lib/tk/image.rb
@@ -10,9 +10,16 @@ class TkImage<TkObject
TkCommandNames = ['image'.freeze].freeze
Tk_IMGTBL = TkCore::INTERP.create_table
- Tk_Image_ID = ['i'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ Tk_IMGTBL.clear }
+ (Tk_Image_ID = ['i'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ Tk_IMGTBL.mutex.synchronize{ Tk_IMGTBL.clear }
+ }
def self.new(keys=nil)
if keys.kind_of?(Hash)
@@ -27,7 +34,10 @@ class TkImage<TkObject
obj = name
else
name = _get_eval_string(name)
- obj = Tk_IMGTBL[name]
+ obj = nil
+ Tk_IMGTBL.mutex.synchronize{
+ obj = Tk_IMGTBL[name]
+ }
end
if obj
if !(keys[:without_creating] || keys['without_creating'])
@@ -43,7 +53,13 @@ class TkImage<TkObject
end
end
end
- super(keys)
+ (obj = self.allocate).instance_eval{
+ Tk_IMGTBL.mutex.synchronize{
+ initialize(keys)
+ Tk_IMGTBL[@path] = self
+ }
+ }
+ obj
end
def initialize(keys=nil)
@@ -55,19 +71,22 @@ class TkImage<TkObject
without_creating = keys.delete('without_creating')
end
unless @path
- # @path = Tk_Image_ID.join('')
- @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_)
- Tk_Image_ID[1].succ!
+ Tk_Image_ID.mutex.synchronize{
+ # @path = Tk_Image_ID.join('')
+ @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_)
+ Tk_Image_ID[1].succ!
+ }
end
unless without_creating
tk_call_without_enc('image', 'create',
@type, @path, *hash_kv(keys, true))
end
- Tk_IMGTBL[@path] = self
end
def delete
- Tk_IMGTBL.delete(@id) if @id
+ Tk_IMGTBL.mutex.synchronize{
+ Tk_IMGTBL.delete(@id) if @id
+ }
tk_call_without_enc('image', 'delete', @path)
self
end
@@ -85,8 +104,10 @@ class TkImage<TkObject
end
def TkImage.names
- Tk.tk_call_without_enc('image', 'names').split.collect!{|id|
- (Tk_IMGTBL[id])? Tk_IMGTBL[id] : id
+ Tk_IMGTBL.mutex.synchronize{
+ Tk.tk_call_without_enc('image', 'names').split.collect!{|id|
+ (Tk_IMGTBL[id])? Tk_IMGTBL[id] : id
+ }
}
end
@@ -135,7 +156,7 @@ class TkPhotoImage<TkImage
self
end
- def cget(option)
+ def cget_strict(option)
case option.to_s
when 'data', 'file'
tk_send 'cget', '-' << option.to_s
@@ -143,6 +164,23 @@ class TkPhotoImage<TkImage
tk_tcl2ruby(tk_send('cget', '-' << option.to_s))
end
end
+ def cget(option)
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ cget_strict(option)
+ else
+ begin
+ cget_strict(option)
+ rescue => e
+ if current_configinfo.has_key?(option.to_s)
+ # error on known option
+ fail e
+ else
+ # unknown option
+ nil
+ end
+ end
+ end
+ end
def copy(src, *opts)
if opts.size == 0
diff --git a/ext/tk/lib/tk/itemconfig.rb b/ext/tk/lib/tk/itemconfig.rb
index 0b84be38b8..9c6a98d0f8 100644
--- a/ext/tk/lib/tk/itemconfig.rb
+++ b/ext/tk/lib/tk/itemconfig.rb
@@ -8,6 +8,11 @@ require 'tk/itemfont.rb'
module TkItemConfigOptkeys
include TkUtil
+ def __item_optkey_aliases(id)
+ {}
+ end
+ private :__item_optkey_aliases
+
def __item_numval_optkeys(id)
[]
end
@@ -115,6 +120,14 @@ module TkItemConfigMethod
include TkTreatItemFont
include TkItemConfigOptkeys
+ def TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ @mode || false
+ end
+ def TkItemConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode)
+ fail SecurityError, "can't change the mode" if $SAFE>=4
+ @mode = (mode)? true: false
+ end
+
def __item_cget_cmd(id)
# maybe need to override
[self.path, 'itemcget', id]
@@ -149,7 +162,7 @@ module TkItemConfigMethod
################################################
- def itemcget(tagOrId, option)
+ def __itemcget_core(tagOrId, option)
orig_opt = option
option = option.to_s
@@ -157,6 +170,11 @@ module TkItemConfigMethod
fail ArgumentError, "Invalid option `#{orig_opt.inspect}'"
end
+ alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == option}
+ if real_name
+ option = real_name.to_s
+ end
+
if ( method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[option] )
optval = tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}"))
begin
@@ -224,11 +242,45 @@ module TkItemConfigMethod
tk_tcl2ruby(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}")), true)
end
end
+ private :__itemcget_core
- def itemconfigure(tagOrId, slot, value=None)
+ def itemcget(tagOrId, option)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ __itemcget_core(tagOrId, option)
+ else
+ begin
+ __itemcget_core(tagOrId, option)
+ rescue => e
+ begin
+ if __current_itemconfiginfo(tagOrId).has_key?(option.to_s)
+ # not tag error & option is known -> error on known option
+ fail e
+ else
+ # not tag error & option is unknown
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
+ def itemcget_strict(tagOrId, option)
+ # never use TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ __itemcget_core(tagOrId, option)
+ end
+
+ def __itemconfigure_core(tagOrId, slot, value=None)
if slot.kind_of? Hash
slot = _symbolkey2str(slot)
+ __item_optkey_aliases(tagid(tagOrId)).each{|alias_name, real_name|
+ alias_name = alias_name.to_s
+ if slot.has_key?(alias_name)
+ slot[real_name.to_s] = slot.delete(alias_name)
+ end
+ }
+
__item_methodcall_optkeys(tagid(tagOrId)).each{|key, method|
value = slot.delete(key.to_s)
self.__send__(method, tagOrId, value) if value
@@ -265,6 +317,11 @@ module TkItemConfigMethod
fail ArgumentError, "Invalid option `#{orig_slot.inspect}'"
end
+ alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
if ( conf = __item_keyonly_optkeys(tagid(tagOrId)).find{|k, v| k.to_s == slot } )
defkey, undefkey = conf
if value
@@ -288,8 +345,58 @@ module TkItemConfigMethod
end
self
end
+ private :__itemconfigure_core
- def itemconfiginfo(tagOrId, slot = nil)
+ def __check_available_itemconfigure_options(tagOrId, keys)
+ id = tagid(tagOrId)
+
+ availables = self.__current_itemconfiginfo(id).keys
+
+ # add non-standard keys
+ availables |= __font_optkeys.map{|k|
+ [k.to_s, "latin#{k}", "ascii#{k}", "kanji#{k}"]
+ }.flatten
+ availables |= __item_methodcall_optkeys(id).keys.map{|k| k.to_s}
+ availables |= __item_keyonly_optkeys(id).keys.map{|k| k.to_s}
+
+ keys = _symbolkey2str(keys)
+
+ keys.delete_if{|k, v| !(availables.include?(k))}
+ end
+
+ def itemconfigure(tagOrId, slot, value=None)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ __itemconfigure_core(tagOrId, slot, value)
+ else
+ if slot.kind_of?(Hash)
+ begin
+ __itemconfigure_core(tagOrId, slot)
+ rescue
+ slot = __check_available_itemconfigure_options(tagOrId, slot)
+ __itemconfigure_core(tagOrId, slot) unless slot.empty?
+ end
+ else
+ begin
+ __itemconfigure_core(tagOrId, slot, value)
+ rescue => e
+ begin
+ if __current_itemconfiginfo(tagOrId).has_key?(slot.to_s)
+ # not tag error & option is known -> error on known option
+ fail e
+ else
+ # not tag error & option is unknown
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
+ self
+ end
+
+ def __itemconfiginfo_core(tagOrId, slot = nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/)
fontkey = $2
@@ -299,6 +406,10 @@ module TkItemConfigMethod
conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1]
if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
|| conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
+ fnt = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt)
+ end
conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), fontkey)
elsif ( __item_configinfo_struct(tagid(tagOrId))[:alias] \
&& conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 \
@@ -310,6 +421,12 @@ module TkItemConfigMethod
else
if slot
slot = slot.to_s
+
+ alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
case slot
when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[slot]
@@ -594,7 +711,7 @@ module TkItemConfigMethod
if v.empty?
conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
else
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new
+ conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new(v)
end
end
@@ -635,6 +752,10 @@ module TkItemConfigMethod
fontconf = ret.assoc(optkey)
if fontconf && fontconf.size > 2
ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/}
+ fnt = fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt)
+ end
fontconf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), optkey)
ret.push(fontconf)
end
@@ -658,7 +779,11 @@ module TkItemConfigMethod
if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
|| conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = fontobj(tagid(tagOrId), fontkey)
+ fnt = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt)
+ end
+ conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), fontkey)
{ conf.shift => conf }
elsif ( __item_configinfo_struct(tagid(tagOrId))[:alias] \
&& conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
@@ -673,6 +798,12 @@ module TkItemConfigMethod
else
if slot
slot = slot.to_s
+
+ alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
case slot
when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[slot]
@@ -1006,6 +1137,10 @@ module TkItemConfigMethod
ret.delete('latin' << optkey)
ret.delete('ascii' << optkey)
ret.delete('kanji' << optkey)
+ fnt = fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt)
+ end
fontconf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), optkey)
ret[optkey] = fontconf
end
@@ -1020,13 +1155,32 @@ module TkItemConfigMethod
end
end
end
+ private :__itemconfiginfo_core
- def current_itemconfiginfo(tagOrId, slot = nil)
+ def itemconfiginfo(tagOrId, slot = nil)
+ if slot && TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ begin
+ __itemconfiginfo_core(tagOrId, slot)
+ rescue => e
+ begin
+ __itemconfiginfo_core(tagOrId)
+ # not tag error -> option is unknown
+ Array.new(__item_configinfo_struct.values.max).unshift(slot.to_s)
+ rescue
+ fail e # tag error
+ end
+ end
+ else
+ __itemconfiginfo_core(tagOrId, slot)
+ end
+ end
+
+ def __current_itemconfiginfo(tagOrId, slot = nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
if slot
org_slot = slot
begin
- conf = itemconfiginfo(tagOrId, slot)
+ conf = __itemconfiginfo_core(tagOrId, slot)
if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
|| conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
return {conf[0] => conf[-1]}
@@ -1037,20 +1191,25 @@ module TkItemConfigMethod
"there is a configure alias loop about '#{org_slot}'"
else
ret = {}
- itemconfiginfo(tagOrId).each{|conf|
+ __itemconfiginfo_core(tagOrId).each{|conf|
if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
|| conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
ret[conf[0]] = conf[-1]
end
}
+
ret
end
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
ret = {}
- itemconfiginfo(slot).each{|key, conf|
+ __itemconfiginfo_core(tagOrId, slot).each{|key, conf|
ret[key] = conf[-1] if conf.kind_of?(Array)
}
ret
end
end
+
+ def current_itemconfiginfo(tagOrId, slot = nil)
+ __current_itemconfiginfo(tagOrId, slot)
+ end
end
diff --git a/ext/tk/lib/tk/itemfont.rb b/ext/tk/lib/tk/itemfont.rb
index ab9e3ff6c9..4c5c917c57 100644
--- a/ext/tk/lib/tk/itemfont.rb
+++ b/ext/tk/lib/tk/itemfont.rb
@@ -94,7 +94,16 @@ module TkTreatItemFont
*(__item_config_cmd(tagid(tagOrId)) << {}))
next
else
- tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << fnt))
+ fnt = hash_kv(fnt) if fnt.kind_of?(Hash)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << fnt))
+ else
+ begin
+ tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << fnt))
+ rescue => e
+ # ignore
+ end
+ end
end
end
next
@@ -147,7 +156,16 @@ module TkTreatItemFont
elsif Tk::JAPANIZED_TK
fobj = fontobj # create a new TkFont object
else
- tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << ltn))
+ ltn = hash_kv(ltn) if ltn.kind_of?(Hash)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << ltn))
+ else
+ begin
+ tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << ltn))
+ rescue => e
+ # ignore
+ end
+ end
next
end
@@ -198,7 +216,16 @@ module TkTreatItemFont
elsif Tk::JAPANIZED_TK
fobj = fontobj # create a new TkFont object
else
- tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << knj))
+ knj = hash_kv(knj) if knj.kind_of?(Hash)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << knj))
+ else
+ begin
+ tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << knj))
+ rescue => e
+ # ignore
+ end
+ end
next
end
diff --git a/ext/tk/lib/tk/label.rb b/ext/tk/lib/tk/label.rb
index 8b45db9b30..80b3d778f1 100644
--- a/ext/tk/lib/tk/label.rb
+++ b/ext/tk/lib/tk/label.rb
@@ -3,7 +3,7 @@
#
require 'tk'
-class TkLabel<TkWindow
+class Tk::Label<TkWindow
TkCommandNames = ['label'.freeze].freeze
WidgetClassName = 'Label'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -16,3 +16,6 @@ class TkLabel<TkWindow
#end
#private :create_self
end
+
+#TkLabel = Tk::Label unless Object.const_defined? :TkLabel
+Tk.__set_toplevel_aliases__(:Tk, Tk::Label, :TkLabel)
diff --git a/ext/tk/lib/tk/labelframe.rb b/ext/tk/lib/tk/labelframe.rb
index 73d5603200..995b5b7e72 100644
--- a/ext/tk/lib/tk/labelframe.rb
+++ b/ext/tk/lib/tk/labelframe.rb
@@ -4,7 +4,7 @@
require 'tk'
require 'tk/frame'
-class TkLabelFrame<TkFrame
+class Tk::LabelFrame<Tk::Frame
TkCommandNames = ['labelframe'.freeze].freeze
WidgetClassName = 'Labelframe'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -22,4 +22,8 @@ class TkLabelFrame<TkFrame
end
private :__val2ruby_optkeys
end
-TkLabelframe = TkLabelFrame
+
+Tk::Labelframe = Tk::LabelFrame
+#TkLabelFrame = Tk::LabelFrame unless Object.const_defined? :TkLabelFrame
+#TkLabelframe = Tk::Labelframe unless Object.const_defined? :TkLabelframe
+Tk.__set_toplevel_aliases__(:Tk, Tk::LabelFrame, :TkLabelFrame, :TkLabelframe)
diff --git a/ext/tk/lib/tk/listbox.rb b/ext/tk/lib/tk/listbox.rb
index 41d02d279e..bb039ffb0e 100644
--- a/ext/tk/lib/tk/listbox.rb
+++ b/ext/tk/lib/tk/listbox.rb
@@ -15,7 +15,7 @@ module TkListItemConfig
private :__item_listval_optkeys
end
-class TkListbox<TkTextWin
+class Tk::Listbox<TkTextWin
include TkListItemConfig
include Scrollable
@@ -277,3 +277,6 @@ class TkListbox<TkTextWin
end
=end
end
+
+#TkListbox = Tk::Listbox unless Object.const_defined? :TkListbox
+Tk.__set_toplevel_aliases__(:Tk, Tk::Listbox, :TkListbox)
diff --git a/ext/tk/lib/tk/macpkg.rb b/ext/tk/lib/tk/macpkg.rb
index 1802073f46..67b0a4bb60 100644
--- a/ext/tk/lib/tk/macpkg.rb
+++ b/ext/tk/lib/tk/macpkg.rb
@@ -20,9 +20,14 @@ module Tk
end
end
-module TkMacResource
+module Tk::MacResource
+end
+#TkMacResource = Tk::MacResource
+Tk.__set_toplevel_aliases__(:Tk, Tk::MacResource, :TkMacResource)
+
+module Tk::MacResource
extend Tk
- extend TkMacResource
+ extend Tk::MacResource
TkCommandNames = ['resource'.freeze].freeze
diff --git a/ext/tk/lib/tk/menu.rb b/ext/tk/lib/tk/menu.rb
index ddddc8e53e..3ae0548dd1 100644
--- a/ext/tk/lib/tk/menu.rb
+++ b/ext/tk/lib/tk/menu.rb
@@ -34,15 +34,16 @@ module TkMenuEntryConfig
private :__item_val2ruby_optkeys
alias entrycget itemcget
+ alias entrycget_strict itemcget_strict
alias entryconfigure itemconfigure
alias entryconfiginfo itemconfiginfo
alias current_entryconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
end
-class TkMenu<TkWindow
+class Tk::Menu<TkWindow
include Wm
include TkMenuEntryConfig
extend TkMenuSpec
@@ -140,9 +141,9 @@ class TkMenu<TkWindow
type = keys.delete('type') if keys.has_key?('type')
if keys.empty?
- TkMenuClone.new(self, parent, type)
+ Tk::MenuClone.new(self, parent, type)
else
- TkMenuClone.new(self, parent, type, keys)
+ Tk::MenuClone.new(self, parent, type, keys)
end
end
@@ -202,6 +203,9 @@ class TkMenu<TkWindow
tk_send_without_enc('unpost')
self
end
+ def xposition(index)
+ number(tk_send_without_enc('xposition', _get_eval_enc_str(index)))
+ end
def yposition(index)
number(tk_send_without_enc('yposition', _get_eval_enc_str(index)))
end
@@ -381,8 +385,11 @@ class TkMenu<TkWindow
=end
end
+#TkMenu = Tk::Menu unless Object.const_defined? :TkMenu
+Tk.__set_toplevel_aliases__(:Tk, Tk::Menu, :TkMenu)
+
-class TkMenuClone<TkMenu
+class Tk::MenuClone<Tk::Menu
=begin
def initialize(parent, type=None)
widgetname = nil
@@ -436,9 +443,12 @@ class TkMenuClone<TkMenu
@src_menu
end
end
-TkCloneMenu = TkMenuClone
+Tk::CloneMenu = Tk::MenuClone
+#TkMenuClone = Tk::MenuClone unless Object.const_defined? :TkMenuClone
+#TkCloneMenu = Tk::CloneMenu unless Object.const_defined? :TkCloneMenu
+Tk.__set_toplevel_aliases__(:Tk, Tk::MenuClone, :TkMenuClone, :TkCloneMenu)
-module TkSystemMenu
+module Tk::SystemMenu
def initialize(parent, keys=nil)
if parent.kind_of? Hash
keys = _symbolkey2str(parent)
@@ -461,38 +471,60 @@ module TkSystemMenu
end
end
end
+TkSystemMenu = Tk::SystemMenu
-class TkSysMenu_Help<TkMenu
+class Tk::SysMenu_Help<Tk::Menu
# for all platform
- include TkSystemMenu
+ include Tk::SystemMenu
SYSMENU_NAME = 'help'
end
+#TkSysMenu_Help = Tk::SysMenu_Help unless Object.const_defined? :TkSysMenu_Help
+Tk.__set_toplevel_aliases__(:Tk, Tk::SysMenu_Help, :TkSysMenu_Help)
-class TkSysMenu_System<TkMenu
+class Tk::SysMenu_System<Tk::Menu
# for Windows
- include TkSystemMenu
+ include Tk::SystemMenu
SYSMENU_NAME = 'system'
end
+#TkSysMenu_System = Tk::SysMenu_System unless Object.const_defined? :TkSysMenu_System
+Tk.__set_toplevel_aliases__(:Tk, Tk::SysMenu_System, :TkSysMenu_System)
-class TkSysMenu_Apple<TkMenu
+class Tk::SysMenu_Apple<Tk::Menu
# for Machintosh
- include TkSystemMenu
+ include Tk::SystemMenu
SYSMENU_NAME = 'apple'
end
+#TkSysMenu_Apple = Tk::SysMenu_Apple unless Object.const_defined? :TkSysMenu_Apple
+Tk.__set_toplevel_aliases__(:Tk, Tk::SysMenu_Apple, :TkSysMenu_Apple)
-class TkMenubutton<TkLabel
+class Tk::Menubutton<Tk::Label
TkCommandNames = ['menubutton'.freeze].freeze
WidgetClassName = 'Menubutton'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
if keys and keys != None
- # tk_call_without_enc('menubutton', @path, *hash_kv(keys, true))
- tk_call_without_enc(self.class::TkCommandNames[0], @path,
- *hash_kv(keys, true))
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ # tk_call_without_enc('menubutton', @path, *hash_kv(keys, true))
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ begin
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ rescue
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ keys = __check_available_configure_options(keys)
+ unless keys.empty?
+ tk_call_without_enc('destroy', @path) rescue nil
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ end
+ end
+ end
else
# tk_call_without_enc('menubutton', @path)
tk_call_without_enc(self.class::TkCommandNames[0], @path)
@@ -506,10 +538,13 @@ class TkMenubutton<TkLabel
private :__boolval_optkeys
end
-TkMenuButton = TkMenubutton
+Tk::MenuButton = Tk::Menubutton
+#TkMenubutton = Tk::Menubutton unless Object.const_defined? :TkMenubutton
+#TkMenuButton = Tk::MenuButton unless Object.const_defined? :TkMenuButton
+Tk.__set_toplevel_aliases__(:Tk, Tk::Menubutton, :TkMenubutton, :TkMenuButton)
-class TkOptionMenubutton<TkMenubutton
+class Tk::OptionMenubutton<Tk::Menubutton
TkCommandNames = ['tk_optionMenu'.freeze].freeze
class OptionMenu<TkMenu
@@ -596,6 +631,9 @@ class TkOptionMenubutton<TkMenubutton
@menu.delete(index, last)
self
end
+ def xposition(index)
+ @menu.xposition(index)
+ end
def yposition(index)
@menu.yposition(index)
end
@@ -605,6 +643,9 @@ class TkOptionMenubutton<TkMenubutton
def menucget(key)
@menu.cget(key)
end
+ def menucget_strict(key)
+ @menu.cget_strict(key)
+ end
def menuconfigure(key, val=None)
@menu.configure(key, val)
self
@@ -618,6 +659,9 @@ class TkOptionMenubutton<TkMenubutton
def entrycget(index, key)
@menu.entrycget(index, key)
end
+ def entrycget_strict(index, key)
+ @menu.entrycget_strict(index, key)
+ end
def entryconfigure(index, key, val=None)
@menu.entryconfigure(index, key, val)
self
@@ -629,4 +673,9 @@ class TkOptionMenubutton<TkMenubutton
@menu.current_entryconfiginfo(index, key)
end
end
-TkOptionMenuButton = TkOptionMenubutton
+
+Tk::OptionMenuButton = Tk::OptionMenubutton
+#TkOptionMenubutton = Tk::OptionMenubutton unless Object.const_defined? :TkOptionMenubutton
+#TkOptionMenuButton = Tk::OptionMenuButton unless Object.const_defined? :TkOptionMenuButton
+Tk.__set_toplevel_aliases__(:Tk, Tk::OptionMenubutton,
+ :TkOptionMenubutton, :TkOptionMenuButton)
diff --git a/ext/tk/lib/tk/menubar.rb b/ext/tk/lib/tk/menubar.rb
index 392b6fbd4e..ef9da809b9 100644
--- a/ext/tk/lib/tk/menubar.rb
+++ b/ext/tk/lib/tk/menubar.rb
@@ -89,7 +89,7 @@ require 'tk/frame'
require 'tk/composite'
require 'tk/menuspec'
-class TkMenubar<TkFrame
+class TkMenubar<Tk::Frame
include TkComposite
include TkMenuSpec
diff --git a/ext/tk/lib/tk/menuspec.rb b/ext/tk/lib/tk/menuspec.rb
index 118a4f42b1..2a2eb9ba3c 100644
--- a/ext/tk/lib/tk/menuspec.rb
+++ b/ext/tk/lib/tk/menuspec.rb
@@ -61,8 +61,12 @@ module TkMenuSpec
tearoff = orig_opts.delete('tearoff') if orig_opts.key?('tearoff')
if menu_name
+ #menu = Tk::Menu.new(parent, :widgetname=>menu_name, :tearoff=>tearoff)
+ # --> use current TkMenu class
menu = TkMenu.new(parent, :widgetname=>menu_name, :tearoff=>tearoff)
else
+ #menu = Tk::Menu.new(parent, :tearoff=>tearoff)
+ # --> use current TkMenu class
menu = TkMenu.new(parent, :tearoff=>tearoff)
end
@@ -150,21 +154,22 @@ module TkMenuSpec
def _use_menubar?(parent)
use_menubar = false
- if parent.kind_of?(TkRoot) || parent.kind_of?(TkToplevel)
- return true
+ if parent.kind_of?(Tk::Root) || parent.kind_of?(Tk::Toplevel)
+ true
+ elsif parent.current_configinfo.has_key?('menu')
+ true
else
- begin
- parent.cget('menu')
- return true
- rescue
- end
+ false
end
- false
end
private :_use_menubar?
def _create_menu_for_menubar(parent)
- unless (mbar = parent.menu).kind_of?(TkMenu)
+ #unless (mbar = parent.menu).kind_of?(TkMenu)
+ # --> use current TkMenu class
+ mbar = parent.menu
+ unless mbar.kind_of?(Tk::Menu) || mbar.kind_of?(TkMenu)
+ #mbar = Tk::Menu.new(parent, :tearoff=>false)
mbar = TkMenu.new(parent, :tearoff=>false)
parent.menu(mbar)
end
@@ -190,7 +195,6 @@ module TkMenuSpec
if _use_menubar?(parent)
# menubar by menu entries
-
mbar = _create_menu_for_menubar(parent)
menu_name = nil
@@ -221,6 +225,8 @@ module TkMenuSpec
else
# menubar by menubuttons
+ #mbtn = Tk::Menubutton.new(parent)
+ # --> use current TkMenubutton class
mbtn = TkMenubutton.new(parent)
menu_name = nil
diff --git a/ext/tk/lib/tk/message.rb b/ext/tk/lib/tk/message.rb
index 79121bebb3..946b68c704 100644
--- a/ext/tk/lib/tk/message.rb
+++ b/ext/tk/lib/tk/message.rb
@@ -4,7 +4,7 @@
require 'tk'
require 'tk/label'
-class TkMessage<TkLabel
+class Tk::Message<Tk::Label
TkCommandNames = ['message'.freeze].freeze
WidgetClassName = 'Message'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -17,3 +17,6 @@ class TkMessage<TkLabel
#end
private :create_self
end
+
+#TkMessage = Tk::Message unless Object.const_defined? :TkMessage
+Tk.__set_toplevel_aliases__(:Tk, Tk::Message, :TkMessage)
diff --git a/ext/tk/lib/tk/msgcat.rb b/ext/tk/lib/tk/msgcat.rb
index 061e43fd89..162953f425 100644
--- a/ext/tk/lib/tk/msgcat.rb
+++ b/ext/tk/lib/tk/msgcat.rb
@@ -74,7 +74,11 @@ class TkMsgCatalog < TkObject
"\n---< backtrace of Ruby side >-----\n" +
_toUTF8(e.backtrace.join("\n")) +
"\n---< backtrace of Tk side >-------"
- msg.instance_variable_set(:@encoding, 'utf-8')
+ if TkCore::WITH_ENCODING
+ msg.force_encoding('utf-8')
+ else
+ msg.instance_variable_set(:@encoding, 'utf-8')
+ end
rescue Exception
msg = e.class.inspect + ': ' + e.message + "\n" +
"\n---< backtrace of Ruby side >-----\n" +
diff --git a/ext/tk/lib/tk/namespace.rb b/ext/tk/lib/tk/namespace.rb
index 5bf6474c5b..20a8d65215 100644
--- a/ext/tk/lib/tk/namespace.rb
+++ b/ext/tk/lib/tk/namespace.rb
@@ -12,17 +12,24 @@ class TkNamespace < TkObject
].freeze
Tk_Namespace_ID_TBL = TkCore::INTERP.create_table
- Tk_Namespace_ID = ["ns".freeze, "00000".taint].freeze
+
+ (Tk_Namespace_ID = ["ns".freeze, "00000".taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
Tk_NsCode_RetObjID_TBL = TkCore::INTERP.create_table
TkCore::INTERP.init_ip_env{
- Tk_Namespace_ID_TBL.clear
- Tk_NsCode_RetObjID_TBL.clear
+ Tk_Namespace_ID_TBL.mutex.synchronize{ Tk_Namespace_ID_TBL.clear }
+ Tk_NsCode_RetObjID_TBL.mutex.synchronize{ Tk_NsCode_RetObjID_TBL.clear }
}
def TkNamespace.id2obj(id)
- Tk_Namespace_ID_TBL[id]? Tk_Namespace_ID_TBL[id]: id
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ Tk_Namespace_ID_TBL[id]? Tk_Namespace_ID_TBL[id]: id
+ }
end
#####################################
@@ -65,11 +72,27 @@ class TkNamespace < TkObject
def cget(slot)
if slot == :namespace || slot == 'namespace'
ns = super(slot)
- if TkNamespace::Tk_Namespace_ID_TBL.key?(ns)
- TkNamespace::Tk_Namespace_ID_TBL[ns]
- else
- ns
- end
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if TkNamespace::Tk_Namespace_ID_TBL.key?(ns)
+ TkNamespace::Tk_Namespace_ID_TBL[ns]
+ else
+ ns
+ end
+ }
+ else
+ super(slot)
+ end
+ end
+ def cget_strict(slot)
+ if slot == :namespace || slot == 'namespace'
+ ns = super(slot)
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if TkNamespace::Tk_Namespace_ID_TBL.key?(ns)
+ TkNamespace::Tk_Namespace_ID_TBL[ns]
+ else
+ ns
+ end
+ }
else
super(slot)
end
@@ -79,9 +102,11 @@ class TkNamespace < TkObject
if slot
if slot == :namespace || slot == 'namespace'
val = super(slot)
- if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
- val = TkNamespace::Tk_Namespace_ID_TBL[val]
- end
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
+ val = TkNamespace::Tk_Namespace_ID_TBL[val]
+ end
+ }
else
val = super(slot)
end
@@ -96,19 +121,23 @@ class TkNamespace < TkObject
info = super()
if TkComm::GET_CONFIGINFO_AS_ARRAY
- info.map!{|inf|
- if inf[0] == 'namespace' &&
- TkNamespace::Tk_Namespace_ID_TBL.key?(inf[-1])
- [inf[0], TkNamespace::Tk_Namespace_ID_TBL[inf[-1]]]
- else
- inf
- end
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ info.map!{|inf|
+ if inf[0] == 'namespace' &&
+ TkNamespace::Tk_Namespace_ID_TBL.key?(inf[-1])
+ [inf[0], TkNamespace::Tk_Namespace_ID_TBL[inf[-1]]]
+ else
+ inf
+ end
+ }
}
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
val = info['namespace']
- if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
- info['namespace'] = TkNamespace::Tk_Namespace_ID_TBL[val]
- end
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
+ info['namespace'] = TkNamespace::Tk_Namespace_ID_TBL[val]
+ end
+ }
end
info
@@ -215,9 +244,11 @@ class TkNamespace < TkObject
def initialize(name = nil, parent = nil)
unless name
- # name = Tk_Namespace_ID.join('')
- name = Tk_Namespace_ID.join(TkCore::INTERP._ip_id_)
- Tk_Namespace_ID[1].succ!
+ Tk_Namespace_ID.mutex.synchronize{
+ # name = Tk_Namespace_ID.join('')
+ name = Tk_Namespace_ID.join(TkCore::INTERP._ip_id_)
+ Tk_Namespace_ID[1].succ!
+ }
end
name = __tk_call('namespace', 'current') if name == ''
if parent
@@ -252,7 +283,9 @@ class TkNamespace < TkObject
# create namespace
__tk_call('namespace', 'eval', @fullname, '')
- Tk_Namespace_ID_TBL[@fullname] = self
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ Tk_Namespace_ID_TBL[@fullname] = self
+ }
end
def self.children(*args)
@@ -260,11 +293,13 @@ class TkNamespace < TkObject
# <pattern> must be glob-style pattern
tk_split_simplelist(tk_call('namespace', 'children', *args)).collect{|ns|
# ns is fullname
- if Tk_Namespace_ID_TBL.key?(ns)
- Tk_Namespace_ID_TBL[ns]
- else
- ns
- end
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if Tk_Namespace_ID_TBL.key?(ns)
+ Tk_Namespace_ID_TBL[ns]
+ else
+ ns
+ end
+ }
}
end
def children(pattern=None)
@@ -290,14 +325,24 @@ class TkNamespace < TkObject
def code(script = Proc.new)
if script.kind_of?(String)
cmd = proc{|*args|
- ret = ScopeArgs.new(@fullname,*args).instance_eval(script)
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ obj = ScopeArgs.new(@fullname,*args)
+ ret = obj.instance_exec(obj, script)
+ else
+ ret = ScopeArgs.new(@fullname,*args).instance_eval(script)
+ end
id = ret.object_id
TkNamespace::Tk_NsCode_RetObjID_TBL[id] = ret
id
}
elsif script.kind_of?(Proc)
cmd = proc{|*args|
- ret = ScopeArgs.new(@fullname,*args).instance_eval(&script)
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ obj = ScopeArgs.new(@fullname,*args)
+ ret = obj.instance_exec(obj, &script)
+ else
+ ret = ScopeArgs.new(@fullname,*args).instance_eval(&script)
+ end
id = ret.object_id
TkNamespace::Tk_NsCode_RetObjID_TBL[id] = ret
id
@@ -319,11 +364,13 @@ class TkNamespace < TkObject
def self.current
ns = self.current_path
- if Tk_Namespace_ID_TBL.key?(ns)
- Tk_Namespace_ID_TBL[ns]
- else
- ns
- end
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if Tk_Namespace_ID_TBL.key?(ns)
+ Tk_Namespace_ID_TBL[ns]
+ else
+ ns
+ end
+ }
end
def current_namespace
# ns_tk_call('namespace', 'current')
@@ -335,11 +382,13 @@ class TkNamespace < TkObject
def self.delete(*ns_list)
tk_call('namespace', 'delete', *ns_list)
ns_list.each{|ns|
- if ns.kind_of?(TkNamespace)
- Tk_Namespace_ID_TBL.delete(ns.path)
- else
- Tk_Namespace_ID_TBL.delete(ns.to_s)
- end
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if ns.kind_of?(TkNamespace)
+ Tk_Namespace_ID_TBL.delete(ns.path)
+ else
+ Tk_Namespace_ID_TBL.delete(ns.to_s)
+ end
+ }
}
end
def delete
@@ -371,7 +420,7 @@ class TkNamespace < TkObject
def self.eval(namespace, cmd = Proc.new, *args)
#tk_call('namespace', 'eval', namespace, cmd, *args)
- TkNamespace.new(namespece).eval(cmd, *args)
+ TkNamespace.new(namespace).eval(cmd, *args)
end
=begin
def eval(cmd = Proc.new, *args)
@@ -444,11 +493,13 @@ class TkNamespace < TkObject
def self.parent(namespace=None)
ns = tk_call('namespace', 'parent', namespace)
- if Tk_Namespace_ID_TBL.key?(ns)
- Tk_Namespace_ID_TBL[ns]
- else
- ns
- end
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if Tk_Namespace_ID_TBL.key?(ns)
+ Tk_Namespace_ID_TBL[ns]
+ else
+ ns
+ end
+ }
end
def parent
tk_call('namespace', 'parent', @fullname)
diff --git a/ext/tk/lib/tk/optiondb.rb b/ext/tk/lib/tk/optiondb.rb
index a806f3971d..186811d37d 100644
--- a/ext/tk/lib/tk/optiondb.rb
+++ b/ext/tk/lib/tk/optiondb.rb
@@ -8,7 +8,11 @@ module TkOptionDB
extend Tk
TkCommandNames = ['option'.freeze].freeze
- CmdClassID = ['CMD_CLASS'.freeze, '00000'.taint].freeze
+ (CmdClassID = ['CMD_CLASS'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
module Priority
WidgetDefault = 20
@@ -250,8 +254,10 @@ module TkOptionDB
def __create_new_class(klass, func, safe = 4, add = false, parent = nil)
if klass.kind_of?(TkWindow)
carrier = klass.path
- klass = CmdClassID.join(TkCore::INTERP._ip_id_)
- CmdClassID[1].succ!
+ CmdClassID.mutex.synchronize{
+ klass = CmdClassID.join(TkCore::INTERP._ip_id_)
+ CmdClassID[1].succ!
+ }
parent = nil # ignore parent
else
klass = klass.to_s if klass.kind_of?(Symbol)
@@ -312,7 +318,7 @@ module TkOptionDB
:singleton_methods, :remove_const, :remove_method, :undef_method,
:to_s, :inspect, :display, :method, :methods, :respond_to?,
:instance_variable_get, :instance_variable_set, :instance_method,
- :instance_eval, :instance_variables, :kind_of?, :is_a?,
+ :instance_eval, :instance_exec, :instance_variables, :kind_of?, :is_a?,
:private_methods, :protected_methods, :public_methods ].each{|m|
alias_method(m, :__null_method)
}
@@ -362,7 +368,7 @@ module TkOptionDB
def new_proc_class_random(klass, func, safe = 4, add = false, &b)
eval_under_random_base(){
- TkOption.new_proc_class(klass, func, safe, add, self, &b)
+ TkOptionDB.new_proc_class(klass, func, safe, add, self, &b)
}
end
module_function :new_proc_class_random
diff --git a/ext/tk/lib/tk/pack.rb b/ext/tk/lib/tk/pack.rb
index 8fab363121..220a38e524 100644
--- a/ext/tk/lib/tk/pack.rb
+++ b/ext/tk/lib/tk/pack.rb
@@ -9,6 +9,7 @@ module TkPack
TkCommandNames = ['pack'.freeze].freeze
+=begin
def configure(win, *args)
if args[-1].kind_of?(Hash)
opts = args.pop
@@ -29,6 +30,22 @@ module TkPack
}
tk_call_without_enc("pack", 'configure', *params)
end
+=end
+ def configure(*args)
+ if args[-1].kind_of?(Hash)
+ opts = args.pop
+ else
+ opts = {}
+ end
+ fail ArgumentError, 'no widget is given' if args.empty?
+ params = []
+ args.flatten(1).each{|win| params.push(_epath(win))}
+ opts.each{|k, v|
+ params.push("-#{k}")
+ params.push(_epath(v)) # have to use 'epath' (hash_kv() is unavailable)
+ }
+ tk_call_without_enc("pack", 'configure', *params)
+ end
alias pack configure
def forget(*args)
diff --git a/ext/tk/lib/tk/package.rb b/ext/tk/lib/tk/package.rb
index d1eb27674d..0c329732f5 100644
--- a/ext/tk/lib/tk/package.rb
+++ b/ext/tk/lib/tk/package.rb
@@ -136,4 +136,8 @@ module TkPackage
def vsatisfies(version1, version2)
bool(tk_call('package', 'vsatisfies', version1, version2))
end
+
+ def prefer(setting = None)
+ tk_call('package', 'prefer', setting)
+ end
end
diff --git a/ext/tk/lib/tk/palette.rb b/ext/tk/lib/tk/palette.rb
index 2b6fdf5d90..2d08d50f6a 100644
--- a/ext/tk/lib/tk/palette.rb
+++ b/ext/tk/lib/tk/palette.rb
@@ -15,7 +15,7 @@ module TkPalette
].freeze
def TkPalette.set(*args)
- args = args.to_a.flatten if args.kind_of? Hash
+ args = args[0].to_a.flatten if args[0].kind_of? Hash
tk_call('tk_setPalette', *args)
end
def TkPalette.setPalette(*args)
diff --git a/ext/tk/lib/tk/panedwindow.rb b/ext/tk/lib/tk/panedwindow.rb
index c6cf3cd11f..030144e677 100644
--- a/ext/tk/lib/tk/panedwindow.rb
+++ b/ext/tk/lib/tk/panedwindow.rb
@@ -3,7 +3,7 @@
#
require 'tk'
-class TkPanedWindow<TkWindow
+class Tk::PanedWindow<TkWindow
TkCommandNames = ['panedwindow'.freeze].freeze
WidgetClassName = 'Panedwindow'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -76,11 +76,32 @@ class TkPanedWindow<TkWindow
self
end
- def panecget(win, key)
+ def panecget_strict(win, key)
# win = win.epath if win.kind_of?(TkObject)
win = _epath(win)
tk_tcl2ruby(tk_send_without_enc('panecget', win, "-#{key}"))
end
+ def panecget(win, key)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ panecget_strict(win, key)
+ else
+ begin
+ panecget_strict(win, key)
+ rescue => e
+ begin
+ if current_paneconfiginfo(win).has_key?(option.to_s)
+ # not tag error & option is known -> error on known option
+ fail e
+ else
+ # not tag error & option is unknown
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
def paneconfigure(win, key, value=nil)
# win = win.epath if win.kind_of?(TkObject)
@@ -229,4 +250,9 @@ class TkPanedWindow<TkWindow
list(tk_send_without_enc('panes'))
end
end
-TkPanedwindow = TkPanedWindow
+
+Tk::Panedwindow = Tk::PanedWindow
+#TkPanedWindow = Tk::PanedWindow unless Object.const_defined? :TkPanedWindow
+#TkPanedwindow = Tk::Panedwindow unless Object.const_defined? :TkPanedwindow
+Tk.__set_toplevel_aliases__(:Tk, Tk::PanedWindow,
+ :TkPanedWindow, :TkPanedwindow)
diff --git a/ext/tk/lib/tk/radiobutton.rb b/ext/tk/lib/tk/radiobutton.rb
index f8f67d709a..1f864ec06b 100644
--- a/ext/tk/lib/tk/radiobutton.rb
+++ b/ext/tk/lib/tk/radiobutton.rb
@@ -4,7 +4,7 @@
require 'tk'
require 'tk/button'
-class TkRadioButton<TkButton
+class Tk::RadioButton<Tk::Button
TkCommandNames = ['radiobutton'.freeze].freeze
WidgetClassName = 'Radiobutton'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -63,4 +63,9 @@ class TkRadioButton<TkButton
end
end
end
-TkRadiobutton = TkRadioButton
+
+Tk::Radiobutton = Tk::RadioButton
+#TkRadioButton = Tk::RadioButton unless Object.const_defined? :TkRadioButton
+#TkRadiobutton = Tk::Radiobutton unless Object.const_defined? :TkRadiobutton
+Tk.__set_toplevel_aliases__(:Tk, Tk::RadioButton,
+ :TkRadioButton, :TkRadiobutton)
diff --git a/ext/tk/lib/tk/root.rb b/ext/tk/lib/tk/root.rb
index 0e5584c7c1..7237b4c614 100644
--- a/ext/tk/lib/tk/root.rb
+++ b/ext/tk/lib/tk/root.rb
@@ -5,7 +5,7 @@ require 'tk'
require 'tk/wm'
require 'tk/menuspec'
-class TkRoot<TkWindow
+class Tk::Root<TkWindow
include Wm
include TkMenuSpec
@@ -14,28 +14,7 @@ class TkRoot<TkWindow
end
private :__methodcall_optkeys
-=begin
- ROOT = []
- def TkRoot.new(keys=nil)
- if ROOT[0]
- Tk_WINDOWS["."] = ROOT[0]
- return ROOT[0]
- end
- new = super(:without_creating=>true, :widgetname=>'.')
- if keys # wm commands
- keys.each{|k,v|
- if v.kind_of? Array
- new.send(k,*v)
- else
- new.send(k,v)
- end
- }
- end
- ROOT[0] = new
- Tk_WINDOWS["."] = new
- end
-=end
- def TkRoot.new(keys=nil, &b)
+ def Root.new(keys=nil, &b)
unless TkCore::INTERP.tk_windows['.']
TkCore::INTERP.tk_windows['.'] =
super(:without_creating=>true, :widgetname=>'.'){}
@@ -62,7 +41,13 @@ class TkRoot<TkWindow
}
end
- root.instance_eval(&b) if block_given?
+ if block_given?
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ root.instance_exec(root, &b)
+ else
+ root.instance_eval(&b)
+ end
+ end
root
end
@@ -102,7 +87,9 @@ class TkRoot<TkWindow
self.menu
end
- def TkRoot.destroy
+ def Root.destroy
TkCore::INTERP._invoke('destroy', '.')
end
end
+
+TkRoot = Tk::Root unless Object.const_defined? :TkRoot
diff --git a/ext/tk/lib/tk/scale.rb b/ext/tk/lib/tk/scale.rb
index 0b703aa055..7e758d92f4 100644
--- a/ext/tk/lib/tk/scale.rb
+++ b/ext/tk/lib/tk/scale.rb
@@ -3,7 +3,7 @@
#
require 'tk'
-class TkScale<TkWindow
+class Tk::Scale<TkWindow
TkCommandNames = ['scale'.freeze].freeze
WidgetClassName = 'Scale'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -14,9 +14,31 @@ class TkScale<TkWindow
cmd = keys.delete('command')
keys['command'] = proc{|val| cmd.call(val.to_f)}
end
- #tk_call_without_enc('scale', @path, *hash_kv(keys, true))
- tk_call_without_enc(self.class::TkCommandNames[0], @path,
- *hash_kv(keys, true))
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ #tk_call_without_enc('scale', @path, *hash_kv(keys, true))
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ begin
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ rescue
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ keys = __check_available_configure_options(keys)
+ unless keys.empty?
+ begin
+ tk_call_without_enc('destroy', @path)
+ rescue
+ # cannot destroy
+ configure(keys)
+ else
+ # re-create widget
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ end
+ end
+ end
+ end
else
#tk_call_without_enc('scale', @path)
tk_call_without_enc(self.class::TkCommandNames[0], @path)
@@ -84,3 +106,6 @@ class TkScale<TkWindow
val
end
end
+
+#TkScale = Tk::Scale unless Object.const_defined? :TkScale
+Tk.__set_toplevel_aliases__(:Tk, Tk::Scale, :TkScale)
diff --git a/ext/tk/lib/tk/scrollable.rb b/ext/tk/lib/tk/scrollable.rb
index ec27b76467..96959b7a4b 100644
--- a/ext/tk/lib/tk/scrollable.rb
+++ b/ext/tk/lib/tk/scrollable.rb
@@ -4,7 +4,7 @@
require 'tk'
module Tk
- module X_Scrollable
+ module XScrollable
def xscrollcommand(cmd=Proc.new)
configure_cmd 'xscrollcommand', cmd
# Tk.update # avoid scrollbar trouble
@@ -38,7 +38,7 @@ module Tk
end
end
- module Y_Scrollable
+ module YScrollable
def yscrollcommand(cmd=Proc.new)
configure_cmd 'yscrollcommand', cmd
# Tk.update # avoid scrollbar trouble
@@ -72,8 +72,11 @@ module Tk
end
end
+ X_Scrollable = XScrollable
+ Y_Scrollable = YScrollable
+
module Scrollable
- include X_Scrollable
- include Y_Scrollable
+ include XScrollable
+ include YScrollable
end
end
diff --git a/ext/tk/lib/tk/scrollbar.rb b/ext/tk/lib/tk/scrollbar.rb
index 70aadfdd4c..87db46a9f9 100644
--- a/ext/tk/lib/tk/scrollbar.rb
+++ b/ext/tk/lib/tk/scrollbar.rb
@@ -3,7 +3,7 @@
#
require 'tk'
-class TkScrollbar<TkWindow
+class Tk::Scrollbar<TkWindow
TkCommandNames = ['scrollbar'.freeze].freeze
WidgetClassName = 'Scrollbar'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -19,9 +19,31 @@ class TkScrollbar<TkWindow
}
if keys and keys != None
- #tk_call_without_enc('scrollbar', @path, *hash_kv(keys, true))
- tk_call_without_enc(self.class::TkCommandNames[0], @path,
- *hash_kv(keys, true))
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ #tk_call_without_enc('scrollbar', @path, *hash_kv(keys, true))
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ begin
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ rescue
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ keys = __check_available_configure_options(keys)
+ unless keys.empty?
+ begin
+ tk_call_without_enc('destroy', @path)
+ rescue
+ # cannot destroy
+ configure(keys)
+ else
+ # re-create widget
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ end
+ end
+ end
+ end
else
#tk_call_without_enc('scrollbar', @path)
tk_call_without_enc(self.class::TkCommandNames[0], @path)
@@ -103,9 +125,33 @@ class TkScrollbar<TkWindow
def activate(element=None)
tk_send_without_enc('activate', element)
end
+
+ def moveto(fraction)
+ tk_send_without_enc('moveto', fraction)
+ self
+ end
+
+ def scroll(*args)
+ tk_send_without_enc('scroll', *args)
+ self
+ end
+
+ def scroll_units(num)
+ scroll(num, 'units')
+ self
+ end
+
+ def scroll_pages(num)
+ scroll(num, 'pages')
+ self
+ end
end
-class TkXScrollbar<TkScrollbar
+#TkScrollbar = Tk::Scrollbar unless Object.const_defined? :TkScrollbar
+Tk.__set_toplevel_aliases__(:Tk, Tk::Scrollbar, :TkScrollbar)
+
+
+class Tk::XScrollbar<Tk::Scrollbar
def create_self(keys)
keys = {} unless keys
keys['orient'] = 'horizontal'
@@ -114,7 +160,11 @@ class TkXScrollbar<TkScrollbar
private :create_self
end
-class TkYScrollbar<TkScrollbar
+#TkXScrollbar = Tk::XScrollbar unless Object.const_defined? :TkXScrollbar
+Tk.__set_toplevel_aliases__(:Tk, Tk::XScrollbar, :TkXScrollbar)
+
+
+class Tk::YScrollbar<Tk::Scrollbar
def create_self(keys)
keys = {} unless keys
keys['orient'] = 'vertical'
@@ -122,3 +172,6 @@ class TkYScrollbar<TkScrollbar
end
private :create_self
end
+
+#TkYScrollbar = Tk::YScrollbar unless Object.const_defined? :TkYScrollbar
+Tk.__set_toplevel_aliases__(:Tk, Tk::YScrollbar, :TkYScrollbar)
diff --git a/ext/tk/lib/tk/scrollbox.rb b/ext/tk/lib/tk/scrollbox.rb
index 833505be17..d20742a666 100644
--- a/ext/tk/lib/tk/scrollbox.rb
+++ b/ext/tk/lib/tk/scrollbox.rb
@@ -1,16 +1,19 @@
#
# tk/scrollbox.rb - Tk Listbox with Scrollbar
# as an example of Composite Widget
-# $Date: 2004/10/11 04:51:07 $
# by Yukihiro Matsumoto <matz@netlab.co.jp>
#
require 'tk'
require 'tk/listbox'
-class TkScrollbox<TkListbox
+class TkScrollbox<Tk::Listbox
include TkComposite
def initialize_composite(keys=nil)
+ #list = Tk::Listbox.new(@frame)
+ # -> use current TkListbox class
list = TkListbox.new(@frame)
+ #scroll = Tk::Scrollbar.new(@frame)
+ # -> use current TkScrollbar class
scroll = TkScrollbar.new(@frame)
@path = list.path
diff --git a/ext/tk/lib/tk/spinbox.rb b/ext/tk/lib/tk/spinbox.rb
index 1eed4d1dc4..34dc1904f7 100644
--- a/ext/tk/lib/tk/spinbox.rb
+++ b/ext/tk/lib/tk/spinbox.rb
@@ -1,12 +1,11 @@
#
# tk/spinbox.rb - Tk spinbox classes
-# $Date: 2005/10/22 22:16:24 $
# by Yukihiro Matsumoto <matz@caelum.co.jp>
#
require 'tk'
require 'tk/entry'
-class TkSpinbox<TkEntry
+class Tk::Spinbox<Tk::Entry
TkCommandNames = ['spinbox'.freeze].freeze
WidgetClassName = 'Spinbox'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -38,6 +37,24 @@ class TkSpinbox<TkEntry
nil
]
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
@@ -97,3 +114,6 @@ class TkSpinbox<TkEntry
_fromUTF8(tk_send_without_enc('set', _get_eval_enc_str(str)))
end
end
+
+#TkSpinbox = Tk::Spinbox unless Object.const_defined? :TkSpinbox
+Tk.__set_toplevel_aliases__(:Tk, Tk::Spinbox, :TkSpinbox)
diff --git a/ext/tk/lib/tk/text.rb b/ext/tk/lib/tk/text.rb
index 0db10a653f..4ec82bed1d 100644
--- a/ext/tk/lib/tk/text.rb
+++ b/ext/tk/lib/tk/text.rb
@@ -1,6 +1,5 @@
#
# tk/text.rb - Tk text classes
-# $Date: 2005/11/23 12:01:05 $
# by Yukihiro Matsumoto <matz@caelum.co.jp>
require 'tk'
require 'tk/itemfont'
@@ -33,34 +32,40 @@ module TkTextTagConfig
def tag_cget(tagOrId, option)
itemcget(['tag', tagOrId], option)
end
+ def tag_cget_strict(tagOrId, option)
+ itemcget_strict(['tag', tagOrId], option)
+ end
def tag_configure(tagOrId, slot, value=None)
itemconfigure(['tag', tagOrId], slot, value)
end
def tag_configinfo(tagOrId, slot=nil)
- itemconfigure(['tag', tagOrId], slot)
+ itemconfiginfo(['tag', tagOrId], slot)
end
def current_tag_configinfo(tagOrId, slot=nil)
- itemconfigure(['tag', tagOrId], slot)
+ current_itemconfiginfo(['tag', tagOrId], slot)
end
def window_cget(tagOrId, option)
itemcget(['window', tagOrId], option)
end
+ def window_cget_strict(tagOrId, option)
+ itemcget_strict(['window', tagOrId], option)
+ end
def window_configure(tagOrId, slot, value=None)
itemconfigure(['window', tagOrId], slot, value)
end
def window_configinfo(tagOrId, slot=nil)
- itemconfigure(['window', tagOrId], slot)
+ itemconfiginfo(['window', tagOrId], slot)
end
def current_window_configinfo(tagOrId, slot=nil)
- itemconfigure(['window', tagOrId], slot)
+ current_itemconfiginfo(['window', tagOrId], slot)
end
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
end
-class TkText<TkTextWin
+class Tk::Text<TkTextWin
ItemConfCMD = ['tag'.freeze, 'configure'.freeze].freeze
#include TkTreatTextTagFont
include TkTextTagConfig
@@ -74,9 +79,9 @@ class TkText<TkTextWin
mod = mod.to_s
if mod =~ /^\s*[+-]?\d/
- TkText::IndexString.new(String.new(id) << ' + ' << mod)
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod)
else
- TkText::IndexString.new(String.new(id) << ' ' << mod)
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod)
end
end
@@ -85,20 +90,20 @@ class TkText<TkTextWin
mod = mod.to_s
if mod =~ /^\s*[+-]?\d/
- TkText::IndexString.new(String.new(id) << ' - ' << mod)
+ Tk::Text::IndexString.new(String.new(id) << ' - ' << mod)
elsif mod =~ /^\s*[-]\s+(\d.*)$/
- TkText::IndexString.new(String.new(id) << ' - -' << $1)
+ Tk::Text::IndexString.new(String.new(id) << ' - -' << $1)
else
- TkText::IndexString.new(String.new(id) << ' ' << mod)
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod)
end
end
def chars(mod)
fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' chars')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' chars')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' chars')
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' chars')
end
end
alias char chars
@@ -107,9 +112,9 @@ class TkText<TkTextWin
# Tk8.5 feature
fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display chars')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display chars')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display chars')
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display chars')
end
end
alias display_char display_chars
@@ -118,9 +123,9 @@ class TkText<TkTextWin
# Tk8.5 feature
fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any chars')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any chars')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any chars')
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any chars')
end
end
alias any_char any_chars
@@ -129,9 +134,9 @@ class TkText<TkTextWin
# Tk8.5 feature
fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' indices')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' indices')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' indices')
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' indices')
end
end
@@ -139,9 +144,9 @@ class TkText<TkTextWin
# Tk8.5 feature
fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display indices')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display indices')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display indices')
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display indices')
end
end
@@ -149,18 +154,18 @@ class TkText<TkTextWin
# Tk8.5 feature
fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any indices')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any indices')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any indices')
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any indices')
end
end
def lines(mod)
fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' lines')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' lines')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' lines')
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' lines')
end
end
alias line lines
@@ -169,9 +174,9 @@ class TkText<TkTextWin
# Tk8.5 feature
fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display_lines')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display_lines')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display lines')
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display lines')
end
end
alias display_line display_lines
@@ -180,43 +185,43 @@ class TkText<TkTextWin
# Tk8.5 feature
fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any_lines')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any_lines')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any lines')
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any lines')
end
end
alias any_line any_lines
def linestart
- TkText::IndexString.new(String.new(id) << ' linestart')
+ Tk::Text::IndexString.new(String.new(id) << ' linestart')
end
def lineend
- TkText::IndexString.new(String.new(id) << ' lineend')
+ Tk::Text::IndexString.new(String.new(id) << ' lineend')
end
def display_linestart
# Tk8.5 feature
- TkText::IndexString.new(String.new(id) << ' display linestart')
+ Tk::Text::IndexString.new(String.new(id) << ' display linestart')
end
def display_lineend
# Tk8.5 feature
- TkText::IndexString.new(String.new(id) << ' display lineend')
+ Tk::Text::IndexString.new(String.new(id) << ' display lineend')
end
def wordstart
- TkText::IndexString.new(String.new(id) << ' wordstart')
+ Tk::Text::IndexString.new(String.new(id) << ' wordstart')
end
def wordend
- TkText::IndexString.new(String.new(id) << ' wordend')
+ Tk::Text::IndexString.new(String.new(id) << ' wordend')
end
def display_wordstart
# Tk8.5 feature
- TkText::IndexString.new(String.new(id) << ' display wordstart')
+ Tk::Text::IndexString.new(String.new(id) << ' display wordstart')
end
def display_wordend
# Tk8.5 feature
- TkText::IndexString.new(String.new(id) << ' display wordend')
+ Tk::Text::IndexString.new(String.new(id) << ' display wordend')
end
end
@@ -251,7 +256,11 @@ class TkText<TkTextWin
def self.new(*args, &block)
obj = super(*args){}
obj.init_instance_variable
- obj.instance_eval(&block) if defined? yield
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ obj.instance_exec(obj, &block) if defined? yield
+ else
+ obj.instance_eval(&block) if defined? yield
+ end
obj
end
@@ -261,8 +270,12 @@ class TkText<TkTextWin
end
def __destroy_hook__
- TkTextTag::TTagID_TBL.delete(@path)
- TkTextMark::TMarkID_TBL.delete(@path)
+ TkTextTag::TTagID_TBL.mutex.synchronize{
+ TkTextTag::TTagID_TBL.delete(@path)
+ }
+ TkTextTag::TMarkID_TBL.mutex.synchronize{
+ TkTextMark::TMarkID_TBL.delete(@path)
+ }
end
def create_self(keys)
@@ -285,16 +298,16 @@ class TkText<TkTextWin
private :__strval_optkeys
def self.at(x, y)
- TkText::IndexString.at(x, y)
+ Tk::Text::IndexString.at(x, y)
end
def at(x, y)
- TkText::IndexString.at(x, y)
+ Tk::Text::IndexString.at(x, y)
end
def index(idx)
- TkText::IndexString.new(tk_send_without_enc('index',
- _get_eval_enc_str(idx)))
+ Tk::Text::IndexString.new(tk_send_without_enc('index',
+ _get_eval_enc_str(idx)))
end
def get_displaychars(*index)
@@ -396,7 +409,7 @@ class TkText<TkTextWin
end
alias previous_mark mark_previous
- def image_cget(index, slot)
+ def image_cget_strict(index, slot)
case slot.to_s
when 'text', 'label', 'show', 'data', 'file'
_fromUTF8(tk_send_without_enc('image', 'cget',
@@ -408,6 +421,28 @@ class TkText<TkTextWin
end
end
+ def image_cget(index, slot)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ image_cget_strict(index, slot)
+ else
+ begin
+ image_cget_strict(index, slot)
+ rescue => e
+ begin
+ if current_image_configinfo(index).has_key?(slot.to_s)
+ # not tag error & option is known -> error on known option
+ fail e
+ else
+ # not tag error & option is unknown
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
+
def image_configure(index, slot, value=None)
if slot.kind_of?(Hash)
_fromUTF8(tk_send_without_enc('image', 'configure',
@@ -713,15 +748,17 @@ class TkText<TkTextWin
def tag_delete(*tags)
tk_send_without_enc('tag', 'delete',
*(tags.collect{|tag| _get_eval_enc_str(tag)}))
- if TkTextTag::TTagID_TBL[@path]
- tags.each{|tag|
- if tag.kind_of?(TkTextTag)
- TkTextTag::TTagID_TBL[@path].delete(tag.id)
- else
- TkTextTag::TTagID_TBL[@path].delete(tag)
- end
- }
- end
+ TkTextTag::TTagID_TBL.mutex.synchronize{
+ if TkTextTag::TTagID_TBL[@path]
+ tags.each{|tag|
+ if tag.kind_of?(TkTextTag)
+ TkTextTag::TTagID_TBL[@path].delete(tag.id)
+ else
+ TkTextTag::TTagID_TBL[@path].delete(tag)
+ end
+ }
+ end
+ }
self
end
alias deltag tag_delete
@@ -968,7 +1005,7 @@ class TkText<TkTextWin
false, true)
r = []
while key=l.shift
- r.push [TkText::IndexString.new(key), TkText::IndexString.new(l.shift)]
+ r.push [Tk::Text::IndexString.new(key), Tk::Text::IndexString.new(l.shift)]
end
r
end
@@ -978,7 +1015,7 @@ class TkText<TkTextWin
_get_eval_enc_str(tag),
_get_eval_enc_str(first),
_get_eval_enc_str(last))).collect{|idx|
- TkText::IndexString.new(idx)
+ Tk::Text::IndexString.new(idx)
}
end
@@ -987,7 +1024,7 @@ class TkText<TkTextWin
_get_eval_enc_str(tag),
_get_eval_enc_str(first),
_get_eval_enc_str(last))).collect{|idx|
- TkText::IndexString.new(idx)
+ Tk::Text::IndexString.new(idx)
}
end
@@ -1183,6 +1220,11 @@ class TkText<TkTextWin
end
def _ktext_length(txt)
+ if TkCore::WITH_ENCODING ### Ruby 1.9 !!!!!!!!!!!!!
+ return txt.length
+ end
+ ###########################
+
if $KCODE !~ /n/i
return txt.gsub(/[^\Wa-zA-Z_\d]/, ' ').length
end
@@ -1232,7 +1274,7 @@ class TkText<TkTextWin
if ret == ""
nil
else
- TkText::IndexString.new(ret)
+ Tk::Text::IndexString.new(ret)
end
end
@@ -1267,7 +1309,7 @@ class TkText<TkTextWin
if ret == ""
nil
else
- TkText::IndexString.new(ret)
+ Tk::Text::IndexString.new(ret)
end
end
@@ -1456,10 +1498,10 @@ class TkText<TkTextWin
# retrieve index
idx = str.index(/ /, i)
if idx
- result.push(TkText::IndexString.new(str[i..(idx-1)]))
+ result.push(Tk::Text::IndexString.new(str[i..(idx-1)]))
i = idx + 1
else
- result.push(TkText::IndexString.new(str[i..-1]))
+ result.push(Tk::Text::IndexString.new(str[i..-1]))
break
end
end
@@ -1527,13 +1569,17 @@ class TkText<TkTextWin
end
end
+#TkText = Tk::Text unless Object.const_defined? :TkText
+Tk.__set_toplevel_aliases__(:Tk, Tk::Text, :TkText)
+
+
#######################################
-class TkText::Peer < TkText
+class Tk::Text::Peer < Tk::Text
# Tk8.5 feature
def initialize(text, parent=nil, keys={})
- unless text.kind_of?(TkText)
- fail ArgumentError, "TkText is expected for 1st argument"
+ unless text.kind_of?(Tk::Text)
+ fail ArgumentError, "Tk::Text is expected for 1st argument"
end
@src_text = text
super(parent, keys)
diff --git a/ext/tk/lib/tk/textimage.rb b/ext/tk/lib/tk/textimage.rb
index a29b23c7dd..fb306a9c17 100644
--- a/ext/tk/lib/tk/textimage.rb
+++ b/ext/tk/lib/tk/textimage.rb
@@ -5,11 +5,11 @@ require 'tk'
require 'tk/text'
class TkTextImage<TkObject
- include TkText::IndexModMethods
+ include Tk::Text::IndexModMethods
def initialize(parent, index, keys)
- #unless parent.kind_of?(TkText)
- # fail ArgumentError, "expect TkText for 1st argument"
+ #unless parent.kind_of?(Tk::Text)
+ # fail ArgumentError, "expect Tk::Text for 1st argument"
#end
@t = parent
if index == 'end' || index == :end
@@ -34,7 +34,7 @@ class TkTextImage<TkObject
end
def id
- TkText::IndexString.new(@id)
+ Tk::Text::IndexString.new(@id)
end
def mark
@path
@@ -52,6 +52,10 @@ class TkTextImage<TkObject
@t.image_cget(@index, slot)
end
+ def cget_strict(slot)
+ @t.image_cget_strict(@index, slot)
+ end
+
def configure(slot, value=None)
@t.image_configure(@index, slot, value)
self
@@ -80,3 +84,5 @@ class TkTextImage<TkObject
value
end
end
+
+TktImage = TkTextImage
diff --git a/ext/tk/lib/tk/textmark.rb b/ext/tk/lib/tk/textmark.rb
index 650d95af70..72c1ce1ab4 100644
--- a/ext/tk/lib/tk/textmark.rb
+++ b/ext/tk/lib/tk/textmark.rb
@@ -5,38 +5,54 @@ require 'tk'
require 'tk/text'
class TkTextMark<TkObject
- include TkText::IndexModMethods
+ include Tk::Text::IndexModMethods
TMarkID_TBL = TkCore::INTERP.create_table
- Tk_TextMark_ID = ['mark'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ TMarkID_TBL.clear }
+ (Tk_TextMark_ID = ['mark'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ TMarkID_TBL.mutex.synchronize{ TMarkID_TBL.clear }
+ }
def TkTextMark.id2obj(text, id)
tpath = text.path
- return id unless TMarkID_TBL[tpath]
- TMarkID_TBL[tpath][id]? TMarkID_TBL[tpath][id]: id
+ TMarkID_TBL.mutex.synchronize{
+ if TMarkID_TBL[tpath]
+ TMarkID_TBL[tpath][id]? TMarkID_TBL[tpath][id]: id
+ else
+ id
+ end
+ }
end
def initialize(parent, index)
- #unless parent.kind_of?(TkText)
- # fail ArgumentError, "expect TkText for 1st argument"
+ #unless parent.kind_of?(Tk::Text)
+ # fail ArgumentError, "expect Tk::Text for 1st argument"
#end
@parent = @t = parent
@tpath = parent.path
- # @path = @id = Tk_TextMark_ID.join('')
- @path = @id = Tk_TextMark_ID.join(TkCore::INTERP._ip_id_).freeze
- TMarkID_TBL[@id] = self
- TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
- TMarkID_TBL[@tpath][@id] = self
- Tk_TextMark_ID[1].succ!
+ Tk_TextMark_ID.mutex.synchronize{
+ # @path = @id = Tk_TextMark_ID.join('')
+ @path = @id = Tk_TextMark_ID.join(TkCore::INTERP._ip_id_).freeze
+ Tk_TextMark_ID[1].succ!
+ }
+ TMarkID_TBL.mutex.synchronize{
+ TMarkID_TBL[@id] = self
+ TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
+ TMarkID_TBL[@tpath][@id] = self
+ }
tk_call_without_enc(@t.path, 'mark', 'set', @id,
_get_eval_enc_str(index))
@t._addtag id, self
end
def id
- TkText::IndexString.new(@id)
+ Tk::Text::IndexString.new(@id)
end
def exist?
@@ -49,15 +65,15 @@ class TkTextMark<TkObject
end
=begin
- # move to TkText::IndexModMethods module
+ # move to Tk::Text::IndexModMethods module
def +(mod)
return chars(mod) if mod.kind_of?(Numeric)
mod = mod.to_s
if mod =~ /^\s*[+-]?\d/
- TkText::IndexString.new(@id + ' + ' + mod)
+ Tk::Text::IndexString.new(@id + ' + ' + mod)
else
- TkText::IndexString.new(@id + ' ' + mod)
+ Tk::Text::IndexString.new(@id + ' ' + mod)
end
end
@@ -66,11 +82,11 @@ class TkTextMark<TkObject
mod = mod.to_s
if mod =~ /^\s*[+-]?\d/
- TkText::IndexString.new(@id + ' - ' + mod)
+ Tk::Text::IndexString.new(@id + ' - ' + mod)
elsif mod =~ /^\s*[-]\s+(\d.*)$/
- TkText::IndexString.new(@id + ' - -' + $1)
+ Tk::Text::IndexString.new(@id + ' - -' + $1)
else
- TkText::IndexString.new(@id + ' ' + mod)
+ Tk::Text::IndexString.new(@id + ' ' + mod)
end
end
=end
@@ -121,46 +137,68 @@ class TkTextMark<TkObject
end
end
end
+TktMark = TkTextMark
class TkTextNamedMark<TkTextMark
- def self.new(parent, name, *args)
- if TMarkID_TBL[parent.path] && TMarkID_TBL[parent.path][name]
- return TMarkID_TBL[parent.path][name]
- else
- super(parent, name, *args)
- end
+ def self.new(parent, name, index=nil)
+ TMarkID_TBL.mutex.synchronize{
+ if TMarkID_TBL[parent.path] && TMarkID_TBL[parent.path][name]
+ obj = TMarkID_TBL[parent.path][name]
+ else
+ # super(parent, name, *args)
+ (obj = self.allocate).instance_eval{
+ @parent = @t = parent
+ @tpath = parent.path
+ @path = @id = name
+ TMarkID_TBL[@id] = self
+ TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
+ TMarkID_TBL[@tpath][@id] = self unless TMarkID_TBL[@tpath][@id]
+ @t._addtag @id, self
+ }
+ obj
+ end
+
+ if obj && index
+ tk_call_without_enc(parent.path, 'mark', 'set', name,
+ _get_eval_enc_str(index))
+ end
+ obj
+ }
end
def initialize(parent, name, index=nil)
- #unless parent.kind_of?(TkText)
- # fail ArgumentError, "expect TkText for 1st argument"
+ # dummy:: not called by 'new' method
+
+ #unless parent.kind_of?(Tk::Text)
+ # fail ArgumentError, "expect Tk::Text for 1st argument"
#end
@parent = @t = parent
@tpath = parent.path
@path = @id = name
- TMarkID_TBL[@id] = self
- TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
- TMarkID_TBL[@tpath][@id] = self unless TMarkID_TBL[@tpath][@id]
tk_call_without_enc(@t.path, 'mark', 'set', @id,
_get_eval_enc_str(index)) if index
- @t._addtag id, self
+ @t._addtag @id, self
end
end
+TktNamedMark = TkTextNamedMark
class TkTextMarkInsert<TkTextNamedMark
def self.new(parent,*args)
super(parent, 'insert', *args)
end
end
+TktMarkInsert = TkTextMarkInsert
class TkTextMarkCurrent<TkTextNamedMark
def self.new(parent,*args)
super(parent, 'current', *args)
end
end
+TktMarkCurrent = TkTextMarkCurrent
class TkTextMarkAnchor<TkTextNamedMark
def self.new(parent,*args)
super(parent, 'anchor', *args)
end
end
+TktMarkAnchor = TkTextMarkAnchor
diff --git a/ext/tk/lib/tk/texttag.rb b/ext/tk/lib/tk/texttag.rb
index cc2c56210f..b08d923ea1 100644
--- a/ext/tk/lib/tk/texttag.rb
+++ b/ext/tk/lib/tk/texttag.rb
@@ -7,17 +7,29 @@ require 'tk/tagfont'
class TkTextTag<TkObject
include TkTreatTagFont
- include TkText::IndexModMethods
+ include Tk::Text::IndexModMethods
TTagID_TBL = TkCore::INTERP.create_table
- Tk_TextTag_ID = ['tag'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ TTagID_TBL.clear }
+ (Tk_TextTag_ID = ['tag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ TTagID_TBL.mutex.synchronize{ TTagID_TBL.clear }
+ }
def TkTextTag.id2obj(text, id)
tpath = text.path
- return id unless TTagID_TBL[tpath]
- TTagID_TBL[tpath][id]? TTagID_TBL[tpath][id]: id
+ TTagID_TBL.mutex.synchronize{
+ if TTagID_TBL[tpath]
+ TTagID_TBL[tpath][id]? TTagID_TBL[tpath][id]: id
+ else
+ id
+ end
+ }
end
def initialize(parent, *args)
@@ -26,12 +38,16 @@ class TkTextTag<TkObject
#end
@parent = @t = parent
@tpath = parent.path
- # @path = @id = Tk_TextTag_ID.join('')
- @path = @id = Tk_TextTag_ID.join(TkCore::INTERP._ip_id_).freeze
- # TTagID_TBL[@id] = self
- TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
- TTagID_TBL[@tpath][@id] = self
- Tk_TextTag_ID[1].succ!
+ Tk_TextTag_ID.mutex.synchronize{
+ # @path = @id = Tk_TextTag_ID.join('')
+ @path = @id = Tk_TextTag_ID.join(TkCore::INTERP._ip_id_).freeze
+ Tk_TextTag_ID[1].succ!
+ }
+ TTagID_TBL.mutex.synchronize{
+ TTagID_TBL[@id] = self
+ TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
+ TTagID_TBL[@tpath][@id] = self
+ }
#tk_call @t.path, "tag", "configure", @id, *hash_kv(keys)
if args != []
keys = args.pop
@@ -47,7 +63,7 @@ class TkTextTag<TkObject
end
def id
- TkText::IndexString.new(@id)
+ Tk::Text::IndexString.new(@id)
end
def exist?
@@ -60,11 +76,11 @@ class TkTextTag<TkObject
end
def first
- TkText::IndexString.new(@id + '.first')
+ Tk::Text::IndexString.new(@id + '.first')
end
def last
- TkText::IndexString.new(@id + '.last')
+ Tk::Text::IndexString.new(@id + '.last')
end
def add(*indices)
@@ -83,7 +99,7 @@ class TkTextTag<TkObject
l = tk_split_simplelist(tk_call_without_enc(@t.path, 'tag', 'ranges', @id))
r = []
while key=l.shift
- r.push [TkText::IndexString.new(key), TkText::IndexString.new(l.shift)]
+ r.push [Tk::Text::IndexString.new(key), Tk::Text::IndexString.new(l.shift)]
end
r
end
@@ -92,7 +108,7 @@ class TkTextTag<TkObject
simplelist(tk_call_without_enc(@t.path, 'tag', 'nextrange', @id,
_get_eval_enc_str(first),
_get_eval_enc_str(last))).collect{|idx|
- TkText::IndexString.new(idx)
+ Tk::Text::IndexString.new(idx)
}
end
@@ -100,7 +116,7 @@ class TkTextTag<TkObject
simplelist(tk_call_without_enc(@t.path, 'tag', 'prevrange', @id,
_get_eval_enc_str(first),
_get_eval_enc_str(last))).collect{|idx|
- TkText::IndexString.new(idx)
+ Tk::Text::IndexString.new(idx)
}
end
@@ -116,6 +132,9 @@ class TkTextTag<TkObject
def cget(key)
@t.tag_cget @id, key
end
+ def cget_strict(key)
+ @t.tag_cget_strict @id, key
+ end
=begin
def cget(key)
case key.to_s
@@ -221,40 +240,58 @@ class TkTextTag<TkObject
def destroy
tk_call_without_enc(@t.path, 'tag', 'delete', @id)
- TTagID_TBL[@tpath].delete(@id) if TTagID_TBL[@tpath]
+ TTagID_TBL.mutex.synchronize{
+ TTagID_TBL[@tpath].delete(@id) if TTagID_TBL[@tpath]
+ }
self
end
end
+TktTag = TkTextTag
class TkTextNamedTag<TkTextTag
def self.new(parent, name, *args)
- if TTagID_TBL[parent.path] && TTagID_TBL[parent.path][name]
- tagobj = TTagID_TBL[parent.path][name]
- if args != []
- keys = args.pop
- if keys.kind_of?(Hash)
- tagobj.add(*args) if args != []
- tagobj.configure(keys)
- else
- args.push keys
- tagobj.add(*args)
- end
+ tagobj = nil
+ TTagID_TBL.mutex.synchronize{
+ if TTagID_TBL[parent.path] && TTagID_TBL[parent.path][name]
+ tagobj = TTagID_TBL[parent.path][name]
+ else
+ # super(parent, name, *args)
+ (tagobj = self.allocate).instance_eval{
+ @parent = @t = parent
+ @tpath = parent.path
+ @path = @id = name
+ TTagID_TBL[@id] = self
+ TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
+ TTagID_TBL[@tpath][@id] = self unless TTagID_TBL[@tpath][@id]
+ @t._addtag @id, self
+ }
+ end
+ }
+
+ if args != []
+ keys = args.pop
+ if keys.kind_of?(Hash)
+ tagobj.add(*args) if args != []
+ tagobj.configure(keys)
+ else
+ args.push keys
+ tagobj.add(*args)
end
- return tagobj
- else
- super(parent, name, *args)
end
+
+ tagobj
end
def initialize(parent, name, *args)
- #unless parent.kind_of?(TkText)
- # fail ArgumentError, "expect TkText for 1st argument"
+ # dummy:: not called by 'new' method
+
+ #unless parent.kind_of?(Tk::Text)
+ # fail ArgumentError, "expect Tk::Text for 1st argument"
#end
@parent = @t = parent
@tpath = parent.path
@path = @id = name
- TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
- TTagID_TBL[@tpath][@id] = self unless TTagID_TBL[@tpath][@id]
+
#if mode
# tk_call @t.path, "addtag", @id, *args
#end
@@ -268,12 +305,14 @@ class TkTextNamedTag<TkTextTag
add(*args)
end
end
- @t._addtag id, self
+ @t._addtag @id, self
end
end
+TktNamedTag = TkTextNamedTag
class TkTextTagSel<TkTextNamedTag
def self.new(parent, *args)
super(parent, 'sel', *args)
end
end
+TktTagSel = TkTextTagSel
diff --git a/ext/tk/lib/tk/textwindow.rb b/ext/tk/lib/tk/textwindow.rb
index 605c40addd..004422e4f3 100644
--- a/ext/tk/lib/tk/textwindow.rb
+++ b/ext/tk/lib/tk/textwindow.rb
@@ -5,11 +5,11 @@ require 'tk'
require 'tk/text'
class TkTextWindow<TkObject
- include TkText::IndexModMethods
+ include Tk::Text::IndexModMethods
def initialize(parent, index, keys = {})
- #unless parent.kind_of?(TkText)
- # fail ArgumentError, "expect TkText for 1st argument"
+ #unless parent.kind_of?(Tk::Text)
+ # fail ArgumentError, "expect Tk::Text for 1st argument"
#end
@t = parent
if index == 'end' || index == :end
@@ -55,7 +55,7 @@ class TkTextWindow<TkObject
end
def id
- TkText::IndexString.new(_epath(@id))
+ Tk::Text::IndexString.new(_epath(@id))
end
def mark
@path
@@ -72,6 +72,9 @@ class TkTextWindow<TkObject
def cget(slot)
@t.window_cget(@index, slot)
end
+ def cget_strict(slot)
+ @t.window_cget_strict(@index, slot)
+ end
def configure(slot, value=None)
if slot.kind_of?(Hash)
@@ -147,3 +150,5 @@ class TkTextWindow<TkObject
value
end
end
+
+TktWindow = TkTextWindow
diff --git a/ext/tk/lib/tk/timer.rb b/ext/tk/lib/tk/timer.rb
index 49b7f1b06a..91840d0575 100644
--- a/ext/tk/lib/tk/timer.rb
+++ b/ext/tk/lib/tk/timer.rb
@@ -1,7 +1,7 @@
#
# tk/timer.rb : methods for Tcl/Tk after command
#
-# $Id: timer.rb,v 1.1.2.15 2005/05/08 14:20:53 nagai Exp $
+# $Id$
#
require 'tk'
@@ -11,7 +11,12 @@ class TkTimer
TkCommandNames = ['after'.freeze].freeze
- Tk_CBID = ['a'.freeze, '00000'.taint].freeze
+ (Tk_CBID = ['a'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
Tk_CBTBL = {}.taint
TkCore::INTERP.add_tk_procs('rb_after', 'id', <<-'EOL')
@@ -96,9 +101,9 @@ class TkTimer
return self
end
@after_script = "rb_after #{@id}"
- @after_id = tk_call_without_enc('after', sleep, @after_script)
@current_args = args
@current_script = [sleep, @after_script]
+ @after_id = tk_call_without_enc('after', sleep, @after_script)
self
end
@@ -106,7 +111,8 @@ class TkTimer
if @running == false || @proc_max == 0 || @do_loop == 0
Tk_CBTBL.delete(@id) ;# for GC
@running = false
- @wait_var.value = 0
+ # @wait_var.value = 0
+ __at_end__
return
end
if @current_pos >= @proc_max
@@ -115,7 +121,8 @@ class TkTimer
else
Tk_CBTBL.delete(@id) ;# for GC
@running = false
- @wait_var.value = 0
+ # @wait_var.value = 0
+ __at_end__
return
end
end
@@ -138,12 +145,16 @@ class TkTimer
end
def initialize(*args, &b)
- # @id = Tk_CBID.join('')
- @id = Tk_CBID.join(TkCore::INTERP._ip_id_)
- Tk_CBID[1].succ!
+ Tk_CBID.mutex.synchronize{
+ # @id = Tk_CBID.join('')
+ @id = Tk_CBID.join(TkCore::INTERP._ip_id_)
+ Tk_CBID[1].succ!
+ }
@wait_var = TkVariable.new(0)
+ @at_end_proc = nil
+
@cb_cmd = TkCore::INTERP.get_cb_entry(self.method(:do_callback))
@set_next = true
@@ -203,6 +214,12 @@ class TkTimer
attr_accessor :loop_exec
+ def __at_end__
+ @at_end_proc.call(self) if @at_end_proc
+ @wait_var.value = 0 # for wait
+ end
+ private :__at_end__
+
def cb_call
@cb_cmd.call
end
@@ -420,7 +437,8 @@ class TkTimer
def cancel
@running = false
- @wait_var.value = 0
+ # @wait_var.value = 0
+ __at_end__
tk_call 'after', 'cancel', @after_id if @after_id
@after_id = nil
@@ -464,6 +482,21 @@ class TkTimer
end
end
+ def at_end(*arg, &b)
+ if arg.empty?
+ if b
+ @at_end_proc = b
+ else
+ # no proc
+ return @at_end_proc
+ end
+ else
+ fail ArgumentError, "wrong number of arguments" if arg.length != 1 || b
+ @at_end_proc = arg[0]
+ end
+ self
+ end
+
def wait(on_thread = true, check_root = false)
if $SAFE >= 4
fail SecurityError, "can't wait timer at $SAFE >= 4"
@@ -562,7 +595,8 @@ class TkRTTimer < TkTimer
if @running == false || @proc_max == 0 || @do_loop == 0
Tk_CBTBL.delete(@id) ;# for GC
@running = false
- @wait_var.value = 0
+ # @wait_var.value = 0
+ __at_end__
return
end
if @current_pos >= @proc_max
@@ -571,7 +605,8 @@ class TkRTTimer < TkTimer
else
Tk_CBTBL.delete(@id) ;# for GC
@running = false
- @wait_var.value = 0
+ # @wait_var.value = 0
+ __at_end__
return
end
end
diff --git a/ext/tk/lib/tk/toplevel.rb b/ext/tk/lib/tk/toplevel.rb
index 5e199e1330..bd6e8307f5 100644
--- a/ext/tk/lib/tk/toplevel.rb
+++ b/ext/tk/lib/tk/toplevel.rb
@@ -5,7 +5,7 @@ require 'tk'
require 'tk/wm'
require 'tk/menuspec'
-class TkToplevel<TkWindow
+class Tk::Toplevel<TkWindow
include Wm
include TkMenuSpec
@@ -72,7 +72,7 @@ class TkToplevel<TkWindow
conf_methods = _symbolkey2str(__methodcall_optkeys())
- keys.each{|k,v|
+ keys.each{|k,v| # k is a String
if conf_methods.key?(k)
wm_cmds[conf_methods[k]] = v
elsif Wm.method_defined?(k)
@@ -117,9 +117,10 @@ class TkToplevel<TkWindow
end
if @classname.kind_of? TkBindTag
@db_class = @classname
- @classname = @classname.id
+ keys['class'] = @classname = @classname.id
elsif @classname
@db_class = TkDatabaseClass.new(@classname)
+ keys['class'] = @classname
else
@db_class = self.class
@classname = @db_class::WidgetClassName
@@ -165,9 +166,10 @@ class TkToplevel<TkWindow
end
if @classname.kind_of? TkBindTag
@db_class = @classname
- @classname = @classname.id
+ keys['class'] = @classname = @classname.id
elsif @classname
@db_class = TkDatabaseClass.new(@classname)
+ keys['class'] = @classname
else
@db_class = self.class
@classname = @db_class::WidgetClassName
@@ -255,3 +257,6 @@ class TkToplevel<TkWindow
end
end
end
+
+#TkToplevel = Tk::Toplevel unless Object.const_defined? :TkToplevel
+Tk.__set_toplevel_aliases__(:Tk, Tk::Toplevel, :TkToplevel)
diff --git a/ext/tk/lib/tk/ttk_selector.rb b/ext/tk/lib/tk/ttk_selector.rb
new file mode 100644
index 0000000000..72ed637a38
--- /dev/null
+++ b/ext/tk/lib/tk/ttk_selector.rb
@@ -0,0 +1,76 @@
+#
+# ttk_selector
+#
+######################################
+# toplevel classes/modules
+module Tk
+ @TOPLEVEL_ALIAS_TABLE[:Ttk] = {
+ :TkButton => 'tkextlib/tile/tbutton',
+
+ :TkCheckbutton => 'tkextlib/tile/tcheckbutton',
+ :TkCheckButton => 'tkextlib/tile/tcheckbutton',
+
+ # :TkDialog => 'tkextlib/tile/dialog',
+
+ :TkEntry => 'tkextlib/tile/tentry',
+
+ :TkCombobox => 'tkextlib/tile/tcombobox',
+
+ :TkFrame => 'tkextlib/tile/tframe',
+
+ :TkLabel => 'tkextlib/tile/tlabel',
+
+ :TkLabelframe => 'tkextlib/tile/tlabelframe',
+ :TkLabelFrame => 'tkextlib/tile/tlabelframe',
+
+ :TkMenubutton => 'tkextlib/tile/tmenubutton',
+ :TkMenuButton => 'tkextlib/tile/tmenubutton',
+
+ :TkNotebook => 'tkextlib/tile/tnotebook',
+
+ # :TkPaned => 'tkextlib/tile/tpaned',
+ :TkPanedwindow => 'tkextlib/tile/tpaned',
+ :TkPanedWindow => 'tkextlib/tile/tpaned',
+
+ :TkProgressbar => 'tkextlib/tile/tprogressbar',
+
+ :TkRadiobutton => 'tkextlib/tile/tradiobutton',
+ :TkRadioButton => 'tkextlib/tile/tradiobutton',
+
+ :TkScale => 'tkextlib/tile/tscale',
+ # :TkProgress => 'tkextlib/tile/tscale',
+
+ :TkScrollbar => 'tkextlib/tile/tscrollbar',
+ :TkXScrollbar => 'tkextlib/tile/tscrollbar',
+ :TkYScrollbar => 'tkextlib/tile/tscrollbar',
+
+ :TkSeparator => 'tkextlib/tile/tseparator',
+
+ :TkSizeGrip => 'tkextlib/tile/sizegrip',
+ :TkSizegrip => 'tkextlib/tile/sizegrip',
+
+ # :TkSquare => 'tkextlib/tile/tsquare',
+
+ :TkTreeview => 'tkextlib/tile/treeview',
+ }
+ @TOPLEVEL_ALIAS_TABLE[:Tile] = @TOPLEVEL_ALIAS_TABLE[:Ttk]
+
+ ################################################
+ # register some Ttk widgets as default
+ # (Ttk is a standard library on Tcl/Tk8.5+)
+ @TOPLEVEL_ALIAS_TABLE[:Ttk].each{|sym, file|
+ unless Object.autoload?(sym) || Object.const_defined?(sym)
+ Object.autoload(sym, file)
+ end
+ }
+
+ ################################################
+
+ @TOPLEVEL_ALIAS_SETUP_PROC[:Tile] =
+ @TOPLEVEL_ALIAS_SETUP_PROC[:Ttk] = proc{|mod|
+ unless Tk.autoload?(:Tile) || Tk.const_defined?(:Tile)
+ Object.autoload :Ttk, 'tkextlib/tile'
+ Tk.autoload :Tile, 'tkextlib/tile'
+ end
+ }
+end
diff --git a/ext/tk/lib/tk/txtwin_abst.rb b/ext/tk/lib/tk/txtwin_abst.rb
index 5520360eab..540f806d17 100644
--- a/ext/tk/lib/tk/txtwin_abst.rb
+++ b/ext/tk/lib/tk/txtwin_abst.rb
@@ -4,7 +4,7 @@
require 'tk'
class TkTextWin<TkWindow
- TkCommnadNames = [].freeze
+ TkCommandNames = [].freeze
#def create_self
# fail RuntimeError, "TkTextWin is an abstract class"
#end
diff --git a/ext/tk/lib/tk/validation.rb b/ext/tk/lib/tk/validation.rb
index 0c5b5c61b9..60bd433cdc 100644
--- a/ext/tk/lib/tk/validation.rb
+++ b/ext/tk/lib/tk/validation.rb
@@ -50,7 +50,8 @@ module Tk
key2class.each{|key, klass|
if keys[key].kind_of?(Array)
cmd, *args = keys[key]
- keys[key] = klass.new(cmd, args.join(' '))
+ #keys[key] = klass.new(cmd, args.join(' '))
+ keys[key] = klass.new(cmd, *args)
# elsif keys[key].kind_of?(Proc) || keys[key].kind_of?(Method)
elsif TkComm._callback_entry?(keys[key])
keys[key] = klass.new(keys[key])
@@ -151,7 +152,8 @@ module Tk
key2class.each{|key, klass|
if keys[key].kind_of?(Array)
cmd, *args = keys[key]
- keys[key] = klass.new(cmd, args.join(' '))
+ #keys[key] = klass.new(cmd, args.join(' '))
+ keys[key] = klass.new(cmd, *args)
# elsif keys[key].kind_of?(Proc) || keys[key].kind_of?(Method)
elsif TkComm._callback_entry?(keys[key])
keys[key] = klass.new(keys[key])
@@ -249,6 +251,24 @@ class TkValidateCommand
nil
]
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
_setup_subst_table(KEY_TBL, PROC_TBL);
#
@@ -277,6 +297,7 @@ class TkValidateCommand
extra_args_tbl = klass._get_extra_args_tbl
if args.compact.size > 0
+ args.map!{|arg| klass._sym2subst(arg)}
args = args.join(' ')
keys = klass._get_subst_key(args)
if cmd.kind_of?(String)
diff --git a/ext/tk/lib/tk/variable.rb b/ext/tk/lib/tk/variable.rb
index e5cacadc1a..f738a96ee7 100644
--- a/ext/tk/lib/tk/variable.rb
+++ b/ext/tk/lib/tk/variable.rb
@@ -16,11 +16,22 @@ class TkVariable
#TkVar_ID_TBL = {}
TkVar_CB_TBL = TkCore::INTERP.create_table
TkVar_ID_TBL = TkCore::INTERP.create_table
- Tk_VARIABLE_ID = ["v".freeze, "00000".taint].freeze
+ (Tk_VARIABLE_ID = ["v".freeze, "00000".taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+ TkCore::INTERP.init_ip_env{
+ TkVar_CB_TBL.mutex.synchronize{ TkVar_CB_TBL.clear }
+ TkVar_ID_TBL.mutex.synchronize{ TkVar_ID_TBL.clear }
+ }
+
+ major, minor, type, type_name, patchlevel = TclTkLib.get_version
+ USE_OLD_TRACE_OPTION_STYLE = (major < 8) || (major == 8 && minor < 4)
#TkCore::INTERP.add_tk_procs('rb_var', 'args',
# "ruby [format \"TkVariable.callback %%Q!%s!\" $args]")
-TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
+ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
if {[set st [catch {eval {ruby_cmd TkVariable callback} $args} ret]] != 0} {
set idx [string first "\n\n" $ret]
if {$idx > 0} {
@@ -44,10 +55,10 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
def TkVariable.callback(id, name1, name2, op)
#name1,name2,op = tk_split_list(args)
#name1,name2,op = tk_split_simplelist(args)
- if TkVar_CB_TBL[id]
+ if cb_obj = TkVar_CB_TBL[id]
#_get_eval_string(TkVar_CB_TBL[name1].trace_callback(name2,op))
begin
- _get_eval_string(TkVar_CB_TBL[id].trace_callback(name2, op))
+ _get_eval_string(cb_obj.trace_callback(name2, op))
rescue SystemExit
exit(0)
rescue Interrupt
@@ -59,7 +70,11 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
"\n---< backtrace of Ruby side >-----\n" +
_toUTF8(e.backtrace.join("\n")) +
"\n---< backtrace of Tk side >-------"
- msg.instance_variable_set(:@encoding, 'utf-8')
+ if TkCore::WITH_ENCODING
+ msg.force_encoding('utf-8')
+ else
+ msg.instance_variable_set(:@encoding, 'utf-8')
+ end
rescue Exception
msg = e.class.inspect + ': ' + e.message + "\n" +
"\n---< backtrace of Ruby side >-----\n" +
@@ -267,11 +282,15 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
def initialize(val="", type=nil)
# @id = Tk_VARIABLE_ID.join('')
begin
- @id = Tk_VARIABLE_ID.join(TkCore::INTERP._ip_id_)
- Tk_VARIABLE_ID[1].succ!
+ Tk_VARIABLE_ID.mutex.synchronize{
+ @id = Tk_VARIABLE_ID.join(TkCore::INTERP._ip_id_)
+ Tk_VARIABLE_ID[1].succ!
+ }
end until INTERP._invoke_without_enc('info', 'globals', @id).empty?
- TkVar_ID_TBL[@id] = self
+ TkVar_ID_TBL.mutex.synchronize{
+ TkVar_ID_TBL[@id] = self
+ }
@var = @id
@elem = nil
@@ -1263,56 +1282,101 @@ end
end
end
+ def _check_trace_opt(opts)
+ if opts.kind_of?(Array)
+ opt_str = opts.map{|s| s.to_s}.join(' ')
+ else
+ opt_str = opts.to_s
+ end
+
+ fail ArgumentError, 'null trace option' if opt_str.empty?
+
+ if opt_str =~ /[^arwu\s]/
+ # new format (Tcl/Tk8.4+?)
+ if opts.kind_of?(Array)
+ opt_ary = opts.map{|opt| opt.to_s.strip}
+ else
+ opt_ary = opt_str.split(/\s+|\|/)
+ opt_ary.delete('')
+ end
+ if USE_OLD_TRACE_OPTION_STYLE
+ opt_ary.uniq.map{|opt|
+ case opt
+ when 'array'
+ 'a'
+ when 'read'
+ 'r'
+ when 'write'
+ 'w'
+ when 'unset'
+ 'u'
+ else
+ fail ArgumentError, "unsupported trace option '#{opt}' on Tcl/Tk#{Tk::TCL_PATCHLEVEL}"
+ end
+ }.join
+ else
+ opt_ary
+ end
+ else
+ # old format
+ opt_ary = opt_str.delete('^arwu').split(//).uniq
+ if USE_OLD_TRACE_OPTION_STYLE
+ opt_ary.join
+ else
+ opt_ary.map{|c|
+ case c
+ when 'a'
+ 'array'
+ when 'r'
+ 'read'
+ when 'w'
+ 'write'
+ when 'u'
+ 'unset'
+ end
+ }
+ end
+ end
+ end
+ private :_check_trace_opt
+
def trace(opts, cmd = Proc.new)
- @trace_var = [] if @trace_var == nil
- #opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
- opts = opts.to_s
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
- @trace_var.unshift([opts,cmd])
+ opts = _check_trace_opt(opts)
+ (@trace_var ||= []).unshift([opts,cmd])
+
if @trace_opts == nil
TkVar_CB_TBL[@id] = self
- @trace_opts = opts.dup
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
+ @trace_opts = opts
+ if USE_OLD_TRACE_OPTION_STYLE
+ Tk.tk_call_without_enc('trace', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
else
- # TCL_VERSION <= 8.3
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, 'rb_var')
+ Tk.tk_call_without_enc('trace', 'add', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
end
-=end
else
newopts = @trace_opts.dup
- #opts.each_byte{|c| newopts += c.chr unless newopts.index(c)}
- opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
- if newopts != @trace_opts
- Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts,
- 'rb_var ' << @id)
- @trace_opts.replace(newopts)
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'remove', 'variable',
- @id, @trace_opts, 'rb_var')
- @trace_opts.replace(newopts)
- Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
+ if USE_OLD_TRACE_OPTION_STYLE
+ opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ if newopts != @trace_opts
Tk.tk_call_without_enc('trace', 'vdelete',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
@trace_opts.replace(newopts)
Tk.tk_call_without_enc('trace', 'variable',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
+ else
+ newopts |= opts
+ unless (newopts - @trace_opts).empty?
+ Tk.tk_call_without_enc('trace', 'remove', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ Tk.tk_call_without_enc('trace', 'add', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
end
-=end
end
end
+
self
end
@@ -1321,65 +1385,54 @@ end
fail(RuntimeError,
"invalid for a TkVariable which denotes an element of Tcl's array")
end
- @trace_elem = {} if @trace_elem == nil
- @trace_elem[elem] = [] if @trace_elem[elem] == nil
- opts = opts.to_s
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
- @trace_elem[elem].unshift([opts,cmd])
+
+ opts = _check_trace_opt(opts)
+
+ ((@trace_elem ||= {})[elem] ||= []).unshift([opts,cmd])
+
if @trace_opts == nil
TkVar_CB_TBL[@id] = self
- @trace_opts = opts.dup
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
+ @trace_opts = opts
+ if USE_OLD_TRACE_OPTION_STYLE
Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
else
- # TCL_VERSION <= 8.3
Tk.tk_call_without_enc('trace', 'variable',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
end
-=end
else
newopts = @trace_opts.dup
- # opts.each_byte{|c| newopts += c.chr unless newopts.index(c)}
- opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
- if newopts != @trace_opts
- Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts,
- 'rb_var ' << @id)
- @trace_opts.replace(newopts)
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'remove', 'variable',
- @id, @trace_opts, 'rb_var')
- @trace_opts.replace(newopts)
- Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
+ if USE_OLD_TRACE_OPTION_STYLE
+ opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ if newopts != @trace_opts
Tk.tk_call_without_enc('trace', 'vdelete',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
@trace_opts.replace(newopts)
Tk.tk_call_without_enc('trace', 'variable',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
+ else
+ newopts |= opts
+ unless (newopts - @trace_opts).empty?
+ Tk.tk_call_without_enc('trace', 'remove', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ Tk.tk_call_without_enc('trace', 'add', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
end
-=end
end
end
+
self
end
- def trace_vinfo
+ def trace_info
return [] unless @trace_var
@trace_var.dup
end
+ alias trace_vinfo trace_info
- def _trace_vinfo_for_element(elem)
+ def trace_info_for_element(elem)
if @elem
fail(RuntimeError,
"invalid for a TkVariable which denotes an element of Tcl's array")
@@ -1388,141 +1441,180 @@ end
return [] unless @trace_elem[elem]
@trace_elem[elem].dup
end
+ alias trace_vinfo_for_element trace_info_for_element
- def trace_vdelete(opts,cmd)
+ def trace_remove(opts,cmd)
return self unless @trace_var.kind_of? Array
- opts = opts.to_s
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
+
+ opts = _check_trace_opt(opts)
+
idx = -1
- newopts = ''
- @trace_var.each_with_index{|e,i|
- if idx < 0 && e[0] == opts && e[1] == cmd
- idx = i
- next
- end
- # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
- }
+ if USE_OLD_TRACE_OPTION_STYLE
+ newopts = ''
+ @trace_var.each_with_index{|e, i|
+ if idx < 0 && e[1] == cmd
+ diff = false
+ ['a', 'r', 'w', 'u'].each{|c|
+ break if (diff = e[0].index(c) ^ opts.index(c))
+ }
+ unless diff
+ #find
+ idx = i
+ next
+ end
+ end
+ e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ }
+ else
+ newopts = []
+ @trace_var.each_with_index{|e, i|
+ if idx < 0 && e[1] == cmd &&
+ e[0].size == opts.size && (e[0] - opts).empty?
+ # find
+ idx = i
+ next
+ end
+ newopts |= e[0]
+ }
+ end
+
if idx >= 0
@trace_var.delete_at(idx)
else
return self
end
- @trace_elem.each{|elem|
+ (@trace_elem ||= {}).each{|elem|
@trace_elem[elem].each{|e|
- # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
+ if USE_OLD_TRACE_OPTION_STYLE
+ e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ else
+ newopts |= e[0]
+ end
}
}
- newopts = newopts.to_s
- newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
- if newopts != @trace_opts
- Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'remove', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
+ if USE_OLD_TRACE_OPTION_STYLE
+ diff = false
+ @trace_opts.each_byte{|c| break if (diff = ! newopts.index(c))}
+ if diff
Tk.tk_call_without_enc('trace', 'vdelete',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ unless @trace_opts.empty?
+ Tk.tk_call_without_enc('trace', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
end
-=end
- @trace_opts.replace(newopts)
- if @trace_opts != ''
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
+ else
+ unless (@trace_opts - newopts).empty?
+ Tk.tk_call_without_enc('trace', 'remove', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ unless @trace_opts.empty?
Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
- Tk.tk_call_without_enc('trace', 'variable',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
end
-=end
end
end
self
end
+ alias trace_delete trace_remove
+ alias trace_vdelete trace_remove
- def trace_vdelete_for_element(elem,opts,cmd)
+ def trace_remove_for_element(elem,opts,cmd)
if @elem
fail(RuntimeError,
"invalid for a TkVariable which denotes an element of Tcl's array")
end
return self unless @trace_elem.kind_of? Hash
return self unless @trace_elem[elem].kind_of? Array
- opts = opts.to_s
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
+
+ opts = _check_trace_opt(opts)
+
idx = -1
- @trace_elem[elem].each_with_index{|e,i|
- if idx < 0 && e[0] == opts && e[1] == cmd
- idx = i
- next
- end
- }
+ if USE_OLD_TRACE_OPTION_STYLE
+ @trace_elem[elem].each_with_index{|e, i|
+ if idx < 0 && e[1] == cmd
+ diff = false
+ ['a', 'r', 'w', 'u'].each{|c|
+ break if (diff = e[0].index(c) ^ opts.index(c))
+ }
+ unless diff
+ #find
+ idx = i
+ next
+ end
+ end
+ }
+ else
+ @trace_elem[elem].each_with_index{|e, i|
+ if idx < 0 && e[1] == cmd &&
+ e[0].size == opts.size && (e[0] - opts).empty?
+ # find
+ idx = i
+ next
+ end
+ }
+ end
+
if idx >= 0
@trace_elem[elem].delete_at(idx)
else
return self
end
- newopts = ''
- @trace_var.each{|e|
- # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
- }
- @trace_elem.each{|elem|
- @trace_elem[elem].each{|e|
- # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
+ if USE_OLD_TRACE_OPTION_STYLE
+ newopts = ''
+ @trace_var.each{|e|
+ e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
}
- }
+ @trace_elem.each{|elem|
+ @trace_elem[elem].each{|e|
+ e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ }
+ }
+ else
+ newopts = []
+ @trace_var.each{|e|
+ newopts |= e[0]
+ }
+ @trace_elem.each{|elem|
+ @trace_elem[elem].each{|e|
+ e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ }
+ }
+ end
- newopts = newopts.to_s
- newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
- if newopts != @trace_opts
- Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'remove', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
+ if USE_OLD_TRACE_OPTION_STYLE
+ diff = false
+ @trace_opts.each_byte{|c| break if (diff = ! newopts.index(c))}
+ if diff
Tk.tk_call_without_enc('trace', 'vdelete',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ unless @trace_opts.empty?
+ Tk.tk_call_without_enc('trace', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
end
-=end
- @trace_opts.replace(newopts)
- if @trace_opts != ''
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
+ else
+ unless (@trace_opts - newopts).empty?
+ Tk.tk_call_without_enc('trace', 'remove', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ unless @trace_opts.empty?
Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
- Tk.tk_call_without_enc('trace', 'variable', @id,
- @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
end
-=end
end
end
self
end
+ alias trace_delete_for_element trace_remove_for_element
+ alias trace_vdelete_for_element trace_remove_for_element
end
class TkVarAccess<TkVariable
@@ -1532,12 +1624,23 @@ class TkVarAccess<TkVariable
return name
end
- if v = TkVar_ID_TBL[name]
- v.value = args[0] unless args.empty?
- return v
- end
+ name = name.to_s
+ v = nil
+ TkVar_ID_TBL.mutex.synchronize{
+ if v = TkVar_ID_TBL[name]
+ v.value = args[0] unless args.empty?
+ return v
+ else
+ (v = self.allocate).instance_eval{
+ @id = name
+ TkVar_ID_TBL[@id] = self
+ @var = @id
+ }
+ end
+ }
- super(name, *args)
+ v.instance_eval{ initialize(name, *args) }
+ v
end
def self.new_hash(name, *args)
@@ -1549,27 +1652,38 @@ class TkVarAccess<TkVariable
return name
end
- if v = TkVar_ID_TBL[name]
- unless v.is_hash?
- fail ArgumentError, "already exist as a scalar variable"
+ name = name.to_s
+ v = nil
+ TkVar_ID_TBL.mutex.synchronize{
+ if v = TkVar_ID_TBL[name]
+ unless v.is_hash?
+ fail ArgumentError, "already exist as a scalar variable"
+ end
+ v.value = args[0] unless args.empty?
+ return v
+ else
+ (v = self.allocate).instance_eval{
+ @id = name
+ TkVar_ID_TBL[@id] = self
+ @var = @id
+ }
end
- v.value = args[0] unless args.empty?
- return v
- end
+ }
INTERP._invoke_without_enc('global', name)
if args.empty? && INTERP._invoke_without_enc('array', 'exist', name) == '0'
- self.new(name, {}) # force creating
+ v.instance_eval{ initialize(name, {}) } # force creating
else
- self.new(name, *args)
+ v.instance_eval{ initialize(name, *args) }
end
+ v
end
def initialize(varname, val=nil)
- @id = varname
- TkVar_ID_TBL[@id] = self
+ # @id = varname
+ # TkVar_ID_TBL[@id] = self
- @var = @id
+ # @var = @id
@elem = nil
@def_default = false
diff --git a/ext/tk/lib/tk/virtevent.rb b/ext/tk/lib/tk/virtevent.rb
index d47e80aecd..ae31ac1f8f 100644
--- a/ext/tk/lib/tk/virtevent.rb
+++ b/ext/tk/lib/tk/virtevent.rb
@@ -9,10 +9,17 @@ class TkVirtualEvent<TkObject
TkCommandNames = ['event'.freeze].freeze
- TkVirtualEventID = ["VirtEvent".freeze, "00000".taint].freeze
+ (TkVirtualEventID = ["VirtEvent".freeze, "00000".taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
TkVirtualEventTBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ TkVirtualEventTBL.clear }
+ TkCore::INTERP.init_ip_env{
+ TkVirtualEventTBL.mutex.synchronize{ TkVirtualEventTBL.clear }
+ }
class PreDefVirtEvent<self
def self.new(event, *sequences)
@@ -21,22 +28,30 @@ class TkVirtualEvent<TkObject
elsif event !~ /^<.*>$/
event = '<' + event + '>'
end
- if TkVirtualEvent::TkVirtualEventTBL.has_key?(event)
- TkVirtualEvent::TkVirtualEventTBL[event]
- else
- super(event, *sequences)
- end
+ TkVirtualEvent::TkVirtualEventTBL.mutex.synchronize{
+ if TkVirtualEvent::TkVirtualEventTBL.has_key?(event)
+ TkVirtualEvent::TkVirtualEventTBL[event]
+ else
+ # super(event, *sequences)
+ (obj = self.allocate).instance_eval{
+ initialize(event, *sequences)
+ TkVirtualEvent::TkVirtualEventTBL[@id] = self
+ }
+ end
+ }
end
def initialize(event, *sequences)
@path = @id = event
- TkVirtualEvent::TkVirtualEventTBL[@id] = self
- add(*sequences)
+ _add_sequences(sequences)
end
end
def TkVirtualEvent.getobj(event)
- obj = TkVirtualEventTBL[event]
+ obj = nil
+ TkVirtualEventTBL.mutex.synchronize{
+ obj = TkVirtualEventTBL[event]
+ }
if obj
obj
else
@@ -55,19 +70,31 @@ class TkVirtualEvent<TkObject
end
def initialize(*sequences)
- # @path = @id = '<' + TkVirtualEventID.join('') + '>'
- @path = @id = '<' + TkVirtualEventID.join(TkCore::INTERP._ip_id_) + '>'
- TkVirtualEventID[1].succ!
- add(*sequences)
+ TkVirtualEventID.mutex.synchronize{
+ # @path = @id = '<' + TkVirtualEventID.join('') + '>'
+ @path = @id = '<' + TkVirtualEventID.join(TkCore::INTERP._ip_id_) + '>'
+ TkVirtualEventID[1].succ!
+ }
+ _add_sequences(sequences)
end
- def add(*sequences)
- if sequences != []
+ def _add_sequences(seq_ary)
+ unless seq_ary.empty?
tk_call_without_enc('event', 'add', "<#{@id}>",
- *(sequences.collect{|seq|
+ *(seq_ary.collect{|seq|
"<#{tk_event_sequence(seq)}>"
}) )
- TkVirtualEventTBL[@id] = self
+ end
+ self
+ end
+ private :_add_sequences
+
+ def add(*sequences)
+ if sequences != []
+ _add_sequences(sequences)
+ TkVirtualEventTBL.mutex.synchronize{
+ TkVirtualEventTBL[@id] = self
+ }
end
self
end
@@ -75,20 +102,26 @@ class TkVirtualEvent<TkObject
def delete(*sequences)
if sequences == []
tk_call_without_enc('event', 'delete', "<#{@id}>")
- TkVirtualEventTBL.delete(@id)
+ TkVirtualEventTBL.mutex.synchronize{
+ TkVirtualEventTBL.delete(@id)
+ }
else
tk_call_without_enc('event', 'delete', "<#{@id}>",
*(sequences.collect{|seq|
"<#{tk_event_sequence(seq)}>"
}) )
- TkVirtualEventTBL.delete(@id) if info == []
+ if tk_call_without_enc('event','info',"<#{@id}>").empty?
+ TkVirtualEventTBL.mutex.synchronize{
+ TkVirtualEventTBL.delete(@id)
+ }
+ end
end
self
end
def info
tk_call_without_enc('event','info',"<#{@id}>").split(/\s+/).collect!{|seq|
- l = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
+ lst = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
case (subseq)
when /^<<[^<>]+>>$/
TkVirtualEvent.getobj(subseq[1..-2])
@@ -98,7 +131,7 @@ class TkVirtualEvent<TkObject
subseq.split('')
end
}.flatten
- (l.size == 1) ? l[0] : l
+ (lst.size == 1) ? lst[0] : lst
}
end
end
diff --git a/ext/tk/lib/tk/winpkg.rb b/ext/tk/lib/tk/winpkg.rb
index 737fb959b5..89fb391c77 100644
--- a/ext/tk/lib/tk/winpkg.rb
+++ b/ext/tk/lib/tk/winpkg.rb
@@ -7,9 +7,14 @@
#
require 'tk'
-module TkWinDDE
+module Tk::WinDDE
+end
+#TkWinDDE = Tk::WinDDE
+Tk.__set_toplevel_aliases__(:Tk, Tk::WinDDE, :TkWinDDE)
+
+module Tk::WinDDE
extend Tk
- extend TkWinDDE
+ extend Tk::WinDDE
TkCommandNames = ['dde'.freeze].freeze
@@ -85,9 +90,14 @@ module TkWinDDE
:poke, :request, :services, :eval
end
-module TkWinRegistry
+module Tk::WinRegistry
+end
+#TkWinRegistry = Tk::WinRegistry
+Tk.__set_toplevel_aliases__(:Tk, Tk::WinRegistry, :TkWinRegistry)
+
+module Tk::WinRegistry
extend Tk
- extend TkWinRegistry
+ extend Tk::WinRegistry
TkCommandNames = ['registry'.freeze].freeze
diff --git a/ext/tk/lib/tk/wm.rb b/ext/tk/lib/tk/wm.rb
index 1f432a3848..0394296189 100644
--- a/ext/tk/lib/tk/wm.rb
+++ b/ext/tk/lib/tk/wm.rb
@@ -5,273 +5,407 @@ require 'tk'
module Tk
module Wm
- include TkComm
+ #include TkComm
+ extend TkCore
TkCommandNames = ['wm'.freeze].freeze
TOPLEVEL_METHODCALL_OPTKEYS = {}
- def aspect(*args)
+ def Wm.aspect(win, *args)
if args.length == 0
- list(tk_call_without_enc('wm', 'aspect', path))
+ list(tk_call_without_enc('wm', 'aspect', win.epath))
else
args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call('wm', 'aspect', path, *args)
- self
+ tk_call('wm', 'aspect', win.epath, *args)
+ win
end
end
+ def aspect(*args)
+ Wm.aspect(self, *args)
+ end
+ alias wm_aspect aspect
TOPLEVEL_METHODCALL_OPTKEYS['aspect'] = 'aspect'
- def attributes(slot=nil,value=None)
+ def Wm.attributes(win, slot=nil,value=TkComm::None)
if slot == nil
- lst = tk_split_list(tk_call('wm', 'attributes', path))
+ lst = tk_split_list(tk_call('wm', 'attributes', win.epath))
info = {}
while key = lst.shift
info[key[1..-1]] = lst.shift
end
info
elsif slot.kind_of? Hash
- tk_call('wm', 'attributes', path, *hash_kv(slot))
- self
- elsif value == None
- tk_call('wm', 'attributes', path, "-#{slot}")
+ tk_call('wm', 'attributes', win.epath, *hash_kv(slot))
+ win
+ elsif value == TkComm::None
+ tk_call('wm', 'attributes', win.epath, "-#{slot}")
else
- tk_call('wm', 'attributes', path, "-#{slot}", value)
- self
+ tk_call('wm', 'attributes', win.epath, "-#{slot}", value)
+ win
end
end
+ def attributes(slot=nil,value=TkComm::None)
+ Wm.attributes(self, slot, value)
+ end
+ alias wm_attributes attributes
TOPLEVEL_METHODCALL_OPTKEYS['attributes'] = 'attributes'
- def client(name=None)
- if name == None
- tk_call('wm', 'client', path)
+ def Wm.client(win, name=TkComm::None)
+ if name == TkComm::None
+ tk_call('wm', 'client', win.epath)
else
name = '' if name == nil
- tk_call('wm', 'client', path, name)
- self
+ tk_call('wm', 'client', win.epath, name)
+ win
end
end
+ def client(name=TkComm::None)
+ Wm.client(self, name)
+ end
+ alias wm_client client
TOPLEVEL_METHODCALL_OPTKEYS['client'] = 'client'
- def colormapwindows(*args)
+ def Wm.colormapwindows(win, *args)
if args.size == 0
- list(tk_call_without_enc('wm', 'colormapwindows', path))
+ list(tk_call_without_enc('wm', 'colormapwindows', win.epath))
else
args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'colormapwindows', path, *args)
- self
+ tk_call_without_enc('wm', 'colormapwindows', win.epath, *args)
+ win
end
end
+ def colormapwindows(*args)
+ Wm.colormapwindows(self, *args)
+ end
+ alias wm_colormapwindows colormapwindows
TOPLEVEL_METHODCALL_OPTKEYS['colormapwindows'] = 'colormapwindows'
- def wm_command(value=nil)
+ def Wm.command(win, value=nil)
if value
- tk_call('wm', 'command', path, value)
- self
+ tk_call('wm', 'command', epath, value)
+ win
else
- #procedure(tk_call('wm', 'command', path))
- tk_call('wm', 'command', path)
+ #procedure(tk_call('wm', 'command', epath))
+ tk_call('wm', 'command', epath)
end
end
+ def wm_command(value=nil)
+ Wm.command(self, value)
+ end
TOPLEVEL_METHODCALL_OPTKEYS['wm_command'] = 'wm_command'
- def deiconify(ex = true)
+ def Wm.deiconify(win, ex = true)
if ex
- tk_call_without_enc('wm', 'deiconify', path)
+ tk_call_without_enc('wm', 'deiconify', win.epath)
else
- self.iconify
+ Wm.iconify(win)
end
- self
+ win
end
+ def deiconify(ex = true)
+ Wm.deiconify(self, ex)
+ end
+ alias wm_deiconify deiconify
- def focusmodel(mode = nil)
+ def Wm.focusmodel(win, mode = nil)
if mode
- tk_call_without_enc('wm', 'focusmodel', path, mode)
- self
+ tk_call_without_enc('wm', 'focusmodel', win.epath, mode)
+ win
else
- tk_call_without_enc('wm', 'focusmodel', path)
+ tk_call_without_enc('wm', 'focusmodel', win.epath)
end
end
+ def focusmodel(mode = nil)
+ Wm.focusmodel(self, mode)
+ end
+ alias wm_focusmodel focusmodel
TOPLEVEL_METHODCALL_OPTKEYS['focusmodel'] = 'focusmodel'
+ def Wm.forget(win)
+ # Tcl/Tk 8.5+
+ # work with dockable frames
+ tk_call_without_enc('wm', 'forget', win.epath)
+ win
+ end
+ def wm_forget
+ Wm.forget(self)
+ end
+
+ def Wm.frame(win)
+ tk_call_without_enc('wm', 'frame', win.epath)
+ end
def frame
- tk_call_without_enc('wm', 'frame', path)
+ Wm.frame(self)
end
+ alias wm_frame frame
- def geometry(geom=nil)
+ def Wm.geometry(win, geom=nil)
if geom
- tk_call_without_enc('wm', 'geometry', path, geom)
- self
+ tk_call_without_enc('wm', 'geometry', win.epath, geom)
+ win
else
- tk_call_without_enc('wm', 'geometry', path)
+ tk_call_without_enc('wm', 'geometry', win.epath)
end
end
+ def geometry(geom=nil)
+ Wm.geometry(self, geom)
+ end
+ alias wm_geometry geometry
TOPLEVEL_METHODCALL_OPTKEYS['geometry'] = 'geometry'
- def wm_grid(*args)
+ def Wm.grid(win, *args)
if args.size == 0
- list(tk_call_without_enc('wm', 'grid', path))
+ list(tk_call_without_enc('wm', 'grid', win.epath))
else
args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'grid', path, *args)
- self
+ tk_call_without_enc('wm', 'grid', win.epath, *args)
+ win
end
end
+ def wm_grid(*args)
+ Wm.grid(self, *args)
+ end
TOPLEVEL_METHODCALL_OPTKEYS['wm_grid'] = 'wm_grid'
- def group(leader = nil)
+ def Wm.group(win, leader = nil)
if leader
- tk_call('wm', 'group', path, leader)
- self
+ tk_call('wm', 'group', win.epath, leader)
+ win
else
- window(tk_call('wm', 'group', path))
+ window(tk_call('wm', 'group', win.epath))
end
end
+ def group(leader = nil)
+ Wm.group(self, leader)
+ end
+ alias wm_group group
TOPLEVEL_METHODCALL_OPTKEYS['group'] = 'group'
- def iconbitmap(bmp=nil)
+ def Wm.iconbitmap(win, bmp=nil)
if bmp
- tk_call_without_enc('wm', 'iconbitmap', path, bmp)
- self
+ tk_call_without_enc('wm', 'iconbitmap', win.epath, bmp)
+ win
else
- image_obj(tk_call_without_enc('wm', 'iconbitmap', path))
+ image_obj(tk_call_without_enc('wm', 'iconbitmap', win.epath))
end
end
+ def iconbitmap(bmp=nil)
+ Wm.iconbitmap(self, bmp)
+ end
+ alias wm_iconbitmap iconbitmap
TOPLEVEL_METHODCALL_OPTKEYS['iconbitmap'] = 'iconbitmap'
- def iconphoto(*imgs)
+ def Wm.iconphoto(win, *imgs)
if imgs.empty?
- @wm_iconphoto = nil unless defined? @wm_iconphoto
- return @wm_iconphoto
+ win.instance_eval{
+ @wm_iconphoto = nil unless defined? @wm_iconphoto
+ return @wm_iconphoto
+ }
end
imgs = imgs[0] if imgs.length == 1 && imgs[0].kind_of?(Array)
- tk_call_without_enc('wm', 'iconphoto', path, *imgs)
- @wm_iconphoto = imgs
- self
+ tk_call_without_enc('wm', 'iconphoto', win.epath, *imgs)
+ win.instance_eval{ @wm_iconphoto = imgs }
+ win
+ end
+ def iconphoto(*imgs)
+ Wm.iconphoto(self, *imgs)
end
+ alias wm_iconphoto iconphoto
TOPLEVEL_METHODCALL_OPTKEYS['iconphoto'] = 'iconphoto'
- def iconphoto_default(*imgs)
+ def Wm.iconphoto_default(win, *imgs)
imgs = imgs[0] if imgs.length == 1 && imgs[0].kind_of?(Array)
- tk_call_without_enc('wm', 'iconphoto', path, '-default', *imgs)
- self
+ tk_call_without_enc('wm', 'iconphoto', win.epath, '-default', *imgs)
+ win
+ end
+ def iconphoto_default(*imgs)
+ Wm.iconphoto_default(self, *imgs)
end
+ alias wm_iconphoto_default iconphoto_default
- def iconify(ex = true)
+ def Wm.iconify(win, ex = true)
if ex
- tk_call_without_enc('wm', 'iconify', path)
+ tk_call_without_enc('wm', 'iconify', win.epath)
else
- self.deiconify
+ Wm.deiconify(win)
end
- self
+ win
+ end
+ def iconify(ex = true)
+ Wm.iconify(self, ex)
end
+ alias wm_iconify iconify
- def iconmask(bmp=nil)
+ def Wm.iconmask(win, bmp=nil)
if bmp
- tk_call_without_enc('wm', 'iconmask', path, bmp)
- self
+ tk_call_without_enc('wm', 'iconmask', win.epath, bmp)
+ win
else
- image_obj(tk_call_without_enc('wm', 'iconmask', path))
+ image_obj(tk_call_without_enc('wm', 'iconmask', win.epath))
end
end
+ def iconmask(bmp=nil)
+ Wm.iconmask(self, bmp)
+ end
+ alias wm_iconmask iconmask
TOPLEVEL_METHODCALL_OPTKEYS['iconmask'] = 'iconmask'
- def iconname(name=nil)
+ def Wm.iconname(win, name=nil)
if name
- tk_call('wm', 'iconname', path, name)
- self
+ tk_call('wm', 'iconname', win.epath, name)
+ win
else
- tk_call('wm', 'iconname', path)
+ tk_call('wm', 'iconname', win.epath)
end
end
+ def iconname(name=nil)
+ Wm.iconname(self, name)
+ end
+ alias wm_iconname iconname
TOPLEVEL_METHODCALL_OPTKEYS['iconname'] = 'iconname'
- def iconposition(*args)
+ def Wm.iconposition(win, *args)
if args.size == 0
- list(tk_call_without_enc('wm', 'iconposition', path))
+ list(tk_call_without_enc('wm', 'iconposition', win.epath))
else
args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'iconposition', path, *args)
- self
+ tk_call_without_enc('wm', 'iconposition', win.epath, *args)
+ win
end
end
+ def iconposition(*args)
+ Wm.iconposition(self, *args)
+ end
+ alias wm_iconposition iconposition
TOPLEVEL_METHODCALL_OPTKEYS['iconposition'] = 'iconposition'
- def iconwindow(win = nil)
- if win
- tk_call_without_enc('wm', 'iconwindow', path, win)
- self
+ def Wm.iconwindow(win, iconwin = nil)
+ if iconwin
+ tk_call_without_enc('wm', 'iconwindow', win.epath, iconwin)
+ win
else
- w = tk_call_without_enc('wm', 'iconwindow', path)
+ w = tk_call_without_enc('wm', 'iconwindow', win.epath)
(w == '')? nil: window(w)
end
end
+ def iconwindow(iconwin = nil)
+ Wm.iconwindow(self, iconwin)
+ end
+ alias wm_iconwindow iconwindow
TOPLEVEL_METHODCALL_OPTKEYS['iconwindow'] = 'iconwindow'
- def maxsize(*args)
+ def Wm.manage(win)
+ # Tcl/Tk 8.5+ feature
+ tk_call_without_enc('wm', 'manage', win.epath)
+ win
+ end
+ def wm_manage
+ Wm.manage(self)
+ end
+=begin
+ def Wm.manage(win, use_id = nil)
+ # Tcl/Tk 8.5+ feature
+ # --------------------------------------------------------------
+ # In the future release, I want to support to embed the 'win'
+ # into the container which has window-id 'use-id'.
+ # It may give users frexibility on controlling their GUI.
+ # However, it may be difficult for current Tcl/Tk (Tcl/Tk8.5.1),
+ # because it seems to require to modify Tcl/Tk's source code.
+ # --------------------------------------------------------------
+ if use_id
+ tk_call_without_enc('wm', 'manage', win.epath, '-use', use_id)
+ else
+ tk_call_without_enc('wm', 'manage', win.epath)
+ end
+ win
+ end
+=end
+
+ def Wm.maxsize(win, *args)
if args.size == 0
- list(tk_call_without_enc('wm', 'maxsize', path))
+ list(tk_call_without_enc('wm', 'maxsize', win.epath))
else
args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'maxsize', path, *args)
- self
+ tk_call_without_enc('wm', 'maxsize', win.epath, *args)
+ win
end
end
+ def maxsize(*args)
+ Wm.maxsize(self, *args)
+ end
+ alias wm_maxsize maxsize
TOPLEVEL_METHODCALL_OPTKEYS['maxsize'] = 'maxsize'
- def minsize(*args)
+ def Wm.minsize(win, *args)
if args.size == 0
- list(tk_call_without_enc('wm', 'minsize', path))
+ list(tk_call_without_enc('wm', 'minsize', win.epath))
else
args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'minsize', path, *args)
- self
+ tk_call_without_enc('wm', 'minsize', win.path, *args)
+ win
end
end
+ def minsize(*args)
+ Wm.minsize(self, *args)
+ end
+ alias wm_minsize minsize
TOPLEVEL_METHODCALL_OPTKEYS['minsize'] = 'minsize'
- def overrideredirect(mode=None)
- if mode == None
- bool(tk_call_without_enc('wm', 'overrideredirect', path))
+ def Wm.overrideredirect(win, mode=TkComm::None)
+ if mode == TkComm::None
+ bool(tk_call_without_enc('wm', 'overrideredirect', win.epath))
else
- tk_call_without_enc('wm', 'overrideredirect', path, mode)
- self
+ tk_call_without_enc('wm', 'overrideredirect', win.epath, mode)
+ win
end
end
+ def overrideredirect(mode=TkComm::None)
+ Wm.overrideredirect(self, mode)
+ end
+ alias wm_overrideredirect overrideredirect
TOPLEVEL_METHODCALL_OPTKEYS['overrideredirect'] = 'overrideredirect'
- def positionfrom(who=None)
- if who == None
- r = tk_call_without_enc('wm', 'positionfrom', path)
+ def Wm.positionfrom(win, who=TkComm::None)
+ if who == TkComm::None
+ r = tk_call_without_enc('wm', 'positionfrom', win.epath)
(r == "")? nil: r
else
- tk_call_without_enc('wm', 'positionfrom', path, who)
- self
+ tk_call_without_enc('wm', 'positionfrom', win.epath, who)
+ win
end
end
+ def positionfrom(who=TkComm::None)
+ Wm.positionfrom(self, who)
+ end
+ alias wm_positionfrom positionfrom
TOPLEVEL_METHODCALL_OPTKEYS['positionfrom'] = 'positionfrom'
- def protocol(name=nil, cmd=nil, &b)
+ def Wm.protocol(win, name=nil, cmd=nil, &b)
if cmd
- tk_call_without_enc('wm', 'protocol', path, name, cmd)
- self
+ tk_call_without_enc('wm', 'protocol', win.epath, name, cmd)
+ win
elsif b
- tk_call_without_enc('wm', 'protocol', path, name, proc(&b))
- self
+ tk_call_without_enc('wm', 'protocol', win.epath, name, proc(&b))
+ win
elsif name
- result = tk_call_without_enc('wm', 'protocol', path, name)
+ result = tk_call_without_enc('wm', 'protocol', win.epath, name)
(result == "")? nil : tk_tcl2ruby(result)
else
- tk_split_simplelist(tk_call_without_enc('wm', 'protocol', path))
+ tk_split_simplelist(tk_call_without_enc('wm', 'protocol', win.epath))
end
end
+ def protocol(name=nil, cmd=nil, &b)
+ Wm.protocol(self, name, cmd, &b)
+ end
+ alias wm_protocol protocol
- def protocols(kv=nil)
+ def Wm.protocols(win, kv=nil)
unless kv
ret = {}
- self.protocol.each{|name|
- ret[name] = self.protocol(name)
+ Wm.protocol(win).each{|name|
+ ret[name] = Wm.protocol(win, name)
}
return ret
end
@@ -279,82 +413,140 @@ module Tk
unless kv.kind_of?(Hash)
fail ArgumentError, 'expect a hash of protocol=>command'
end
- kv.each{|k, v| self.protocol(k, v)}
- self
+ kv.each{|k, v| Wm.protocol(win, k, v)}
+ win
end
+ def protocols(kv=nil)
+ Wm.protocols(self, kv)
+ end
+ alias wm_protocols protocols
TOPLEVEL_METHODCALL_OPTKEYS['protocols'] = 'protocols'
- def resizable(*args)
+ def Wm.resizable(win, *args)
if args.length == 0
- list(tk_call_without_enc('wm', 'resizable', path)).collect{|e| bool(e)}
+ list(tk_call_without_enc('wm', 'resizable', win.epath)).map!{|e| bool(e)}
else
args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'resizable', path, *args)
- self
+ tk_call_without_enc('wm', 'resizable', win.epath, *args)
+ win
end
end
+ def resizable(*args)
+ Wm.resizable(self, *args)
+ end
+ alias wm_resizable resizable
TOPLEVEL_METHODCALL_OPTKEYS['resizable'] = 'resizable'
- def sizefrom(who=None)
- if who == None
- r = tk_call_without_enc('wm', 'sizefrom', path)
+ def Wm.sizefrom(win, who=TkComm::None)
+ if who == TkComm::None
+ r = tk_call_without_enc('wm', 'sizefrom', win.epath)
(r == "")? nil: r
else
- tk_call_without_enc('wm', 'sizefrom', path, who)
- self
+ tk_call_without_enc('wm', 'sizefrom', win.epath, who)
+ win
end
end
+ def sizefrom(who=TkComm::None)
+ Wm.sizefrom(self, who)
+ end
+ alias wm_sizefrom sizefrom
TOPLEVEL_METHODCALL_OPTKEYS['sizefrom'] = 'sizefrom'
+ def Wm.stackorder(win)
+ list(tk_call('wm', 'stackorder', win.epath))
+ end
def stackorder
- list(tk_call('wm', 'stackorder', path))
+ Wm.stackorder(self)
end
+ alias wm_stackorder stackorder
- def stackorder_isabove(win)
- bool(tk_call('wm', 'stackorder', path, 'isabove', win))
+ def Wm.stackorder_isabove(win, target)
+ bool(tk_call('wm', 'stackorder', win.epath, 'isabove', target))
+ end
+ def Wm.stackorder_is_above(win, target)
+ Wm.stackorder_isabove(win, target)
+ end
+ def stackorder_isabove(target)
+ Wm.stackorder_isabove(self, target)
end
+ alias stackorder_is_above stackorder_isabove
+ alias wm_stackorder_isabove stackorder_isabove
+ alias wm_stackorder_is_above stackorder_isabove
- def stackorder_isbelow(win)
- bool(tk_call('wm', 'stackorder', path, 'isbelow', win))
+ def Wm.stackorder_isbelow(win, target)
+ bool(tk_call('wm', 'stackorder', win.epath, 'isbelow', target))
end
+ def Wm.stackorder_is_below(win, target)
+ Wm.stackorder_isbelow(win, target)
+ end
+ def stackorder_isbelow(target)
+ Wm.stackorder_isbelow(self, target)
+ end
+ alias stackorder_is_below stackorder_isbelow
+ alias wm_stackorder_isbelow stackorder_isbelow
+ alias wm_stackorder_is_below stackorder_isbelow
- def state(st=nil)
+ def Wm.state(win, st=nil)
if st
- tk_call_without_enc('wm', 'state', path, st)
- self
+ tk_call_without_enc('wm', 'state', win.epath, st)
+ win
else
- tk_call_without_enc('wm', 'state', path)
+ tk_call_without_enc('wm', 'state', win.epath)
end
end
+ def state(st=nil)
+ Wm.state(self, st)
+ end
+ alias wm_state state
TOPLEVEL_METHODCALL_OPTKEYS['state'] = 'state'
- def title(str=nil)
+ def Wm.title(win, str=nil)
if str
- tk_call('wm', 'title', path, str)
- self
+ tk_call('wm', 'title', win.epath, str)
+ win
else
- tk_call('wm', 'title', path)
+ tk_call('wm', 'title', win.epath)
end
end
+ def title(str=nil)
+ Wm.title(self, str)
+ end
+ alias wm_title title
TOPLEVEL_METHODCALL_OPTKEYS['title'] = 'title'
- def transient(master=nil)
+ def Wm.transient(win, master=nil)
if master
- tk_call_without_enc('wm', 'transient', path, master)
- self
+ tk_call_without_enc('wm', 'transient', win.epath, master)
+ win
else
- window(tk_call_without_enc('wm', 'transient', path))
+ window(tk_call_without_enc('wm', 'transient', win.epath))
end
end
+ def transient(master=nil)
+ Wm.transient(self, master)
+ end
+ alias wm_transient transient
TOPLEVEL_METHODCALL_OPTKEYS['transient'] = 'transient'
- def withdraw(ex = true)
+ def Wm.withdraw(win, ex = true)
if ex
- tk_call_without_enc('wm', 'withdraw', path)
+ tk_call_without_enc('wm', 'withdraw', win.epath)
else
- self.deiconify
+ Wm.deiconify(win)
end
- self
+ win
end
+ def withdraw(ex = true)
+ Wm.withdraw(self, ex)
+ end
+ alias wm_withdraw withdraw
+ end
+
+ module Wm_for_General
+ Wm.instance_methods.each{|m|
+ if (m = m.to_s) =~ /^wm_(.*)$/
+ eval "def #{m}(*args, &b); Tk::Wm.#{$1}(self, *args, &b); end"
+ end
+ }
end
end
diff --git a/ext/tk/lib/tkclass.rb b/ext/tk/lib/tkclass.rb
index 355b1a1b1d..87f5acc453 100644
--- a/ext/tk/lib/tkclass.rb
+++ b/ext/tk/lib/tkclass.rb
@@ -3,7 +3,7 @@
# Date: 2000/11/27 09:23:36
# by Yukihiro Matsumoto <matz@caelum.co.jp>
#
-# $Id: tkclass.rb,v 1.6.2.1 2004/10/11 04:51:06 nagai Exp $
+# $Id$
require "tk"
diff --git a/ext/tk/lib/tkextlib/SUPPORT_STATUS b/ext/tk/lib/tkextlib/SUPPORT_STATUS
index 8d7b6fc44a..cfbe274c86 100644
--- a/ext/tk/lib/tkextlib/SUPPORT_STATUS
+++ b/ext/tk/lib/tkextlib/SUPPORT_STATUS
@@ -1,7 +1,7 @@
[ current support status of Tcl/Tk extensions ]
- *******<<< RELEASE_DATE of the libraries : 2005/12/11 >>>*******
+ *** RELEASE_DATE of the libraries => see 'tkextlib/version.rb' ***
The following list shows *CURRENT* status when this file was modifyed
at last. If you want to add other Tcl/Tk extensions to the planed list
@@ -56,23 +56,23 @@ script may give you some hints about that.
===< support with some examples (may be beta quality) >=======================
Tcllib 1.8
-Tklib 0.4.1 http://sf.net/projects/tcllib ==> tcllib
+Tklib 0.4.1 http://sourceforge.net/projects/tcllib ==> tcllib
-IWidgets 4.0.2 http://sf.net/projects/incrTcl ==> iwidgets
+IWidgets 4.0.2 http://sourceforge.net/projects/incrtcl ==> iwidgets
-BWidgets 1.7 http://sf.net/projects/tcllib ==> bwidget
+BWidgets 1.7 http://sourceforge.net/projects/tcllib ==> bwidget
-TkTable 2.9 http://sf.net/projects/tktable ==> tktable
+TkTable 2.9 http://sourceforge.net/projects/tktable ==> tktable
* see also <http://www.korus.hu/~fery/ruby/tktable.rb>
written by Ferenc Engard (ferenc@engard.hu)
-vu 2.3.0 http://tktable.sourceforge.net ==> vu
+vu 2.3.0 http://sourceforge.net/projects/tktable ==> vu
-TkHTML 2.0 http://www.hwaci.com/sw/tkhtml/index.html ==> tkHTML
+TkHTML 2.0 http://www.hwaci.com/sw/tkhtml/ ==> tkHTML
ICONS 1.0 http://www.satisoft.com/tcltk/icons/ ==> ICONS
-TkImg 1.3 http://sf.net/projects/tkimg ==> tkimg
+TkImg 1.3 http://sourceforge.net/projects/tkimg ==> tkimg
BLT 2.4z http://sourceforge.net/projects/blt
@@ -81,20 +81,20 @@ BLT 2.4z http://sourceforge.net/projects/blt
==> blt
TkTreeCtrl CVS/Hd(2005-12-02)
- http://tktreectrl.sourceforge.net/ ==> treectrl
+ http://sourceforge.net/projects/tktreectrl ==> treectrl
-Tile CVS/Hd(2005-12-07)
- http://tktable.sourceforge.net/tile/ ==> tile
+Tile 0.8.0/8.5.1
+ http://sourceforge.net/projects/tktable ==> tile
===< support (may be alpha or beta quality) >=================================
IncrTcl CVS/Hd(2005-02-14)
- http://sf.net/projects/incrTcl ==> itcl, itk
+ http://sourceforge.net/projects/incrtcl ==> itcl, itk
TclX CVS/Hd(2005-02-07)
- http://sf.net/projects/tclx
+ http://sourceforge.net/projects/tclx
==> tclx (partial support; infox command and
XPG/3 message catalogs only)
@@ -105,7 +105,7 @@ Trofs 0.4.3 http://math.nist.gov/~DPorter/tcltk/trofs/
===< possibly available (not tested; alpha quality) >=========================
winico 0.6
- http://tktable.sourceforge.net
+ http://sourceforge.net/projects/tktable
==> winico (win32 only)
TkTrans latest(2004-10-11)
@@ -160,17 +160,17 @@ QuickTimeTcl *** http://hem.fyristorg.com/matben/qt/
===< may not support (already exist, out of Ruby/Tk scope, and so on) >=======
-TkCon *** http://sf.net/projects/tkcon
+TkCon *** http://sourceforge.net/projects/tkcon
-Expect *** http://sf.net/projects/expect
+Expect *** http://sourceforge.net/projects/expect
-TclXML *** http://sf.net/projects/tclxml
+TclXML *** http://sourceforge.net/projects/tclxml
-TclXSLT *** http://sf.net/projects/tclxml
+TclXSLT *** http://sourceforge.net/projects/tclxml
-TclDOM *** http://sf.net/projects/tclxml
+TclDOM *** http://sourceforge.net/projects/tclxml
-TclSOAP *** http://sf.net/projects/tclsoap
+TclSOAP *** http://sourceforge.net/projects/tclsoap
Snack *** http://www.speech.kth.se/~kare/snack2.2.tar.gz
* use Snack for Ruby
@@ -182,7 +182,7 @@ tDOM *** http://www.tdom.org
Mk4tcl *** http://www.equi4.com/metakit/tcl.html
-Memchan *** http://memchan.sourceforge.net/
+Memchan *** http://sourceforge.net/projects/memchan
XOTcl *** http://www.xotcl.org/
diff --git a/ext/tk/lib/tkextlib/blt.rb b/ext/tk/lib/tkextlib/blt.rb
index 8ac8605513..115eb927ba 100644
--- a/ext/tk/lib/tkextlib/blt.rb
+++ b/ext/tk/lib/tkextlib/blt.rb
@@ -68,7 +68,7 @@ module Tk
params.concat(hash_kv(args.shift, true)) if args[0].kind_of?(Hash)
- params << '--'
+ params << '--' if args[0] =~ /^\s*-[^-]/
params.concat(args)
tk_call('::blt::bgexec', *params)
@@ -85,7 +85,7 @@ module Tk
params.concat(hash_kv(args.shift, true)) if args[0].kind_of?(Hash)
- params << '--'
+ params << '--' if args[0] =~ /^\s*-[^-]/
params.concat(args)
params << '&'
diff --git a/ext/tk/lib/tkextlib/blt/bitmap.rb b/ext/tk/lib/tkextlib/blt/bitmap.rb
index 31cf8d4229..23c6d2d064 100644
--- a/ext/tk/lib/tkextlib/blt/bitmap.rb
+++ b/ext/tk/lib/tkextlib/blt/bitmap.rb
@@ -13,7 +13,16 @@ module Tk::BLT
TkCommandNames = ['::blt::bitmap'.freeze].freeze
BITMAP_ID_TBL = TkCore::INTERP.create_table
- BITMAP_ID = ['blt_bitmap_id'.freeze, '00000'.taint].freeze
+
+ (BITMAP_ID = ['blt_bitmap_id'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ BITMAP_ID_TBL.mutex.synchronize{ BITMAP_ID_TBL.clear }
+ }
def self.data(name)
dat = tk_simple_list(tk_call('::blt::bitmap', 'data', name))
@@ -64,9 +73,13 @@ module Tk::BLT
if name
@id = name
else
- @id = BITMAP_ID.join(TkCore::INTERP._ip_id_)
- BITMAP_ID[1].succ!
- BITMAP_ID_TBL[@id] = self
+ BITMAP_ID.mutex.synchronize{
+ @id = BITMAP_ID.join(TkCore::INTERP._ip_id_)
+ BITMAP_ID[1].succ!
+ }
+ BITMAP_ID_TBL.mutex.synchronize{
+ BITMAP_ID_TBL[@id] = self
+ }
end
@path = @id
diff --git a/ext/tk/lib/tkextlib/blt/busy.rb b/ext/tk/lib/tkextlib/blt/busy.rb
index 4726e466f4..2f807fcd9c 100644
--- a/ext/tk/lib/tkextlib/blt/busy.rb
+++ b/ext/tk/lib/tkextlib/blt/busy.rb
@@ -19,7 +19,7 @@ module Tk::BLT
class Shield < TkWindow
def self.shield_path(win)
win = window(win) unless win.kind_of?(TkWindow)
- if win.kind_of?(TkToplevel)
+ if win.kind_of?(Tk::Toplevel)
win.path + '._Busy'
else
win.path + '_Busy'
diff --git a/ext/tk/lib/tkextlib/blt/component.rb b/ext/tk/lib/tkextlib/blt/component.rb
index ad78a5430b..b2005b2f2b 100644
--- a/ext/tk/lib/tkextlib/blt/component.rb
+++ b/ext/tk/lib/tkextlib/blt/component.rb
@@ -85,6 +85,9 @@ module Tk::BLT
def axis_cget(id, option)
ret = itemcget(['axis', tagid(id)], option)
end
+ def axis_cget_strict(id, option)
+ ret = itemcget_strict(['axis', tagid(id)], option)
+ end
def axis_configure(*args)
slot = args.pop
if slot.kind_of?(Hash)
@@ -118,6 +121,9 @@ module Tk::BLT
def crosshairs_cget(option)
itemcget('crosshairs', option)
end
+ def crosshairs_cget_strict(option)
+ itemcget_strict('crosshairs', option)
+ end
def crosshairs_configure(slot, value=None)
itemconfigure('crosshairs', slot, value)
end
@@ -131,6 +137,9 @@ module Tk::BLT
def element_cget(id, option)
itemcget(['element', tagid(id)], option)
end
+ def element_cget_strict(id, option)
+ itemcget_strict(['element', tagid(id)], option)
+ end
def element_configure(*args)
slot = args.pop
if slot.kind_of?(Hash)
@@ -152,6 +161,9 @@ module Tk::BLT
def bar_cget(id, option)
itemcget(['bar', tagid(id)], option)
end
+ def bar_cget_strict(id, option)
+ itemcget_strict(['bar', tagid(id)], option)
+ end
def bar_configure(*args)
slot = args.pop
if slot.kind_of?(Hash)
@@ -173,6 +185,9 @@ module Tk::BLT
def line_cget(id, option)
itemcget(['line', tagid(id)], option)
end
+ def line_cget_strict(id, option)
+ itemcget_strict(['line', tagid(id)], option)
+ end
def line_configure(*args)
slot = args.pop
if slot.kind_of?(Hash)
@@ -194,6 +209,9 @@ module Tk::BLT
def gridline_cget(option)
itemcget('grid', option)
end
+ def gridline_cget_strict(option)
+ itemcget_strict('grid', option)
+ end
def gridline_configure(slot, value=None)
itemconfigure('grid', slot, value)
end
@@ -207,6 +225,9 @@ module Tk::BLT
def legend_cget(option)
itemcget('legend', option)
end
+ def legend_cget_strict(option)
+ itemcget_strict('legend', option)
+ end
def legend_configure(slot, value=None)
itemconfigure('legend', slot, value)
end
@@ -220,6 +241,9 @@ module Tk::BLT
def pen_cget(id, option)
itemcget(['pen', tagid(id)], option)
end
+ def pen_cget_strict(id, option)
+ itemcget_strict(['pen', tagid(id)], option)
+ end
def pen_configure(*args)
slot = args.pop
if slot.kind_of?(Hash)
@@ -241,6 +265,9 @@ module Tk::BLT
def postscript_cget(option)
itemcget('postscript', option)
end
+ def postscript_cget_strict(option)
+ itemcget_strict('postscript', option)
+ end
def postscript_configure(slot, value=None)
itemconfigure('postscript', slot, value)
end
@@ -254,6 +281,9 @@ module Tk::BLT
def marker_cget(id, option)
itemcget(['marker', tagid(id)], option)
end
+ def marker_cget_strict(id, option)
+ itemcget_strict(['marker', tagid(id)], option)
+ end
def marker_configure(*args)
slot = args.pop
if slot.kind_of?(Hash)
@@ -273,11 +303,12 @@ module Tk::BLT
end
alias __itemcget itemcget
+ alias __itemcget_strict itemcget_strict
alias __itemconfiginfo itemconfiginfo
alias __current_itemconfiginfo current_itemconfiginfo
private :__itemcget, :__itemconfiginfo, :__current_itemconfiginfo
- def itemcget(tagOrId, option)
+ def itemcget_strict(tagOrId, option)
ret = __itemcget(tagid(tagOrId), option)
if option == 'bindtags' || option == :bindtags
ret.collect{|tag| TkBindTag.id2obj(tag)}
@@ -285,6 +316,27 @@ module Tk::BLT
ret
end
end
+ def itemcget(tagOrId, option)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ itemcget_strict(tagOrId, option)
+ else
+ begin
+ itemcget_strict(tagOrId, option)
+ rescue => e
+ begin
+ if current_itemconfiginfo(tagOrId).has_key?(option.to_s)
+ # error on known option
+ fail e
+ else
+ # unknown option
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
def itemconfiginfo(tagOrId, slot = nil)
ret = __itemconfiginfo(tagid(tagOrId), slot)
@@ -321,19 +373,30 @@ module Tk::BLT
ret
end
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
#################
class Axis < TkObject
- OBJ_ID = ['blt_chart_axis'.freeze, '00000'.taint].freeze
- OBJ_TBL={}
+ (OBJ_ID = ['blt_chart_axis'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ AxisID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ AxisID_TBL.mutex.synchronize{ AxisID_TBL.clear }
+ }
def self.id2obj(chart, id)
cpath = chart.path
- return id unless OBJ_TBL[cpath]
- OBJ_TBL[cpath][id]? OBJ_TBL[cpath][id]: id
+ AxisID_TBL.mutex.synchronize{
+ return id unless AxisID_TBL[cpath]
+ AxisID_TBL[cpath][id]? AxisID_TBL[cpath][id]: id
+ }
end
def self.new(chart, axis=nil, keys={})
@@ -341,12 +404,48 @@ module Tk::BLT
keys = axis
axis = nil
end
- OBJ_TBL[chart.path] = {} unless OBJ_TBL[chart.path]
- return OBJ_TBL[chart.path][axis] if axis && OBJ_TBL[chart.path][axis]
- super(chart, axis, keys)
+ if keys
+ keys = _symbolkey2str(keys)
+ not_create = keys.delete('without_creating')
+ else
+ not_create = false
+ end
+
+ obj = nil
+ AxisID_TBL.mutex.synchronize{
+ chart_path = chart.path
+ AxisID_TBL[chart_path] ||= {}
+ if axis && AxisID_TBL[chart_path][axis]
+ obj = AxisID_TBL[chart_path][axis]
+ else
+ (obj = self.allocate).instance_eval{
+ if axis
+ @axis = @id = axis.to_s
+ else
+ OBJ_ID.mutex.synchronize{
+ @axis = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
+ end
+ @path = @id
+ @parent = @chart = chart
+ @cpath = @chart.path
+ Axis::AxisID_TBL[@cpath][@axis] = self
+ unless not_create
+ tk_call(@chart, 'axis', 'create', @axis, keys)
+ return obj
+ end
+ }
+ end
+ }
+
+ obj.configure(keys) if obj && ! keys.empty?
+ obj
end
def initialize(chart, axis=nil, keys={})
+ # dummy:: not called by 'new' method
+
if axis.kind_of?(Hash)
keys = axis
axis = nil
@@ -354,13 +453,15 @@ module Tk::BLT
if axis
@axis = @id = axis.to_s
else
- @axis = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
- OBJ_ID[1].succ!
+ OBJ_ID.mutex.synchronize{
+ @axis = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
end
@path = @id
@parent = @chart = chart
@cpath = @chart.path
- Axis::OBJ_TBL[@cpath][@axis] = self
+ # Axis::AxisID_TBL[@cpath][@axis] = self
keys = _symbolkey2str(keys)
unless keys.delete('without_creating')
# @chart.axis_create(@axis, keys)
@@ -379,6 +480,9 @@ module Tk::BLT
def cget(option)
@chart.axis_cget(@id, option)
end
+ def cget_strict(option)
+ @chart.axis_cget_strict(@id, option)
+ end
def configure(key, value=None)
@chart.axis_configure(@id, key, value)
self
@@ -438,17 +542,34 @@ module Tk::BLT
#################
class Crosshairs < TkObject
- OBJ_TBL={}
+ CrosshairsID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ CrosshairsID_TBL.mutex.synchronize{ CrosshairsID_TBL.clear }
+ }
def self.new(chart, keys={})
- return OBJ_TBL[chart.path] if OBJ_TBL[chart.path]
- super(chart, keys)
+ obj = nil
+ CrosshairsID_TBL.mutex.synchronize{
+ unless (obj = CrosshairsID_TBL[chart.path])
+ (obj = self.allocate).instance_eval{
+ @parent = @chart = chart
+ @cpath = @chart.path
+ @path = @id = 'crosshairs'
+ Crosshairs::CrosshairsID_TBL[@cpath] = self
+ }
+ end
+ }
+ chart.crosshair_configure(keys) if obj && ! keys.empty?
+ obj
end
def initialize(chart, keys={})
+ # dummy:: not called by 'new' method
+
@parent = @chart = chart
@cpath = @chart.path
- Crosshairs::OBJ_TBL[@cpath] = self
+ # Crosshairs::CrosshairsID_TBL[@cpath] = self
@chart.crosshair_configure(keys) unless keys.empty?
@path = @id = 'crosshairs'
end
@@ -464,6 +585,9 @@ module Tk::BLT
def cget(option)
@chart.crosshair_cget(option)
end
+ def cget_strict(option)
+ @chart.crosshair_cget_strict(option)
+ end
def configure(key, value=None)
@chart.crosshair_configure(key, value)
self
@@ -500,12 +624,18 @@ module Tk::BLT
ElementTypeName = 'element'
ElementTypeToClass = { ElementTypeName=>self }
+
ElementID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ ElementID_TBL.clear }
+ TkCore::INTERP.init_ip_env{
+ ElementID_TBL.mutex.synchronize{ ElementID_TBL.clear }
+ }
- OBJ_ID = ['blt_chart_element'.freeze, '00000'.taint].freeze
- OBJ_TBL={}
+ (OBJ_ID = ['blt_chart_element'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
def Element.type2class(type)
ElementTypeToClass[type]
@@ -513,8 +643,10 @@ module Tk::BLT
def Element.id2obj(chart, id)
cpath = chart.path
- return id unless OBJ_TBL[cpath]
- OBJ_TBL[cpath][id]? OBJ_TBL[cpath][id]: id
+ ElementID_TBL.mutex.synchronize{
+ return id unless ElementID_TBL[cpath]
+ ElementID_TBL[cpath][id]? ElementID_TBL[cpath][id]: id
+ }
end
def self.new(chart, element=nil, keys={})
@@ -522,14 +654,49 @@ module Tk::BLT
keys = element
element = nil
end
- OBJ_TBL[chart.path] = {} unless OBJ_TBL[chart.path]
- if element && OBJ_TBL[chart.path][element]
- return OBJ_TBL[chart.path][element]
+ if keys
+ keys = _symbolkey2str(keys)
+ not_create = keys.delete('without_creating')
+ else
+ not_create = false
end
- super(chart, element, keys)
+
+ obj = nil
+ ElementID_TBL.mutex.synchronize{
+ chart_path = chart.path
+ ElementID_TBL[chart_path] ||= {}
+ if element && ElementID_TBL[chart_path][element]
+ obj = ElementID_TBL[chart_path][element]
+ else
+ (obj = self.allocate).instance_eval{
+ if element
+ @element = @id = element.to_s
+ else
+ OBJ_ID.mutex.synchronize{
+ @element = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
+ end
+ @path = @id
+ @parent = @chart = chart
+ @cpath = @chart.path
+ @typename = self.class::ElementTypeName
+ Element::ElementID_TBL[@cpath][@element] = self
+ unless not_create
+ tk_call(@chart, @typename, 'create', @element, keys)
+ return obj
+ end
+ }
+ end
+ }
+
+ obj.configure(keys) if obj && ! keys.empty?
+ obj
end
def initialize(chart, element=nil, keys={})
+ # dummy:: not called by 'new' method
+
if element.kind_of?(Hash)
keys = element
element = nil
@@ -537,14 +704,16 @@ module Tk::BLT
if element
@element = @id = element.to_s
else
- @element = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
- OBJ_ID[1].succ!
+ OBJ_ID.mutex.synchronize{
+ @element = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
end
@path = @id
@parent = @chart = chart
@cpath = @chart.path
@typename = self.class::ElementTypeName
- Element::OBJ_TBL[@cpath][@element] = self
+ # Element::ElementID_TBL[@cpath][@element] = self
keys = _symbolkey2str(keys)
unless keys.delete('without_creating')
# @chart.element_create(@element, keys)
@@ -564,6 +733,9 @@ module Tk::BLT
# @chart.element_cget(@id, option)
@chart.__send__(@typename + '_cget', @id, option)
end
+ def cget_strict(option)
+ @chart.__send__(@typename + '_cget_strict', @id, option)
+ end
def configure(key, value=None)
# @chart.element_configure(@id, key, value)
@chart.__send__(@typename + '_configure', @id, key, value)
@@ -622,17 +794,33 @@ module Tk::BLT
#################
class GridLine < TkObject
- OBJ_TBL={}
+ GridLineID_TBL = TkCore::INTERP.create_table
+ TkCore::INTERP.init_ip_env{
+ GridLineID_TBL.mutex.synchronize{ GridLineID_TBL.clear }
+ }
def self.new(chart, keys={})
- return OBJ_TBL[chart.path] if OBJ_TBL[chart.path]
- super(chart, keys)
+ obj = nil
+ GridLineID_TBL.mutex.synchronize{
+ unless (obj = GridLineID_TBL[chart.path])
+ (obj = self.allocate).instance_eval{
+ @parent = @chart = chart
+ @cpath = @chart.path
+ @path = @id = 'grid'
+ GridLine::GridLineID_TBL[@cpath] = self
+ }
+ end
+ }
+ chart.gridline_configure(keys) if obj && ! keys.empty?
+ obj
end
def initialize(chart, keys={})
+ # dummy:: not called by 'new' method
+
@parent = @chart = chart
@cpath = @chart.path
- GridLine::OBJ_TBL[@cpath] = self
+ # GridLine::GridLineID_TBL[@cpath] = self
@chart.gridline_configure(keys) unless keys.empty?
@path = @id = 'grid'
end
@@ -648,6 +836,9 @@ module Tk::BLT
def cget(option)
@chart.gridline_cget(option)
end
+ def cget_strict(option)
+ @chart.gridline_cget_strict(option)
+ end
def configure(key, value=None)
@chart.gridline_configure(key, value)
self
@@ -676,18 +867,35 @@ module Tk::BLT
#################
class Legend < TkObject
- OBJ_TBL={}
+ LegendID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ LegendID_TBL.mutex.synchronize{ LegendID_TBL.clear }
+ }
def self.new(chart, keys={})
- return OBJ_TBL[chart.path] if OBJ_TBL[chart.path]
- super(chart, keys)
+ obj = nil
+ LegenedID_TBL.mutex.synchronize{
+ unless (obj = LegenedID_TBL[chart.path])
+ (obj = self.allocate).instance_eval{
+ @parent = @chart = chart
+ @cpath = @chart.path
+ @path = @id = 'crosshairs'
+ Legend::LegenedID_TBL[@cpath] = self
+ }
+ end
+ }
+ chart.legend_configure(keys) if obj && ! keys.empty?
+ obj
end
def initialize(chart, keys={})
+ # dummy:: not called by 'new' method
+
@parent = @chart = chart
@cpath = @chart.path
- Crosshairs::OBJ_TBL[@cpath] = self
- @chart.crosshair_configure(keys) unless keys.empty?
+ # Legend::LegendID_TBL[@cpath] = self
+ @chart.legend_configure(keys) unless keys.empty?
@path = @id = 'legend'
end
@@ -702,6 +910,9 @@ module Tk::BLT
def cget(option)
@chart.legend_cget(option)
end
+ def cget_strict(option)
+ @chart.legend_cget_strict(option)
+ end
def configure(key, value=None)
@chart.legend_configure(key, value)
self
@@ -729,13 +940,24 @@ module Tk::BLT
#################
class Pen < TkObject
- OBJ_ID = ['blt_chart_pen'.freeze, '00000'.taint].freeze
- OBJ_TBL={}
+ (OBJ_ID = ['blt_chart_pen'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ PenID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ PenID_TBL.mutex.synchronize{ PenID_TBL.clear }
+ }
def self.id2obj(chart, id)
cpath = chart.path
- return id unless OBJ_TBL[cpath]
- OBJ_TBL[cpath][id]? OBJ_TBL[cpath][id]: id
+ PenID_TBL.mutex.synchronize{
+ return id unless PenID_TBL[cpath]
+ PenID_TBL[cpath][id]? PenID_TBL[cpath][id]: id
+ }
end
def self.new(chart, pen=nil, keys={})
@@ -743,9 +965,43 @@ module Tk::BLT
keys = pen
pen = nil
end
- OBJ_TBL[chart.path] = {} unless OBJ_TBL[chart.path]
- return OBJ_TBL[chart.path][pen] if pen && OBJ_TBL[chart.path][pen]
- super(chart, pen, keys)
+ if keys
+ keys = _symbolkey2str(keys)
+ not_create = keys.delete('without_creating')
+ else
+ not_create = false
+ end
+
+ obj = nil
+ PenID_TBL.mutex.synchronize{
+ chart_path = chart.path
+ PenID_TBL[chart_path] ||= {}
+ if pen && PenID_TBL[chart_path][pen]
+ obj = PenID_TBL[chart_path][pen]
+ else
+ (obj = self.allocate).instance_eval{
+ if pen
+ @pen = @id = pen.to_s
+ else
+ OBJ_ID.mutex.synchronize{
+ @pen = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
+ end
+ @path = @id
+ @parent = @chart = chart
+ @cpath = @chart.path
+ Pen::PenID_TBL[@cpath][@pen] = self
+ unless not_create
+ tk_call(@chart, 'pen', 'create', @pen, keys)
+ return obj
+ end
+ }
+ end
+ }
+
+ obj.configure(keys) if obj && ! keys.empty?
+ obj
end
def initialize(chart, pen=nil, keys={})
@@ -756,13 +1012,15 @@ module Tk::BLT
if pen
@pen = @id = pen.to_s
else
- @pen = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
- OBJ_ID[1].succ!
+ OBJ_ID.mutex.synchronize{
+ @pen = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
end
@path = @id
@parent = @chart = chart
@cpath = @chart.path
- Pen::OBJ_TBL[@cpath][@pen] = self
+ Pen::PenID_TBL[@cpath][@pen] = self
keys = _symbolkey2str(keys)
unless keys.delete('without_creating')
# @chart.pen_create(@pen, keys)
@@ -781,6 +1039,9 @@ module Tk::BLT
def cget(option)
@chart.pen_cget(@id, option)
end
+ def cget_strict(option)
+ @chart.pen_cget_strict(@id, option)
+ end
def configure(key, value=None)
@chart.pen_configure(@id, key, value)
self
@@ -805,17 +1066,34 @@ module Tk::BLT
#################
class Postscript < TkObject
- OBJ_TBL={}
+ PostscriptID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ PostscriptID_TBL.mutex.synchronize{ PostscriptID_TBL.clear }
+ }
def self.new(chart, keys={})
- return OBJ_TBL[chart.path] if OBJ_TBL[chart.path]
- super(chart, keys)
+ obj = nil
+ PostscriptID_TBL.mutex.synchronize{
+ unless (obj = PostscriptID_TBL[chart.path])
+ (obj = self.allocate).instance_eval{
+ @parent = @chart = chart
+ @cpath = @chart.path
+ @path = @id = 'postscript'
+ Postscript::PostscriptID_TBL[@cpath] = self
+ }
+ end
+ }
+ chart.postscript_configure(keys) if obj && ! keys.empty?
+ obj
end
def initialize(chart, keys={})
+ # dummy:: not called by 'new' method
+
@parent = @chart = chart
@cpath = @chart.path
- Postscript::OBJ_TBL[@cpath] = self
+ # Postscript::PostscriptID_TBL[@cpath] = self
@chart.postscript_configure(keys) unless keys.empty?
@path = @id = 'postscript'
end
@@ -831,6 +1109,9 @@ module Tk::BLT
def cget(option)
@chart.postscript_cget(option)
end
+ def cget_strict(option)
+ @chart.postscript_cget_strict(option)
+ end
def configure(key, value=None)
@chart.postscript_configure(key, value)
self
@@ -870,7 +1151,9 @@ module Tk::BLT
MarkerTypeToClass = {}
MarkerID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ MarkerID_TBL.clear }
+ TkCore::INTERP.init_ip_env{
+ MarkerID_TBL.mutex.synchronize{ MarkerID_TBL.clear }
+ }
def Marker.type2class(type)
MarkerTypeToClass[type]
@@ -878,8 +1161,13 @@ module Tk::BLT
def Marker.id2obj(chart, id)
cpath = chart.path
- return id unless MarkerID_TBL[cpath]
- MarkerID_TBL[cpath][id]? MarkerID_TBL[cpath][id]: id
+ MarkerID_TBL.mutex.synchronize{
+ if MarkerID_TBL[cpath]
+ MarkerID_TBL[cpath][id]? MarkerID_TBL[cpath][id]: id
+ else
+ id
+ end
+ }
end
def self._parse_create_args(keys)
@@ -902,6 +1190,13 @@ module Tk::BLT
fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
}
+ __item_optkey_aliases(nil).each{|alias_name, real_name|
+ alias_name = alias_name.to_s
+ if keys.has_key?(alias_name)
+ keys[real_name.to_s] = keys.delete(alias_name)
+ end
+ }
+
__item_methodcall_optkeys(nil).each{|key|
key = key.to_s
methodkeys[key] = keys.delete(key) if keys.key?(key)
@@ -943,10 +1238,10 @@ module Tk::BLT
@parent = @chart = chart
@cpath = chart.path
@id = id
- unless Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath]
- Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] = {}
- end
- Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL.mutex.synchronize{
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] ||= {}
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self
+ }
}
obj
end
@@ -956,10 +1251,10 @@ module Tk::BLT
@cpath = parent.path
@path = @id = create_self(*args) # an integer number as 'item id'
- unless Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath]
- Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] = {}
- end
- Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL.mutex.synchronize{
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] ||= {}
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self
+ }
end
def create_self(*args)
self.class.create(@chart, *args) # return an integer as 'item id'
@@ -977,6 +1272,9 @@ module Tk::BLT
def cget(option)
@chart.marker_cget(@id, option)
end
+ def cget_strict(option)
+ @chart.marker_cget_strict(@id, option)
+ end
def configure(key, value=None)
@chart.marker_configure(@id, key, value)
self
@@ -1037,14 +1335,14 @@ module Tk::BLT
#################
def __destroy_hook__
- Axis::OBJ_TBL.delete(@path)
- Crosshairs::OBJ_TBL.delete(@path)
- Element::OBJ_TBL.delete(@path)
- GridLine::OBJ_TBL.delete(@path)
- Legend::OBJ_TBL.delete(@path)
- Pen::OBJ_TBL.delete(@path)
- Postscript::OBJ_TBL.delete(@path)
- Marker::OBJ_TBL.delete(@path)
+ Axis::AxisID_TBL.delete(@path)
+ Crosshairs::CrosshairsID_TBL.delete(@path)
+ Element::ElementID_TBL.delete(@path)
+ GridLine::GridLineID_TBL.delete(@path)
+ Legend::LegendID_TBL.delete(@path)
+ Pen::PenID_TBL.delete(@path)
+ Postscript::PostscriptID_TBL.delete(@path)
+ Marker::MarkerID_TBL.delete(@path)
super()
end
@@ -1559,6 +1857,9 @@ module Tk::BLT
def xaxis_cget(option)
itemcget('xaxis', option)
end
+ def xaxis_cget_strict(option)
+ itemcget_strict('xaxis', option)
+ end
def xaxis_configure(slot, value=None)
if slot.kind_of?(Hash)
slot = _symbolkey2str(slot)
@@ -1628,6 +1929,9 @@ module Tk::BLT
def x2axis_cget(option)
itemcget('x2axis', option)
end
+ def x2axis_cget_strict(option)
+ itemcget_strict('x2axis', option)
+ end
def x2axis_configure(slot, value=None)
if slot.kind_of?(Hash)
slot = _symbolkey2str(slot)
@@ -1697,6 +2001,9 @@ module Tk::BLT
def yaxis_cget(option)
itemcget('yaxis', option)
end
+ def yaxis_cget_strict(option)
+ itemcget_strict('yaxis', option)
+ end
def yaxis_configure(slot, value=None)
if slot.kind_of?(Hash)
slot = _symbolkey2str(slot)
@@ -1766,6 +2073,9 @@ module Tk::BLT
def y2axis_cget(option)
itemcget('y2axis', option)
end
+ def y2axis_cget_strict(option)
+ itemcget_strict('y2axis', option)
+ end
def y2axis_configure(slot, value=None)
if slot.kind_of?(Hash)
slot = _symbolkey2str(slot)
diff --git a/ext/tk/lib/tkextlib/blt/container.rb b/ext/tk/lib/tkextlib/blt/container.rb
index 60ba1dec1e..cdbec21f25 100644
--- a/ext/tk/lib/tkextlib/blt/container.rb
+++ b/ext/tk/lib/tkextlib/blt/container.rb
@@ -11,18 +11,18 @@ module Tk::BLT
TkCommandNames = ['::blt::container'.freeze].freeze
WidgetClassName = 'Container'.freeze
WidgetClassNames[WidgetClassName] = self
- end
- def __strval_optkeys
- super() << 'name'
- end
- private :__strval_optkeys
+ def __strval_optkeys
+ super() << 'name'
+ end
+ private :__strval_optkeys
- def find_command(pat)
- list(tk_send_without_enc(tk_call(self.path, 'find', '-command', pat)))
- end
+ def find_command(pat)
+ Hash[*simplelist(tk_send_without_enc('find', '-command', pat))]
+ end
- def find_name(pat)
- list(tk_send_without_enc(tk_call(self.path, 'find', '-name', pat)))
+ def find_name(pat)
+ Hash[*simplelist(tk_send_without_enc('find', '-name', pat))]
+ end
end
end
diff --git a/ext/tk/lib/tkextlib/blt/dragdrop.rb b/ext/tk/lib/tkextlib/blt/dragdrop.rb
index 68fb9e591a..201548504a 100644
--- a/ext/tk/lib/tkextlib/blt/dragdrop.rb
+++ b/ext/tk/lib/tkextlib/blt/dragdrop.rb
@@ -81,6 +81,24 @@ module Tk::BLT
nil
]
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
_setup_subst_table(KEY_TBL, PROC_TBL)
def self.ret_val(val)
@@ -107,6 +125,24 @@ module Tk::BLT
nil
]
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
_setup_subst_table(KEY_TBL, PROC_TBL)
def self.ret_val(val)
@@ -145,6 +181,24 @@ module Tk::BLT
nil
]
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
_setup_subst_table(KEY_TBL, PROC_TBL)
end
diff --git a/ext/tk/lib/tkextlib/blt/eps.rb b/ext/tk/lib/tkextlib/blt/eps.rb
index 586a42470c..0dba87a7cc 100644
--- a/ext/tk/lib/tkextlib/blt/eps.rb
+++ b/ext/tk/lib/tkextlib/blt/eps.rb
@@ -14,7 +14,7 @@ module Tk::BLT
end
end
-class TkCanvas
+class Tk::Canvas
alias __BLT_EPS_item_strval_optkeys __item_strval_optkeys
def __item_strval_optkeys(id)
__BLT_EPS_item_strval_optkeys(id) + [
diff --git a/ext/tk/lib/tkextlib/blt/htext.rb b/ext/tk/lib/tkextlib/blt/htext.rb
index a0cf3dc036..0d9cb30185 100644
--- a/ext/tk/lib/tkextlib/blt/htext.rb
+++ b/ext/tk/lib/tkextlib/blt/htext.rb
@@ -22,6 +22,7 @@ module Tk::BLT
WidgetClassNames[WidgetClassName] = self
alias window_cget itemcget
+ alias window_cget_strict itemcget_strict
alias window_configure itemconfigure
alias window_configuinfo itemconfiginfo
alias current_window_configuinfo current_itemconfiginfo
diff --git a/ext/tk/lib/tkextlib/blt/table.rb b/ext/tk/lib/tkextlib/blt/table.rb
index fc1bf54e65..dfa10269ed 100644
--- a/ext/tk/lib/tkextlib/blt/table.rb
+++ b/ext/tk/lib/tkextlib/blt/table.rb
@@ -17,97 +17,103 @@ module Tk::BLT
module TableContainer
def blt_table_add(*args)
- Tk::BLT::Table.add(@path, *args)
+ Tk::BLT::Table.add(self, *args)
self
end
def blt_table_arrange()
- Tk::BLT::Table.arrange(@path)
+ Tk::BLT::Table.arrange(self)
self
end
def blt_table_cget(*args)
- Tk::BLT::Table.cget(@path, *args)
+ Tk::BLT::Table.cget(self, *args)
+ end
+ def blt_table_cget_strict(*args)
+ Tk::BLT::Table.cget_strict(self, *args)
end
def blt_table_configure(*args)
- Tk::BLT::Table.configure(@path, *args)
+ Tk::BLT::Table.configure(self, *args)
self
end
def blt_table_configinfo(*args)
- Tk::BLT::Table.configinfo(@path, *args)
+ Tk::BLT::Table.configinfo(self, *args)
end
def blt_table_current_configinfo(*args)
- Tk::BLT::Table.current_configinfo(@path, *args)
+ Tk::BLT::Table.current_configinfo(self, *args)
end
def blt_table_locate(x, y)
- Tk::BLT::Table.locate(@path, x, y)
+ Tk::BLT::Table.locate(self, x, y)
end
def blt_table_delete(*args)
- Tk::BLT::Table.delete(@path, *args)
+ Tk::BLT::Table.delete(self, *args)
self
end
def blt_table_extents(item)
- Tk::BLT::Table.extents(@path, item)
+ Tk::BLT::Table.extents(self, item)
end
def blt_table_insert(*args)
- Tk::BLT::Table.insert(@path, *args)
+ Tk::BLT::Table.insert(self, *args)
self
end
def blt_table_insert_before(*args)
- Tk::BLT::Table.insert_before(@path, *args)
+ Tk::BLT::Table.insert_before(self, *args)
self
end
def blt_table_insert_after(*args)
- Tk::BLT::Table.insert_after(@path, *args)
+ Tk::BLT::Table.insert_after(self, *args)
self
end
def blt_table_join(first, last)
- Tk::BLT::Table.join(@path, first, last)
+ Tk::BLT::Table.join(self, first, last)
self
end
def blt_table_save()
- Tk::BLT::Table.save(@path)
+ Tk::BLT::Table.save(self)
end
def blt_table_search(*args)
- Tk::BLT::Table.search(@path, *args)
+ Tk::BLT::Table.search(self, *args)
end
def blt_table_split(*args)
- Tk::BLT::Table.split(@path, *args)
+ Tk::BLT::Table.split(self, *args)
self
end
def blt_table_itemcget(*args)
- Tk::BLT::Table.itemcget(@path, *args)
+ Tk::BLT::Table.itemcget(self, *args)
+ end
+ def blt_table_itemcget_strict(*args)
+ Tk::BLT::Table.itemcget_strict(self, *args)
end
def blt_table_itemconfigure(*args)
- Tk::BLT::Table.itemconfigure(@path, *args)
+ Tk::BLT::Table.itemconfigure(self, *args)
self
end
def blt_table_itemconfiginfo(*args)
- Tk::BLT::Table.itemconfiginfo(@path, *args)
+ Tk::BLT::Table.itemconfiginfo(self, *args)
end
def blt_table_current_itemconfiginfo(*args)
- Tk::BLT::Table.current_itemconfiginfo(@path, *args)
+ Tk::BLT::Table.current_itemconfiginfo(self, *args)
end
def blt_table_iteminfo(item)
- Tk::BLT::Table.iteminfo(@path, item)
+ Tk::BLT::Table.iteminfo(self, item)
end
end
end
@@ -117,28 +123,32 @@ end
############################################
class << Tk::BLT::Table
def __item_cget_cmd(id) # id := [ container, item ]
- ['::blt::table', 'cget', id[0].path, id[1]]
+ win = (id[0].kind_of?(TkWindow))? id[0].path: id[0].to_s
+ ['::blt::table', 'cget', win, id[1]]
end
private :__item_cget_cmd
def __item_config_cmd(id) # id := [ container, item, ... ]
container, *items = id
- ['::blt::table', 'configure', container.path, *items]
+ win = (container.kind_of?(TkWindow))? container.path: container.to_s
+ ['::blt::table', 'configure', win, *items]
end
private :__item_config_cmd
def __item_pathname(id)
- id[0].path + ';'
+ win = (id[0].kind_of?(TkWindow))? id[0].path: id[0].to_s
+ win + ';'
end
private :__item_pathname
alias __itemcget itemcget
+ alias __itemcget_strict itemcget_strict
alias __itemconfigure itemconfigure
alias __itemconfiginfo itemconfiginfo
alias __current_itemconfiginfo current_itemconfiginfo
- private :__itemcget, :__itemconfigure
- private :__itemconfiginfo, :__current_itemconfiginfo
+ private :__itemcget, :__itemcget_strict
+ private :__itemconfigure, :__itemconfiginfo, :__current_itemconfiginfo
def __boolval_optkeys
super() << 'propagate'
@@ -173,6 +183,9 @@ class << Tk::BLT::Table
def cget(container, option)
__itemcget([container], option)
end
+ def cget_strict(container, option)
+ __itemcget_strict([container], option)
+ end
def configure(container, *args)
__itemconfigure([container], *args)
@@ -189,11 +202,15 @@ class << Tk::BLT::Table
def itemcget(container, item, option)
__itemcget([container, tagid(item)], option)
end
+ def itemcget_strict(container, item, option)
+ __itemcget_strict([container, tagid(item)], option)
+ end
def itemconfigure(container, *args)
if args[-1].kind_of?(Hash)
# container, item, item, ... , hash_optkeys
keys = args.pop
+ fail ArgumentError, 'no item is given' if args.empty?
id = [container]
args.each{|item| id << tagid(item)}
__itemconfigure(id, keys)
@@ -201,10 +218,12 @@ class << Tk::BLT::Table
# container, item, item, ... , option, value
val = args.pop
opt = args.pop
+ fail ArgumentError, 'no item is given' if args.empty?
id = [container]
args.each{|item| id << tagid(item)}
__itemconfigure(id, opt, val)
end
+ container
end
def itemconfiginfo(container, *args)
@@ -222,11 +241,35 @@ class << Tk::BLT::Table
slot = nil
end
+ fail ArgumentError, 'no item is given' if args.empty?
+
id = [container]
args.each{|item| id << tagid(item)}
__itemconfiginfo(id, slot)
end
+ def current_itemconfiginfo(container, *args)
+ slot = args[-1]
+ if slot.kind_of?(String) || slot.kind_of?(Symbol)
+ slot = slot.to_s
+ if slot[0] == ?. || slot =~ /^\d+,\d+$/ || slot =~ /^(c|C|r|R)(\*|\d+)/
+ # widget || row,col || Ci or Ri
+ slot = nil
+ else
+ # option
+ slot = args.pop
+ end
+ else
+ slot = nil
+ end
+
+ fail ArgumentError, 'no item is given' if args.empty?
+
+ id = [container]
+ args.each{|item| id << tagid(item)}
+ __current_itemconfiginfo(id, slot)
+ end
+
def info(container)
ret = {}
inf = list(tk_call('::blt::table', 'info', container))
@@ -238,12 +281,22 @@ class << Tk::BLT::Table
end
def iteminfo(container, item)
- ret = {}
- inf = list(tk_call('::blt::table', 'info', container, tagid(item)))
- until inf.empty?
- opt = inf.slice!(0..1)
- ret[opt[1..-1]] = opt[1]
+ inf = list(tk_call('::blt::table', 'info', container, tagid(item)).chomp)
+
+ ret = []
+ until inf.empty? || (inf[0].kind_of?(String) && inf[0] =~ /^-/)
+ ret << inf.shift
end
+
+ if inf.length > 1
+ keys = {}
+ while inf.length > 1
+ opt = inf.slice!(0..1)
+ keys[opt[0][1..-1]] = opt[1]
+ end
+ ret << keys
+ end
+
ret
end
@@ -253,7 +306,7 @@ class << Tk::BLT::Table
tk_call('::blt::table', container)
begin
class << container
- include Tk::BLT::TABLE::TableContainer
+ include Tk::BLT::Table::TableContainer
end
rescue
warn('fail to include TableContainer methods (frozen object?)')
@@ -276,10 +329,12 @@ class << Tk::BLT::Table
}
tk_call('::blt::table', container, *args)
end
+ container
end
def arrange(container)
tk_call('::blt::table', 'arrange', container)
+ container
end
def delete(container, *args)
diff --git a/ext/tk/lib/tkextlib/blt/tabset.rb b/ext/tk/lib/tkextlib/blt/tabset.rb
index c26b6ee001..ca81ad8f95 100644
--- a/ext/tk/lib/tkextlib/blt/tabset.rb
+++ b/ext/tk/lib/tkextlib/blt/tabset.rb
@@ -12,14 +12,26 @@ module Tk::BLT
include TkTreatItemFont
TabID_TBL = TkCore::INTERP.create_table
- TabsetTab_ID = ['blt_tabset_tab'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ TabID_TBL.clear }
+ (TabsetTab_ID = ['blt_tabset_tab'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ TabID_TBL.mutex.synchronize{ TabID_TBL.clear }
+ }
def self.id2obj(tabset, id)
tpath = tabset.path
- return id unless TabID_TBL[tpath]
- TabID_TBL[tpath][id]? TabID_TBL[tpath]: id
+ TabID_TBL.mutex.synchronize{
+ if TabID_TBL[tpath]
+ TabID_TBL[tpath][id]? TabID_TBL[tpath]: id
+ else
+ id
+ end
+ }
end
def self.new(parent, pos=nil, name=nil, keys={})
@@ -32,12 +44,20 @@ module Tk::BLT
keys = name
name = nil
end
-
- if name && TabID_TBL[parent.path] && TabID_TBL[parent.path][name]
- TabID_TBL[parent.path][name]
- else
- super(parent, pos, name, keys)
- end
+ obj = nil
+ TabID_TBL.mutex.synchronize{
+ if name && TabID_TBL[parent.path] && TabID_TBL[parent.path][name]
+ obj = TabID_TBL[parent.path][name]
+ obj.configure if keys && ! keys.empty?
+ else
+ (obj = self.allocate).instance_eval{
+ initialize(parent, pos, name, keys)
+ TabID_TBL[@tpath] = {} unless TabID_TBL[@tpath]
+ TabID_TBL[@tpath][@id] = self
+ }
+ end
+ }
+ obj
end
def initialize(parent, pos, name, keys)
@@ -45,9 +65,6 @@ module Tk::BLT
@tpath = parent.path
if name
@path = @id = name
- TabID_TBL[@tpath] = {} unless TabID_TBL[@tpath]
- TabID_TBL[@tpath][@id] = self
-
unless (list(tk_call(@tpath, 'tab', 'names', @id)).empty?)
if pos
idx = tk_call(@tpath, 'index', '-name', @id)
@@ -58,18 +75,18 @@ module Tk::BLT
end
end
tk_call(@tpath, 'tab', 'configure', @id, keys)
- return
+ else
+ pos = 'end' unless pos
+ tk_call(@tpath, 'insert', pos, @id, keys)
end
-
else
- @path = @id = TabsetTab_ID.join(TkCore::INTERP._ip_id_)
- TabID_TBL[@tpath] = {} unless TabID_TBL[@tpath]
- TabID_TBL[@tpath][@id] = self
- TabsetTab_ID[1].succ!
+ TabsetTab_ID.mutex.synchronize{
+ @path = @id = TabsetTab_ID.join(TkCore::INTERP._ip_id_)
+ TabsetTab_ID[1].succ!
+ }
+ pos = 'end' unless pos
+ tk_call(@tpath, 'insert', pos, @id, keys)
end
-
- pos = 'end' unless pos
- tk_call(@tpath, 'insert', pos, @id, keys)
end
#def bind(context, cmd=Proc.new, *args)
@@ -111,6 +128,9 @@ module Tk::BLT
def cget(*args)
@t.tab_cget(@id, *args)
end
+ def cget_strict(*args)
+ @t.tab_cget_strict(@id, *args)
+ end
def configure(*args)
@t.tab_configure(@id, *args)
end
@@ -123,7 +143,9 @@ module Tk::BLT
def delete()
@t.delete(@id)
- TabID_TBL[@tpath].delete(@id)
+ TabID_TBL.mutex.synchronize{
+ TabID_TBL[@tpath].delete(@id)
+ }
self
end
@@ -184,7 +206,9 @@ module Tk::BLT
WidgetClassNames[WidgetClassName] = self
def __destroy_hook__
- Tk::BLT::Tabset::Tab::TabID_TBL.delete(@path)
+ Tk::BLT::Tabset::Tab::TabID_TBL.mutex.synchronize{
+ Tk::BLT::Tabset::Tab::TabID_TBL.delete(@path)
+ }
end
########################################
@@ -219,6 +243,7 @@ module Tk::BLT
private :__item_pathname
alias tab_cget itemcget
+ alias tab_cget_strict itemcget_strict
alias tab_configure itemconfigure
alias tab_configinfo itemconfiginfo
alias current_tab_configinfo current_itemconfiginfo
@@ -291,11 +316,15 @@ module Tk::BLT
def delete(first, last=None)
tk_send('delete', tagindex(first), tagindex(last))
if first.kind_of?(Tk::BLT::Tabset::Tab)
- TabID_TBL[@path].delete(first.id)
+ TabID_TBL.mutex.synchronize{
+ TabID_TBL[@path].delete(first.id)
+ }
end
# middle tabs of the range are unknown
if last.kind_of?(Tk::BLT::Tabset::Tab)
- TabID_TBL[@path].delete(last.id)
+ TabID_TBL.mutex.synchronize{
+ TabID_TBL[@path].delete(last.id)
+ }
end
self
end
diff --git a/ext/tk/lib/tkextlib/blt/ted.rb b/ext/tk/lib/tkextlib/blt/ted.rb
index 39495842b4..670265fc78 100644
--- a/ext/tk/lib/tkextlib/blt/ted.rb
+++ b/ext/tk/lib/tkextlib/blt/ted.rb
@@ -30,11 +30,14 @@ module Tk::BLT
end
private :__item_config_cmd
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
def cget(master, option)
- itemconfigure(master, slot, value)
+ itemcget(master, option)
+ end
+ def cget_strict(master, option)
+ itemcget_strict(master, option)
end
def configure(master, slot, value=None)
itemconfigure(master, slot, value)
diff --git a/ext/tk/lib/tkextlib/blt/tile/button.rb b/ext/tk/lib/tkextlib/blt/tile/button.rb
index dd715c8b98..2e0863cfbe 100644
--- a/ext/tk/lib/tkextlib/blt/tile/button.rb
+++ b/ext/tk/lib/tkextlib/blt/tile/button.rb
@@ -9,7 +9,7 @@ require 'tkextlib/blt/tile.rb'
module Tk::BLT
module Tile
- class Button < TkButton
+ class Button < Tk::Button
TkCommandNames = ['::blt::tile::button'.freeze].freeze
end
end
diff --git a/ext/tk/lib/tkextlib/blt/tile/checkbutton.rb b/ext/tk/lib/tkextlib/blt/tile/checkbutton.rb
index ebe79179a5..da230b5925 100644
--- a/ext/tk/lib/tkextlib/blt/tile/checkbutton.rb
+++ b/ext/tk/lib/tkextlib/blt/tile/checkbutton.rb
@@ -9,9 +9,9 @@ require 'tkextlib/blt/tile.rb'
module Tk::BLT
module Tile
- class Checkbutton < TkCheckbutton
+ class CheckButton < Tk::CheckButton
TkCommandNames = ['::blt::tile::checkbutton'.freeze].freeze
end
- CheckButton = Checkbutton
+ Checkbutton = CheckButton
end
end
diff --git a/ext/tk/lib/tkextlib/blt/tile/frame.rb b/ext/tk/lib/tkextlib/blt/tile/frame.rb
index 10469fd35f..5434af4b72 100644
--- a/ext/tk/lib/tkextlib/blt/tile/frame.rb
+++ b/ext/tk/lib/tkextlib/blt/tile/frame.rb
@@ -9,7 +9,7 @@ require 'tkextlib/blt/tile.rb'
module Tk::BLT
module Tile
- class Frame < TkFrame
+ class Frame < Tk::Frame
TkCommandNames = ['::blt::tile::frame'.freeze].freeze
end
end
diff --git a/ext/tk/lib/tkextlib/blt/tile/label.rb b/ext/tk/lib/tkextlib/blt/tile/label.rb
index ec67babd58..f370c1403b 100644
--- a/ext/tk/lib/tkextlib/blt/tile/label.rb
+++ b/ext/tk/lib/tkextlib/blt/tile/label.rb
@@ -9,7 +9,7 @@ require 'tkextlib/blt/tile.rb'
module Tk::BLT
module Tile
- class Label < TkLabel
+ class Label < Tk::Label
TkCommandNames = ['::blt::tile::label'.freeze].freeze
end
end
diff --git a/ext/tk/lib/tkextlib/blt/tile/radiobutton.rb b/ext/tk/lib/tkextlib/blt/tile/radiobutton.rb
index 7573aa08d6..814f9a5cc4 100644
--- a/ext/tk/lib/tkextlib/blt/tile/radiobutton.rb
+++ b/ext/tk/lib/tkextlib/blt/tile/radiobutton.rb
@@ -9,9 +9,9 @@ require 'tkextlib/blt/tile.rb'
module Tk::BLT
module Tile
- class Radiobutton < TkRadiobutton
+ class RadioButton < Tk::RadioButton
TkCommandNames = ['::blt::tile::radiobutton'.freeze].freeze
end
- RadioButton = Radiobutton
+ Radiobutton = RadioButton
end
end
diff --git a/ext/tk/lib/tkextlib/blt/tile/scrollbar.rb b/ext/tk/lib/tkextlib/blt/tile/scrollbar.rb
index ba3bf316f0..2ae871d518 100644
--- a/ext/tk/lib/tkextlib/blt/tile/scrollbar.rb
+++ b/ext/tk/lib/tkextlib/blt/tile/scrollbar.rb
@@ -9,7 +9,7 @@ require 'tkextlib/blt/tile.rb'
module Tk::BLT
module Tile
- class Scrollbar < TkScrollbar
+ class Scrollbar < Tk::Scrollbar
TkCommandNames = ['::blt::tile::scrollbar'.freeze].freeze
end
end
diff --git a/ext/tk/lib/tkextlib/blt/tile/toplevel.rb b/ext/tk/lib/tkextlib/blt/tile/toplevel.rb
index 6cc2c91415..76d5f86b1b 100644
--- a/ext/tk/lib/tkextlib/blt/tile/toplevel.rb
+++ b/ext/tk/lib/tkextlib/blt/tile/toplevel.rb
@@ -9,7 +9,7 @@ require 'tkextlib/blt/tile.rb'
module Tk::BLT
module Tile
- class Toplevel < TkToplevel
+ class Toplevel < Tk::Toplevel
TkCommandNames = ['::blt::tile::toplevel'.freeze].freeze
end
end
diff --git a/ext/tk/lib/tkextlib/blt/tree.rb b/ext/tk/lib/tkextlib/blt/tree.rb
index 07dc7ef7e8..77b85f1717 100644
--- a/ext/tk/lib/tkextlib/blt/tree.rb
+++ b/ext/tk/lib/tkextlib/blt/tree.rb
@@ -12,53 +12,77 @@ module Tk::BLT
###################################
- class Node < TkObject
+ class Node < TkObject
TreeNodeID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ TreeNodeID_TBL.clear }
+
+ TkCore::INTERP.init_ip_env{
+ TreeNodeID_TBL.mutex.synchronize{ TreeNodeID_TBL.clear }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless TreeNodeID_TBL[tpath]
- if TreeNodeID_TBL[tpath][id]
- TreeNodeID_TBL[tpath][id]
- else
- begin
- self.new(tree, nil, 'node'=>Integer(id))
- rescue
+ TreeNodeID_TBL.mutex.synchronize{
+ if TreeNodeID_TBL[tpath]
+ if TreeNodeID_TBL[tpath][id]
+ TreeNodeID_TBL[tpath][id]
+ else
+ begin
+ # self.new(tree, nil, 'node'=>Integer(id))
+ id = Integer(id)
+ if bool(tk_call(@tpath, 'exists', id))
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = tpath
+ @path = @id = id
+ TreeNodeID_TBL[@tpath] = {} unless TreeNodeID_TBL[@tpath]
+ TreeNodeID_TBL[@tpath][@id] = self
+ }
+ obj
+ else
+ id
+ end
+ rescue
+ id
+ end
+ end
+ else
id
end
- end
+ }
end
def self.new(tree, parent, keys={})
keys = _symbolkey2str(keys)
tpath = tree.path
- if (id = keys['node']) && (obj = TreeNodeID_TBL[tpath][id])
- keys.delete('node')
- tk_call(tree.path, 'move', id, parent, keys) if parent
- return obj
- end
+ TreeNodeID_TBL.mutex.synchronize{
+ TreeNodeID_TBL[tpath] ||= {}
+ if (id = keys['node']) && (obj = TreeNodeID_TBL[tpath][id])
+ keys.delete('node')
+ tk_call(tree.path, 'move', id, parent, keys) if parent
+ return obj
+ end
- super(tree, parent, keys)
+ (obj = self.allocate).instance_eval{
+ initialize(tree, parent, keys)
+ TreeNodeID_TBL[tpath][@id] = self
+ }
+ obj
+ }
end
def initialize(tree, parent, keys={})
@parent = @tree = tree
@tpath = @parent.path
- parent = tk_call(@tpath, 'root') unless parent
-
if (id = keys['node']) && bool(tk_call(@tpath, 'exists', id))
@path = @id = id
keys.delete('node')
tk_call(@tpath, 'move', @id, parent, keys) if parent
else
+ parent = tk_call(@tpath, 'root') unless parent
@path = @id = tk_call(@tpath, 'insert', parent, keys)
end
-
- TreeNodeID_TBL[@tpath] = {} unless TreeNodeID_TBL[@tpath]
- TreeNodeID_TBL[@tpath][@id] = self
end
def id
@@ -243,17 +267,42 @@ module Tk::BLT
class Tag < TkObject
TreeTagID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ TreeTagID_TBL.clear }
- TreeTag_ID = ['blt_tree_tag'.freeze, '00000'.taint].freeze
+
+ TkCore::INTERP.init_ip_env{
+ TreeTagID_TBL.mutex.synchronize{ TreeTagID_TBL.clear }
+ }
+
+ (TreeTag_ID = ['blt_tree_tag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless TreeTagID_TBL[tpath]
- if TreeTagID_TBL[tpath][id]
- TreeTagID_TBL[tpath][id]
- else
- self.new(tree, id)
- end
+ TreeTagID_TBL.mutex.synchronize{
+ if TreeTagID_TBL[tpath]
+ if TreeTagID_TBL[tpath][id]
+ TreeTagID_TBL[tpath][id]
+ else
+ begin
+ # self.new(tree, id)
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = id.dup.freeze if id
+ TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
+ TreeTagID_TBL[@tpath][@id] = self
+ }
+ obj
+ rescue
+ id
+ end
+ end
+ else
+ id
+ end
+ }
end
def initialize(tree, tag_str = nil)
@@ -263,12 +312,15 @@ module Tk::BLT
if tag_str
@path = @id = tag_str.dup.freeze
else
- @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_)
- TreeTagID_TBL[@id] = self
- TreeTag_ID[1].succ!
+ TreeTag_ID.mutex.synchronize{
+ @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_)
+ TreeTag_ID[1].succ!
+ }
end
- TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
- TreeTagID_TBL[@tpath][@id] = self
+ TreeTagID_TBL.mutex.synchronize{
+ TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
+ TreeTagID_TBL[@tpath][@id] = self
+ }
end
def id
@@ -287,7 +339,9 @@ module Tk::BLT
def forget()
tk_call(@tpath, 'tag', 'forget', @id)
- TreeTagID_TBL[@tpath].delete(@id)
+ TreeTagID_TBL.mutex.synchronize{
+ TreeTagID_TBL[@tpath].delete(@id)
+ }
self
end
@@ -312,44 +366,63 @@ module Tk::BLT
class Notify < TkObject
NotifyID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ NotifyID_TBL.clear }
+
+ TkCore::INTERP.init_ip_env{
+ NotifyID_TBL.mutex.synchronize{ NotifyID_TBL.clear }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless NotifyID_TBL[tpath]
- if NotifyID_TBL[tpath][id]
- NotifyID_TBL[tpath][id]
- else
- begin
- self.new([tree, id])
- rescue
- id
+ NotifyID_TBL.mutex.synchronize{
+ if NotifyID_TBL[tpath]
+ if NotifyID_TBL[tpath][id]
+ NotifyID_TBL[tpath][id]
+ else
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = id
+ NotifyID_TBL[@tpath] ||= {}
+ NotifyID_TBL[@tpath][@id] = self
+ }
+ obj
+ end
+ else
+ return id
end
- end
+ }
end
def self.new(tree, *args, &b)
- if tree.kind_of?(Array)
- # not create
- if obj = NotifyID_TBL[tree[0].path][tree[1]]
+ NotifyID_TBL.mutex.synchronize{
+ if tree.kind_of?(Array)
+ # not create
+ tpath = tree[0].path
+ NotifyID_TBL[tpath] ||= {}
+ unless (obj = NotifyID_TBL[tpath][tree[1]])
+ (NotifyID_TBL[tpath][tree[1]] =
+ obj = self.allocate).instance_eval{
+ @parent = @tree = tree[0]
+ @tpath = @parent.path
+ @path = @id = tree[1]
+ }
+ end
return obj
- else
- return super(false, tree[0], tree[1])
end
- end
- super(true, tree, *args, &b)
+ (obj = self.allocate).instance_eval{
+ initialize(tree, *args, &b)
+ NotifyID_TBL[@tpath] ||= {}
+ NotifyID_TBL[@tpath][@id] = self
+ }
+ return obj
+ }
end
- def initialize(create, tree, *args, &b)
+ def initialize(tree, *args, &b)
@parent = @tree = tree
@tpath = @parent.path
- unless create
- @path = @id = args[0]
- return
- end
-
# if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
if TkComm._callback_entry?(args[0])
cmd = args.shift
@@ -378,7 +451,9 @@ module Tk::BLT
def delete()
tk_call(@tpath, 'notify', 'delete', @id)
- NotifyID_TBL[tpath].delete(@id)
+ NotifyID_TBL.mutex.synchronize{
+ NotifyID_TBL[@tpath].delete(@id)
+ }
self
end
@@ -395,44 +470,69 @@ module Tk::BLT
class Trace < TkObject
TraceID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ TraceID_TBL.clear }
+
+ TkCore::INTERP.init_ip_env{
+ TraceID_TBL.mutex.synchronize{ TraceID_TBL.clear }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless TraceID_TBL[tpath]
- if TraceID_TBL[tpath][id]
- TraceID_TBL[tpath][id]
- else
- begin
- self.new([tree, id])
- rescue
+ TraceID_TBL.mutex.synchronize{
+ if TraceID_TBL[tpath]
+ if TraceID_TBL[tpath][id]
+ TraceID_TBL[tpath][id]
+ else
+ begin
+ # self.new([tree, id])
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = node # == traceID
+ TraceID_TBL[@tpath] ||= {}
+ TraceID_TBL[@tpath][@id] = self
+ }
+ obj
+ rescue
+ id
+ end
+ end
+ else
id
end
- end
+ }
end
def self.new(tree, *args, &b)
- if tree.kind_of?(Array)
- # not create
- if obj = TraceID_TBL[tree[0].path][tree[1]]
+ TraceID_TBL.mutex.synchronize{
+ if tree.kind_of?(Array)
+ # not create
+ tpath = tree[0].path
+ TraceID_TBL[tpath] ||= {}
+ unless (obj = TraceID_TBL[tpath][tree[1]])
+ (TraceID_TBL[tpath][tree[1]] =
+ obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = tree[1] # == traceID
+ }
+ end
return obj
- else
- return super(false, tree[0], tree[1])
end
- end
- super(true, tree, *args, &b)
+ # super(true, tree, *args, &b)
+ (obj = self.allocate).instance_eval{
+ initialize(tree, *args, &b)
+ TraceID_TBL[@tpath] ||= {}
+ TraceID_TBL[@tpath][@id] = self
+ }
+ return obj
+ }
end
- def initialize(create, tree, node, key, opts, cmd=nil, &b)
+ def initialize(tree, node, key, opts, cmd=nil, &b)
@parent = @tree = tree
@tpath = @parent.path
- unless create
- @path = @id = node # == traceID
- return
- end
-
if !cmd
if b
cmd = Proc.new(&b)
@@ -459,7 +559,9 @@ module Tk::BLT
def delete()
tk_call(@tpath, 'trace', 'delete', @id)
- TraceID_TBL[tpath].delete(@id)
+ TraceID_TBL.mutex.synchronize{
+ TraceID_TBL[tpath].delete(@id)
+ }
self
end
@@ -475,7 +577,12 @@ module Tk::BLT
###################################
TreeID_TBL = TkCore::INTERP.create_table
- Tree_ID = ['blt_tree'.freeze, '00000'.taint].freeze
+
+ (Tree_ID = ['blt_tree'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
def __keyonly_optkeys
{
@@ -498,7 +605,9 @@ module Tk::BLT
end
def self.id2obj(id)
- TreeID_TBL[id]? TreeID_TBL[id]: id
+ TreeID_TBL.mutex.synchronize{
+ TreeID_TBL[id]? TreeID_TBL[id]: id
+ }
end
def self.names(pat = None)
@@ -513,27 +622,45 @@ module Tk::BLT
end
def self.new(name = nil)
- return TreeID_TBL[name] if name && TreeID_TBL[name]
- super(name)
+ TreeID_TBL.mutex.synchronize{
+ if name && TreeID_TBL[name]
+ TreeID_TBL[name]
+ else
+ (obj = self.allocate).instance_eval{
+ initialize(name)
+ TreeID_TBL[@id] = self
+ }
+ obj
+ end
+ }
end
def initialzie(name = nil)
if name
@path = @id = name
else
- @path = @id = Tree_ID.join(TkCore::INTERP._ip_id_)
- TreeID_TBL[@id] = self
- Tree_ID[1].succ!
+ Tree_ID.mutex.synchronize{
+ @path = @id = Tree_ID.join(TkCore::INTERP._ip_id_)
+ Tree_ID[1].succ!
+ }
end
- TreeID_TBL[@id] = self
+
tk_call('::blt::tree', 'create', @id)
end
def __destroy_hook__
- Tk::BLT::Tree::Node::TreeNodeID_TBL.delete(@path)
- Tk::BLT::Tree::Tag::TreeTagID_TBL.delete(@path)
- Tk::BLT::Tree::Notify::NotifyID_TBL.delete(@path)
- Tk::BLT::Tree::Trace::TraceID_TBL.delete(@path)
+ Tk::BLT::Tree::Node::TreeNodeID_TBL.mutex.synchronize{
+ Tk::BLT::Tree::Node::TreeNodeID_TBL.delete(@path)
+ }
+ Tk::BLT::Tree::Tag::TreeTagID_TBL.mutex.synchronize{
+ Tk::BLT::Tree::Tag::TreeTagID_TBL.delete(@path)
+ }
+ Tk::BLT::Tree::Notify::NotifyID_TBL.mutex.synchronize{
+ Tk::BLT::Tree::Notify::NotifyID_TBL.delete(@path)
+ }
+ Tk::BLT::Tree::Trace::TraceID_TBL.mutex.synchronize{
+ Tk::BLT::Tree::Trace::TraceID_TBL.delete(@path)
+ }
end
def tagid(tag)
@@ -592,12 +719,14 @@ module Tk::BLT
def delete(*nodes)
tk_call('::blt::tree', 'delete', *(nodes.collect{|node| tagid(node)}))
- nodes.each{|node|
- if node.kind_of?(Tk::BLT::Tree::Node)
- Tk::BLT::Tree::Node::TreeNodeID_TBL[@path].delete(node.id)
- else
- Tk::BLT::Tree::Node::TreeNodeID_TBL[@path].delete(node.to_s)
- end
+ Tk::BLT::Tree::Node::TreeNodeID_TBL.mutex.synchronize{
+ nodes.each{|node|
+ if node.kind_of?(Tk::BLT::Tree::Node)
+ Tk::BLT::Tree::Node::TreeNodeID_TBL[@path].delete(node.id)
+ else
+ Tk::BLT::Tree::Node::TreeNodeID_TBL[@path].delete(node.to_s)
+ end
+ }
}
self
end
@@ -728,7 +857,9 @@ module Tk::BLT
id.delete
else
tk_call(@path, 'notify', 'delete', id)
- Tk::BLT::Tree::Notify::NotifyID_TBL[@path].delete(id.to_s)
+ Tk::BLT::Tree::Notify::NotifyID_TBL.mutex.synchronize{
+ Tk::BLT::Tree::Notify::NotifyID_TBL[@path].delete(id.to_s)
+ }
end
self
end
@@ -835,7 +966,9 @@ module Tk::BLT
def tag_forget(tag)
tag = tag.id if tag.kind_of?(Tk::BLT::Tree::Tag)
tk_call(@path, 'tag', 'forget', tag)
- TreeTagID_TBL[@path].delete(tag)
+ TreeTagID_TBL.mutex.synchronize{
+ TreeTagID_TBL[@path].delete(tag)
+ }
self
end
@@ -889,7 +1022,9 @@ module Tk::BLT
def trace_delete(*args)
args = args.collect{|id| tagid(id)}
tk_call(@path, 'trace', 'delete', *args)
- args.each{|id| Tk::BLT::Tree::Trace::TraceID_TBL[@path].delete(id.to_s)}
+ Tk::BLT::Tree::Trace::TraceID_TBL.mutex.synchronize{
+ args.each{|id| Tk::BLT::Tree::Trace::TraceID_TBL[@path].delete(id.to_s)}
+ }
self
end
diff --git a/ext/tk/lib/tkextlib/blt/treeview.rb b/ext/tk/lib/tkextlib/blt/treeview.rb
index 0343d28b9c..c5a5697186 100644
--- a/ext/tk/lib/tkextlib/blt/treeview.rb
+++ b/ext/tk/lib/tkextlib/blt/treeview.rb
@@ -98,6 +98,9 @@ module Tk::BLT::Treeview::ConfigMethod
def column_cget(name, option)
itemcget(['column', name], option)
end
+ def column_cget_strict(name, option)
+ itemcget_strict(['column', name], option)
+ end
def column_configure(name, slot, value=None)
itemconfigure(['column', name], slot, value)
end
@@ -111,6 +114,9 @@ module Tk::BLT::Treeview::ConfigMethod
def button_cget(option)
itemcget('button', option)
end
+ def button_cget_strict(option)
+ itemcget_strict('button', option)
+ end
def button_configure(slot, value=None)
itemconfigure('button', slot, value)
end
@@ -129,6 +135,14 @@ module Tk::BLT::Treeview::ConfigMethod
ret
end
end
+ def entry_cget_strict(option)
+ ret = itemcget_strict('entry', option)
+ if option == 'bindtags' || option == :bindtags
+ ret.collect{|tag| TkBindTag.id2obj(tag)}
+ else
+ ret
+ end
+ end
def entry_configure(slot, value=None)
itemconfigure('entry', slot, value)
end
@@ -170,6 +184,9 @@ module Tk::BLT::Treeview::ConfigMethod
def sort_cget(option)
itemcget('sort', option)
end
+ def sort_cget_strict(option)
+ itemcget_strict('sort', option)
+ end
def sort_configure(slot, value=None)
itemconfigure('sort', slot, value)
end
@@ -183,6 +200,9 @@ module Tk::BLT::Treeview::ConfigMethod
def text_cget(option)
itemcget('text', option)
end
+ def text_cget_strict(option)
+ itemcget_strict('text', option)
+ end
def text_configure(slot, value=None)
itemconfigure('text', slot, value)
end
@@ -193,8 +213,8 @@ module Tk::BLT::Treeview::ConfigMethod
current_itemconfiginfo('text', slot)
end
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
end
class Tk::BLT::Treeview
@@ -239,6 +259,24 @@ class Tk::BLT::Treeview
nil
]
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
@@ -273,8 +311,12 @@ class Tk::BLT::Treeview
########################
def __destroy_hook__
- Tk::BLT::Treeview::Node::TreeNodeID_TBL.delete(@path)
- Tk::BLT::Treeview::Tag::TreeTagID_TBL.delete(@path)
+ Tk::BLT::Treeview::Node::TreeNodeID_TBL.mutex.synchronize{
+ Tk::BLT::Treeview::Node::TreeNodeID_TBL.delete(@path)
+ }
+ Tk::BLT::Treeview::Tag::TreeTagID_TBL.mutex.synchronize{
+ Tk::BLT::Treeview::Tag::TreeTagID_TBL.delete(@path)
+ }
end
def tagid(tag)
@@ -472,6 +514,24 @@ class Tk::BLT::Treeview
nil
]
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
@@ -487,7 +547,8 @@ class Tk::BLT::Treeview
def _find_exec_flag_value(val)
if val.kind_of?(Array)
cmd, *args = val
- FindExecFlagValue.new(cmd, args.join(' '))
+ #FindExecFlagValue.new(cmd, args.join(' '))
+ FindExecFlagValue.new(cmd, *args)
elsif TkComm._callback_entry?(val)
FindExecFlagValue.new(val)
else
@@ -967,22 +1028,47 @@ class Tk::BLT::Treeview::Node < TkObject
include Tk::BLT::Treeview::TagOrID_Methods
TreeNodeID_TBL = TkCore::INTERP.create_table
- TreeNode_ID = ['blt_treeview_node'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ TreeNodeID_TBL.clear }
+ (TreeNode_ID = ['blt_treeview_node'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ TreeNodeID_TBL.mutex.synchronize{ TreeNodeID_TBL.clear }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless TreeNodeID_TBL[tpath]
- if TreeNodeID_TBL[tpath][id]
- TreeNodeID_TBL[tpath][id]
- else
- begin
- self.new(tree, nil, nil, 'node'=>Integer(id))
- rescue
+ TreeNodeID_TBL.mutex.synchronize{
+ if TreeNodeID_TBL[tpath]
+ if TreeNodeID_TBL[tpath][id]
+ TreeNodeID_TBL[tpath][id]
+ else
+ begin
+ # self.new(tree, nil, nil, 'node'=>Integer(id))
+ unless (tk_call(@tpath, 'get', id)).empty?
+ id = Integer(id)
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = id
+ TreeNodeID_TBL[@tpath] ||= {}
+ TreeNodeID_TBL[@tpath][@id] = self
+ }
+ obj
+ else
+ id
+ end
+ rescue
+ id
+ end
+ end
+ else
id
end
- end
+ }
end
def self.new(tree, pos, parent=nil, keys={})
@@ -994,13 +1080,21 @@ class Tk::BLT::Treeview::Node < TkObject
keys = _symbolkey2str(keys)
tpath = tree.path
- if (id = keys['node']) && (obj = TreeNodeID_TBL[tpath][id])
- keys.delete('node')
- tk_call(tree.path, 'move', id, pos, parent) if parent
- return obj
- end
+ TreeNodeID_TBL.mutex.synchronize{
+ TreeNodeID_TBL[tpath] ||= {}
+ if (id = keys['node']) && (obj = TreeNodeID_TBL[tpath][id])
+ keys.delete('node')
+ tk_call(tree.path, 'move', id, pos, parent) if parent
+ return obj
+ end
- super(tree, pos, parent, keys)
+ #super(tree, pos, parent, keys)
+ (obj = self.allocate).instance_eval{
+ initialize(tree, pos, parent, keys)
+ TreeNodeID_TBL[tpath][@id] = self
+ }
+ obj
+ }
end
def initialize(tree, pos, parent, keys)
@@ -1008,11 +1102,18 @@ class Tk::BLT::Treeview::Node < TkObject
@tpath = @parent.path
if (id = keys['node'])
+ # if tk_call(@tpath, 'get', id).empty?
+ # fail RuntimeError, "not exist the node '#{id}'"
+ # end
@path = @id = id
tk_call(@tpath, 'move', @id, pos, tagid(parent)) if parent
+ configure(keys) if keys && ! keys.empty?
else
- name = TreeNode_ID.join(TkCore::INTERP._ip_id_).freeze
- TreeNode_ID[1].succ!
+ name = nil
+ TreeNode_ID.mutex.synchronize{
+ name = TreeNode_ID.join(TkCore::INTERP._ip_id_).freeze
+ TreeNode_ID[1].succ!
+ }
at = keys.delete['at']
@@ -1035,9 +1136,6 @@ class Tk::BLT::Treeview::Node < TkObject
end
@path = @id
end
-
- TreeNodeID_TBL[@tpath] = {} unless TreeNodeID_TBL[@tpath]
- TreeNodeID_TBL[@tpath][@id] = self
end
def id
@@ -1051,37 +1149,66 @@ class Tk::BLT::Treeview::Tag < TkObject
include Tk::BLT::Treeview::TagOrID_Methods
TreeTagID_TBL = TkCore::INTERP.create_table
- TreeTag_ID = ['blt_treeview_tag'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ TreeTagID_TBL.clear }
+ (TreeTag_ID = ['blt_treeview_tag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
- def self.id2obj(tree, id)
+ TkCore::INTERP.init_ip_env{
+ TreeTagID_TBL.mutex.synchronize{ TreeTagID_TBL.clear }
+ }
+
+ def self.id2obj(tree, name)
tpath = tree.path
- return id unless TreeTagID_TBL[tpath]
- if TreeTagID_TBL[tpath][id]
- TreeTagID_TBL[tpath][id]
- else
- begin
- self.new(tree, nil, nil, 'name'=>Integer(id))
- rescue
+ TreeTagID_TBL.mutex.synchronize{
+ if TreeTagID_TBL[tpath]
+ if TreeTagID_TBL[tpath][name]
+ TreeTagID_TBL[tpath][name]
+ else
+ #self.new(tree, name)
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = name
+ TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
+ TreeTagID_TBL[@tpath][@id] = self
+ }
+ obj
+ end
+ else
id
end
- end
+ }
end
def self.new_by_name(tree, name, *ids)
- if (obj = TreeTagID_TBL[tree.path][name])
- return obj
- end
- new([tree, name], ids)
+ TreeTagID_TBL.mutex.synchronize{
+ unless (obj = TreeTagID_TBL[tree.path][name])
+ (obj = self.allocate).instance_eval{
+ initialize(tree, name, ids)
+ TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
+ TreeTagID_TBL[@tpath][@id] = self
+ }
+ end
+ obj
+ }
end
def self.new(tree, *ids)
- if tree.kind_of?(Array)
- super(tree[0], tree[1], ids)
- else
- super(tree, nil, ids)
- end
+ TreeTagID_TBL.mutex.synchronize{
+ (obj = self.allocate).instance_eval{
+ if tree.kind_of?(Array)
+ initialize(tree[0], tree[1], ids)
+ else
+ initialize(tree, nil, ids)
+ end
+ TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
+ TreeTagID_TBL[@tpath][@id] = self
+ }
+ obj
+ }
end
def initialize(tree, name, ids)
@@ -1091,13 +1218,12 @@ class Tk::BLT::Treeview::Tag < TkObject
if name
@path = @id = name
else
- @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_).freeze
- TreeTag_ID[1].succ!
+ TreeTag_ID.mutex.synchronize{
+ @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_).freeze
+ TreeTag_ID[1].succ!
+ }
end
- TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
- TreeTagID_TBL[@tpath][@id] = self
-
unless ids.empty?
tk_call(@tpath, 'tag', 'add', @id, *(ids.collect{|id| tagid(id)}))
end
diff --git a/ext/tk/lib/tkextlib/blt/unix_dnd.rb b/ext/tk/lib/tkextlib/blt/unix_dnd.rb
index 3130c1e56f..445002d7a5 100644
--- a/ext/tk/lib/tkextlib/blt/unix_dnd.rb
+++ b/ext/tk/lib/tkextlib/blt/unix_dnd.rb
@@ -30,11 +30,14 @@ module Tk::BLT
end
private :__item_config_cmd
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
def cget(win, option)
- itemconfigure(['cget', win], slot, value)
+ itemcget(['cget', win], option)
+ end
+ def cget_strict(win, option)
+ itemcget_strict(['cget', win], option)
end
def configure(win, slot, value=None)
itemconfigure(['configure', win], slot, value)
@@ -46,8 +49,11 @@ module Tk::BLT
current_itemconfiginfo(['configure', win], slot)
end
- def tokwn_cget(win, option)
- itemconfigure(['token', 'cget', win], slot, value)
+ def token_cget(win, option)
+ itemcget(['token', 'cget', win], option)
+ end
+ def token_cget_strict(win, option)
+ itemcget_strict(['token', 'cget', win], option)
end
def token_configure(win, slot, value=None)
itemconfigure(['token', 'configure', win], slot, value)
diff --git a/ext/tk/lib/tkextlib/blt/vector.rb b/ext/tk/lib/tkextlib/blt/vector.rb
index 540b6b9102..76c12a24e8 100644
--- a/ext/tk/lib/tkextlib/blt/vector.rb
+++ b/ext/tk/lib/tkextlib/blt/vector.rb
@@ -23,14 +23,17 @@ module Tk::BLT
end
def self.names(pat=None)
- simplelist(tk_call('::blt::vector', 'names', pat)).collect{|name|
- if TkVar_ID_TBL[name]
- TkVar_ID_TBL[name]
- elsif name[0..1] == '::' && TkVar_ID_TBL[name[2..-1]]
- TkVar_ID_TBL[name[2..-1]]
- else
- name
- end
+ list = simplelist(tk_call('::blt::vector', 'names', pat))
+ TkVar_ID_TBL.mutex.synchronize{
+ list.collect{|name|
+ if TkVar_ID_TBL[name]
+ TkVar_ID_TBL[name]
+ elsif name[0..1] == '::' && TkVar_ID_TBL[name[2..-1]]
+ TkVar_ID_TBL[name[2..-1]]
+ else
+ name
+ end
+ }
}
end
@@ -53,7 +56,9 @@ module Tk::BLT
"#auto", *hash_kv(keys))
end
- TkVar_ID_TBL[@id] = self
+ TkVar_ID_TBL.mutex.synchronize{
+ TkVar_ID_TBL[@id] = self
+ }
@def_default = false
@default_val = nil
@@ -221,13 +226,21 @@ module Tk::BLT
class VectorAccess < Vector
def self.new(name)
- return TkVar_ID_TBL[name] if TkVar_ID_TBL[name]
- super(name, size=nil, keys={})
+ TkVar_ID_TBL.mutex.synchronize{
+ if TkVar_ID_TBL[name]
+ TkVar_ID_TBL[name]
+ else
+ (obj = self.allocate).instance_eval{
+ initialize(name)
+ TkVar_ID_TBL[@id] = self
+ }
+ obj
+ end
+ }
end
def initialize(vec_name)
@id = vec_name
- TkVar_ID_TBL[@id] = self
@def_default = false
@default_val = nil
diff --git a/ext/tk/lib/tkextlib/blt/watch.rb b/ext/tk/lib/tkextlib/blt/watch.rb
index ae5e50f126..219ff78e97 100644
--- a/ext/tk/lib/tkextlib/blt/watch.rb
+++ b/ext/tk/lib/tkextlib/blt/watch.rb
@@ -13,11 +13,23 @@ module Tk::BLT
TkCommandNames = ['::blt::watch'.freeze].freeze
WATCH_ID_TBL = TkCore::INTERP.create_table
- BLT_WATCH_ID = ['blt_watch_id'.freeze, '00000'.taint].freeze
+
+ (BLT_WATCH_ID = ['blt_watch_id'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ WATCH_ID_TBL.mutex.synchronize{ WATCH_ID_TBL.clear }
+ }
def self.names(state = None)
- tk_split_list(tk_call('::blt::watch', 'names', state)).collect{|name|
- WATCH_ID_TBL[name] || name
+ lst = tk_split_list(tk_call('::blt::watch', 'names', state))
+ WATCH_ID_TBL.mutex.synchronize{
+ lst.collect{|name|
+ WATCH_ID_TBL[name] || name
+ }
}
end
@@ -45,13 +57,17 @@ module Tk::BLT
if name
@id = name.to_s
else
- @id = BLT_WATCH_ID.join(TkCore::INTERP._ip_id_)
- BLT_WATCH_ID[1].succ!
+ BLT_WATCH_ID.mutex.synchronize{
+ @id = BLT_WATCH_ID.join(TkCore::INTERP._ip_id_)
+ BLT_WATCH_ID[1].succ!
+ }
end
@path = @id
- WATCH_ID_TBL[@id] = self
+ WATCH_ID_TBL.mutex.synchronize{
+ WATCH_ID_TBL[@id] = self
+ }
tk_call('::blt::watch', 'create', @id, *hash_kv(keys))
end
@@ -130,7 +146,7 @@ module Tk::BLT
end
end
end
- def cget(key)
+ def cget_strict(key)
key = key.to_s
begin
info.assoc(key)[1]
@@ -138,5 +154,22 @@ module Tk::BLT
fail ArgumentError, "unknown option '#{key}'"
end
end
+ def cget(key)
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ cget_strict(key)
+ else
+ begin
+ cget_strict(key)
+ rescue => e
+ if current_configinfo.has_key?(key.to_s)
+ # error on known option
+ fail e
+ else
+ # unknown option
+ nil
+ end
+ end
+ end
+ end
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/button.rb b/ext/tk/lib/tkextlib/bwidget/button.rb
index 4a9d4a7948..8f3087d098 100644
--- a/ext/tk/lib/tkextlib/bwidget/button.rb
+++ b/ext/tk/lib/tkextlib/bwidget/button.rb
@@ -9,7 +9,7 @@ require 'tkextlib/bwidget.rb'
module Tk
module BWidget
- class Button < TkButton
+ class Button < Tk::Button
end
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/buttonbox.rb b/ext/tk/lib/tkextlib/bwidget/buttonbox.rb
index ef999239f9..8d6d212189 100644
--- a/ext/tk/lib/tkextlib/bwidget/buttonbox.rb
+++ b/ext/tk/lib/tkextlib/bwidget/buttonbox.rb
@@ -31,7 +31,7 @@ class Tk::BWidget::ButtonBox
name = tagOrId[:name]
return index(name) unless name.empty?
end
- if tagOrId.kind_of?(TkButton)
+ if tagOrId.kind_of?(Tk::Button)
return index(tagOrId[:text])
end
# index(tagOrId.to_s)
@@ -40,7 +40,13 @@ class Tk::BWidget::ButtonBox
def add(keys={}, &b)
win = window(tk_send('add', *hash_kv(keys)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
@@ -54,7 +60,7 @@ class Tk::BWidget::ButtonBox
name = idx[:name]
idx = name unless name.empty?
end
- if idx.kind_of?(TkButton)
+ if idx.kind_of?(Tk::Button)
idx = idx[:text]
end
number(tk_send('index', idx.to_s))
@@ -62,7 +68,13 @@ class Tk::BWidget::ButtonBox
def insert(idx, keys={}, &b)
win = window(tk_send('insert', tagid(idx), *hash_kv(keys)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/combobox.rb b/ext/tk/lib/tkextlib/bwidget/combobox.rb
index 31f71c3aaf..1c58a4ccb0 100644
--- a/ext/tk/lib/tkextlib/bwidget/combobox.rb
+++ b/ext/tk/lib/tkextlib/bwidget/combobox.rb
@@ -25,7 +25,13 @@ class Tk::BWidget::ComboBox
def get_listbox(&b)
win = window(tk_send_without_enc('getlistbox'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/dialog.rb b/ext/tk/lib/tkextlib/bwidget/dialog.rb
index 2790d88d24..291ca4a962 100644
--- a/ext/tk/lib/tkextlib/bwidget/dialog.rb
+++ b/ext/tk/lib/tkextlib/bwidget/dialog.rb
@@ -59,6 +59,13 @@ class Tk::BWidget::Dialog
end
end
+ def cget_strict(slot)
+ if slot.to_s == 'relative'
+ super('parent')
+ else
+ super(slot)
+ end
+ end
def cget(slot)
if slot.to_s == 'relative'
super('parent')
@@ -103,7 +110,7 @@ class Tk::BWidget::Dialog
name = tagOrId[:name]
return index(name) unless name.empty?
end
- if tagOrId.kind_of?(TkButton)
+ if tagOrId.kind_of?(Tk::Button)
return index(tagOrId[:text])
end
# index(tagOrId.to_s)
@@ -112,19 +119,37 @@ class Tk::BWidget::Dialog
def add(keys={}, &b)
win = window(tk_send('add', *hash_kv(keys)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
def get_frame(&b)
win = window(tk_send('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
def get_buttonbox(&b)
win = window(@path + '.bbox')
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/dynamichelp.rb b/ext/tk/lib/tkextlib/bwidget/dynamichelp.rb
index 224304f2ab..846e58062d 100644
--- a/ext/tk/lib/tkextlib/bwidget/dynamichelp.rb
+++ b/ext/tk/lib/tkextlib/bwidget/dynamichelp.rb
@@ -34,6 +34,13 @@ module Tk::BWidget::DynamicHelp
['DynamicHelp::configure']
end
+ def self.cget_strict(slot)
+ slot = slot.to_s
+ info = {}
+ self.current_configinfo.each{|k,v| info[k.to_s] = v if k.to_s == slot}
+ fail RuntimeError, "unknown option \"-#{slot}\"" if info.empty?
+ info.values[0]
+ end
def self.cget(slot)
self.current_configinfo(slot).values[0]
end
diff --git a/ext/tk/lib/tkextlib/bwidget/entry.rb b/ext/tk/lib/tkextlib/bwidget/entry.rb
index aafb4aa7ff..a56890f4e3 100644
--- a/ext/tk/lib/tkextlib/bwidget/entry.rb
+++ b/ext/tk/lib/tkextlib/bwidget/entry.rb
@@ -9,7 +9,7 @@ require 'tkextlib/bwidget.rb'
module Tk
module BWidget
- class Entry < TkEntry
+ class Entry < Tk::Entry
end
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/label.rb b/ext/tk/lib/tkextlib/bwidget/label.rb
index ce10ecaf8b..88a504aa50 100644
--- a/ext/tk/lib/tkextlib/bwidget/label.rb
+++ b/ext/tk/lib/tkextlib/bwidget/label.rb
@@ -9,7 +9,7 @@ require 'tkextlib/bwidget.rb'
module Tk
module BWidget
- class Label < TkLabel
+ class Label < Tk::Label
end
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/labelentry.rb b/ext/tk/lib/tkextlib/bwidget/labelentry.rb
index 931feb9b48..95b40946a6 100644
--- a/ext/tk/lib/tkextlib/bwidget/labelentry.rb
+++ b/ext/tk/lib/tkextlib/bwidget/labelentry.rb
@@ -11,7 +11,7 @@ require 'tkextlib/bwidget/entry'
module Tk
module BWidget
- class LabelEntry < TkEntry
+ class LabelEntry < Tk::Entry
end
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/labelframe.rb b/ext/tk/lib/tkextlib/bwidget/labelframe.rb
index f7b267eebb..dc221806e4 100644
--- a/ext/tk/lib/tkextlib/bwidget/labelframe.rb
+++ b/ext/tk/lib/tkextlib/bwidget/labelframe.rb
@@ -40,7 +40,13 @@ class Tk::BWidget::LabelFrame
end
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/listbox.rb b/ext/tk/lib/tkextlib/bwidget/listbox.rb
index 1267500661..093fcb6fb3 100644
--- a/ext/tk/lib/tkextlib/bwidget/listbox.rb
+++ b/ext/tk/lib/tkextlib/bwidget/listbox.rb
@@ -211,14 +211,26 @@ class Tk::BWidget::ListBox::Item
include TkTreatTagFont
ListItem_TBL = TkCore::INTERP.create_table
- ListItem_ID = ['bw:item'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ ListItem_TBL.clear }
+ (ListItem_ID = ['bw:item'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ ListItem_TBL.mutex.synchronize{ ListItem_TBL.clear }
+ }
def self.id2obj(lbox, id)
lpath = lbox.path
- return id unless ListItem_TBL[lpath]
- ListItem_TBL[lpath][id]? ListItem_TBL[lpath][id]: id
+ ListItem_TBL.mutex.synchronize{
+ if ListItem_TBL[lpath]
+ ListItem_TBL[lpath][id]? ListItem_TBL[lpath][id]: id
+ else
+ id
+ end
+ }
end
def initialize(lbox, *args)
@@ -250,13 +262,17 @@ class Tk::BWidget::ListBox::Item
if keys.key?('itemname')
@path = @id = keys.delete('itemname')
else
- @path = @id = ListItem_ID.join(TkCore::INTERP._ip_id_)
- ListItem_ID[1].succ!
+ ListItem_ID.mutex.synchronize{
+ @path = @id = ListItem_ID.join(TkCore::INTERP._ip_id_)
+ ListItem_ID[1].succ!
+ }
end
- ListItem_TBL[@id] = self
- ListItem_TBL[@lpath] = {} unless ListItem_TBL[@lpath]
- ListItem_TBL[@lpath][@id] = self
+ ListItem_TBL.mutex.synchronize{
+ ListItem_TBL[@id] = self
+ ListItem_TBL[@lpath] = {} unless ListItem_TBL[@lpath]
+ ListItem_TBL[@lpath][@id] = self
+ }
@listbox.insert(index, @id, keys)
end
@@ -281,6 +297,9 @@ class Tk::BWidget::ListBox::Item
def cget(key)
@listbox.itemcget(@id, key)
end
+ def cget_strict(key)
+ @listbox.itemcget_strict(@id, key)
+ end
def configure(key, val=None)
@listbox.itemconfigure(@id, key, val)
diff --git a/ext/tk/lib/tkextlib/bwidget/mainframe.rb b/ext/tk/lib/tkextlib/bwidget/mainframe.rb
index c54e878557..de66eaf81e 100644
--- a/ext/tk/lib/tkextlib/bwidget/mainframe.rb
+++ b/ext/tk/lib/tkextlib/bwidget/mainframe.rb
@@ -41,37 +41,73 @@ class Tk::BWidget::MainFrame
def add_indicator(keys={}, &b)
win = window(tk_send('addindicator', *hash_kv(keys)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
def add_toolbar(&b)
win = window(tk_send('addtoolbar'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
def get_frame(&b)
win = window(tk_send('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
def get_indicator(idx, &b)
win = window(tk_send('getindicator', idx))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
def get_menu(menu_id, &b)
win = window(tk_send('getmenu', menu_id))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
def get_toolbar(idx, &b)
win = window(tk_send('gettoolbar', idx))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/messagedlg.rb b/ext/tk/lib/tkextlib/bwidget/messagedlg.rb
index 9c946d0630..b88461baf7 100644
--- a/ext/tk/lib/tkextlib/bwidget/messagedlg.rb
+++ b/ext/tk/lib/tkextlib/bwidget/messagedlg.rb
@@ -65,6 +65,17 @@ class Tk::BWidget::MessageDlg
end
@keys[slot]
end
+ def cget_strict(slot)
+ slot = slot.to_s
+ if slot == 'relative'
+ slot = 'parent'
+ end
+ if winfo_exist?
+ val = super(slot)
+ @keys[slot] = val
+ end
+ @keys[slot]
+ end
def configure(slot, value=None)
if winfo_exist?
@@ -173,6 +184,9 @@ class Tk::BWidget::MessageDlg
end
def create
- num_or_str(tk_call(self.class::TkCommandNames[0], @path, *hash_kv(@keys)))
+ # return the index of the pressed button, or nil if it is destroyed
+ ret = num_or_str(tk_call(self.class::TkCommandNames[0],
+ @path, *hash_kv(@keys)))
+ (ret < 0)? nil: ret
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/notebook.rb b/ext/tk/lib/tkextlib/bwidget/notebook.rb
index 5146d4915d..423943619c 100644
--- a/ext/tk/lib/tkextlib/bwidget/notebook.rb
+++ b/ext/tk/lib/tkextlib/bwidget/notebook.rb
@@ -89,7 +89,13 @@ class Tk::BWidget::NoteBook
def add(page, &b)
win = window(tk_send('add', tagid(page)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
@@ -105,7 +111,13 @@ class Tk::BWidget::NoteBook
def get_frame(page, &b)
win = window(tk_send('getframe', tagid(page)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
@@ -115,7 +127,13 @@ class Tk::BWidget::NoteBook
def insert(index, page, keys={}, &b)
win = window(tk_send('insert', index, tagid(page), *hash_kv(keys)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb b/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb
index fc01284be6..fbc2c11255 100644
--- a/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb
+++ b/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb
@@ -26,7 +26,13 @@ class Tk::BWidget::PagesManager
def add(page, &b)
win = window(tk_send('add', tagid(page)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
@@ -42,7 +48,13 @@ class Tk::BWidget::PagesManager
def get_frame(page, &b)
win = window(tk_send('getframe', tagid(page)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/panedwindow.rb b/ext/tk/lib/tkextlib/bwidget/panedwindow.rb
index 19982c6095..4d979fd523 100644
--- a/ext/tk/lib/tkextlib/bwidget/panedwindow.rb
+++ b/ext/tk/lib/tkextlib/bwidget/panedwindow.rb
@@ -25,7 +25,13 @@ class Tk::BWidget::PanedWindow
def get_frame(idx, &b)
win = window(tk_send_without_enc('getframe', idx))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/panelframe.rb b/ext/tk/lib/tkextlib/bwidget/panelframe.rb
index 13f8817d74..84bae0768b 100644
--- a/ext/tk/lib/tkextlib/bwidget/panelframe.rb
+++ b/ext/tk/lib/tkextlib/bwidget/panelframe.rb
@@ -36,7 +36,13 @@ class Tk::BWidget::PanelFrame
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/progressdlg.rb b/ext/tk/lib/tkextlib/bwidget/progressdlg.rb
index fbf00f3b00..32600255d5 100644
--- a/ext/tk/lib/tkextlib/bwidget/progressdlg.rb
+++ b/ext/tk/lib/tkextlib/bwidget/progressdlg.rb
@@ -51,4 +51,8 @@ class Tk::BWidget::ProgressDlg
def value= (val)
@keys['variable'].value = val
end
+
+ def create
+ window(tk_call(self.class::TkCommandNames[0], @path, *hash_kv(@keys)))
+ end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb b/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb
index a3986681a5..010c960ec5 100644
--- a/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb
+++ b/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb
@@ -23,7 +23,13 @@ class Tk::BWidget::ScrollableFrame
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb b/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb
index e9e53235b7..3599fd8459 100644
--- a/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb
+++ b/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb
@@ -21,7 +21,13 @@ class Tk::BWidget::ScrolledWindow
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/selectcolor.rb b/ext/tk/lib/tkextlib/bwidget/selectcolor.rb
index 742a84cd84..0f9014f8de 100644
--- a/ext/tk/lib/tkextlib/bwidget/selectcolor.rb
+++ b/ext/tk/lib/tkextlib/bwidget/selectcolor.rb
@@ -10,6 +10,11 @@ require 'tkextlib/bwidget/messagedlg'
module Tk
module BWidget
class SelectColor < Tk::BWidget::MessageDlg
+ class Dialog < Tk::BWidget::SelectColor
+ end
+ class Menubutton < Tk::Menubutton
+ end
+ MenuButton = Menubutton
end
end
end
@@ -43,3 +48,26 @@ class Tk::BWidget::SelectColor
tk_call('SelectColor::setcolor', idx, color)
end
end
+
+class Tk::BWidget::SelectColor::Dialog
+ def create_self(keys)
+ super(keys)
+ @keys['type'] = 'dialog'
+ end
+
+ def create
+ @keys['type'] = 'dialog' # 'dialog' type returns color
+ tk_call(Tk::BWidget::SelectColor::TkCommandNames[0],
+ @path, *hash_kv(@keys))
+ end
+end
+
+class Tk::BWidget::SelectColor::Menubutton
+ def create_self(keys)
+ keys = {} unless keys
+ keys = _symbolkey2str(keys)
+ keys['type'] = 'menubutton' # 'toolbar' type returns widget path
+ window(tk_call(Tk::BWidget::SelectColor::TkCommandNames[0],
+ @path, *hash_kv(keys)))
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/selectfont.rb b/ext/tk/lib/tkextlib/bwidget/selectfont.rb
index 478787602a..e53eb3b5bc 100644
--- a/ext/tk/lib/tkextlib/bwidget/selectfont.rb
+++ b/ext/tk/lib/tkextlib/bwidget/selectfont.rb
@@ -66,7 +66,7 @@ class Tk::BWidget::SelectFont::Dialog
end
def create
- @keys['type'] = 'dialog'
+ @keys['type'] = 'dialog' # 'dialog' type returns font name
tk_call(Tk::BWidget::SelectFont::TkCommandNames[0], @path, *hash_kv(@keys))
end
end
@@ -79,7 +79,8 @@ class Tk::BWidget::SelectFont::Toolbar
def create_self(keys)
keys = {} unless keys
keys = _symbolkey2str(keys)
- keys['type'] = 'toolbar'
- tk_call(Tk::BWidget::SelectFont::TkCommandNames[0], @path, *hash_kv(keys))
+ keys['type'] = 'toolbar' # 'toolbar' type returns widget path
+ window(tk_call(Tk::BWidget::SelectFont::TkCommandNames[0],
+ @path, *hash_kv(keys)))
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/spinbox.rb b/ext/tk/lib/tkextlib/bwidget/spinbox.rb
index ca4c046e5c..48358baa5c 100644
--- a/ext/tk/lib/tkextlib/bwidget/spinbox.rb
+++ b/ext/tk/lib/tkextlib/bwidget/spinbox.rb
@@ -10,7 +10,7 @@ require 'tkextlib/bwidget/entry'
module Tk
module BWidget
- class SpinBox < TkEntry
+ class SpinBox < Tk::Entry
end
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/statusbar.rb b/ext/tk/lib/tkextlib/bwidget/statusbar.rb
index df16e4c0b7..39c678d37e 100644
--- a/ext/tk/lib/tkextlib/bwidget/statusbar.rb
+++ b/ext/tk/lib/tkextlib/bwidget/statusbar.rb
@@ -36,7 +36,13 @@ class Tk::BWidget::StatusBar
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/titleframe.rb b/ext/tk/lib/tkextlib/bwidget/titleframe.rb
index f519490430..68534e66e9 100644
--- a/ext/tk/lib/tkextlib/bwidget/titleframe.rb
+++ b/ext/tk/lib/tkextlib/bwidget/titleframe.rb
@@ -21,7 +21,13 @@ class Tk::BWidget::TitleFrame
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/tree.rb b/ext/tk/lib/tkextlib/bwidget/tree.rb
index e7178debe2..aed4512a73 100644
--- a/ext/tk/lib/tkextlib/bwidget/tree.rb
+++ b/ext/tk/lib/tkextlib/bwidget/tree.rb
@@ -263,14 +263,26 @@ class Tk::BWidget::Tree::Node
include TkTreatTagFont
TreeNode_TBL = TkCore::INTERP.create_table
- TreeNode_ID = ['bw:node'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ TreeNode_TBL.clear }
+ (TreeNode_ID = ['bw:node'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ TreeNode_TBL.mutex.synchronize{ TreeNode_TBL.clear }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless TreeNode_TBL[tpath]
- TreeNode_TBL[tpath][id]? TreeNode_TBL[tpath][id]: id
+ TreeNode_TBL.mutex.synchronize{
+ if TreeNode_TBL[tpath]
+ TreeNode_TBL[tpath][id]? TreeNode_TBL[tpath][id]: id
+ else
+ id
+ end
+ }
end
def initialize(tree, *args)
@@ -311,13 +323,17 @@ class Tk::BWidget::Tree::Node
if keys.key?('nodename')
@path = @id = keys.delete('nodename')
else
- @path = @id = TreeNode_ID.join(TkCore::INTERP._ip_id_)
- TreeNode_ID[1].succ!
+ TreeNode_ID.mutex.synchronize{
+ @path = @id = TreeNode_ID.join(TkCore::INTERP._ip_id_)
+ TreeNode_ID[1].succ!
+ }
end
- TreeNode_TBL[@id] = self
- TreeNode_TBL[@tpath] = {} unless TreeNode_TBL[@tpath]
- TreeNode_TBL[@tpath][@id] = self
+ TreeNode_TBL.mutex.synchronize{
+ TreeNode_TBL[@id] = self
+ TreeNode_TBL[@tpath] = {} unless TreeNode_TBL[@tpath]
+ TreeNode_TBL[@tpath][@id] = self
+ }
@tree.insert(index, parent, @id, keys)
end
@@ -342,6 +358,9 @@ class Tk::BWidget::Tree::Node
def cget(key)
@tree.itemcget(@id, key)
end
+ def cget_strict(key)
+ @tree.itemcget_strict(@id, key)
+ end
def configure(key, val=None)
@tree.itemconfigure(@id, key, val)
diff --git a/ext/tk/lib/tkextlib/bwidget/widget.rb b/ext/tk/lib/tkextlib/bwidget/widget.rb
index 568e503a8b..a93364b567 100644
--- a/ext/tk/lib/tkextlib/bwidget/widget.rb
+++ b/ext/tk/lib/tkextlib/bwidget/widget.rb
@@ -29,6 +29,13 @@ module Tk::BWidget::Widget
['Widget::configure']
end
+ def self.cget_strict(slot)
+ slot = slot.to_s
+ info = {}
+ self.current_configinfo.each{|k,v| info[k.to_s] = v if k.to_s == slot}
+ fail RuntimeError, "unknown option \"-#{slot}\"" if info.empty?
+ info.values[0]
+ end
def self.cget(slot)
self.current_configinfo(slot).values[0]
end
@@ -43,7 +50,13 @@ module Tk::BWidget::Widget
def self.create(klass, path, rename=None, &b)
win = window(tk_call('Widget::create', klass, path, rename))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
@@ -99,9 +112,12 @@ module Tk::BWidget::Widget
tk_call('Widget::setoption', win, option, value)
end
- def self.sub_cget(win, subwidget)
+ def self.sub_cget_strict(win, subwidget)
tk_call('Widget::subcget', win, subwidget)
end
+ def self.sub_cget(win, subwidget)
+ self.sub_cget_strict(win, subwidget)
+ end
def self.sync_options(klass, subclass, subpath, options)
tk_call('Widget::syncoptions', klass, subclass, subpath, options)
diff --git a/ext/tk/lib/tkextlib/itcl/incr_tcl.rb b/ext/tk/lib/tkextlib/itcl/incr_tcl.rb
index 07abf3a7bf..2b75d62eb9 100644
--- a/ext/tk/lib/tkextlib/itcl/incr_tcl.rb
+++ b/ext/tk/lib/tkextlib/itcl/incr_tcl.rb
@@ -40,16 +40,22 @@ module Tk
class ItclObject < TkObject
ITCL_CLASSNAME = ''.freeze
- ITCL_OBJ_ID = ['itclobj'.freeze, '00000'.taint].freeze
+ (ITCL_OBJ_ID = ['itclobj'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
ITCL_OBJ_TBL = {}.taint
def initialize(*args)
if (@klass = self.class::ITCL_CLASSNAME).empty?
fail RuntimeError, 'unknown itcl class (abstract class?)'
end
- @id = Tk::Itcl::ItclObject::TCL_OBJ_ID.join(TkCore::INTERP._ip_id_)
+ Tk::Itcl::ItclObject::ITCL_OBJ_ID.mutex.synchronize{
+ @id = Tk::Itcl::ItclObject::TCL_OBJ_ID.join(TkCore::INTERP._ip_id_)
+ Tk::Itcl::ItclObject::ITCL_OBJ_ID[1].succ!
+ }
@path = @id
- Tk::Itcl::ItclObject::ITCL_OBJ_ID[1].succ!
end
def self.call_proc(name, *args)
diff --git a/ext/tk/lib/tkextlib/itk/incr_tk.rb b/ext/tk/lib/tkextlib/itk/incr_tk.rb
index 0626536e36..e06deb552c 100644
--- a/ext/tk/lib/tkextlib/itk/incr_tk.rb
+++ b/ext/tk/lib/tkextlib/itk/incr_tk.rb
@@ -145,9 +145,16 @@ module Tk
private :__config_cmd
ComponentID_TBL = TkCore::INTERP.create_table
- Itk_Component_ID = ['itk:component'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ ComponentID_TBL.clear }
+ (Itk_Component_ID = ['itk:component'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ ComponentID_TBL.mutex.synchronize{ ComponentID_TBL.clear }
+ }
def self.id2obj(master, id)
if master.kind_of?(TkObject)
@@ -155,8 +162,13 @@ module Tk
else
master = master.to_s
end
- return id unless ComponentID_TBL.key?(master)
- (ComponentID_TBL.key?(id))? ComponentID_TBL[master][id]: id
+ ComponentID_TBL.mutex.synchronize{
+ if ComponentID_TBL.key?(master)
+ (ComponentID_TBL[master].key?(id))? ComponentID_TBL[master][id]: id
+ else
+ id
+ end
+ }
end
def self.new(master, component=nil)
@@ -171,17 +183,21 @@ module Tk
elsif component
component = component.to_s
else
- component = Itk_Component_ID.join(TkCore::INTERP._ip_id_)
- Itk_Component_ID[1].succ!
+ Itk_Component_ID.mutex.synchronize{
+ component = Itk_Component_ID.join(TkCore::INTERP._ip_id_)
+ Itk_Component_ID[1].succ!
+ }
end
- if ComponentID_TBL.key?(master)
- if ComponentID_TBL[master].key?(component)
- return ComponentID_TBL[master][component]
+ ComponentID_TBL.mutex.synchronize{
+ if ComponentID_TBL.key?(master)
+ if ComponentID_TBL[master].key?(component)
+ return ComponentID_TBL[master][component]
+ end
+ else
+ ComponentID_TBL[master] = {}
end
- else
- ComponentID_TBL[master] = {}
- end
+ }
super(master, component)
end
@@ -190,7 +206,9 @@ module Tk
@master = master
@component = component
- ComponentID_TBL[@master][@component] = self
+ ComponentID_TBL.mutex.synchronize{
+ ComponentID_TBL[@master][@component] = self
+ }
begin
@widget = window(tk_call(@master, 'component', @component))
diff --git a/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb b/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb
index a055e07ac9..05d58c386f 100644
--- a/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb
@@ -47,12 +47,13 @@ class Tk::Iwidgets::Buttonbox
end
alias buttoncget itemcget
+ alias buttoncget_strict itemcget_strict
alias buttonconfigure itemconfigure
alias buttonconfiginfo itemconfiginfo
alias current_buttonconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
diff --git a/ext/tk/lib/tkextlib/iwidgets/calendar.rb b/ext/tk/lib/tkextlib/iwidgets/calendar.rb
index 0152f8593a..8495f0e29b 100644
--- a/ext/tk/lib/tkextlib/iwidgets/calendar.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/calendar.rb
@@ -45,6 +45,25 @@ class Tk::Iwidgets::Calendar
class ValidateArgs < TkUtil::CallbackSubst
KEY_TBL = [ [?d, ?s, :date], nil ]
PROC_TBL = [ [?s, TkComm.method(:string) ], nil ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
diff --git a/ext/tk/lib/tkextlib/iwidgets/checkbox.rb b/ext/tk/lib/tkextlib/iwidgets/checkbox.rb
index abd23299a8..c85d356c55 100644
--- a/ext/tk/lib/tkextlib/iwidgets/checkbox.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/checkbox.rb
@@ -47,12 +47,13 @@ class Tk::Iwidgets::Checkbox
end
alias buttoncget itemcget
+ alias buttoncget_strict itemcget_strict
alias buttonconfigure itemconfigure
alias buttonconfiginfo itemconfiginfo
alias current_buttonconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
@@ -85,12 +86,24 @@ class Tk::Iwidgets::Checkbox
self
end
- def get(idx)
- simplelist(tk_call(@path, 'get', index(idx))).collect{|id|
- Tk::Itk::Component.id2obj(id)
+ def get_tags
+ simplelist(tk_call_without_enc(@path, 'get'))
+ end
+
+ def get_objs
+ simplelist(tk_call_without_enc(@path, 'get')).collect{|id|
+ Tk::Itk::Component.id2obj(self, id)
}
end
+ def get(idx=nil)
+ if idx
+ bool(tk_call_without_enc(@path, 'get', index(idx)))
+ else
+ get_tags
+ end
+ end
+
def index(idx)
number(tk_call(@path, 'index', tagid(idx)))
end
diff --git a/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb b/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb
index d6c668621d..8d43cc07ab 100644
--- a/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb
@@ -47,12 +47,13 @@ class Tk::Iwidgets::Dialogshell
end
alias buttoncget itemcget
+ alias buttoncget_strict itemcget_strict
alias buttonconfigure itemconfigure
alias buttonconfiginfo itemconfiginfo
alias current_buttonconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
diff --git a/ext/tk/lib/tkextlib/iwidgets/entryfield.rb b/ext/tk/lib/tkextlib/iwidgets/entryfield.rb
index 6aa933ce06..d53df216bf 100644
--- a/ext/tk/lib/tkextlib/iwidgets/entryfield.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/entryfield.rb
@@ -42,6 +42,25 @@ class Tk::Iwidgets::Entryfield
[ ?w, TkComm.method(:window) ],
nil
]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
_setup_subst_table(KEY_TBL, PROC_TBL);
end
diff --git a/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb b/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb
index 4cc6aeecbd..d9220fecbf 100644
--- a/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb
@@ -30,6 +30,25 @@ class Tk::Iwidgets::Hierarchy
class ValidateArgs < TkUtil::CallbackSubst
KEY_TBL = [ [?n, ?s, :node], nil ]
PROC_TBL = [ [?s, TkComm.method(:string) ], nil ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
@@ -57,6 +76,24 @@ class Tk::Iwidgets::Hierarchy
nil
]
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
@@ -78,6 +115,25 @@ class Tk::Iwidgets::Hierarchy
nil
]
PROC_TBL = [ [ ?s, TkComm.method(:string) ], nil ]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
@@ -207,7 +263,7 @@ class Tk::Iwidgets::Hierarchy
self
end
- # based on TkText widget
+ # based on Tk::Text widget
def bbox(index)
list(tk_send_without_enc('bbox', _get_eval_enc_str(index)))
diff --git a/ext/tk/lib/tkextlib/iwidgets/menubar.rb b/ext/tk/lib/tkextlib/iwidgets/menubar.rb
index dea3d34c2a..5aaefbe50d 100644
--- a/ext/tk/lib/tkextlib/iwidgets/menubar.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/menubar.rb
@@ -62,12 +62,13 @@ class Tk::Iwidgets::Menubar
end
alias menucget itemcget
+ alias menucget_strict itemcget_strict
alias menuconfigure itemconfigure
alias menuconfiginfo itemconfiginfo
alias current_menuconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
diff --git a/ext/tk/lib/tkextlib/iwidgets/messagebox.rb b/ext/tk/lib/tkextlib/iwidgets/messagebox.rb
index 2bbbec7666..98ac32900c 100644
--- a/ext/tk/lib/tkextlib/iwidgets/messagebox.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/messagebox.rb
@@ -47,12 +47,13 @@ class Tk::Iwidgets::Messagebox
private :__item_boolval_optkeys
alias typecget itemcget
+ alias typecget_strict itemcget_strict
alias typeconfigure itemconfigure
alias typeconfiginfo itemconfiginfo
alias current_typeconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
diff --git a/ext/tk/lib/tkextlib/iwidgets/notebook.rb b/ext/tk/lib/tkextlib/iwidgets/notebook.rb
index 0f9d713ea1..03b50633df 100644
--- a/ext/tk/lib/tkextlib/iwidgets/notebook.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/notebook.rb
@@ -42,12 +42,13 @@ class Tk::Iwidgets::Notebook
end
alias pagecget itemcget
+ alias pagecget_strict itemcget_strict
alias pageconfigure itemconfigure
alias pageconfiginfo itemconfiginfo
alias current_pageconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
@@ -146,7 +147,12 @@ class Tk::Iwidgets::Notebook
def view(*idxs)
if idxs.size == 0
- window(tk_send_without_enc('view'))
+ idx = num_or_str(tk_send_without_enc('view'))
+ if idx.kind_of?(Fixnum) && idx < 0
+ nil
+ else
+ idx
+ end
else
tk_send_without_enc('view', *idxs)
self
@@ -160,8 +166,8 @@ class Tk::Iwidgets::Notebook
end
alias xview_moveto view_moveto
alias yview_moveto view_moveto
- def view_scroll(*idxs)
- view('scroll', *idxs)
+ def view_scroll(index, what='pages')
+ view('scroll', index, what)
end
alias xview_scroll view_scroll
alias yview_scroll view_scroll
diff --git a/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb b/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb
index 035df0a5b8..3bf73d69fe 100644
--- a/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb
@@ -42,12 +42,13 @@ class Tk::Iwidgets::Panedwindow
end
alias panecget itemcget
+ alias panecget_strict itemcget_strict
alias paneconfigure itemconfigure
alias paneconfiginfo itemconfiginfo
alias current_paneconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
diff --git a/ext/tk/lib/tkextlib/iwidgets/radiobox.rb b/ext/tk/lib/tkextlib/iwidgets/radiobox.rb
index d4316754f2..e9d9521252 100644
--- a/ext/tk/lib/tkextlib/iwidgets/radiobox.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/radiobox.rb
@@ -47,12 +47,13 @@ class Tk::Iwidgets::Radiobox
end
alias buttoncget itemcget
+ alias buttoncget_strict itemcget_strict
alias buttonconfigure itemconfigure
alias buttonconfiginfo itemconfiginfo
alias current_buttonconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
@@ -85,10 +86,13 @@ class Tk::Iwidgets::Radiobox
self
end
- def get(idx)
- simplelist(tk_call(@path, 'get', index(idx))).collect{|id|
- Tk::Itk::Component.id2obj(id)
- }
+ def get_tag
+ ((tag = tk_call_without_enc(@path, 'get')).empty?)? nil: tag
+ end
+ alias get get_tag
+
+ def get_obj
+ (tag = get_tag)? Tk::Itk::Component.id2obj(self, tag): nil
end
def index(idx)
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb
index 407c8f2aad..67ad67d07e 100644
--- a/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb
@@ -37,7 +37,7 @@ class Tk::Iwidgets::Scrolledcanvas
end
def method_missing(id, *args)
- if @canvas.methods.include?(id.id2name)
+ if @canvas.respond_to?(id)
@canvas.__send__(id, *args)
else
super(id, *args)
@@ -171,10 +171,16 @@ class Tk::Iwidgets::Scrolledcanvas
end
def delete(*args)
- if TkcItem::CItemID_TBL[self.path]
+ tbl = nil
+ TkcItem::CItemID_TBL.mutex.synchronize{
+ tbl = TkcItem::CItemID_TBL[self.path]
+ }
+ if tbl
find('withtag', *args).each{|item|
if item.kind_of?(TkcItem)
- TkcItem::CItemID_TBL[self.path].delete(item.id)
+ TkcItem::CItemID_TBL.mutex.synchronize{
+ tbl.delete(item.id)
+ }
end
}
end
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb
index cd1f6f0f79..7543d557e3 100644
--- a/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb
@@ -42,7 +42,7 @@ class Tk::Iwidgets::Scrolledlistbox
end
def method_missing(id, *args)
- if @listbox.methods.include?(id.id2name)
+ if @listbox.respond_to?(id)
@listbox.__send__(id, *args)
else
super(id, *args)
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb
index fdafc8dc7f..d6436d202a 100644
--- a/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb
@@ -37,7 +37,7 @@ class Tk::Iwidgets::Scrolledtext
end
def method_missing(id, *args)
- if @text.methods.include?(id.id2name)
+ if @text.respond_to?(id)
@text.__send__(id, *args)
else
super(id, *args)
@@ -116,7 +116,7 @@ class Tk::Iwidgets::Scrolledtext
get('-displaychars', *index)
end
- def image_cget(index, slot)
+ def image_cget_strict(index, slot)
case slot.to_s
when 'text', 'label', 'show', 'data', 'file'
_fromUTF8(tk_send_without_enc('image', 'cget',
@@ -127,6 +127,27 @@ class Tk::Iwidgets::Scrolledtext
"-#{slot}")))
end
end
+ def image_cget(index, slot)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ image_cget_strict(index, slot)
+ else
+ begin
+ image_cget_strict(index, slot)
+ rescue => e
+ begin
+ if current_image_configinfo.has_key?(slot.to_s)
+ # error on known option
+ fail e
+ else
+ # unknown option
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
def image_configure(index, slot, value=None)
if slot.kind_of? Hash
@@ -322,6 +343,11 @@ class Tk::Iwidgets::Scrolledtext
def _ktext_length(txt)
+ if TkCore::WITH_ENCODING ### Ruby 1.9 !!!!!!!!!!!!!
+ return txt.length
+ end
+ ###########################
+
if $KCODE !~ /n/i
return txt.gsub(/[^\Wa-zA-Z_\d]/, ' ').length
end
diff --git a/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb b/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb
index bb81fcca5e..bf9b5ec30a 100644
--- a/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb
@@ -59,7 +59,7 @@ class Tk::Iwidgets::Selectionbox
self
end
- # based on TkListbox ( and TkTextWin )
+ # based on Tk::Listbox ( and TkTextWin )
def curselection
list(tk_send_without_enc('curselection'))
end
diff --git a/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb b/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb
index ab790e97a6..f772ecf8c2 100644
--- a/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb
@@ -49,7 +49,7 @@ class Tk::Iwidgets::Selectiondialog
self
end
- # based on TkListbox ( and TkTextWin )
+ # based on Tk::Listbox ( and TkTextWin )
def curselection
list(tk_send_without_enc('curselection'))
end
diff --git a/ext/tk/lib/tkextlib/iwidgets/spinner.rb b/ext/tk/lib/tkextlib/iwidgets/spinner.rb
index 174b9bd506..aeee5c9038 100644
--- a/ext/tk/lib/tkextlib/iwidgets/spinner.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/spinner.rb
@@ -37,6 +37,25 @@ class Tk::Iwidgets::Spinner
[ ?w, TkComm.method(:window) ],
nil
]
+
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
_setup_subst_table(KEY_TBL, PROC_TBL);
end
diff --git a/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb b/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb
index 0d9715f87b..dbb90e5102 100644
--- a/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb
@@ -47,12 +47,13 @@ class Tk::Iwidgets::Tabnotebook
end
alias pagecget itemcget
+ alias pagecget_strict itemcget_strict
alias pageconfigure itemconfigure
alias pageconfiginfo itemconfiginfo
alias current_pageconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
@@ -116,6 +117,11 @@ class Tk::Iwidgets::Tabnotebook
self
end
+ def show_tab(idx)
+ @tabset.show_tab(idx)
+ self
+ end
+
def scrollcommand(cmd=Proc.new)
configure_cmd 'scrollcommand', cmd
self
@@ -147,7 +153,12 @@ class Tk::Iwidgets::Tabnotebook
def view(*index)
if index.size == 0
- window(tk_send_without_enc('view'))
+ idx = num_or_str(tk_send_without_enc('view'))
+ if idx.kind_of?(Fixnum) && idx < 0
+ nil
+ else
+ idx
+ end
else
tk_send_without_enc('view', *index)
self
@@ -161,8 +172,8 @@ class Tk::Iwidgets::Tabnotebook
end
alias xview_moveto view_moveto
alias yview_moveto view_moveto
- def view_scroll(*index)
- view('scroll', *index)
+ def view_scroll(index, what='pages')
+ view('scroll', index, what)
end
alias xview_scroll view_scroll
alias yview_scroll view_scroll
diff --git a/ext/tk/lib/tkextlib/iwidgets/tabset.rb b/ext/tk/lib/tkextlib/iwidgets/tabset.rb
index 54e56d0514..300ba9dee0 100644
--- a/ext/tk/lib/tkextlib/iwidgets/tabset.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/tabset.rb
@@ -42,12 +42,13 @@ class Tk::Iwidgets::Tabset
end
alias tabcget itemcget
+ alias tabcget_strict itemcget_strict
alias tabconfigure itemconfigure
alias tabconfiginfo itemconfiginfo
alias current_tabconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
@@ -96,4 +97,48 @@ class Tk::Iwidgets::Tabset
tk_call(@path, 'select', index(idx))
self
end
+
+ def show_tab(idx)
+ if index(idx) == 0
+ self.start = 0
+ return
+ end
+
+ reutrn unless @canvas ||= self.winfo_children[0]
+
+ delta = 1 if (delta = cget(:gap)) == 'overlap' ||
+ (delta = self.winfo_pixels(delta) + 1) <= 0
+
+ case cget(:tabpos)
+ when 's', 'n'
+ if (head = tabcget(idx, :left)) < 0
+ self.start -= head
+ return
+ end
+ tabs_size = @canvas.winfo_width
+ tab_start, tab_end = @canvas .
+ find_overlapping(head, 0, head + delta, @canvas.winfo_height) .
+ find_all{|id| @canvas.itemtype(id) == TkcPolygon} .
+ map!{|id| bbox = @canvas.bbox(id); [bbox[0], bbox[2]]} . max
+
+ when 'e', 'w'
+ if (head = tabcget(idx, :top)) < 0
+ self.start -= head
+ return
+ end
+ tabs_size = @canvas.winfo_height
+ tab_start, tab_end = @canvas .
+ find_overlapping(0, head, @canvas.winfo_width, head + delta) .
+ find_all{|id| @canvas.itemtype(id) == TkcPolygon} .
+ map!{|id| bbox = @canvas.bbox(id); [bbox[1], bbox[3]]} . max
+ end
+
+ if (size = tab_end - tab_start + 1) > tabs_size
+ self.start -= tab_start
+ elsif head + size > tabs_size
+ self.start -= head + size - tabs_size
+ end
+
+ self
+ end
end
diff --git a/ext/tk/lib/tkextlib/tcllib/autoscroll.rb b/ext/tk/lib/tkextlib/tcllib/autoscroll.rb
index 6940a9174c..7db3c2e2b7 100644
--- a/ext/tk/lib/tkextlib/tcllib/autoscroll.rb
+++ b/ext/tk/lib/tkextlib/tcllib/autoscroll.rb
@@ -108,7 +108,7 @@ module Tk
end
end
-class TkScrollbar
+class Tk::Scrollbar
def autoscroll
# Arranges for the already existing scrollbar to be mapped
# and unmapped as needed.
diff --git a/ext/tk/lib/tkextlib/tcllib/ctext.rb b/ext/tk/lib/tkextlib/tcllib/ctext.rb
index 70a45dd8e7..9014037f3d 100644
--- a/ext/tk/lib/tkextlib/tcllib/ctext.rb
+++ b/ext/tk/lib/tkextlib/tcllib/ctext.rb
@@ -15,7 +15,7 @@ TkPackage.require('ctext')
module Tk
module Tcllib
- class CText < TkText
+ class CText < Tk::Text
PACKAGE_NAME = 'ctext'.freeze
def self.package_name
PACKAGE_NAME
diff --git a/ext/tk/lib/tkextlib/tcllib/datefield.rb b/ext/tk/lib/tkextlib/tcllib/datefield.rb
index bd84488101..2244dd7a9a 100644
--- a/ext/tk/lib/tkextlib/tcllib/datefield.rb
+++ b/ext/tk/lib/tkextlib/tcllib/datefield.rb
@@ -24,7 +24,7 @@ TkPackage.require('datefield')
module Tk
module Tcllib
- class Datefield < TkEntry
+ class Datefield < Tk::Entry
PACKAGE_NAME = 'datefield'.freeze
def self.package_name
PACKAGE_NAME
diff --git a/ext/tk/lib/tkextlib/tcllib/getstring.rb b/ext/tk/lib/tkextlib/tcllib/getstring.rb
index bf5e54e8cf..fc5d8b26d9 100644
--- a/ext/tk/lib/tkextlib/tcllib/getstring.rb
+++ b/ext/tk/lib/tkextlib/tcllib/getstring.rb
@@ -87,7 +87,7 @@ class Tk::Tcllib::GetString_Dialog
@variable.value
end
- def cget(slot)
+ def cget_strict(slot)
slot = slot.to_s
if slot == 'text'
@text
@@ -95,6 +95,9 @@ class Tk::Tcllib::GetString_Dialog
@keys[slot]
end
end
+ def cget(slot)
+ cget_strict(slot)
+ end
def configure(slot, value=None)
if slot.kind_of?(Hash)
diff --git a/ext/tk/lib/tkextlib/tcllib/ico.rb b/ext/tk/lib/tkextlib/tcllib/ico.rb
index 3beeb11a4d..8c92926a4c 100644
--- a/ext/tk/lib/tkextlib/tcllib/ico.rb
+++ b/ext/tk/lib/tkextlib/tcllib/ico.rb
@@ -94,8 +94,10 @@ class Tk::Tcllib::ICO
if keys.key?('name')
@path = keys['name'].to_s
else
- @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_)
- Tk_Image_ID[1].succ!
+ Tk_Image_ID.mutex.synchronize{
+ @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_)
+ Tk_Image_ID[1].succ!
+ }
end
tk_call_without_enc('::ico::getIcon', file, index, '-name', @path,
'-format', 'image', *hash_kv(keys, true))
diff --git a/ext/tk/lib/tkextlib/tcllib/ip_entry.rb b/ext/tk/lib/tkextlib/tcllib/ip_entry.rb
index 8c9e0bd683..c4b8240c04 100644
--- a/ext/tk/lib/tkextlib/tcllib/ip_entry.rb
+++ b/ext/tk/lib/tkextlib/tcllib/ip_entry.rb
@@ -18,7 +18,7 @@ TkPackage.require('ipentry')
module Tk
module Tcllib
- class IP_Entry < TkEntry
+ class IP_Entry < Tk::Entry
PACKAGE_NAME = 'ipentry'.freeze
def self.package_name
PACKAGE_NAME
diff --git a/ext/tk/lib/tkextlib/tcllib/plotchart.rb b/ext/tk/lib/tkextlib/tcllib/plotchart.rb
index f5f344ceb3..06ab20f3e6 100644
--- a/ext/tk/lib/tkextlib/tcllib/plotchart.rb
+++ b/ext/tk/lib/tkextlib/tcllib/plotchart.rb
@@ -225,7 +225,7 @@ module Tk::Tcllib::Plotchart
end
############################
- class XYPlot < TkCanvas
+ class XYPlot < Tk::Canvas
include ChartMethod
TkCommandNames = [
@@ -247,7 +247,7 @@ module Tk::Tcllib::Plotchart
@xaxis = args.shift
@yaxis = args.shift
- if parent.kind_of?(TkCanvas)
+ if parent.kind_of?(Tk::Canvas)
@path = parent.path
else
super(parent, *args) # create canvas widget
@@ -265,7 +265,9 @@ module Tk::Tcllib::Plotchart
private :_create_chart
def __destroy_hook__
- Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ }
end
def plot(series, x, y)
@@ -337,7 +339,7 @@ module Tk::Tcllib::Plotchart
end
############################
- class PolarPlot < TkCanvas
+ class PolarPlot < Tk::Canvas
include ChartMethod
TkCommandNames = [
@@ -356,7 +358,7 @@ module Tk::Tcllib::Plotchart
@radius_data = args.shift
- if parent.kind_of?(TkCanvas)
+ if parent.kind_of?(Tk::Canvas)
@path = parent.path
else
super(parent, *args) # create canvas widget
@@ -374,7 +376,9 @@ module Tk::Tcllib::Plotchart
private :_create_chart
def __destroy_hook__
- Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ }
end
def plot(series, radius, angle)
@@ -395,7 +399,7 @@ module Tk::Tcllib::Plotchart
Polarplot = PolarPlot
############################
- class IsometricPlot < TkCanvas
+ class IsometricPlot < Tk::Canvas
include ChartMethod
TkCommandNames = [
@@ -430,7 +434,7 @@ module Tk::Tcllib::Plotchart
@stepsize = args.shift
end
- if parent.kind_of?(TkCanvas)
+ if parent.kind_of?(Tk::Canvas)
@path = parent.path
else
super(parent, *args) # create canvas widget
@@ -475,7 +479,7 @@ module Tk::Tcllib::Plotchart
Isometricplot = IsometricPlot
############################
- class Plot3D < TkCanvas
+ class Plot3D < Tk::Canvas
include ChartMethod
TkCommandNames = [
@@ -500,7 +504,7 @@ module Tk::Tcllib::Plotchart
@yaxis = args.shift
@zaxis = args.shift
- if parent.kind_of?(TkCanvas)
+ if parent.kind_of?(Tk::Canvas)
@path = parent.path
else
super(parent, *args) # create canvas widget
@@ -557,7 +561,7 @@ module Tk::Tcllib::Plotchart
end
############################
- class Piechart < TkCanvas
+ class Piechart < Tk::Canvas
include ChartMethod
TkCommandNames = [
@@ -566,7 +570,7 @@ module Tk::Tcllib::Plotchart
].freeze
def initialize(*args) # args := ([parent] [, keys])
- if args[0].kind_of?(TkCanvas)
+ if args[0].kind_of?(Tk::Canvas)
parent = args.shift
@path = parent.path
else
@@ -588,7 +592,7 @@ module Tk::Tcllib::Plotchart
end
############################
- class Barchart < TkCanvas
+ class Barchart < Tk::Canvas
include ChartMethod
TkCommandNames = [
@@ -626,7 +630,7 @@ module Tk::Tcllib::Plotchart
@series_size = args.shift
end
- if parent.kind_of?(TkCanvas)
+ if parent.kind_of?(Tk::Canvas)
@path = parent.path
else
super(parent, *args) # create canvas widget
@@ -645,7 +649,9 @@ module Tk::Tcllib::Plotchart
private :_create_chart
def __destroy_hook__
- Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ }
end
def plot(series, dat, col=None)
@@ -672,7 +678,7 @@ module Tk::Tcllib::Plotchart
end
############################
- class Timechart < TkCanvas
+ class Timechart < Tk::Canvas
include ChartMethod
TkCommandNames = [
@@ -699,7 +705,7 @@ module Tk::Tcllib::Plotchart
@time_end = args.shift
@items = args.shift
- if parent.kind_of?(TkCanvas)
+ if parent.kind_of?(Tk::Canvas)
@path = parent.path
else
super(parent, *args) # create canvas widget
@@ -733,7 +739,7 @@ module Tk::Tcllib::Plotchart
end
############################
- class Gnattchart < TkCanvas
+ class Gnattchart < Tk::Canvas
include ChartMethod
TkCommandNames = [
@@ -772,7 +778,7 @@ module Tk::Tcllib::Plotchart
@text_width = None
end
- if parent.kind_of?(TkCanvas)
+ if parent.kind_of?(Tk::Canvas)
@path = parent.path
else
super(parent, *args) # create canvas widget
@@ -834,23 +840,38 @@ module Tk::Tcllib::Plotchart
############################
class PlotSeries < TkObject
SeriesID_TBL = TkCore::INTERP.create_table
- Series_ID = ['series'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ SeriesID_TBL.clear }
+
+ (Series_ID = ['series'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+ TkCore::INTERP.init_ip_env{
+ SeriesID_TBL.mutex.synchronize{ SeriesID_TBL.clear }
+ }
def self.id2obj(chart, id)
path = chart.path
- return id unless SeriesID_TBL[path]
- SeriesID_TBL[path][id]? SeriesID_TBL[path][id]: id
+ SeriesID_TBL.mutex.synchronize{
+ if SeriesID_TBL[path]
+ SeriesID_TBL[path][id]? SeriesID_TBL[path][id]: id
+ else
+ id
+ end
+ }
end
def initialize(chart, keys=nil)
@parent = @chart_obj = chart
@ppath = @chart_obj.path
- @path = @series = @id = Series_ID.join(TkCore::INTERP._ip_id_)
- # SeriesID_TBL[@id] = self
- SeriesID_TBL[@ppath] = {} unless SeriesID_TBL[@ppath]
- SeriesID_TBL[@ppath][@id] = self
- Series_ID[1].succ!
+ Series_ID.mutex.synchronize{
+ @path = @series = @id = Series_ID.join(TkCore::INTERP._ip_id_)
+ Series_ID[1].succ!
+ }
+ SeriesID_TBL.mutex.synchronize{
+ SeriesID_TBL[@ppath] ||= {}
+ SeriesID_TBL[@ppath][@id] = self
+ }
dataconfig(keys) if keys.kind_of?(Hash)
end
diff --git a/ext/tk/lib/tkextlib/tcllib/swaplist.rb b/ext/tk/lib/tkextlib/tcllib/swaplist.rb
index 97de0a27c1..1c813e36da 100644
--- a/ext/tk/lib/tkextlib/tcllib/swaplist.rb
+++ b/ext/tk/lib/tkextlib/tcllib/swaplist.rb
@@ -90,7 +90,7 @@ class Tk::Tcllib::Swaplist_Dialog
end
alias selected value
- def cget(slot)
+ def cget_strict(slot)
slot = slot.to_s
if slot == 'complete_list'
@complete_list
@@ -100,6 +100,9 @@ class Tk::Tcllib::Swaplist_Dialog
@keys[slot]
end
end
+ def cget(slot)
+ cget_strict(slot)
+ end
def configure(slot, value=None)
if slot.kind_of?(Hash)
diff --git a/ext/tk/lib/tkextlib/tcllib/tablelist.rb b/ext/tk/lib/tkextlib/tcllib/tablelist.rb
index 42435a1971..efeb8fbbac 100644
--- a/ext/tk/lib/tkextlib/tcllib/tablelist.rb
+++ b/ext/tk/lib/tkextlib/tcllib/tablelist.rb
@@ -23,5 +23,5 @@ else
# TkPackage.require('Tablelist', '4.2')
TkPackage.require('Tablelist')
- requrie 'tkextlib/tcllib/tablelist_core'
+ require 'tkextlib/tcllib/tablelist_core'
end
diff --git a/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb b/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb
index a939a58331..d7a6c97210 100644
--- a/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb
+++ b/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb
@@ -70,6 +70,9 @@ module Tk::Tcllib::TablelistItemConfig
def cell_cget(tagOrId, option)
itemcget(['cell', tagOrId], option)
end
+ def cell_cget_strict(tagOrId, option)
+ itemcget_strict(['cell', tagOrId], option)
+ end
def cell_configure(tagOrId, slot, value=None)
itemconfigure(['cell', tagOrId], slot, value)
end
@@ -80,6 +83,7 @@ module Tk::Tcllib::TablelistItemConfig
current_itemconfiginfo(['cell', tagOrId], slot)
end
alias cellcget cell_cget
+ alias cellcget_strict cell_cget_strict
alias cellconfigure cell_configure
alias cellconfiginfo cell_configinfo
alias current_cellconfiginfo current_cell_configinfo
@@ -87,6 +91,9 @@ module Tk::Tcllib::TablelistItemConfig
def column_cget(tagOrId, option)
itemcget(['column', tagOrId], option)
end
+ def column_cget_strict(tagOrId, option)
+ itemcget_strict(['column', tagOrId], option)
+ end
def column_configure(tagOrId, slot, value=None)
itemconfigure(['column', tagOrId], slot, value)
end
@@ -97,6 +104,7 @@ module Tk::Tcllib::TablelistItemConfig
current_itemconfiginfo(['column', tagOrId], slot)
end
alias columncget column_cget
+ alias columncget_strict column_cget_strict
alias columnconfigure column_configure
alias columnconfiginfo column_configinfo
alias current_columnconfiginfo current_column_configinfo
@@ -104,6 +112,9 @@ module Tk::Tcllib::TablelistItemConfig
def row_cget(tagOrId, option)
itemcget(['row', tagOrId], option)
end
+ def row_cget_strict(tagOrId, option)
+ itemcget_strict(['row', tagOrId], option)
+ end
def row_configure(tagOrId, slot, value=None)
itemconfigure(['row', tagOrId], slot, value)
end
@@ -114,12 +125,13 @@ module Tk::Tcllib::TablelistItemConfig
current_itemconfiginfo(['row', tagOrId], slot)
end
alias rowcget row_cget
+ alias rowcget_strict row_cget_strict
alias rowconfigure row_configure
alias rowconfiginfo row_configinfo
alias current_rowconfiginfo current_row_configinfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
end
class Tk::Tcllib::Tablelist
diff --git a/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb b/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb
index 92dde65ce7..b366e0198b 100644
--- a/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb
+++ b/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb
@@ -125,7 +125,9 @@ module Tk::Tcllib::Tkpiechart
def delete
tk_call_without_enc('::stooop::delete', @tag_key)
- CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ CItemID_TBL.mutex.synchronize{
+ CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ }
self
end
@@ -184,8 +186,10 @@ module Tk::Tcllib::Tkpiechart
@id = "slices(#{@tag_key})"
@tag = TkcNamedTag.new(@pie.canvas, @id)
- CItemID_TBL[@path] = {} unless CItemID_TBL[@path]
- CItemID_TBL[@path][@id] = self
+ CItemID_TBL.mutex.synchronize{
+ CItemID_TBL[@path] = {} unless CItemID_TBL[@path]
+ CItemID_TBL[@path][@id] = self
+ }
end
def tag_key
@@ -200,7 +204,9 @@ module Tk::Tcllib::Tkpiechart
def delete
tk_call_without_enc('pie::deleteSlice', @pie.tag_key, @tag_key)
- CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ CItemID_TBL.mutex.synchronize{
+ CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ }
@pie._delete_slice(self)
self
end
diff --git a/ext/tk/lib/tkextlib/tile.rb b/ext/tk/lib/tkextlib/tile.rb
index 690f93f029..60ea012cc0 100644
--- a/ext/tk/lib/tkextlib/tile.rb
+++ b/ext/tk/lib/tkextlib/tile.rb
@@ -4,6 +4,7 @@
#
require 'tk'
+require 'tk/ttk_selector'
# call setup script for general 'tkextlib' libraries
require 'tkextlib/setup.rb'
@@ -15,33 +16,66 @@ require 'tkextlib/tile/setup.rb'
# TkPackage.require('tile', '0.4')
# TkPackage.require('tile', '0.6')
# TkPackage.require('tile', '0.7')
-verstr = TkPackage.require('tile')
+if Tk::TK_MAJOR_VERSION > 8 ||
+ (Tk::TK_MAJOR_VERSION == 8 && Tk::TK_MINOR_VERSION >= 5)
+ TkPackage.require('tile') # for compatibility (version check of 'tile')
+ verstr = TkPackage.require('Ttk')
+else
+ verstr = TkPackage.require('tile')
+end
+
ver = verstr.split('.')
-if ver[0].to_i == 0 && ver[1].to_i <= 4
- # version 0.4 or former
- module Tk
- module Tile
- USE_TILE_NAMESPACE = true
- USE_TTK_NAMESPACE = false
- TILE_SPEC_VERSION_ID = 0
+if ver[0].to_i == 0
+ # Tile extension package
+ if ver[1].to_i <= 4
+ # version 0.4 or former
+ module Tk
+ module Tile
+ USE_TILE_NAMESPACE = true
+ USE_TTK_NAMESPACE = false
+ TILE_SPEC_VERSION_ID = 0
+ end
end
- end
-elsif ver[0].to_i == 0 && ver[1].to_i <= 6
- # version 0.5 -- version 0.6
- module Tk
- module Tile
- USE_TILE_NAMESPACE = true
- USE_TTK_NAMESPACE = true
- TILE_SPEC_VERSION_ID = 5
+ elsif ver[1].to_i <= 6
+ # version 0.5 -- version 0.6
+ module Tk
+ module Tile
+ USE_TILE_NAMESPACE = true
+ USE_TTK_NAMESPACE = true
+ TILE_SPEC_VERSION_ID = 5
+ end
+ end
+ elsif ver[1].to_i <= 7
+ module Tk
+ module Tile
+ USE_TILE_NAMESPACE = false
+ USE_TTK_NAMESPACE = true
+ TILE_SPEC_VERSION_ID = 7
+ end
+ end
+ else
+ # version 0.8 or later
+ module Tk
+ module Tile
+ USE_TILE_NAMESPACE = false
+ USE_TTK_NAMESPACE = true
+ TILE_SPEC_VERSION_ID = 8
+ end
end
end
+
+ module Tk::Tile
+ PACKAGE_NAME = 'tile'.freeze
+ end
else
- # version 0.7 or later
+ # Ttk package merged Tcl/Tk core (Tcl/Tk 8.5+)
module Tk
module Tile
USE_TILE_NAMESPACE = false
USE_TTK_NAMESPACE = true
- TILE_SPEC_VERSION_ID = 7
+ TILE_SPEC_VERSION_ID = 8
+
+ PACKAGE_NAME = 'Ttk'.freeze
end
end
end
@@ -51,30 +85,114 @@ module Tk
module Tile
TkComm::TkExtlibAutoloadModule.unshift(self)
- PACKAGE_NAME = 'tile'.freeze
def self.package_name
PACKAGE_NAME
end
def self.package_version
begin
- TkPackage.require('tile')
+ TkPackage.require(PACKAGE_NAME)
rescue
''
end
end
def self.__Import_Tile_Widgets__!
+ warn 'Warning: "Tk::Tile::__Import_Tile_Widgets__!" is obsolete.' <<
+ ' To control default widget set, use "Tk.default_widget_set = :Ttk"'
Tk.tk_call('namespace', 'import', '-force', 'ttk::*')
end
- def self.load_images(imgdir, pat=TkComm::None)
- images = Hash[*TkComm.simplelist(Tk.tk_call('::tile::LoadImages',
- imgdir, pat))]
- images.keys.each{|k|
- images[k] = TkPhotoImage.new(:imagename=>images[k],
- :without_creating=>true)
+ def self.__define_LoadImages_proc_for_compatibility__!
+ # Ttk 8.5 (Tile 0.8) lost 'LoadImages' utility procedure.
+ # So, some old scripts doen't work, because those scripts use the
+ # procedure to define local styles.
+ # Of course, rewriting such Tcl/Tk scripts isn't difficult for
+ # Tcl/Tk users. However, it may be troublesome for Ruby/Tk users
+ # who use such Tcl/Tk scripts as it is.
+ # This method may help Ruby/Tk users who don't want to modify old
+ # Tcl/Tk scripts for the latest version of Ttk (Tile) extension.
+ # This method defines a comaptible 'LoadImages' procedure on the
+ # Tcl/Tk interpreter working under Ruby/Tk.
+ # Please give attention to use this method. It may conflict with
+ # some definitions on Tcl/Tk scripts.
+ klass_name = self.name
+ proc_name = 'LoadImages'
+ if Tk::Tile::USE_TTK_NAMESPACE
+ ns_list = ['::tile']
+ if Tk.info(:commands, "::ttk::#{proc_name}").empty?
+ ns_list << '::ttk'
+ end
+ else # Tk::Tile::USE_TILE_NAMESPACE
+ ns_list = ['::ttk']
+ if Tk.info(:commands, "::tile::#{proc_name}").empty?
+ ns_list << '::tile'
+ end
+ end
+
+ ns_list.each{|ns|
+ cmd = "#{ns}::#{proc_name}"
+ unless Tk.info(:commands, cmd).empty?
+ #fail RuntimeError, "can't define '#{cmd}' command (already exist)"
+
+ # do nothing !!!
+ warn "Warning: can't define '#{cmd}' command (already exist)" if $DEBUG
+ next
+ end
+ TkNamespace.eval(ns){
+ TkCore::INTERP.add_tk_procs(proc_name, 'imgdir {patterns {*.gif}}',
+ <<-'EOS')
+ foreach pattern $patterns {
+ foreach file [glob -directory $imgdir $pattern] {
+ set img [file tail [file rootname $file]]
+ if {![info exists images($img)]} {
+ set images($img) [image create photo -file $file]
+ }
+ }
+ }
+ return [array get images]
+ EOS
+ }
}
+ end
+
+ def self.load_images(imgdir, pat=nil)
+ if Tk::Tile::TILE_SPEC_VERSION_ID < 8
+ if Tk::Tile::USE_TTK_NAMESPACE
+ cmd = '::ttk::LoadImages'
+ else # Tk::Tile::USE_TILE_NAMESPACE
+ cmd = '::tile::LoadImages'
+ end
+ pat ||= TkComm::None
+ images = Hash[*TkComm.simplelist(Tk.tk_call(cmd, imgdir, pat))]
+ images.keys.each{|k|
+ images[k] = TkPhotoImage.new(:imagename=>images[k],
+ :without_creating=>true)
+ }
+ else ## TILE_SPEC_VERSION_ID >= 8
+ pat ||= '*.gif'
+ if pat.kind_of?(Array)
+ pat_list = pat
+ else
+ pat_list = [ pat ]
+ end
+ Dir.chdir(imgdir){
+ pat_list.each{|pat|
+ Dir.glob(pat).each{|f|
+ img = File.basename(f, '.*')
+ unless TkComm.bool(Tk.info('exists', "images(#{img})"))
+ Tk.tk_call('set', "images(#{img})",
+ Tk.tk_call('image', 'create', 'photo', '-file', f))
+ end
+ }
+ }
+ }
+ images = Hash[*TkComm.simplelist(Tk.tk_call('array', 'get', 'images'))]
+ images.keys.each{|k|
+ images[k] = TkPhotoImage.new(:imagename=>images[k],
+ :without_creating=>true)
+ }
+ end
images
end
@@ -83,12 +201,53 @@ module Tk
args.map!{|arg| TkComm._get_eval_string(arg)}.join('.')
end
- module KeyNav
- def self.enableMnemonics(w)
- Tk.tk_call('::keynav::enableMnemonics', w)
+ def self.themes(glob_ptn = nil)
+ if TILE_SPEC_VERSION_ID < 8 && Tk.info(:commands, '::ttk::themes').empty?
+ fail RuntimeError, 'not support glob option' if glob_ptn
+ cmd = ['::tile::availableThemes']
+ else
+ glob_ptn = '*' unless glob_ptn
+ cmd = ['::ttk::themes', glob_ptn]
+ end
+
+ begin
+ TkComm.simplelist(Tk.tk_call_without_enc(*cmd))
+ rescue
+ TkComm.simplelist(Tk.tk_call('lsearch', '-all', '-inline',
+ Tk::Tile::Style.theme_names,
+ glob_ptn))
+ end
+ end
+
+ def self.set_theme(theme)
+ if TILE_SPEC_VERSION_ID < 8 && Tk.info(:commands, '::ttk::setTheme').empty?
+ cmd = '::tile::setTheme'
+ else
+ cmd = '::ttk::setTheme'
+ end
+
+ begin
+ Tk.tk_call_without_enc(cmd, theme)
+ rescue
+ Tk::Tile::Style.theme_use(theme)
end
- def self.defaultButton(w)
- Tk.tk_call('::keynav::defaultButton', w)
+ end
+
+ module KeyNav
+ if Tk::Tile::TILE_SPEC_VERSION_ID < 8
+ def self.enableMnemonics(w)
+ Tk.tk_call('::keynav::enableMnemonics', w)
+ end
+ def self.defaultButton(w)
+ Tk.tk_call('::keynav::defaultButton', w)
+ end
+ else # dummy
+ def self.enableMnemonics(w)
+ ""
+ end
+ def self.defaultButton(w)
+ ""
+ end
end
end
@@ -103,6 +262,12 @@ module Tk
Menu = 'TkMenuFont'
SmallCaption = 'TkSmallCaptionFont'
Icon = 'TkIconFont'
+
+ TkFont::SYSTEM_FONT_NAMES.add [
+ 'TkDefaultFont', 'TkTextFont', 'TkHeadingFont',
+ 'TkCaptionFont', 'TkTooltipFont', 'TkFixedFont',
+ 'TkMenuFont', 'TkSmallCaptionFont', 'TkIconFont'
+ ]
end
module ParseStyleLayout
@@ -141,7 +306,7 @@ module Tk
end
private :__val2ruby_optkeys
- def instate(state, script=nil, &b)
+ def ttk_instate(state, script=nil, &b)
if script
tk_send('instate', state, script)
elsif b
@@ -150,14 +315,30 @@ module Tk
bool(tk_send('instate', state))
end
end
+ alias tile_instate ttk_instate
- def state(state=nil)
+ def ttk_state(state=nil)
if state
tk_send('state', state)
else
list(tk_send('state'))
end
end
+ alias tile_state ttk_state
+
+ def ttk_identify(x, y)
+ ret = tk_send_without_enc('identify', x, y)
+ (ret.empty?)? nil: ret
+ end
+ alias tile_identify ttk_identify
+
+ # remove instate/state/identify method
+ # to avoid the conflict with widget options
+ if Tk.const_defined?(:USE_OBSOLETE_TILE_STATE_METHOD) && Tk::USE_OBSOLETE_TILE_STATE_METHOD
+ alias instate ttk_instate
+ alias state ttk_state
+ alias identify ttk_identify
+ end
end
######################################
@@ -183,18 +364,24 @@ module Tk
autoload :TLabelframe, 'tkextlib/tile/tlabelframe'
autoload :Labelframe, 'tkextlib/tile/tlabelframe'
+ autoload :TLabelFrame, 'tkextlib/tile/tlabelframe'
+ autoload :LabelFrame, 'tkextlib/tile/tlabelframe'
autoload :TLabel, 'tkextlib/tile/tlabel'
autoload :Label, 'tkextlib/tile/tlabel'
autoload :TMenubutton, 'tkextlib/tile/tmenubutton'
autoload :Menubutton, 'tkextlib/tile/tmenubutton'
+ autoload :TMenuButton, 'tkextlib/tile/tmenubutton'
+ autoload :MenuButton, 'tkextlib/tile/tmenubutton'
autoload :TNotebook, 'tkextlib/tile/tnotebook'
autoload :Notebook, 'tkextlib/tile/tnotebook'
autoload :TPaned, 'tkextlib/tile/tpaned'
autoload :Paned, 'tkextlib/tile/tpaned'
+ autoload :PanedWindow, 'tkextlib/tile/tpaned'
+ autoload :Panedwindow, 'tkextlib/tile/tpaned'
autoload :TProgressbar, 'tkextlib/tile/tprogressbar'
autoload :Progressbar, 'tkextlib/tile/tprogressbar'
@@ -211,6 +398,8 @@ module Tk
autoload :TScrollbar, 'tkextlib/tile/tscrollbar'
autoload :Scrollbar, 'tkextlib/tile/tscrollbar'
+ autoload :XScrollbar, 'tkextlib/tile/tscrollbar'
+ autoload :YScrollbar, 'tkextlib/tile/tscrollbar'
autoload :TSeparator, 'tkextlib/tile/tseparator'
autoload :Separator, 'tkextlib/tile/tseparator'
@@ -218,8 +407,13 @@ module Tk
autoload :TSquare, 'tkextlib/tile/tsquare'
autoload :Square, 'tkextlib/tile/tsquare'
+ autoload :SizeGrip, 'tkextlib/tile/sizegrip'
+ autoload :Sizegrip, 'tkextlib/tile/sizegrip'
+
autoload :Treeview, 'tkextlib/tile/treeview'
autoload :Style, 'tkextlib/tile/style'
end
end
+
+Ttk = Tk::Tile
diff --git a/ext/tk/lib/tkextlib/tile/dialog.rb b/ext/tk/lib/tkextlib/tile/dialog.rb
index f8ddf62598..ef2d1fe577 100644
--- a/ext/tk/lib/tkextlib/tile/dialog.rb
+++ b/ext/tk/lib/tkextlib/tile/dialog.rb
@@ -51,12 +51,24 @@ class Tk::Tile::Dialog
alias display show
def client_frame
- window(tk_call_without_enc('::ttk::dialog::clientframe'))
+ window(tk_call_without_enc('::ttk::dialog::clientframe', @path))
end
+ def cget_strict(slot)
+ @keys[slot.to_s]
+ end
+ def cget(slot)
+ @keys[slot.to_s]
+ end
+=begin
def cget(slot)
- @keys[slot]
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ cget_strict(slot)
+ else
+ cget_strict(slot) rescue nil
+ end
end
+=end
def configure(slot, value=None)
if slot.kind_of?(Hash)
diff --git a/ext/tk/lib/tkextlib/tile/sizegrip.rb b/ext/tk/lib/tkextlib/tile/sizegrip.rb
new file mode 100644
index 0000000000..c5068919a4
--- /dev/null
+++ b/ext/tk/lib/tkextlib/tile/sizegrip.rb
@@ -0,0 +1,29 @@
+#
+# ttk::sizegrip widget
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+require 'tk'
+require 'tkextlib/tile.rb'
+
+module Tk
+ module Tile
+ class SizeGrip < TkWindow
+ end
+ Sizegrip = SizeGrip
+ end
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Sizegrip, :TkSizegrip, :TkSizeGrip)
+
+
+class Tk::Tile::SizeGrip < TkWindow
+ include Tk::Tile::TileWidget
+
+ TkCommandNames = ['::ttk::sizegrip'.freeze].freeze
+ WidgetClassName = 'TSizegrip'.freeze
+ WidgetClassNames[WidgetClassName] = self
+
+ def self.style(*args)
+ [self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
+ end
+end
diff --git a/ext/tk/lib/tkextlib/tile/style.rb b/ext/tk/lib/tkextlib/tile/style.rb
index 485a36d7d6..ca7ee99c32 100644
--- a/ext/tk/lib/tkextlib/tile/style.rb
+++ b/ext/tk/lib/tkextlib/tile/style.rb
@@ -17,6 +17,145 @@ module Tk::Tile::Style
end
class << Tk::Tile::Style
+ if Tk::Tile::TILE_SPEC_VERSION_ID < 8
+ TkCommandNames = ['style'.freeze].freeze
+
+ # --- Tk::Tile::Style.__define_wrapper_proc_for_compatibility__! ---
+ # On Ttk (Tile) extension, 'style' command has imcompatible changes
+ # depend on the version of the extention. It requires modifying the
+ # Tcl/Tk scripts to define local styles. The rule for modification
+ # is a simple one. But, if users want to keep compatibility between
+ # versions of the extension, they will have to contrive to do that.
+ # It may be troublesome, especially for Ruby/Tk users.
+ # This method may help such work. This method make some definitions
+ # on the Tcl/Tk interpreter to work with different version of style
+ # command format. Please give attention to use this method. It may
+ # conflict with some definitions on Tcl/Tk scripts.
+ if Tk::Tile::TILE_SPEC_VERSION_ID < 7
+ def __define_wrapper_proc_for_compatibility__!
+ __define_themes_and_setTheme_proc__!
+
+ unless Tk.info(:commands, '::ttk::style').empty?
+ # fail RuntimeError,
+ # "can't define '::ttk::style' command (already exist)"
+
+ # do nothing !!!
+ warn "Warning: can't define '::ttk::style' command (already exist)" if $DEBUG
+ return
+ end
+ TkCore::INTERP.add_tk_procs('::ttk::style', 'args', <<-'EOS')
+ if [string equal [lrange $args 0 1] {element create}] {
+ if [string equal [lindex $args 3] image] {
+ set spec [lindex $args 4]
+ set map [lrange $spec 1 end]
+ if [llength $map] {
+ # return [eval [concat [list ::style element create [lindex $args 2] image [lindex $spec 0] -map $map] [lrange $args 5 end]]]
+ return [uplevel 1 [list ::style element create [lindex $args 2] image [lindex $spec 0] -map $map] [lrange $args 5 end]]
+ }
+ }
+ }
+ # return [eval "::style $args"]
+ return [uplevel 1 ::style $args]
+ EOS
+ #########################
+ end
+ else ### TILE_SPEC_VERSION_ID == 7
+ def __define_wrapper_proc_for_compatibility__!
+ __define_themes_and_setTheme_proc__!
+
+ unless Tk.info(:commands, '::ttk::style').empty?
+ # fail RuntimeError,
+ # "can't define '::ttk::style' command (already exist)"
+
+ # do nothing !!!
+ warn "Warning: can't define '::ttk::style' command (already exist)" if $DEBUG
+ return
+ end
+ TkCore::INTERP.add_tk_procs('::ttk::style', 'args', <<-'EOS')
+ if [string equal [lrange $args 0 1] {element create}] {
+ if [string equal [lindex $args 3] image] {
+ set spec [lindex $args 4]
+ set map [lrange $spec 1 end]
+ if [llength $map] {
+ # return [eval [concat [list ::style element create [lindex $args 2] image [lindex $spec 0] -map $map] [lrange $args 5 end]]]
+ return [uplevel 1 [list ::style element create [lindex $args 2] image [lindex $spec 0] -map $map] [lrange $args 5 end]]]
+ }
+ }
+ } elseif [string equal [lindex $args 0] default] {
+ # return [eval "::style [lreplace $args 0 0 configure]"]
+ return [uplevel 1 ::style [lreplace $args 0 0 configure]]
+ }
+ # return [eval "::style $args"]
+ return [uplevel 1 ::style $args]
+ EOS
+ #########################
+ end
+ end
+ else ### TILE_SPEC_VERSION_ID >= 8
+ TkCommandNames = ['::ttk::style'.freeze].freeze
+
+ def __define_wrapper_proc_for_compatibility__!
+ __define_themes_and_setTheme_proc__!
+
+ unless Tk.info(:commands, '::style').empty?
+ # fail RuntimeError, "can't define '::style' command (already exist)"
+
+ # do nothing !!!
+ warn "Warning: can't define '::style' command (already exist)" if $DEBUG
+ return
+ end
+ TkCore::INTERP.add_tk_procs('::style', 'args', <<-'EOS')
+ if [string equal [lrange $args 0 1] {element create}] {
+ if [string equal [lindex $args 3] image] {
+ set name [lindex $args 4]
+ set opts [lrange $args 5 end]
+ set idx [lsearch $opts -map]
+ if {$idx >= 0 && [expr $idx % 2 == 0]} {
+ # return [eval [concat [list ::ttk::style element create [lindex $args 2] image [concat $name [lindex $opts [expr $idx + 1]]]] [lreplace $opts $idx [expr $idx + 1]]]]
+ return [uplevel 1 [list ::ttk::style element create [lindex $args 2] image [concat $name [lindex $opts [expr $idx + 1]]]] [lreplace $opts $idx [expr $idx + 1]]]
+ }
+ }
+ } elseif [string equal [lindex $args 0] default] {
+ # return [eval "::ttk::style [lreplace $args 0 0 configure]"]
+ return [uplevel 1 ::ttk::style [lreplace $args 0 0 configure]]
+ }
+ # return [eval "::ttk::style $args"]
+ return [uplevel 1 ::ttk::style $args]
+ EOS
+ #########################
+ end
+ end
+
+ def __define_themes_and_setTheme_proc__!
+ TkCore::INTERP.add_tk_procs('::ttk::themes', '{ptn *}', <<-'EOS')
+ #set themes [list]
+ set themes [::ttk::style theme names]
+ foreach pkg [lsearch -inline -all -glob [package names] ttk::theme::$ptn] {
+ set theme [namespace tail $pkg]
+ if {[lsearch -exact $themes $theme] < 0} {
+ lappend themes $theme
+ }
+ }
+ foreach pkg [lsearch -inline -all -glob [package names] tile::theme::$ptn] {
+ set theme [namespace tail $pkg]
+ if {[lsearch -exact $themes $theme] < 0} {
+ lappend themes $theme
+ }
+ }
+ return $themes
+ EOS
+ #########################
+ TkCore::INTERP.add_tk_procs('::ttk::setTheme', 'theme', <<-'EOS')
+ variable currentTheme
+ if {[lsearch -exact [::ttk::style theme names] $theme] < 0} {
+ package require [lsearch -inline -regexp [package names] (ttk|tile)::theme::$theme]
+ }
+ ::ttk::style theme use $theme
+ set currentTheme $theme
+ EOS
+ end
+ private :__define_themes_and_setTheme_proc__!
+
def configure(style=nil, keys=nil)
if style.kind_of?(Hash)
keys = style
@@ -31,9 +170,9 @@ class << Tk::Tile::Style
end
if keys && keys != None
- tk_call('style', sub_cmd, style, *hash_kv(keys))
+ tk_call(TkCommandNames[0], sub_cmd, style, *hash_kv(keys))
else
- tk_call('style', sub_cmd, style)
+ tk_call(TkCommandNames[0], sub_cmd, style)
end
end
alias default configure
@@ -46,11 +185,34 @@ class << Tk::Tile::Style
style = '.' unless style
if keys && keys != None
- tk_call('style', 'map', style, *hash_kv(keys))
+ if keys.kind_of?(Hash)
+ tk_call(TkCommandNames[0], 'map', style, *hash_kv(keys))
+ else
+ simplelist(tk_call(TkCommandNames[0], 'map', style, '-' << keys.to_s))
+ end
else
- tk_call('style', 'map', style)
+ ret = {}
+ Hash[*(simplelist(tk_call(TkCommandNames[0], 'map', style)))].each{|k, v|
+ ret[k[1..-1]] = list(v)
+ }
+ ret
end
end
+ alias map_configure map
+
+ def map_configinfo(style=nil, key=None)
+ style = '.' unless style
+ map(style, key)
+ end
+
+ def map_default_configinfo(key=None)
+ map('.', key)
+ end
+
+ def lookup(style, opt, state=None, fallback_value=None)
+ tk_call(TkCommandNames[0], 'lookup', style,
+ '-' << opt.to_s, state, fallback_value)
+ end
include Tk::Tile::ParseStyleLayout
@@ -62,42 +224,93 @@ class << Tk::Tile::Style
style = '.' unless style
if spec
- tk_call('style', 'layout', style, spec)
+ tk_call(TkCommandNames[0], 'layout', style, spec)
else
- _style_layout(list(tk_call('style', 'layout', style)))
+ _style_layout(list(tk_call(TkCommandNames[0], 'layout', style)))
end
end
def element_create(name, type, *args)
- tk_call('style', 'element', 'create', name, type, *args)
+ if type == 'image' || type == :image
+ element_create_image(name, *args)
+ else
+ tk_call(TkCommandNames[0], 'element', 'create', name, type, *args)
+ end
+ end
+
+ def element_create_image(name, *args)
+ fail ArgumentError, 'Must supply a base image' unless (spec = args.shift)
+ if (opts = args.shift)
+ if opts.kind_of?(Hash)
+ opts = _symbolkey2str(opts)
+ else
+ fail ArgumentError, 'bad option'
+ end
+ end
+ fail ArgumentError, 'too many arguments' unless args.empty?
+
+ if spec.kind_of?(Array)
+ # probably, command format is tile 0.8+ (Tcl/Tk8.5+) style
+ if Tk::Tile::TILE_SPEC_VERSION_ID >= 8
+ if opts
+ tk_call(TkCommandNames[0],
+ 'element', 'create', name, 'image', spec, opts)
+ else
+ tk_call(TkCommandNames[0], 'element', 'create', name, 'image', spec)
+ end
+ else
+ fail ArgumentError, 'illegal arguments' if opts.key?('map')
+ base = spec.shift
+ opts['map'] = spec
+ tk_call(TkCommandNames[0],
+ 'element', 'create', name, 'image', base, opts)
+ end
+ else
+ # probably, command format is tile 0.7.8 or older style
+ if Tk::Tile::TILE_SPEC_VERSION_ID >= 8
+ spec = [spec, *(opts.delete('map'))] if opts.key?('map')
+ end
+ if opts
+ tk_call(TkCommandNames[0],
+ 'element', 'create', name, 'image', spec, opts)
+ else
+ tk_call(TkCommandNames[0], 'element', 'create', name, 'image', spec)
+ end
+ end
end
def element_names()
- list(tk_call('style', 'element', 'names'))
+ list(tk_call(TkCommandNames[0], 'element', 'names'))
end
def element_options(elem)
- simplelist(tk_call('style', 'element', 'options', elem))
+ simplelist(tk_call(TkCommandNames[0], 'element', 'options', elem))
end
def theme_create(name, keys=nil)
+ name = name.to_s
if keys && keys != None
- tk_call('style', 'theme', 'create', name, *hash_kv(keys))
+ tk_call(TkCommandNames[0], 'theme', 'create', name, *hash_kv(keys))
else
- tk_call('style', 'theme', 'create', name)
+ tk_call(TkCommandNames[0], 'theme', 'create', name)
end
+ name
end
def theme_settings(name, cmd=nil, &b)
+ name = name.to_s
cmd = Proc.new(&b) if !cmd && b
- tk_call('style', 'theme', 'settings', name, cmd)
+ tk_call(TkCommandNames[0], 'theme', 'settings', name, cmd)
+ name
end
def theme_names()
- list(tk_call('style', 'theme', 'names'))
+ list(tk_call(TkCommandNames[0], 'theme', 'names'))
end
def theme_use(name)
- tk_call('style', 'theme', 'use', name)
+ name = name.to_s
+ tk_call(TkCommandNames[0], 'theme', 'use', name)
+ name
end
end
diff --git a/ext/tk/lib/tkextlib/tile/tbutton.rb b/ext/tk/lib/tkextlib/tile/tbutton.rb
index 1142a27100..5d7db10fe9 100644
--- a/ext/tk/lib/tkextlib/tile/tbutton.rb
+++ b/ext/tk/lib/tkextlib/tile/tbutton.rb
@@ -7,13 +7,16 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TButton < TkButton
+ class TButton < Tk::Button
end
Button = TButton
end
end
-class Tk::Tile::TButton < TkButton
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Button, :TkButton)
+
+
+class Tk::Tile::TButton < Tk::Button
include Tk::Tile::TileWidget
if Tk::Tile::USE_TTK_NAMESPACE
diff --git a/ext/tk/lib/tkextlib/tile/tcheckbutton.rb b/ext/tk/lib/tkextlib/tile/tcheckbutton.rb
index fce799683d..172225fcec 100644
--- a/ext/tk/lib/tkextlib/tile/tcheckbutton.rb
+++ b/ext/tk/lib/tkextlib/tile/tcheckbutton.rb
@@ -7,7 +7,7 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TCheckButton < TkCheckButton
+ class TCheckButton < Tk::CheckButton
end
TCheckbutton = TCheckButton
CheckButton = TCheckButton
@@ -15,7 +15,11 @@ module Tk
end
end
-class Tk::Tile::TCheckButton < TkCheckButton
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Checkbutton,
+ :TkCheckbutton, :TkCheckButton)
+
+
+class Tk::Tile::TCheckButton < Tk::CheckButton
include Tk::Tile::TileWidget
if Tk::Tile::USE_TTK_NAMESPACE
diff --git a/ext/tk/lib/tkextlib/tile/tcombobox.rb b/ext/tk/lib/tkextlib/tile/tcombobox.rb
index c63ab94dbe..b64372f1c9 100644
--- a/ext/tk/lib/tkextlib/tile/tcombobox.rb
+++ b/ext/tk/lib/tkextlib/tile/tcombobox.rb
@@ -13,6 +13,9 @@ module Tk
end
end
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Combobox, :TkCombobox)
+
+
class Tk::Tile::TCombobox < Tk::Tile::TEntry
include Tk::Tile::TileWidget
@@ -39,16 +42,12 @@ class Tk::Tile::TCombobox < Tk::Tile::TEntry
end
def current
- number(tk_send_without_enc('current', idx))
+ number(tk_send_without_enc('current'))
end
def current=(idx)
tk_send_without_enc('current', idx)
end
- def identify(x, y)
- tk_send_without_enc('identify', x, y)
- end
-
def set(val)
tk_send('set', val)
end
diff --git a/ext/tk/lib/tkextlib/tile/tentry.rb b/ext/tk/lib/tkextlib/tile/tentry.rb
index 4d57ce7756..0bea98dcd9 100644
--- a/ext/tk/lib/tkextlib/tile/tentry.rb
+++ b/ext/tk/lib/tkextlib/tile/tentry.rb
@@ -7,13 +7,16 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TEntry < TkEntry
+ class TEntry < Tk::Entry
end
Entry = TEntry
end
end
-class Tk::Tile::TEntry < TkEntry
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Entry, :TkEntry)
+
+
+class Tk::Tile::TEntry < Tk::Entry
include Tk::Tile::TileWidget
if Tk::Tile::USE_TTK_NAMESPACE
@@ -24,6 +27,11 @@ class Tk::Tile::TEntry < TkEntry
WidgetClassName = 'TEntry'.freeze
WidgetClassNames[WidgetClassName] = self
+ def __optkey_aliases
+ {:vcmd=>:validatecommand, :invcmd=>:invalidcommand}
+ end
+ private :__optkey_aliases
+
def __boolval_optkeys
super() << 'exportselection'
end
diff --git a/ext/tk/lib/tkextlib/tile/tframe.rb b/ext/tk/lib/tkextlib/tile/tframe.rb
index 691c9c42af..3b5f98bb6e 100644
--- a/ext/tk/lib/tkextlib/tile/tframe.rb
+++ b/ext/tk/lib/tkextlib/tile/tframe.rb
@@ -7,13 +7,16 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TFrame < TkFrame
+ class TFrame < Tk::Frame
end
Frame = TFrame
end
end
-class Tk::Tile::TFrame < TkFrame
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Frame, :TkFrame)
+
+
+class Tk::Tile::TFrame < Tk::Frame
include Tk::Tile::TileWidget
if Tk::Tile::USE_TTK_NAMESPACE
diff --git a/ext/tk/lib/tkextlib/tile/tlabel.rb b/ext/tk/lib/tkextlib/tile/tlabel.rb
index 4111d1906a..7d074d3842 100644
--- a/ext/tk/lib/tkextlib/tile/tlabel.rb
+++ b/ext/tk/lib/tkextlib/tile/tlabel.rb
@@ -7,13 +7,16 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TLabel < TkLabel
+ class TLabel < Tk::Label
end
Label = TLabel
end
end
-class Tk::Tile::TLabel < TkLabel
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Label, :TkLabel)
+
+
+class Tk::Tile::TLabel < Tk::Label
include Tk::Tile::TileWidget
if Tk::Tile::USE_TTK_NAMESPACE
diff --git a/ext/tk/lib/tkextlib/tile/tlabelframe.rb b/ext/tk/lib/tkextlib/tile/tlabelframe.rb
index 8981232b25..cff66d8658 100644
--- a/ext/tk/lib/tkextlib/tile/tlabelframe.rb
+++ b/ext/tk/lib/tkextlib/tile/tlabelframe.rb
@@ -9,10 +9,16 @@ module Tk
module Tile
class TLabelframe < Tk::Tile::TFrame
end
- Labelframe = TLabelframe
+ TLabelFrame = TLabelframe
+ Labelframe = TLabelframe
+ LabelFrame = TLabelframe
end
end
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Labelframe,
+ :TkLabelframe, :TkLabelFrame)
+
+
class Tk::Tile::TLabelframe < Tk::Tile::TFrame
include Tk::Tile::TileWidget
diff --git a/ext/tk/lib/tkextlib/tile/tmenubutton.rb b/ext/tk/lib/tkextlib/tile/tmenubutton.rb
index 4b81fa1c81..7c6ab28e52 100644
--- a/ext/tk/lib/tkextlib/tile/tmenubutton.rb
+++ b/ext/tk/lib/tkextlib/tile/tmenubutton.rb
@@ -7,13 +7,19 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TMenubutton < TkMenubutton
+ class TMenubutton < Tk::Menubutton
end
- Menubutton = TMenubutton
+ TMenuButton = TMenubutton
+ Menubutton = TMenubutton
+ MenuButton = TMenubutton
end
end
-class Tk::Tile::TMenubutton < TkMenubutton
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Menubutton,
+ :TkMenubutton, :TkMenuButton)
+
+
+class Tk::Tile::TMenubutton < Tk::Menubutton
include Tk::Tile::TileWidget
if Tk::Tile::USE_TTK_NAMESPACE
diff --git a/ext/tk/lib/tkextlib/tile/tnotebook.rb b/ext/tk/lib/tkextlib/tile/tnotebook.rb
index abaed8ee9c..4d65e363da 100644
--- a/ext/tk/lib/tkextlib/tile/tnotebook.rb
+++ b/ext/tk/lib/tkextlib/tile/tnotebook.rb
@@ -13,6 +13,9 @@ module Tk
end
end
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Notebook, :TkNotebook)
+
+
class Tk::Tile::TNotebook < TkWindow
################################
include TkItemConfigMethod
@@ -27,24 +30,46 @@ class Tk::Tile::TNotebook < TkWindow
end
private :__item_config_cmd
- def __item_listval_optkeys
+ def __item_listval_optkeys(id)
[]
end
private :__item_listval_optkeys
- def __item_methodcall_optkeys # { key=>method, ... }
+ def __item_methodcall_optkeys(id) # { key=>method, ... }
{}
end
- private :__item_listval_optkeys
+ private :__item_methodcall_optkeys
#alias tabcget itemcget
+ #alias tabcget_strict itemcget_strict
alias tabconfigure itemconfigure
alias tabconfiginfo itemconfiginfo
alias current_tabconfiginfo current_itemconfiginfo
- def tabcget(tagOrId, option)
+ def tabcget_strict(tagOrId, option)
tabconfigure(tagOrId, option)[-1]
end
+ def tabcget(tagOrId, option)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ tabcget_strict(tagOrId, option)
+ else
+ begin
+ tabcget_strict(tagOrId, option)
+ rescue => e
+ begin
+ if current_tabconfiginfo(tagOrId).has_key?(option.to_s)
+ # not tag error & option is known -> error on known option
+ fail e
+ else
+ # not tag error & option is unknown
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
################################
include Tk::Tile::TileWidget
@@ -74,9 +99,9 @@ class Tk::Tile::TNotebook < TkWindow
def add(child, keys=nil)
if keys && keys != None
- tk_send_without_enc('add', _epath(child), *hash_kv(keys))
+ tk_send('add', _epath(child), *hash_kv(keys))
else
- tk_send_without_enc('add', _epath(child))
+ tk_send('add', _epath(child))
end
self
end
@@ -104,6 +129,10 @@ class Tk::Tile::TNotebook < TkWindow
self
end
+ def selected
+ window(tk_send_without_enc('select'))
+ end
+
def tabs
list(tk_send('tabs'))
end
diff --git a/ext/tk/lib/tkextlib/tile/tpaned.rb b/ext/tk/lib/tkextlib/tile/tpaned.rb
index 11178b19d3..d96ff43973 100644
--- a/ext/tk/lib/tkextlib/tile/tpaned.rb
+++ b/ext/tk/lib/tkextlib/tile/tpaned.rb
@@ -9,15 +9,23 @@ module Tk
module Tile
class TPaned < TkWindow
end
- Paned = TPaned
+ PanedWindow = Panedwindow = Paned = TPaned
end
end
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Panedwindow,
+ :TkPanedwindow, :TkPanedWindow)
+
+
class Tk::Tile::TPaned < TkWindow
include Tk::Tile::TileWidget
if Tk::Tile::USE_TTK_NAMESPACE
- TkCommandNames = ['::ttk::paned'.freeze].freeze
+ if Tk::Tile::TILE_SPEC_VERSION_ID < 8
+ TkCommandNames = ['::ttk::paned'.freeze].freeze
+ else
+ TkCommandNames = ['::ttk::panedwindow'.freeze].freeze
+ end
else
TkCommandNames = ['::tpaned'.freeze].freeze
end
@@ -28,9 +36,21 @@ class Tk::Tile::TPaned < TkWindow
[self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
end
- def add(win, keys)
- win = _epath(win)
- tk_send_without_enc('add', win, *hash_kv(keys))
+ def add(*args)
+ keys = args.pop
+ fail ArgumentError, "no window in arguments" unless keys
+
+ if keys && keys.kind_of?(Hash)
+ fail ArgumentError, "no window in arguments" if args == []
+ opts = hash_kv(keys)
+ else
+ args.push(keys) if keys
+ opts = []
+ end
+
+ args.each{|win|
+ tk_send_without_enc('add', _epath(win), *opts)
+ }
self
end
@@ -46,10 +66,33 @@ class Tk::Tile::TPaned < TkWindow
self
end
- def panecget(pane, slot)
+ def panecget_strict(pane, slot)
pane = _epath(pane)
tk_tcl2ruby(tk_send_without_enc('pane', pane, "-#{slot}"))
end
+ alias pane_cget_strict panecget_strict
+
+ def panecget(pane, slot)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ panecget_strict(pane, slot)
+ else
+ begin
+ panecget_strict(pane, slot)
+ rescue => e
+ begin
+ if current_paneconfiginfo(pane).has_key?(slot.to_s)
+ # not tag error & option is known -> error on known option
+ fail e
+ else
+ # not tag error & option is unknown
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
alias pane_cget panecget
def paneconfigure(pane, key, value=nil)
diff --git a/ext/tk/lib/tkextlib/tile/tprogressbar.rb b/ext/tk/lib/tkextlib/tile/tprogressbar.rb
index 36c1c75c23..f786d370dd 100644
--- a/ext/tk/lib/tkextlib/tile/tprogressbar.rb
+++ b/ext/tk/lib/tkextlib/tile/tprogressbar.rb
@@ -13,6 +13,9 @@ module Tk
end
end
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Progressbar, :TkProgressbar)
+
+
class Tk::Tile::TProgressbar
include Tk::Tile::TileWidget
diff --git a/ext/tk/lib/tkextlib/tile/tradiobutton.rb b/ext/tk/lib/tkextlib/tile/tradiobutton.rb
index e2f614cb97..d653a6d256 100644
--- a/ext/tk/lib/tkextlib/tile/tradiobutton.rb
+++ b/ext/tk/lib/tkextlib/tile/tradiobutton.rb
@@ -7,7 +7,7 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TRadioButton < TkRadioButton
+ class TRadioButton < Tk::RadioButton
end
TRadiobutton = TRadioButton
RadioButton = TRadioButton
@@ -15,7 +15,11 @@ module Tk
end
end
-class Tk::Tile::TRadioButton < TkRadioButton
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Radiobutton,
+ :TkRadiobutton, :TkRadioButton)
+
+
+class Tk::Tile::TRadioButton < Tk::RadioButton
include Tk::Tile::TileWidget
if Tk::Tile::USE_TTK_NAMESPACE
diff --git a/ext/tk/lib/tkextlib/tile/treeview.rb b/ext/tk/lib/tkextlib/tile/treeview.rb
index d3ffbbfa6b..c978a1a07b 100644
--- a/ext/tk/lib/tkextlib/tile/treeview.rb
+++ b/ext/tk/lib/tkextlib/tile/treeview.rb
@@ -9,129 +9,999 @@ module Tk
module Tile
class Treeview < TkWindow
end
+ end
+end
- module TreeviewConfig
- include TkItemConfigMethod
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Treeview, :TkTreeview)
- def __item_cget_cmd(id)
- [self.path, id[0], id[1]]
- end
- private :__item_cget_cmd
- def __item_config_cmd(id)
- [self.path, id[0], id[1]]
- end
- private :__item_config_cmd
-
- def __item_numstrval_optkeys(id)
- case id[0]
- when :item, 'item'
- ['width']
- when :column, 'column'
- super(id[1])
- when :heading, 'heading'
- super(id[1])
- end
- end
- private :__item_numstrval_optkeys
-
- def __item_strval_optkeys(id)
- case id[0]
- when :item, 'item'
- super(id) + ['id']
- when :column, 'column'
- super(id[1])
- when :heading, 'heading'
- super(id[1])
- end
- end
- private :__item_strval_optkeys
-
- def __item_boolval_optkeys(id)
- case id[0]
- when :item, 'item'
- ['open']
- when :column, 'column'
- super(id[1])
- when :heading, 'heading'
- super(id[1])
+module Tk::Tile::TreeviewConfig
+ include TkItemConfigMethod
+
+ def __item_configinfo_struct(id)
+ # maybe need to override
+ {:key=>0, :alias=>nil, :db_name=>nil, :db_class=>nil,
+ :default_value=>nil, :current_value=>1}
+ end
+ private :__item_configinfo_struct
+
+ def __itemconfiginfo_core(tagOrId, slot = nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/)
+ fontkey = $2
+ return [slot.to_s, tagfontobj(tagid(tagOrId), fontkey)]
+ else
+ if slot
+ slot = slot.to_s
+
+ alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
+ case slot
+ when /^(#{__tile_specific_item_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ # On tile-0.7.{2-8}, 'state' options has no '-' at its head.
+ val = tk_call(*(__item_confinfo_cmd(tagid(tagOrId)) << slot))
+ rescue
+ # Maybe, 'state' option has '-' in future.
+ val = tk_call(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ end
+ return [slot, val]
+
+ when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
+ method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[slot]
+ optval = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ begin
+ val = method.call(tagOrId, optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}lcall(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ return [slot, val]
+
+ when /^(#{__item_methodcall_optkeys(tagid(tagOrId)).keys.join('|')})$/
+ method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[slot]
+ return [slot, self.__send__(method, tagOrId)]
+
+ when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ val = number(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
+ rescue
+ val = nil
+ end
+ return [slot, val]
+
+ when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/
+ val = num_or_str(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
+ return [slot, val]
+
+ when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ val = bool(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
+ rescue
+ val = nil
+ end
+ return [slot, val]
+
+ when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/
+ val = simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
+ return [slot, val]
+
+ when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/
+ val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ if val =~ /^[0-9]/
+ return [slot, list(val)]
+ else
+ return [slot, val]
+ end
+
+ when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/
+ val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ return [slot, val]
+
+ when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
+ val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ if val.empty?
+ return [slot, nil]
+ else
+ return [slot, TkVarAccess.new(val)]
+ end
+
+ else
+ val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ if val.index('{')
+ return [slot, tk_split_list(val)]
+ else
+ return [slot, tk_tcl2ruby(val)]
+ end
+ end
+
+ else # ! slot
+ ret = Hash[*(tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))), false, false))].to_a.collect{|conf|
+ conf[0] = conf[0][1..-1] if conf[0][0] == ?-
+ case conf[0]
+ when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
+ method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[conf[0]]
+ optval = conf[1]
+ begin
+ val = method.call(tagOrId, optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[1] = val
+
+ when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/
+ # do nothing
+
+ when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ conf[1] = number(conf[1])
+ rescue
+ conf[1] = nil
+ end
+
+ when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/
+ conf[1] = num_or_str(conf[1])
+
+ when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ conf[1] = bool(conf[1])
+ rescue
+ conf[1] = nil
+ end
+
+ when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/
+ conf[1] = simplelist(conf[1])
+
+ when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/
+ if conf[1] =~ /^[0-9]/
+ conf[1] = list(conf[1])
+ end
+
+ when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
+ if conf[1].empty?
+ conf[1] = nil
+ else
+ conf[1] = TkVarAccess.new(conf[1])
+ end
+
+ else
+ if conf[1].index('{')
+ conf[1] = tk_split_list(conf[1])
+ else
+ conf[1] = tk_tcl2ruby(conf[1])
+ end
+ end
+
+ conf
+ }
+
+ __item_font_optkeys(tagid(tagOrId)).each{|optkey|
+ optkey = optkey.to_s
+ fontconf = ret.assoc(optkey)
+ if fontconf
+ ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/}
+ fontconf[1] = tagfontobj(tagid(tagOrId), optkey)
+ ret.push(fontconf)
+ end
+ }
+
+ __item_methodcall_optkeys(tagid(tagOrId)).each{|optkey, method|
+ ret << [optkey.to_s, self.__send__(method, tagOrId)]
+ }
+
+ ret
end
end
- private :__item_boolval_optkeys
-
- def __item_listval_optkeys(id)
- case id[0]
- when :item, 'item'
- ['values']
- when :column, 'column'
- []
- when :heading, 'heading'
- []
+
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/)
+ fontkey = $2
+ return {slot.to_s => tagfontobj(tagid(tagOrId), fontkey)}
+ else
+ if slot
+ slot = slot.to_s
+
+ alias_name, real_name = __item_optkey_aliases(tagid(tagOrId)).find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
+ case slot
+ when /^(#{__tile_specific_item_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ # On tile-0.7.{2-8}, 'state' option has no '-' at its head.
+ val = tk_call(*(__item_confinfo_cmd(tagid(tagOrId)) << slot))
+ rescue
+ # Maybe, 'state' option has '-' in future.
+ val = tk_call(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ end
+ return {slot => val}
+
+ when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
+ method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[slot]
+ optval = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ begin
+ val = method.call(tagOrId, optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}lcall(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ return {slot => val}
+
+ when /^(#{__item_methodcall_optkeys(tagid(tagOrId)).keys.join('|')})$/
+ method = _symbolkey2str(__item_methodcall_optkeys(tagid(tagOrId)))[slot]
+ return {slot => self.__send__(method, tagOrId)}
+
+ when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ val = number(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
+ rescue
+ val = nil
+ end
+ return {slot => val}
+
+ when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/
+ val = num_or_str(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
+ return {slot => val}
+
+ when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ val = bool(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
+ rescue
+ val = nil
+ end
+ return {slot => val}
+
+ when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/
+ val = simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}")))
+ return {slot => val}
+
+ when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/
+ val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ if val =~ /^[0-9]/
+ return {slot => list(val)}
+ else
+ return {slot => val}
+ end
+
+ when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/
+ val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ return {slot => val}
+
+ when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
+ val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ if val.empty?
+ return {slot => nil}
+ else
+ return {slot => TkVarAccess.new(val)}
+ end
+
+ else
+ val = tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)) << "-#{slot}"))
+ if val.index('{')
+ return {slot => tk_split_list(val)}
+ else
+ return {slot => tk_tcl2ruby(val)}
+ end
+ end
+
+ else # ! slot
+ ret = {}
+ ret = Hash[*(tk_split_simplelist(tk_call_without_enc(*(__item_confinfo_cmd(tagid(tagOrId)))), false, false))].to_a.collect{|conf|
+ conf[0] = conf[0][1..-1] if conf[0][0] == ?-
+
+ optkey = conf[0]
+ case optkey
+ when /^(#{__item_val2ruby_optkeys(tagid(tagOrId)).keys.join('|')})$/
+ method = _symbolkey2str(__item_val2ruby_optkeys(tagid(tagOrId)))[optkey]
+ optval = conf[1]
+ begin
+ val = method.call(tagOrId, optval)
+ rescue => e
+ warn("Warning:: #{e.message} (when #{method}.call(#{tagOrId.inspect}, #{optval.inspect})") if $DEBUG
+ val = optval
+ end
+ conf[1] = val
+
+ when /^(#{__item_strval_optkeys(tagid(tagOrId)).join('|')})$/
+ # do nothing
+
+ when /^(#{__item_numval_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ conf[1] = number(conf[1])
+ rescue
+ conf[1] = nil
+ end
+
+ when /^(#{__item_numstrval_optkeys(tagid(tagOrId)).join('|')})$/
+ conf[1] = num_or_str(conf[1])
+
+ when /^(#{__item_boolval_optkeys(tagid(tagOrId)).join('|')})$/
+ begin
+ conf[1] = bool(conf[1])
+ rescue
+ conf[1] = nil
+ end
+
+ when /^(#{__item_listval_optkeys(tagid(tagOrId)).join('|')})$/
+ conf[1] = simplelist(conf[1])
+
+ when /^(#{__item_numlistval_optkeys(tagid(tagOrId)).join('|')})$/
+ if conf[1] =~ /^[0-9]/
+ conf[1] = list(conf[1])
+ end
+
+ when /^(#{__item_tkvariable_optkeys(tagid(tagOrId)).join('|')})$/
+ if conf[1].empty?
+ conf[1] = nil
+ else
+ conf[1] = TkVarAccess.new(conf[1])
+ end
+
+ else
+ if conf[1].index('{')
+ return [slot, tk_split_list(conf[1])]
+ else
+ return [slot, tk_tcl2ruby(conf[1])]
+ end
+ end
+
+ ret[conf[0]] = conf[1]
+ }
+
+ __item_font_optkeys(tagid(tagOrId)).each{|optkey|
+ optkey = optkey.to_s
+ fontconf = ret[optkey]
+ if fontconf.kind_of?(Array)
+ ret.delete(optkey)
+ ret.delete('latin' << optkey)
+ ret.delete('ascii' << optkey)
+ ret.delete('kanji' << optkey)
+ fontconf[1] = tagfontobj(tagid(tagOrId), optkey)
+ ret[optkey] = fontconf
+ end
+ }
+
+ __item_methodcall_optkeys(tagid(tagOrId)).each{|optkey, method|
+ ret[optkey.to_s] = self.__send__(method, tagOrId)
+ }
+
+ ret
end
end
- private :__item_listval_optkeys
+ end
+ end
+
+ ###################
- alias __itemcget itemcget
- alias __itemconfigure itemconfigure
- alias __itemconfiginfo itemconfiginfo
- alias __current_itemconfiginfo current_itemconfiginfo
+ def __item_cget_cmd(id)
+ [self.path, id[0], id[1]]
+ end
+ private :__item_cget_cmd
- private :__itemcget, :__itemconfigure
- private :__itemconfiginfo, :__current_itemconfiginfo
+ def __item_config_cmd(id)
+ [self.path, id[0], id[1]]
+ end
+ private :__item_config_cmd
- # Treeview Item
- def itemcget(tagOrId, option)
- __itemcget([:item, tagOrId], option)
- end
- def itemconfigure(tagOrId, slot, value=None)
- __itemconfigure([:item, tagOrId], slot, value)
- end
- def itemconfiginfo(tagOrId, slot=nil)
- __itemconfiginfo([:item, tagOrId], slot)
- end
- def current_itemconfiginfo(tagOrId, slot=nil)
- __current_itemconfiginfo([:item, tagOrId], slot)
- end
+ def __item_numstrval_optkeys(id)
+ case id[0]
+ when :item, 'item'
+ ['width']
+ when :column, 'column'
+ super(id[1]) + ['minwidth']
+ when :tag, 'tag'
+ super(id[1])
+ when :heading, 'heading'
+ super(id[1])
+ else
+ super(id[1])
+ end
+ end
+ private :__item_numstrval_optkeys
- # Treeview Column
- def columncget(tagOrId, option)
- __itemcget([:column, tagOrId], option)
+ def __item_strval_optkeys(id)
+ case id[0]
+ when :item, 'item'
+ super(id) + ['id']
+ when :column, 'column'
+ super(id[1])
+ when :tag, 'tag'
+ super(id[1])
+ when :heading, 'heading'
+ super(id[1])
+ else
+ super(id[1])
+ end
+ end
+ private :__item_strval_optkeys
+
+ def __item_boolval_optkeys(id)
+ case id[0]
+ when :item, 'item'
+ ['open']
+ when :column, 'column'
+ super(id[1]) + ['stretch']
+ when :tag, 'tag'
+ super(id[1])
+ when :heading, 'heading'
+ super(id[1])
+ end
+ end
+ private :__item_boolval_optkeys
+
+ def __item_listval_optkeys(id)
+ case id[0]
+ when :item, 'item'
+ ['values']
+ when :column, 'column'
+ []
+ when :heading, 'heading'
+ []
+ else
+ []
+ end
+ end
+ private :__item_listval_optkeys
+
+ def __item_val2ruby_optkeys(id)
+ case id[0]
+ when :item, 'item'
+ {
+ 'tags'=>proc{|arg_id, val|
+ simplelist(val).collect{|tag|
+ Tk::Tile::Treeview::Tag.id2obj(self, tag)
+ }
+ }
+ }
+ when :column, 'column'
+ {}
+ when :heading, 'heading'
+ {}
+ else
+ {}
+ end
+ end
+ private :__item_val2ruby_optkeys
+
+ def __tile_specific_item_optkeys(id)
+ case id[0]
+ when :item, 'item'
+ []
+ when :column, 'column'
+ []
+ when :heading, 'heading'
+ ['state'] # On tile-0.7.{2-8}, 'state' options has no '-' at its head.
+ else
+ []
+ end
+ end
+ private :__item_val2ruby_optkeys
+
+ def itemconfiginfo(tagOrId, slot = nil)
+ __itemconfiginfo_core(tagOrId, slot)
+ end
+
+ def current_itemconfiginfo(tagOrId, slot = nil)
+ if TkComm::GET_CONFIGINFO_AS_ARRAY
+ if slot
+ org_slot = slot
+ begin
+ conf = __itemconfiginfo_core(tagOrId, slot)
+ if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
+ || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
+ return {conf[0] => conf[-1]}
+ end
+ slot = conf[__item_configinfo_struct(tagid(tagOrId))[:alias]]
+ end while(org_slot != slot)
+ fail RuntimeError,
+ "there is a configure alias loop about '#{org_slot}'"
+ else
+ ret = {}
+ __itemconfiginfo_core(tagOrId).each{|conf|
+ if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
+ || conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
+ ret[conf[0]] = conf[-1]
+ end
+ }
+ ret
end
- def columnconfigure(tagOrId, slot, value=None)
- __itemconfigure([:column, tagOrId], slot, value)
+ else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
+ ret = {}
+ __itemconfiginfo_core(tagOrId, slot).each{|key, conf|
+ ret[key] = conf[-1] if conf.kind_of?(Array)
+ }
+ ret
+ end
+ end
+
+ alias __itemcget itemcget
+ alias __itemcget_strict itemcget_strict
+ alias __itemconfigure itemconfigure
+ alias __itemconfiginfo itemconfiginfo
+ alias __current_itemconfiginfo current_itemconfiginfo
+
+ private :__itemcget, :__itemcget_strict
+ private :__itemconfigure, :__itemconfiginfo, :__current_itemconfiginfo
+
+ # Treeview Item
+ def itemcget(tagOrId, option)
+ __itemcget([:item, tagOrId], option)
+ end
+ def itemcget_strict(tagOrId, option)
+ __itemcget_strict([:item, tagOrId], option)
+ end
+ def itemconfigure(tagOrId, slot, value=None)
+ __itemconfigure([:item, tagOrId], slot, value)
+ end
+ def itemconfiginfo(tagOrId, slot=nil)
+ __itemconfiginfo([:item, tagOrId], slot)
+ end
+ def current_itemconfiginfo(tagOrId, slot=nil)
+ __current_itemconfiginfo([:item, tagOrId], slot)
+ end
+
+ # Treeview Column
+ def columncget(tagOrId, option)
+ __itemcget([:column, tagOrId], option)
+ end
+ def columncget_strict(tagOrId, option)
+ __itemcget_strict([:column, tagOrId], option)
+ end
+ def columnconfigure(tagOrId, slot, value=None)
+ __itemconfigure([:column, tagOrId], slot, value)
+ end
+ def columnconfiginfo(tagOrId, slot=nil)
+ __itemconfiginfo([:column, tagOrId], slot)
+ end
+ def current_columnconfiginfo(tagOrId, slot=nil)
+ __current_itemconfiginfo([:column, tagOrId], slot)
+ end
+ alias column_cget columncget
+ alias column_cget_strict columncget_strict
+ alias column_configure columnconfigure
+ alias column_configinfo columnconfiginfo
+ alias current_column_configinfo current_columnconfiginfo
+
+ # Treeview Heading
+ def headingcget_strict(tagOrId, option)
+ if __tile_specific_item_optkeys([:heading, tagOrId]).index(option.to_s)
+ begin
+ # On tile-0.7.{2-8}, 'state' options has no '-' at its head.
+ tk_call(*(__item_cget_cmd([:heading, tagOrId]) << option.to_s))
+ rescue
+ # Maybe, 'state' option has '-' in future.
+ tk_call(*(__item_cget_cmd([:heading, tagOrId]) << "-#{option}"))
end
- def columnconfiginfo(tagOrId, slot=nil)
- __itemconfiginfo([:column, tagOrId], slot)
+ else
+ __itemcget_strict([:heading, tagOrId], option)
+ end
+ end
+ def headingcget(tagOrId, option)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ headingcget_strict(tagOrId, option)
+ else
+ begin
+ headingcget_strict(tagOrId, option)
+ rescue => e
+ begin
+ if current_headingconfiginfo(tagOrId).has_key?(option.to_s)
+ # not tag error & option is known -> error on known option
+ fail e
+ else
+ # not tag error & option is unknown
+ nil
+ end
+ rescue
+ fail e # tag error
+ end
end
- def current_columnconfiginfo(tagOrId, slot=nil)
- __current_itemconfiginfo([:column, tagOrId], slot)
+ end
+ end
+ def headingconfigure(tagOrId, slot, value=None)
+ if slot.kind_of?(Hash)
+ slot = _symbolkey2str(slot)
+ sp_kv = []
+ __tile_specific_item_optkeys([:heading, tagOrId]).each{|k|
+ sp_kv << k << _get_eval_string(slot.delete(k)) if slot.has_key?(k)
+ }
+ tk_call(*(__item_config_cmd([:heading, tagOrId]).concat(sp_kv)))
+ tk_call(*(__item_config_cmd([:heading, tagOrId]).concat(hash_kv(slot))))
+ elsif __tile_specific_item_optkeys([:heading, tagOrId]).index(slot.to_s)
+ begin
+ # On tile-0.7.{2-8}, 'state' options has no '-' at its head.
+ tk_call(*(__item_cget_cmd([:heading, tagOrId]) << slot.to_s << value))
+ rescue
+ # Maybe, 'state' option has '-' in future.
+ tk_call(*(__item_cget_cmd([:heading, tagOrId]) << "-#{slot}" << value))
end
- alias column_cget columncget
- alias column_configure columnconfigure
- alias column_configinfo columnconfiginfo
- alias current_column_configinfo current_columnconfiginfo
-
- # Treeview Heading
- def headingcget(tagOrId, option)
- __itemcget([:heading, tagOrId], option)
+ else
+ __itemconfigure([:heading, tagOrId], slot, value)
+ end
+ self
+ end
+ def headingconfiginfo(tagOrId, slot=nil)
+ __itemconfiginfo([:heading, tagOrId], slot)
+ end
+ def current_headingconfiginfo(tagOrId, slot=nil)
+ __current_itemconfiginfo([:heading, tagOrId], slot)
+ end
+ alias heading_cget headingcget
+ alias heading_cget_strict headingcget_strict
+ alias heading_configure headingconfigure
+ alias heading_configinfo headingconfiginfo
+ alias current_heading_configinfo current_headingconfiginfo
+
+ # Treeview Tag
+ def tagcget(tagOrId, option)
+ __itemcget([:tag, tagOrId], option)
+ end
+ def tagcget_strict(tagOrId, option)
+ __itemcget_strict([:tag, tagOrId], option)
+ end
+ def tagconfigure(tagOrId, slot, value=None)
+ __itemconfigure([:tag, tagOrId], slot, value)
+ end
+ def tagconfiginfo(tagOrId, slot=nil)
+ __itemconfiginfo([:tag, tagOrId], slot)
+ end
+ def current_tagconfiginfo(tagOrId, slot=nil)
+ __current_itemconfiginfo([:tag, tagOrId], slot)
+ end
+ alias tag_cget tagcget
+ alias tag_cget_strict tagcget_strict
+ alias tag_configure tagconfigure
+ alias tag_configinfo tagconfiginfo
+ alias current_tag_configinfo current_tagconfiginfo
+end
+
+########################
+
+class Tk::Tile::Treeview::Item < TkObject
+ ItemID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ Tk::Tile::Treeview::Item::ItemID_TBL.clear
+ }
+ }
+
+ def self.id2obj(tree, id)
+ tpath = tree.path
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ if Tk::Tile::Treeview::Item::ItemID_TBL[tpath]
+ (Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id])? \
+ Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id]: id
+ else
+ id
end
- def headingconfigure(tagOrId, slot, value=None)
- __itemconfigure([:heading, tagOrId], slot, value)
+ }
+ end
+
+ def self.assign(tree, id)
+ tpath = tree.path
+ obj = nil
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ if Tk::Tile::Treeview::Item::ItemID_TBL[tpath] &&
+ Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id]
+ return Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id]
end
- def headingconfiginfo(tagOrId, slot=nil)
- __itemconfiginfo([:heading, tagOrId], slot)
+
+ obj = self.allocate
+ obj.instance_eval{
+ @parent = @t = tree
+ @tpath = tpath
+ @path = @id = id
+ }
+ Tk::Tile::Treeview::Item::ItemID_TBL[tpath] ||= {}
+ Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id] = obj
+ }
+ obj
+ end
+
+ def _insert_item(tree, parent_item, idx, keys={})
+ keys = _symbolkey2str(keys)
+ id = keys.delete('id')
+ if id
+ num_or_str(tk_call(tree, 'insert',
+ parent_item, idx, '-id', id, *hash_kv(keys)))
+ else
+ num_or_str(tk_call(tree, 'insert', parent_item, idx, *hash_kv(keys)))
+ end
+ end
+ private :_insert_item
+
+ def initialize(tree, parent_item = '', idx = 'end', keys = {})
+ if parent_item.kind_of?(Hash)
+ keys = parent_item
+ idx = 'end'
+ parent_item = ''
+ elsif idx.kind_of?(Hash)
+ keys = idx
+ idx = 'end'
+ end
+
+ @parent = @t = tree
+ @tpath = tree.path
+ @path = @id = _insert_item(@t, parent_item, idx, keys)
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ ItemID_TBL[@tpath] = {} unless ItemID_TBL[@tpath]
+ ItemID_TBL[@tpath][@id] = self
+ }
+ end
+ def id
+ @id
+ end
+
+ def cget(option)
+ @t.itemcget(@id, option)
+ end
+ def cget_strict(option)
+ @t.itemcget_strict(@id, option)
+ end
+
+ def configure(key, value=None)
+ @t.itemconfigure(@id, key, value)
+ self
+ end
+
+ def configinfo(key=nil)
+ @t.itemconfiginfo(@id, key)
+ end
+
+ def current_configinfo(key=nil)
+ @t.current_itemconfiginfo(@id, key)
+ end
+
+ def open?
+ cget('open')
+ end
+ def open
+ configure('open', true)
+ self
+ end
+ def close
+ configure('open', false)
+ self
+ end
+
+ def bbox(column=None)
+ @t.bbox(@id, column)
+ end
+
+ def children
+ @t.children(@id)
+ end
+ def set_children(*items)
+ @t.set_children(@id, *items)
+ self
+ end
+
+ def delete
+ @t.delete(@id)
+ self
+ end
+
+ def detach
+ @t.detach(@id)
+ self
+ end
+
+ def exist?
+ @t.exist?(@id)
+ end
+
+ def focus
+ @t.focus_item(@id)
+ end
+
+ def index
+ @t.index(@id)
+ end
+
+ def insert(idx='end', keys={})
+ @t.insert(@id, idx, keys)
+ end
+
+ def move(parent, idx)
+ @t.move(@id, parent, idx)
+ self
+ end
+
+ def next_item
+ @t.next_item(@id)
+ end
+
+ def parent_item
+ @t.parent_item(@id)
+ end
+
+ def prev_item
+ @t.prev_item(@id)
+ end
+
+ def see
+ @t.see(@id)
+ self
+ end
+
+ def selection_add
+ @t.selection_add(@id)
+ self
+ end
+
+ def selection_remove
+ @t.selection_remove(@id)
+ self
+ end
+
+ def selection_set
+ @t.selection_set(@id)
+ self
+ end
+
+ def selection_toggle
+ @t.selection_toggle(@id)
+ self
+ end
+
+ def get_directory
+ @t.get_directory(@id)
+ end
+ alias get_dictionary get_directory
+
+ def get(col)
+ @t.get(@id, col)
+ end
+
+ def set(col, value)
+ @t.set(@id, col, value)
+ end
+end
+
+########################
+
+class Tk::Tile::Treeview::Root < Tk::Tile::Treeview::Item
+ def self.new(tree, keys = {})
+ tpath = tree.path
+ obj = nil
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ if Tk::Tile::Treeview::Item::ItemID_TBL[tpath] &&
+ Tk::Tile::Treeview::Item::ItemID_TBL[tpath]['']
+ obj = Tk::Tile::Treeview::Item::ItemID_TBL[tpath]['']
+ else
+ #super(tree, keys)
+ (obj = self.allocate).instance_eval{
+ @parent = @t = tree
+ @tpath = tree.path
+ @path = @id = ''
+ Tk::Tile::Treeview::Item::ItemID_TBL[@tpath] ||= {}
+ Tk::Tile::Treeview::Item::ItemID_TBL[@tpath][@id] = self
+ }
end
- def current_headingconfiginfo(tagOrId, slot=nil)
- __current_itemconfiginfo([:heading, tagOrId], slot)
+ }
+ obj.configure(keys) if keys && ! keys.empty?
+ obj
+ end
+
+ def initialize(tree, keys = {})
+ # dummy:: not called by 'new' method
+ @parent = @t = tree
+ @tpath = tree.path
+ @path = @id = ''
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ Tk::Tile::Treeview::Item::ItemID_TBL[@tpath] ||= {}
+ Tk::Tile::Treeview::Item::ItemID_TBL[@tpath][@id] = self
+ }
+ end
+end
+
+########################
+
+class Tk::Tile::Treeview::Tag < TkObject
+ include TkTreatTagFont
+
+ TagID_TBL = TkCore::INTERP.create_table
+
+ (Tag_ID = ['tile_treeview_tag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ Tk::Tile::Treeview::Tag::TagID_TBL.mutex.synchronize{
+ Tk::Tile::Treeview::Tag::TagID_TBL.clear
+ }
+ }
+
+ def self.id2obj(tree, id)
+ tpath = tree.path
+ Tk::Tile::Treeview::Tag::TagID_TBL.mutex.synchronize{
+ if Tk::Tile::Treeview::Tag::TagID_TBL[tpath]
+ (Tk::Tile::Treeview::Tag::TagID_TBL[tpath][id])? \
+ Tk::Tile::Treeview::Tag::TagID_TBL[tpath][id]: id
+ else
+ id
end
- alias heading_cget headingcget
- alias heading_configure headingconfigure
- alias heading_configinfo headingconfiginfo
- alias current_heading_configinfo current_headingconfiginfo
+ }
+ end
+
+ def initialize(tree, keys=nil)
+ @parent = @t = tree
+ @tpath = tree.path
+ Tag_ID.mutex.synchronize{
+ @path = @id = Tag_ID.join(TkCore::INTERP._ip_id_)
+ Tag_ID[1].succ!
+ }
+ TagID_TBL.mutex.synchronize{
+ TagID_TBL[@tpath] = {} unless TagID_TBL[@tpath]
+ TagID_TBL[@tpath][@id] = self
+ }
+ if keys && keys != None
+ tk_call_without_enc(@tpath, 'tag', 'configure', *hash_kv(keys, true))
+ end
+ end
+ def id
+ @id
+ end
+
+ def bind(seq, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ @t.tag_bind(@id, seq, cmd, *args)
+ self
+ end
+
+ def bind_append(seq, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
end
+ @t.tag_bind_append(@id, seq, cmd, *args)
+ self
+ end
+
+ def bind_remove(seq)
+ @t.tag_bind_remove(@id, seq)
+ self
+ end
+
+ def bindinfo(seq=nil)
+ @t.tag_bindinfo(@id, seq)
+ end
+
+ def cget(option)
+ @t.tagcget(@id, option)
+ end
+ def cget_strict(option)
+ @t.tagcget_strict(@id, option)
+ end
+
+ def configure(key, value=None)
+ @t.tagconfigure(@id, key, value)
+ self
+ end
+
+ def configinfo(key=nil)
+ @t.tagconfiginfo(@id, key)
+ end
+
+ def current_configinfo(key=nil)
+ @t.current_tagconfiginfo(@id, key)
end
end
+########################
+
class Tk::Tile::Treeview < TkWindow
include Tk::Tile::TileWidget
include Scrollable
@@ -146,20 +1016,42 @@ class Tk::Tile::Treeview < TkWindow
WidgetClassName = 'Treeview'.freeze
WidgetClassNames[WidgetClassName] = self
+ def __destroy_hook__
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ Tk::Tile::Treeview::Item::ItemID_TBL.delete(@path)
+ }
+ Tk::Tile::Treeview::Tag::ItemID_TBL.mutex.synchronize{
+ Tk::Tile::Treeview::Tag::ItemID_TBL.delete(@path)
+ }
+ end
+
def self.style(*args)
[self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
end
def tagid(id)
- if id.kind_of?(Array)
+ if id.kind_of?(Tk::Tile::Treeview::Item) ||
+ id.kind_of?(Tk::Tile::Treeview::Tag)
+ id.id
+ elsif id.kind_of?(Array)
[id[0], _get_eval_string(id[1])]
else
_get_eval_string(id)
end
end
+ def root
+ Tk::Tile::Treeview::Root.new(self)
+ end
+
+ def bbox(item, column=None)
+ list(tk_send('item', 'bbox', item, column))
+ end
+
def children(item)
- simplelist(tk_send_without_enc('children', item))
+ simplelist(tk_send_without_enc('children', item)).collect{|id|
+ Tk::Tile::Treeview::Item.id2obj(self, id)
+ }
end
def set_children(item, *items)
tk_send_without_enc('children', item,
@@ -181,55 +1073,84 @@ class Tk::Tile::Treeview < TkWindow
bool(tk_send_without_enc('exists', _get_eval_enc_str(item)))
end
- def focus_item(item = None)
- tk_send('focus', item)
+ def focus_item(item = nil)
+ if item
+ tk_send('focus', item)
+ item
+ else
+ id = tk_send('focus')
+ (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id)
+ end
end
def identify(x, y)
+ # tile-0.7.2 or previous
ret = simplelist(tk_send('identify', x, y))
case ret[0]
- when 'heading', 'separator', 'cell'
+ when 'heading', 'separator'
+ ret[-1] = num_or_str(ret[-1])
+ when 'cell'
+ ret[1] = Tk::Tile::Treeview::Item.id2obj(self, ret[1])
ret[-1] = num_or_str(ret[-1])
+ when 'item', 'row'
+ ret[1] = Tk::Tile::Treeview::Item.id2obj(self, ret[1])
end
end
- def index(item)
- number(tk_send('index', item))
+ def row_identify(x, y)
+ id = tk_send('identify', 'row', x, y)
+ (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id)
end
- def insert(parent, idx, keys={})
- keys = _symbolkey2str(keys)
- id = keys.delete('id')
- if id
- tk_send('insert', parent, idx, '-id', id, *hash_kv(keys))
- else
- tk_send('insert', parent, idx, *hash_kv(keys))
- end
- self
+ def column_identify(x, y)
+ tk_send('identify', 'column', x, y)
end
- def instate(spec, cmd=Proc.new)
- tk_send('instate', spec, cmd)
+ def index(item)
+ number(tk_send('index', item))
end
- def state(spec=None)
- tk_send('state', spec)
+
+ # def insert(parent, idx='end', keys={})
+ # keys = _symbolkey2str(keys)
+ # id = keys.delete('id')
+ # if id
+ # num_or_str(tk_send('insert', parent, idx, '-id', id, *hash_kv(keys)))
+ # else
+ # num_or_str(tk_send('insert', parent, idx, *hash_kv(keys)))
+ # end
+ # end
+ def insert(parent, idx='end', keys={})
+ Tk::Tile::Treeview::Item.new(self, parent, idx, keys)
end
+ # def instate(spec, cmd=Proc.new)
+ # tk_send('instate', spec, cmd)
+ # end
+ # def state(spec=None)
+ # tk_send('state', spec)
+ # end
+
def move(item, parent, idx)
tk_send('move', item, parent, idx)
self
end
- def next(item)
- tk_send('next', item)
+ def next_item(item)
+ id = tk_send('next', item)
+ (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id)
end
- def parent(item)
- tk_send('parent', item)
+ def parent_item(item)
+ if (id = tk_send('parent', item)).empty?
+ Tk::Tile::Treeview::Root.new(self)
+ else
+ Tk::Tile::Treeview::Item.id2obj(self, id)
+ end
end
- def prev(item)
- tk_send('prev', item)
+ def prev_item(item)
+ id = tk_send('prev', item)
+ (id.empty?)? nil: Tk::Tile::Treeview::Item.id2obj(self, id)
end
def see(item)
@@ -238,7 +1159,9 @@ class Tk::Tile::Treeview < TkWindow
end
def selection
- simplelist(tk_send('selection'))
+ simplelist(tk_send('selection')).collect{|id|
+ Tk::Tile::Treeview::Item.id2obj(self, id)
+ }
end
alias selection_get selection
@@ -270,6 +1193,8 @@ class Tk::Tile::Treeview < TkWindow
end
ret
end
+ alias get_dictionary get_directory
+
def get(item, col)
tk_send('set', item, col)
end
@@ -277,4 +1202,37 @@ class Tk::Tile::Treeview < TkWindow
tk_send('set', item, col, value)
self
end
+
+ def tag_bind(tag, seq, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind([@path, 'tag', 'bind', tag], seq, cmd, *args)
+ self
+ end
+ alias tagbind tag_bind
+
+ def tag_bind_append(tag, seq, *args)
+ if TkComm._callback_entry?(args[0]) || !block_given?
+ cmd = args.shift
+ else
+ cmd = Proc.new
+ end
+ _bind_append([@path, 'tag', 'bind', tag], seq, cmd, *args)
+ self
+ end
+ alias tagbind_append tag_bind_append
+
+ def tag_bind_remove(tag, seq)
+ _bind_remove([@path, 'tag', 'bind', tag], seq)
+ self
+ end
+ alias tagbind_remove tag_bind_remove
+
+ def tag_bindinfo(tag, context=nil)
+ _bindinfo([@path, 'tag', 'bind', tag], context)
+ end
+ alias tagbindinfo tag_bindinfo
end
diff --git a/ext/tk/lib/tkextlib/tile/tscale.rb b/ext/tk/lib/tkextlib/tile/tscale.rb
index 7ec72e3515..2c46fd9bd4 100644
--- a/ext/tk/lib/tkextlib/tile/tscale.rb
+++ b/ext/tk/lib/tkextlib/tile/tscale.rb
@@ -7,7 +7,7 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TScale < TkScale
+ class TScale < Tk::Scale
end
Scale = TScale
@@ -17,7 +17,10 @@ module Tk
end
end
-class Tk::Tile::TScale < TkScale
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Scale, :TkScale)
+
+
+class Tk::Tile::TScale < Tk::Scale
include Tk::Tile::TileWidget
if Tk::Tile::USE_TTK_NAMESPACE
diff --git a/ext/tk/lib/tkextlib/tile/tscrollbar.rb b/ext/tk/lib/tkextlib/tile/tscrollbar.rb
index bd49ae18e3..163b8f4713 100644
--- a/ext/tk/lib/tkextlib/tile/tscrollbar.rb
+++ b/ext/tk/lib/tkextlib/tile/tscrollbar.rb
@@ -7,13 +7,16 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TScrollbar < TkScrollbar
+ class TScrollbar < Tk::Scrollbar
end
Scrollbar = TScrollbar
end
end
-class Tk::Tile::TScrollbar < TkScrollbar
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Scrollbar, :TkScrollbar)
+
+
+class Tk::Tile::TScrollbar < Tk::Scrollbar
include Tk::Tile::TileWidget
if Tk::Tile::USE_TTK_NAMESPACE
@@ -28,3 +31,24 @@ class Tk::Tile::TScrollbar < TkScrollbar
[self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
end
end
+
+class Tk::Tile::XScrollbar < Tk::Tile::TScrollbar
+ def create_self(keys)
+ keys = {} unless keys
+ keys['orient'] = 'horizontal'
+ super(keys)
+ end
+ private :create_self
+end
+
+class Tk::Tile::YScrollbar < Tk::Tile::TScrollbar
+ def create_self(keys)
+ keys = {} unless keys
+ keys['orient'] = 'vertical'
+ super(keys)
+ end
+ private :create_self
+end
+
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::XScrollbar, :TkXScrollbar)
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::YScrollbar, :TkYScrollbar)
diff --git a/ext/tk/lib/tkextlib/tile/tseparator.rb b/ext/tk/lib/tkextlib/tile/tseparator.rb
index ca731d4e5b..30fae2c525 100644
--- a/ext/tk/lib/tkextlib/tile/tseparator.rb
+++ b/ext/tk/lib/tkextlib/tile/tseparator.rb
@@ -13,6 +13,9 @@ module Tk
end
end
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Separator, :TkSeparator)
+
+
class Tk::Tile::TSeparator < TkWindow
include Tk::Tile::TileWidget
diff --git a/ext/tk/lib/tkextlib/tkDND/shape.rb b/ext/tk/lib/tkextlib/tkDND/shape.rb
index 570c93b0d9..d44068ed33 100644
--- a/ext/tk/lib/tkextlib/tkDND/shape.rb
+++ b/ext/tk/lib/tkextlib/tkDND/shape.rb
@@ -11,15 +11,15 @@ require 'tkextlib/setup.rb'
# call setup script
require 'tkextlib/tkDND/setup.rb'
-# TkPackage.require('shape', '0.3')
-TkPackage.require('shape')
+# TkPackage.require('Shape', '0.3')
+TkPackage.require('Shape')
module Tk
module TkDND
module Shape
extend TkCore
- PACKAGE_NAME = 'shape'.freeze
+ PACKAGE_NAME = 'Shape'.freeze
def self.package_name
PACKAGE_NAME
end
@@ -27,26 +27,28 @@ module Tk
=begin
def self.package_version
begin
- TkPackage.require('shape')
+ TkPackage.require('Shape')
rescue
''
end
end
=end
- def self.package_version
- Tk.tk_call('set', 'shape_version')
- end
- alias shape_version package_version
+ class << self
+ def package_version
+ Tk.tk_call('set', 'shape_version')
+ end
+ alias shape_version package_version
- def self.package_patchlevel
- Tk.tk_call('set', 'shape_patchlevel')
- end
- alias shape_patchlevel package_patchlevel
+ def package_patchlevel
+ Tk.tk_call('set', 'shape_patchLevel')
+ end
+ alias shape_patchlevel package_patchlevel
- def self.version
- tk_call('shape', 'version')
+ def version
+ tk_call('shape', 'version')
+ end
+ alias xshape_version version
end
- alias xshape_version version
############################
diff --git a/ext/tk/lib/tkextlib/tkDND/tkdnd.rb b/ext/tk/lib/tkextlib/tkDND/tkdnd.rb
index a040532eb6..9a9b2dc42c 100644
--- a/ext/tk/lib/tkextlib/tkDND/tkdnd.rb
+++ b/ext/tk/lib/tkextlib/tkDND/tkdnd.rb
@@ -57,6 +57,24 @@ module Tk
nil
]
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
# setup tables
_setup_subst_table(KEY_TBL, PROC_TBL);
end
diff --git a/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb b/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb
index 8527f61df1..d893a83cf2 100644
--- a/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb
+++ b/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb
@@ -39,7 +39,10 @@ class Tk::HTML_Widget::ClippingWindow
WidgetClassNames[WidgetClassName] = self
HtmlClip_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ HtmlClip_TBL.clear }
+
+ TkCore::INTERP.init_ip_env{
+ HtmlClip_TBL.mutex.synchronize{ HtmlClip_TBL.clear }
+ }
def self.new(parent, keys={})
if parent.kind_of?(Hash)
@@ -54,7 +57,9 @@ class Tk::HTML_Widget::ClippingWindow
else
ppath = ''
end
- return HtmlClip_TBL[ppath] if HtmlClip_TBL[ppath]
+ HtmlClip_TBL.mutex.synchronize{
+ return HtmlClip_TBL[ppath] if HtmlClip_TBL[ppath]
+ }
widgetname = keys.delete('widgetname')
if widgetname =~ /^(.*)\.[^.]+$/
@@ -62,7 +67,9 @@ class Tk::HTML_Widget::ClippingWindow
if ppath2[0] != ?.
ppath2 = ppath + '.' + ppath2
end
- return HtmlClip_TBL[ppath2] if HtmlClip_TBL[ppath2]
+ HtmlClip_TBL.mutex.synchronize{
+ return HtmlClip_TBL[ppath2] if HtmlClip_TBL[ppath2]
+ }
ppath = ppath2
end
@@ -79,7 +86,9 @@ class Tk::HTML_Widget::ClippingWindow
@parent = parent
@ppath = parent.path
@path = @id = @ppath + '.x'
- HtmlClip_TBL[@ppath] = self
+ HtmlClip_TBL.mutex.synchronize{
+ HtmlClip_TBL[@ppath] = self
+ }
end
def method_missing(m, *args, &b)
diff --git a/ext/tk/lib/tkextlib/tktable/tktable.rb b/ext/tk/lib/tkextlib/tktable/tktable.rb
index 4edaabc847..f6cf24b40f 100644
--- a/ext/tk/lib/tkextlib/tktable/tktable.rb
+++ b/ext/tk/lib/tkextlib/tktable/tktable.rb
@@ -77,6 +77,9 @@ module Tk::TkTable::ConfigMethod
def tag_cget(tagOrId, option)
itemcget(['tag', tagid(tagOrId)], option)
end
+ def tag_cget_strict(tagOrId, option)
+ itemcget_strict(['tag', tagid(tagOrId)], option)
+ end
def tag_configure(tagOrId, slot, value=None)
itemconfigure(['tag', tagid(tagOrId)], slot, value)
end
@@ -90,6 +93,9 @@ module Tk::TkTable::ConfigMethod
def window_cget(tagOrId, option)
itemcget(['window', tagid(tagOrId)], option)
end
+ def window_cget_strict(tagOrId, option)
+ itemcget_strict(['window', tagid(tagOrId)], option)
+ end
def window_configure(tagOrId, slot, value=None)
if slot == :window || slot == 'window'
value = _epath(value)
@@ -108,8 +114,8 @@ module Tk::TkTable::ConfigMethod
current_itemconfiginfo(['window', tagid(tagOrId)], slot)
end
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
end
#####################################################
@@ -118,23 +124,39 @@ class Tk::TkTable::CellTag
include TkTreatTagFont
CellTagID_TBL = TkCore::INTERP.create_table
- CellTag_ID = ['tktbl:celltag'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ CellTagID_TBL.clear }
+ (CellTag_ID = ['tktbl:celltag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ CellTagID_TBL.mutex.synchronize{ CellTagID_TBL.clear }
+ }
def self.id2obj(table, id)
tpath = table.path
- return id unless CellTagID_TBL[tpath]
- CellTagID_TBL[tpath][id]? CellTagID_TBL[tpath][id] : id
+ CellTagID_TBL.mutex.synchronize{
+ if CellTagID_TBL[tpath]
+ CellTagID_TBL[tpath][id]? CellTagID_TBL[tpath][id] : id
+ else
+ id
+ end
+ }
end
def initialize(parent, keys=nil)
@parent = @t = parent
@tpath - parent.path
- @path = @id = CellTag_ID.join(TkCore::INTERP._ip_id_)
- CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath]
- CellTagID_TBL[@tpath][@id] = self
- CellTag_ID[1].succ!
+ CellTag_ID.mutex.synchronize{
+ @path = @id = CellTag_ID.join(TkCore::INTERP._ip_id_)
+ CellTag_ID[1].succ!
+ }
+ CellTagID_TBL.mutex.synchronize{
+ CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath]
+ CellTagID_TBL[@tpath][@id] = self
+ }
configure(keys) if keys
end
@@ -144,7 +166,9 @@ class Tk::TkTable::CellTag
def destroy
tk_call(@tpath, 'tag', 'delete', @id)
- CellTagID_TBL[@tpath].delete(@id) if CellTagID_TBL[@tpath]
+ CellTagID_TBL.mutex.synchronize{
+ CellTagID_TBL[@tpath].delete(@id) if CellTagID_TBL[@tpath]
+ }
self
end
alias delete destroy
@@ -176,6 +200,9 @@ class Tk::TkTable::CellTag
def cget(key)
@t.tag_cget(@id, key)
end
+ def cget_strict(key)
+ @t.tag_cget_strict(@id, key)
+ end
def configure(key, val=None)
@t.tag_configure(@id, key, val)
end
@@ -189,22 +216,35 @@ end
class Tk::TkTable::NamedCellTag < Tk::TkTable::CellTag
def self.new(parent, name, keys=nil)
- if CellTagID_TBL[parent.path] && CellTagID_TBL[parent.path][name]
- cell = CellTagID_TBL[parent.path][name]
- cell.configure(keys) if keys
- return cell
- else
- super(parent, name, keys)
- end
+ obj = nil
+ CellTagID_TBL.mutex.synchronize{
+ if CellTagID_TBL[parent.path] && CellTagID_TBL[parent.path][name]
+ obj = CellTagID_TBL[parent.path][name]
+ else
+ #super(parent, name, keys)
+ (obj = self.allocate).instance_eval{
+ @parent = @t = parent
+ @tpath = parent.path
+ @path = @id = name
+ CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath]
+ CellTagID_TBL[@tpath][@id] = self
+ }
+ end
+ }
+ obj.configure(keys) if keys && ! keys.empty?
+ obj
end
def initialize(parent, name, keys=nil)
+ # dummy:: not called by 'new' method
@parent = @t = parent
- @tpath - parent.path
+ @tpath = parent.path
@path = @id = name
- CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath]
- CellTagID_TBL[@tpath][@id] = self
- configure(keys) if keys
+ CellTagID_TBL.mutex.synchronize{
+ CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath]
+ CellTagID_TBL[@tpath][@id] = self
+ }
+ configure(keys) if keys && ! keys.empty?
end
end
@@ -220,7 +260,9 @@ class Tk::TkTable
include Tk::ValidateConfigure
def __destroy_hook__
- Tk::TkTable::CelTag::CellTagID_TBL.delete(@path)
+ Tk::TkTable::CelTag::CellTagID_TBL.mutex.synchronize{
+ Tk::TkTable::CelTag::CellTagID_TBL.delete(@path)
+ }
end
def __boolval_optkeys
@@ -258,6 +300,24 @@ class Tk::TkTable
nil
]
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
@@ -291,6 +351,24 @@ class Tk::TkTable
nil
]
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
@@ -322,6 +400,24 @@ class Tk::TkTable
nil
]
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
@@ -356,6 +452,24 @@ class Tk::TkTable
nil
]
+=begin
+ # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) )
+ KEY_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String)
+ end
+ inf
+ }
+
+ PROC_TBL.map!{|inf|
+ if inf.kind_of?(Array)
+ inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String)
+ end
+ inf
+ }
+=end
+
_setup_subst_table(KEY_TBL, PROC_TBL);
end
@@ -746,15 +860,17 @@ class Tk::TkTable
end
def tagid2obj(tagid)
- if Tk::TkTable::CellTag::CellTagID_TBL.key?(@path)
- if Tk::TkTable::CellTag::CellTagID_TBL[@path].key?(tagid)
- Tk::TkTable::CellTag::CellTagID_TBL[@path][tagid]
+ Tk::TkTable::CellTag::CellTagID_TBL.mutex.synchronize{
+ if Tk::TkTable::CellTag::CellTagID_TBL.key?(@path)
+ if Tk::TkTable::CellTag::CellTagID_TBL[@path].key?(tagid)
+ Tk::TkTable::CellTag::CellTagID_TBL[@path][tagid]
+ else
+ tagid
+ end
else
tagid
end
- else
- tagid
- end
+ }
end
def tag_cell(tag, *cells)
@@ -775,13 +891,15 @@ class Tk::TkTable
end
def tag_delete(tag)
tk_send('tag', 'delete', tagid(tag))
- if Tk::TkTable::CellTag::CellTagID_TBL[@path]
- if tag.kind_of? Tk::TkTable::CellTag
- Tk::TkTable::CellTag::CellTagID_TBL[@path].delete(tag.id)
- else
- Tk::TkTable::CellTag::CellTagID_TBL[@path].delete(tag)
+ Tk::TkTable::CellTag::CellTagID_TBL.mutex.synchronize{
+ if Tk::TkTable::CellTag::CellTagID_TBL[@path]
+ if tag.kind_of? Tk::TkTable::CellTag
+ Tk::TkTable::CellTag::CellTagID_TBL[@path].delete(tag.id)
+ else
+ Tk::TkTable::CellTag::CellTagID_TBL[@path].delete(tag)
+ end
end
- end
+ }
self
end
def tag_exist?(tag)
diff --git a/ext/tk/lib/tkextlib/tktrans/tktrans.rb b/ext/tk/lib/tkextlib/tktrans/tktrans.rb
index 665c57af0c..e051c09211 100644
--- a/ext/tk/lib/tkextlib/tktrans/tktrans.rb
+++ b/ext/tk/lib/tkextlib/tktrans/tktrans.rb
@@ -39,7 +39,7 @@ class TkWindow
end
end
-class TkRoot
+class Tk::Root
undef tktrans_set_image, tktrans_get_image
def tktrans_set_image(img)
@@ -51,7 +51,7 @@ class TkRoot
end
end
-class TkToplevel
+class Tk::Toplevel
undef tktrans_set_image, tktrans_get_image
def tktrans_set_image(img)
diff --git a/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb
index 12f7cffabf..e10e6e299e 100644
--- a/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb
+++ b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb