diff options
author | Yukihiro Matsumoto <[email protected]> | 1996-12-24 15:20:58 +0900 |
---|---|---|
committer | Takashi Kokubun <[email protected]> | 2019-08-17 22:09:32 +0900 |
commit | 554b989ba1623b9f6a0b76f00824c83a23fbcbc1 (patch) | |
tree | 71f06227fe259bebaa5ca4bf05cc398184bced68 /ext | |
parent | fca49a8a69a0f6bb4feae74c6cd0e93d7fac8b36 (diff) |
version 0.99.4-961224v0_99_4_961224
https://cache.ruby-lang.org/pub/ruby/1.0/ruby-0.99.4-961224.tar.gz
Tue Dec 24 15:20:58 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.4-961224
* configure.in: charがunsignedかどうかもチェック
* regex.c (SIGN_EXTEND_CHAR): __CHAR_UNSIGNED__にも対応
* pack.c (pack_unpack): 明示的にsigned charを指定.
Mon Dec 23 14:41:23 1996 Yukihiro Matsumoto <[email protected]>
* ruby.c (load_file): 標準入力からのスクリプトで一時ファイルを使わ
ないように
* object.c (f_integer): `0x', `0'などでbaseを解釈するように.
Fri Dec 20 01:44:39 1996 Yukihiro Matsumoto <[email protected]>
* Makefile.in (flock.o): flockに対応
Thu Dec 19 20:13:32 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.4-961219
Wed Dec 18 00:06:48 1996 Yukihiro Matsumoto <[email protected]>
* glob.c (glob_filename): strrchrがマクロの場合に対応
* configure.in: <sys/select.h>をチェック
* ext/kconv/kconv.c: 1.62ベースに
* ext/kconv/kconv.c: Kconvモジュール
* string.c (str_substr): lenが元の文字列より長い時に対応
* parse.y (iterator): 「$bar do .. end」などは許さないように
* parse.y (iterator): FID(foo!,foo?)をdo形式のイテレータにできる.
* missing/flock.c (flock): lockf()を使って代替
* file.c (file_flock): flockを実装
Tue Dec 17 12:13:38 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.4-961217
Fri Dec 13 02:05:03 1996 Yukihiro Matsumoto <[email protected]>
* configure.in: RUBYLIBのカレントを後回し(@mix/awk offline)
* dln.c: AIXに対応した?(@mix/awk offline)
* eval.c (thread_schedule): critical sectionでも明示的なコンテキス
トスイッチは起きないとまずい
* re.c (reg_search): matchに失敗した時に$~をnilに.
* re.c (reg_search): 毎回matchを生成するように
Thu Dec 12 17:03:30 1996 Yukihiro Matsumoto <[email protected]>
* numeric.c (flo_to_s): 2.0.to_s -> 2.0に
* eval.c (thread_save_context): $_, $~をthread毎に保存
* eval.c (thread_kill): main threadではexit(0)
* string.c (str_split_method): 間違った結果を返していた
Thu Dec 12 15:32:48 1996 WATANABE Hirofumi <[email protected]>
* dir.c: CYGWIN32対応
* ext/socket/socket.c: CYGWIN32対応
* io.c: CYGWIN32対応
Thu Dec 12 14:43:51 1996 Jun Kuroda <[email protected]>
* lib/tk.rb: wish4.2も探索候補に含める
* config.guess: JCC対応
Thu Dec 12 00:41:17 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.4-961212
* parse.y (parse_string): """..."""はやはり無くすことにした
* parse.y (parse_regx): %r|...|でterminatorを \ でエスケープできる
ように
* signal.c (posix_signal): sigactionを使うsignal
* configure.in: posix signal/bsd signalの検出
Wed Dec 11 17:47:35 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (thread_schedule): critical sectionではコンテキストスイッ
チが起きないように
* lib/thread.rb: SharedMutexクラス
* lib/jcode.rb: String#scanを使うように
Tue Dec 10 12:21:28 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.3-961210
* string.c (str_split_method): 正規表現に()を含む時にバグ
* lib/jcode.rb: ちょっとましになった
* string.c (tr_setup_table): 置換文字が短すぎる(2文字)のときのバグ
Mon Dec 9 11:38:04 1996 Yukihiro Matsumoto <[email protected]>
* string.c (str_scan): 文字列のマッチを行う.イテレータとしても動
作する
* regex.c (re_copy_registers): allocatedが初期化されていなかった
* re.c (match_to_s): $~の文字列化
* re.c (match_to_a): $~を配列化できるように
* re.c (match_getter): レジスタが初期化されていなかった
Thu Dec 5 11:06:10 1996 Yukihiro Matsumoto <[email protected]>
* string.c (str_split_method): マッチしなかった括弧は空文字列を
pushするべきではない
* string.c (str_succ): アルファベットを含まない文字に対応
Wed Dec 4 10:48:09 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.3-961204
* io.c (io_binmode): DJGPPでのbinmode対応
* sprintf.c (f_sprintf): intの範囲の数値は直接sprintfで変換する
* sprintf.c (f_sprintf): "%02s"に頼らない
* re.c (reg_search): indexでSEGV
Tue Dec 3 10:09:36 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.3-961203
* ext/extmk.rb.in (install): INSTALL_DATAからINSTALLに変更
* dln.c: hpux対応
* string.c (str_aset_method): 負の値を含む範囲でも例外を起こさない
* array.c (ary_replace): 負の値を含む範囲でも例外を起こさない
* array.c (beg_len): beg==endの時,長さ0に
Mon Dec 2 14:07:12 1996 Yukihiro Matsumoto <[email protected]>
* configure.in: HP shl対応
* string.c (str_upto): beg > endの時無限ループに落ちるのを止めた
* range.c (range_each): String#uptoが再定義された場合に対応
* string.c (str_split_method): "ABC".split(/(B)/)が誤動作
Sat Nov 30 01:43:52 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (rb_eval): undefでSEGV
Fri Nov 29 12:17:59 1996 Yukihiro Matsumoto <[email protected]>
* sample/ruby-mode.el (ruby-parse-region): %Q#..#などに対応.しか
し,区切り文字が演算子で行末にある場合には対応できなかった.
* re.c (reg_raise): 例外でもスラッシュをエスケープ
* re.c (reg_inspect): スラッシュをエスケープ
* parse.y (parse_string): `%[QqXxRr](.)..\1'なる文字列形式(テスト
採用)
* parse.y (parse_qstring): '''...'''の形式
* ext/dbm/dbm.c (Init_dbm): 述語key?,value?の追加
* ext/dbm/dbm.c (Init_dbm): includes->include?
* hash.c (Init_Hash): 述語key?,value?,include?の追加
* eval.c (rb_eval): else節が実行されない(うーん)
* string.c (str_sub_iter_s): イテレータブロック内でマッチが行われ
ると位置がずれる(時に無限ループに落ちる)
* string.c (str_resize): lenが0の時sizeの調整が行われなかった
Thu Nov 28 00:59:54 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.3-961128
* parse.y (parse_string): 3-quote styleの文字列(例:"""abc"d"e""")
* configure.in (EXTSTATIC): extを静的にリンクする時にはrubyはdllを
使うように
* io.c (Init_IO): getsの引数が間違っていた
* string.c (str_each_line): RSを明示的に指定できるように
Wed Nov 27 12:37:46 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.3-961127
* eval.c (rb_eval): iver defined? でselfを指定するのを忘れた
* io.c: gets等でRSを明示的に指定できるように
* ext/extmk.rb.in (install): static linkに失敗
Tue Nov 26 10:33:04 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.3-961126
* string.c (str_sub_s): 置換後の文字列長さが間違っていた
Mon Nov 25 09:11:22 1996 Yukihiro Matsumoto <[email protected]>
* numeric.c (fix_rshift): 32以上の右シフトで0を返すように(Cの
rshiftは(x>>(y%32))を返していた).
* string.c (str_gsub): 置換が行われない場合があった
* string.c (str_resize): 本当に必要な時だけrealloc
Thu Nov 21 04:13:21 1996 Yukihiro Matsumoto <[email protected]>
* configure.in (EXTSTATIC): --with-static-linked-extで全てのモジュー
ルを静的リンクするように
* pack.c (pack_unpack): 行末の改行がない時にもチェックサムをスキッ
プするように
Wed Nov 20 96 21:42:51 1996 Yasuo OHBA <[email protected]>
* configure.in: freebsd対応
Wed Nov 20 10:24:24 1996 Yukihiro Matsumoto <[email protected]>
* ext/extmk.rb.in (install): 通常リンク用のLDFLAGSとダイナミックリ
ンク用のDLDFALGSを分離
* ext/extmk.rb.in (install): コンパイルの成功したものを静的リンク
のリストに追加する
* eval.c (f_missing): オブジェクトの文字列表現が長すぎる時バッファ
を書き潰していた
* process.c (proc_exec_v): forkした後例外を発生させてはいけない
Tue Nov 19 13:28:15 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.3-961119
* eval.c (mod_method_defined): Module#method_defined? の追加
* parse.y (call_args): 引数が唯一のコマンドコールである時のバグ(戻
り値が展開されてしまう)
Mon Nov 18 13:28:18 1996 Yukihiro Matsumoto <[email protected]>
* string.c (str_sub): 失敗した時にnilを返していた
* string.c (str_split_method): 検索開始位置が移動してなかった
* ext/socket/socket.c (sock_s_getservbyaname): まだ間違っていた
* version 0.99.3-961118
* string.c (str_sub_s): 元の文字列を置換するのを止めた
* pack.c (encodes): 領域外をアクセスしていた
Fri Nov 15 17:10:35 1996 Yukihiro Matsumoto <[email protected]>
* bignum.c (big_divmod): Bignumが引数の場合の対応忘れ
* sample/ruby-mode.el (ruby-expr-beg): word?形式への対応が不完全
Wed Nov 13 15:42:40 1996 Yukihiro Matsumoto <[email protected]>
* string.c (str_tr_s_bang): tr_sでtrが行われていなかった
* eval.c (rb_eval): autoloadクラスのチェック
* string.c (f_sub): subがsub!と同じ動作になっていた
* eval.c (thread_sleep): stopとsleepの分離
Mon Nov 11 13:53:19 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.3-961111
* numeric.c (fix_step): to, stepが整数以外の場合に対応
* eval.c (rb_call): dynamic varがdynamic scopingになっていた(これ
はまずい)
* string.c (str_chop_bang): 長さ0の文字列のchopで,領域外のアクセ
スが発生していた.
* parse.y (yyerror): 割り当てた領域外をアクセスしていた
Fri Nov 8 11:54:46 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (thread_yield): scopeをheapにコピー
Thu Nov 7 09:56:53 1996 Yukihiro Matsumoto <[email protected]>
* numeric.c (num_coerce): とりあえず両辺をFloatに変換することに
Wed Nov 6 10:45:13 1996 Yasuo OHBA <[email protected]>
* lib/parsearg.rb: 第2引数を変更.
Tue Nov 5 14:21:09 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.3-961105
Sat Nov 2 01:11:40 1996 Yukihiro Matsumoto <[email protected]>
* bignum.c (big_pow): typo (dy -> dx)
* bignum.c (big_divmod): 知らない型はfloatに変換してみる
* numeric.c (fix_lshift): 境界条件のバグ(負になっていた)
* bignum.c (big_pow): 無駄なfloatへの変換をなくした
* math.c (math_atan2): typo(x -> y)
Fri Nov 1 15:30:59 1996 Yukihiro Matsumoto <[email protected]>
* ext/socket/socket.c (sock_gethostname): gethostnameがない時には
unameを使ってホスト名を得る
* ext/etc/etc.c (etc_getlogin): getloginがNULLを返しても環境変数を
調べるように
* object.c (krn_clone): オブジェクトのフラグもコピー
* hash.c (rb_cmp): ハッシュの比較を`=='でなく`eql?'に変更
* math.c (Need_Float): Float()を使って変換する
* compar.c (cmp_gt): 以前の右辺を返す仕様の名残が残っていた
Thu Oct 31 12:55:51 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.3-961031
* numeric.c (Init_Numeric): typo
* eval.c (error_print): 長すぎるtrace backを途中省略する
* regex.c (re_compile_pattern): 全角のrangeに対応
Wed Oct 30 03:03:18 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.3-961030
* io.c (f_ungetc): 関数を追加
* eval.c (dyna_var_asgn): return値忘れ
Tue Oct 29 10:05:28 1996 Yukihiro Matsumoto <[email protected]>
* string.c (f_split): 関数splitを追加
* eval.c (rb_call): ネストした外側のクラス/モジュールの定数を参照
できるように
Mon Oct 28 09:51:03 1996 Yukihiro Matsumoto <[email protected]>
* string.c (str_sub): offsetが文字の末尾にある時のチェック
* regex.c (re_match): 割り当てるレジスタの数が1多かった
* io.c (io_gets): $/ = ""の動作をperlに合わせる(awkとはちょっと違
うらしい)
* io.c (io_gets): $/ = nilの時少し高速化
* string.c (str_split_method): 括弧がnullにマッチした時にも無視し
ないように
* string.c (str_split_method): 括弧にマッチした分はlimitの数に含め
ないように.
* numeric.c (num_coerce_bin): coerceの定義を変更,2要素の配列
[x,y]を返すように
* sample/ruby-mode.el (ruby-calculate-indent): "do |aa|"の対応を改
善した.
Sat Oct 26 01:43:51 1996 Yukihiro Matsumoto <[email protected]>
* ext/marshal/marshal.c (w_object): ビルトインクラスのサブクラスを
正しく復旧できるように
* ext/marshal/marshal.c (w_object): ユーザ定義dumpの優先
* numeric.c (flo_coerce): Float()を使って定義
* numeric.c (Init_Numeric): Numericのnewのundefはまずい
* ext/marshal/marshal.c (w_symbol): シンボルの内容(文字列)は一度し
かファイルに書き出さない.
* sample/ruby-mode.el (ruby-parse-region): if/while修飾子に対応し
なくなっていた
* bignum.c (Init_Bignum): Bignum.newを除く
* eval.c (rb_eval): 引数評価後にファイル名と行番号を再設定
* numeric.c (flo_div): typo
* sample/ruby-mode.el (ruby-parse-region): def /, def `に対応
Fri Oct 25 09:26:29 1996 Yukihiro Matsumoto <[email protected]>
* sample/ruby-mode.el (ruby-calculate-indent): "do |aa|"に対応
* array.c (ary_aset): indexがfixnumの場合ちょっと高速化
* eval.c (thread_fd_writable): 書き込み前のselectチェック
* array.c (ary_assoc): 無限ループに落ちた
* eval.c (thread_wait_for): selectがエラー終了した時,linux以外で
の動作が正しくなかった.
Thu Oct 24 08:26:48 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (backtrace): `$@'を文字列から配列に変更した.
* eval.c (eval): eval中の例外発生位置を保存する
* bignum.c (bigsub): オペランドの大小比較の失敗
* re.c (reg_search): 直接参照がない時にも`$~'がセットされるように
Wed Oct 23 10:40:10 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.2-961023
* ext/marshal/marshal.c (r_bytes): mallocをやめ,allocaを使う
* sample/ruby-mode.el (ruby-calculate-indent): 括弧の対応を変更.
()内ではインデントをレベルを合わせるように
Tue Oct 22 12:59:11 1996 Yukihiro Matsumoto <[email protected]>
* hash.c (hash_s_new): sizeを指定できるように
* ext/marshal/marshal.c (w_object): dumpする深さ制限を指定できるよ
うに
* array.c (ary_s_new): sizeを指定した時の初期化忘れ
* object.c (f_float): big2dblの宣言忘れ.
* bignum.c (bigsub): 大きさの近いBignum同士の演算で結果が負になる
場合に間違いがあった.
* array.c (ary_aset): 置換先と置換元が同じ長さの時内容を
shift(memmove)しないように.
* ext/marshal/marshal.c (marshal_dump): ファイルフォーマットにバー
ジョンを埋め込むように
* ext/marshal/marshal.c (tmpnam): linux-aout-dln用に定義
Mon Oct 21 08:40:20 1996 Yukihiro Matsumoto <[email protected]>
* ext/socket/socket.c (sock_s_gethostbyname): hostent構造体の情報
を返す
(sock_s_gethostbyaddr): IPアドレスからhostent構造体を得る
(sock_s_getservbyaname): getservbyname(3)
Fri Oct 18 10:37:36 1996 Yukihiro Matsumoto <[email protected]>
* sample/ruby-mode.el (ruby-indent-to): 移動先カラムが負になるバグ
* eval.c (compile): evalで元ソースの行番号でエラーを表示する
Thu Oct 17 09:52:28 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (eval): evalで文法エラーがあった時にSEGV
* lib/safe.rb: Restricted.evalの中だけ制限を加える.
* eval.c (error_print): バックトレースの出力.callerで例外発生位置
を調整した時に問題が出る(そんなことをしなければ良いのだが…)
* eval.c (make_backtrace): バックトレースの生成
Wed Oct 16 12:56:22 1996 Yukihiro Matsumoto <[email protected]>
* ruby-man-0.99.2-jp/index.html: 日本語版ドキュメントの完成(長かった…)
* re.c (reg_regcomp): $=がnilの時の処理
* string.c (f_chop): $_に対するchop
Tue Oct 15 11:04:23 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.2-961015
Mon Oct 14 18:22:38 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (thread_schedule): BOW対応.selectが-1を返した時にバグ(実
はdo .. whileがcontinueで先頭にジャンプすると思い込んでいた.条
件の直前だったのね ^^);;;;;
* sample/ruby-mode.el (ruby-mode-syntax-table): ?のsyntaxが"/"では
まずいらしい
* hash.c (rb_hash): name conflict
Fri Oct 11 00:23:05 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.2-961011
* ext/marshal/marshal.c (w_object): 結局動いていなかった循環オブジェ
クト対応を外した.
* hash.c (rb_hash): Fixnumと文字列の高速化
* ext/marshal/marshal.c (w_object): 無駄なデータの削除(フォーマッ
トの非互換性)
* io.c (io_readline): 戻り値の不備
* ext/marshal/marshal.c (marshal_dumps): MSDOS対応
* ruby.c (load_file): MSDOS対応
Wed Oct 9 17:46:27 1996 Yukihiro Matsumoto <[email protected]>
* ext/extmk.rb.in (install): 無駄なコピーを避ける
* string.c (str_sub_method): マッチがなかった時のString#subの値が
違っていた.
* eval.c (obj_extend): extendした時にobject_extendedを呼ぶように
Tue Oct 8 00:55:38 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (thread_alloc): 割当の平均化
* eval.c (thread_schedule): joinのバグを修正
* eval.c (thread_wait_for): selectへの割込みなどに対応
* eval.c (thread_select): linuxのselectの挙動に対応(timeoutが変化
する)
Mon Oct 7 09:47:19 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.2-961007
* eval.c (PUSH_BLOCK): the_classの保存を忘れていた.
* ext/dbm/dbm.c (fdbm_store): sizeの保存する場所が間違っていた
* ext/socket/socket.c (s_accept): thread対応していなかった
Sat Oct 5 01:32:27 1996 Yukihiro Matsumoto <[email protected]>
* io.c (io_readchar): EOFで例外を発生させる
Fri Oct 4 11:59:54 1996 Yukihiro Matsumoto <[email protected]>
* ext/marshal/marshal.c (w_object): HashとObjectの復旧に必要なハッ
シュテーブルが渡されていなかった.
* variable.c (rb_path2class): ユーザ定義クラスの復旧に失敗していた
* variable.c (rb_path2class): クラスが存在しない時のエラーをFatal
からNameErrorへ.
* range.c (range_s_new): first,lastが両方Numericの時エラーになって
いた.
* range.c: start->first, end->last
Wed Oct 2 02:02:46 1996 Yukihiro Matsumoto <[email protected]>
* file.c: DJGPPでchmod,chownを使えるように(ってDOSにchownがあるのか?)
* class.c (rb_singleton_class): ビルトインクラスもextendしたり特異
メソッドを追加したりできるように
* variable.c (rb_set_class_path): ユーザ定義のトップレベルクラスに
pathを設定しない
* eval.c (eval): 例外がRuntimeErrorに化けていた
* eval.c (eval): eval中の例外の表現の改善
* eval.c (eval): eval_with_bindingとの一本化
* eval.c (rb_eval): クラス/モジュール定義の中から定義中のクラス/モ
ジュールが参照できるように
Tue Oct 1 01:40:09 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.2-961001
* parse.y: cur_crefが2度宣言されていた
* signal.c (trap): SIGSEGV,SIGBUSのない機種に対応
* io.c (Init_IO): 引数タイプの指定間違い
Mon Sep 30 15:28:00 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.2-960930
* config.guess,config.sub: $host_osが正しく設定されない
* eval.c (rb_eval): yieldで正しくないselfが設定されていた
* eval.c (ruby_run): toplevelの例外処理のバグ
Mon Sep 30 09:13:26 1996 WATANABE Hirofumi <[email protected]>
* djgpp対応
Sat Sep 28 02:45:10 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.2-960928
* sample/ruby-mode.el (ruby-beginning-of-block): ブロックの先頭に
移動(正しくインデントしていないと動作しない)
(ruby-end-of-block): 同上
* eval.c (class_s_new): Class#newがイテレータとして呼ばれた時は
initializeもイテレータとして呼ばれるように
* signal.c (sigsegv): SEGVでbacktraceを表示するように
Fri Sep 27 09:51:07 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.2-960927
* eval.c (error_print): 引数のないraiseでメッセージが正しく表示さ
れるように.
* eval.c (rb_longjmp): mesgがnilの時RuntimeErrorを生成する.
* eval.c (f_raise): 引数がない時に対応
* eval.c (thread_mark): stack上にないデータのアドレス変換を行って
いた.
* eval.c (Init_Thread): 割込みの間隔が1秒と長すぎた.
Thu Sep 26 16:02:45 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (thread_schedule): 一度ペンディングになるとフラグがクリア
されていなかった.
* process.c (rb_proc_exec): system/execの引数が空文字列であった場
合,例外を発生すべきだった.
* config.sub/config.guess: 新しいものに置き換え
Thu Sep 26 15:41:35 1996 WATANABE Hirofumi <[email protected]>
* io.c (next_argv): -i.bakをBOWとDOSに対応.
Thu Sep 26 01:31:43 1996 Yukihiro Matsumoto <[email protected]>
* io.c (io_sysread): EOFで例外
* io.c (f_readline): EOFで例外を発生するように.getsは互換性のため
nilを返すままにする
* eval.c (proc_call): lambdaからのreturnでIN_BLOCKフラグが立ったま
まだった
* eval.c (PUSH_BLOCK2): threadに対応するためBlockを一度stackにコピー
Wed Sep 25 11:54:11 1996 Yukihiro Matsumoto <[email protected]>
* parse.y (method_call): Const::method()形式を使えるようにしてみた.
引数括弧は省略できない.
* sample/test.rb: Process.killの存在を確かめてからテストを行う
* eval.c (eval_with_binding): 第2引数としてbinding(またはlambda)を
与えるとその環境でevalを実行するようにした
* eval.c (f_binding): 現在のbindingを返す関数
* eval.c: block構造体にthe_classを保存するメンバを追加
* process.c (Init_process): kill,wait,waitpidをProcessに移動
Tue Sep 24 02:44:43 1996 Yukihiro Matsumoto <[email protected]>
* sample/ruby-mode.el: いろいろ問題が多いので以前の高速化は破棄.
別のアプローチを使った.
* lib/tk.rb (Tk.pack): 複数のウィンドウを受け付けるpack
Sat Sep 21 11:08:09 1996 Yukihiro Matsumoto <[email protected]>
* parse.y (exprs): 空文も受け付けるように文法を変更.今までは改行
の連続だけが許されていた.
Fri Sep 20 11:39:18 1996 Yukihiro Matsumoto <[email protected]>
* Failの大半を名前つき例外に変更.
* re.c (Init_Regexp): 名前つき例外を導入.
* eval.c (f_missing): Objectはinspectしない.
* object.c (inspect_i): Object#inspectでloopに対応.
* regex.c (re_search): /^$/が""にマッチしなかった.
Thu Sep 19 19:25:12 1996 Yukihiro Matsumoto <[email protected]>
* regex.c (re_search): /^$/が非空行にマッチしていた.
Tue Sep 17 10:28:11 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.2-960917
Mon Sep 16 10:47:56 1996 Yukihiro Matsumoto <[email protected]>
* sample/ruby-mode.el (ruby-calculate-indent): 演算子継続の場合の
文字列の判定のバグ
* sample/ruby-mode.el (ruby-calculate-indent): elseなどの次の行の
インデント計算を正しく.
Sat Sep 14 08:37:19 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.2-960914
Fri Sep 13 08:06:03 1996 Yukihiro Matsumoto <[email protected]>
* ext/socket/socket.c (tcpaddr): port番号にntohsをつけ忘れ
* dln.c (link_undef): テーブルの種類が間違っていた.
* bignum.c (bigadd): 引き算が発生する時に計算違いが起きていた.
* parse.y (iter_do_block): do..endでもdynamic variableを.
* bignum.c (big_pow): より正確な計算を(整数同士ではfloatに変換しな
い).
Thu Sep 12 13:11:55 1996 Yukihiro Matsumoto <[email protected]>
* variable.c (rb_set_class_path): Stringクラスが初期化される前に
Stringを作っていた.組込みクラスにはpathはいらない
* parse.y (yylex): 0.1が0になっていた
* parse.y (yylex): 行番号の不整合
* gc.c (oblist_live_obj): 今「生きている」全部のオブジェクトを返す
イテレータ.そのクラス(またはサブクラス)の全部のインスタンスを返
すeach_object_ofも定義した.
* class.c (rb_define_class_id): 無駄なクラスを割り当てていた.結果
として未初期化のクラスオブジェクトが存在していた.
Wed Sep 11 00:56:23 1996 Yukihiro Matsumoto <[email protected]>
* parse.y (yylex): octalの定数の検出をより正確に(090はエラーとか).
* bignum.c (big_minus): yがxより大きい場合にエラー.
* parse.y (yylex): エラー行番号の表示をより正確に
* sample/ruby-mode.el (ruby-expr-beg): 変数名が1文字の時誤動作して
いた.
* sample/ruby-mode.el (ruby-calculate-indent): ?/でループに落ちい
たバグを修正.
* enum.c (enum_min,enum_max): sortのようにイテレータとしても動作す
るように.
* enum.c (enum_find_all): typo
Tue Sep 10 12:07:12 1996 Yukihiro Matsumoto <[email protected]>
* node.h (nd_line): NODEのlineをflagsに押し込めてオブジェクトサイ
ズを小さくした.制限:32bit intのマシンの場合,ファイルの行数が
32767を越えると正常に表示されない.
* st.c: hashとcompareの関数メンバを構造体にパック,クラス的な使い
方を行う.1 tableあたり4 byteの節約.
Mon Sep 9 16:35:54 1996 Yukihiro Matsumoto <[email protected]>
* file.c (file_truncate): 提供されない時には特別な例外を発生するよ
うに.
* eval.c (Init_Proc): 不適切な位置のlocal-jumpを例外に.
Sat Sep 7 17:06:15 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (proc_call): まだスコープがスタック上にある時には局所脱出
を有効にする.これで,procを生成してcallすることは,スコープを脱
出しない限り,yieldと同じ意味を持つことになる.
Fri Sep 6 13:30:59 1996 Yukihiro Matsumoto <[email protected]>
* sample/ruby-mode.el (ruby-indent-to): インデントが変わらない時に
はバッファを変更しない.
(ruby-calculate-indent): まず文字列の内部か判断してから,前の行
からパーズを行う.defunが大きくなった時の高速化.
(ruby-in-string-p): 文字列の内部かどうかを判断する関数(以前の
parseから分離)
(ruby-parse-region): 文字列に対する処理をはずす.
(ruby-beginning-of-block): ブロックの先頭に
(ruby-end-of-block): ブロックの末尾に(遅い…)
Thu Sep 5 14:23:07 1996 Yukihiro Matsumoto <[email protected]>
* file.c (file_s_split): [dirname,basename]にsplitする.
* eval.c (rb_eval): evalの中でも定数の値が正しくなるように.これで
定数に関しては静的なスコープが保証されるようになった.
* st.c (rehash): ハッシュ拡大の系数を2から1.79に.割算がより良い値
を返すように.
Thu Sep 5 00:32:07 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (class_superclass) クラスのスーパークラスを返すメソッド.
Wed Sep 4 16:54:56 1996 Yukihiro Matsumoto <[email protected]>
* random.c (f_rand): Bignumやlongの範囲を越えるFloatに対する乱数も
発生できるように.
* struct.c (struct_alloc): Fatalではなく例外を発生させるように(通
常の使用で発生しうる).
* struct.c (struct_s_members): Structの特異メソッドではなく,生成
されたStructクラスの特異メソッドにした.
* st.c (st_init_table): ruby専用にパラメタを固定にした(サイ
ズが減った)
Mon Sep 2 11:37:59 1996 Yukihiro Matsumoto <[email protected]>
* array.c (ary_shift): capaがあまりにも大きい時には領域をREALLOC
(ary_pop): 同上
* string.c (str_inspect): multibyte character 対応にミス.
(str_inspect): unsigned charにしないと符号展開されてしまう
* parse.y (primary): `::'をprimaryに移動 Foo::Bar.Bazがエラーにな
らないように.
* parse.y (primary): オペレータ形式の特異メソッドが定義できない
* random.c (f_rand): maxが0の時に対応
* io.c (io_printf): 関数を定義していたがインタプリタに登録していな
かった.
* file.c (file_s_basename): 第2引数が無い時にエラー.
Thu Aug 29 10:49:40 1996 Yukihiro Matsumoto <[email protected]>
* parse.y (expr): イテレータの新形式に「method do .. end」形式を採
用した.もちろん昔の形式も有効.
* sample/ruby-mode.el (ruby-calculate-indent): endの数の方が多い場
合にもエラーを起こさないように.
Wed Aug 28 09:41:36 1996 Yukihiro Matsumoto <[email protected]>
* numeric.c (upto,downto,step,times): 対象がfixnumの範囲を越えても
動作するように.
Mon Aug 26 10:04:37 1996 Yukihiro Matsumoto <[email protected]>
* missing/setenv.c (envix): typo(missing `== 0' for memcmp)
* dir.c (dir_foreach): foreach(dir open -> read loop -> closeまで)
* io.c (io_foreach): foreach(file open -> read loop -> closeまで)
* Fatalのうち捕捉可能ないくつかを例外に.
Sat Aug 24 23:56:37 1996 Yukihiro Matsumoto <[email protected]>
* bignum.c (bigdivmod): FIX2INT -> INT2FIX 大間違い
Fri Aug 23 18:13:03 1996 Yukihiro Matsumoto <[email protected]>
* regex.c (re_free_registers): allocateしていない時には当然 free
してはいけない.
Thu Aug 22 01:20:35 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (thread_create): 外側から強制終了させられたthreadは
cleanupする必要が無い.
Wed Aug 21 09:57:28 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (thread_create): threadを終了させた大域脱出の情報を
main_threadに渡すように.
* parse.y (call_args): 最終引数に括弧を省略したメソッド呼出しを置
けるように(例: print foo bar, baz == print(foo(bar,baz)))
Tue Aug 20 13:37:16 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (masign): 多重代入とrest引数の動作を合わせて空の配列を代
入するように.
* parse.y (arg): defined?の強度をもうちょっと強く
* eval.c (error_print): -wで例外名も表示するように
* eval.c (rb_eval): 新構文に対応
(handle_rescue): 捕捉する例外を kind_of? で同定
* parse.y (primary): rescueの構文を変更(同定引数の追加,複数rescue)
* Fail()のかなりを適当な例外を使うように
* eval.c (thread_interrupt): Interrupt(今はnon-local jump)は
main-threadに送られるように.
* eval.c (rb_longjmp): $! の内容を文字列から例外クラスに変更
(rb_raise): rb_fail から名称変更
(rb_interrupt): 例外化
(rb_exit): 例外化
* error.c (Init_Exception): 例外クラスの新設(文字列のサブクラス)
Mon Aug 19 19:40:52 1996 Yukihiro Matsumoto <[email protected]>
* signal.c (trap): 古いハンドラを返すように.
Wed Aug 14 00:07:18 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (rb_trap_eval): ハンドラのためにthreadをforkすることを止
めた.
* eval.c (thread_mark): thread毎の $!, $@ をマークし忘れ
* ext/dbm/dbm.c (fdbm_delete): イテレータとして呼ばれた場合,要素
が無ければブロックを評価する.
* hash.c (hash_delete): イテレータとして呼ばれた場合,要素が無けれ
ばブロックを評価する.
* array.c (ary_delete): イテレータとして呼ばれた場合,要素が無けれ
ばブロックを評価する.
* eval.c (rb_interrupt): SIGINTのデフォルトをexitから特別な大域脱
出に.やはり割り込まれた位置の表示が無いのは寂しいので.
Tue Aug 13 01:34:00 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (rb_exit): sub-thread内でのexitもstatusを保存するように
(thread_create): 自thread内のexitに対応
* signal.c (sighandle): SIGINTのデフォルトハンドラはexitするように
(以前は例外を発生していた).
* 例外の一部をFatalに.
* string.c (str_aset): 文字列の置換の対象が部分文字列でなかった時,
例外を発生させないように
* eval.c (proc_call): Procの中からbreak/nextは通し,他のものは通さ
ないように
Mon Aug 12 14:15:09 1996 Yukihiro Matsumoto <[email protected]>
* object.c (krn_type): 文字列を返す
* eval.c (thread_create): sub-thread内でのexitに対応
* numeric.c (fix_type): 文字列を返す
* io.c (f_p): デバッグ用データ表示メソッド
* eval.c (f_missing): nil/TRUE/FALSEを特別扱い
* string.c (str_inspect): 長い文字列を短縮表示.inspectの働きを
human readable stringの生成に統一(re-generatable string は正式に
無くなった).
Sat Aug 10 16:54:21 1996 Yukihiro Matsumoto <[email protected]>
* object.c (Init_Object): kernel/nil/false/trueのクラス名を変更(小
文字に),rubyスクリプトからアクセスできないように.
* eval.c (rb_eval): CONSTANTのアクセス先を単純化.crefを使わない.
* eval.c (f_eval): 特異メソッド内でも定数の値が正しくなるように
Fri Aug 9 12:23:17 1996 Yukihiro Matsumoto <[email protected]>
* array.c (ary_concat): append -> concat Stringに合わせた
* parse.y (yylex): `$;'が使えなかった.
* array.c (ary_push_method): 複数引数を受け付けるように.
(ary_unshift): 複数引数を受け付けるように.
* io.c (io_popen): IO.popenでcommand pipeが開けるように.
* object.c (Init_Object): KernelとNilをruby scriptからアクセスでき
ないように.
Thu Aug 8 01:21:47 1996 Yukihiro Matsumoto <[email protected]>
* object.c (f_integer): 整数への変換関数
(f_float): 実数への変換関数
(f_string): 文字列への変換関数
(f_array): 配列への変換関数
* bignum.c (big_to_i): FIXNUMの範囲でない時はBignumのまま返すよう
に変更.
Wed Aug 7 09:28:38 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99.1-960807
* parse.y (mlhs): 「*foo = 1,2,3」タイプの多重代入も可能に.
* object.c (Init_Object): クラスTrue/Falseをruby scriptからアクセ
スできないように.
* object.c (nil_inspect): inspect表現は"nil"に
* io.c (io_print): nilのprintをnilに.
* object.c (nil_to_s): nilの文字列表現を""に.
Tue Aug 6 01:12:32 1996 Yukihiro Matsumoto <[email protected]>
* dir.c (dir_s_open): file descripterが足りない時にはgcしてからも
う一度openしてみる.
* io.c (rb_fopen): すべてのfopen()についてfile descripterが足りな
い時にはgcしてからもう一度openしてみる.
* ext/socket/socket.c (Init_socket): 定数の追加.
* sample/ruby-mode.el (ruby-indent-to): インデント後のカーソル位置
の調整を正しく.
* gc.c (gc): 割込みチェックを行わない(Cコードの中で安心して
malloc()が使えなくなるので).
* st.c (call_hash_func): signalとthreadによる割込みに対応.
* sig.h (DEFER_INTS): 割込み禁止区間の指定
* eval.c (f_require): threadによるrequireの競合に対応(最初の
requireが終了するまで他のthreadは待つ).
* bignum.c (str2inum): 0x80000000の値が負になっていた
* sprintf.c (f_sprintf): 文字列末尾,行末の単独の`%'に対応
* bignum.c (big_cmp): 比較の結果が逆になる時があった.
Mon Aug 5 10:58:13 1996 Yukihiro Matsumoto <[email protected]>
* process.c (proc_exec_v): 例外のメッセージを分かりやすく.
* ext/dbm/dbm.c (fdbm_store): nilを格納すると要素の削除になる
* ext/dbm/dbm.c: サイズをキャッシュ.
Sat Aug 3 01:52:52 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (rb_fail): `fail'が引数無しで呼ばれた時だけ以前の`$@'を保
存するように.
* eval.c (f_fail): frameの調整
Fri Aug 2 11:26:21 1996 Yukihiro Matsumoto <[email protected]>
* ext/socket/socket.c (bsock_setopt): valとしてTRUE/FALSE/Fixnumも
受け付けるように.
* ext/socket/socket.c (Init_socket): SO_REUSEADDR等の定数の追加
* ext/md5/md5init.c: md5モジュール(初の複数ファイルからなるモジュー
ルでもある)
* ruby.h (Make_Data_Struct): Data: objectのinstance変数に格納 ->
Data型のObjectに(Dir,Time,Proc,Thread,DBM)
Thu Aug 1 11:38:44 1996 Yukihiro Matsumoto <[email protected]>
* ext/dbm/dbm.c (fdbm_store): valueが文字で無い時に対応
Wed Jul 31 10:53:42 1996 Yukihiro Matsumoto <[email protected]>
* ext/socket/socket.c (open_inet): htonsが必要であった
(tcpaddr): ntohlで変換した
* process.c (rb_proc_exec): execvp -> execv
Tue Jul 30 17:48:33 1996 Yukihiro Matsumoto <[email protected]>
* eval.c: `$?'をthread localに
* Makefile.in (install): install時にstripを行う
* configure.in: install時のstripの検出
* configure.in: NEXTSTEP対応
* version 0.99.1-960730
Tue Jul 30 16:40:35 1996 SHIROYAMA Takayuki <[email protected]>
* dln.c (dln_load): NeXT dln(mach-o)対応.configureは未対応
Tue Jul 30 09:46:51 1996 Yukihiro Matsumoto <[email protected]>
* process.c (f_system): 複数引数もとれるように
* process.c (f_exec): 複数引数もとれるように
* array.c (ary_append): 配列(またはEnum)の要素を破壊的に追加
* array.c (ary_plus): Enumはその要素を追加
* file.c (file_s_open): File.openを追加
* struct.c (struct_new): FIX2INTを忘れていた
* file.c (Init_File): exists? -> exist?
* object.c (obj_is_kind_of): is_kind_of? -> kind_of?, is_a?
* object.c (obj_is_instance_of): is_instance_of? -> instance_of?
Mon Jul 29 16:40:02 1996 Yukihiro Matsumoto <[email protected]>
* parse.y (parse_regx): 式展開を行った場合,casefoldの設定ができて
いなかった.
* object.c (true_type): TRUE/FALSEにtypeを実装.
* parse.y (read_escape): 3文字以内のoctalに対応(\0とか)
Fri Jul 26 00:31:45 1996 Yukihiro Matsumoto <[email protected]>
* array.c (ary_reverse_bang): in-placeで配列を反転させる
(ary_sort_bang): in-placeでsortする
(ary_sort): sortした配列を返すように
(ary_delete_at): 指定した位置の要素を削除する
* eval.c (rb_call): stack深さチェックを毎回は行わないように
* error.c (Warning): 実行中のwarningが表示されていなかった
* eval.c (compile): 例外発生を分離.
* eval.c (f_eval): 変数rb_in_evalを正しく管理するように
* ext/dbm/dbm.c (fdbm_store): 格納するkeyを文字列に変換
* eval.c (rb_call): 無限再帰のチェックを大域脱出を行うC methodにも
対応させた.threadのstack深さチェックルーチンを流用.
* parse.y (yylex): 第1引数のunary -/+の判定が間違っていた.
* parse.y (yylex): unary +で数字を余計に読んでいた(ex. +5 -> 55)
Thu Jul 25 12:15:04 1996 Yukihiro Matsumoto <[email protected]>
* parse.y (yylex): 曖昧でない引数に対して警告を出していた.
* eval.c (iterator_p): 引数で呼んでも正しい結果を返すように.
* parse.y: break/next/redo/retryのメソッド化.
* sample/ruby-mode.el (ruby-calculate-indent): nestのチェックミス
* sample/ruby-mode.el (ruby-parse-region): 予約語のチェックを強化
* parse.y (primary): unless/untilの復活
Tue Jul 23 18:50:10 1996 Yukihiro Matsumoto <[email protected]>
* array.c (Array#empty?), Hash.c (Hash#empty?), ext/dbm/dbm.c (DBM#empty?):
空の判定述語
* eval.c (f_unless): ifの逆をするイテレータ
* eval.c (f_until): whileの逆をするイテレータ
* parse.y: notの優先順位をand/orより高く
* parse.y (expr): `!'を引数括弧を省略したcallでも有効に
Mon Jul 22 10:15:38 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99-960722
* array.c (ary_print_on): OFSのNILチェックが不完全
* ruby.c (load_file): 標準入力からのスクリプトが空の時に対応.
* ruby.c (proc_options): -wでは引数無しの時には標準入力からスクリ
プトをとる(-vではたんに終了する).
* array.c (ary_compact): nilの要素を取り除くメソッド
* array.c (ary_nitems): nilでない要素を数えるメソッド
Sun Jul 20 00:51:53 1996 Yukihiro Matsumoto <[email protected]>
* ruby.c (proc_options): -w optionを追加
* parse.y: {}が閉じていない時には展開しない文字列を
Fri Jul 19 16:16:05 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99-960719
* lib/find.rb: 石塚版(pruneの拡張付き)
* file.c (test_l): lstatで調べないとね.
* eval.c (f_throw): 第2引数を省略可能に.
* parse.y (str_extend): {}のネストに対応
Thu Jul 18 18:25:46 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99-960718
* parse.y (str_extend): 文字列中の式展開に \" ' ` / を含む事ができ
るように.
Tue Jul 16 15:55:31 1996 Yukihiro Matsumoto <[email protected]>
* sample/ruby-mode.el (ruby-parse-region): 正規表現内のエスケープ
に対応
* version 0.99-960716
Fri Jul 12 10:06:19 1996 Yukihiro Matsumoto <[email protected]>
* io.c (f_select): 引数のclose check.
* ruby.c (load_file): #!行の引数チェックを第1引数に限定(実をいうと
DOS改行対策)
Wed Jul 10 17:18:35 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99-960710
* time.c (time_s_timegm/time_s_timelocal): 時間を生成するメソッド
Mon Jun 17 15:59:20 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99-960617
* parse.y (yyerror): エラー表示の簡略化.
Wed Jun 12 14:11:01 1996 Yukihiro Matsumoto <[email protected]>
* signal.c (rb_trap_exit): trap 0はthreadを生成せずに処理する.
Fri Jun 7 10:17:01 1996 Yukihiro Matsumoto <[email protected]>
* array.c/hash.c (indexes): 配列1引数のパターンを無くした.配列の
場合は`*ary'を使ってもらおう.
* eval.c (thread_wait_threads): main_threadが終了する前に他の
threadを待つ(強制的には終了させない).
(ruby_run): 他のthreadを待っている間にシグナルが来たら,全thread
を強制終了させる.
* eval.c (rb_fail): メソッド名を`$!'に埋め込む.
* eval.c (thread_create): main_threadのコンテクストがセーブされな
い場合があった.
* process.c (f_sleep): 時間を指定せず,threadがひとつしかない状況
にも対応.
* eval.c (thread_create): create後,fnを呼び出す前にcontext switch
が起きると違うcontextでfnが実行されてしまうバグ.
Mon Jun 3 08:03:17 1996 Yukihiro Matsumoto <[email protected]>
* struct.c (struct_s_def): メンバの指定を文字列,シンボル(FIXNUM)
双方で可能にした.
* ext/etc/etc.c (Init_etc): 構造体オブジェクトをGCから保護した.
* error.c (rb_sys_fail): nil/FALSEを引数として受け付けるように.
Thu May 30 16:19:08 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (thread_select): EINTRに対応.
Wed May 29 11:04:51 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (f_catch): catch/throwを実装した.
Tue May 28 13:30:52 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99-960528
* eval.c (thread_cleanup): main threadが終了すると他のthreadも終了
することの明確化.
* signal.c (trap): SIGINTのデフォルトの設定ミス(本当にSIG_DFLでは
まずかった).rubyではちゃんとハンドルしないと.
* eval.c (thread_interrupt): SIGINTはmain_threadに例外を発生させる
ように.
Mon May 27 15:13:31 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (thread_status): threadの状態を返すメソッド.threadの終了
を待たない.
* eval.c (thread_value): 一種のpromiseを実装するためのメソッド.
* eval.c (thread_join): 待っているthreadが例外を起こした時には,
joinがその例外を発生するように.
* eval.c (thread_create): threadでの例外をpropagateしないように.
Fri May 24 10:47:53 1996 Yukihiro Matsumoto <[email protected]>
* enum.c (Init_Enumerable): `size' as alias to the `length'
* eval.c (thread_save_context): `$@', `$!'をスレッド毎にセーブ.
* eval.c (superclass): エラー表示をより親切に.
Thu May 23 10:38:41 1996 Yukihiro Matsumoto <[email protected]>
* version 0.99-960523
* eval.c (superclass): エラー時にスーパークラス名を(分かれば)表示
するように.
Wed May 22 19:48:42 1996 Yukihiro Matsumoto <[email protected]>
* parse.y (superclass): スーパークラスの指定子を`:'から`<'に変更.
Tue May 21 09:27:59 1996 Yukihiro Matsumoto <[email protected]>
* lib/thread.rb: threadをサポートするクラス(Mutex, Queue).
Mon May 20 09:39:49 1996 Yukihiro Matsumoto <[email protected]>
* time.c (time_cmp): 浮動小数点数も扱えるように.
(time_minus): Time - Timeが浮動小数点数を返すように.
Fri May 17 15:40:10 1996 Yukihiro Matsumoto <[email protected]>
* process.c (rb_proc_exec): Thread対応時にexecの直前に
ITIMER_VIRTUALをリセットする.
Tue May 14 02:12:44 1996 Yukihiro Matsumoto <[email protected]>
* signal.c (sighandle): SIGINTに対してデフォルトで例外を発生させる
のをやめ,status 130でexitするようにした.
* eval.c (thread_schedule): Threadのバグはほとんどとれたようだ.
Fri May 10 11:21:08 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (thread_schedule): ユーザレベルThread機能.効率はともかく
移植性はある.今後,thread間の通信機能を実装する予定.
Thu May 2 21:22:31 1996 Yukihiro Matsumoto <[email protected]>
* time.c (time_timeval): struct timevalを直接返すように(static変数
を使わない).
Wed May 1 17:27:32 1996 Yukihiro Matsumoto <[email protected]>
* process.c (f_sleep): 整数以外のtimeを指定できるように.
Thu Apr 25 08:19:15 1996 Yukihiro Matsumoto <[email protected]>
* file.c (file_s_dirname): ファイル名が"/"を含まない時,"."を返す
ように(GNU dirnameの仕様).
* file.c (file_s_basename): まだnilと0を混同しているソースが残って
いた.
* parse.y (exprs): エラーリカバリを追加.
Wed Apr 24 15:51:05 1996 Yukihiro Matsumoto <[email protected]>
* string.c (str_chop_bang): CRLFの場合2 bytesをchop!するように.
* ext/socket/socket.c (tcp_svr_s_open): まだnilと0を混同しているソー
スが残っていた.
Tue Apr 23 18:14:25 1996 Yukihiro Matsumoto <[email protected]>
* pack.c (pack_pack): "A/a"のバグ.余計なpaddingが入っていた.
Thu Apr 18 13:02:11 1996 Yukihiro Matsumoto <[email protected]>
* configure.in: アーキテクチャ依存部を別ディレクトリにインストール
するように.
* parse.y (yyerror): エラー発生時にエラー行とその位置を表示するよ
うに.
Wed Apr 17 14:22:42 1996 Yukihiro Matsumoto <[email protected]>
* defines.h: SAFE_SIGHANDLEを無くし,危険な選択はできないように.
* io.c (io_ungetc): 新機能.
* ruby.c (load_file): ファイルからの読み込み方式が変わったのに対応.
* parse.y (compile_file): ファイルからの入力を一度全部読み込むのを
止めて,getsを使うことにした.
Wed Apr 10 17:40:11 1996 Yukihiro Matsumoto <[email protected]>
* version 0.98
Tue Apr 9 09:54:30 1996 Yukihiro Matsumoto <[email protected]>
* parse.y (iter_block): イテレータブロックの指定をメソッド呼び出し
に限定.文法の明確化.
* eval.c (rb_eval): 条件式の正規表現の比較をinline化.
* eval.c (rb_eval): defined? の 定義情報(種別)を文字列で返す.
* node.h: NODE_BEGIN -> NODE_RESCUE, NODE_ENSUREに分離.
* eval.c (rb_eval): option -n/-pのトップレベルループのinline展開.
* parse.y (cond0): 条件式中の文字列は比較の対象としない
Wed Mar 27 12:33:54 1996 Tairo Nomura <[email protected]>
* defines.h: NeXT対応
Wed Mar 27 10:02:44 1996 Yukihiro Matsumoto <[email protected]>
* parse.y: 予約語の変更 continue -> next
Mon Mar 25 07:34:37 1996 Yukihiro Matsumoto <[email protected]>
* parse.y (parse_regx): o(once)オプションを追加.
Fri Mar 22 14:25:35 1996 Yukihiro Matsumoto <[email protected]>
* version 0.97d
* eval.c (dyna_var_defined): 動的ローカル変数の定義チェック用ルー
チン.
* parse.y (gettable): eval()の中での動的ローカル変数(既に値を持っ
ているもの)の検出に失敗していた.
Tue Mar 19 10:46:47 1996 Yukihiro Matsumoto <[email protected]>
* version 0.97c
* re.c (reg_s_new): compile時にsegmentation fault.
* parse.y (str_extend): いつもevalするように.
Wed Mar 13 11:00:42 1996 Yukihiro Matsumoto <[email protected]>
* parse.y (str_extend): 文字列中の式展開の不備を無くした.
* parse.y: 下手なエラーリカバリを外した.
Tue Mar 12 12:30:20 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (rescue): 間違ってensureでも例外を捕捉していた.
Wed Mar 6 12:11:03 1996 Yukihiro Matsumoto <[email protected]>
* parse.y (var_extend): 変数展開"#{}"で,任意の式を書けるようにし
た,これで「変数」展開では無くなっちゃったなあ.
* regex.c (init_syntax_once): `_'をwordに追加.
* regex.c (re_compile_pattern): `\w',`\W'の判定をsyntax tableを使
うように.
Tue Feb 27 10:15:32 1996 Yukihiro Matsumoto <[email protected]>
* object.c (obj_inspect): 表示するインスタンス変数が無い時には,
to_sを使う.
* configure.in: dlnの検出を自動的に.
Mon Feb 26 19:55:33 1996 Yukihiro Matsumoto <[email protected]>
* ruby.c (readin): read(2)で一度にファイルが読み込めない場合に対応.
Sat Feb 24 14:47:18 1996 Yukihiro Matsumoto <[email protected]>
* version 0.97b
Fri Feb 23 11:26:02 1996 Yukihiro Matsumoto <[email protected]>
* class.c (rb_define_module): C言語で定義されたモジュールのPATHの
設定忘れ.文字列化でcore dump.
* eval.c (mod_include): 戻り値をnilに.
* version 0.97a
Thu Feb 22 21:03:42 1996 Yukihiro Matsumoto <[email protected]>
* array.c (ary_times): 「配列*文字列」がjoinと同じ働きをするように.
Wed Feb 21 11:18:09 1996 Yukihiro Matsumoto <[email protected]>
* configure.in : fileCountをcache.
* configure.in : LinuxでELF環境を自動的に検出できるよう.
Tue Feb 20 11:18:09 1996 Mitsuhide Satou <[email protected]>
* FreeBSD dynamic link対応.
Fri Feb 16 08:50:01 1996 Yukihiro Matsumoto <[email protected]>
* object.c (obj_inspect): インスタンス変数を持たないオブジェクトも
正しく表示されるように.
Wed Feb 14 16:56:44 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (rb_eval): 条件式の`2..2'など左辺成立直後に右辺が成立する
パターンにバグ.
Tue Feb 13 18:22:22 1996 Yukihiro Matsumoto <[email protected]>
* version 0.97
Fri Feb 9 21:32:55 1996 Yukihiro Matsumoto <[email protected]>
* lib/tkscrollbox.rb: スクロールでtclの設定を行い,ruby<->wishの不
要な通信を無くした.
Wed Feb 7 10:26:52 1996 Yukihiro Matsumoto <[email protected]>
* string.c (str_aref): indexをunsigned intでとっていた.
* string.c (str_aref): 範囲外のindexに対してnilを返す.
* parse.y (special_local_set): `$_'が宣言無しに使われた場合に対応.
関数をvariable.cから移動.
* string.c (str_sub): 置換開始位置が間違っていた.
Tue Feb 6 16:17:31 1996 Yukihiro Matsumoto <[email protected]>
* sample/ruby-mode.el (ruby-parse-region): コメントの読み飛ばしの
バグ.
Fri Feb 2 18:35:28 1996 Yukihiro Matsumoto <[email protected]>
* variable.c (lastline_get): `$_'を`$~'と同じようにSCOPEローカルな
変数にした.
Thu Feb 1 14:14:07 1996 Yukihiro Matsumoto <[email protected]>
* file.c: statのcacheをやめた.
Wed Jan 31 07:13:08 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (proc_s_new): procの中でyieldを呼ばれた時にcore dumpして
いた.とりあえず例外を発生させる.
* variable.c (rb_class2path): singleton classに対応.
* ext/etc/etc.c (Init_etc): struct_defineのターミネータがnilだった
(0でなければならない).
* ext/marshal/marshal.c: TRUE/FALSEを吐き出せるように.
* eval.c (rb_get_method_body): キャッシュのalias対応,いままでは
aliasはキャッシュに入っていなかった.
Tue Jan 30 09:55:13 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (rb_eval): NODE_BLOCK - tail recursive(というほどでもない
が).
* io.c (io_pipe): pipe(2)を実装した.
* eval.c (rb_eval): Qselfをなくした.thread対応への第一歩.先は遠
いが….
* eval.c (proc_call): procの中でのreturnはprocの終了を意味するよう
に.ただし,procからのyieldの中でのreturnは例外を発生する.
Wed Jan 24 11:33:48 1996 Yukihiro Matsumoto <[email protected]>
* version 0.96a
* dir.c (dir_each): `$_'の値を変更するのをやめた.
* io.c (f_readlines): nilとFALSEの分離のあおりで無限ループに落ちて
いた.
* ruby.c (ruby_options): $0の設定ミス.
Tue Jan 23 15:28:21 1996 Yukihiro Matsumoto <[email protected]>
* eval.c (rb_eval): ``は文字列を引数とするメソッド(`)呼び出しのシ
ンタックスシュガーであるとした.
* ruby.c (addpath): `-I'オプションでディレクトリが「前に」追加され
るように変更.
Fri Jan 19 11:23:12 1996 Yukihiro Matsumoto <[email protected]>
* dln.c (load_1): N_INDR対応(出来たような気がする).
Thu Jan 18 18:14:20 1996 Yukihiro Matsumoto <[email protected]>
* ruby.texi: FALSEとnilの分離を反映した.
Tue Jan 16 17:39:23 1996 Yukihiro Matsumoto <[email protected]>
* version 0.96 - とりあえずnilとFALSEを区別する版
Wed Jan 10 15:31:48 1996 Yukihiro Matsumoto <[email protected]>
* re.c (reg_match): マッチしなかった時の戻り値はFALSE.
* object.c (rb_equal): `0 == nil'がTRUEになるバグ.
Tue Jan 9 00:44:58 1996 Yukihiro Matsumoto <[email protected]>
* nilとFALSEが分離可能に変更.
* nilとFALSEと0の区別を厳密に.
* struct.c (struct_new): 引数を0で終る必要が無くなった.
* object.c (inspect_i): オブジェクトのチェックのバグ(Fixnumでcore
dumpしていた).
* range.c (range_to_s): Rangeの表示を改善.
* object.c (true_inspect): TRUEの表示を`TRUE'に.
Mon Jan 8 15:02:33 1996 Yukihiro Matsumoto <[email protected]>
* numeric.c (fix_mul): divide by zero errorが発生した(オーバーフロー
検出のバグ)
* texinfo.texをパッケージに含めた.
Sun Dec 31 00:08:49 1995 Yukihiro Matsumoto <[email protected]>
* eval.c (rb_eval): `::'では,そのクラスで定義された定数を参照する
ように変更.
* string.c (Init_String): eachをeach_lineに戻した.
Thu Dec 28 12:31:55 1995 Yukihiro Matsumoto <[email protected]>
* eval.c (rb_eval): caseの演算子を`=~'から`==='に.
* variable.c (rb_const_set): クラス定数の再定義を許す(同じクラスで
は不可).警告は出す.
Wed Dec 27 13:27:52 1995 Yukihiro Matsumoto <[email protected]>
* version 0.95c
* ext/tkutil/tkutil.c: wishがあってもなくても一応コンパイルだけは
するように.
* lib/tk.rb: 環境変数PATHから{wish|wish4.0}を探すように.
Tue Dec 26 01:03:42 1995 Yukihiro Matsumoto <[email protected]>
* sample/ruby-mode.el (ruby-parse-region): 正規表現の検出強化.
* numeric.c (fix_mul): 乗算のオーバーフロー検出アルゴリズムのバグ.
* ext/extmk.rb.in: ./install-shを使う場合のPATHを調整.
* Makefile.in (install): lib/*.rbを一つずつインストール.
* io.c (io_each_line): イテレータの戻り値をnilで統一.
Fri Dec 22 10:34:32 1995 Yukihiro Matsumoto <[email protected]>
* version 0.95b
* variable.c (f_untrace_var): 第2引数を指定すると特定のtraceを削除
できるように.
* variable.c (f_trace_var): 第2引数がnilの時,traceを削除する.
* lib/tk.rb (file_readable/file_writable): 第2引数をnilにすること
によるevent handlerの削除.
* parse.y (variable): ドキュメントに`__FILE__'と`__LINE__'が残って
いた.`caller(0)'で代用したはずだったのに.
* eval.c (f_eval): $!のリセット.
* error.c (err_sprintf): 勝手に"\n"を付加するのを止めた.
* parse.y (f_arglist): 引数リスト直後のif/whileの読み間違い.
lex_stateの値が設定されていなかった.
Co-authored-by: Jun Kuroda <[email protected]>
Co-authored-by: Mitsuhide Satou <[email protected]>
Co-authored-by: SHIROYAMA Takayuki <[email protected]>
Co-authored-by: Tairo Nomura <[email protected]>
Co-authored-by: WATANABE Hirofumi <[email protected]>
Co-authored-by: Yasuo OHBA <[email protected]>
Diffstat (limited to 'ext')
-rw-r--r-- | ext/Setup | 4 | ||||
-rw-r--r-- | ext/Setup.dj | 8 | ||||
-rw-r--r-- | ext/dbm/MANIFEST | 1 | ||||
-rw-r--r-- | ext/dbm/dbm.c | 188 | ||||
-rw-r--r-- | ext/dbm/dbm.doc | 107 | ||||
-rw-r--r-- | ext/dbm/extconf.rb | 2 | ||||
-rw-r--r-- | ext/etc/etc.c | 36 | ||||
-rw-r--r-- | ext/extmk.rb.in | 148 | ||||
-rw-r--r-- | ext/kconv/MANIFEST | 2 | ||||
-rw-r--r-- | ext/kconv/kconv.c | 1934 | ||||
-rw-r--r-- | ext/marshal/MANIFEST | 1 | ||||
-rw-r--r-- | ext/marshal/extconf.rb | 2 | ||||
-rw-r--r-- | ext/marshal/marshal.c | 519 | ||||
-rw-r--r-- | ext/marshal/marshal.doc | 5 | ||||
-rw-r--r-- | ext/md5/MANIFEST | 6 | ||||
-rw-r--r-- | ext/md5/depend | 2 | ||||
-rw-r--r-- | ext/md5/md5.doc | 36 | ||||
-rw-r--r-- | ext/md5/md5.h | 86 | ||||
-rw-r--r-- | ext/md5/md5c.c | 337 | ||||
-rw-r--r-- | ext/md5/md5init.c | 90 | ||||
-rw-r--r-- | ext/socket/MANIFEST | 1 | ||||
-rw-r--r-- | ext/socket/extconf.rb | 7 | ||||
-rw-r--r-- | ext/socket/socket.c | 426 | ||||
-rw-r--r-- | ext/socket/socket.doc | 227 | ||||
-rw-r--r-- | ext/tkutil/MANIFEST | 2 | ||||
-rw-r--r-- | ext/tkutil/depend | 1 | ||||
-rw-r--r-- | ext/tkutil/extconf.rb | 11 | ||||
-rw-r--r-- | ext/tkutil/tkutil.c | 1 |
28 files changed, 3492 insertions, 698 deletions
@@ -2,6 +2,8 @@ #dbm #etc +#kconv #marshal +#md5 #socket -tkutil +#tkutil diff --git a/ext/Setup.dj b/ext/Setup.dj new file mode 100644 index 0000000000..eb60525de0 --- /dev/null +++ b/ext/Setup.dj @@ -0,0 +1,8 @@ +option nodynamic + +dbm +#etc +marshal +md5 +#socket +#tkutil diff --git a/ext/dbm/MANIFEST b/ext/dbm/MANIFEST index 141b8dd601..8beec6783d 100644 --- a/ext/dbm/MANIFEST +++ b/ext/dbm/MANIFEST @@ -1,5 +1,4 @@ MANIFEST dbm.c -dbm.doc depend extconf.rb diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c index dbdd99c0ca..5d8a12e3f9 100644 --- a/ext/dbm/dbm.c +++ b/ext/dbm/dbm.c @@ -17,10 +17,14 @@ #include <errno.h> VALUE cDBM; -static ID id_dbm; extern VALUE mEnumerable; +struct dbmdata { + int di_size; + DBM *di_dbm; +}; + static void closeddbm() { @@ -28,24 +32,15 @@ closeddbm() } #define GetDBM(obj, dbmp) {\ - DBM **_dbm;\ - Get_Data_Struct(obj, id_dbm, DBM*, _dbm);\ - dbmp = *_dbm;\ - if (dbmp == Qnil) closeddbm();\ + Get_Data_Struct(obj, struct dbmdata, dbmp);\ + if (dbmp->di_dbm == 0) closeddbm();\ } static void free_dbm(dbmp) - DBM **dbmp; + struct dbmdata *dbmp; { - if (*dbmp) dbm_close(*dbmp); -} - -#define MakeDBM(obj, dp) {\ - DBM **_dbm;\ - if (!id_dbm) id_dbm = rb_intern("dbm");\ - Make_Data_Struct(obj,id_dbm,DBM*,Qnil,free_dbm,_dbm);\ - *_dbm=dp;\ + if (dbmp->di_dbm) dbm_close(dbmp->di_dbm); } static VALUE @@ -55,7 +50,8 @@ fdbm_s_open(argc, argv, class) VALUE class; { VALUE file, vmode; - DBM *dbm, **dbm2; + DBM *dbm; + struct dbmdata *dbmp; int mode; VALUE obj; @@ -70,7 +66,7 @@ fdbm_s_open(argc, argv, class) } Check_Type(file, T_STRING); - dbm = Qnil; + dbm = 0; if (mode >= 0) dbm = dbm_open(RSTRING(file)->ptr, O_RDWR|O_CREAT, mode); if (!dbm) @@ -83,8 +79,9 @@ fdbm_s_open(argc, argv, class) rb_sys_fail(RSTRING(file)->ptr); } - obj = obj_alloc(class); - MakeDBM(obj, dbm); + obj = Make_Data_Struct(class,struct dbmdata,0,free_dbm,dbmp); + dbmp->di_dbm = dbm; + dbmp->di_size = -1; return obj; } @@ -93,12 +90,12 @@ static VALUE fdbm_close(obj) VALUE obj; { - DBM **dbmp; + struct dbmdata *dbmp; - Get_Data_Struct(obj, id_dbm, DBM*, dbmp); - if (*dbmp == Qnil) Fail("already closed DBM file"); - dbm_close(*dbmp); - *dbmp = Qnil; + Get_Data_Struct(obj, struct dbmdata, dbmp); + if (dbmp->di_dbm == 0) closeddbm(); + dbm_close(dbmp->di_dbm); + dbmp->di_dbm = 0; return Qnil; } @@ -108,15 +105,17 @@ fdbm_fetch(obj, keystr) VALUE obj, keystr; { datum key, value; + struct dbmdata *dbmp; DBM *dbm; Check_Type(keystr, T_STRING); key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; value = dbm_fetch(dbm, key); - if (value.dptr == Qnil) { + if (value.dptr == 0) { return Qnil; } return str_new(value.dptr, value.dsize); @@ -128,38 +127,47 @@ fdbm_indexes(obj, args) struct RArray *args; { VALUE *p, *pend; - struct RArray *new; + VALUE new; int i = 0; - if (!args || args->len == 1 && TYPE(args->ptr) != T_ARRAY) { - args = (struct RArray*)rb_to_a(args->ptr[0]); - } - - new = (struct RArray*)ary_new2(args->len); + args = (struct RArray*)rb_to_a(args); + new = ary_new2(args->len); p = args->ptr; pend = p + args->len; while (p < pend) { - new->ptr[i++] = fdbm_fetch(obj, *p++); - new->len = i; + ary_push(new, fdbm_fetch(obj, *p++)); } - return (VALUE)new; + return new; } static VALUE fdbm_delete(obj, keystr) VALUE obj, keystr; { - datum key; + datum key, value; + struct dbmdata *dbmp; DBM *dbm; Check_Type(keystr, T_STRING); key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; + + value = dbm_fetch(dbm, key); + if (value.dptr == 0) { + if (iterator_p()) rb_yield(Qnil); + return Qnil; + } + if (dbm_delete(dbm, key)) { + dbmp->di_size = -1; Fail("dbm_delete failed"); } + else if (dbmp->di_size >= 0) { + dbmp->di_size--; + } return obj; } @@ -168,10 +176,12 @@ fdbm_shift(obj) VALUE obj; { datum key, val; + struct dbmdata *dbmp; DBM *dbm; VALUE keystr, valstr; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; key = dbm_firstkey(dbm); if (!key.dptr) return Qnil; @@ -188,17 +198,19 @@ fdbm_delete_if(obj) VALUE obj; { datum key, val; + struct dbmdata *dbmp; DBM *dbm; VALUE keystr, valstr; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { val = dbm_fetch(dbm, key); keystr = str_new(key.dptr, key.dsize); valstr = str_new(val.dptr, val.dsize); - if (rb_yield(assoc_new(keystr, valstr)) - && dbm_delete(dbm, key)) { - Fail("dbm_delete failed"); + if (RTEST(rb_yield(assoc_new(keystr, valstr)))) { + if (dbm_delete(dbm, key)) { + Fail("dbm_delete failed"); + } } } return obj; @@ -209,9 +221,12 @@ fdbm_clear(obj) VALUE obj; { datum key; + struct dbmdata *dbmp; DBM *dbm; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; + dbmp->di_size = -1; for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { if (dbm_delete(dbm, key)) { Fail("dbm_delete failed"); @@ -225,6 +240,7 @@ fdbm_store(obj, keystr, valstr) VALUE obj, keystr, valstr; { datum key, val; + struct dbmdata *dbmp; DBM *dbm; if (valstr == Qnil) { @@ -232,19 +248,26 @@ fdbm_store(obj, keystr, valstr) return Qnil; } - Check_Type(keystr, T_STRING); + keystr = obj_as_string(keystr); + key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; - Check_Type(valstr, T_STRING); + + if (NIL_P(valstr)) return fdbm_delete(obj, keystr); + + valstr = obj_as_string(valstr); val.dptr = RSTRING(valstr)->ptr; val.dsize = RSTRING(valstr)->len; - GetDBM(obj, dbm); + Get_Data_Struct(obj, struct dbmdata, dbmp); + dbmp->di_size = -1; + dbm = dbmp->di_dbm; if (dbm_store(dbm, key, val, DBM_REPLACE)) { dbm_clearerr(dbm); if (errno == EPERM) rb_sys_fail(Qnil); Fail("dbm_store failed"); } + return valstr; } @@ -253,24 +276,56 @@ fdbm_length(obj) VALUE obj; { datum key; + struct dbmdata *dbmp; DBM *dbm; int i = 0; - GetDBM(obj, dbm); + Get_Data_Struct(obj, struct dbmdata, dbmp); + if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size); + dbm = dbmp->di_dbm; + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { i++; } + dbmp->di_size = i; + return INT2FIX(i); } static VALUE +fdbm_empty(obj) + VALUE obj; +{ + datum key; + struct dbmdata *dbmp; + DBM *dbm; + int i = 0; + + Get_Data_Struct(obj, struct dbmdata, dbmp); + if (dbmp->di_size < 0) { + dbm = dbmp->di_dbm; + + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + i++; + } + } + else { + i = dbmp->di_size; + } + if (i == 0) return TRUE; + return FALSE; +} + +static VALUE fdbm_each_value(obj) VALUE obj; { datum key, val; + struct dbmdata *dbmp; DBM *dbm; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { val = dbm_fetch(dbm, key); rb_yield(str_new(val.dptr, val.dsize)); @@ -283,9 +338,11 @@ fdbm_each_key(obj) VALUE obj; { datum key; + struct dbmdata *dbmp; DBM *dbm; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { rb_yield(str_new(key.dptr, key.dsize)); } @@ -298,9 +355,11 @@ fdbm_each_pair(obj) { datum key, val; DBM *dbm; + struct dbmdata *dbmp; VALUE keystr, valstr; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { val = dbm_fetch(dbm, key); @@ -317,11 +376,14 @@ fdbm_keys(obj) VALUE obj; { datum key; + struct dbmdata *dbmp; DBM *dbm; VALUE ary; + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; + ary = ary_new(); - GetDBM(obj, dbm); for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { ary_push(ary, str_new(key.dptr, key.dsize)); } @@ -334,11 +396,14 @@ fdbm_values(obj) VALUE obj; { datum key, val; + struct dbmdata *dbmp; DBM *dbm; VALUE ary; + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; + ary = ary_new(); - GetDBM(obj, dbm); for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { val = dbm_fetch(dbm, key); ary_push(ary, str_new(val.dptr, val.dsize)); @@ -352,13 +417,15 @@ fdbm_has_key(obj, keystr) VALUE obj, keystr; { datum key, val; + struct dbmdata *dbmp; DBM *dbm; Check_Type(keystr, T_STRING); key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; val = dbm_fetch(dbm, key); if (val.dptr) return TRUE; return FALSE; @@ -369,13 +436,15 @@ fdbm_has_value(obj, valstr) VALUE obj, valstr; { datum key, val; + struct dbmdata *dbmp; DBM *dbm; Check_Type(valstr, T_STRING); val.dptr = RSTRING(valstr)->ptr; val.dsize = RSTRING(valstr)->len; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { val = dbm_fetch(dbm, key); if (val.dsize == RSTRING(valstr)->len && @@ -390,10 +459,12 @@ fdbm_to_a(obj) VALUE obj; { datum key, val; + struct dbmdata *dbmp; DBM *dbm; VALUE ary; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; ary = ary_new(); for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { @@ -417,6 +488,7 @@ Init_dbm() rb_define_method(cDBM, "indexes", fdbm_indexes, -2); rb_define_method(cDBM, "length", fdbm_length, 0); rb_define_alias(cDBM, "size", "length"); + rb_define_method(cDBM, "empty?", fdbm_empty, 0); rb_define_method(cDBM, "each", fdbm_each_pair, 0); rb_define_method(cDBM, "each_value", fdbm_each_value, 0); rb_define_method(cDBM, "each_key", fdbm_each_key, 0); @@ -427,9 +499,11 @@ Init_dbm() rb_define_method(cDBM, "delete", fdbm_delete, 1); rb_define_method(cDBM, "delete_if", fdbm_delete_if, 0); rb_define_method(cDBM, "clear", fdbm_clear, 0); - rb_define_method(cDBM, "includes", fdbm_has_key, 1); - rb_define_method(cDBM, "has_key", fdbm_has_key, 1); - rb_define_method(cDBM, "has_value", fdbm_has_value, 1); + rb_define_method(cDBM, "include?", fdbm_has_key, 1); + rb_define_method(cDBM, "has_key?", fdbm_has_key, 1); + rb_define_method(cDBM, "has_value?", fdbm_has_value, 1); + rb_define_method(cDBM, "key?", fdbm_has_key, 1); + rb_define_method(cDBM, "value?", fdbm_has_value, 1); rb_define_method(cDBM, "to_a", fdbm_to_a, 0); } diff --git a/ext/dbm/dbm.doc b/ext/dbm/dbm.doc deleted file mode 100644 index 45f174b7aa..0000000000 --- a/ext/dbm/dbm.doc +++ /dev/null @@ -1,107 +0,0 @@ -.\" dbm.doc - -*- Indented-Text -*- created at: Thu Mar 23 20:28:31 JST 1995 - -** DBM(���饹) - -NDBM�ե�������������륯�饹���������ǡ����Ȥ��ʸ����Ǥʤ���Ф� -��ʤ��Ȥ������¤ȡ��ǡ������ե��������¸�����Ȥ�����������Ƥ� -Dict���饹������Ʊ�ͤ˰������Ȥ��Ǥ��롥NDBM�������Ƥ��ʤ������ƥ�Ǥ� -���Υ��饹���������ʤ��� - -SuperClass: Object - -Included Modules: Enumerable - -Methods: - - self [key] - - key���Ȥ����ͤ��֤��� - - self [key]= value - - key���Ȥ��ơ�value���Ǽ���롥value�Ȥ���nil����ꤹ��ȡ� - key���Ф�����ܤκ���Ȥʤ롥 - - clear - - DBM�ե��������Ȥ���ˤ��롥 - - close - - DBM�ե�������������롥�ʸ�������㳰��ȯ�������롥 - - delete(key) - - key���Ȥ����Ȥ������롥 - - delete_if - - ���Ǥ������륤�ƥ졼����key::value�Ȥ����ڥ���Ϳ���ơ��֥��� - ����ɾ�������ͤ����λ�������������ܤ������롥 - - each - each_pair - - key::value�ʤ�ڥ���Ϳ���륤�ƥ졼���� - - each_key - - ���Ƥ�key���Ф��Ʒ����֤����ƥ졼���� - - each_value - - ���Ƥ�value���Ф��Ʒ����֤����ƥ졼���� - - has_key(key) - includes(key) - - key���ǡ����١������¸�ߤ�����������֤� - - has_value(value) - - value���ͤȤ����Ȥ��ǡ����١������¸�ߤ���������� - �֤� - - indexes(ary) - indexes(key-1, ..., key-n) - - 1���ܤη����Ǥ�ʸ��������������Ȥ��Ƽ����ơ��������Ǥ� - �Ȥ������Ǥ�ޤ�������֤���2���ܤη����Ǥϳư������ͤ��� - �������Ǥ�ޤ�������֤�. - - keys - - �ǡ����١������¸�ߤ��륭�����Ƥ�ޤ�������֤��� - - length - size - - �ǡ����١���������Ǥο����֤���(����:���ߤμ¸��Ǥ����ǿ���� - ���뤿��˥ǡ����١�����������������Τǡ��빽�����Ȥ��⤤���� - ��Ĥ��ƻȤ�����.) - - shift - - �ǡ����١���������Ǥ��ļ��Ф�(�ǡ����١�������������)�� - key::value�Ȥ����ڥ����֤��� - - to_a - - �ǡ����١������key-value�ڥ������ǤȤ���������֤��� - - values - - �ǡ����١������¸�ߤ��������Ƥ�ޤ�������֤��� - -Single Methods: - - open(dbname[, mode]) - - dbname�ǻ��ꤷ���ǡ����١�����⡼�ɤ�mode�����ꤷ�ƥ����ץ� - �롥mode�ξ�ά�ͤ�0666�Ǥ��롥mode�Ȥ���nil����ꤹ��ȥǡ��� - �١���������¸�ߤ��ʤ����ˤϿ����˥����ץ���nil���֤��� - -------------------------------------------------------- -Local variables: -fill-column: 70 -end: diff --git a/ext/dbm/extconf.rb b/ext/dbm/extconf.rb index 5105cd662f..2302ee2d5d 100644 --- a/ext/dbm/extconf.rb +++ b/ext/dbm/extconf.rb @@ -1,4 +1,4 @@ -have_library("dbm", "dbm_open") +have_library("gdbm", "dbm_open") or have_library("dbm", "dbm_open") if have_func("dbm_open") create_makefile("dbm") end diff --git a/ext/etc/etc.c b/ext/etc/etc.c index e4e4098f8a..524800bd03 100644 --- a/ext/etc/etc.c +++ b/ext/etc/etc.c @@ -24,12 +24,16 @@ static VALUE etc_getlogin(obj) VALUE obj; { + char *getenv(); + char *login; + #ifdef HAVE_GETLOGIN char *getlogin(); - char *login = getlogin(); + + login = getlogin(); + if (!login) login = getenv("USER"); #else - char *getenv(); - char *login = getenv("USER"); + login = getenv("USER"); #endif if (login) @@ -42,7 +46,7 @@ static VALUE setup_passwd(pwd) struct passwd *pwd; { - if (pwd == Qnil) rb_sys_fail("/etc/passwd"); + if (pwd == 0) rb_sys_fail("/etc/passwd"); return struct_new(sPasswd, str_new2(pwd->pw_name), str_new2(pwd->pw_passwd), @@ -69,7 +73,8 @@ setup_passwd(pwd) #ifdef PW_EXPIRE INT2FIX(pwd->pw_expire), #endif - Qnil); + 0 /*dummy*/ + ); } #endif @@ -91,7 +96,7 @@ etc_getpwuid(argc, argv, obj) uid = getuid(); } pwd = getpwuid(uid); - if (pwd == Qnil) Fail("can't find user for %d", uid); + if (pwd == 0) Fail("can't find user for %d", uid); return setup_passwd(pwd); #else return Qnil; @@ -107,7 +112,7 @@ etc_getpwnam(obj, nam) Check_Type(nam, T_STRING); pwd = getpwnam(RSTRING(nam)->ptr); - if (pwd == Qnil) Fail("can't find user for %s", RSTRING(nam)->ptr); + if (pwd == 0) Fail("can't find user for %s", RSTRING(nam)->ptr); return setup_passwd(pwd); #else return Qnil; @@ -130,7 +135,7 @@ etc_passwd(obj) return obj; } pw = getpwent(); - if (pw == Qnil) Fail("can't fetch next -- /etc/passwd"); + if (pw == 0) Fail("can't fetch next -- /etc/passwd"); return setup_passwd(pw); #else return Qnil; @@ -155,8 +160,7 @@ setup_group(grp) str_new2(grp->gr_name), str_new2(grp->gr_passwd), INT2FIX(grp->gr_gid), - mem, - Qnil); + mem); } #endif @@ -170,7 +174,7 @@ etc_getgrgid(obj, id) gid = NUM2INT(id); grp = getgrgid(gid); - if (grp == Qnil) Fail("can't find group for %d", gid); + if (grp == 0) Fail("can't find group for %d", gid); return setup_group(grp); #else return Qnil; @@ -186,7 +190,7 @@ etc_getgrnam(obj, nam) Check_Type(nam, T_STRING); grp = getgrnam(RSTRING(nam)->ptr); - if (grp == Qnil) Fail("can't find group for %s", RSTRING(nam)->ptr); + if (grp == 0) Fail("can't find group for %s", RSTRING(nam)->ptr); return setup_group(grp); #else return Qnil; @@ -214,7 +218,7 @@ etc_group(obj) #endif } -VALUE mEtc; +static VALUE mEtc; void Init_etc() @@ -252,9 +256,11 @@ Init_etc() #ifdef PW_EXPIRE "expire", #endif - Qnil); + 0); + rb_global_variable(&sPasswd); #ifdef HAVE_GETGRENT - sGroup = struct_define("Group", "name", "passwd", "gid", "mem", Qnil); + sGroup = struct_define("Group", "name", "passwd", "gid", "mem", 0); + rb_global_variable(&sGroup); #endif } diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in index b61ccd222f..bd4eed306b 100644 --- a/ext/extmk.rb.in +++ b/ext/extmk.rb.in @@ -1,21 +1,24 @@ #! /usr/local/bin/ruby -if $ARGV[0] == 'install' +if ARGV[0] == 'static' + $force_static = TRUE + ARGV.shift +elsif ARGV[0] == 'install' $install = TRUE - $ARGV.shift -end - -if $ARGV[0] == 'clean' + ARGV.shift +elsif ARGV[0] == 'clean' $clean = TRUE - $ARGV.shift + ARGV.shift end +$extlist = [] + $cache_mod = FALSE; $lib_cache = {} $func_cache = {} $hdr_cache = {} -if File.exists?("config.cache") then +if File.exist?("config.cache") then f = open("config.cache", "r") while f.gets case $_ @@ -31,10 +34,10 @@ if File.exists?("config.cache") then end def older(file1, file2) - if !File.exists?(file1) then + if !File.exist?(file1) then return TRUE end - if !File.exists?(file2) then + if !File.exist?(file2) then return FALSE end if File.mtime(file1) < File.mtime(file2) @@ -61,7 +64,7 @@ def have_library(lib, func) end cfile = open("conftest.c", "w") - printf cfile, "\ + cfile.printf "\ int main() { return 0; } int t() { %s(); return 0; } ", func @@ -99,7 +102,7 @@ def have_func(func) end cfile = open("conftest.c", "w") - printf cfile, "\ + cfile.printf "\ char %s(); int main() { return 0; } int t() { %s(); return 0; } @@ -136,7 +139,7 @@ def have_header(header) end cfile = open("conftest.c", "w") - printf cfile, "\ + cfile.printf "\ #include <%s> ", header cfile.close @@ -162,7 +165,7 @@ def create_header() hfile = open("extconf.h", "w") for line in $defs line =~ /^-D(.*)/ - printf hfile, "#define %s 1\n", $1 + hfile.printf "#define %s 1\n", $1 end hfile.close end @@ -180,7 +183,7 @@ def create_makefile(target) $libs = "" if not $libs mfile = open("Makefile", "w") - printf mfile, "\ + mfile.printf "\ SHELL = /bin/sh #### Start of system configuration section. #### @@ -191,36 +194,37 @@ VPATH = @srcdir@ CC = @CC@ CFLAGS = %s #$CFLAGS %s +LDFLAGS = @LDFLAGS@ +DLDFLAGS = @DLDFLAGS@ LDSHARED = @LDSHARED@ ", if $static then "" else "@CCDLFLAGS@" end, $defs.join(" ") - printf mfile, "\ + mfile.printf "\ prefix = @prefix@ -binprefix = exec_prefix = @exec_prefix@ bindir = $(exec_prefix)/bin -libdir = @prefix@/lib/ruby +libdir = @archlib@ @SET_MAKE@ #### End of system configuration section. #### " - printf mfile, "LIBS = %s\n", $libs - printf mfile, "OBJS = " + mfile.printf "LIBS = %s\n", $libs + mfile.printf "OBJS = " if !$objs then $objs = Dir["*.c"] for f in $objs f.sub!(/\.c$/, ".o") end end - printf mfile, $objs.join(" ") - printf mfile, "\n" + mfile.printf $objs.join(" ") + mfile.printf "\n" - printf mfile, "\ + dots = if "@INSTALL@" =~ /^\// then "" else "../" end + mfile.printf "\ TARGET = %s.%s -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ +INSTALL = %s@INSTALL@ all: $(TARGET) @@ -229,56 +233,53 @@ clean:; @rm -f *.o *.so *.sl @rm -f core ruby *~ realclean: clean -", target, if $static then "o" else "@DLEXT@" end +", target, + if $static then "o" else "@DLEXT@" end, dots if !$static - printf mfile, "\ + mfile.printf "\ install: $(libdir)/$(TARGET) $(libdir)/$(TARGET): $(TARGET) @test -d $(libdir) || mkdir $(libdir) - $(INSTALL_DATA) $(TARGET) $(libdir)/$(TARGET) + $(INSTALL) $(TARGET) $(libdir)/$(TARGET) " else - printf mfile, "\ + mfile.printf "\ install:; " end if !$static && "@DLEXT@" != "o" - printf mfile, "\ + mfile.printf "\ $(TARGET): $(OBJS) - $(LDSHARED) -o $(TARGET) $(OBJS) $(LIBS) + $(LDSHARED) $(DLDFLAGS) -o $(TARGET) $(OBJS) $(LIBS) " - elsif !File.exists?(target + ".c") - printf mfile, "\ + elsif !File.exist?(target + ".c") + mfile.printf "\ $(TARGET): $(OBJS) - ld $(LDDLFLAGS) -r $(TARGET) $(OBJS) + ld $(LDFLAGS) -r -o $(TARGET) $(OBJS) " end - if File.exists?("depend") + if File.exist?("depend") dfile = open("depend", "r") - printf mfile, "###\n" + mfile.printf "###\n" while line = dfile.gets() - printf mfile, "%s", line + mfile.printf "%s", line end dfile.close end mfile.close if $static - $extinit += format("\ -\tInit_%s();\n\ -\trb_provide(\"%s.o\");\n\ -", target, target) - $extobjs += format("ext/%s/%s.o ", $static, target) + $extlist.push [$static,target] end end def extmake(target) - if $static_ext[target] + if $force_static or $static_ext[target] $static = target else $static = FALSE @@ -294,19 +295,19 @@ def extmake(target) begin Dir.chdir target if $static_ext.size > 0 || - !File.exists?("./Makefile") || + !File.exist?("./Makefile") || older("./Makefile", "../Setup") || older("./Makefile", "../extmk.rb") || older("./Makefile", "./extconf.rb") then $defs = [] - if File.exists?("extconf.rb") + if File.exist?("extconf.rb") load "extconf.rb" else create_makefile(target); end end - if File.exists?("./Makefile") + if File.exist?("./Makefile") if $install system "make install" elsif $clean @@ -328,10 +329,10 @@ if File.file? "./Setup" while f.gets() $_.chop! sub!(/#.*$/, '') - continue if /^\s*$/ + next if /^\s*$/ if /^option +nodynamic/ $nodynamic = TRUE - continue + next end $static_ext[$_.split[0]] = TRUE end @@ -339,36 +340,56 @@ if File.file? "./Setup" end for d in Dir["*"] - File.directory?(d) || continue - File.file?(d + "/MANIFEST") || continue + File.directory?(d) || next + File.file?(d + "/MANIFEST") || next d = $1 if d =~ /\/([\/]*)$/ - print "compiling ", d, "\n" - + if $install + print "installing ", d, "\n" + elsif $clean + print "cleaning ", d, "\n" + else + print "compiling ", d, "\n" + end extmake(d) end if $cache_mod f = open("config.cache", "w") for k,v in $lib_cache - printf f, "lib: %s %s\n", k, v + f.printf "lib: %s %s\n", k, v end for k,v in $func_cache - printf f, "func: %s %s\n", k, v + f.printf "func: %s %s\n", k, v end for k,v in $hdr_cache - printf f, "hdr: %s %s\n", k, v + f.printf "hdr: %s %s\n", k, v end f.close end -exit if $install -if $extobjs +exit if $install or $clean +if $extlist.size > 0 + for s,t in $extlist + f = format("%s/%s.o", s, t) + if File.exist?(f) + $extinit += format("\ +\tInit_%s();\n\ +\trb_provide(\"%s.o\");\n\ +", t, t) + $extobjs += "ext/" + $extobjs += f + $extobjs += " " + else + FALSE + end + end + if older("extinit.c", "Setup") f = open("extinit.c", "w") - printf f, "void Init_ext() {\n" - printf f, $extinit - printf f, "}\n" + f.printf "void Init_ext() {\n" + f.printf $extinit + f.printf "}\n" f.close end if older("extinit.o", "extinit.c") @@ -378,16 +399,19 @@ if $extobjs end Dir.chdir ".." - $extobjs = "ext/extinit.o " + $extobjs if older("ruby", "ext/Setup") or older("ruby", "miniruby") `rm -f ruby` end + + $extobjs = "ext/extinit.o " + $extobjs system format('make ruby PROGRAM=ruby EXTOBJS="%s" EXTLIBS="%s"', $extobjs, $extlibs) else Dir.chdir ".." - `rm -f ruby` - `cp miniruby ruby` + if older("ruby", "miniruby") + `rm -f ruby` + `cp miniruby ruby` + end end #Local variables: diff --git a/ext/kconv/MANIFEST b/ext/kconv/MANIFEST new file mode 100644 index 0000000000..8f37a9e166 --- /dev/null +++ b/ext/kconv/MANIFEST @@ -0,0 +1,2 @@ +MANIFEST +kconv.c diff --git a/ext/kconv/kconv.c b/ext/kconv/kconv.c new file mode 100644 index 0000000000..fd6c3bed0a --- /dev/null +++ b/ext/kconv/kconv.c @@ -0,0 +1,1934 @@ +/** Network Kanji Filter. (PDS Version) +************************************************************************ +** Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA) +** Ϣ���衧 �ʳ����ٻ��̸���ꡡ���եȣ���������� +** ��E-Mail Address: [email protected]�� +** Copyright (C) 1996 +** Ϣ���衧 ΰ����ؾ��ز� ���� ���� mine/X0208 support +** ��E-Mail Address: [email protected]�� +** Ϣ���衧 COW for DOS & Win16 & Win32 & OS/2 +** ��E-Mail Address: [email protected]�� +** ��������Ū�Ȥ��ʤ��¤ꡢ���Υ������Τ����ʤ� +** ʣ�̡����ѡ�������������ޤ������κݤˤϡ�������ʬ��Ĥ����ȡ� +** ���Υץ������ˤĤ��Ƥ��ä˲����ݾڤ⤷�ʤ����������餺�� +** Everyone is permitted to do anything on this program +** including copying, modifying, improving +** as long as you don't try to make money off it, +** or pretend that you wrote it. +** i.e., the above copyright notice has to appear in all copies. +** THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE. +***********************************************************************/ + +/*********************************************************************** +** 1996/03/10 modified for Kconv - by Ikuo Nakagawa +***********************************************************************/ +/*********************************************************************** +** 1996/12/18 modified for kconv(ruby) - by [email protected] +***********************************************************************/ + +static char *CopyRight = + "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),1996 S. Kono, COW"; +static char *Version = + "1.62"; +static char *Patchlevel = + "5/9612/Shinji Kono, COW matz"; + +/* +** +** +** +** USAGE: nkf [flags] [file] +** +** Flags: +** b Output is bufferred (DEFAULT) +** u Output is unbufferred +** +** t no operation +** +** j Outout code is JIS 7 bit (DEFAULT SELECT) +** s Output code is MS Kanji (DEFAULT SELECT) +** e Output code is AT&T JIS (DEFAULT SELECT) +** l Output code is JIS 7bit and ISO8859-1 Latin-1 +** +** m MIME conversion for ISO-2022-JP +** i_ Output sequence to designate JIS-kanji (DEFAULT_J) +** o_ Output sequence to designate single-byte roman characters (DEFAULT_R) +** +** r {de/en}crypt ROT13/47 +** +** v display Version +** +** T Text mode output (for MS-DOS) +** +** x Do not convert X0201 kana into X0208 +** Z Convert X0208 alphabet to ASCII +** +** f60 fold option +** +** m MIME decode +** B try to fix broken JIS, missing Escape +** B[1-9] broken level +** +** O Output to 'nkf.out' file +** d Delete \r in line feed +** c Add \r in line feed +**/ +/******************************/ +/* �ǥե���Ȥν��ϥ��������� */ +/* Select DEFAULT_CODE */ +#define DEFAULT_CODE_JIS +/* #define DEFAULT_CODE_SJIS */ +/* #define DEFAULT_CODE_EUC */ +/******************************/ +/* �ץ��ȥ����פ����� */ +#define ANSI_C_PROTOTYPE +/******************************/ + +/* for Kconv: _AUTO, _EUC, _SJIS, _JIS */ +#define _AUTO 0 +#define _JIS 1 +#define _EUC 2 +#define _SJIS 3 + +#ifdef __STDC__ +#define ANSI_C_PROTOTYPE +#endif + +#if (defined(__TURBOC__) || defined(LSI_C)) && !defined(MSDOS) +#define MSDOS +#endif + +#include <stdio.h> + +#if defined(MSDOS) || defined(__OS2__) +#include <stdlib.h> +#include <fcntl.h> +#include <io.h> +#endif + +#ifdef MSDOS +#ifdef LSI_C +#define setbinmode(fp) fsetbin(fp) +#else /* Microsoft C, Turbo C */ +#define setbinmode(fp) setmode(fileno(fp), O_BINARY) +#endif +#else /* UNIX,OS/2 */ +#define setbinmode(fp) +#endif + +#ifdef _IOFBF /* SysV and MSDOS */ +#define setvbuffer(fp, buf, size) setvbuf(fp, buf, _IOFBF, size) +#else /* BSD */ +#define setvbuffer(fp, buf, size) setbuffer(fp, buf, size) +#endif + +/*Borland C++ 4.5 EasyWin*/ +#if defined(__TURBOC__) && defined(_Windows) && !defined(__WIN32__) /*Easy Win */ +#define EASYWIN +#include <windows.h> +#endif + +#define FALSE 0 +#define TRUE 1 + +/* state of output_mode and input_mode */ + +#define ASCII 0 +#define X0208 1 +#define X0201 2 +#define NO_X0201 3 +#define JIS_INPUT 4 +#define SJIS_INPUT 5 +#define LATIN1_INPUT 6 +#define FIXED_MIME 7 +#define DOUBLE_SPACE -2 + +#define NL 0x0a +#define ESC 0x1b +#define SP 0x20 +#define AT 0x40 +#define SSP 0xa0 +#define DEL 0x7f +#define SI 0x0f +#define SO 0x0e +#define SSO 0x8e + +#define HOLD_SIZE 32 +#define IOBUF_SIZE 16384 + +#define DEFAULT_J 'B' +#define DEFAULT_R 'B' + +#define SJ0162 0x00e1 /* 01 - 62 ku offset */ +#define SJ6394 0x0161 /* 63 - 94 ku offset */ + + +/* MIME preprocessor */ + +#define _GETC() (*inptr ? (int)(*inptr++) : EOF) +#define _UNGETC(c) (*--inptr = (c)) +#define PUTCHAR(c) (outlen + 1 < outsiz ? \ + ((outptr[outlen++] = (c)), (outptr[outlen] = '\0')) : EOF) +#define GETC() ((!mime_mode)?_GETC():mime_getc()) +#define UNGETC(c) ((!mime_mode)?_UNGETC(c):mime_ungetc(c)) + +#ifdef EASYWIN /*Easy Win */ +extern POINT _BufferSize; +#endif + +/* buffers */ + +static unsigned char hold_buf[HOLD_SIZE*2]; +static int hold_count; +static unsigned char *inptr; +static char *outptr; +static int outsiz; +static int outlen; + +/* MIME preprocessor fifo */ + +#define MIME_BUF_SIZE (1024) /* 2^n ring buffer */ +#define MIME_BUF_MASK (MIME_BUF_SIZE-1) +#define Fifo(n) mime_buf[(n)&MIME_BUF_MASK] +static unsigned char mime_buf[MIME_BUF_SIZE]; +static unsigned int mime_top = 0; +static unsigned int mime_last = 0; /* decoded */ +static unsigned int mime_input = 0; /* undecoded */ + +/* flags */ +static int unbuf_f = FALSE; +static int estab_f = FALSE; +#ifdef notdef +static int nop_f = FALSE; +static int binmode_f = TRUE; /* binary mode */ +#endif +static int rot_f = FALSE; /* rot14/43 mode */ +static int input_f = FALSE; /* non fixed input code */ +static int alpha_f = FALSE; /* convert JIx0208 alphbet to ASCII */ +static int mime_f = FALSE; /* convert MIME B base64 or Q */ +static int mimebuf_f = FALSE; /* MIME buffered input */ +static int broken_f = FALSE; /* convert ESC-less broken JIS */ +static int iso8859_f = FALSE; /* ISO8859 through */ +#if defined(MSDOS) || defined(__OS2__) +static int x0201_f = TRUE; /* Assume JISX0201 kana */ +#else +static int x0201_f = NO_X0201; /* Assume NO JISX0201 */ +#endif + +/* X0208 -> ASCII converter */ + +static int c1_return; + +/* fold parameter */ +static int line = 0; /* chars in line */ +static int prev = 0; +static int fold_f = FALSE; +static int fold_len = 0; + +/* options */ +static char kanji_intro = DEFAULT_J, + ascii_intro = DEFAULT_R; + +/* Folding */ + +static int fold(); +#define FOLD_MARGIN 10 +#define DEFAULT_FOLD 60 + +/* Global states */ +static int output_mode = ASCII, /* output kanji mode */ + input_mode = ASCII, /* input kanji mode */ + shift_mode = FALSE; /* TRUE shift out, or X0201 */ +static int mime_mode = FALSE; /* MIME mode B base64, Q hex */ + +/* X0208 -> ASCII translation table */ + +static unsigned char cv[],dv[],ev[],fv[]; + +#ifdef notdef +static int file_out = FALSE; +static int end_check; +#endif +static int add_cr = FALSE; +static int del_cr = FALSE; + +/* function prototype */ +#ifdef ANSI_C_PROTOTYPE +static void (*iconv) (register int c2,register int c1); /* s_iconv or oconv */ +static void (*oconv) (register int c2,register int c1); /* [ejs]_oconv */ +static int do_kconv(char *i, char *o, int siz, int out_code, int in_code); +static void h_conv(register int c2,register int c1); +static int push_hold_buf(int c2,int c1); +static void s_iconv(register int c2,register int c1); +static void e_oconv(register int c2,register int c1); +static void s_oconv(register int c2,register int c1); +static void j_oconv(register int c2,register int c1); +static int fold(register int c2,register int c1); +static int pre_convert(register int c1,register int c2); +static int mime_begin(); +static int mime_getc(); +static int mime_ungetc(unsigned int c); +static int mime_integrity(unsigned char *p); +static int base64decode(int c); +#else +static void (*iconv) (); /* s_iconv or oconv */ +static void (*oconv) (); /* [ejs]_oconv */ +static int s_iconv (); +static int e_oconv (); +static int j_oconv (); +static int s_oconv (); +static int noconvert (); +static int do_kconv(); +static void h_conv (); +static int push_hold_buf (); +#endif + +#ifdef notdef +main (argc, argv) + int argc; + char **argv; +{ + register FILE *fin; + register char *cp; + +#ifdef EASYWIN /*Easy Win */ + _BufferSize.y = 400;/*Set Scroll Buffer Size*/ +#endif +#ifdef DEFAULT_CODE_JIS + oconv = j_oconv; /* DEFAULT Code is JIS */ +#endif +#ifdef DEFAULT_CODE_SJIS + oconv = s_oconv; /* DEFAULT Code is S-JIS */ +#endif +#ifdef DEFAULT_CODE_EUC + oconv = e_oconv; /* DEFAULT Code is EUC */ +#endif + + for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) { + cp = *argv; + while (*cp) { + switch (*cp++) { + case 'b': /* buffered mode */ + unbuf_f = FALSE; + continue; + case 'u': /* non bufferd mode */ + unbuf_f = TRUE; + continue; + case 't': /* transparent mode */ + nop_f = TRUE; + continue; + case 'j': /* JIS output */ + case 'n': + oconv = j_oconv; + continue; + case 'e': /* AT&T EUC output */ + oconv = e_oconv; + continue; + case 's': /* SJIS output */ + oconv = s_oconv; + continue; + case 'l': /* ISO8859 Latin-1 support, no conversion */ + iso8859_f = TRUE; /* Only compatible with ISO-2022-JP */ + input_f = LATIN1_INPUT; + continue; + case 'i': /* Kanji IN ESC-$-@/B */ + if(*cp=='@'||*cp=='B') + kanji_intro = *cp++; + continue; + case 'o': /* ASCII IN ESC-(-J/B */ + if(*cp=='J'||*cp=='B'||*cp=='H') + ascii_intro = *cp++; + continue; + case 'r': + rot_f = TRUE; + continue; +#if defined(MSDOS) || defined(__OS2__) + case 'T': + binmode_f = FALSE; + continue; +#endif + case 'v': + usage(); + exit(1); + break; + /* Input code assumption */ + case 'J': /* JIS input */ + case 'E': /* AT&T EUC input */ + input_f = JIS_INPUT; + continue; + case 'S': /* MS Kanji input */ + input_f = SJIS_INPUT; + if(x0201_f==NO_X0201) x0201_f=TRUE; + continue; + case 'Z': /* Convert X0208 alphabet to asii */ + /* bit:0 Convert X0208 + bit:1 Convert Kankaku to one space + bit:2 Convert Kankaku to two spaces + */ + if('9'>= *cp && *cp>='0') + alpha_f |= 1<<(*cp++ -'0'); + else + alpha_f |= TRUE; + continue; + case 'x': /* Convert X0201 kana to X0208 or X0201 Conversion */ + x0201_f = FALSE; /* No X0201->X0208 conversion */ + /* accept X0201 + ESC-(-I in JIS, EUC, MS Kanji + SI/SO in JIS, EUC, MS Kanji + SSO in EUC, JIS, not in MS Kanji + MS Kanji (0xa0-0xdf) + output X0201 + ESC-(-I in JIS (0x20-0x5f) + SSO in EUC (0xa0-0xdf) + 0xa0-0xd in MS Kanji (0xa0-0xdf) + */ + continue; + case 'X': /* Assume X0201 kana */ + /* Default value is NO_X0201 for EUC/MS-Kanji mix */ + x0201_f = TRUE; + continue; + case 'f': /* folding -f60 or -f */ + fold_f = TRUE; + fold_len = atoi(cp); + if(!(0<fold_len && fold_len<BUFSIZ)) + fold_len = DEFAULT_FOLD; + while('0'<= *cp && *cp <='9') cp++; + continue; + case 'm': /* MIME support */ + mime_f = TRUE; + if(*cp=='B'||*cp=='Q') { + mime_mode = *cp++; + mimebuf_f = FIXED_MIME; + } + continue; + case 'B': /* Broken JIS support */ + /* bit:0 no ESC JIS + bit:1 allow any x on ESC-(-x or ESC-$-x + bit:2 reset to ascii on NL + */ + if('9'>= *cp && *cp>='0') + broken_f |= 1<<(*cp++ -'0'); + else + broken_f |= TRUE; + continue; + case 'O':/* for Output file */ + file_out = TRUE; + continue; + case 'c':/* add cr code */ + add_cr = TRUE; + continue; + case 'd':/* delete cr code */ + del_cr = TRUE; + continue; + default: + /* bogus option but ignored */ + continue; + } + } + } + + if(iso8859_f && (oconv != j_oconv || !x0201_f )) { + fprintf(stderr,"Mixed ISO8859/JISX0201/SJIS/EUC output is not allowed.\n"); + exit(1); + } + + if(binmode_f == TRUE) +#ifdef __OS2__ + if(freopen("","wb",stdout) == NULL) + return (-1); +#else + setbinmode(stdout); +#endif + + if(unbuf_f) + setbuf (stdout, (char *) NULL); + else + setvbuffer (stdout, stdobuf, IOBUF_SIZE); + + if(argc == 0) { + if(binmode_f == TRUE) +#ifdef __OS2__ + if(freopen("","rb",stdin) == NULL) return (-1); +#else + setbinmode(stdin); +#endif + setvbuffer (stdin, stdibuf, IOBUF_SIZE); + if(nop_f) + noconvert (stdin); + else + convert (stdin); + } else { + while (argc--) { + if((fin = fopen (*argv++, "r")) == NULL) { + perror (*--argv); + return (-1); + } else { +/* reopen file for stdout */ + if(file_out == TRUE){ + if(argc == 1 ) { + if(freopen(*argv++, "w", stdout) == NULL) { + perror (*--argv); + return (-1); + } + argc--; + } else { + if(freopen("nkf.out", "w", stdout) == NULL) { + perror (*--argv); + return (-1); + } + } + if(binmode_f == TRUE) { +#ifdef __OS2__ + if(freopen("","wb",stdout) == NULL) + return (-1); +#else + setbinmode(stdout); +#endif + } + } + if(binmode_f == TRUE) +#ifdef __OS2__ + if(freopen("","rb",fin) == NULL) + return (-1); +#else + setbinmode(fin); +#endif + setvbuffer (fin, stdibuf, IOBUF_SIZE); + if(nop_f) + noconvert (fin); + else + convert (fin); + fclose (fin); + } + } + } +#ifdef EASYWIN /*Easy Win */ + if(file_out == FALSE) + scanf("%d",&end_check); + else + fclose(stdout); +#else /* for Other OS */ + if(file_out == TRUE) + fclose(stdout); +#endif + return (0); +} + +int +noconvert (f) + register FILE *f; +{ + register int c; + + while ((c = getc (f)) != EOF) + putchar (c); + return 1; +} + +#endif /* notdef */ + +static int +do_kconv(i, o, siz, out_code, in_code) + char *i; + char *o; + int siz, out_code, in_code; +{ + register int c1, + c2; + + c2 = 0; + + if (siz <= 0) { + return 0; + } + *o = '\0'; + + inptr = (unsigned char *)i; /* input buffer */ + outptr = o; /* output buffer */ + outsiz = siz; /* output buffer size */ + outlen = 0; /* current length of output string */ + x0201_f = FALSE; /* don't assume JISX0201 kana */ + rot_f = FALSE; /* rot14/43 mode */ + input_f = FALSE; /* non fixed input code */ + alpha_f = FALSE; /* convert JISX0208 alphbet to ASCII */ + mime_f = TRUE; /* convert MIME base64 */ + broken_f = FALSE; /* convert ESC-less broken JIS */ + + switch (out_code) { + case _SJIS: + oconv = s_oconv; + break; + case _EUC: + oconv = e_oconv; + break; + default: + oconv = j_oconv; + break; + } + + switch (in_code) { + case _SJIS: + input_f = SJIS_INPUT; + x0201_f = TRUE; + break; + case _EUC: + case _JIS: + input_f = JIS_INPUT; + break; + default: + input_f = FALSE; + break; + } + + if(input_f == JIS_INPUT || input_f == LATIN1_INPUT) { + estab_f = TRUE; iconv = oconv; + } else if(input_f == SJIS_INPUT) { + estab_f = TRUE; iconv = s_iconv; + } else { + estab_f = FALSE; iconv = oconv; + } + input_mode = ASCII; + output_mode = ASCII; + shift_mode = FALSE; + mime_mode = FALSE; + +#define NEXT continue /* no output, get next */ +#define SEND ; /* output c1 and c2, get next */ +#define LAST break /* end of loop, go closing */ + + while ((c1 = GETC()) != EOF) { + if(!c2 && !input_mode && c1<DEL && !mime_mode && !output_mode + && !shift_mode && !fold_f && !rot_f) { + /* plain ASCII tight loop, no conversion and no fold */ + while(c1!='=' && c1!=SO && c1!=EOF && + c1!=ESC && c1!='$' && c1<DEL && c1!='\r' && c1!='\n') { + PUTCHAR(c1); + c1 = _GETC(); + } + if(c1==EOF) LAST; + } + if(c2) { + /* second byte */ + if(c2 > DEL) { + /* in case of 8th bit is on */ + if(!estab_f) { + /* in case of not established yet */ + if(c1 > SSP) { + /* It is still ambiguious */ + h_conv (c2, c1); + c2 = 0; + NEXT; + } else if(c1 < AT) { + /* ignore bogus code */ + c2 = 0; + NEXT; + } else { + /* established */ + /* it seems to be MS Kanji */ + estab_f = TRUE; + iconv = s_iconv; + SEND; + } + } else + /* in case of already established */ + if(c1 < AT) { + /* ignore bogus code */ + c2 = 0; + NEXT; + } else + SEND; + } else + /* 7 bit code */ + /* it might be kanji shitfted */ + if((c1 == DEL) || (c1 <= SP)) { + /* ignore bogus first code */ + c2 = 0; + NEXT; + } else + SEND; + } else { + /* first byte */ + if(c1 > DEL) { + /* 8 bit code */ + if(!estab_f && !iso8859_f) { + /* not established yet */ + if(c1 < SSP) { + /* it seems to be MS Kanji */ + estab_f = TRUE; + iconv = s_iconv; + } else if(c1 < 0xe0) { + /* it seems to be EUC */ + estab_f = TRUE; + iconv = oconv; + } else { + /* still ambiguious */ + } + c2 = c1; + NEXT; + } else { /* estab_f==TRUE */ + if(iso8859_f) { + SEND; + } else if(SSP<=c1 && c1<0xe0 && iconv == s_iconv) { + /* SJIS X0201 Case... */ + /* This is too arrogant, but ... */ + if(x0201_f==NO_X0201) { + iconv = oconv; + c2 = c1; + NEXT; + } else + if(x0201_f) { + if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) { + /* look ahead for X0201/X0208conversion */ + if((c2 = GETC()) == EOF) { + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + LAST; + } else if(c2==(0xde)) { /* ���� */ + (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]); + c2=0; + NEXT; + } else if(c2==(0xdf)&&ev[(c1-SSP)*2]) { + /* Ⱦ���� */ + (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]); + c2=0; + NEXT; + } + UNGETC(c2); c2 = 0; + } + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + NEXT; + } else + SEND; + } else if(c1==SSO && iconv != s_iconv) { + /* EUC X0201 Case */ + /* This is too arrogant + if(x0201_f == NO_X0201) { + estab_f = FALSE; + c2 = 0; + NEXT; + } */ + c1 = GETC(); /* skip SSO */ + euc_1byte_check: + if(x0201_f && SSP<=c1 && c1<0xe0) { + if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) { + if((c2 = GETC()) == EOF) { + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + LAST; + } + /* forward lookup ����/Ⱦ���� */ + if(c2 != SSO) { + UNGETC(c2); c2 = 0; + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + NEXT; + } else if((c2 = GETC()) == EOF) { + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + (*oconv)(0,SSO); + LAST; + } else if(c2==(0xde)) { /* ���� */ + (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]); + c2=0; + NEXT; + } else if(c2==(0xdf)&&ev[(c1-SSP)*2]) { + /* Ⱦ���� */ + (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]); + c2=0; + NEXT; + } else { + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + /* we have to check this c2 */ + /* and no way to push back SSO */ + c1 = c2; c2 = 0; + goto euc_1byte_check; + } + } + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + NEXT; + } else + SEND; + } else if(c1 < SSP && iconv != s_iconv) { + /* strange code in EUC */ + iconv = s_iconv; /* try SJIS */ + c2 = c1; + NEXT; + } else { + /* already established */ + c2 = c1; + NEXT; + } + } + } else if((c1 > SP) && (c1 != DEL)) { + /* in case of Roman characters */ + if(shift_mode) { + c1 |= 0x80; + /* output 1 shifted byte */ + if(x0201_f && (!iso8859_f||input_mode==X0201) && + SSP<=c1 && c1<0xe0 ) { + if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) { + if((c2 = GETC()) == EOF) { + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + LAST; + } else if(c2==(0xde&0x7f)) { /* ���� */ + (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]); + c2=0; + NEXT; + } else if(c2==(0xdf&0x7f)&&ev[(c1-SSP)*2]) { + /* Ⱦ���� */ + (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]); + c2=0; + NEXT; + } + UNGETC(c2); c2 = 0; + } + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + NEXT; + } else + SEND; + } else if(c1 == '(' && broken_f && input_mode == X0208 + && !mime_mode ) { + /* Try to recover missing escape */ + if((c1 = GETC()) == EOF) { + (*oconv) (0, '('); + LAST; + } else { + if(c1 == 'B' || c1 == 'J' || c1 == 'H') { + input_mode = ASCII; shift_mode = FALSE; + NEXT; + } else { + (*oconv) (0, '('); + /* do not modify various input_mode */ + /* It can be vt100 sequence */ + SEND; + } + } + } else if(input_mode == X0208) { + /* in case of Kanji shifted */ + c2 = c1; + NEXT; + /* goto next_byte */ + } else if(c1 == '=' && mime_f && !mime_mode ) { + if((c1 = _GETC()) == EOF) { + (*oconv) (0, '='); + LAST; + } else if(c1 == '?') { + /* =? is mime conversion start sequence */ + if(mime_begin() == EOF) /* check in detail */ + LAST; + else + NEXT; + } else { + (*oconv) (0, '='); + _UNGETC(c1); + NEXT; + } + } else if(c1 == '$' && broken_f && !mime_mode) { + /* try to recover missing escape */ + if((c1 = GETC()) == EOF) { + (*oconv) (0, '$'); + LAST; + } else if(c1 == '@'|| c1 == 'B') { + /* in case of Kanji in ESC sequence */ + input_mode = X0208; + shift_mode = FALSE; + NEXT; + } else { + /* sorry */ + (*oconv) (0, '$'); + (*oconv) (0, c1); + NEXT; + } + } else + SEND; + } else if(c1 == SI) { + shift_mode = FALSE; + NEXT; + } else if(c1 == SO) { + shift_mode = TRUE; + NEXT; + } else if(c1 == ESC ) { + if((c1 = GETC()) == EOF) { + (*oconv) (0, ESC); + LAST; + } else if(c1 == '$') { + if((c1 = GETC()) == EOF) { + (*oconv) (0, ESC); + (*oconv) (0, '$'); + LAST; + } else if(c1 == '@'|| c1 == 'B') { + /* This is kanji introduction */ + input_mode = X0208; + shift_mode = FALSE; + NEXT; + } else if(broken_f&0x2) { + input_mode = X0208; + shift_mode = FALSE; + NEXT; + } else { + (*oconv) (0, ESC); + (*oconv) (0, '$'); + (*oconv) (0, c1); + NEXT; + } + } else if(c1 == '(') { + if((c1 = GETC()) == EOF) { + (*oconv) (0, ESC); + (*oconv) (0, '('); + LAST; + } else { + if(c1 == 'I') { + /* This is X0201 kana introduction */ + input_mode = X0201; shift_mode = X0201; + NEXT; + } else if(c1 == 'B' || c1 == 'J' || c1 == 'H') { + /* This is X0208 kanji introduction */ + input_mode = ASCII; shift_mode = FALSE; + NEXT; + } else if(broken_f&0x2) { + input_mode = ASCII; shift_mode = FALSE; + NEXT; + } else { + (*oconv) (0, ESC); + (*oconv) (0, '('); + /* maintain various input_mode here */ + SEND; + } + } + } else { + /* lonely ESC */ + (*oconv) (0, ESC); + SEND; + } + } else if(c1 == NL && broken_f&4) { + input_mode = ASCII; + SEND; + } else + SEND; + } + /* send: */ + if(input_mode == X0208) + (*oconv) (c2, c1); /* this is JIS, not SJIS/EUC case */ + else + (*iconv) (c2, c1); /* can be EUC/SJIS */ + c2 = 0; + continue; + /* goto next_word */ + } + + /* epilogue */ + (*iconv) (EOF, 0); + return outlen; +} + + +static void +h_conv (c2, c1) + register int c1, + c2; +{ + register int wc; + + + /** it must NOT be in the kanji shifte sequence */ + /** it must NOT be written in JIS7 */ + /** and it must be after 2 byte 8bit code */ + + hold_count = 0; + push_hold_buf (c2, c1); + c2 = 0; + + while ((c1 = GETC()) != EOF) { + if(c2) { + /* second byte */ + if(!estab_f) { + /* not established */ + if(c1 > SSP) { + /* it is still ambiguious yet */ + SEND; + } else if(c1 < AT) { + /* ignore bogus first byte */ + c2 = 0; + SEND; + } else { + /* now established */ + /* it seems to be MS Kanji */ + estab_f = TRUE; + iconv = s_iconv; + SEND; + } + } else + SEND; + } else { + /* First byte */ + if(c1 > DEL) { + /* 8th bit is on */ + if(c1 < SSP) { + /* it seems to be MS Kanji */ + estab_f = TRUE; + iconv = s_iconv; + } else if(c1 < 0xe0) { + /* it seems to be EUC */ + estab_f = TRUE; + iconv = oconv; + } else { + /* still ambiguious */ + } + c2 = c1; + NEXT; + } else + /* 7 bit code , then send without any process */ + SEND; + } + /* send: */ + if((push_hold_buf (c2, c1) == EOF) || estab_f) + break; + c2 = 0; + continue; + } + + /** now, + ** 1) EOF is detected, or + ** 2) Code is established, or + ** 3) Buffer is FULL (but last word is pushed) + ** + ** in 1) and 3) cases, we continue to use + ** Kanji codes by oconv and leave estab_f unchanged. + **/ + + for (wc = 0; wc < hold_count; wc += 2) { + c2 = hold_buf[wc]; + c1 = hold_buf[wc+1]; + (*iconv) (c2, c1); + } + return; +} + + + +int +push_hold_buf (c2, c1) + int c2, + c1; +{ + if(hold_count >= HOLD_SIZE*2) + return (EOF); + hold_buf[hold_count++] = c2; + hold_buf[hold_count++] = c1; + return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count); +} + + +static void +s_iconv (c2, c1) + register int c2, + c1; +{ + if((c2 == EOF) || (c2 == 0)) { + /* NOP */ + } else { + c2 = c2 + c2 - ((c2 <= 0x9f) ? SJ0162 : SJ6394); + if(c1 < 0x9f) + c1 = c1 - ((c1 > DEL) ? SP : 0x1f); + else { + c1 = c1 - 0x7e; + c2++; + } + } + (*oconv) (c2, c1); +} + + +static void +e_oconv (c2, c1) + register int c2, + c1; +{ + c2 = pre_convert(c1,c2); c1 = c1_return; + if(fold_f) { + switch(fold(c2,c1)) { + case '\n': + if(add_cr == TRUE) { + PUTCHAR('\r'); + c1 = '\n'; + } + PUTCHAR('\n'); + break; + case 0: return; + case '\r': + c1 = '\n'; c2 = 0; + break; + case '\t': + case ' ': + c1 = ' '; c2 = 0; + break; + } + } + if(c2==DOUBLE_SPACE) { + PUTCHAR(' '); PUTCHAR(' '); + return; + } + if(c2 == EOF) + return; + else if(c2 == 0 && (c1&0x80)) { + PUTCHAR(SSO); PUTCHAR(c1); + } else if(c2 == 0) { + if(c1 == '\n' && add_cr == TRUE) + PUTCHAR('\r'); + if(c1 != '\r') + PUTCHAR(c1); + else if(del_cr == FALSE) + PUTCHAR(c1); + } else { + if((c1<0x20 || 0x7e<c1) || + (c2<0x20 || 0x7e<c2)) { + estab_f = FALSE; + return; /* too late to rescue this char */ + } + PUTCHAR(c2 | 0x080); + PUTCHAR(c1 | 0x080); + } +} + + +static void +s_oconv (c2, c1) + register int c2, + c1; +{ + c2 = pre_convert(c1,c2); c1 = c1_return; + if(fold_f) { + switch(fold(c2,c1)) { + case '\n': + if(add_cr == TRUE) { + PUTCHAR('\r'); + c1 = '\n'; + } + PUTCHAR('\n'); + break; + case '\r': + c1 = '\n'; c2 = 0; + break; + case 0: return; + case '\t': + case ' ': + c1 = ' '; c2 = 0; + break; + } + } + if(c2==DOUBLE_SPACE) { + PUTCHAR(' '); PUTCHAR(' '); + return; + } + if(c2 == EOF) + return; + else if(c2 == 0) { + if(c1 == '\n' && add_cr == TRUE) + PUTCHAR('\r'); + if(c1 != '\r') + PUTCHAR(c1); + else if(del_cr == FALSE) + PUTCHAR(c1); + } else { + if((c1<0x20 || 0x7e<c1) || + (c2<0x20 || 0x7e<c2)) { + estab_f = FALSE; + return; /* too late to rescue this char */ + } + PUTCHAR((((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1))); + PUTCHAR((c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e))); + } +} + +static void +j_oconv (c2, c1) + register int c2, + c1; +{ + c2 = pre_convert(c1,c2); c1 = c1_return; + if(fold_f) { + switch(fold(c2,c1)) { + case '\n': + if(output_mode) { + PUTCHAR(ESC); + PUTCHAR('('); + PUTCHAR(ascii_intro); + } + if(add_cr == TRUE) { + PUTCHAR('\r'); + c1 = '\n'; + } + PUTCHAR('\n'); + output_mode = ASCII; + break; + case '\r': + c1 = '\n'; c2 = 0; + break; + case '\t': + case ' ': + c1 = ' '; c2 = 0; + break; + case 0: return; + } + } + if(c2 == EOF) { + if(output_mode) { + PUTCHAR(ESC); + PUTCHAR('('); + PUTCHAR(ascii_intro); + } + } else if(c2 == 0 && (c1 & 0x80)) { + if(input_mode==X0201 || !iso8859_f) { + if(output_mode!=X0201) { + PUTCHAR(ESC); + PUTCHAR('('); + PUTCHAR('I'); + output_mode = X0201; + } + c1 &= 0x7f; + } else { + /* iso8859 introduction, or 8th bit on */ + /* Can we convert in 7bit form using ESC-'-'-A ? + Is this popular? */ + } + PUTCHAR(c1); + } else if(c2 == 0) { + if(output_mode) { + PUTCHAR(ESC); + PUTCHAR('('); + PUTCHAR(ascii_intro); + output_mode = ASCII; + } + if(c1 == '\n' && add_cr == TRUE) + PUTCHAR('\r'); + if(c1 != '\r') + PUTCHAR(c1); + else if(del_cr == FALSE) + PUTCHAR(c1); + } else if(c2 == DOUBLE_SPACE) { + if(output_mode) { + PUTCHAR(ESC); + PUTCHAR('('); + PUTCHAR(ascii_intro); + output_mode = ASCII; + } + PUTCHAR(' '); + if(c1 == '\n' && add_cr == TRUE) + PUTCHAR('\r'); + if(c1 != '\r') + PUTCHAR(c1); + else if(del_cr == FALSE) + PUTCHAR(c1); + } else { + if(output_mode != X0208) { + PUTCHAR(ESC); + PUTCHAR('$'); + PUTCHAR(kanji_intro); + output_mode = X0208; + } + if(c1<0x20 || 0x7e<c1) + return; + if(c2<0x20 || 0x7e<c2) + return; + PUTCHAR(c2); + if(c1 == '\n' && add_cr == TRUE) + PUTCHAR('\r'); + if(c1 != '\r') + PUTCHAR(c1); + else if(del_cr == FALSE) + PUTCHAR(c1); + } +} + + +#define rot13(c) ( \ + ( c < 'A' ) ? c: \ + (c <= 'M') ? (c + 13): \ + (c <= 'Z') ? (c - 13): \ + (c < 'a') ? (c): \ + (c <= 'm') ? (c + 13): \ + (c <= 'z') ? (c - 13): \ + (c) \ +) + +#define rot47(c) ( \ + ( c < '!' ) ? c: \ + ( c <= 'O' ) ? (c + 47) : \ + ( c <= '~' ) ? (c - 47) : \ + c \ +) + +/* + Return value of fold() + + \n add newline and output char + \r add newline and output nothing + ' ' space + 0 skip + 1 (or else) normal output + + fold state in prev (previous character) + + >0x80 Japanese (X0208/X0201) + <0x80 ASCII + \n new line + ' ' space + + This fold algorthm does not preserve heading space in a line. + This is the main difference from fmt. +*/ + +int +fold(c2,c1) +register int c2,c1; +{ + int prev0; + if(c1=='\r') + return 0; /* ignore cr */ + if(c1== 8) { + if(line>0) line--; + return 1; + } + if(c2==EOF && line != 0) /* close open last line */ + return '\n'; + /* new line */ + if(c1=='\n') { + if(prev == c1) { /* duplicate newline */ + if(line) { + line = 0; + return '\n'; /* output two newline */ + } else { + line = 0; + return 1; + } + } else { + if(prev&0x80) { /* Japanese? */ + prev = c1; + return 0; /* ignore given single newline */ + } else if(prev==' ') { + return 0; + } else { + prev = c1; + if(++line<=fold_len) + return ' '; + else { + line = 0; + return '\r'; /* fold and output nothing */ + } + } + } + } + if(c1=='\f') { + prev = '\n'; + if(line==0) + return 1; + line = 0; + return '\n'; /* output newline and clear */ + } + /* X0208 kankaku or ascii space */ + if( (c2==0&&c1==' ')|| + (c2==0&&c1=='\t')|| + (c2==DOUBLE_SPACE)|| + (c2=='!'&& c1=='!')) { + if(prev == ' ') { + return 0; /* remove duplicate spaces */ + } + prev = ' '; + if(++line<=fold_len) + return ' '; /* output ASCII space only */ + else { + prev = ' '; line = 0; + return '\r'; /* fold and output nothing */ + } + } + prev0 = prev; /* we still need this one... , but almost done */ + prev = c1; + if(c2 || (SSP<=c1 && c1<=0xdf)) + prev |= 0x80; /* this is Japanese */ + line += (c2==0)?1:2; + if(line<=fold_len) { /* normal case */ + return 1; + } + if(line>=fold_len+FOLD_MARGIN) { /* too many kinsou suspension */ + line = (c2==0)?1:2; + return '\n'; /* We can't wait, do fold now */ + } + /* simple kinsoku rules return 1 means no folding */ + if(c2==0) { + if(c1==0xde) return 1; /* ��*/ + if(c1==0xdf) return 1; /* ��*/ + if(c1==0xa4) return 1; /* ��*/ + if(c1==0xa3) return 1; /* ��*/ + if(c1==0xa1) return 1; /* ��*/ + if(c1==0xb0) return 1; /* - */ + if(SSP<=c1 && c1<=0xdf) { /* X0201 */ + line = 1; + return '\n';/* add one new line before this character */ + } + /* fold point in ASCII { [ ( */ + if(( c1!=')'&& + c1!=']'&& + c1!='}'&& + c1!='.'&& + c1!=','&& + c1!='!'&& + c1!='?'&& + c1!='/'&& + c1!=':'&& + c1!=';')&& + ((prev0=='\n')|| (prev0==' ')|| /* ignored new line */ + (prev0&0x80)) /* X0208 - ASCII */ + ) { + line = 1; + return '\n';/* add one new line before this character */ + } + return 1; /* default no fold in ASCII */ + } else { + if(c2=='!') { + if(c1=='"') return 1; /* �� */ + if(c1=='#') return 1; /* �� */ + if(c1=='$') return 1; /* �� */ + if(c1=='%') return 1; /* �� */ + if(c1=='\'') return 1; /* �� */ + if(c1=='(') return 1; /* �� */ + if(c1==')') return 1; /* �� */ + if(c1=='*') return 1; /* �� */ + if(c1=='+') return 1; /* �� */ + if(c1==',') return 1; /* �� */ + } + line = 2; + return '\n'; /* add one new line before this character */ + } +} + +int +pre_convert(c1,c2) +register int c1,c2; +{ + if(c2) c1 &= 0x7f; + c1_return = c1; + if(c2==EOF) return c2; + c2 &= 0x7f; + if(rot_f) { + if(c2) { + c1 = rot47(c1); + c2 = rot47(c2); + } else { + if(!(c1 & 0x80)) + c1 = rot13(c1); + } + c1_return = c1; + } + /* JISX0208 Alphabet */ + if(alpha_f && c2 == 0x23 ) return 0; + /* JISX0208 Kigou */ + if(alpha_f && c2 == 0x21 ) { + if(0x21==c1) { + if(alpha_f&0x2) { + c1_return = ' '; + return 0; + } else if(alpha_f&0x4) { + c1_return = ' '; + return DOUBLE_SPACE; + } else { + return c2; + } + } else if(0x20<c1 && c1<0x7f && fv[c1-0x20]) { + c1_return = fv[c1-0x20]; + return 0; + } + } + return c2; +} + + +/* X0201 / X0208 conversion tables */ + +/* X0201 kana conversion table */ +/* 90-9F A0-DF */ +unsigned char cv[]= { +0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57, +0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21, +0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29, +0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43, +0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26, +0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d, +0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35, +0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d, +0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46, +0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c, +0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52, +0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e, +0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62, +0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69, +0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d, +0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c, +0x00,0x00}; + + +/* X0201 kana conversion table for daguten */ +/* 90-9F A0-DF */ +unsigned char dv[]= { +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e, +0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36, +0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e, +0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47, +0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53, +0x25,0x56,0x25,0x59,0x25,0x5c,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00}; + +/* X0201 kana conversion table for han-daguten */ +/* 90-9F A0-DF */ +unsigned char ev[]= { +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x25,0x51,0x25,0x54, +0x25,0x57,0x25,0x5a,0x25,0x5d,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00}; + + +/* X0208 kigou conversion table */ +/* 0x8140 - 0x819e */ +unsigned char fv[] = { + +0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a, +0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00, +0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f, +0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27, +0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d, +0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00, +0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +} ; + + +/* This converts =?ISO-2022-JP?B?HOGE HOGE?= */ + +unsigned char *mime_pattern[] = { + (unsigned char *)"\075?ISO-8859-1?Q?", + (unsigned char *)"\075?ISO-2022-JP?B?", + (unsigned char *)"\075?ISO-2022-JP?Q?", + NULL +}; + +int mime_encode[] = { + 'Q', 'B', 'Q', + 0 +}; + +int iso8859_f_save; + +#define nkf_toupper(c) (('a'<=c && c<='z')?(c-('a'-'A')):c) +/* I don't trust portablity of toupper */ + +int +mime_begin() +{ + int c1; + int i,j,k; + unsigned char *p,*q; + int r[20]; /* recovery buffer, max mime pattern lenght */ + + mime_mode = FALSE; + /* =? has been checked */ + j = 0; + p = mime_pattern[j]; + r[0]='='; r[1]='?'; + + for(i=2;p[i]>' ';i++) { /* start at =? */ + if( ((r[i] = c1 = _GETC())==EOF) || nkf_toupper(c1) != p[i] ) { + /* pattern fails, try next one */ + q = p; + while (p = mime_pattern[++j]) { + for(k=2;k<i;k++) /* assume length(p) > i */ + if(p[k]!=q[k]) break; + if(k==i && nkf_toupper(c1)==p[k]) break; + } + if(p) continue; /* found next one, continue */ + /* all fails, output from recovery buffer */ + _UNGETC(c1); + for(j=0;j<i;j++) { + (*oconv)(0,r[j]); + } + return c1; + } + } + iso8859_f_save = iso8859_f; + if(j==0) { + iso8859_f = TRUE; + } + mime_mode = mime_encode[j]; + if(mime_mode=='B') { + mimebuf_f = unbuf_f; + if(!unbuf_f) { + /* do MIME integrity check */ + return mime_integrity(mime_pattern[j]); + } + } + mimebuf_f = TRUE; + return c1; +} + +#define mime_getc0() (mimebuf_f?_GETC():Fifo(mime_input++)) +#define mime_ungetc0(c) (mimebuf_f?_UNGETC(c):mime_input--) + +int +mime_getc() +{ + int c1, c2, c3, c4, cc; + int t1, t2, t3, t4, mode, exit_mode; + + if(mime_top != mime_last) { /* Something is in FIFO */ + return Fifo(mime_top++); + } + + if(mimebuf_f == FIXED_MIME) + exit_mode = mime_mode; + else + exit_mode = FALSE; + if(mime_mode == 'Q') { + if((c1 = mime_getc0()) == EOF) return (EOF); + if(c1=='_') return ' '; + if(c1!='=' && c1!='?') + return c1; + mime_mode = exit_mode; /* prepare for quit */ + if(c1<=' ') return c1; + if((c2 = mime_getc0()) == EOF) return (EOF); + if(c2<=' ') return c2; + if(c1=='?'&&c2=='=') { + /* end Q encoding */ + input_mode = exit_mode; + iso8859_f = iso8859_f_save; + return _GETC(); + } + if(c1=='?') { + mime_mode = 'Q'; /* still in MIME */ + mime_ungetc0(c2); + return c1; + } + if((c3 = mime_getc0()) == EOF) return (EOF); + if(c2<=' ') return c2; + mime_mode = 'Q'; /* still in MIME */ +#define hex(c) (('0'<=c&&c<='9')?(c-'0'):\ + ('A'<=c&&c<='F')?(c-'A'+10):('a'<=c&&c<='f')?(c-'a'+10):0) + return ((hex(c2)<<4) + hex(c3)); + } + + if(mime_mode != 'B') { + mime_mode = FALSE; + return _GETC(); + } + + + /* Base64 encoding */ + /* + MIME allows line break in the middle of + Base64, but we are very pessimistic in decoding + in unbuf mode because MIME encoded code may broken by + less or editor's control sequence (such as ESC-[-K in unbuffered + mode. ignore incomplete MIME. + */ + mode = mime_mode; + mime_mode = exit_mode; /* prepare for quit */ + + while ((c1 = mime_getc0())<=' ') { + if(c1==EOF) + return (EOF); + } + if((c2 = mime_getc0())<=' ') { + if(c2==EOF) + return (EOF); + if(mimebuf_f!=FIXED_MIME) input_mode = ASCII; + return c2; + } + if((c1 == '?') && (c2 == '=')) { + input_mode = ASCII; + while((c1 = _GETC())==' ' /* || c1=='\n' || c1=='\r' */); + return c1; + } + if((c3 = mime_getc0())<=' ') { + if(c3==EOF) + return (EOF); + if(mimebuf_f!=FIXED_MIME) input_mode = ASCII; + return c3; + } + if((c4 = mime_getc0())<=' ') { + if(c4==EOF) + return (EOF); + if(mimebuf_f!=FIXED_MIME) input_mode = ASCII; + return c4; + } + + mime_mode = mode; /* still in MIME sigh... */ + + /* BASE 64 decoding */ + + t1 = 0x3f & base64decode(c1); + t2 = 0x3f & base64decode(c2); + t3 = 0x3f & base64decode(c3); + t4 = 0x3f & base64decode(c4); + cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03); + if(c2 != '=') { + Fifo(mime_last++) = cc; + cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f); + if(c3 != '=') { + Fifo(mime_last++) = cc; + cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f); + if(c4 != '=') + Fifo(mime_last++) = cc; + } + } else { + return c1; + } + return Fifo(mime_top++); +} + +int +mime_ungetc(c) +unsigned int c; +{ + Fifo(mime_last++) = c; + return c; +} + + +int +mime_integrity(p) +unsigned char *p; +{ + int c,d; + unsigned int q; + /* In buffered mode, read until =? or NL or buffer full + */ + mime_input = mime_top; + mime_last = mime_top; + while(*p) Fifo(mime_input++) = *p++; + d = 0; + q = mime_input; + while((c=_GETC())!=EOF) { + if(((mime_input-mime_top)&MIME_BUF_MASK)==0) break; + if(c=='=' && d=='?') { + /* checked. skip header, start decode */ + Fifo(mime_input++) = c; + mime_input = q; + return 1; + } + if(!( (c=='+'||c=='/'|| c=='=' || c=='?' || + ('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9')))) + break; + /* Should we check length mod 4? */ + Fifo(mime_input++) = c; + d=c; + } + /* In case of Incomplete MIME, no MIME decode */ + Fifo(mime_input++) = c; + mime_last = mime_input; /* point undecoded buffer */ + mime_mode = 1; /* no decode on Fifo last in mime_getc */ + return 1; +} + +int +base64decode(c) + int c; +{ + int i; + if(c > '@') + if(c < '[') + i = c - 'A'; /* A..Z 0-25 */ + else + i = c - 'G' /* - 'a' + 26 */ ; /* a..z 26-51 */ + else if(c > '/') + i = c - '0' + '4' /* - '0' + 52 */ ; /* 0..9 52-61 */ + else if(c == '+') + i = '>' /* 62 */ ; /* + 62 */ + else + i = '?' /* 63 */ ; /* / 63 */ + return (i); +} + +#ifdef notdef +int +usage() +{ + fprintf(stderr,"USAGE: nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n"); + fprintf(stderr,"Flags:\n"); + fprintf(stderr,"b,u Output is bufferred (DEFAULT),Output is unbufferred\n"); +#ifdef DEFAULT_CODE_SJIS + fprintf(stderr,"j,s,e Outout code is JIS 7 bit, Shift JIS (DEFAULT), AT&T JIS (EUC)\n"); +#endif +#ifdef DEFAULT_CODE_JIS + fprintf(stderr,"j,s,e Outout code is JIS 7 bit (DEFAULT), Shift JIS, AT&T JIS (EUC)\n"); +#endif +#ifdef DEFAULT_CODE_EUC + fprintf(stderr,"j,s,e Outout code is JIS 7 bit, Shift JIS, AT&T JIS (EUC) (DEFAULT)\n"); +#endif + fprintf(stderr,"J,S,E Input assumption is JIS 7 bit , Shift JIS, AT&T JIS (EUC)\n"); + fprintf(stderr,"t no conversion\n"); + fprintf(stderr,"i_ Output sequence to designate JIS-kanji (DEFAULT B)\n"); + fprintf(stderr,"o_ Output sequence to designate ASCII (DEFAULT B)\n"); + fprintf(stderr,"r {de/en}crypt ROT13/47\n"); + fprintf(stderr,"v Show this usage\n"); + fprintf(stderr,"m[BQ] MIME decode [B:base64 stream,Q:quoted stream]\n"); + fprintf(stderr,"l ISO8859-1 (Latin-1) support\n"); + fprintf(stderr,"f Folding: -f60 or -f\n"); + fprintf(stderr,"Z[0-2] Convert X0208 alphabet to ASCII 1: Kankaku to space,2: 2 spaces\n"); + fprintf(stderr,"X,x Assume X0201 kana in MS-Kanji, -x preserves X0201\n"); + fprintf(stderr,"B[0-2] Broken input 0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n"); +#ifdef MSDOS + fprintf(stderr,"T Text mode output\n"); +#endif + fprintf(stderr,"O Output to File (DEFAULT 'nkf.out')\n"); + fprintf(stderr,"d,c Delete \\r in line feed, Add \\r in line feed\n"); + fprintf(stderr,"Network Kanji Filter Version %s (%s) " +#if defined(MSDOS) && !defined(_Windows) + "for DOS" +#endif +#if !defined(__WIN32__) && defined(_Windows) + "for Win16" +#endif +#if defined(__WIN32__) && defined(_Windows) + "for Win32" +#endif +#ifdef __OS2__ + "for OS/2" +#endif + ,Version,Patchlevel); + fprintf(stderr,"\n%s\n",CopyRight); + return 0; +} +#endif /* notdef */ + +#include "ruby.h" + +static VALUE +kconv_kconv(argc, argv) + int argc; + VALUE *argv; +{ + struct RString *src, *dst; + VALUE in, out; + int in_code, out_code; + + rb_scan_args(argc, argv, "12", &src, &out, &in); + Check_Type(src, T_STRING); + + if (NIL_P(out)) { + out_code = _JIS; + } + else { + out_code = NUM2INT(out); + } + if (NIL_P(in)) { + in_code = _AUTO; + } + else { + in_code = NUM2INT(in); + } + + dst = RSTRING(str_new(0, src->len*3+10)); /* large enough? */ + dst->len = do_kconv(src->ptr, dst->ptr, dst->len, out_code, in_code); + + return (VALUE)dst; +} + +static VALUE +kconv_tojis(obj, src) + VALUE obj; + struct RString *src; +{ + struct RString *dst; + + Check_Type(src, T_STRING); + + dst = RSTRING(str_new(0, src->len*3+10)); /* large enough? */ + dst->len = do_kconv(src->ptr, dst->ptr, dst->len, _JIS, _AUTO); + + return (VALUE)dst; +} + +static VALUE +kconv_toeuc(obj, src) + VALUE obj; + struct RString* src; +{ + struct RString *dst; + + Check_Type(src, T_STRING); + + dst = RSTRING(str_new(0, src->len*3+10)); /* large enough? */ + dst->len = do_kconv(src->ptr, dst->ptr, dst->len, _EUC, _AUTO); + + return (VALUE)dst; +} + +static VALUE +kconv_tosjis(obj, src) + VALUE obj; + struct RString* src; +{ + struct RString *dst; + + Check_Type(src, T_STRING); + + dst = RSTRING(str_new(0, src->len*3+10)); /* large enough? */ + dst->len = do_kconv(src->ptr, dst->ptr, dst->len, _SJIS, _AUTO); + + return (VALUE)dst; +} + +void +Init_kconv() +{ + VALUE mKconv = rb_define_module("Kconv"); + + rb_define_module_function(mKconv, "kconv", kconv_kconv, -1); + rb_define_module_function(mKconv, "tojis", kconv_tojis, 1); + rb_define_module_function(mKconv, "toeuc", kconv_toeuc, 1); + rb_define_module_function(mKconv, "tosjis", kconv_tosjis, 1); + + rb_define_const(mKconv, "AUTO", INT2FIX(_AUTO)); + rb_define_const(mKconv, "JIS", INT2FIX(_JIS)); + rb_define_const(mKconv, "EUC", INT2FIX(_EUC)); + rb_define_const(mKconv, "SJIS", INT2FIX(_SJIS)); +} + +/** + ** �ѥå������ + ** [email protected] (Kusakabe Youichi) + ** NIDE Naoyuki <[email protected]> + ** [email protected] (Junn Ohta) + ** [email protected] (Tomoyuki Inoue) + ** [email protected] (Tetsuaki Kiriyama) + ** Kimihiko Sato <[email protected]> + ** [email protected] (Akihiko Kuroe) + ** [email protected] (Shinji Kono) + ** [email protected] (COW) + ** [email protected] (Jun Kuroda) + ** + ** �ǽ������� + ** 1996.12.18 + **/ + +/* end */ diff --git a/ext/marshal/MANIFEST b/ext/marshal/MANIFEST index 53b0849484..54870ec71f 100644 --- a/ext/marshal/MANIFEST +++ b/ext/marshal/MANIFEST @@ -1,4 +1,5 @@ MANIFEST depend +extconf.rb marshal.c marshal.doc diff --git a/ext/marshal/extconf.rb b/ext/marshal/extconf.rb new file mode 100644 index 0000000000..65923049e5 --- /dev/null +++ b/ext/marshal/extconf.rb @@ -0,0 +1,2 @@ +have_func("tmpnam") +create_makefile("marshal") diff --git a/ext/marshal/marshal.c b/ext/marshal/marshal.c index 0b29ad5ab8..eae8d7fe09 100644 --- a/ext/marshal/marshal.c +++ b/ext/marshal/marshal.c @@ -13,24 +13,52 @@ #include "io.h" #include "st.h" +#define MARSHAL_MAJOR 2 +#define MARSHAL_MINOR 1 + #define TYPE_NIL '0' +#define TYPE_TRUE 'T' +#define TYPE_FALSE 'F' #define TYPE_FIXNUM 'i' #define TYPE_OBJECT 'o' -#define TYPE_LINK '@' +#define TYPE_USERDEF 'u' #define TYPE_FLOAT 'f' #define TYPE_BIGNUM 'l' #define TYPE_STRING '"' +#define TYPE_STRING2 '\'' #define TYPE_REGEXP '/' #define TYPE_ARRAY '[' +#define TYPE_ARRAY2 ']' #define TYPE_HASH '{' +#define TYPE_HASH2 '}' #define TYPE_STRUCT 'S' +#define TYPE_SYMBOL ':' +#define TYPE_SYMLINK ';' + +VALUE cString; +VALUE cArray; +VALUE cHash; + char *rb_class2path(); VALUE rb_path2class(); static ID s_dump, s_load; +#if (defined(linux) && defined(USE_DLN_A_OUT)) || !defined(HAVE_TMPNAM) +#define tmpnam(s) ltmpnam(s) +static char * +tmpnam(s) + char *s; +{ + static int n = 0; + + sprintf(s, "/tmp/rb-mrsr-%x%x", getpid(), n++); + return s; +} +#endif + #define w_byte(c, fp) putc((c), fp) #define w_bytes(s, n, fp) (w_long((n), fp),fwrite(s, 1, n, fp)) @@ -66,70 +94,119 @@ w_float(d, fp) } static void -w_symbol(id, fp) +w_symbol(id, fp, table) ID id; FILE *fp; + st_table *table; { char *sym = rb_id2name(id); + int num; - w_bytes(sym, strlen(sym), fp); + if (st_lookup(table, id, &num)) { + w_byte(TYPE_SYMLINK, fp); + w_long(num, fp); + } + else { + w_byte(TYPE_SYMBOL, fp); + w_bytes(sym, strlen(sym), fp); + st_insert(table, id, table->num_entries); + } +} + +static void +w_unique(s, fp, table) + char *s; + FILE *fp; + st_table *table; +{ + w_symbol(rb_intern(s), fp, table); } static void w_object(); extern VALUE cBignum, cStruct; +struct each_arg { + FILE *fp; + VALUE limit; + st_table *table; +}; + static int -hash_each(key, value, fp) +hash_each(key, value, arg) VALUE key, value; - FILE *fp; + struct each_arg *arg; { - w_object(key, fp); - w_object(value, fp); + w_object(key, arg->fp, arg->limit, arg->table); + w_object(value, arg->fp, arg->limit, arg->table); return ST_CONTINUE; } static int -obj_each(id, value, fp) +obj_each(id, value, arg) ID id; VALUE value; - FILE *fp; + struct each_arg *arg; { - w_symbol(id, fp); - w_object(value, fp); + w_symbol(id, arg->fp, arg->table); + w_object(value, arg->fp, arg->limit, arg->table); return ST_CONTINUE; } -struct st_table *new_idhash(); - static void -w_object(obj, fp, port, table) - VALUE obj, port; +w_object(obj, fp, limit, table) + VALUE obj; FILE *fp; + int limit; st_table *table; { + struct each_arg arg; + int n; + + if (limit == 0) { + Fail("exceed depth limit"); + } + limit--; + + arg.fp = fp; + arg.limit = limit; + arg.table = table; + if (obj == Qnil) { w_byte(TYPE_NIL, fp); } - else if (FIXNUM_P(obj)) { - w_byte(TYPE_FIXNUM, fp); - w_long(FIX2INT(obj), fp); + else if (obj == TRUE) { + w_byte(TYPE_TRUE, fp); + } + else if (obj == FALSE) { + w_byte(TYPE_FALSE, fp); } - else if (st_lookup(table, obj, 0)) { - w_byte(TYPE_LINK, fp); - w_long(obj, fp); + else if (FIXNUM_P(obj)) { + if (sizeof(long) == 4) { + w_byte(TYPE_FIXNUM, fp); + w_long(FIX2INT(obj), fp); + } } else { - st_insert(table, obj, 0); + if (rb_respond_to(obj, s_dump)) { + VALUE v; + + w_byte(TYPE_USERDEF, fp); + w_unique(rb_class2path(CLASS_OF(obj)), fp, table); + v = rb_funcall(obj, s_dump, 1, limit); + if (TYPE(v) != T_STRING) { + TypeError("_dump_to must return String"); + } + w_bytes(RSTRING(v)->ptr, RSTRING(v)->len, fp); + return; + } switch (BUILTIN_TYPE(obj)) { case T_FLOAT: w_byte(TYPE_FLOAT, fp); - w_long(obj, fp); w_float(RFLOAT(obj)->value, fp); - break; + return; case T_BIGNUM: w_byte(TYPE_BIGNUM, fp); - w_long(obj, fp); { char sign = RBIGNUM(obj)->sign?'+':'-'; int len = RBIGNUM(obj)->len; @@ -142,80 +219,92 @@ w_object(obj, fp, port, table) d++; } } - break; + return; + } + switch (BUILTIN_TYPE(obj)) { case T_STRING: - w_byte(TYPE_STRING, fp); - w_long(obj, fp); - w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, fp); - break; + if (CLASS_OF(obj) == cString) { + w_byte(TYPE_STRING, fp); + w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, fp); + } + else { + w_byte(TYPE_STRING2, fp); + w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, fp); + w_unique(rb_class2path(CLASS_OF(obj)), fp, table); + } + return; case T_REGEXP: w_byte(TYPE_REGEXP, fp); - w_long(obj, fp); w_bytes(RREGEXP(obj)->str, RREGEXP(obj)->len, fp); w_byte(FL_TEST(obj, FL_USER1), fp); - break; + return; case T_ARRAY: - w_byte(TYPE_ARRAY, fp); - w_long(obj, fp); + if (CLASS_OF(obj) == cArray) w_byte(TYPE_ARRAY, fp); + else w_byte(TYPE_ARRAY2, fp); { int len = RARRAY(obj)->len; VALUE *ptr = RARRAY(obj)->ptr; w_long(len, fp); while (len--) { - w_object(*ptr, fp, port, table); + w_object(*ptr, fp, limit, table); ptr++; } } + if (CLASS_OF(obj) != cArray) { + w_unique(rb_class2path(CLASS_OF(obj)), fp, table); + } break; case T_HASH: + if (CLASS_OF(obj) == cHash) w_byte(TYPE_HASH, fp); + else w_byte(TYPE_HASH2, fp); w_byte(TYPE_HASH, fp); - w_long(obj, fp); w_long(RHASH(obj)->tbl->num_entries, fp); - st_foreach(RHASH(obj)->tbl, hash_each, fp); + st_foreach(RHASH(obj)->tbl, hash_each, &arg); + if (CLASS_OF(obj) != cHash) { + w_unique(rb_class2path(CLASS_OF(obj)), fp, table); + } break; case T_STRUCT: w_byte(TYPE_STRUCT, fp); - w_long(obj, fp); { int len = RSTRUCT(obj)->len; char *path = rb_class2path(CLASS_OF(obj)); VALUE mem; int i; - w_bytes(path, strlen(path), fp); + w_unique(path, fp, table); w_long(len, fp); mem = rb_ivar_get(CLASS_OF(obj), rb_intern("__member__")); if (mem == Qnil) { - Fail("non-initialized struct"); + Fatal("non-initialized struct"); } for (i=0; i<len; i++) { - w_symbol(FIX2INT(RARRAY(mem)->ptr[i]), fp); - w_object(RSTRUCT(obj)->ptr[i], fp, port, table); + w_symbol(FIX2INT(RARRAY(mem)->ptr[i]), fp, table); + w_object(RSTRUCT(obj)->ptr[i], fp, limit, table); } } break; case T_OBJECT: w_byte(TYPE_OBJECT, fp); - w_long(obj, fp); { VALUE class = CLASS_OF(obj); - char *path = rb_class2path(class); + char *path; - w_bytes(path, strlen(path), fp); - if (rb_responds_to(obj, s_dump)) { - w_long(-1, fp); - rb_funcall(obj, s_dump, 1, port); + if (FL_TEST(class, FL_SINGLETON)) { + TypeError("singleton can't be dumped"); } - else if (ROBJECT(obj)->iv_tbl) { + path = rb_class2path(class); + w_unique(path, fp, table); + if (ROBJECT(obj)->iv_tbl) { w_long(ROBJECT(obj)->iv_tbl->num_entries, fp); - st_foreach(ROBJECT(obj)->iv_tbl, obj_each, fp); + st_foreach(ROBJECT(obj)->iv_tbl, obj_each, &arg); } else { w_long(0, fp); @@ -224,59 +313,108 @@ w_object(obj, fp, port, table) break; default: - Fail("can't dump %s", rb_class2name(CLASS_OF(obj))); + TypeError("can't dump %s", rb_class2name(CLASS_OF(obj))); break; } } } +struct dump_arg { + VALUE obj; + FILE *fp; + int limit; + st_table *table; +}; + static VALUE -marshal_dump(self, obj, port) - VALUE self, obj, port; +dump(arg) + struct dump_arg *arg; +{ + w_object(arg->obj, arg->fp, arg->limit, arg->table); +} + +static VALUE +dump_ensure(arg) + struct dump_arg *arg; +{ + st_free_table(arg->table); +} + +static VALUE +dump_on(obj, port, limit) + VALUE obj, port; + int limit; { extern VALUE cIO; FILE *fp; OpenFile *fptr; - st_table *table; + struct dump_arg arg; if (obj_is_kind_of(port, cIO)) { GetOpenFile(port, fptr); - if (!(fptr->mode & FMODE_WRITABLE)) { - Fail("not opened for writing"); - } + io_writable(fptr); fp = (fptr->f2) ? fptr->f2 : fptr->f; } else { - Fail("instance of IO needed"); + TypeError("instance of IO needed"); } - table = new_idhash(); + w_byte(MARSHAL_MAJOR, fp); + w_byte(MARSHAL_MINOR, fp); - w_object(obj, fp, port, table); + arg.obj = obj; + arg.fp = fp; + arg.limit = limit; + arg.table = st_init_numtable(); + rb_ensure(dump, &arg, dump_ensure, &arg); - st_free_table(table); return Qnil; } static VALUE -marshal_dumps(self, obj) - VALUE self, obj; +marshal_dump(argc, argv) + int argc; + VALUE argv; +{ + VALUE obj, port, lim; + int limit; + + rb_scan_args(argc, argv, "21", &obj, &port, &lim); + if (NIL_P(lim)) limit = 100; + else limit = NUM2INT(lim); + + dump_on(obj, port, limit); +} + +static VALUE +marshal_dumps(argc, argv) + int argc; + VALUE argv; { + VALUE obj, lim; + int limit; VALUE str = str_new(0, 0); VALUE port; - FILE *fp = Qnil; + FILE *fp = 0; char buf[BUFSIZ]; int n; - sprintf(buf, "/tmp/rb-mrsr-%x", getpid()^(int)buf); + rb_scan_args(argc, argv, "11", &obj, &lim); + if (NIL_P(lim)) limit = 100; + else limit = NUM2INT(lim); + + tmpnam(buf); port = file_open(buf, "w"); - if (!port) rb_sys_fail("tmp file"); - fp = fopen(buf, "r"); - if (!fp) rb_sys_fail("tmp file(read)"); + fp = rb_fopen(buf, "r"); +#if !defined(MSDOS) && !defined(__BOW__) unlink(buf); +#endif - marshal_dump(self, obj, port); + dump_on(obj, port, limit); io_close(port); +#if defined(MSDOS) || defined(__BOW__) + unlink(buf); +#endif while (n = fread(buf, 1, BUFSIZ, fp)) { str_cat(str, buf, n); @@ -310,67 +448,96 @@ r_long(fp) /* XXX If your long is > 32 bits, add sign-extension here!!! */ return x; } -#define r_bytes(s, fp) r_bytes0(&s, fp) -static int -r_bytes0(s, fp) - char **s; + +#define r_bytes(s, fp) \ + (s = (char*)r_long(fp), r_bytes0(&s,ALLOCA_N(char,(int)s),(int)s,fp)) + +static char +r_bytes0(sp, s, len, fp) + char **sp, *s; + int len; FILE *fp; { - int len = r_long(fp); - *s = ALLOC_N(char, len+1); + fread(s, 1, len, fp); + (s)[len] = '\0'; + *sp = s; - fread(*s, 1, len, fp); - (*s)[len] = '\0'; return len; } static ID -r_symbol(fp) +r_symbol(fp, table) FILE *fp; + st_table *table; { char *buf; ID id; + char type; + if (r_byte(fp) == TYPE_SYMLINK) { + int num = r_long(fp); + + if (st_lookup(table, num, &id)) { + return id; + } + TypeError("bad symbol"); + } r_bytes(buf, fp); id = rb_intern(buf); - free(buf); + st_insert(table, table->num_entries, id); + return id; } +static char* +r_unique(fp, table) + FILE *fp; + st_table *table; +{ + return rb_id2name(r_symbol(fp, table)); +} + static VALUE -r_object(fp, port, table) +r_string(fp) + FILE *fp; +{ + char *buf; + int len = r_bytes(buf, fp); + VALUE v; + + v = str_new(buf, len); + + return v; +} + +static VALUE +r_object(fp, table) FILE *fp; - VALUE port; st_table *table; { VALUE v; int type = r_byte(fp); - int id; switch (type) { case EOF: - Fail("EOF read where object expected"); + eof_error("EOF read where object expected"); return Qnil; case TYPE_NIL: return Qnil; - case TYPE_LINK: - if (st_lookup(table, r_long(fp), &v)) { - return v; - } - Fail("corrupted marshal file"); - break; + case TYPE_TRUE: + return TRUE; + + case TYPE_FALSE: + return FALSE; case TYPE_FIXNUM: { int i = r_long(fp); return INT2FIX(i); } - } - id = r_long(fp); - switch (type) { case TYPE_FLOAT: { double atof(); @@ -378,9 +545,8 @@ r_object(fp, port, table) r_bytes(buf, fp); v = float_new(atof(buf)); - free(buf); + return v; } - break; case TYPE_BIGNUM: { @@ -395,18 +561,16 @@ r_object(fp, port, table) while (len--) { *digits++ = r_short(fp); } - v = (VALUE)big; + return (VALUE)big; } - break; case TYPE_STRING: - { - char *buf; - int len = r_bytes(buf, fp); - v = str_new(buf, len); - free(buf); - } - break; + return r_string(fp); + + case TYPE_STRING2: + v = r_string(fp); + RBASIC(v)->class = rb_path2class(r_unique(fp, table)); + return v; case TYPE_REGEXP: { @@ -414,19 +578,18 @@ r_object(fp, port, table) int len = r_bytes(buf, fp); int ci = r_byte(fp); v = reg_new(buf, len, ci); - free(buf); + return v; } - break; case TYPE_ARRAY: { int len = r_long(fp); v = ary_new2(len); while (len--) { - ary_push(v, r_object(fp, port, table)); + ary_push(v, r_object(fp, table)); } + return v; } - break; case TYPE_HASH: { @@ -434,120 +597,150 @@ r_object(fp, port, table) v = hash_new(); while (len--) { - VALUE key = r_object(fp, port, table); - VALUE value = r_object(fp, port, table); + VALUE key = r_object(fp, table); + VALUE value = r_object(fp, table); hash_aset(v, key, value); } + return v; } - break; case TYPE_STRUCT: { VALUE class, mem, values; - char *path; int i, len; - r_bytes(path, fp); - class = rb_path2class(path); - free(path); + class = rb_path2class(r_unique(fp, table)); mem = rb_ivar_get(class, rb_intern("__member__")); if (mem == Qnil) { - Fail("non-initialized struct"); + Fatal("non-initialized struct"); } len = r_long(fp); - values = ary_new(); + values = ary_new2(len); i = 0; - while (len--) { - ID slot = r_symbol(fp); - if (RARRAY(mem)->ptr[i++] != INT2FIX(slot)) - Fail("struct not compatible"); - ary_push(values, r_object(fp, port, table)); + for (i=0; i<len; i++) { + ID slot = r_symbol(fp, table); + if (RARRAY(mem)->ptr[i] != INT2FIX(slot)) + TypeError("struct not compatible"); + ary_push(values, r_object(fp, table)); } v = struct_alloc(class, values); } break; + case TYPE_USERDEF: + { + VALUE class; + int len; + + class = rb_path2class(r_unique(fp, table)); + if (rb_respond_to(class, s_load)) { + v = rb_funcall(class, s_load, 1, r_string(fp)); + } + else { + TypeError("class %s needs to have method `_load_from'", + rb_class2name(class)); + } + } + break; case TYPE_OBJECT: { VALUE class; int len; - char *path; - r_bytes(path, fp); - class = rb_path2class(path); - free(path); + class = rb_path2class(r_unique(fp, table)); len = r_long(fp); - if (len == -1) { - if (rb_responds_to(class, s_load)) { - v = rb_funcall(class, s_load, 1, port); - } - else { - Fail("class %s needs to have method `_load_from'", - rb_class2name(class)); - } - } - else { - v = obj_alloc(class); - if (len > 0) { - while (len--) { - ID id = r_symbol(fp); - VALUE val = r_object(fp, port, table); - rb_ivar_set(v, id, val); - } + v = obj_alloc(class); + if (len > 0) { + while (len--) { + ID id = r_symbol(fp, table); + VALUE val = r_object(fp, table); + rb_ivar_set(v, id, val); } } } break; default: - Fail("dump format error(0x%x)", type); + ArgError("dump format error(0x%x)", type); break; } - st_insert(table, id, v); return v; } +struct load_arg { + FILE *fp; + st_table *table; +}; + +static VALUE +load(arg) + struct load_arg *arg; +{ + return r_object(arg->fp, arg->table); +} + +static VALUE +load_ensure(arg) + struct load_arg *arg; +{ + st_free_table(arg->table); +} + static VALUE marshal_load(self, port) VALUE self, port; { extern VALUE cIO; - void *fp; + FILE *fp; + int major; VALUE v; OpenFile *fptr; - st_table *table; + char buf[32]; +#if defined(MSDOS) || defined(__BOW__) + int need_unlink_tmp = 0; +#endif + struct load_arg arg; if (TYPE(port) == T_STRING) { - char buf[32]; - - sprintf(buf, "/tmp/rb-mrsw-%x", getpid()^(int)buf); - fp = fopen(buf, "w"); - if (!fp) rb_sys_fail("tmp file"); + tmpnam(buf); + fp = rb_fopen(buf, "w"); v = file_open(buf, "r"); - if (!v) rb_sys_fail("tmp file(read)"); +#if defined(MSDOS) || defined(__BOW__) + need_unlink_tmp = 0; +#else unlink(buf); +#endif fwrite(RSTRING(port)->ptr, RSTRING(port)->len, 1, fp); fclose(fp); port = v; } + if (obj_is_kind_of(port, cIO)) { GetOpenFile(port, fptr); - if (!(fptr->mode & FMODE_READABLE)) { - Fail("not opened for reading"); - } + io_readable(fptr); fp = fptr->f; } else { - Fail("instance of IO needed"); + TypeError("instance of IO needed"); } - table = new_idhash(); - - v = r_object(fp, port, table); - - st_free_table(table); + major = r_byte(fp); + if (major == MARSHAL_MAJOR) { + if (r_byte(fp) != MARSHAL_MINOR) { + Warning("Old marshal file format (can be read)"); + } + arg.fp = fp; + arg.table = st_init_numtable(); + v = rb_ensure(load, &arg, load_ensure, &arg); + } +#if defined(MSDOS) || defined(__BOW__) + if (need_unlink_tmp) unlink(buf); +#endif + if (major != MARSHAL_MAJOR) { + TypeError("Old marshal file format (can't read)"); + } return v; } @@ -558,8 +751,8 @@ Init_marshal() s_dump = rb_intern("_dump_to"); s_load = rb_intern("_load_from"); - rb_define_module_function(mMarshal, "dump", marshal_dump, 2); - rb_define_module_function(mMarshal, "dumps", marshal_dumps, 1); + rb_define_module_function(mMarshal, "dump", marshal_dump, -1); + rb_define_module_function(mMarshal, "dumps", marshal_dumps, -1); rb_define_module_function(mMarshal, "load", marshal_load, 1); rb_define_module_function(mMarshal, "restore", marshal_load, 1); } diff --git a/ext/marshal/marshal.doc b/ext/marshal/marshal.doc index 8c3b63072e..7529e7942f 100644 --- a/ext/marshal/marshal.doc +++ b/ext/marshal/marshal.doc @@ -10,7 +10,7 @@ ruby���֥������Ȥ�ե�����˽Ф����ꡤ�ɤߤ��٤����ꤹ�뵡ǽ���� Methods: Single Methods: - dump(obj, port) + dump(obj, port[, limit]) obj��Ƶ�Ū�˥ե�����˽Ф����ե�����˽Ф��ʤ����饹�Υ� ����ե�����˽Ф����Ȥ�����㳰��ȯ�������롥�ե����� @@ -28,6 +28,9 @@ Single Methods: `_dump_to'����ĥ��饹��ɬ��Ʊ���ե����ޥåȤ��ɤ��᤹�ðۥ�å� `_load_from'���������ɬ�פ����롥 + limit����ꤷ����硤limit�ʰʾ忼����������֥������Ȥ����� + �Ǥ��ʤ�(�ǥե���Ȥ�100��٥�)�����limit����ꤹ��ȿ��������å� + ��Ԥ�ʤ��� dumps(obj) diff --git a/ext/md5/MANIFEST b/ext/md5/MANIFEST new file mode 100644 index 0000000000..e4f0004b4a --- /dev/null +++ b/ext/md5/MANIFEST @@ -0,0 +1,6 @@ +MANIFEST +depend +md5.doc +md5.h +md5c.c +md5init.c diff --git a/ext/md5/depend b/ext/md5/depend new file mode 100644 index 0000000000..be56da89b9 --- /dev/null +++ b/ext/md5/depend @@ -0,0 +1,2 @@ +md5c.o: md5c.c md5.h +md5init.o: md5init.c ../../ruby.h ../../config.h ../../defines.h md5.h diff --git a/ext/md5/md5.doc b/ext/md5/md5.doc new file mode 100644 index 0000000000..2203404602 --- /dev/null +++ b/ext/md5/md5.doc @@ -0,0 +1,36 @@ +.\" md5.doc - -*- Indented-Text -*- created at: Fri Aug 2 12:01:27 JST 1996 + +** MD5(���饹) + +RFC1321�˵��Ҥ���Ƥ���RSA Data Security, Inc. �� MD5 Message-Digest +Algorithm��������륯�饹�� + +SuperClass: Object + +Class Methods: + + new([str]) + md5([str]) + + ������MD5���֥������Ȥ��������롥ʸ���������Ϳ������Ȥ��� + ���ɲä���(see update)�� + +Methods: + + clone + + MD5���֥������Ȥ�ʣ������ + + digest + + ���ޤǤ��ɲä���ʸ������Ф���ϥå����ͤ�16�Х���Ĺ��ʸ����� + �֤��� + + update(str) + + key���Ȥ����ͤ��֤��� + +------------------------------------------------------- +Local variables: +fill-column: 70 +end: diff --git a/ext/md5/md5.h b/ext/md5/md5.h new file mode 100644 index 0000000000..81a6d7ff36 --- /dev/null +++ b/ext/md5/md5.h @@ -0,0 +1,86 @@ +/* MD5.H - header file for MD5C.C + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +/* ========== include global.h ========== */ +/* GLOBAL.H - RSAREF types and constants + */ + +/* PROTOTYPES should be set to one if and only if the compiler supports + function argument prototyping. +The following makes PROTOTYPES default to 0 if it has not already + been defined with C compiler flags. + */ +#ifdef HAVE_PROTOTYPES +#define PROTOTYPES 1 +#endif +#ifndef PROTOTYPES +#define PROTOTYPES 0 +#endif + +/* POINTER defines a generic pointer type */ +typedef unsigned char *POINTER; + +/* UINT2 defines a two byte word */ +typedef unsigned short int UINT2; + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#else +/* Wild guess */ +#define LONG_MAX 2147483647L +#endif + +/* UINT4 defines a four byte word */ +#if defined(INT_MAX) && INT_MAX == 2147483647 +typedef unsigned int UINT4; +#else +#if defined(LONG_MAX) && LONG_MAX == 2147483647L +typedef unsigned long int UINT4; +#endif +/* Too bad if neither is */ +#endif + +/* PROTO_LIST is defined depending on how PROTOTYPES is defined above. +If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it + returns an empty list. + */ +#if PROTOTYPES +#define PROTO_LIST(list) list +#else +#define PROTO_LIST(list) () +#endif +/* ========== End global.h; continue md5.h ========== */ + +/* MD5 context. */ +typedef struct { + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} MD5_CTX; + +void MD5Init PROTO_LIST ((MD5_CTX *)); +void MD5Update PROTO_LIST + ((MD5_CTX *, unsigned char *, unsigned int)); +void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); diff --git a/ext/md5/md5c.c b/ext/md5/md5c.c new file mode 100644 index 0000000000..d7c7e4fb27 --- /dev/null +++ b/ext/md5/md5c.c @@ -0,0 +1,337 @@ +/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "md5.h" + +/* Constants for MD5Transform routine. + */ + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); +static void Encode PROTO_LIST + ((unsigned char *, UINT4 *, unsigned int)); +static void Decode PROTO_LIST + ((UINT4 *, unsigned char *, unsigned int)); +static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); +static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); + +static unsigned char PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G, H and I are basic MD5 functions. + */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. + */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +Rotation is separate from addition to prevent recomputation. + */ +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +/* MD5 initialization. Begins an MD5 operation, writing a new context. + */ +void MD5Init (context) +MD5_CTX *context; /* context */ +{ + context->count[0] = context->count[1] = 0; + /* Load magic initialization constants. +*/ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* MD5 block update operation. Continues an MD5 message-digest + operation, processing another message block, and updating the + context. + */ +void MD5Update (context, input, inputLen) +MD5_CTX *context; /* context */ +unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +{ + unsigned int i, index, partLen; + + /* Compute number of bytes mod 64 */ + index = (unsigned int)((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((UINT4)inputLen << 3)) + < ((UINT4)inputLen << 3)) + context->count[1]++; + context->count[1] += ((UINT4)inputLen >> 29); + + partLen = 64 - index; + + /* Transform as many times as possible. +*/ + if (inputLen >= partLen) { + MD5_memcpy + ((POINTER)&context->buffer[index], (POINTER)input, partLen); + MD5Transform (context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform (context->state, &input[i]); + + index = 0; + } + else + i = 0; + + /* Buffer remaining input */ + MD5_memcpy + ((POINTER)&context->buffer[index], (POINTER)&input[i], + inputLen-i); +} + +/* MD5 finalization. Ends an MD5 message-digest operation, writing the + the message digest and zeroizing the context. + */ +void MD5Final (digest, context) +unsigned char digest[16]; /* message digest */ +MD5_CTX *context; /* context */ +{ + unsigned char bits[8]; + unsigned int index, padLen; + + /* Save number of bits */ + Encode (bits, context->count, 8); + + /* Pad out to 56 mod 64. +*/ + index = (unsigned int)((context->count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + MD5Update (context, PADDING, padLen); + + /* Append length (before padding) */ + MD5Update (context, bits, 8); + + /* Store state in digest */ + Encode (digest, context->state, 16); + + /* Zeroize sensitive information. +*/ + MD5_memset ((POINTER)context, 0, sizeof (*context)); +} + +/* MD5 basic transformation. Transforms state based on block. + */ +static void MD5Transform (state, block) +UINT4 state[4]; +unsigned char block[64]; +{ + UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode (x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. +*/ + MD5_memset ((POINTER)x, 0, sizeof (x)); +} + +/* Encodes input (UINT4) into output (unsigned char). Assumes len is + a multiple of 4. + */ +static void Encode (output, input, len) +unsigned char *output; +UINT4 *input; +unsigned int len; +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + +/* Decodes input (unsigned char) into output (UINT4). Assumes len is + a multiple of 4. + */ +static void Decode (output, input, len) +UINT4 *output; +unsigned char *input; +unsigned int len; +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | + (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); +} + +/* Note: Replace "for loop" with standard memcpy if possible. + */ + +static void MD5_memcpy (output, input, len) +POINTER output; +POINTER input; +unsigned int len; +{ + unsigned int i; + + for (i = 0; i < len; i++) + output[i] = input[i]; +} + +/* Note: Replace "for loop" with standard memset if possible. + */ +static void MD5_memset (output, value, len) +POINTER output; +int value; +unsigned int len; +{ + unsigned int i; + + for (i = 0; i < len; i++) + ((char *)output)[i] = (char)value; +} diff --git a/ext/md5/md5init.c b/ext/md5/md5init.c new file mode 100644 index 0000000000..85f0847e71 --- /dev/null +++ b/ext/md5/md5init.c @@ -0,0 +1,90 @@ +/************************************************ + + md5init.c - + + $Author: matz $ + created at: Fri Aug 2 09:24:12 JST 1996 + + Copyright (C) 1995 Yukihiro Matsumoto + +************************************************/ +/* This module provides an interface to the RSA Data Security, + Inc. MD5 Message-Digest Algorithm, described in RFC 1321. + It requires the files md5c.c and md5.h (which are slightly changed + from the versions in the RFC to avoid the "global.h" file.) */ + +#include "ruby.h" +#include "md5.h" + +static VALUE cMD5; + +static VALUE +md5_update(obj, str) + VALUE obj; + struct RString *str; +{ + MD5_CTX *md5; + + Check_Type(str, T_STRING); + Get_Data_Struct(obj, MD5_CTX, md5); + MD5Update(md5, str->ptr, str->len); + + return Qnil; +} +static VALUE +md5_digest(obj) + VALUE obj; +{ + MD5_CTX *md5, ctx; + unsigned char digest[16]; + + Get_Data_Struct(obj, MD5_CTX, md5); + ctx = *md5; + MD5Final(digest, &ctx); + + return str_new(digest, 16); +} + +static VALUE +md5_clone(obj) + VALUE obj; +{ + VALUE clone; + MD5_CTX *md5, *md5_new; + + Get_Data_Struct(obj, MD5_CTX, md5); + obj = Make_Data_Struct(CLASS_OF(obj), MD5_CTX, 0, 0, md5_new); + *md5_new = *md5; + + return obj; +} + +static VALUE +md5_new(argc, argv, class) +{ + int i; + VALUE arg, obj; + MD5_CTX *md5; + + rb_scan_args(argc, argv, "01", &arg); + if (!NIL_P(arg)) Check_Type(arg, T_STRING); + + obj = Make_Data_Struct(class, MD5_CTX, 0, 0, md5); + MD5Init(md5); + if (!NIL_P(arg)) { + md5_update(obj, arg); + } + + return obj; +} + +Init_md5() +{ + cMD5 = rb_define_class("MD5", cObject); + + rb_define_singleton_method(cMD5, "new", md5_new, -1); + + rb_define_method(cMD5, "update", md5_update, 1); + rb_define_method(cMD5, "digest", md5_digest, 0); + rb_define_method(cMD5, "clone", md5_clone, 0); +} diff --git a/ext/socket/MANIFEST b/ext/socket/MANIFEST index 836caada41..d41d9e0b69 100644 --- a/ext/socket/MANIFEST +++ b/ext/socket/MANIFEST @@ -2,4 +2,3 @@ MANIFEST depend extconf.rb socket.c -socket.doc diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb index 60d6deeb84..f2ec0578d5 100644 --- a/ext/socket/extconf.rb +++ b/ext/socket/extconf.rb @@ -1,6 +1,11 @@ -have_library("inet", "gethostbyname") have_library("socket", "socket") +have_library("inet", "gethostbyname") +have_library("nsl", "gethostbyname") have_header("sys/un.h") if have_func("socket") + have_func("hsterror") + unless have_func("gethostname") + have_func("uname") + end create_makefile("socket") end diff --git a/ext/socket/socket.c b/ext/socket/socket.c index 5671b2762c..6b4f0f5559 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -18,11 +18,11 @@ #include <errno.h> #ifdef HAVE_SYS_UN_H #include <sys/un.h> -#else -#undef AF_UNIX #endif extern VALUE cIO; +extern VALUE cInteger; + VALUE cBasicSocket; VALUE cTCPsocket; VALUE cTCPserver; @@ -32,6 +32,9 @@ VALUE cUNIXserver; #endif VALUE cSocket; +extern VALUE eException; +static VALUE eSocket; + FILE *rb_fdopen(); char *strdup(); @@ -52,8 +55,9 @@ sock_new(class, fd) VALUE class; int fd; { - VALUE sock = obj_alloc(class); OpenFile *fp; + NEWOBJ(sock, struct RFile); + OBJSETUP(sock, class, T_FILE); MakeOpenFile(sock, fp); #ifdef NT @@ -64,7 +68,7 @@ sock_new(class, fd) fp->f2 = rb_fdopen(fd, "w"); fp->mode = FMODE_READWRITE|FMODE_SYNC; - return sock; + return (VALUE)sock; } static VALUE @@ -86,34 +90,53 @@ bsock_shutdown(argc, argv, sock) } GetOpenFile(sock, fptr); if (shutdown(fileno(fptr->f), how) == -1) - rb_sys_fail(Qnil); + rb_sys_fail(0); return INT2FIX(0); } static VALUE -bsock_setopt(sock, lev, optname, val) +bsock_setsockopt(sock, lev, optname, val) VALUE sock, lev, optname; struct RString *val; { int level, option; OpenFile *fptr; + int i; + char *v; + int vlen; level = NUM2INT(lev); option = NUM2INT(optname); - Check_Type(val, T_STRING); + switch (TYPE(val)) { + case T_FIXNUM: + i = FIX2INT(val); + goto numval; + case T_FALSE: + i = 0; + goto numval; + case T_TRUE: + i = 1; + numval: + v = (char*)&i; vlen = sizeof(i); + break; + default: + Check_Type(val, T_STRING); + v = val->ptr; vlen = val->len; + } GetOpenFile(sock, fptr); - if (setsockopt(fileno(fptr->f), level, option, val->ptr, val->len) < 0) + if (setsockopt(fileno(fptr->f), level, option, v, vlen) < 0) rb_sys_fail(fptr->path); return INT2FIX(0); } static VALUE -bsock_getopt(sock, lev, optname) +bsock_getsockopt(sock, lev, optname) VALUE sock, lev, optname; { +#if !defined(__CYGWIN32__) int level, option, len; struct RString *val; OpenFile *fptr; @@ -128,7 +151,11 @@ bsock_getopt(sock, lev, optname) if (getsockopt(fileno(fptr->f), level, option, val->ptr, &len) < 0) rb_sys_fail(fptr->path); val->len = len; + return (VALUE)val; +#else + rb_notimplement(); +#endif } static VALUE @@ -184,8 +211,14 @@ open_inet(class, h, serv, server) if (hostaddr == -1) { if (server && !strlen(host)) hostaddr = INADDR_ANY; - else - rb_sys_fail(host); + else { +#ifdef HAVE_HSTRERROR + extern int h_errno; + Raise(eSocket, (char *)hstrerror(h_errno)); +#else + Raise(eSocket, "host not found"); +#endif + } } _hostent.h_addr_list = (char **)hostaddrPtr; _hostent.h_addr_list[0] = (char *)&hostaddr; @@ -203,27 +236,31 @@ open_inet(class, h, serv, server) Check_Type(serv, T_STRING); servent = getservbyname(RSTRING(serv)->ptr, "tcp"); if (servent == NULL) { - servport = strtoul(RSTRING(serv)->ptr, Qnil, 0); - if (servport == -1) Fail("no such servce %s", RSTRING(serv)->ptr); + servport = strtoul(RSTRING(serv)->ptr, 0, 0); + if (servport == -1) { + Raise(eSocket, "no such servce %s", RSTRING(serv)->ptr); + } setup_servent: - _servent.s_port = servport; - _servent.s_proto = "tcp"; + _servent.s_port = htons(servport); + _servent.s_proto = "tcp"; servent = &_servent; } protoent = getprotobyname(servent->s_proto); - if (protoent == NULL) Fail("no such proto %s", servent->s_proto); + if (protoent == NULL) { + Raise(eSocket, "no such proto %s", servent->s_proto); + } fd = socket(PF_INET, SOCK_STREAM, protoent->p_proto); sockaddr.sin_family = AF_INET; - if (h == Qnil) { - sockaddr.sin_addr.s_addr = INADDR_ANY; - } - else { + if (h) { memcpy((char *)&(sockaddr.sin_addr.s_addr), (char *) hostent->h_addr_list[0], (size_t) hostent->h_length); } + else { + sockaddr.sin_addr.s_addr = INADDR_ANY; + } sockaddr.sin_port = servent->s_port; if (server) { @@ -248,7 +285,7 @@ open_inet(class, h, serv, server) } static VALUE -tcp_s_sock_open(class, host, serv) +tcp_s_open(class, host, serv) VALUE class, host, serv; { Check_Type(host, T_STRING); @@ -266,7 +303,7 @@ tcp_svr_s_open(argc, argv, class) if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) return open_inet(class, arg1, arg2, 1); else - return open_inet(class, Qnil, arg1, 1); + return open_inet(class, 0, arg1, 1); } static VALUE @@ -279,10 +316,15 @@ s_accept(class, fd, sockaddr, len) int fd2; retry: +#ifdef THREAD + thread_wait_fd(fd); +#endif + TRAP_BEG; fd2 = accept(fd, sockaddr, len); + TRAP_END; if (fd2 < 0) { if (errno == EINTR) goto retry; - rb_sys_fail(Qnil); + rb_sys_fail(0); } return sock_new(class, fd2); } @@ -301,7 +343,7 @@ tcp_accept(sock) (struct sockaddr*)&from, &fromlen); } -#ifdef AF_UNIX +#ifdef HAVE_SYS_UN_H static VALUE open_unix(class, path, server) VALUE class; @@ -346,11 +388,63 @@ open_unix(class, path, server) } #endif +static void +setipaddr(name, addr) + char *name; + struct sockaddr_in *addr; +{ + int d1, d2, d3, d4; + char ch; + struct hostent *hp; + long x; + unsigned char *a; + char buf[16]; + + if (name[0] == 0) { + addr->sin_addr.s_addr = INADDR_ANY; + } + else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) { + addr->sin_addr.s_addr = INADDR_BROADCAST; + } + else if (sscanf(name, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 && + 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 && + 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) { + addr->sin_addr.s_addr = htonl( + ((long) d1 << 24) | ((long) d2 << 16) | + ((long) d3 << 8) | ((long) d4 << 0)); + } + else { + hp = gethostbyname(name); + if (!hp) { +#ifdef HAVE_HSTRERROR + extern int h_errno; + Raise(eSocket, (char *)hstrerror(h_errno)); +#else + Raise(eSocket, "host not found"); +#endif + } + memcpy((char *) &addr->sin_addr, hp->h_addr, hp->h_length); + } +} + +static VALUE +mkipaddr(x) + unsigned long x; +{ + char buf[16]; + + x = ntohl(x); + sprintf(buf, "%d.%d.%d.%d", + (int) (x>>24) & 0xff, (int) (x>>16) & 0xff, + (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff); + return str_new2(buf); +} + static VALUE tcpaddr(sockaddr) struct sockaddr_in *sockaddr; { - VALUE family, port, addr; + VALUE family, port, addr1, addr2; VALUE ary; struct hostent *hostent; @@ -358,17 +452,15 @@ tcpaddr(sockaddr) hostent = gethostbyaddr((char*)&sockaddr->sin_addr.s_addr, sizeof(sockaddr->sin_addr), AF_INET); + addr1 = 0; if (hostent) { - addr = str_new2(hostent->h_name); + addr1 = str_new2(hostent->h_name); } - else { - char buf[16]; - char *a = (char*)&sockaddr->sin_addr; - sprintf(buf, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]); - addr = str_new2(buf); - } - port = INT2FIX(sockaddr->sin_port); - ary = ary_new3(3, family, port, addr); + addr2 = mkipaddr(sockaddr->sin_addr.s_addr); + if (!addr1) addr1 = addr2; + + port = INT2FIX(ntohs(sockaddr->sin_port)); + ary = ary_new3(4, family, port, addr1, addr2); return ary; } @@ -399,11 +491,30 @@ tcp_peeraddr(sock) GetOpenFile(sock, fptr); if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) - rb_sys_fail("getsockname(2)"); + rb_sys_fail("getpeername(2)"); return tcpaddr(&addr); } -#ifdef AF_UNIX +static VALUE +tcp_s_getaddress(obj, host) + VALUE obj, host; +{ + struct sockaddr_in addr; + struct hostent *h; + + if (obj_is_kind_of(host, cInteger)) { + int i = NUM2INT(host); + addr.sin_addr.s_addr = htonl(i); + } + else { + Check_Type(host, T_STRING); + setipaddr(RSTRING(host)->ptr, &addr); + } + + return mkipaddr(addr.sin_addr.s_addr); +} + +#ifdef HAVE_SYS_UN_H static VALUE unix_s_sock_open(sock, path) VALUE sock, path; @@ -418,11 +529,11 @@ unix_path(sock) OpenFile *fptr; GetOpenFile(sock, fptr); - if (fptr->path == Qnil) { + if (fptr->path == 0) { struct sockaddr_un addr; int len = sizeof(addr); if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) - rb_sys_fail(Qnil); + rb_sys_fail(0); fptr->path = strdup(addr.sun_path); } return str_new2(fptr->path); @@ -515,7 +626,7 @@ setup_domain_and_type(domain, dv, type, tv) *dv = PF_IPX; #endif else - Fail("Unknown socket domain %s", ptr); + Raise(eSocket, "Unknown socket domain %s", ptr); } else { *dv = NUM2INT(domain); @@ -543,7 +654,7 @@ setup_domain_and_type(domain, dv, type, tv) *tv = SOCK_PACKET; #endif else - Fail("Unknown socket type %s", ptr); + Raise(eSocket, "Unknown socket type %s", ptr); } else { *tv = NUM2INT(type); @@ -559,7 +670,7 @@ sock_s_open(class, domain, type, protocol) setup_domain_and_type(domain, &d, type, &t); fd = socket(d, t, NUM2INT(protocol)); - if (fd < 0) rb_sys_fail("socke(2)"); + if (fd < 0) rb_sys_fail("socket(2)"); return sock_new(class, fd); } @@ -574,6 +685,7 @@ static VALUE sock_s_socketpair(class, domain, type, protocol) VALUE class, domain, type, protocol; { +#if !defined(__CYGWIN32__) int fd; int d, t, sp[2]; @@ -582,6 +694,9 @@ sock_s_socketpair(class, domain, type, protocol) rb_sys_fail("socketpair(2)"); return assoc_new(sock_new(class, sp[0]), sock_new(class, sp[1])); +#else + rb_notimplement(); +#endif } static VALUE @@ -665,6 +780,9 @@ sock_send(argc, argv, sock) GetOpenFile(sock, fptr); f = fptr->f2?fptr->f2:fptr->f; fd = fileno(f); +#ifdef THREAD + thread_fd_writable(fd); +#endif if (to) { Check_Type(to, T_STRING); n = sendto(fd, msg->ptr, msg->len, NUM2INT(flags), @@ -703,8 +821,15 @@ s_recv(sock, argc, argv, from) GetOpenFile(sock, fptr); fd = fileno(fptr->f); - if ((str->len = recvfrom(fd, str->ptr, str->len, flags, - (struct sockaddr*)buf, &alen)) < 0) { +#ifdef THREAD + thread_wait_fd(fd); +#endif + TRAP_BEG; + str->len = recvfrom(fd, str->ptr, str->len, flags, + (struct sockaddr*)buf, &alen); + TRAP_END; + + if (str->len < 0) { rb_sys_fail("recvfrom(2)"); } @@ -732,28 +857,173 @@ sock_recvfrom(argc, argv, sock) return s_recv(sock, argc, argv, 1); } +#ifdef HAVE_GETHOSTNAME +static VALUE +sock_gethostname(obj) + VALUE obj; +{ + char buf[1024]; + + if (gethostname(buf, (int)sizeof buf - 1) < 0) + rb_sys_fail("gethostname"); + + buf[sizeof buf - 1] = '\0'; + return str_new2(buf); +} +#else +#ifdef HAVE_UNAME + +#include <sys/utsname.h> + +static VALUE +sock_gethostname(obj) + VALUE obj; +{ + struct utsname un; + + uname(&un); + return str_new2(un.nodename); +} +#else +static VALUE +sock_gethostname(obj) + VALUE obj; +{ + rb_notimplement(); +} +#endif +#endif + +static VALUE +mkhostent(h) + struct hostent *h; +{ + struct sockaddr_in addr; + char **pch; + VALUE ary, names; + + if (h == NULL) { +#ifdef HAVE_HSTRERROR + extern int h_errno; + Raise(eSocket, (char *)hstrerror(h_errno)); +#else + Raise(eSocket, "host not found"); +#endif + } + ary = ary_new(); + ary_push(ary, str_new2(h->h_name)); + names = ary_new(); + ary_push(ary, names); + for (pch = h->h_aliases; *pch; pch++) { + ary_push(names, str_new2(*pch)); + } + ary_push(ary, INT2FIX(h->h_length)); +#ifdef h_addr + for (pch = h->h_addr_list; *pch; pch++) { + ary_push(ary, str_new(*pch, h->h_length)); + } +#else + ary_push(ary, str_new(h->h_addr, h->h_length)); +#endif + + return ary; +} + +static VALUE +sock_s_gethostbyname(obj, host) + VALUE obj, host; +{ + struct sockaddr_in addr; + struct hostent *h; + + if (obj_is_kind_of(host, cInteger)) { + int i = NUM2INT(host); + addr.sin_addr.s_addr = htonl(i); + } + else { + Check_Type(host, T_STRING); + setipaddr(RSTRING(host)->ptr, &addr); + } + h = gethostbyaddr((char *)&addr.sin_addr, + sizeof(addr.sin_addr), + AF_INET); + + return mkhostent(h); +} + +sock_s_gethostbyaddr(argc, argv) + int argc; + VALUE *argv; +{ + VALUE vaddr, vtype; + int type; + + struct sockaddr_in *addr; + struct hostent *h; + + rb_scan_args(argc, argv, "11", &addr, &type); + Check_Type(addr, T_STRING); + if (!NIL_P(type)) { + type = NUM2INT(vtype); + } + else { + type = AF_INET; + } + + h = gethostbyaddr(RSTRING(addr)->ptr, RSTRING(addr)->len, type); + + return mkhostent(h); +} + +static VALUE +sock_s_getservbyaname(argc, argv) + int argc; + VALUE *argv; +{ + VALUE service, protocol; + char *name, *proto; + struct servent *sp; + int port; + + rb_scan_args(argc, argv, "11", &service, &protocol); + Check_Type(service, T_STRING); + if (NIL_P(protocol)) proto = "tcp"; + else proto = RSTRING(protocol)->ptr; + + sp = getservbyname(RSTRING(service)->ptr, proto); + if (!sp) { + Raise(eSocket, "service/proto not found"); + } + port = ntohs(sp->s_port); + + return INT2FIX(port); +} + Init_socket () { + eSocket = rb_define_class("SocketError", eException); + cBasicSocket = rb_define_class("BasicSocket", cIO); rb_undef_method(cBasicSocket, "new"); rb_define_method(cBasicSocket, "shutdown", bsock_shutdown, -1); - rb_define_method(cBasicSocket, "setopt", bsock_setopt, 3); - rb_define_method(cBasicSocket, "getopt", bsock_getopt, 2); + rb_define_method(cBasicSocket, "setsockopt", bsock_setsockopt, 3); + rb_define_method(cBasicSocket, "getsockopt", bsock_getsockopt, 2); rb_define_method(cBasicSocket, "getsockname", bsock_getsockname, 0); rb_define_method(cBasicSocket, "getpeername", bsock_getpeername, 0); cTCPsocket = rb_define_class("TCPsocket", cBasicSocket); - rb_define_singleton_method(cTCPsocket, "open", tcp_s_sock_open, 2); - rb_define_singleton_method(cTCPsocket, "new", tcp_s_sock_open, 2); + rb_define_singleton_method(cTCPsocket, "open", tcp_s_open, 2); + rb_define_singleton_method(cTCPsocket, "new", tcp_s_open, 2); rb_define_method(cTCPsocket, "addr", tcp_addr, 0); rb_define_method(cTCPsocket, "peeraddr", tcp_peeraddr, 0); + rb_define_singleton_method(cTCPsocket, "getaddress", tcp_s_getaddress, 1); cTCPserver = rb_define_class("TCPserver", cTCPsocket); rb_define_singleton_method(cTCPserver, "open", tcp_svr_s_open, -1); rb_define_singleton_method(cTCPserver, "new", tcp_svr_s_open, -1); rb_define_method(cTCPserver, "accept", tcp_accept, 0); -#ifdef AF_UNIX +#ifdef HAVE_SYS_UN_H cUNIXsocket = rb_define_class("UNIXsocket", cBasicSocket); rb_define_singleton_method(cUNIXsocket, "open", unix_s_sock_open, 1); rb_define_singleton_method(cUNIXsocket, "new", unix_s_sock_open, 1); @@ -782,4 +1052,64 @@ Init_socket () rb_define_method(cSocket, "recvfrom", sock_recv, -1); rb_define_singleton_method(cSocket, "socketpair", sock_s_socketpair, 3); + rb_define_singleton_method(cSocket, "pair", sock_s_socketpair, 3); + rb_define_singleton_method(cSocket, "gethostname", sock_gethostname, 0); + rb_define_singleton_method(cSocket, "gethostbyname", sock_s_gethostbyname, 1); + rb_define_singleton_method(cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1); + rb_define_singleton_method(cSocket, "getservbyname", sock_s_getservbyaname, -1); + + /* constants */ + rb_define_const(cSocket, "AF_INET", INT2FIX(AF_INET)); + rb_define_const(cSocket, "PF_INET", INT2FIX(PF_INET)); +#ifdef AF_UNIX + rb_define_const(cSocket, "AF_UNIX", INT2FIX(AF_UNIX)); + rb_define_const(cSocket, "PF_UNIX", INT2FIX(PF_UNIX)); +#endif +#ifdef AF_IPX + rb_define_const(cSocket, "AF_IPX", INT2FIX(AF_IPX)); + rb_define_const(cSocket, "PF_IPX", INT2FIX(PF_IPX)); +#endif +#ifdef AF_APPLETALK + rb_define_const(cSocket, "AF_APPLETALK", INT2FIX(AF_APPLETALK)); + rb_define_const(cSocket, "PF_APPLETALK", INT2FIX(PF_APPLETALK)); +#endif + + rb_define_const(cSocket, "MSG_OOB", INT2FIX(MSG_OOB)); + rb_define_const(cSocket, "MSG_PEEK", INT2FIX(MSG_PEEK)); + rb_define_const(cSocket, "MSG_DONTROUTE", INT2FIX(MSG_DONTROUTE)); + + rb_define_const(cSocket, "SOCK_STREAM", INT2FIX(SOCK_STREAM)); + rb_define_const(cSocket, "SOCK_DGRAM", INT2FIX(SOCK_DGRAM)); + rb_define_const(cSocket, "SOCK_RAW", INT2FIX(SOCK_RAW)); +#ifdef SOCK_RDM + rb_define_const(cSocket, "SOCK_RDM", INT2FIX(SOCK_RDM)); +#endif +#ifdef SOCK_SEQPACKET + rb_define_const(cSocket, "SOCK_SEQPACKET", INT2FIX(SOCK_SEQPACKET)); +#endif +#ifdef SOCK_PACKET + rb_define_const(cSocket, "SOCK_PACKET", INT2FIX(SOCK_PACKET)); +#endif + + rb_define_const(cSocket, "SOL_SOCKET", INT2FIX(SOL_SOCKET)); +#ifdef SOL_IP + rb_define_const(cSocket, "SOL_IP", INT2FIX(SOL_IP)); +#endif +#ifdef SOL_IPX + rb_define_const(cSocket, "SOL_IPX", INT2FIX(SOL_IPX)); +#endif +#ifdef SOL_ATALK + rb_define_const(cSocket, "SOL_ATALK", INT2FIX(SOL_ATALK)); +#endif +#ifdef SOL_TCP + rb_define_const(cSocket, "SOL_TCP", INT2FIX(SOL_TCP)); +#endif +#ifdef SOL_UDP + rb_define_const(cSocket, "SOL_UDP", INT2FIX(SOL_UDP)); +#endif + + rb_define_const(cSocket, "SO_DEBUG", INT2FIX(SO_DEBUG)); + rb_define_const(cSocket, "SO_REUSEADDR", INT2FIX(SO_REUSEADDR)); + rb_define_const(cSocket, "SO_KEEPALIVE", INT2FIX(SO_KEEPALIVE)); + rb_define_const(cSocket, "SO_LINGER", INT2FIX(SO_LINGER)); } diff --git a/ext/socket/socket.doc b/ext/socket/socket.doc deleted file mode 100644 index aa5bfedbff..0000000000 --- a/ext/socket/socket.doc +++ /dev/null @@ -1,227 +0,0 @@ -.\" socket.doc - -*- Indented-Text -*- created at: Thu Mar 23 20:29:02 JST 1995 - -** Socket(���饹) - -SuperClass: BasicSocket - -�����åȤ��Τ�Τ��Ф��륷���ƥॳ�����٥�Υ������������륯�饹�� -Perl�Υ����åȤ��Ф��륢��������Ʊ��٥�ε�ǽ�����Ƥ��롥���Υ��� -���Ǥϥ����åȥ��ɥ쥹��pack���줿ʸ����ǡ����ꤹ�롥UDP�����åȤϤ� -�Υ��饹��Ȥä����Ѥ��롥 - -Methods: - - accept - - ��������³������դ��ơ���������³���Ф��륽���åȤȥ��ɥ쥹�� - �ڥ����֤���accept(2)�ȡ� - - bind(addr) - - bind(2)��Ʊ��Ư���롥addr��pack���줿�����åȥ��ɥ쥹��¤ - �ΤǤ��롥 - - connect(addr) - - connect(2)��Ʊ��Ư���롥addr��pack���줿�����åȥ��ɥ쥹�� - ¤�ΤǤ��롥 - - listen(backlog) - - listen(2)��Ʊ��Ư���롥 - - recv(len[, flags]) - - �����åȤ���ǡ����������ꡤʸ����Ȥ����֤���len�ϼ������ - �����Ĺ������ꤹ�롥flags�ˤĤ��Ƥ�recv(2)�ȡ�flags�Υ� - �ե�����ͤ�0�Ǥ��롥 - - recvfrom(len[, flags]) - - recv��Ʊ�ͤ˥����åȤ���ǡ����������뤬������ͤ�ʸ������� - ����åȤΥ��ɥ쥹�Υڥ��Ǥ��롥�����ˤĤ��Ƥ�recv��Ʊ�͡� - - send(mesg, flags[, to]) - - �����åȤ�𤷤ƥǡ��������롥flags�˴ؤ��Ƥ�send(2)�Ȥλ��� - connect���Ƥ��ʤ������åȤ��Ф��Ƥ�������Ǥ���to����ꤹ��ɬ - �פ����롥�ºݤ����ä��ǡ�����Ĺ�����֤��� - -Single Methods: - - open(domain, type, protocol) - new(domain, type, protocol) - - �����������åȤ��������롥domain��type��protocol�ϥ��롼�� - �ե�������������Ƥ�������ͤǻ��ꤹ�롥domain��type�˴ؤ��� - �ϡ�ʸ����ǻ���Ǥ��뤬�����٤ƤС����Ƥ����ݾڤϤʤ��� - - socketpair(domain, type, protocol) - - �����åȤΥڥ����֤��������λ���� open��Ʊ���Ǥ��롥 - -** BasicSocket(���饹) - -�����åȤ�ɽ����ݥ��饹������Ū�ʥ����å����ϥ��֥��饹���������롥 -�㤨�Х����ͥåȥɥᥤ��ξ���TCPsocket���Ѥ��롥 - -SuperClass: IO - -Methods: - - getopt(level, optname) - - �����åȤΥ��ץ�����������롥getsockopt(2)�ȤΤ��ȡ��� - ���������ץ��������Ƥ�ޤ�ʸ������֤��� - - getpeername - - ��³�������Υ����åȤξ�������롥�ѥå����줿sockaddr��¤�� - ��٥��˥���פ���ʸ�����֤���롥getpeername(2)�ȤΤ��ȡ� - - getsockname - - �����åȤξ�������롥�ѥå����줿sockaddr��¤�Τ�٥��˥���� - ����ʸ�����֤���롥getsockname(2)�ȤΤ��ȡ� - - setopt(level, optname, optval) - - �����åȤΥ��ץ��������ꤹ�롥setsockopt(2)�ȤΤ��ȡ� - - shutdown(how) - - �����åȤΰʹߤ���³��λ�����롥how��0�Ǥ�������ʹߤμ������� - how��1�Ǥ�����ϡ��ʹߤ����������ݤ���롥how��2�λ��ˤϡ����� - �ʹߤ������������Ȥ�˵��ݤ���롥shutdown(2)�ȡ� - -** TCPserver(���饹) - -TCP/IP���ȥ���³�Υ�����¦�Υ����åȤΥ��饹�����Υ��饹�ˤ�ä� -��ñ�˥����åȤ����Ѥ��������ФΥץ�����ߥ��Ǥ��롥�㤨��echo���� -�Фϰʲ��Τ褦�ˤʤ롥 - - gs = TCPserver.open(4444) - socks = [gs] - - while TRUE - nsock = select(socks); - if nsock == nil; continue end - for s in nsock[0] - if s == gs - socks.push(s.accept) - else - if s.eof - s.close - socks.delete(s) - else - str = s.gets - s.write(str) - end - end - end - end - -SuperClass: TCPsocket - -Methods: - - accept - - ���饤����Ȥ������³�������դ�����³����TCPsocket�Υ��� - �������֤��� - -Single Methods: - - new([host, ]service) - open([host, ]service) - - service��/etc/services(�ޤ���NIS)����Ͽ����Ƥ��륵���ӥ�̾�� - �ݡ����ֹ�ǻ��ꤹ�롥host����ꤷ�����ϻ��ꤷ���ۥ��Ȥ������ - ³����������դ��롥��ά�������ƤΥۥ��Ȥ������³�������� - ���롥 - -** TCPsocket - -�����ͥåȥɥᥤ��Υ��ȥ������åȤΥ��饹���̾��IO���饹�� -���֥��饹��Ʊ�ͤ������Ϥ��Ǥ��롥���Υ��饹�ˤ�äƥ����åȤ��Ѥ����� -�饤����Ȥ��ñ�˵��ҤǤ��롥�桼�������ϤΤޤޥ����Ф�ž������� -�������ϰʲ��Τ褦�ˤʤ롥 - - s = TCPsocket("localhost", 4444) - while gets() - s.write($_) - print(s.read) - end - -SuperClass: BasicSocket - -Methods: - - addr - - �����åȤ���³�����ɽ��������֤�����������γ����Ǥ���1���� - ��ʸ���� "AF_INET"����2���Ǥ�port�ֹ桤��3���Ǥ��ۥ��Ȥ�ɽ��ʸ - ����Ǥ��롥 - - peeraddr - - ��³����襽���åȤξ����ɽ��������֤�����������γ����Ǥ� - addr��åɤ��֤������Ʊ���Ǥ��롥 - -Single Methods: - - open(host, service) - new(host, service) - - host�ǻ��ꤷ���ۥ��Ȥ�service�ǻ��ꤷ���ݡ��Ȥ���³���������� - �Ȥ��֤���host�ϥۥ���̾���ޤ��ϥ����ͥåȥ��ɥ쥹��ʸ - ����service��/etc/services(�ޤ���NIS)����Ͽ����Ƥ��륵���� - ��̾���ݡ����ֹ�Ǥ��롥 - -** UNIXserver - -UNIX���ȥ���³�Υ�����¦�Υ����åȤΥ��饹�� - -SuperClass: UNIXsocket - -Methods: - - accept - - ���饤����Ȥ������³�������դ�����³����UNIXsocket�Υ��� - �������֤��� - -** UNIXsocket - -UNIX�ɥᥤ��Υ��ȥ������åȤΥ��饹���̾��IO���饹�Υ��֥��饹 -��Ʊ�ͤ������Ϥ��Ǥ��롥 - -SuperClass: BasicSocket - -Methods: - - addr - - �����åȤ���³�����ɽ��������֤�����������γ����Ǥ���1���� - ��ʸ���� "AF_UNIX"����2���Ǥ�path�Ǥ��롥 - - path - - UNIX�����åȤΥѥ����֤��� - - peeraddr - - ��³����襽���åȤξ����ɽ��������֤�����������γ����Ǥ� - addr��åɤ��֤������Ʊ���Ǥ��롥 - -Single Methods: - - open(path) - new(path) - - path�ǻ��ꤷ���ѥ�̾���Ѥ�����³���������åȤ��֤��� - -------------------------------------------------------- -Local variables: -fill-column: 70 -end: diff --git a/ext/tkutil/MANIFEST b/ext/tkutil/MANIFEST index 98df4663b3..870e04b586 100644 --- a/ext/tkutil/MANIFEST +++ b/ext/tkutil/MANIFEST @@ -1,3 +1,3 @@ MANIFEST -extconf.rb tkutil.c +depend diff --git a/ext/tkutil/depend b/ext/tkutil/depend new file mode 100644 index 0000000000..ead83eda57 --- /dev/null +++ b/ext/tkutil/depend @@ -0,0 +1 @@ +tkutil.o: tkutil.c ../../ruby.h ../../config.h ../../defines.h diff --git a/ext/tkutil/extconf.rb b/ext/tkutil/extconf.rb deleted file mode 100644 index b61a7ac01c..0000000000 --- a/ext/tkutil/extconf.rb +++ /dev/null @@ -1,11 +0,0 @@ -for dir in ENV['PATH'].split(':') - if File.exists? "#{dir}/wish" - $CFLAGS = $CFLAGS + " -DWISHPATH=" + "'\"#{dir}/wish\"'" - have_wish = TRUE - break - end -end - -if have_wish and have_func('pipe') - create_makefile("tkutil") -end diff --git a/ext/tkutil/tkutil.c b/ext/tkutil/tkutil.c index 2b74b254c2..51e3412ab5 100644 --- a/ext/tkutil/tkutil.c +++ b/ext/tkutil/tkutil.c @@ -47,7 +47,6 @@ Init_tkutil() VALUE mTK = rb_define_module("TkUtil"); VALUE cTK = rb_define_class("TkKernel", cObject); - rb_define_const(mTK, "WISH_PATH", str_new2(WISHPATH)); rb_define_singleton_method(mTK, "eval_cmd", tk_eval_cmd, -1); rb_define_singleton_method(cTK, "new", tk_s_new, -1); |