summaryrefslogtreecommitdiff
path: root/missing
diff options
context:
space:
mode:
authorYukihiro Matsumoto <matz@ruby-lang.org>1994-07-18 10:19:15 +0900
committerTakashi Kokubun <takashikkbn@gmail.com>2019-08-17 22:09:29 +0900
commit200e0ee2fd3c1c006c528874a88f684447215524 (patch)
treedf2252585f3000878a15123d98ccb08124306b90 /missing
version 0.49v0_49
https://cache.ruby-lang.org/pub/ruby/1.0/ruby-0.49.tar.gz Mon Jul 18 10:19:15 1994 Yukihiro Matsumoto (matz@ix-02) * parse.y: 多重代入を処理するルールにバグがあって, 3要素以上の多重 代入に失敗していた. * eval.c(rb_eval): 多重代入で, 右辺が配列でない時には`to_a'メソッ ドで配列に変換して代入するようにした. 今までの仕様だと右辺値が第 1要素にそのまま代入されていたが, structなど配列に変換できるもの は変換した方が嬉しい気がする. * dbm.c,dict.c(delete_if): メソッド追加. * process.c(wait,waitpid): システムコールwaitpidまたはwait4がある 時はそちらを使うように. configureもそれらをチェックするように変更. * dbm.c, dict.c(clear): メソッド追加. Fri Jul 15 10:54:45 1994 Yukihiro Matsumoto (matz@ix-02) * array.c(Fary_fill,Fary_clear): メソッドを追加. * string.c(Fstr_split): $;の値が長さ1の文字列である時, これを正規 表現化しないで, 単なる文字として分割する. * string.c(Fstr_aset/Fstr_aref): インデックスが文字列の範囲外だっ た時の動作をArrayを参考に修正した. * array.c(astore,Fary_aset): 領域をreallocした後, ゼロでクリアする ように. 今まで配列にゴミが入っていた. * array.c: []/[]=でのインデックス関係を整理. 基本的に負のインデッ クスに代入しない限り例外は起きないように変更した. 必要に応じて適 当に解釈して, 必要ならば領域を拡張するように. Thu Jul 14 11:18:07 1994 Yukihiro Matsumoto (matz@ix-02) * autoexec.c: 削除. autoload関係の機能は今後検討しよう. * dict.c: 辞書クラスの正式名称をDictに変更した. 別名としてHashを用 意した. 今までDictionaryなどと長い名前にしていたが誰も使っていな かったしね. *BACKWARD INCOMPATIBILITY* * parse.y: Dictを生成する構文を追加. こちらを{..}にした. * parse.y: 配列を生成する構文を[..]に変更した. 過去のRubyスクリプ トとの互換性が保てないが, Dictを生成する構文を導入するに当たり, perl5に合わせて(意識して), 変更する時期は今しかないと考えた. *BACKWARD INCOMPATIBILITY* * eval.c(Feval): eval()でメソッドを定義する時, 定義されるクラスを メソッドの所属するクラスにした. 今まではObjectクラスに定義されて いた. * parse.y: ローカル引数がない時のeval()で落ちていた. Thu Jul 14 11:18:07 1994 Yukihiro Matsumoto (matz@ix-02) * eval.c: メソッドが存在しない時にはKernel:_undefined(id)が呼ばれ るように. しかし, rubyでは個々のメソッド毎の処理よりも, クラス 単位の処理が必要な気もするなあ. * autoexec.c: 削除. autoload関係の機能は今後検討しよう. * dict.c: 辞書クラスの正式名称をDictに変更した. 別名としてHashを用 意した. 今までDictionaryなどと長い名前にしていたが誰も使っていな かったしね. *BACKWARD INCOMPATIBILITY* * parse.y: Dictを生成する構文を追加. こちらを{..}にした. * parse.y: 配列を生成する構文を[..]に変更した. 過去のRubyスクリプ トとの互換性が保てないが, Dictを生成する構文を導入するに当たり, perl5に合わせて(意識して), 変更する時期は今しかないと考えた. *BACKWARD INCOMPATIBILITY* * eval.c(Feval): eval()でメソッドを定義する時, 定義されるクラスを メソッドの所属するクラスにした. 今まではObjectクラスに定義されて いた. * parse.y: ローカル引数がない時のeval()で落ちていた. Tue Jul 12 09:41:28 1994 Yukihiro Matsumoto (matz@ix-02) * pack.c: uuencode形式のサポート. * `-0'を`-R'に. 出力レコードセパレータをコマンドラインから指定する 方法はなくなった. どうも, 仕様がゆれるなあ. Mon Jul 11 09:51:24 1994 Yukihiro Matsumoto (matz@ix-02) * ruby.c: `-r'オプションは`-0'オプションになった. 当面は`-r'も有効 だが変更される可能性がある. `-R'は当面はそのまま. * version.c: version表示に日付を含めた. * parse.y: private methodの復活. RubyのprivateメソッドはC++におけ るprotected methodに該当するもので, `@'で始まる名前を持つ. * env.h: struct ENVIRONの定義を分離. * parse.y: `\$var', `\@var', `%var'も許すように. * variable.c(Fdefined): idも引数として受け付けるように. * parse.y: if文/unless文にキーワードthenを追加. thenなしというのは, 意外と間違いが多いので. もちろん省略できる. Sat Jul 9 02:16:04 1994 Yukihiro Matsumoto (matz@dyna) * eval.c(rb_eval): class/moduleの評価で新しいスコープを割り当てて いなかった. スコープ割り当て部分をrb_call()からrb_eval()に移した. * eval.c(rb_call): realloc()に渡される事のある, ローカル変数用の領 域をalloca()していた. たまに落ちるわけだ. * string.c(Fstr_times): 割り当てた領域を越えた部分を変更していた. Wed Jul 6 15:52:42 1994 Yukihiro Matsumoto (matz@ix-02) * socket.c: Socket -> BasicSocket, RawSocket -> Socket に改名. * string.c(ucfirst,lcfirst): 最初の1文字だけの大文字/小文字変換. * numeric.c(chr): 整数の文字列化メソッド. * inits.c, dbm.c: DBMが使えない時はクラスそのものを定義しないよう にした. 利用できないクラスはnilとすることを今後のポリシーとしよ う(いままではアクセスした時点でエラーが発生していた). autoexec() のあり方も検討が必要になりそうだ. * bignum.c(bigadd): バグ修正. Thu Jul 7 11:12:18 1994 Yukihiro Matsumoto (matz@ix-02) * eval.c(Fload,Feval): eval_treeをクリアし忘れていた. * _inspect: オブジェクトを可読形式の文字列に変換する(主にデバッグ 出力用). Wed Jul 6 00:57:18 1994 Yukihiro Matsumoto (matz@dyna) * numeric.c, bignum.c: 整数に対する`[]'演算子. nビット目がセットさ れているかどうかを返す. Tue Jul 5 12:48:39 1994 Yukihiro Matsumoto (matz@ix-02) * io.c(Feof): 追加. コマンドラインからなる仮想ファイルについても EOFが検出できるように. * ruby.c: -l/-r/-R/-Xオプションの追加. * ruby.c: -n/-pオプションのloopの付加などをメインルーチンに移動し た. これで, オプションの解析途中で(`-c'オプションのせいで)終了な どといったことはない. * io.c(Fgets): 高速化. 凝ったことをしない方が速かった. 虚しい. Mon Jul 4 15:55:48 1994 Yukihiro Matsumoto (matz@ix-02) * Socket:getsockname/getpeername - ようやく仕様が安定した. * io.c(Fgets): eachでgetsを記述するのではなく, getsでeachを記述す るようにした. Fri Jul 1 10:35:49 1994 Yukihiro Matsumoto (matz@ix-02) * $ENV[env] = nil/$ENV.delete(env)で環境変数を削除できるようになっ た. $ENV.deleteは環境変数の以前の値を返す. * !~の定義が間違っていた. * Dict,DBM:[]= - nilの代入によって要素を削除できるようになった. こ れにともないnilはDictの要素になれなくなった. * ソースの整理. 盲腸のような使われていないコードをなくしたり, 変数 名を付け変えたりした. Fri Jul 1 00:21:29 1994 Yukihiro Matsumoto (matz@dyna) * Array:join() - 要素数0の配列に対して空文字列を返す. * RawSocket:open(),socketpair() - 文字列で指定できるドメインとタイ プをいくつか追加した. Thu Jun 30 13:51:29 1994 Yukihiro Matsumoto (matz@ix-02) * -fオプションをなくした. 昔(loadのなかった頃)の名残なので, 今となっ ては必要ないだろう. * -sオプションを追加. perlの-sオプションと同じ動きをする. * RawSocketクラスを提供する. Socketに対するシステムコールレベルの アクセスが可能になった. Thu Jun 30 00:27:19 1994 Yukihiro Matsumoto (matz@dyna) * Socket - bug fixes. * linuxではsyscall(SYS_select)が正常に動作しない. * Socket:addr,peeraddr - 配列としてsockaddrの情報を返す. Wed Jun 29 00:14:20 1994 Yukihiro Matsumoto (matz@dyna) * Socket:setopt,getopt - setsockopt(2), getsockopt(2)へのアクセス を実現. * sprintf() - rubyにはunsignedは無いので, %uを取り除いた. * sprintf() - %b, %x, %oでは2の補数表現, %B, %X, %Oでは符号付き表 現で出力するように. ここ数日でsprintf()の仕様がゆらいでいたが, これで落ち着きそうだ. Tue Jun 28 14:42:03 1994 Yukihiro Matsumoto (matz@ix-02) * Bignum:<<,>> - 2の補数をとる処理を除いた. シフト演算には関係ない 処理だった. * Bignum:^ - bug fix. 符合が反対だった. * sprintf() - 2進出力子"%b"を追加. * sprintf() - %x, %oでFixnumを出力する時, 2の補数表示を行なわない. * sprintf() - %x, %oはやはり負の数の時は`-'を出力するように. Mon Jun 27 14:56:13 1994 Yukihiro Matsumoto (matz@ix-02) * sprintf() - Bignumについても%d, %oは(2の補数表現に変換して)正の 整数を表示するようにした. * Bignumに対する論理演算の定義を修正した. 負の数は2の補数表現であ るとみなし, かつ仮想的に左側に無限に1が連続しているような演算結 果を得る. * Fixnum:<<,>> - 符合付シフトに変更. * Bignum:>> - 負の整数のシフトに対応した. * __END__, ^D, ^Zでスクリプトを終了できる. * -xオプションを追加. #! ..rubyなる行まで読み飛ばす. * -cオプションを追加. コンパイルのみを行う. Sat Jun 25 01:37:21 1994 Yukihiro Matsumoto (matz@dyna) * Fixnum:<< - 必要に応じてBignumに拡張して左シフトするように. よっ て, シフト幅が32を越えるとCやPerlとは違った値を返す. Fri Jun 24 10:01:28 1994 Yukihiro Matsumoto (matz@ix-02) * ioctl()/fcntl() - システムコールを呼び出す前にバッファの大きさを 調節するようにした. * String:toupper/tolower - 文字列を置き換えたコピーを作るのではな く, 元の文字列の内容を変更するようにした. * inplace editを実現した. perlと同じように`-i'オプションで指定する. もっとも, こちらはMS-DOSのこととか考えてないけど. * デフォルトの出力先を追加した. 今までは$stdoutに代入するしか方法 はなかった. Fri Jun 17 10:55:08 1994 Yukihiro Matsumoto (matz@ix-02) * 環境変数にアクセスする方法としてgetenv()/setenv()以外に$ENVを用 意した. $ENVは文字列-文字列の辞書であるかのように動作するEnvDict オブジェクトが代入されている(eachはassocを与える). * nilに代入するとcore dumpした. コンパイル時のチェックを強化. * Struct: struct_new()の引数をGCプロテクトする必要がある. せめてス タック領域だけでもスキャンできるようにしなければいけないんだろう か? でも, 移植性がなあ. Fri Jun 17 01:01:46 1994 Yukihiro Matsumoto (matz@dyna) * Time::asctime() - 日付のフォーマットで日が落ちていた. * Stat: StatはEtcなどと同様にStructで実現したので, Statクラスは無 くなった. Thu Jun 16 10:32:23 1994 Yukihiro Matsumoto (matz@ix-02) * bignum.c: いくつかのバグを修正した. Fixnumを渡すべきところで普通 のintを渡していた. 失敗. * big2str() - 1桁ずつbaseで割る代わりに, 4桁ずつ割算を行なうように した. これで多倍長割算の回数が1/4になる. さらに整数->数(文字)へ の変換をテーブルを用いるようにした. * rb_ivar_get_1() - すでに何らかのインスタンス変数を持つオブジェク トでは, 未定義のインスタンス変数の値が不定値になっていた. * yylex() - インスタンス変数の認識に失敗していた. attr()は正しく動 作していたので, 混用すると動作しなかった. 全部違っていたから動い ていたのね. * Object:attr() - すでにアクセスメソッドが定義されている時にはデフォ ルトのアクセスメソッドを定義しないようにした. もっともアクセスメ ソッドと同名のメソッドの区別はRubyには存在しないけど, それは仕方 がないよね. * pack.c: エンディアンをautoconfで判定するようにしたので, v/Vが使 えるようになった. またntoh?()/hton?()も自前で用意した. * Stat: st_rdevをアクセスするメソッドを追加. さらにシステムがstat 構造体にst_blksize, st_blockを持っているかをautoconfでチェックす るようにした. * ドキュメントを少し整備した. * INT2FIX()のうち, 31bit幅が保証できないものは, int2inum()に置き換 えた. Wed Jun 15 10:18:27 1994 Yukihiro Matsumoto (matz@ix-02) * sprintf() - bignumの出力の時, 出力幅を正しく計算するようにした. * str2inum() - baseが0の時, baseを自動判定するように(0xで始まる時 16 進, 0で始まる時8進). Tue Jun 14 16:08:42 1994 Yukihiro Matsumoto (matz@ix-02) * gc.c: Bignumを追加するのを忘れていた. 組み込み型を追加した時には 必ずmark()とsweep()にその型に関する処理を追加する必要がある. * bignum: 割算も動いたような気がする. アルゴリズムを理解していない ので, 自信がない. Mon Jun 13 14:36:55 1994 Yukihiro Matsumoto (matz@ix-02) * まだサポートしていないメソッドなどがあるが, 曲がりなりにもBignum が使えるようになる. これでioctlも使える. Fri Jun 10 17:26:42 1994 Yukihiro Matsumoto (matz@ix-02) * Comparable: 基礎となるメソッドを`=='と`>'から`<=>'に変更した. 今 後Comparableのサブクラスは`<=>'だけを定義する必要がある. Wed Jun 8 13:12:18 1994 Yukihiro Matsumoto (matz@ix-02) * Need_Fixnum()をほとんどなくして, NUM2INT()で直接intに変換するこ とにした. これで31bitに丸めて桁落ちをおこす問題がなくなる. Tue Jun 7 09:45:31 1994 Yukihiro Matsumoto (matz@ix-02) * ruby.h: マクロFIXABLE(n)を追加. ついでにFIXNUM周りの定義を変更し て, 移植性を高めた(つもり). * C++の予約語であるnewを削除した. しかし, もうひとつの予約語である classに関しては, 置き換える単語が思いつかないこともあってそのま まになっている. * 31bitを越えそうなINT2FIX()を関数呼び出しに変えた. 将来bignumが導 入された時には自動的にbignumを返すようにする. * readline() - 引数の`-'は標準入力を意味するようになった. * ruby.h: 右シフトが論理シフトか算術シフトかは処理系依存のようなの で, ruby.hでcppを使ってチェックするようにした. これでうまくいく と思うのだが, 手元に符合付intを論理シフトする処理系がないので確 認できない. NEWS-OSのCCは確か右シフトはいつも論理シフトだったよ うな気がするんだけど…. Mon Jun 6 10:10:22 1994 Yukihiro Matsumoto (matz@ix-02) * FIX2INT()の定義を変更した. どうして昔はうまく動かなかったんだろ うか? もしかして, 右シフトの符号拡張は処理系依存? * FIX2INT()とFIX2UINT()を使い分けるようにした. もっともfixnumは31 ビットしかないので, 本質的な解決にはならないのだが(ioctlが組み込 みたかった). * printを関数的メソッドから通常メソッドに変更. 引数が与えられない 時にはレシーバをプリントするようにした. これでprintをメッセージ 形式でも実行できるようになった. 例: ruby -e 'readlines().sort.print' 上のスクリプトは, 引数として与えられた(あるいは標準入力から読み 込まれた)文字列を各行毎にソートして表示する. * eval.c: argc,argvパターンで引数を受けるメソッドに引数が一つも与 えられない時, argvがnilになっていた(argv[0]にアクセスすると落ち てしまう). * _exit()を追加. こちらは例外処理など行なわない. * dbmクラス: クラス名称をDBM(大文字)に統一した. Sat Jun 4 00:51:04 1994 Yukihiro Matsumoto (matz@dyna) * ループ変数にも属性や配列要素を指定できるようにした. Fri Jun 3 09:49:48 1994 Yukihiro Matsumoto (matz@ix-02) * 多重代入において, 属性代入, 配列要素への代入も行なえるようにした. * Need_Fixnum(): nilを0に変換するように. * Enumerable:min, max, index, includes - 追加. min, maxは要素が `<=>'メソッドを持つことを仮定している. * Dict/Dbm:length - 要素数を返すメソッド. * Dbmクラスにto_aメソッドを追加. * Sunにおけるsortの誤動作の件, 昨日の修正でfixされた. しかし, それ でなぜ動かなかったのかは明らかではないが…. 比較関数がどんな値を 返しても指定した領域外をアクセスするのはバグではないか. * ファイルの全内容を読んで, 各行を配列として返すメソッドはpythonを 参考にして`readlines'という名前にした. それにともないgetsに対し てreadlineという別名を用意した. Fri Jun 3 00:08:38 1994 Yukihiro Matsumoto (matz@dyna) * Array:sort - 判別関数の戻り値はFixnumではなく, Intであるべきだっ た. 間違い. Sunで動作がおかしかったのはこのせいかも知れない. Thu Jun 2 11:48:37 1994 Yukihiro Matsumoto (matz@ix-02) * IO:read_all() - ストリームの最後まで入力して, 各行を要素とする配 列を返すメソッドを追加. また関数メソッド read_all()も追加した. これは引数のファイルから読み込んで各行を要素とする配列を返す. 意 味的には def read_all() ary = {} while gets() ary.push($_) end end とほぼ等価である. * String:atoiメソッドを削除. to_aメソッドからaが配列であるとの連想 を呼んで, 混乱を招かないため. 代わりにto_iメソッドを使うこと. * 配列への変換メソッドto_aを導入した. 通常のオブジェクトは自分自身 を唯一の要素とする長さ1の配列を返す. 配列は自分自身を, 辞書はキー と値のペアの配列を返す. Enumeratedをincludeしたクラスは, eachが 返す各要素を含む配列を返す. * file.c: 不定個の引数を受けとるメソッド(chmod,chown,utimes)を書き 換えて, 整理した. それに伴い, 最初に全ての引数の型チェックを行な うようにした. 型チェックに失敗すると処理を行なわずに例外を発生さ せる. * configure.in: 不必要なテストを行なわないように修正した. Tue May 31 10:41:08 1994 Yukihiro Matsumoto (matz@ix-02) * String:pack(): 2進数の文字列変換(B,b)で0と1が逆だった. * Math.c: 実数系のメソッドに引数として整数が渡された時に自動的に変 換するようにした. * toupper(), tolower(): 文字列の判定ミスで変換されていなかった. * getopt_long()の仕様によって, スクリプトへの引数がインタプリタの 引数だと解釈されていた. 引数パターン文字列の先頭に`+'を追加. * config.hを削除した. DEFINEはMakefileで与えられる. * sprintf(): "%d"に文字列が与えられた時にはアドレスではなく内容を 整数に変換するようにした. ついでに浮動小数点数も変換するように変 更した. * regexp.c: rubyの拡張正規表現(\d, \D, \s, \S)の処理で割り当てた領 域を越えてバッファに書き込んでいた. 処理前にバッファをきちんと拡 張するようにした. これで昨日問題にしていたメモリの問題は解決でき たと思う. * yylex(): ダブルクォート文字列中でダブルクォートを表現するため のバックスラッシュ表現ができなかった. Mon May 30 10:07:42 1994 Yukihiro Matsumoto (matz@ix-02) * 演算子`!'の右辺も条件式であるとした. これによって, この演算子を 再定義する人は混乱するかも知れないが, 大多数のこの演算子を使う人 は混乱を避けることができると思う. * autoconfを使って, 自動的にMakefile, config.hを生成するようにした. これで, 大抵のマシンでは`configure'を実行した後, `make'一発でコ ンパイルできると思う. * clone: サブクラスに対して用いられた場合, 元のオブジェクトと同じ クラスのインスタンスを返すように(以前はビルトインクラスの場合を 考えてなかった). * ビルトインクラスのサブクラスも作れるように, リテラルのあるクラス にもnewメソッドを追加した. * malloc()で落ちる. purifyが必要かも知れない. * re.c: rb_global_variable()の呼びだし形式の間違い. 変数へのポイン タを渡さなければいけない. * parse.y: ローカル変数の扱いに引数の評価順に依存する移植性のない 部分があった. * attr(): 属性設定のバグを直した. いつ内部仕様が変わったんだろう…? Sat May 28 23:08:18 1994 Yukihiro Matsumoto (matz@dyna) * 正規表現キャッシュの文字列一致判定をポインタ一致から内容一致に変 更した. そういえば文字列リテラルは一回毎に新しくオブジェクトが生 成されるのだった. Fri May 27 11:42:00 1994 Yukihiro Matsumoto (matz@ix-02) * 正規表現の文字コードのデフォルトを漢字非対応にした. これによって 若干の高速化が図れる. * trから文字削除(delete), 文字圧縮(squeeze)を分離した. それにとも ないtrのオプション引数はなくなった. Thu May 26 10:32:55 1994 Yukihiro Matsumoto (matz@ix-02) * スクリプト読み込みルーチンを書き直して, 通常ファイル以外のファイ ル名や空文字列がスクリプトとして与えられた場合に対応した. また, 標準入力からスクリプトを読み込む時に, 一時ファイルが/tmpに残らな いようにした. * Fixnum:id2name - IDから文字列に戻す関数. String:internの逆. * Array: 配列の範囲外の要素をアクセスした時に例外を発生させずに, nilを返すようにした. 配列は自動的に拡張される. * string:stripを追加. * -nオプションが-eオプションを複数指定した時も動作するように. * parse.yで<sys/types.h>もインクルードするようにした. * fname周りの細かいbugを修正. Wed May 26 11:45:10 1994 Yukihiro Matsumoto (matz@dyna) * 定数をキャッシュするようにした. 繰り返しが多い場合には有効のはず だが, 一度しかアクセスしない場合は遅くなるなあ. Wed May 25 00:42:24 1994 Yukihiro Matsumoto (matz@dyna) * 多重代入文(foo, bar = 1, 2)の採用. * 条件式部に文字列あるいは正規表現リテラルをおくと`=~'演算子によっ て`$_'と比較される. 更に`...'の両辺では整数リテラルが`$.'と比較 される. Mon May 23 23:27:03 1994 Yukihiro Matsumoto (matz@dyna) * &式 形式はなくなった. 代わりにkernel:apply(id, args..)を導入. * def op () ..形式の導入. opは再定義可能な演算子. * constantの代入時チェック. 既に初期化されている定数に代入した場合 は例外が発生する. * 多重代入文. Thu May 19 22:57:07 1994 Yukihiro Matsumoto (matz@dyna) * 複合文でもvoid valueのチェックを行うようにした. * untilの動作の修正(do..until型だった). Wed May 18 01:06:25 1994 Yukihiro Matsumoto (matz@dyna) * 移植に関する若干の問題を修正. * 別名の構文を「def a b」にした. * until/unless: 演算子から制御文へ. 例外を捕捉する機能はそのまま. * 選択可能な機能をconfig.hからdefines.hに移動. Fri May 13 23:20:21 1994 Yukihiro Matsumoto (matz@dyna) * -yオプションを新設. -dオプションからコンパイラのデバッグ部分を分 離した. Tue Apr 25 20:17:33 1994 Yukihiro Matsumoto (matz@dyna) * マルチバイト文字列を識別子に使えるように. 個人的には使いたくは無 いけどなあ. * `-v'フラグの状態を$verboseでアクセスできるように. * CVSの導入に伴い, バージョン管理の方法を変更. * 真面目にChangeLogをつける事にした. Tue Mar 8 10:09:25 1994 Yukihiro Matsumoto (matz at nws119) * %変数名 によるクラス定数を導入. * undef メソッド によるメソッド定義の取り消しを導入. * rb_get_method_bodyではthe_envを変更せず, rb_call()で明示的に変更 するように. これでresponds_toなどで環境が破壊されない. Mon Mar 7 17:46:15 1994 Yukihiro Matsumoto (matz at nws119) * 「&文字列」形式. 「式.文字列」型のメッセージセンドはなくなった. * 自己代入形式(+=. -=, ...) * obj.attr = expr形式の採用. Thu Feb 24 16:23:28 1994 Yukihiro Matsumoto (matz at nws119) * toint, tofloat, print_stringをそれぞれto_i, to_f, to_sに変更. * String:clone - Copy on Writeの実現. Tue Feb 22 11:11:44 1994 Yukihiro Matsumoto (matz at nws119) * re.c: マッチした文字列の保存に失敗していた. * trap: 可能ならば処理に時間のかかるシステムコール(read, wait, sigpause, select)をフックして割り込み処理の即答性を高める(DOSな どでは無理だなあ). * trap: 割り込みをその場で処理するか(迅速だが危険), 安全なタイミン グで処理するかを選択できるように. Tue Feb 17 11:11:12 1994 Yukihiro Matsumoto (matz at nws119) * trap: 割り込みハンドラ. Wed Feb 16 12:29:12 1994 Yukihiro Matsumoto (matz at nws119) * String:crypt: 暗号化ルーチン * "::"演算子の追加. a::b は {a, b}と同義. a::b::c は {a, {b, c}}と 同義(右結合). 同義とはいうものの, "::"演算子を使った方が少しだけ メモリ効率が良い. * Dir.rmdir(), File.unlink(), File.utime() -- 各システムコールへの インタフェース. * kill -- kill(2) I/F * select(): readのチェックではstdioにバッファリングされているかど うかをチェックするように. Tue Feb 15 15:08:31 1994 Yukihiro Matsumoto (matz at nws119) * file.c: statをキャッシュするように. * File:utime()を追加. * unliteralize(): フラグを破壊していた. * Bug(): coreを吐くように. * String:tr -- tr(1)互換. 引数パターンがちょっと違うけど…. Mon Feb 14 18:24:13 1994 Yukihiro Matsumoto (matz at nws119) * unless, untilが例外も偽と見なすように. * select() -- select(2) I/F * Array:pack, String:unpack: perlのpack/unpackの同等品 Tue Feb 8 17:11:10 1994 Yukihiro Matsumoto (matz at nws119) * setenv()のないシステムのためにputenv()を使ったコードも用意した. Mon Feb 7 09:52:44 1994 Yukihiro Matsumoto (matz at nws119) * 引数の一番最後に`*'を置けるようにした. これでrest引数のリストを 操作する必要が少なくなる. Fri Feb 4 18:23:26 1994 Yukihiro Matsumoto (matz at nws119) * ruby-mode.elを書き直す. ずいぶんましになったと思う. * 文字列リテラルのCopy on Writeを実現. これで文字列がリテラルであ るからといっていちいちcloneしなくても済む. Tue Feb 1 09:21:09 1994 Yukihiro Matsumoto (matz at nws119) * sub(), gsub()で, マッチした文字列を$&, $1..$9でアクセスできるよ うにした. 同時にマッチした部分文字列をコピーしておくように(元の 文字列が変更されても状態を保存するため). Mon Jan 31 15:16:58 1994 Yukihiro Matsumoto (matz at nws119) * プライベートメソッドの仕様を変更. 今までは同じクラスのメソッドか らしかアクセスできなかったが, サブクラスのメソッドからもアクセス できるようにした(C++におけるprotected メンバ関数). * メソッドサーチのアルゴリズムを改善し, 10%程度の高速化を行なった. * 高速化. Cで記述されたメソッドを呼び出す時にはsetjmpを呼ばないよ うにした. これでCメソッドを多用する場合には3倍程度高速になった. Fri Jan 28 15:44:04 1994 Yukihiro Matsumoto (matz at nws119) * sh-modeを元にruby-mode.elを作る. 演算子で終る, 2行に渡る文には対 応していないけど…. Thu Jan 27 11:35:19 1994 Yukihiro Matsumoto (matz at nws119) * freenode(): NODE_NILの解放忘れ. * 字句解析部のバグ修正(コメントの後の状態を戻し忘れ). * protect .. endのバグ修正. GC_LINKのネストが不正だった. * joinのバグ修正(使っているオブジェクトをfreeしていた). * splitのバグ修正(アルゴリズムがおかしかった). * fork()を追加. Wed Jan 26 17:09:56 1994 Yukihiro Matsumoto (matz at nws119) * ファイルテストメソッドの追加. * rb_autoexec(): クラスを初めてアクセスした時の挙動を制御できるよ うにした. これでautoloadも実現できる. これにともないメソッド unknownはなくなった. Tue Jan 25 15:51:36 1994 Yukihiro Matsumoto (matz at nws119) * Dbmクラス, Mathモジュールを作成. * -Iオプションでサーチパスに追加できるように. * サーチパスを変数$load_pathに設定できるように. * load(): ダイナミックロードを使えるようにした. Tue Jan 18 14:14:01 1994 Yukihiro Matsumoto (matz at nws119) * Comparable:"<=>" * Float,Fixnum:"**" * Array:sort Fri Jan 14 16:53:37 1994 Yukihiro Matsumoto (matz at nws119) * version 0.07 * メソッドに関するドキュメントを充実させた. * String:index(): 引数positionを増やした. Thu Jan 13 15:13:52 1994 Yukihiro Matsumoto (matz at nws119) * 未初期化の変数アクセスをなくした. * 無駄なhash tableのアロケーションを削除. * Purify'd(on Sun) * ~RE と ~STRのコンパイル時展開の抑制. * Sunへ移植. signal()の戻り値. RDataのbug修正. * parse.y: nlsルールを削除. * yylex(): 改行と符合の解析部分を変更. * missing/strftime.c: 移植用. * Time:strftime: その他のメソッドもstrftimeを利用するように. * メソッド再定義時にメソッドキャッシュをクリアする. Fri Jan 7 15:23:20 1994 Yukihiro Matsumoto (matz at nws119) * Float:coerce(): FixnumとFloat以外の引数を与えられるた時には例外 を発生するように. * Stat: stat構造体の全てのメンバに対するアクセスメソッドを用意. * 未定義のクラス/モジュールへの参照がunknownメソッドを呼び出すよう にした. * baseline - version 0.06.
Diffstat (limited to 'missing')
-rw-r--r--missing/CVS/Entries9
-rw-r--r--missing/CVS/Repository1
-rw-r--r--missing/getopt.c662
-rw-r--r--missing/getopt.h128
-rw-r--r--missing/getopt1.c162
-rw-r--r--missing/memmove.c24
-rw-r--r--missing/mkdir.c103
-rw-r--r--missing/strerror.c19
-rw-r--r--missing/strftime.c781
-rw-r--r--missing/strstr.c73
-rw-r--r--missing/strtol.c84
-rw-r--r--missing/strtoul.c184
12 files changed, 2230 insertions, 0 deletions
diff --git a/missing/CVS/Entries b/missing/CVS/Entries
new file mode 100644
index 0000000000..2c02d6e353
--- /dev/null
+++ b/missing/CVS/Entries
@@ -0,0 +1,9 @@
+/getopt.c/0.26/Wed Jun 1 23:41:18 1994 Mon Apr 18 12:30:25 1994//
+/getopt.h/0.26/Wed Jun 1 23:41:18 1994 Mon Apr 18 12:30:25 1994//
+/getopt1.c/0.26/Wed Jun 1 23:41:18 1994 Mon Apr 18 12:30:25 1994//
+/memmove.c/0.26/Wed Jun 1 23:41:18 1994 Mon Apr 18 12:30:25 1994//
+/mkdir.c/1.1/Wed Jun 1 23:41:18 1994 Wed Jun 1 23:38:35 1994//
+/strerror.c/0.26/Wed Jun 1 23:41:18 1994 Mon Apr 18 12:30:25 1994//
+/strftime.c/0.26/Wed Jun 1 23:41:19 1994 Mon Apr 18 12:30:25 1994//
+/strtol.c/0.26/Wed Jun 1 23:41:19 1994 Mon Apr 18 12:30:25 1994//
+/strtoul.c/0.26/Wed Jun 1 23:41:19 1994 Mon Apr 18 12:30:25 1994//
diff --git a/missing/CVS/Repository b/missing/CVS/Repository
new file mode 100644
index 0000000000..a7ac69cf13
--- /dev/null
+++ b/missing/CVS/Repository
@@ -0,0 +1 @@
+/work/cvsroot/ruby/missing
diff --git a/missing/getopt.c b/missing/getopt.c
new file mode 100644
index 0000000000..bbf345c33c
--- /dev/null
+++ b/missing/getopt.c
@@ -0,0 +1,662 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+ before changing it!
+
+ Copyright (C) 1987, 88, 89, 90, 91, 1992 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef GAWK
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#include <string.h>
+#endif /* GNU C library. */
+
+
+#ifndef __STDC__
+#define const
+#endif
+
+/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
+ long-named option. Because this is not POSIX.2 compliant, it is
+ being phased out. */
+#define GETOPT_COMPAT
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg = 0;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+int optind = 0;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return EOF with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+#ifdef __GNU_LIBRARY__
+#include <string.h>
+#define my_index strchr
+#define my_bcopy(src, dst, n) memcpy ((dst), (src), (n))
+#else
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+char *getenv ();
+
+static char *
+my_index (string, chr)
+ char *string;
+ int chr;
+{
+ while (*string)
+ {
+ if (*string == chr)
+ return string;
+ string++;
+ }
+ return 0;
+}
+
+static void
+my_bcopy (from, to, size)
+ char *from, *to;
+ int size;
+{
+ int i;
+ for (i = 0; i < size; i++)
+ to[i] = from[i];
+}
+#endif /* GNU C library. */
+
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+static void
+exchange (argv)
+ char **argv;
+{
+ int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *);
+ char **temp = (char **) malloc (nonopts_size);
+
+ /* Interchange the two blocks of data in ARGV. */
+
+ my_bcopy (&argv[first_nonopt], temp, nonopts_size);
+ my_bcopy (&argv[last_nonopt], &argv[first_nonopt],
+ (optind - last_nonopt) * sizeof (char *));
+ my_bcopy (temp, &argv[first_nonopt + optind - last_nonopt], nonopts_size);
+
+ free(temp);
+
+ /* Update records for the slots the non-options now occupy. */
+
+ first_nonopt += (optind - last_nonopt);
+ last_nonopt = optind;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns `EOF'.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+ const struct option *longopts;
+ int *longind;
+ int long_only;
+{
+ int option_index;
+
+ optarg = 0;
+
+ /* Initialize the internal data when the first call is made.
+ Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ if (optind == 0)
+ {
+ first_nonopt = last_nonopt = optind = 1;
+
+ nextchar = NULL;
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (getenv ("POSIXLY_CORRECT") != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+ }
+
+ if (nextchar == NULL || *nextchar == '\0')
+ {
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Now skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc
+ && (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#ifdef GETOPT_COMPAT
+ && (longopts == NULL
+ || argv[optind][0] != '+' || argv[optind][1] == '\0')
+#endif /* GETOPT_COMPAT */
+ )
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* Special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return EOF;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
+#ifdef GETOPT_COMPAT
+ && (longopts == NULL
+ || argv[optind][0] != '+' || argv[optind][1] == '\0')
+#endif /* GETOPT_COMPAT */
+ )
+ {
+ if (ordering == REQUIRE_ORDER)
+ return EOF;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Start decoding its characters. */
+
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
+ }
+
+ if (longopts != NULL
+ && ((argv[optind][0] == '-'
+ && (argv[optind][1] == '-' || long_only))
+#ifdef GETOPT_COMPAT
+ || argv[optind][0] == '+'
+#endif /* GETOPT_COMPAT */
+ ))
+ {
+ const struct option *p;
+ char *s = nextchar;
+ int exact = 0;
+ int ambig = 0;
+ const struct option *pfound = NULL;
+ int indfound = 0;
+ extern int strncmp();
+
+ while (*s && *s != '=')
+ s++;
+
+ /* Test all options for either exact match or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name;
+ p++, option_index++)
+ if (!strncmp (p->name, nextchar, s - nextchar))
+ {
+ if (s - nextchar == strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' is ambiguous\n",
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ if (*s)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = s + 1;
+ else
+ {
+ if (opterr)
+ {
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ "%s: option `--%s' doesn't allow an argument\n",
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ "%s: option `%c%s' doesn't allow an argument\n",
+ argv[0], argv[optind - 1][0], pfound->name);
+ }
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' requires an argument\n",
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+#ifdef GETOPT_COMPAT
+ || argv[optind][0] == '+'
+#endif /* GETOPT_COMPAT */
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (opterr)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, "%s: unrecognized option `--%s'\n",
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (opterr)
+ {
+ if (c < 040 || c >= 0177)
+ fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
+ argv[0], c);
+ else
+ fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
+ }
+ return '?';
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = 0;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `-%c' requires an argument\n",
+ argv[0], c);
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+getopt (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == EOF)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/missing/getopt.h b/missing/getopt.h
new file mode 100644
index 0000000000..de027434f7
--- /dev/null
+++ b/missing/getopt.h
@@ -0,0 +1,128 @@
+/* Declarations for getopt.
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+#if __STDC__
+ const char *name;
+#else
+ char *name;
+#endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+enum _argtype
+{
+ no_argument,
+ required_argument,
+ optional_argument
+};
+
+#if __STDC__
+#if defined(__GNU_LIBRARY__)
+/* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in stdlib.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+#endif /* not __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+ const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind);
+
+/* Internal only. Users should not call this directly. */
+extern int _getopt_internal (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind,
+ int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* not __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
diff --git a/missing/getopt1.c b/missing/getopt1.c
new file mode 100644
index 0000000000..eb06338ab3
--- /dev/null
+++ b/missing/getopt1.c
@@ -0,0 +1,162 @@
+/* Getopt for GNU.
+ Copyright (C) 1987, 88, 89, 90, 91, 1992 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifdef LIBC
+/* For when compiled as part of the GNU C library. */
+#include <ansidecl.h>
+#endif
+
+#ifndef RUBY
+#include "getopt.h"
+#endif
+
+#ifndef __STDC__
+#define const
+#endif
+
+#if defined(STDC_HEADERS) || defined(__GNU_LIBRARY__) || defined (LIBC)
+#include <stdlib.h>
+#else /* STDC_HEADERS or __GNU_LIBRARY__ */
+char *getenv ();
+#endif /* STDC_HEADERS or __GNU_LIBRARY__ */
+
+#if !defined (NULL)
+#define NULL 0
+#endif
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+ If an option that starts with '-' (not '--') doesn't match a long option,
+ but does match a short option, it is parsed as a short option
+ instead. */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"add", 1, 0, 0},
+ {"append", 0, 0, 0},
+ {"delete", 1, 0, 0},
+ {"verbose", 0, 0, 0},
+ {"create", 0, 0, 0},
+ {"file", 1, 0, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long (argc, argv, "abc:d:0123456789",
+ long_options, &option_index);
+ if (c == EOF)
+ break;
+
+ switch (c)
+ {
+ case 0:
+ printf ("option %s", long_options[option_index].name);
+ if (optarg)
+ printf (" with arg %s", optarg);
+ printf ("\n");
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case 'd':
+ printf ("option d with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/missing/memmove.c b/missing/memmove.c
new file mode 100644
index 0000000000..09e64702b6
--- /dev/null
+++ b/missing/memmove.c
@@ -0,0 +1,24 @@
+/*
+ * memmove --- move memories.
+ *
+ * We supply this routine for those systems that aren't standard yet.
+ */
+
+char *
+memmove (dst, src, n)
+ char *dst, *src;
+ int n;
+{
+ char *ret = dst;
+
+ if (src < dst) {
+ src += n;
+ dst += n;
+ while (n--)
+ *--dst = *--src;
+ }
+ else if (dst < src)
+ while (n--)
+ *dst++ = *src++;
+ return ret;
+}
diff --git a/missing/mkdir.c b/missing/mkdir.c
new file mode 100644
index 0000000000..5225e586d9
--- /dev/null
+++ b/missing/mkdir.c
@@ -0,0 +1,103 @@
+/*
+ * Written by Robert Rother, Mariah Corporation, August 1985.
+ *
+ * If you want it, it's yours. All I ask in return is that if you
+ * figure out how to do this in a Bourne Shell script you send me
+ * a copy.
+ * sdcsvax!rmr or rmr@uscd
+ *
+ * Severely hacked over by John Gilmore to make a 4.2BSD compatible
+ * subroutine. 11Mar86; hoptoad!gnu
+ *
+ * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
+ * subroutine didn't return EEXIST. It does now.
+ */
+
+#include <sys/stat.h>
+/*
+ * Make a directory.
+ */
+int
+mkdir (dpath, dmode)
+ char *dpath;
+ int dmode;
+{
+ int cpid, status;
+ struct stat statbuf;
+
+ if (stat (dpath, &statbuf) == 0)
+ {
+ errno = EEXIST; /* Stat worked, so it already exists */
+ return -1;
+ }
+
+ /* If stat fails for a reason other than non-existence, return error */
+ if (errno != ENOENT)
+ return -1;
+
+ switch (cpid = fork ())
+ {
+
+ case -1: /* Error in fork() */
+ return (-1); /* Errno is set already */
+
+ case 0: /* Child process */
+ /*
+ * Cheap hack to set mode of new directory. Since this
+ * child process is going away anyway, we zap its umask.
+ * FIXME, this won't suffice to set SUID, SGID, etc. on this
+ * directory. Does anybody care?
+ */
+ status = umask (0); /* Get current umask */
+ status = umask (status | (0777 & ~dmode)); /* Set for mkdir */
+ execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
+ _exit (-1); /* Can't exec /bin/mkdir */
+
+ default: /* Parent process */
+ while (cpid != wait (&status)); /* Wait for kid to finish */
+ }
+
+ if (WIFSIGNALED (status) || WEXITSTATUS (status) != 0)
+ {
+ errno = EIO; /* We don't know why, but */
+ return -1; /* /bin/mkdir failed */
+ }
+
+ return 0;
+}
+
+int
+rmdir (dpath)
+ char *dpath;
+{
+ int cpid, status;
+ struct stat statbuf;
+
+ if (stat (dpath, &statbuf) != 0)
+ {
+ /* Stat just set errno. We don't have to */
+ return -1;
+ }
+
+ switch (cpid = fork ())
+ {
+
+ case -1: /* Error in fork() */
+ return (-1); /* Errno is set already */
+
+ case 0: /* Child process */
+ execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
+ _exit (-1); /* Can't exec /bin/mkdir */
+
+ default: /* Parent process */
+ while (cpid != wait (&status)); /* Wait for kid to finish */
+ }
+
+ if (WIFSIGNALED (status) || WEXITSTATUS (status) != 0)
+ {
+ errno = EIO; /* We don't know why, but */
+ return -1; /* /bin/mkdir failed */
+ }
+
+ return 0;
+}
diff --git a/missing/strerror.c b/missing/strerror.c
new file mode 100644
index 0000000000..44013b3892
--- /dev/null
+++ b/missing/strerror.c
@@ -0,0 +1,19 @@
+/*
+ * strerror.c --- Map an integer error number into a printable string.
+ */
+
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+static char msg[50];
+
+char *
+strerror(error)
+ int error;
+{
+ if ((error <= sys_nerr) && (error > 0)) {
+ return sys_errlist[error];
+ }
+ sprintf (msg, "Unknown error (%d)", error);
+ return msg;
+}
diff --git a/missing/strftime.c b/missing/strftime.c
new file mode 100644
index 0000000000..36a325aa51
--- /dev/null
+++ b/missing/strftime.c
@@ -0,0 +1,781 @@
+/*
+ * strftime.c
+ *
+ * Public-domain implementation of ANSI C library routine.
+ *
+ * It's written in old-style C for maximal portability.
+ * However, since I'm used to prototypes, I've included them too.
+ *
+ * If you want stuff in the System V ascftime routine, add the SYSV_EXT define.
+ * For extensions from SunOS, add SUNOS_EXT.
+ * For stuff needed to implement the P1003.2 date command, add POSIX2_DATE.
+ * For VMS dates, add VMS_EXT.
+ * For complete POSIX semantics, add POSIX_SEMANTICS.
+ *
+ * The code for %c, %x, and %X is my best guess as to what's "appropriate".
+ * This version ignores LOCALE information.
+ * It also doesn't worry about multi-byte characters.
+ * So there.
+ *
+ * This file is also shipped with GAWK (GNU Awk), gawk specific bits of
+ * code are included if GAWK is defined.
+ *
+ * Arnold Robbins
+ * January, February, March, 1991
+ * Updated March, April 1992
+ * Updated April, 1993
+ * Updated February, 1994
+ * Updated May, 1994
+ *
+ * Fixes from ado@elsie.nci.nih.gov
+ * February 1991, May 1992
+ * Fixes from Tor Lillqvist tml@tik.vtt.fi
+ * May, 1993
+ * Further fixes from ado@elsie.nci.nih.gov
+ * February 1994
+ */
+
+#ifndef RUBY
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+#endif
+#if defined(TM_IN_SYS_TIME) || ! defined(RUBY)
+#include <sys/types.h>
+#include <sys/time.h>
+#endif
+
+/* defaults: season to taste */
+#define SYSV_EXT 1 /* stuff in System V ascftime routine */
+#define SUNOS_EXT 1 /* stuff in SunOS strftime routine */
+#define POSIX2_DATE 1 /* stuff in Posix 1003.2 date command */
+#define VMS_EXT 1 /* include %v for VMS date format */
+#ifndef RUBY
+#define POSIX_SEMANTICS 1 /* call tzset() if TZ changes */
+#endif
+
+#if defined(POSIX2_DATE)
+#if ! defined(SYSV_EXT)
+#define SYSV_EXT 1
+#endif
+#if ! defined(SUNOS_EXT)
+#define SUNOS_EXT 1
+#endif
+#endif
+
+#if defined(POSIX2_DATE)
+#define adddecl(stuff) stuff
+#else
+#define adddecl(stuff)
+#endif
+
+#undef strchr /* avoid AIX weirdness */
+
+#ifndef __STDC__
+#define const /**/
+extern void *malloc();
+extern void *realloc();
+extern void tzset();
+extern char *strchr();
+extern char *getenv();
+static int weeknumber();
+adddecl(static int iso8601wknum();)
+#else
+extern void *malloc(unsigned count);
+extern void *realloc(void *ptr, unsigned count);
+extern void tzset(void);
+extern char *strchr(const char *str, int ch);
+extern char *getenv(const char *v);
+static int weeknumber(const struct tm *timeptr, int firstweekday);
+adddecl(static int iso8601wknum(const struct tm *timeptr);)
+#endif
+
+#ifdef __GNUC__
+#define inline __inline__
+#else
+#define inline /**/
+#endif
+
+#define range(low, item, hi) max(low, min(item, hi))
+
+#if !defined(OS2) && !defined(MSDOS) && defined(HAVE_TZNAME)
+extern char *tzname[2];
+extern int daylight;
+#endif
+
+/* min --- return minimum of two numbers */
+
+#ifndef __STDC__
+static inline int
+min(a, b)
+int a, b;
+#else
+static inline int
+min(int a, int b)
+#endif
+{
+ return (a < b ? a : b);
+}
+
+/* max --- return maximum of two numbers */
+
+#ifndef __STDC__
+static inline int
+max(a, b)
+int a, b;
+#else
+static inline int
+max(int a, int b)
+#endif
+{
+ return (a > b ? a : b);
+}
+
+/* strftime --- produce formatted time */
+
+#ifndef __STDC__
+size_t
+strftime(s, maxsize, format, timeptr)
+char *s;
+size_t maxsize;
+const char *format;
+const struct tm *timeptr;
+#else
+size_t
+strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
+#endif
+{
+ char *endp = s + maxsize;
+ char *start = s;
+ auto char tbuf[100];
+ int i;
+ static short first = 1;
+#ifdef POSIX_SEMANTICS
+ static char *savetz = NULL;
+ static int savetzlen = 0;
+ char *tz;
+#endif /* POSIX_SEMANTICS */
+#ifndef HAVE_TM_ZONE
+ extern char *timezone();
+ struct timeval tv;
+ struct timezone zone;
+#endif /* HAVE_TM_ZONE */
+
+ /* various tables, useful in North America */
+ static const char *days_a[] = {
+ "Sun", "Mon", "Tue", "Wed",
+ "Thu", "Fri", "Sat",
+ };
+ static const char *days_l[] = {
+ "Sunday", "Monday", "Tuesday", "Wednesday",
+ "Thursday", "Friday", "Saturday",
+ };
+ static const char *months_a[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+ };
+ static const char *months_l[] = {
+ "January", "February", "March", "April",
+ "May", "June", "July", "August", "September",
+ "October", "November", "December",
+ };
+ static const char *ampm[] = { "AM", "PM", };
+
+ if (s == NULL || format == NULL || timeptr == NULL || maxsize == 0)
+ return 0;
+
+ /* quick check if we even need to bother */
+ if (strchr(format, '%') == NULL && strlen(format) + 1 >= maxsize)
+ return 0;
+
+#ifndef POSIX_SEMANTICS
+ if (first) {
+ tzset();
+ first = 0;
+ }
+#else /* POSIX_SEMANTICS */
+ tz = getenv("TZ");
+ if (first) {
+ if (tz != NULL) {
+ int tzlen = strlen(tz);
+
+ savetz = (char *) malloc(tzlen + 1);
+ if (savetz != NULL) {
+ savetzlen = tzlen + 1;
+ strcpy(savetz, tz);
+ }
+ }
+ tzset();
+ first = 0;
+ }
+ /* if we have a saved TZ, and it is different, recapture and reset */
+ if (tz && savetz && (tz[0] != savetz[0] || strcmp(tz, savetz) != 0)) {
+ i = strlen(tz) + 1;
+ if (i > savetzlen) {
+ savetz = (char *) realloc(savetz, i);
+ if (savetz) {
+ savetzlen = i;
+ strcpy(savetz, tz);
+ }
+ } else
+ strcpy(savetz, tz);
+ tzset();
+ }
+#endif /* POSIX_SEMANTICS */
+
+ for (; *format && s < endp - 1; format++) {
+ tbuf[0] = '\0';
+ if (*format != '%') {
+ *s++ = *format;
+ continue;
+ }
+ again:
+ switch (*++format) {
+ case '\0':
+ *s++ = '%';
+ goto out;
+
+ case '%':
+ *s++ = '%';
+ continue;
+
+ case 'a': /* abbreviated weekday name */
+ if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6)
+ strcpy(tbuf, "?");
+ else
+ strcpy(tbuf, days_a[timeptr->tm_wday]);
+ break;
+
+ case 'A': /* full weekday name */
+ if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6)
+ strcpy(tbuf, "?");
+ else
+ strcpy(tbuf, days_l[timeptr->tm_wday]);
+ break;
+
+#ifdef SYSV_EXT
+ case 'h': /* abbreviated month name */
+#endif
+ case 'b': /* abbreviated month name */
+ if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)
+ strcpy(tbuf, "?");
+ else
+ strcpy(tbuf, months_a[timeptr->tm_mon]);
+ break;
+
+ case 'B': /* full month name */
+ if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)
+ strcpy(tbuf, "?");
+ else
+ strcpy(tbuf, months_l[timeptr->tm_mon]);
+ break;
+
+ case 'c': /* appropriate date and time representation */
+ sprintf(tbuf, "%s %s %2d %02d:%02d:%02d %d",
+ days_a[range(0, timeptr->tm_wday, 6)],
+ months_a[range(0, timeptr->tm_mon, 11)],
+ range(1, timeptr->tm_mday, 31),
+ range(0, timeptr->tm_hour, 23),
+ range(0, timeptr->tm_min, 59),
+ range(0, timeptr->tm_sec, 61),
+ timeptr->tm_year + 1900);
+ break;
+
+ case 'd': /* day of the month, 01 - 31 */
+ i = range(1, timeptr->tm_mday, 31);
+ sprintf(tbuf, "%02d", i);
+ break;
+
+ case 'H': /* hour, 24-hour clock, 00 - 23 */
+ i = range(0, timeptr->tm_hour, 23);
+ sprintf(tbuf, "%02d", i);
+ break;
+
+ case 'I': /* hour, 12-hour clock, 01 - 12 */
+ i = range(0, timeptr->tm_hour, 23);
+ if (i == 0)
+ i = 12;
+ else if (i > 12)
+ i -= 12;
+ sprintf(tbuf, "%02d", i);
+ break;
+
+ case 'j': /* day of the year, 001 - 366 */
+ sprintf(tbuf, "%03d", timeptr->tm_yday + 1);
+ break;
+
+ case 'm': /* month, 01 - 12 */
+ i = range(0, timeptr->tm_mon, 11);
+ sprintf(tbuf, "%02d", i + 1);
+ break;
+
+ case 'M': /* minute, 00 - 59 */
+ i = range(0, timeptr->tm_min, 59);
+ sprintf(tbuf, "%02d", i);
+ break;
+
+ case 'p': /* am or pm based on 12-hour clock */
+ i = range(0, timeptr->tm_hour, 23);
+ if (i < 12)
+ strcpy(tbuf, ampm[0]);
+ else
+ strcpy(tbuf, ampm[1]);
+ break;
+
+ case 'S': /* second, 00 - 61 */
+ i = range(0, timeptr->tm_sec, 61);
+ sprintf(tbuf, "%02d", i);
+ break;
+
+ case 'U': /* week of year, Sunday is first day of week */
+ sprintf(tbuf, "%02d", weeknumber(timeptr, 0));
+ break;
+
+ case 'w': /* weekday, Sunday == 0, 0 - 6 */
+ i = range(0, timeptr->tm_wday, 6);
+ sprintf(tbuf, "%d", i);
+ break;
+
+ case 'W': /* week of year, Monday is first day of week */
+ sprintf(tbuf, "%02d", weeknumber(timeptr, 1));
+ break;
+
+ case 'x': /* appropriate date representation */
+ sprintf(tbuf, "%s %s %2d %d",
+ days_a[range(0, timeptr->tm_wday, 6)],
+ months_a[range(0, timeptr->tm_mon, 11)],
+ range(1, timeptr->tm_mday, 31),
+ timeptr->tm_year + 1900);
+ break;
+
+ case 'X': /* appropriate time representation */
+ sprintf(tbuf, "%02d:%02d:%02d",
+ range(0, timeptr->tm_hour, 23),
+ range(0, timeptr->tm_min, 59),
+ range(0, timeptr->tm_sec, 61));
+ break;
+
+ case 'y': /* year without a century, 00 - 99 */
+ i = timeptr->tm_year % 100;
+ sprintf(tbuf, "%02d", i);
+ break;
+
+ case 'Y': /* year with century */
+ sprintf(tbuf, "%d", 1900 + timeptr->tm_year);
+ break;
+
+ case 'Z': /* time zone name or abbrevation */
+#ifdef HAVE_TZNAME
+#ifdef HAVE_DAYLIGHT
+ i = (daylight && timeptr->tm_isdst); /* 0 or 1 */
+#else
+ i = timeptr->tm_isdst;
+#endif
+ strcpy(tbuf, tzname[i]);
+#else
+#ifdef HAVE_TM_ZONE
+ strcpy(tbuf, timeptr->tm_zone);
+#else
+ gettimeofday(& tv, & zone);
+ strcpy(tbuf, timezone(zone.tz_minuteswest,
+ timeptr->tm_isdst));
+#endif
+#endif
+ break;
+
+#ifdef SYSV_EXT
+ case 'n': /* same as \n */
+ tbuf[0] = '\n';
+ tbuf[1] = '\0';
+ break;
+
+ case 't': /* same as \t */
+ tbuf[0] = '\t';
+ tbuf[1] = '\0';
+ break;
+
+ case 'D': /* date as %m/%d/%y */
+ strftime(tbuf, sizeof tbuf, "%m/%d/%y", timeptr);
+ break;
+
+ case 'e': /* day of month, blank padded */
+ sprintf(tbuf, "%2d", range(1, timeptr->tm_mday, 31));
+ break;
+
+ case 'r': /* time as %I:%M:%S %p */
+ strftime(tbuf, sizeof tbuf, "%I:%M:%S %p", timeptr);
+ break;
+
+ case 'R': /* time as %H:%M */
+ strftime(tbuf, sizeof tbuf, "%H:%M", timeptr);
+ break;
+
+ case 'T': /* time as %H:%M:%S */
+ strftime(tbuf, sizeof tbuf, "%H:%M:%S", timeptr);
+ break;
+#endif
+
+#ifdef SUNOS_EXT
+ case 'k': /* hour, 24-hour clock, blank pad */
+ sprintf(tbuf, "%2d", range(0, timeptr->tm_hour, 23));
+ break;
+
+ case 'l': /* hour, 12-hour clock, 1 - 12, blank pad */
+ i = range(0, timeptr->tm_hour, 23);
+ if (i == 0)
+ i = 12;
+ else if (i > 12)
+ i -= 12;
+ sprintf(tbuf, "%2d", i);
+ break;
+#endif
+
+
+#ifdef VMS_EXT
+ case 'v': /* date as dd-bbb-YYYY */
+ sprintf(tbuf, "%02d-%3.3s-%4d",
+ range(1, timeptr->tm_mday, 31),
+ months_a[range(0, timeptr->tm_mon, 11)],
+ timeptr->tm_year + 1900);
+ for (i = 3; i < 6; i++)
+ if (islower(tbuf[i]))
+ tbuf[i] = toupper(tbuf[i]);
+ break;
+#endif
+
+
+#ifdef POSIX2_DATE
+ case 'C':
+ sprintf(tbuf, "%02d", (timeptr->tm_year + 1900) / 100);
+ break;
+
+
+ case 'E':
+ case 'O':
+ /* POSIX locale extensions, ignored for now */
+ goto again;
+
+ case 'V': /* week of year according ISO 8601 */
+#if defined(RUBY) && defined(VMS_EXT)
+ {
+ extern int do_lint;
+ extern void warning();
+ static int warned = 0;
+
+ if (! warned && do_lint) {
+ warned = 1;
+ warning(
+ "conversion %%V added in P1003.2; for VMS style date, use %%v");
+ }
+ }
+#endif
+ sprintf(tbuf, "%02d", iso8601wknum(timeptr));
+ break;
+
+ case 'u':
+ /* ISO 8601: Weekday as a decimal number [1 (Monday) - 7] */
+ sprintf(tbuf, "%d", timeptr->tm_wday == 0 ? 7 :
+ timeptr->tm_wday);
+ break;
+#endif /* POSIX2_DATE */
+ default:
+ tbuf[0] = '%';
+ tbuf[1] = *format;
+ tbuf[2] = '\0';
+ break;
+ }
+ i = strlen(tbuf);
+ if (i) {
+ if (s + i < endp - 1) {
+ strcpy(s, tbuf);
+ s += i;
+ } else
+ return 0;
+ }
+ }
+out:
+ if (s < endp && *format == '\0') {
+ *s = '\0';
+ return (s - start);
+ } else
+ return 0;
+}
+
+/* isleap --- is a year a leap year? */
+
+#ifndef __STDC__
+static int
+isleap(year)
+int year;
+#else
+static int
+isleap(int year)
+#endif
+{
+ return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
+}
+
+
+#ifdef POSIX2_DATE
+/* iso8601wknum --- compute week number according to ISO 8601 */
+
+#ifndef __STDC__
+static int
+iso8601wknum(timeptr)
+const struct tm *timeptr;
+#else
+static int
+iso8601wknum(const struct tm *timeptr)
+#endif
+{
+ /*
+ * From 1003.2:
+ * If the week (Monday to Sunday) containing January 1
+ * has four or more days in the new year, then it is week 1;
+ * otherwise it is the highest numbered week of the previous
+ * (52 or 53) year, and the next week is week 1.
+ *
+ * ADR: This means if Jan 1 was Monday through Thursday,
+ * it was week 1, otherwise week 52 or 53.
+ *
+ * XPG4 erroneously included POSIX.2 rationale text in the
+ * main body of the standard. Thus it requires week 53.
+ */
+
+ int weeknum, jan1day, diff;
+
+ /* get week number, Monday as first day of the week */
+ weeknum = weeknumber(timeptr, 1);
+
+ /*
+ * With thanks and tip of the hatlo to tml@tik.vtt.fi
+ *
+ * What day of the week does January 1 fall on?
+ * We know that
+ * (timeptr->tm_yday - jan1.tm_yday) MOD 7 ==
+ * (timeptr->tm_wday - jan1.tm_wday) MOD 7
+ * and that
+ * jan1.tm_yday == 0
+ * and that
+ * timeptr->tm_wday MOD 7 == timeptr->tm_wday
+ * from which it follows that. . .
+ */
+ jan1day = timeptr->tm_wday - (timeptr->tm_yday % 7);
+ if (jan1day < 0)
+ jan1day += 7;
+
+ /*
+ * If Jan 1 was a Monday through Thursday, it was in
+ * week 1. Otherwise it was last year's highest week, which is
+ * this year's week 0.
+ *
+ * What does that mean?
+ * If Jan 1 was Monday, the week number is exactly right, it can
+ * never be 0.
+ * If it was Tuesday through Thursday, the weeknumber is one
+ * less than it should be, so we add one.
+ * Otherwise, Friday, Saturday or Sunday, the week number is
+ * OK, but if it is 0, it needs to be 52 or 53.
+ */
+ switch (jan1day) {
+ case 1: /* Monday */
+ break;
+ case 2: /* Tuesday */
+ case 3: /* Wednedsday */
+ case 4: /* Thursday */
+ weeknum++;
+ break;
+ case 5: /* Friday */
+ case 6: /* Saturday */
+ case 0: /* Sunday */
+ if (weeknum == 0) {
+#ifdef USE_BROKEN_XPG4
+ /* XPG4 (as of March 1994) says 53 unconditionally */
+ weeknum = 53;
+#else
+ /* get week number of last week of last year */
+ struct tm dec31ly; /* 12/31 last year */
+ dec31ly = *timeptr;
+ dec31ly.tm_year--;
+ dec31ly.tm_mon = 11;
+ dec31ly.tm_mday = 31;
+ dec31ly.tm_wday = (jan1day == 0) ? 6 : jan1day - 1;
+ dec31ly.tm_yday = 364 + isleap(dec31ly.tm_year + 1900);
+ weeknum = iso8601wknum(& dec31ly);
+#endif
+ }
+ break;
+ }
+ return weeknum;
+}
+#endif
+
+/* weeknumber --- figure how many weeks into the year */
+
+/* With thanks and tip of the hatlo to ado@elsie.nci.nih.gov */
+
+#ifndef __STDC__
+static int
+weeknumber(timeptr, firstweekday)
+const struct tm *timeptr;
+int firstweekday;
+#else
+static int
+weeknumber(const struct tm *timeptr, int firstweekday)
+#endif
+{
+ int wday = timeptr->tm_wday;
+ int ret;
+
+ if (firstweekday == 1) {
+ if (wday == 0) /* sunday */
+ wday = 6;
+ else
+ wday--;
+ }
+ ret = ((timeptr->tm_yday + 7 - wday) / 7);
+ if (ret < 0)
+ ret = 0;
+ return ret;
+}
+
+#if 0
+/* ADR --- I'm loathe to mess with ado's code ... */
+
+Date: Wed, 24 Apr 91 20:54:08 MDT
+From: Michal Jaegermann <audfax!emory!vm.ucs.UAlberta.CA!NTOMCZAK>
+To: arnold@audiofax.com
+
+Hi Arnold,
+in a process of fixing of strftime() in libraries on Atari ST I grabbed
+some pieces of code from your own strftime. When doing that it came
+to mind that your weeknumber() function compiles a little bit nicer
+in the following form:
+/*
+ * firstweekday is 0 if starting in Sunday, non-zero if in Monday
+ */
+{
+ return (timeptr->tm_yday - timeptr->tm_wday +
+ (firstweekday ? (timeptr->tm_wday ? 8 : 1) : 7)) / 7;
+}
+How nicer it depends on a compiler, of course, but always a tiny bit.
+
+ Cheers,
+ Michal
+ ntomczak@vm.ucs.ualberta.ca
+#endif
+
+#ifdef TEST_STRFTIME
+
+/*
+ * NAME:
+ * tst
+ *
+ * SYNOPSIS:
+ * tst
+ *
+ * DESCRIPTION:
+ * "tst" is a test driver for the function "strftime".
+ *
+ * OPTIONS:
+ * None.
+ *
+ * AUTHOR:
+ * Karl Vogel
+ * Control Data Systems, Inc.
+ * vogelke@c-17igp.wpafb.af.mil
+ *
+ * BUGS:
+ * None noticed yet.
+ *
+ * COMPILE:
+ * cc -o tst -DTEST_STRFTIME strftime.c
+ */
+
+/* ADR: I reformatted this to my liking, and deleted some unneeded code. */
+
+#ifndef NULL
+#include <stdio.h>
+#endif
+#include <sys/time.h>
+#include <string.h>
+
+#define MAXTIME 132
+
+/*
+ * Array of time formats.
+ */
+
+static char *array[] =
+{
+ "(%%A) full weekday name, var length (Sunday..Saturday) %A",
+ "(%%B) full month name, var length (January..December) %B",
+ "(%%C) Century %C",
+ "(%%D) date (%%m/%%d/%%y) %D",
+ "(%%E) Locale extensions (ignored) %E",
+ "(%%H) hour (24-hour clock, 00..23) %H",
+ "(%%I) hour (12-hour clock, 01..12) %I",
+ "(%%M) minute (00..59) %M",
+ "(%%O) Locale extensions (ignored) %O",
+ "(%%R) time, 24-hour (%%H:%%M) %R",
+ "(%%S) second (00..61) %S",
+ "(%%T) time, 24-hour (%%H:%%M:%%S) %T",
+ "(%%U) week of year, Sunday as first day of week (00..53) %U",
+ "(%%V) week of year according to ISO 8601 %V",
+ "(%%W) week of year, Monday as first day of week (00..53) %W",
+ "(%%X) appropriate locale time representation (%H:%M:%S) %X",
+ "(%%Y) year with century (1970...) %Y",
+ "(%%Z) timezone (EDT), or blank if timezone not determinable %Z",
+ "(%%a) locale's abbreviated weekday name (Sun..Sat) %a",
+ "(%%b) locale's abbreviated month name (Jan..Dec) %b",
+ "(%%c) full date (Sat Nov 4 12:02:33 1989)%n%t%t%t %c",
+ "(%%d) day of the month (01..31) %d",
+ "(%%e) day of the month, blank-padded ( 1..31) %e",
+ "(%%h) should be same as (%%b) %h",
+ "(%%j) day of the year (001..366) %j",
+ "(%%k) hour, 24-hour clock, blank pad ( 0..23) %k",
+ "(%%l) hour, 12-hour clock, blank pad ( 0..12) %l",
+ "(%%m) month (01..12) %m",
+ "(%%p) locale's AM or PM based on 12-hour clock %p",
+ "(%%r) time, 12-hour (same as %%I:%%M:%%S %%p) %r",
+ "(%%u) ISO 8601: Weekday as decimal number [1 (Monday) - 7] %u",
+ "(%%v) VAX date (dd-bbb-YYYY) %v",
+ "(%%w) day of week (0..6, Sunday == 0) %w",
+ "(%%x) appropriate locale date representation %x",
+ "(%%y) last two digits of year (00..99) %y",
+ (char *) NULL
+};
+
+/* main routine. */
+
+int
+main(argc, argv)
+int argc;
+char **argv;
+{
+ long time();
+
+ char *next;
+ char string[MAXTIME];
+
+ int k;
+ int length;
+
+ struct tm *tm;
+
+ long clock;
+
+ /* Call the function. */
+
+ clock = time((long *) 0);
+ tm = localtime(&clock);
+
+ for (k = 0; next = array[k]; k++) {
+ length = strftime(string, MAXTIME, next, tm);
+ printf("%s\n", string);
+ }
+
+ exit(0);
+}
+#endif /* TEST_STRFTIME */
diff --git a/missing/strstr.c b/missing/strstr.c
new file mode 100644
index 0000000000..ff28ebffd6
--- /dev/null
+++ b/missing/strstr.c
@@ -0,0 +1,73 @@
+/*
+ * strstr.c --
+ *
+ * Source code for the "strstr" library routine.
+ *
+ * Copyright 1988-1991 Regents of the University of California
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appears in all copies. The University of California
+ * makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Header: /work/cvsroot/ruby/missing/strstr.c,v 1.1 1994/06/27 15:49:21 matz Exp $ SPRITE (Berkeley)";
+#endif /* not lint */
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * strstr --
+ *
+ * Locate the first instance of a substring in a string.
+ *
+ * Results:
+ * If string contains substring, the return value is the
+ * location of the first matching instance of substring
+ * in string. If string doesn't contain substring, the
+ * return value is 0. Matching is done on an exact
+ * character-for-character basis with no wildcards or special
+ * characters.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+strstr(string, substring)
+ register char *string; /* String to search. */
+ char *substring; /* Substring to try to find in string. */
+{
+ register char *a, *b;
+
+ /* First scan quickly through the two strings looking for a
+ * single-character match. When it's found, then compare the
+ * rest of the substring.
+ */
+
+ b = substring;
+ if (*b == 0) {
+ return string;
+ }
+ for ( ; *string != 0; string += 1) {
+ if (*string != *b) {
+ continue;
+ }
+ a = string;
+ while (1) {
+ if (*b == 0) {
+ return string;
+ }
+ if (*a++ != *b++) {
+ break;
+ }
+ }
+ b = substring;
+ }
+ return (char *) 0;
+}
diff --git a/missing/strtol.c b/missing/strtol.c
new file mode 100644
index 0000000000..4941f43b91
--- /dev/null
+++ b/missing/strtol.c
@@ -0,0 +1,84 @@
+/*
+ * strtol.c --
+ *
+ * Source code for the "strtol" library procedure.
+ *
+ * Copyright 1988 Regents of the University of California
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies. The University of California
+ * makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ */
+
+#include <ctype.h>
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * strtol --
+ *
+ * Convert an ASCII string into an integer.
+ *
+ * Results:
+ * The return value is the integer equivalent of string. If endPtr
+ * is non-NULL, then *endPtr is filled in with the character
+ * after the last one that was part of the integer. If string
+ * doesn't contain a valid integer value, then zero is returned
+ * and *endPtr is set to string.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+long int
+strtol(string, endPtr, base)
+ char *string; /* String of ASCII digits, possibly
+ * preceded by white space. For bases
+ * greater than 10, either lower- or
+ * upper-case digits may be used.
+ */
+ char **endPtr; /* Where to store address of terminating
+ * character, or NULL. */
+ int base; /* Base for conversion. Must be less
+ * than 37. If 0, then the base is chosen
+ * from the leading characters of string:
+ * "0x" means hex, "0" means octal, anything
+ * else means decimal.
+ */
+{
+ register char *p;
+ int result;
+
+ /*
+ * Skip any leading blanks.
+ */
+
+ p = string;
+ while (isspace(*p)) {
+ p += 1;
+ }
+
+ /*
+ * Check for a sign.
+ */
+
+ if (*p == '-') {
+ p += 1;
+ result = -(strtoul(p, endPtr, base));
+ } else {
+ if (*p == '+') {
+ p += 1;
+ }
+ result = strtoul(p, endPtr, base);
+ }
+ if ((result == 0) && (endPtr != 0) && (*endPtr == p)) {
+ *endPtr = string;
+ }
+ return result;
+}
diff --git a/missing/strtoul.c b/missing/strtoul.c
new file mode 100644
index 0000000000..f16f2ad9cf
--- /dev/null
+++ b/missing/strtoul.c
@@ -0,0 +1,184 @@
+/*
+ * strtoul.c --
+ *
+ * Source code for the "strtoul" library procedure.
+ *
+ * Copyright 1988 Regents of the University of California
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies. The University of California
+ * makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ */
+
+#include <ctype.h>
+
+/*
+ * The table below is used to convert from ASCII digits to a
+ * numerical equivalent. It maps from '0' through 'z' to integers
+ * (100 for non-digit characters).
+ */
+
+static char cvtIn[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* '0' - '9' */
+ 100, 100, 100, 100, 100, 100, 100, /* punctuation */
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'A' - 'Z' */
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35,
+ 100, 100, 100, 100, 100, 100, /* punctuation */
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'a' - 'z' */
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * strtoul --
+ *
+ * Convert an ASCII string into an integer.
+ *
+ * Results:
+ * The return value is the integer equivalent of string. If endPtr
+ * is non-NULL, then *endPtr is filled in with the character
+ * after the last one that was part of the integer. If string
+ * doesn't contain a valid integer value, then zero is returned
+ * and *endPtr is set to string.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+unsigned long int
+strtoul(string, endPtr, base)
+ char *string; /* String of ASCII digits, possibly
+ * preceded by white space. For bases
+ * greater than 10, either lower- or
+ * upper-case digits may be used.
+ */
+ char **endPtr; /* Where to store address of terminating
+ * character, or NULL. */
+ int base; /* Base for conversion. Must be less
+ * than 37. If 0, then the base is chosen
+ * from the leading characters of string:
+ * "0x" means hex, "0" means octal, anything
+ * else means decimal.
+ */
+{
+ register char *p;
+ register unsigned long int result = 0;
+ register unsigned digit;
+ int anyDigits = 0;
+
+ /*
+ * Skip any leading blanks.
+ */
+
+ p = string;
+ while (isspace(*p)) {
+ p += 1;
+ }
+
+ /*
+ * If no base was provided, pick one from the leading characters
+ * of the string.
+ */
+
+ if (base == 0)
+ {
+ if (*p == '0') {
+ p += 1;
+ if (*p == 'x') {
+ p += 1;
+ base = 16;
+ } else {
+
+ /*
+ * Must set anyDigits here, otherwise "0" produces a
+ * "no digits" error.
+ */
+
+ anyDigits = 1;
+ base = 8;
+ }
+ }
+ else base = 10;
+ } else if (base == 16) {
+
+ /*
+ * Skip a leading "0x" from hex numbers.
+ */
+
+ if ((p[0] == '0') && (p[1] == 'x')) {
+ p += 2;
+ }
+ }
+
+ /*
+ * Sorry this code is so messy, but speed seems important. Do
+ * different things for base 8, 10, 16, and other.
+ */
+
+ if (base == 8) {
+ for ( ; ; p += 1) {
+ digit = *p - '0';
+ if (digit > 7) {
+ break;
+ }
+ result = (result << 3) + digit;
+ anyDigits = 1;
+ }
+ } else if (base == 10) {
+ for ( ; ; p += 1) {
+ digit = *p - '0';
+ if (digit > 9) {
+ break;
+ }
+ result = (10*result) + digit;
+ anyDigits = 1;
+ }
+ } else if (base == 16) {
+ for ( ; ; p += 1) {
+ digit = *p - '0';
+ if (digit > ('z' - '0')) {
+ break;
+ }
+ digit = cvtIn[digit];
+ if (digit > 15) {
+ break;
+ }
+ result = (result << 4) + digit;
+ anyDigits = 1;
+ }
+ } else {
+ for ( ; ; p += 1) {
+ digit = *p - '0';
+ if (digit > ('z' - '0')) {
+ break;
+ }
+ digit = cvtIn[digit];
+ if (digit >= base) {
+ break;
+ }
+ result = result*base + digit;
+ anyDigits = 1;
+ }
+ }
+
+ /*
+ * See if there were any digits at all.
+ */
+
+ if (!anyDigits) {
+ p = string;
+ }
+
+ if (endPtr != 0) {
+ *endPtr = p;
+ }
+
+ return result;
+}