/*	
 *	clipmisc.c
 *
 *	エラー処理、その他いろいろです。
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2017 Naoyuki Sawa
 *
 *	* Wed Dec 12 21:51:29 JST 2001 Naoyuki Sawa
 *	- 作成開始。
 *	* Thu May 30 22:41:27 JST 2002 Naoyuki Sawa
 *	- die()の終了ボタンを、STARTからSELECTに変更。
 *	* Sun Jan 26 19:33:00 JST 2003 Naoyuki Sawa
 *	- die()関数の宣言に__attribute__((noreturn))属性を追加したので、
 *	  警告抑制のため、die()関数の最後にexit(1)を追加。
 *	  メモ:__attribute__((...))は関数宣言時のみ指定可能です。
 *	       関数実装時に指定するとコンパイルエラーとなります。
 *	* Sun May 4 18:05:00 JST 2003 Naoyuki Sawa
 *	- fpk_size()/fpk_load()を追加しました。
 *	  以前、zip形式のサポート追加時に、fpk形式のサポートは削除したのですが、
 *	  空きメモリ容量が逼迫してzip展開用バッファ(≒32K)も取れないような場合に
 *	  やはりfpk形式を使うこともあるので、fpk形式のサポートを再実装しました。
 *	* Sat Nov 22 06:00:00 JST 2003 Naoyuki Sawa
 *	- トレース出力(TRACE_ON/TRACE/trace())を追加しました。
 *	* Wed Sep 15 06:36:00 JST 2004 Naoyuki Sawa
 *	- コンパイラバグ回避のため、RND8/16,RND8/16_RANGEをマクロ→関数化しました。
 *	  過去のソースの互換性のため、関数を呼び出すマクロも定義してあります。
 *	* Tue Dec 13 04:26:00 JST 2005 Naoyuki Sawa
 *	- die()内の不要なpceLCDDispStop()呼び出しを削除しました。
 *	* Mon Dec 26 01:25:00 JST 2005 Naoyuki Sawa
 *	- コレクション関連の実装を、clipmisc.cからclipcoll.cへ分離しました。
 *	- インターフェイス関連の実装を、clipmisc.cからclipintf.cへ分離しました。
 *	* Thu Jul 06 11:48:53 JST 2006 Naoyuki Sawa
 *	- 32bit擬似乱数生成関数(rnd32())を追加しました。
 *	  32bit疑似乱数生成アルゴリズムとして、「Xorshift RNGs」を採用しました。(以下、Xorshift法と呼ぶことにします)
 *	  Xorshift法の資料を、「clip\keep\Xorshift RNGs.zip」に保存しました。
 *	- Xorshift法による32bit擬似乱数生成関数(rnd32())を新設したことに伴い、8bit擬似乱数も線形合成法→Xorshift法に変更しました。
 *	  線形合成法に問題が有ったわけではありませんが、全体の統一のためと、Xorshift法の方が良い擬似乱数(かな?)と思ったからです。
 *	- Xorshift法による32bit擬似乱数生成関数(rnd32())を新設したことに伴い、16bit擬似乱数も線形合成法→Xorshift法に変更しました。
 *	  線形合成法に問題が有ったわけではありませんが、全体の統一のためと、Xorshift法の方が良い擬似乱数(かな?)と思ったからです。
 *	* Tue Oct 03 01:05:53 JST 2006 Naoyuki Sawa
 *	- 呼び出し階層の少ないデバッグブレークを「DebugBreak()」→「__asm int 3」に変更しました。
 *	  2006/10/3現在は、呼び出し階層の少なさよりもエラーダイアログの判り易さを優先して、
 *	  「DebugBreak()」でも「__asm int 3」でもなく「abort()」を採用しているのですが、
 *	  今後のための覚え書きとして、コメントとして残しておくことにしました。
 *	* Thu Aug 13 17:02:32 JST 2009 Naoyuki Sawa
 *	- ユーティリティ：検索のセクションを追加しました。
 *	- quick_search()を追加しました。
 *	* Sat Jan 23 03:38:06 JST 2010 Naoyuki Sawa
 *	- match()を追加しました。
 *	* Wed Mar 17 01:31:08 JST 2010 Naoyuki Sawa
 *	- ユーティリティ：メルセンヌ・ツイスタ擬似乱数のセクションを追加しました。
 *	- MT_init()とMT_int32()を作成し、同時に、アセンブラ化しました。
 *	  オリジナル版のメルセンヌ・ツイスタ擬似乱数プログラムを元に、P/ECE用にアセンブラ化したものです。
 *	  また、元にしたオリジナル版プログラムを、keep/メルセンヌ・ツイスタ擬似乱数.7zに保存しました。
 *	  http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/mt.htmlのページから、ダウンロードしたものです。
 *	* Thu Oct 21 03:01:12 JST 2010 Naoyuki Sawa
 *	- shuffle()関数を、高速化・省メモリ化しました。
 *	  高速化の効果は、要素数32768個のint型配列をシャフルした場合、約10%の高速化です。
 *	  省メモリ化の効果は、4バイト小さくなっただけです。
 *	* Mon Jan 03 22:48:46 JST 2011 Naoyuki Sawa
 *	- match()→VERY_simple_RegEx_matching()に名前変更しました。
 *	* Tue Apr 19 17:31:57 JST 2011 Naoyuki Sawa
 *	- ユーティリティ：ユーティリティ：乱数生成アルゴリズムWELLのセクションを追加しました。
 *	- WELL_init()とWELL_next()を作成し、WELL_next()をアセンブラ化しました。
 *	- 乱数生成アルゴリズムWELLの資料を、keep/乱数生成アルゴリズムWELL.7zに保存しました。
 *	* Sat Jan 14 00:03:29 JST 2012 Naoyuki Sawa
 *	- die2()とdie3()を追加しました。
 *	  die()の固定引数版で、die2()はDIEマクロで，die3()はASSERTマクロで使用します。
 *	  可変引数のdie()を使うよりも、固定引数のdie2()，die3()を使う方が、呼び出しコードが短くなります。
 *	  特にDIEマクロは使用箇所が多く、die2()とdie3()の増加分を相殺して、ライブラリ全体のコードサイズ節約に寄与します。
 *	- DIEマクロとASSERTマクロが、die()の代りに、die2()とdie3()を使用するように変更しました。
 *	* Wed Nov 21 21:34:03 JST 2012 Naoyuki Sawa
 *	- rnd8(),rnd16(),rnd32(),rnd8_range(),rnd16_range(),rnd32_range()を、アセンブラ化しました。
 *	  アセンブラ化によって、僅かに省メモリになりました。
 *	  今回のアセンブラ化は、高速化が目的ではありません。(むしろ、少し低速化した関数もあります。)
 *	  rnd8(),rnd16(),rnd32(),rnd8_range(),rnd16_range(),rnd32_range()に、さほど高速性は必要無いと考え、省メモリを優先しました。
 *	* Thu Dec 06 17:08:54 JST 2012 Naoyuki Sawa
 *	- メルセンヌ・ツイスタ擬似乱数を、clipmt.hとclipmt.cへ分離しました。
 *	- 乱数生成アルゴリズムWELLを、clipwell.hとclipwell.cへ分離しました。
 *	* Sat Dec 08 22:01:35 JST 2012 Naoyuki Sawa
 *	- random_value_less_than_or_equal_to()とminimum_mask_greater_than_or_equal_to()を追加しました。
 *	* Fri Oct 03 20:36:20 JST 2014 Naoyuki Sawa
 *	- ユーティリティ：文字列操作のセクションを追加しました。
 *	- strtrim()を追加しました。
 *	* Sat Oct 04 21:40:12 JST 2014 Naoyuki Sawa
 *	- strescape(),strcompress()を追加しました。
 *	* Sat Oct 11 12:29:17 JST 2014 Naoyuki Sawa
 *	- strtrim(),strescape(),strcompress()を、clipmisc.h,cからclipstr.h,cへ移動しました。今後は「ユーティリティ：文字列操作」はclipstr.h,cに追加してください。
 *	* Wed Dec 10 00:39:11 JST 2014 Naoyuki Sawa
 *	- die()が使用するフォントを切り替えられるようにしました。
 *	  詳細は、clip.mkの'Wed Dec 10 00:39:11 JST 2014'のコメントを参照してください。
 *	* Tue Dec 23 21:05:49 JST 2014 Naoyuki Sawa
 *	- Asm版die()を2命令節約しました。_diefontは0～2なのでxld.wでなくld.wで充分でした。
 *	* Wed Dec 31 17:37:43 JST 2014 Naoyuki Sawa
 *	- cstart.cのpceAppInit00()でpceLCDDispStart()を呼び出し、液晶画面の表示を開始するようにしました。
 *	  この変更に伴い、die()内のpceLCDDispStart()呼び出しは不要になり、削除しました。
 *	* Tue Jan 06 21:26:41 JST 2015 Naoyuki Sawa
 *	- 乱数関連の宣言と実装を、clipmisc.*⇒cliprnd.*へ分離しました。
 *	  使用頻度は高いので、無駄なリンクを防ぐためと言うよりも、モジュール分けして分り易くするためです。
 *	- 「ユーティリティ：任意長パケットキュー」を、clipmisc.*⇒clipque.*へ分離しました。
 *	  使用頻度が低いので、無駄にリンクして容量が増加する事を防ぐためです。
 *	- 「ユーティリティ：リングバッファ」を、clipmisc.*⇒clipbuf.*へ分離しました。
 *	  使用頻度が低いので、無駄にリンクして容量が増加する事を防ぐためです。
 *	- 「ユーティリティ：ダブルリンクリスト」を、clipmisc.*⇒clipdlst.*へ分離しました。
 *	  使用頻度は高いので、無駄なリンクを防ぐためと言うよりも、モジュール分けして分り易くするためです。
 *	- 「ユーティリティ：検索」を、clipmisc.*⇒clipmatc.*へ分離しました。
 *	  使用頻度が低いので、無駄にリンクして容量が増加する事を防ぐためです。
 *	- 「ユーティリティ：ソート」の宣言を、clipmisc.hからclipsort.hへ分離しました。
 *	  「ユーティリティ：ソート」の実装は既に、clipsort.cで行っていたので、今回分離したのは宣言のみです。
 *	  宣言も分離することにした理由は、宣言と実装のファイルの対応付けを、分り易くするためです。
 *	- コレクション関連の宣言を、clipmisc.hからclipcoll.hへ分離しました。
 *	  コレクション関連の実装は既に、clipmisc.cからclipcoll.cへ分離してあったので、今回分離したのは宣言のみです。
 *	  宣言も分離することにした理由は、宣言と実装のファイルの対応付けを、分り易くするためです。
 *	- インターフェイス関連の宣言を、clipmisc.hからclipintf.hへ分離しました。
 *	  インターフェイス関連の実装は既に、clipmisc.cからclipintf.cへ分離してあったので、今回分離したのは宣言のみです。
 *	  宣言も分離することにした理由は、宣言と実装のファイルの対応付けを、分り易くするためです。
 *	- ファイルパック形式関連の宣言を、clipmisc.hからclipfpk.hへ分離しました。
 *	  ファイルパック形式関連の実装は既に、clipmisc.cからclipfpk.cへ分離してあったので、今回分離したのは宣言のみです。
 *	  宣言も分離することにした理由は、宣言と実装のファイルの対応付けを、分り易くするためです。
 *	* Tue Jul 14 21:03:47 JST 2015 Naoyuki Sawa
 *	- Windows版のdie()の停止前に、fflush(NULL)を追加しました。
 *	* Tue Nov 17 21:10:26 JST 2015 Naoyuki Sawa
 *	- ENTER_CS,LEAVE_CSの定義をclippce.h⇒clipmisc.hへ移動しました。
 *	  clipmisc.hにVC++6.0プロジェクト用のENTER_CS,LEAVE_CSの定義を追加した事に伴い、P/ECE用のENTER_CS,LEAVE_CSもclipmisc.hの同じ場所で定義する方が管理し易いと思うからです。
 *	- VC++6.0プロジェクト用のENTER_CS,LEAVE_CSの定義を追加しました。
 *	* Sun Nov 22 21:02:41 JST 2015 Naoyuki Sawa
 *	- parse_cmdline()を追加しました。
 *	- 環境変数'プログラム名_OPTION'で指定されたオプション(有れば)を、コマンドライン引数にマージするようにしました。
 *	* Fri Apr 15 21:07:28 JST 2016 Naoyuki Sawa
 *	- vdie()を追加しました。
 *	- P/ECE版の実装は、既存のdie()はそのままにして、新しくvdie()を追加しました。
 *	  P/ECE版の既存のdie()は、P/ECE APIのpceFontPrintf()を使用しているので、die()とvdie()に分割する事は出来ないからです。
 *	- P/ECE版の実装は、dief()と同様に、_def_vbuff[]の下端80～87ラインに、書式付き文字列を展開します。
 *	  詳細は、clipflt1.cの、dief()のコメントを参照して下さい。
 *	- Windows版の実装は、既存のdie()を、die()とvdie()に分割し、die()からvdie()を呼び出すように変更しました。
 *	  既存のdie()を利用しているアプリケーションの観点からは、die()の動作は変わっていないので、アプリケーションの変更は不要です。
 *	* Fri Apr 15 23:25:13 JST 2016 Naoyuki Sawa
 *	- Windows版のvdie()の動作を少し変更しました。
 *	  これまでは、常に、エラーメッセージをコンソールに出力していました。
 *	  変更後は、標準エラー出力がコンソールならば、これまで通りエラーメッセージをコンソールに出力しますが、
 *	  標準エラー出力がコンソールでなければ、エラーメッセージをメッセージボックスで表示するようにしました。
 *	- 標準エラー出力がコンソールでないケースとしては、以下のようなケースが考えられる。
 *	  ①明示的に標準エラー出力をファイル等へリダイレクトして実行した場合
 *	  ②VC++のアプリケーションの設定で、ウインドウアプリケーションとしてビルドした場合
 *	  ③VC++のアプリケーションの設定はコンソールアプリケーションだが、の中で'#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")'を指定した場合
 *	  等が考えられる。
 *	  今回この対応を行った理由は、主に、②③のケースでもデバッグし易いようにするためです。
 *	* Sun May 29 21:54:56 JST 2016 Naoyuki Sawa
 *	- Visual C++ .NETで、main()が呼び出される前にプロセスが終了してしまう問題を修正しました。
 *	  詳細は、cliplibc.cの同日のコメントを参照して下さい。
 *	* Mon Jun 13 21:45:44 JST 2016 Naoyuki Sawa
 *	- P/ECE環境のENTER_CS,LEAVE_CSマクロのコードサイズを削減しました。
 *	  変更前は、直接pceSyncEnterCriticalSection(),pceSyncLeaveCriticalSection()APIを呼び出していましたが、変更後は、新たに作成したEnterCS(),LeaveCS()を経由するように変更しました。
 *	  そうした理由は、pceSyncEnterCriticalSection(),pceSyncLeaveCriticalSection()はスタックを介して値を受け渡しするので、必ずスタック操作が入ってしまっていたからです。
 *	  EnterCS(),LeaveCS()は、値返し,値渡しで値を受け渡すので、コンパイラは必要に応じてそれらの値をスタックでなくレジスタに保持する事が出来、コードサイズが削減出来ます。
 *	  CRITICAL_SECTIONは、P/ECE環境ではunsigned longなので、値返し,値渡しして、(可能ならば)レジスタに保持する方が効率が良いからです。
 *	  既に、ENTER_IL,LEAVE_ILマクロはそのような構造()になっているので、今回、ENTER_CS,LEAVE_CSマクロも同様の構造にして、コードサイズを節約する事にしました。
 *	- コードサイズの節約効果は、test.pce雛形プロジェクトをそのまま多数のモジュールを組み込んだ状態でビルドした場合の比較で、全体で72バイトの節約でした。
 *	  元々、ENTER_CS,LEAVE_CSマクロを使用している箇所はさほど多くは無いので、効果はさほど大きくは有りませんが、一応、コードサイズ削減にはなりました。
 *	- コードサイズ節約効果の他に、EnterCS(),LeaveCS()が値返しで有る事で、アセンブラコードからも呼び出し易くなったと思います。
 *	  今後、アセンブラコードの中で、ENTER_CS,LEAVE_CSの処理を行う必要が有る場合は、EnterCS(),LeaveCS()関数を呼び出して下さい。
 *	  これまで通りpceSyncEnterCriticalSection(),pceSyncLeaveCriticalSection()APIを使っても構いませんが、大抵の場合EnterCS(),LeaveCS()関数を使う方がコードサイズの節約になると思います。
 *	* Tue Aug 16 21:54:11 JST 2016 Naoyuki Sawa
 *	- エラー停止処理とトレース出力処理を、clipmisc.h,clipmisc.cから、clipdie.h,clipdie.cへ分離しました。
 *	* Tue Aug 16 22:54:46 JST 2016 Naoyuki Sawa
 *	- merge_env_option()が確実に実行されるように、「#pragma comment(linker, "/INCLUDE:_pmerge_env_option")」を追加しました。
 *	  具体的には、clipmisc.c内のpmerge_env_option変数をローカル変数からグローバル変数に変更し、その変数がアプリケーションに常にリンクされるように、clipmisc.h内に上記のプラグマを追加しました。
 *	  そうした理由は、以下の通りです。
 *	- 本日、エラー停止処理とトレース出力処理を、clipmisc.h,clipmisc.cから、clipdie.h,clipdie.cへ分離した事に伴い、当モジュールで定義されるグローバルシンボルが大分少なくなりました。
 *	  これまでは、当モジュールがdie()等の必ず参照されるグローバルシンボルを含んでいたので、当モジュールは必ずリンクされ、merge_env_option()もまず確実に呼び出されていたのですが、
 *	  本日の変更によって、die()等が別モジュールへ移動し、当モジュールで定義されるグローバルシンボルをアプリケーションが(直接,又は,間接的に)参照するか、やや心配になって来ました。
 *	  実験したところ、本日時点のモジュール構成で、最小限のアプリケーションでも、当モジュールはリンクされ、merge_env_option()は呼び出されるようです。(EnterCS等が参照されているためかと思います)
 *	  とは言え、偶然に依存するのも心許無いので、今のうちに、merge_env_option()が確実に実行されるようにしておく事にしました。
 *	  その方法としては、pmerge_env_optionを明示的に参照する事によって、merge_env_option()が確実に実行されるようにしました。
 *	  pmerge_env_optionを明示的に参照する方法は、下記のプラグマを利用しました。
 *	  □「MSDN ライブラリ Microsoft Visual Studio 6.0 - comment」より:
 *	  │linker
 *	  │オブジェクトファイルにリンカオプションを記録します。
 *	  │このコメント型を使うと、[プロジェクト設定]ダイアログボックスの[リンク]タブでオプションを指定する代わりにリンカオプションを指定できます。
 *	  │たとえば、次のように/includeオプションを指定して、強制的にシンボルを取り込むことができます。
 *	  │#pragma comment(linker, "/include:__mySymbol")
 *	- 「#pragma comment(linker, "/INCLUDE:pmerge_env_option")」ではなく、「#pragma comment(linker, "/INCLUDE:_pmerge_env_option")」とする必要が有る事に注意して下さい。
 *	  変数pmerge3_env_optionはCリンケージなので、リンカのシンボル名としては先頭に「_」が一つ付与されるからです。
 *	  例えば上のMSDN ライブラリの例の場合、元の変数名は「_mySymbol」で、シンボル名としては「_」を一つ付与して「__mySymbol」になったのだろうと推測されます。
 *	* Wed Sep 07 21:52:10 JST 2016 Naoyuki Sawa
 *	- 64ビット版では、「#pragma section(".CRT$XIU", long, read)」を追加しました。
 *	  詳細は/clip/test.win/keep/開発メモ.txtの'Thu Aug 11 23:59:25 JST 2016'のコメントを参照して下さい。
 *	* Thu Sep 08 22:20:43 JST 2016 Naoyuki Sawa
 *	- init_cs()が確実に実行されるように、「#pragma comment(linker, "/INCLUDE:_pinit_cs")」及び「#pragma comment(linker, "/INCLUDE:pinit_cs")」を追加しました。
 *	  詳細は、cliplibc.h の同日のコメントを参照して下さい。
 *	* Sun May 07 09:13:01 JST 2017 Naoyuki Sawa
 *	- merge_env_option()にて、不正なメモリ開放を行ってヒープを破壊してしまっていた、重大なバグを修正しました。
 *	  詳細は、以下の通りです。
 *	- merge_env_option()の最後でfree(argv2)を行っているので、parse_cmdline()から返されたargv2は変更してはいけません。
 *	  にもかかわらず、これまでのmerge_env_option()の実装では、argv2を直接インクリメントして進めてしまっていました。
 *	  そのため、merge_env_option()の最後のfree(argv2)は、不正なメモリ開放であり、ヒープを破壊してしまっていました。
 *	- 今回、以下のように呼び出した時に一般保護エラーが発生した問題を追いかけて、このバグに気付きました。
 *	  │env.exe WIN32=1 DTEXDEFC_OPTION="-n -a" cmd.exe /C CALL MkTexDef.bat tmp\TexDef.txt
 *	  上記の呼び出しで必ず一般保護エラーが再現するわけではなく、ある程度大きなスクリプトでガーベージコレクトが発生した時だけ再現します。
 *	  Boehm GCによってヒープ破壊を検出して欲しい所ですが、デバッグ版でもリリース版でも検出されず、いきなり落ちるようです。
 *	- 今回、バグを修正した事により、ライブラリ側の問題は解決したはずです。
 *	  ただし、これまでバグを含んだライブラリをリンクして作成したツールは、全てこのバグを内包しています。
 *	  当ライブラリのmerge_env_option()実装後に、当ライブラリを使用してビルドしたツールは、全てリビルドする必要が有ります。
 *	  しかしながら、対象となるツールの数が多過ぎるので、一度に全部ではなく、優先度の高いツールから、順次、リビルドして行こうと思います。
 *	  優先度の高いツールとは、「env.exe ????????_OPTION=～」を使う等の方法で(それには限りませんが)、コマンドライン引数のマージを使う事が多いツールです。
 *	  具体的には、/clip/tool/MkTexDef.bat等の、「/clip/tool/Mk??????.bat」から呼び出されるツール群です。
 *	  ともかく、ツールにバグを抱えたまま使用し続けるのは危険ですから、出来るだけ早く、全て、リビルドしなければいけません。	→→→→→→→→→→→→→→→→{{2017/05/08コメント追記:リビルド作業の進捗については、/clip/tool/BuildTools/ライブラリのバグ修正に伴う、ツールのリビルド作業について.txt を参照して下さい。}}	{{2017/05/09コメント追記:リビルド作業を完了しました。}}
 */
#include "clip.h"

/*****************************************************************************
 *	グローバル変数
 *****************************************************************************/

//{{2015/11/17追加:VC++6.0プロジェクト用のENTER_CS,LEAVE_CSの定義を追加しました。
#ifdef  _MSC_VER
// * Tue Nov 17 21:10:26 JST 2015 Naoyuki Sawa
// - VC++6.0プロジェクト用のENTER_CS,LEAVE_CSの定義を追加しました。
// - main()が呼び出される前にクリティカルセクションオブジェクトを初期化します。
//   仕組みの詳細は、cliplibc.cのinit_program_invocation_name()のコメントを参照して下さい。
// * Sun May 29 21:54:56 JST 2016 Naoyuki Sawa
// - Visual C++ .NETで、main()が呼び出される前にプロセスが終了してしまう問題を修正しました。
//   詳細は、cliplibc.cの同日のコメントを参照して下さい。
CRITICAL_SECTION __cs__;//clipmisc.cのinit_cs()にて、main()が呼び出される前に初期化される。
//{{2016/05/29変更:Visual C++ .NETで、main()が呼び出される前にプロセスが終了してしまう問題を修正しました。
//static void init_cs() {	//main()が呼び出される前に、mainCRTStartup()⇒_cinit()⇒_initterm()から呼び出される。
//↓2016/05/29変更:Visual C++ .NETで、main()が呼び出される前にプロセスが終了してしまう問題を修正しました。
#if     (_MSC_VER > 1200)	//Visual C++ .NETならば…
static int  init_cs() {	//main()が呼び出される前に、mainCRTStartup()⇒_cinit()⇒_initterm()から呼び出される。
#else //(_MSC_VER > 1200)	//Visual C++ 6.0 ならば…
static void init_cs() {	//main()が呼び出される前に、mainCRTStartup()⇒_cinit()⇒_initterm()から呼び出される。
#endif//(_MSC_VER > 1200)
//}}2016/05/29変更:Visual C++ .NETで、main()が呼び出される前にプロセスが終了してしまう問題を修正しました。
	InitializeCriticalSection(&__cs__);
//{{2016/05/29追加:Visual C++ .NETで、main()が呼び出される前にプロセスが終了してしまう問題を修正しました。
#if     (_MSC_VER > 1200)	//Visual C++ .NETならば…
	return 0;	//VC++2015では、main()が呼び出される前に実行する関数が0を返すと、main()を呼び出さずに終了する。VC++6.0では、main()が呼び出される前に実行する関数の戻り値は検査されない。
#endif//(_MSC_VER > 1200)
//}}2016/05/29追加:Visual C++ .NETで、main()が呼び出される前にプロセスが終了してしまう問題を修正しました。
}
//{{2016/09/07追加:64ビット版では、「#pragma section(".CRT$XIU", long, read)」を追加しました。
#ifdef  _WIN64
#pragma section(".CRT$XIU", long, read)	//x64ではこの指定を追加しないと初期化関数が呼び出されません。詳細は/clip/test.win/keep/開発メモ.txtの'Thu Aug 11 23:59:25 JST 2016'のコメントを参照して下さい。
#endif//_WIN64
//}}2016/09/07追加:64ビット版では、「#pragma section(".CRT$XIU", long, read)」を追加しました。
#pragma data_seg(".CRT$XIU")	//'#pragma data_seg(".CRT$XCU")'でも構いません。
//{{2016/09/08変更:init_cs()が確実に実行されるように、「#pragma comment(linker, "/INCLUDE:_pinit_cs")」及び「#pragma comment(linker, "/INCLUDE:pinit_cs")」を追加しました。
//static void* /*!!const不可!!*/ pinit_cs/*変数名は関係無いので何でも良い*/ = init_cs;	//このポインタが".CRT$XI?"セグメント内に配置されて、mainCRTStartup()がポインタの指す関数を呼び出します。
//↓2016/09/08変更:init_cs()が確実に実行されるように、「#pragma comment(linker, "/INCLUDE:_pinit_cs")」及び「#pragma comment(linker, "/INCLUDE:pinit_cs")」を追加しました。
/*static*/ void* /*!!const不可!!*/ pinit_cs/*変数名は関係無いので何でも良い*/ = init_cs;	//このポインタが".CRT$XI?"セグメント内に配置されて、mainCRTStartup()がポインタの指す関数を呼び出します。
//}}2016/09/08変更:init_cs()が確実に実行されるように、「#pragma comment(linker, "/INCLUDE:_pinit_cs")」及び「#pragma comment(linker, "/INCLUDE:pinit_cs")」を追加しました。
#pragma data_seg()		//元のセグメントに戻す。忘れないで!!
#endif//_MSC_VER
//}}2015/11/17追加:VC++6.0プロジェクト用のENTER_CS,LEAVE_CSの定義を追加しました。

/*****************************************************************************
 *	汎用マクロ・関数
 *****************************************************************************/

//{{2016/06/13追加:P/ECE環境のENTER_CS,LEAVE_CSマクロのコードサイズを削減しました。
// * Mon Jun 13 21:45:44 JST 2016 Naoyuki Sawa
// - P/ECE環境のENTER_CS,LEAVE_CSマクロのコードサイズを削減しました。
//   変更前は、直接pceSyncEnterCriticalSection(),pceSyncLeaveCriticalSection()APIを呼び出していましたが、変更後は、新たに作成したEnterCS(),LeaveCS()を経由するように変更しました。
//   そうした理由は、pceSyncEnterCriticalSection(),pceSyncLeaveCriticalSection()はスタックを介して値を受け渡しするので、必ずスタック操作が入ってしまっていたからです。
//   EnterCS(),LeaveCS()は、値返し,値渡しで値を受け渡すので、コンパイラは必要に応じてそれらの値をスタックでなくレジスタに保持する事が出来、コードサイズが削減出来ます。
//   CRITICAL_SECTIONは、P/ECE環境ではunsigned longなので、値返し,値渡しして、(可能ならば)レジスタに保持する方が効率が良いからです。
//   既に、ENTER_IL,LEAVE_ILマクロはそのような構造()になっているので、今回、ENTER_CS,LEAVE_CSマクロも同様の構造にして、コードサイズを節約する事にしました。
// - コードサイズの節約効果は、test.pce雛形プロジェクトをそのまま多数のモジュールを組み込んだ状態でビルドした場合の比較で、全体で72バイトの節約でした。
//   元々、ENTER_CS,LEAVE_CSマクロを使用している箇所はさほど多くは無いので、効果はさほど大きくは有りませんが、一応、コードサイズ削減にはなりました。
// - コードサイズ節約効果の他に、EnterCS(),LeaveCS()が値返しで有る事で、アセンブラコードからも呼び出し易くなったと思います。
//   今後、アセンブラコードの中で、ENTER_CS,LEAVE_CSの処理を行う必要が有る場合は、EnterCS(),LeaveCS()関数を呼び出して下さい。
//   これまで通りpceSyncEnterCriticalSection(),pceSyncLeaveCriticalSection()APIを使っても構いませんが、大抵の場合EnterCS(),LeaveCS()関数を使う方がコードサイズの節約になると思います。
#ifdef  PIECE
CRITICAL_SECTION EnterCS() {
	CRITICAL_SECTION cs;
	pceSyncEnterCriticalSection(&cs);
	return cs;
	//C言語のままでも最適なコードが生成されるので、アセンブラ化はしませんでした。
	//生成されるコードは、以下の通りです。
	//│EnterCS:
	//│    xsub    %sp,%sp,4
	//│    ld.w    %r12,%sp
	//│    xcall   pceSyncEnterCriticalSection
	//│    xld.w   %r10,[%sp+0]
	//│    xadd    %sp,%sp,4
	//│    ret
}
void LeaveCS(CRITICAL_SECTION cs) {
	pceSyncLeaveCriticalSection(&cs);
	//C言語のままでも最適なコードが生成されるので、アセンブラ化はしませんでした。
	//生成されるコードは、以下の通りです。
	//│LeaveCS:
	//│    xsub    %sp,%sp,4
	//│    xld.w   [%sp+0],%r12
	//│    ld.w    %r12,%sp
	//│    xcall   pceSyncLeaveCriticalSection
	//│    xadd    %sp,%sp,4
	//│    ret
}
#endif//PIECE
//}}2016/06/13追加:P/ECE環境のENTER_CS,LEAVE_CSマクロのコードサイズを削減しました。

//{{2015/01/06削除:乱数関連の宣言と実装を、clipmisc.*⇒cliprnd.*へ分離しました。
//#ifndef PIECE
////int
////rnd8(int* seed)
////{
////	/* 8ビット乱数(『Z80マシン語秘伝の書』より) */
////	*seed = *seed * 5 + 0x3711;
////	return (*seed >> 8) & 0xff;
////}
////↓* Thu Jul 06 11:48:53 JST 2006 Naoyuki Sawa
////↓- Xorshift法による32bit擬似乱数生成関数(rnd32())を新設したことに伴い、8bit擬似乱数も線形合成法→Xorshift法に変更しました。
////↓  線形合成法に問題が有ったわけではありませんが、全体の統一のためと、Xorshift法の方が良い擬似乱数(かな?)と思ったからです。
//int
//rnd8(int* seed)
//{
//	/* 32bit擬似乱数値の中央8bitを、8bit擬似乱数値として返します。
//	 * - 大きなビット数の擬似乱数値から、小さなビット数の擬似乱数値を取り出す場合、
//	 *   最上位や最下位から取り出すよりも、中央部を取り出す方が良いとされています。
//	 *
//	 *	++++-++++-++++-++++-++++-++++-++++-++++-< rnd32()
//	 *	|||| |||| |||| |||| |||| |||| |||| ||||
//	 *	1111 1111 1111 1111 0000 0000 0000 0000
//	 *	fedc ba98 7654 3210 fedc ba98 7654 3210
//	 *	               |||| ||||
//	 *	               ++++-++++----------------> rnd8()
//	 */
//	return (unsigned char)(rnd32(seed) >> ((32 - 8) / 2));
//}
////int
////rnd16(int* seed)
////{
////	/* 16ビット乱数(VisualC++ 6.0 \VC98\CRT\SRC\RAND.C を参考にしました) */
////	*seed = *seed * 214013 + 2531011;
////	return (*seed >> 16) & 0xffff;
////}
////↓* Thu Jul 06 11:48:53 JST 2006 Naoyuki Sawa
////↓- Xorshift法による32bit擬似乱数生成関数(rnd32())を新設したことに伴い、16bit擬似乱数も線形合成法→Xorshift法に変更しました。
////↓  線形合成法に問題が有ったわけではありませんが、全体の統一のためと、Xorshift法の方が良い擬似乱数(かな?)と思ったからです。
//int
//rnd16(int* seed)
//{
//	/* 32bit擬似乱数値の中央16bitを、16bit擬似乱数値として返します。
//	 * - 大きなビット数の擬似乱数値から、小さなビット数の擬似乱数値を取り出す場合、
//	 *   最上位や最下位から取り出すよりも、中央部を取り出す方が良いとされています。
//	 *
//	 *	++++-++++-++++-++++-++++-++++-++++-++++-< rnd32()
//	 *	|||| |||| |||| |||| |||| |||| |||| ||||
//	 *	1111 1111 1111 1111 0000 0000 0000 0000
//	 *	fedc ba98 7654 3210 fedc ba98 7654 3210
//	 *	          |||| |||| |||| ||||
//	 *	          ++++-++++-++++-++++-----------> rnd16()
//	 */
//	return (unsigned short)(rnd32(seed) >> ((32 - 16) / 2));
//}
///* * Thu Jul 06 11:48:53 JST 2006 Naoyuki Sawa
// * - 32bit擬似乱数生成関数(rnd32())を追加しました。
// *   32bit疑似乱数生成アルゴリズムとして、「Xorshift RNGs」を採用しました。(以下、Xorshift法と呼ぶことにします)
// *   Xorshift法の資料を、「clip\keep\Xorshift RNGs.zip」に保存しました。
// * - 旧いrnd16()関数で利用していた線形合成方法をそのまま使い、16bit右シフトせずにそのまま32bit擬似乱数として返す方法も可能ですが、
// *   その方法では、偶数/奇数が交互に生成されてしまうこと等、良くない擬似乱数であると判断したので、Xorshift法を使うことにしました。
// */
//int
//rnd32(int* seed)
//{
//#define MAGIC_NUMBER 2463534242u /* 0以外ならば何でも可 */
//
//	/* 前回の乱数値を取り出します。
//	 * - 以下のシフト演算は、算術シフトでなく論理シフトで行う必要があるので、符号無し値として取り出します。
//	 *   関数インターフェイス(seed引数)は、利用側の使い易さを考えて、符号付き値へのポインタとしてあります。
//	 */
//	unsigned y = *seed;
//
//	/* 前回の乱数値が0だったならば、0以外の適当な値に置き換えます。
//	 * - Xorshift法の乱数列は、M系列乱数に性格が似ていて、0を生成できません。
//	 *   32ビット乱数列を生成する場合、周期は「2^32」でなく「(2^32)-1」です。
//	 *   すなわち、0x00000000～0xFFFFFFFFの範囲の乱数列を生成するのではなく、0x00000001～0xFFFFFFFFの範囲の乱数列を生成します。
//	 *   0を含めるには、乱数列の適当な位置に、明示的に0を挟む必要があります。
//	 * - MAGIC_NUMBERの値に意味は無く、0以外の値ならば何でも構いません。
//	 *   Xorshift法の原典のサンプルコードが、たまたま初期シード値として「2463534242」を使っていたので、それにちなんだだけです。
//	 *   初期シード値も、0以外ならば何でも良く、Xorshift法の原典資料のサンプルコードにおいても、「2463534242」に意味はありません。
//	 * - 本関数は、Xorshift法の原典のサンプルコードに手を加えて、0にも対応しているので、初期シード値として0を指定することも可能です。
//	 *   MAGIC_NUMBERにだけは、0を指定することは不可です。
//	 */
//	if(y == 0) y = MAGIC_NUMBER;
//
//	/* Xorshift法を使って、前回の乱数値から、今回の乱数値を生成します。
//	 * - シフト数[13,17,5]の組み合わせは、Xorshift法の原典のサンプルコードを参考にしました。
//	 *   Xorshift法の原典には、これ以外にも、様々なシフト数の組み合わせが載っています。
//	 */
//	y ^= (y << 13);
//	y ^= (y >> 17);
//	y ^= (y <<  5);
//
//	/* 今回の乱数値が特定の値になったら、その前に、明示的に0を挟みます。
//	 * - Xorshift法は0を生成できないので、乱数列の適当な位置に、明示的に0を挟む必要があります。
//	 *   上述のコメントを参照してください。
//	 */
//	if(y == MAGIC_NUMBER) y = 0;
//
//	/* 今回の乱数値を、次回の乱数シードとして格納します。
//	 * - 関数の戻り値である乱数値と格納する乱数シードは同じ値なので、seed引数を無くすことも可能ですが、
//	 *   たとえば、以下のような呼び出し方ができると便利なので、あえてseed引数を設けてあります。
//	 *
//	 *	retval = rnd32(&seed) % 100; // 0～99の乱数値を生成する
//	 *
//	 *   また、今後、疑似乱数生成に利用するアルゴリズムを変更し、戻り値と乱数シードが同じでなくなった場合にも対応できます。
//	 *   実際に今回、疑似乱数生成アルゴリズムを、線形合成法→Xorshift法に変更したわけですが、関数インターフェイスに変化はありません。
//	 * - rnd32()の戻り値は(int)なので、0x00000000～0xFFFFFFFFではなく、-0x80000000～0x7FFFFFFFとなります。
//	 *   rnd8()の戻り値が0x00～0xFFであることや、rnd16()の戻り値が0x0000～0xFFFFであることに較べると、一貫性に欠けます。
//	 *   それでもあえてこの仕様とした理由は、rnd8()もrnd16()も戻り値が(int)であり、rnd32()だけ戻り値の型を変えるのが嫌だったからです。
//	 *   0x00000000～0xFFFFFFFFの乱数値が必要ならば、呼び出し側にて戻り値を(unsigned)にキャストしてください。
//	 *   明示的な(unsigned)へのキャストを要求する方が、見た目で判らない(unsigned)値が式に与える影響の伝播よりも、安全だと考えました。
//	 */
//	return (*seed = y);
//
//#undef MAGIC_NUMBER
//}
//int
//rnd8_range(int* seed, int a, int b)
//{
//	return rnd8(seed) % (b - a) + a;
//}
//int
//rnd16_range(int* seed, int a, int b)
//{
//	return rnd16(seed) % (b - a) + a;
//}
//int
//rnd32_range(int* seed, int a, int b)
//{
//	return (unsigned)rnd32(seed) % (unsigned)(b - a) + a;
//	//     ~~~~~~~~~~←─必要!!─→~~~~~~~~~~
//}
//#else /*PIECE*/
//asm("
//		.code
//		.align		1
//		.global		rnd8
//		.global		rnd16
//		.global		rnd32
//		.global		rnd8_range
//		.global		rnd16_range
//		.global		rnd32_range
//		;//-------------------------------------;//
//rnd8:
//		call		rnd16			;// %r10 := y = rnd32(seed) >> 12
//		sra		%r10, 4			;//           = rnd16(seed) >> 4
//		ret.d
//		ld.ub		%r10, %r10		;// return (unsigned char)y		*delay*
//		;//-------------------------------------;//
//rnd16:
//		call		rnd32			;// %r10 := y = rnd32(seed) >> 8
//		sra		%r10, 8
//		ret.d
//		ld.uh		%r10, %r10		;// return (unsigned short)y		*delay*
//		;//-------------------------------------;//
//rnd32:
//		ld.w		%r10, [%r12]		;// %r10 := y = *seed
//		xld.w		%r11, 2463534242	;// %r11 := MAGIC_NUMBER		*anti-interlock*
//		cmp		%r10, 0			;// if(y == 0) {
//		jrne		2			;//    y  = MAGIC_NUMBER
//		 ld.w		%r10, %r11		;// }
//		;//
//		ld.w		%r9, %r10		;// %r9  :=       y
//		xsll		%r9, 13			;// %r9  :=      (y << 13)
//		xor		%r10, %r9		;// %r10 := y ^= (y << 13)
//		;//
//		ld.w		%r9, %r10		;// %r9  :=       y
//		xsrl		%r9, 17			;// %r9  :=      (y >> 17)
//		xor		%r10, %r9		;// %r10 := y ^= (y >> 17)
//		;//
//		ld.w		%r9, %r10		;// %r9  :=       y
//		xsll		%r9, 5			;// %r9  :=      (y <<  5)
//		xor		%r10, %r9		;// %r10 := y ^= (y <<  5)
//		;//
//		cmp		%r10, %r11		;// if(y == MAGIC_NUMBER) {
//		jrne		2			;//    y  = 0
//		 ld.w		%r10, 0			;// }
//		;//
//		ld.w		[%r12], %r10		;// *seed = y
//		ret					;// return  y
//		;//-------------------------------------;//
//rnd8_range:
//		ld.w		%r15, %r13		;// %r15 :=                                             a
//		ld.w		%r13, %r14		;// %r13 :=                                    b
//		call.d		rnd8			;// %r10 :=            rnd8(seed)				アセンブラ版の rnd8は %r9,%r10,%r11,%psr 以外を破壊しません。
//		sub		%r13, %r15		;// %r13 :=                                   (b - a)		*delay*
//		;//
//		xcall.d		__modsi3		;// %r10 :=            rnd8(seed) %           (b - a)		CLiP版の__modsi3は %r9,%r10,%alr,%ahr,%psr 以外を破壊しません。(clipidiv.s 参照)
//		ld.w		%r12, %r10		;// %r12 :=            rnd8(seed)				*delay*
//		;//
//		ret.d
//		add		%r10, %r15		;// %r10 :=            rnd8(seed) %           (b - a) + a	*delay*
//		;//-------------------------------------;//
//rnd16_range:
//		ld.w		%r15, %r13		;// %r15 :=                                             a
//		ld.w		%r13, %r14		;// %r13 :=                                    b
//		call.d		rnd16			;// %r10 :=           rnd16(seed)				アセンブラ版のrnd16は %r9,%r10,%r11,%psr 以外を破壊しません。
//		sub		%r13, %r15		;// %r13 :=                                   (b - a)		*delay*
//		;//
//		xcall.d		__modsi3		;// %r10 :=           rnd16(seed) %           (b - a)		CLiP版の__modsi3は %r9,%r10,%alr,%ahr,%psr 以外を破壊しません。(clipidiv.s 参照)
//		ld.w		%r12, %r10		;// %r12 :=           rnd16(seed)				*delay*
//		;//
//		ret.d
//		add		%r10, %r15		;// %r10 :=           rnd16(seed) %           (b - a) + a	*delay*
//		;//-------------------------------------;//
//rnd32_range:
//		ld.w		%r15, %r13		;// %r15 :=                                             a
//		ld.w		%r13, %r14		;// %r13 :=                                    b
//		call.d		rnd32			;// %r10 :=           rnd32(seed)				アセンブラ版のrnd32は %r9,%r10,%r11,%psr 以外を破壊しません。
//		sub		%r13, %r15		;// %r13 :=                                   (b - a)		*delay*
//		;//
//		xcall.d		__umodsi3		;// %r10 := (unsigned)rnd32(seed) % (unsigned)(b - a)		CLiP版の__modsi3は %r9,%r10,%alr,%ahr,%psr 以外を破壊しません。(clipidiv.s 参照)
//		ld.w		%r12, %r10		;// %r12 :=           rnd32(seed)				*delay*
//		;//
//		ret.d
//		add		%r10, %r15		;// %r10 := (unsigned)rnd32(seed) % (unsigned)(b - a) + a	*delay*
//");
//#endif/*PIECE*/
//
////{{2010/10/21:高速化・省メモリ化に伴い削除
////void
////shuffle(void* base, int num, int width, int* seed)
////{
////	int i;
////	int c;
////	int i_dst;
////	int i_src;
////	unsigned char* p_dst;
////	unsigned char* p_src;
////
////	///* 0要素未満の配列は不正です。また、
////	// * 現在の実装は16bit乱数を利用しているため、65536要素超過の配列には未対応です。
////	// */
////	//if((num < 0) || (num > (1<<16))) {
////	//	DIE();
////	//}
////	//↓2006/07/06 numの範囲検査を削除しました。
////	// * Thu Jul 06 11:48:53 JST 2006 Naoyuki Sawa
////	// - rnd32()の新設に伴い、16bit乱数→32bit乱数を利用するよう変更しました。
////	//   この変更により、65536要素以上の配列をシャッフルできなかった制限が無くなりました。
////	//   (num < 0)の制限は引き続き存在しますが、自明なので、検査を省略することにしました。
////
////	/* 先頭要素から最終要素まで順番に... */
////	p_dst = base;
////	for(i_dst = 0; i_dst < num; i_dst++) {
////
////		/* 交換相手の要素を決定します。 */
////		//i_src = RND16_RANGE(*seed, i_dst, num);
////		//↓* Thu Jul 06 11:48:53 JST 2006 Naoyuki Sawa
////		//↓- rnd32()の新設に伴い、16bit乱数→32bit乱数を利用するよう変更しました。
////		//↓  この変更により、65536要素以上の配列をシャッフルできなかった制限が無くなりました。
////		i_src = RND32_RANGE(*seed, i_dst, num);
////		p_src = (unsigned char*)base + width * i_src;
////
////		/* 1バイトづつ交換します。 */
////		for(i = 0; i < width; i++) {
////			c = *p_dst;
////			    *p_dst = *p_src;
////			             *p_src = c;
////			p_dst++;
////			p_src++;
////		}
////	}
////}
////}}2010/10/21:高速化・省メモリ化に伴い削除
////↓ * Thu Oct 21 03:01:12 JST 2010 Naoyuki Sawa
////↓ - shuffle()関数を、高速化・省メモリ化しました。
////↓   高速化の効果は、要素数32768個のint型配列をシャフルした場合、約10%の高速化です。
////↓   省メモリ化の効果は、4バイト小さくなっただけです。
//void
//shuffle(void* base, int num, int width, int* seed)
//{
//	int i;
//	int c;
//	unsigned char* p_dst;
//	unsigned char* p_src;
//
//	/* 交換先要素は、配列の先頭要素から、配列の(最終要素-1)まで。 */
//	p_dst = base;
//	while(num > 1) {
//		/* 交換元要素は、交換先要素から、配列の最終要素まで。 */
//		p_src = &p_dst[((unsigned)rnd32(seed) % num) * width];
//		//              ~~~~~~~~~~必要!
//		/* 交換先要素と、交換元要素を、一文字づつ交換します。 */
//		for(i = 0; i < width; i++) {
//			c = *p_dst;
//			    *p_dst = *p_src;
//			             *p_src = c;
//			p_dst++;
//			p_src++;
//		}
//		num--;
//	}
//}
//}}2015/01/06削除:乱数関連の宣言と実装を、clipmisc.*⇒cliprnd.*へ分離しました。

//{{2016/08/16削除:エラー停止処理とトレース出力処理を、clipmisc.h,clipmisc.cから、clipdie.h,clipdie.cへ分離しました。
///*****************************************************************************
// *	エラー処理
// *****************************************************************************/
//
////{{2015/02/08コメント追加━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
//// * Sun Feb 08 19:33:38 JST 2015 Naoyuki Sawa
//// - VC++6.0でコンパイルした時、'PIECE'シンボルを定義していないのに、以下の'#ifdef PIECE'ブロック内でエラーが出る事が有ります。
////   『プリコンパイル済みヘッダーを自動的に使用』の設定になっていると、上記のエラーが出るようです。
////   『プリコンパイル済みヘッダーを使用しない』の設定に変更すると、上記のエラーが出なくなりました。
////   詳細な原因は判らないのですが、ともかく常に『プリコンパイル済みヘッダーを使用しない』の設定にしておく方が安全だと思います。
////}}2015/02/08コメント追加━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
//
//#ifdef PIECE
///* void die(const char* fmt, ...) __attribute__((noreturn)) */
//asm("
//	.code
//	.align	1
//	.global	die
//die:
//	; as33アセンブラは、未定義シンボルをexternと見なすので、
//	; 明示的なextern宣言は必要ありません。(_def_vbuffのこと)
//;//不要	xcall pceLCDDispStop		; pceLCDDispStop(); {{2005/12/13 Naoyuki Sawa 不要なので削除しました}}
//	xld.w %r12, _def_vbuff		; pceLCDSetBuffer(_def_vbuff);
//	xcall pceLCDSetBuffer
//;//不要	xcall pceLCDDispStart		; pceLCDDispStart();	//{{2014/12/31削除:cstart.cのpceAppInit00()でpceLCDDispStart()を呼び出し、液晶画面の表示を開始するようにしました。}}
//;//{{2014/12/10変更:die()が使用するフォントを切り替えられるようにしました。詳細は、clip.mkの'Wed Dec 10 00:39:11 JST 2014'のコメントを参照してください。
//;//{{	xld.w %r12, 0			; pceFontSetType(0);
//;//↓2014/12/10変更:die()が使用するフォントを切り替えられるようにしました。詳細は、clip.mkの'Wed Dec 10 00:39:11 JST 2014'のコメントを参照してください。
//  ;//{{2014/12/23変更:Asm版die()を2命令節約しました。_diefontは0～2なのでxld.wでなくld.wで充分でした。
//  ;//	xld.w %r12, _diefont		; pceFontSetType(_diefont);
//  ;//↓2014/12/23変更:Asm版die()を2命令節約しました。_diefontは0～2なのでxld.wでなくld.wで充分でした。
//	 ld.w %r12, _diefont@l		; pceFontSetType(_diefont);
//  ;//}}2014/12/23変更:Asm版die()を2命令節約しました。_diefontは0～2なのでxld.wでなくld.wで充分でした。
//;//}}2014/12/10変更:die()が使用するフォントを切り替えられるようにしました。詳細は、clip.mkの'Wed Dec 10 00:39:11 JST 2014'のコメントを参照してください。
//	xcall pceFontSetType
//	xld.w %r12, 3			; pceFontSetTxColor(3);
//	xcall pceFontSetTxColor
//	xld.w %r12, 0			; pceFontSetBkColor(0);
//	xcall pceFontSetBkColor
//	xld.w %r12, 0			; pceFontSetPos(0, 0);
//	xld.w %r13, 0
//	xcall pceFontSetPos
//	xld.w %r4, die_L10		; pceFontPrintf(fmt, ...);
//	xld.w [%sp], %r4
//	xjp pceFontPrintf
//die_L10:
//	xcall pceLCDTrans		; pceLCDTrans();
//die_L20:				; for(;;) {
//	xcall yield			;	yield();
//	xcall pcePadGet			;	if(pcePadGet() & TRG_SELECT) {
//	xand %r10, %r10, 0x4000		;
//	xjreq die_L30			;
//	xld.w %r12, 1			;		pceAppReqExit(1);
//	xcall pceAppReqExit		;
//die_L30:				;	}
//	xjp die_L20			; }
//");
////{{2016/04/15追加:vdie()を追加しました。
//// * Fri Apr 15 21:07:28 JST 2016 Naoyuki Sawa
//// - vdie()を追加しました。
//// - P/ECE版の実装は、既存のdie()はそのままにして、新しくvdie()を追加しました。
////   P/ECE版の既存のdie()は、P/ECE APIのpceFontPrintf()を使用しているので、die()とvdie()に分割する事は出来ないからです。
//// - P/ECE版の実装は、dief()と同様に、_def_vbuff[]の下端80～87ラインに、書式付き文字列を展開します。
////   詳細は、clipflt1.cの、dief()のコメントを参照して下さい。
//// - Windows版の実装は、既存のdie()を、die()とvdie()に分割し、die()からvdie()を呼び出すように変更しました。
////   既存のdie()を利用しているアプリケーションの観点からは、die()の動作は変わっていないので、アプリケーションの変更は不要です。
//void vdie(const char* fmt, va_list ap) /*__attribute__((noreturn))*/ {
//	vsnprintf(&_def_vbuff[DISP_X * (DISP_Y - 8)], DISP_X * 8, fmt, ap);
//	die("%s", &_def_vbuff[DISP_X * (DISP_Y - 8)]);
//}
////}}2016/04/15追加:vdie()を追加しました。
//#else /*PIECE*/
//// * __declspec(noreturn)は、.hファイルの関数宣言に付加するだけで良いようです。
////   .cファイルの関数定義には、付加してもしなくても同じみたいです。(実験より)
////   GCCの__attribute__((noreturn))が、関数定義には付加できないことに合わせて、
////   __declspec(noreturn)も、関数定義には付加しないことにしました。
//// * GCCは、__attribute__((noreturn))を付加した関数が、誤って処理を返した場合、
////   コンパイル時に警告を表示します。
////   Visual C++は、__declspec(noreturn)を付加した関数が、誤って処理を返しても、
////   コンパイル時に警告を表示しないので、注意が必要です。
//// * Fri Apr 15 21:07:28 JST 2016 Naoyuki Sawa
//// - vdie()を追加しました。
//// - P/ECE版の実装は、既存のdie()はそのままにして、新しくvdie()を追加しました。
////   P/ECE版の既存のdie()は、P/ECE APIのpceFontPrintf()を使用しているので、die()とvdie()に分割する事は出来ないからです。
//// - P/ECE版の実装は、dief()と同様に、_def_vbuff[]の下端80～87ラインに、書式付き文字列を展開します。
////   詳細は、clipflt1.cの、dief()のコメントを参照して下さい。
//// - Windows版の実装は、既存のdie()を、die()とvdie()に分割し、die()からvdie()を呼び出すように変更しました。
////   既存のdie()を利用しているアプリケーションの観点からは、die()の動作は変わっていないので、アプリケーションの変更は不要です。
//// * Fri Apr 15 23:25:13 JST 2016 Naoyuki Sawa
//// - Windows版のvdie()の動作を少し変更しました。
////   これまでは、常に、エラーメッセージをコンソールに出力していました。
////   変更後は、標準エラー出力がコンソールならば、これまで通りエラーメッセージをコンソールに出力しますが、
////   標準エラー出力がコンソールでなければ、エラーメッセージをメッセージボックスで表示するようにしました。
//// - 標準エラー出力がコンソールでないケースとしては、以下のようなケースが考えられる。
////   ①明示的に標準エラー出力をファイル等へリダイレクトして実行した場合
////   ②VC++のアプリケーションの設定で、ウインドウアプリケーションとしてビルドした場合
////   ③VC++のアプリケーションの設定はコンソールアプリケーションだが、の中で'#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")'を指定した場合
////   等が考えられる。
////   今回この対応を行った理由は、主に、②③のケースでもデバッグし易いようにするためです。
///*__declspec(noreturn)*/ void die(const char* fmt, ...) {
//	va_list ap;
//	va_start(ap, fmt);
////{{2016/04/15変更:vdie()を追加しました。
////	vfprintf(stderr, fmt, ap);
////	va_end(ap);
////↓2016/04/15変更:vdie()を追加しました。
//	vdie(fmt, ap);
////不要	va_end(ap);
//}
///*__declspec(noreturn)*/ void vdie(const char* fmt, va_list ap) {
//	//標準エラー出力がコンソールならば、エラーメッセージをコンソールに出力する。
//	if(isatty(fileno(stderr))) {
//		vfprintf(stderr, fmt, ap);
//	//標準エラー出力がコンソールでなければ、エラーメッセージをメッセージボックスで表示する。
//	// - 標準エラー出力がコンソールでないケースとしては、以下のようなケースが考えられる。
//	//   ①明示的に標準エラー出力をファイル等へリダイレクトして実行した場合
//	//   ②VC++のアプリケーションの設定で、ウインドウアプリケーションとしてビルドした場合
//	//   ③VC++のアプリケーションの設定はコンソールアプリケーションだが、の中で'#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")'を指定した場合
//	//   等が考えられる。
//	//   今回この対応を行った理由は、主に、②③のケースでもデバッグし易いようにするためです。
//	} else {
//		char* str = strdup_vprintf(fmt, ap);	//エラー処理の中でstrdup_vprintf()を使うのは少し怖いが、大抵は大丈夫だろう。
//		MessageBox(NULL, str, program_invocation_short_name, MB_OK|MB_ICONERROR|MB_TASKMODAL);	//MB_SYSTEMMODALではなくMB_TASKMODALが適切です。名前とは裏腹にアプリケーションのスレッドに属する全てのウインドウにフォーカスを移せなくするのはMB_SYSTEMMODALではなくMB_TASKMODALの方です。
//	//不要	free(str);	⇒この後すぐに終了するのでメモリ解放は不要です。二重遭難の危険を少しでも減らすためにメモリ解放しない事にしました。
//	}
////}}2016/04/15変更:vdie()を追加しました。
//    //{{2015/07/14追加:Windows版のdie()の停止前に、fflush(NULL)を追加しました。
//	//abort()が出力ストリームをフラッシュするかしないかは環境依存であり、Visual C++ではフラッシュしないようです。
//	//従って、エラーログを確実に保存するために、少なくともfflush(stderr)が必要です。
//	//エラーログ以外の出力ストリームも確実に保存できるよう、fflush(NULL)とする事にしました。
//	fflush(NULL);
//    //}}2015/07/14追加:Windows版のdie()の停止前に、fflush(NULL)を追加しました。
//#if 1
//	abort(); /* DebugBreak()よりもエラーダイアログが判り易いです */
//#else
//	//DebugBreak(); /* abort()よりも呼び出し階層が少なくて済みます */
//	//↓* Tue Oct 03 01:05:53 JST 2006 Naoyuki Sawa
//	//↓- 呼び出し階層の少ないデバッグブレークを「DebugBreak()」→「__asm int 3」に変更しました。
//	//↓  2006/10/3現在は、呼び出し階層の少なさよりもエラーダイアログの判り易さを優先して、
//	//↓  「DebugBreak()」でも「__asm int 3」でもなく「abort()」を採用しているのですが、
//	//↓  今後のための覚え書きとして、コメントとして残しておくことにしました。
//	__asm int 3; /* DebugBreak()よりもさらに呼び出し階層が少なくて済みます */
//#endif
//}
//#endif /*PIECE*/
//
////{{2012/01/14:追加
///*__declspec(noreturn)*/ void die2(const char* file, int line) /*__attribute__((noreturn))*/ {
//	die("%s(%d)", file, line);
//}
///*__declspec(noreturn)*/ void die3(const char* file, int line, const char* f) /*__attribute__((noreturn))*/ {
//	die("%s(%d): %s", file, line, f);
//}
////}}2012/01/14:追加
//
///*****************************************************************************
// *	トレース出力
// *****************************************************************************/
//
//void
//trace(const char* fmt, ...)
//{
//	va_list ap;
//	va_start(ap, fmt);
//	vfprintf(stderr, fmt, ap);
//	va_end(ap);
//}
//}}2016/08/16削除:エラー停止処理とトレース出力処理を、clipmisc.h,clipmisc.cから、clipdie.h,clipdie.cへ分離しました。

//{{2015/01/06削除:「ユーティリティ：任意長パケットキュー」を、clipmisc.*⇒clipque.*へ分離しました。
///*****************************************************************************
// *	ユーティリティ：任意長パケットキュー
// *****************************************************************************/
//
//QUEUE*
//create_queue(int capacity)
//{
//	QUEUE* queue;
//
//	if(capacity < 0) {
//		DIE();
//	}
//
//	/* パケットサイズ格納用のsizeof(int)を加算して、実際のストレージサイズとします。
//	 * 最大で、capacityバイトのパケットを一つ、キューに格納できるようにするためです。
//	 */
//	capacity += sizeof(int);
//
//	/* ヘッダとストレージのメモリを確保します。 */
//	queue = malloc(sizeof(QUEUE) + capacity);
//	if(!queue) {
//		DIE(); /* メモリ不足 */
//	}
//
//	/* ヘッダを初期化します。 */
//	queue->capacity = capacity;
//	queue->size = 0;
//
//	return queue;
//}
//
//void
//delete_queue(QUEUE* queue)
//{
//	/* ヘッダとストレージのメモリを開放します。 */
//	free(queue);
//}
//
//void
//clear_queue(QUEUE* queue)
//{
//	queue->size = 0;
//}
//
//int
//write_queue(QUEUE* queue, const void* packet/*[length]*/, int length)
//{
//	unsigned char* storage = (unsigned char*)(queue + 1);
//
//	if(length < 0) {
//		DIE();
//	}
//
//	/* パケットサイズとパケットデータを追加する空き容量があるか？ */
//	if((int)(queue->size + (sizeof(int) + length)) > queue->capacity) {
//		return -1;
//	}
//
//	/* キューの末尾にパケットサイズとパケットデータを追加します。 */
//	PUT_LEWORD(storage + queue->size, length);
//	memcpy(storage + queue->size + sizeof(int), packet, length);
//	queue->size += (sizeof(int) + length);
//
//	return length;
//}
//
//int
//read_queue(QUEUE* queue, void* packet/*[maxlength]*/, int maxlength)
//{
//	unsigned char* storage = (unsigned char*)(queue + 1);
//	int length;
//
//	if(maxlength < 0) {
//		DIE();
//	}
//
//	/* キューが空でないか？ */
//	if(!queue->size) {
//		return -1;
//	}
//
//	/* キューの先頭のパケットサイズを取得します。 */
//	if(queue->size < sizeof(int)) {
//		DIE(); /* キュー破損？ */
//	}
//	length = LEWORD(storage);
//	if((length < 0) || ((int)(sizeof(int) + length) > queue->size)) {
//		DIE(); /* キュー破損？ */
//	}
//
//	/* 指定されたメモリ領域に格納できるか？ */
//	if(length > maxlength) {
//		return -1;
//	}
//
//	/* キューの先頭のパケットを、指定されたメモリ領域にコピーします。
//	 * ただし、packet=NULLならば、読み出したパケットデータを破棄します。
//	 */
//	if(packet) {
//		memcpy(packet, storage + sizeof(int), length);
//	}
//
//	/* キューの先頭のパケットを削除し、その分、キューを詰めます。 */
//	queue->size -= (sizeof(int) + length);
//	memmove(storage, storage + (sizeof(int) + length), queue->size);
//
//	return length;
//}
//
//const void*
//peek_queue(QUEUE* queue, int* _length)
//{
//	unsigned char* storage = (unsigned char*)(queue + 1);
//	int length;
//
//	/* キューが空か？ */
//	if(!queue->size) {
//		return NULL;
//	}
//
//	/* キューの先頭のパケットサイズを取得します。 */
//	if(queue->size < sizeof(int)) {
//		DIE(); /* キュー破損？ */
//	}
//	length = LEWORD(storage);
//	if((length < 0) || ((int)(sizeof(int) + length) > queue->size)) {
//		DIE(); /* キュー破損？ */
//	}
//
//	/* パケットサイズを格納します。 */
//	if(_length) {
//		*_length = length;
//	}
//
//	/* パケットデータの先頭アドレスを返します。 */
//	return storage + sizeof(int);
//}
//
//int
//queue_space(QUEUE* queue)
//{
//	int space = queue->capacity - queue->size - sizeof(int);
//	if(space < 0) {
//		space = 0;
//	}
//	return space;
//}
//}}2015/01/06削除:「ユーティリティ：任意長パケットキュー」を、clipmisc.*⇒clipque.*へ分離しました。

//{{2015/01/06削除:「ユーティリティ：リングバッファ」を、clipmisc.*⇒clipbuf.*へ分離しました。
///*****************************************************************************
// *	ユーティリティ：リングバッファ
// *****************************************************************************/
//
//BUFFER*
//create_buffer(int capacity)
//{
//	BUFFER* buffer;
//
//	if(capacity < 0) {
//		DIE();
//	}
//
//	/* ヘッダとストレージのメモリを確保します。 */
//	buffer = malloc(sizeof(BUFFER) + capacity);
//	if(!buffer) {
//		DIE(); /* メモリ不足 */
//	}
//
//	/* ヘッダを初期化します。 */
//	buffer->capacity = capacity;
//	buffer->size = 0;
//
//	return buffer;
//}
//
//void
//delete_buffer(BUFFER* buffer)
//{
//	/* ヘッダとストレージのメモリを開放します。 */
//	free(buffer);
//}
//
//void
//clear_buffer(BUFFER* buffer)
//{
//	buffer->size = 0;
//}
//
//int
//write_buffer(BUFFER* buffer, const void* data/*[length]*/, int length)
//{
//	unsigned char* storage = (unsigned char*)(buffer + 1);
//
//	if(length < 0) {
//		DIE();
//	}
//
//	/* 書き込むデータ長を、ストレージの空き容量へ切り詰めます。 */
//	if(length > (buffer->capacity - buffer->size)) {
//		length = (buffer->capacity - buffer->size);
//	}
//
//	/* ストレージへ、データを書き込みます。 */
//	memcpy(storage + buffer->size, data, length);
//	buffer->size += length;
//
//	/* 実際に書き込んだデータ長を返します。 */
//	return length;
//}
//
//int
//read_buffer(BUFFER* buffer, void* data/*[maxlength]*/, int maxlength)
//{
//	unsigned char* storage = (unsigned char*)(buffer + 1);
//	int length;
//
//	if(maxlength < 0) {
//		DIE();
//	}
//
//	/* 読み出すデータ長を、指定されたメモリ領域サイズへ切り詰めます。 */
//	length = maxlength < buffer->size
//	       ? maxlength : buffer->size;
//
//	/* ストレージ先頭のデータを、指定されたメモリ領域にコピーします。
//	 * ただし、data=NULLならば、読み出したデータを破棄します。
//	 */
//	if(data) {
//		memcpy(data, storage, length);
//	}
//
//	/* ストレージ先頭のデータを削除し、その分、ストレージを詰めます。 */
//	buffer->size -= length;
//	memmove(storage, storage + length, buffer->size);
//
//	/* 実際に読み出したデータ長を返します。 */
//	return length;
//}
//
//const void*
//peek_buffer(BUFFER* buffer, int* length)
//{
//	/* データ長を格納します。 */
//	if(length) {
//		*length = buffer->size;
//	}
//
//	/* ストレージの先頭アドレスを返します。 */
//	return buffer + 1;
//}
//
//int
//buffer_space(BUFFER* buffer)
//{
//	/* 書き込み可能な最大データ長は、ストレージの空き容量です。 */
//	return buffer->capacity - buffer->size;
//}
//}}2015/01/06削除:「ユーティリティ：リングバッファ」を、clipmisc.*⇒clipbuf.*へ分離しました。

//{{2015/01/06削除:「ユーティリティ：ダブルリンクリスト」を、clipmisc.*⇒clipdlst.*へ分離しました。
///*****************************************************************************
// *	ユーティリティ：ダブルリンクリスト
// *****************************************************************************/
//
//void
//InitializeListHead(LIST_ENTRY* ListHead)
//{
//	ListHead->Flink = ListHead->Blink = ListHead;
//}
//
//int
//IsListEmpty(LIST_ENTRY* ListHead)
//{
//	return ListHead->Flink == ListHead;
//}
//
//LIST_ENTRY*
//RemoveHeadList(LIST_ENTRY* ListHead)
//{
//	LIST_ENTRY* Head = ListHead->Flink;
//	RemoveEntryList(Head);
//	return Head;
//}
//
//LIST_ENTRY*
//RemoveTailList(LIST_ENTRY* ListHead)
//{
//	LIST_ENTRY* Tail = ListHead->Blink;
//	RemoveEntryList(Tail);
//	return Tail;
//}
//
//void
//RemoveEntryList(LIST_ENTRY* Entry)
//{
//	LIST_ENTRY* Flink = Entry->Flink;
//	LIST_ENTRY* Blink = Entry->Blink;
//	Blink->Flink = Flink;
//	Flink->Blink = Blink;
//}
//
//void
//InsertHeadList(LIST_ENTRY* ListHead, LIST_ENTRY* Entry)
//{
//	LIST_ENTRY* Head = ListHead->Flink;
//	Entry->Flink = Head;
//	Entry->Blink = ListHead;
//	ListHead->Flink = Head->Blink = Entry;
//}
//
//void
//InsertTailList(LIST_ENTRY* ListHead, LIST_ENTRY* Entry)
//{
//	LIST_ENTRY* Tail = ListHead->Blink;
//	Entry->Flink = ListHead;
//	Entry->Blink = Tail;
//	Tail->Flink = ListHead->Blink = Entry;
//}
//}}2015/01/06削除:「ユーティリティ：ダブルリンクリスト」を、clipmisc.*⇒clipdlst.*へ分離しました。

//{{2015/01/06削除:「ユーティリティ：検索」を、clipmisc.*⇒clipmatc.*へ分離しました。
///*****************************************************************************
// *	ユーティリティ：検索
// *****************************************************************************/
//
//#ifndef PIECE
//void*
//quick_search(const void* _mem1/*[len1]*/, int len1, const void* _mem2/*[len2]*/, int len2)
//{
//	int tbl[256]; /* スタックを1KB消費します */
//	unsigned char* mem1 = (unsigned char*)_mem1;
//	unsigned char* mem2 = (unsigned char*)_mem2;
//	unsigned char* tmp1;
//	unsigned char* tmp2;
//	unsigned char* lim1;
//	int i;
//
//	/* 空パターン検索は、データ先頭に一致する */
//	if(!len2) {
//		return mem1;
//	}
//
//	/* データの比較窓の、最大アドレスを求める */
//	len1 -= len2;
//	if(len1 < 0) {
//		return NULL;
//	}
//	lim1 = mem1 + len1; /* = mem1+(len1-len2) */
//
//	/* スキップテーブルを初期化する */
//	i = 0;
//	do {
//		tbl[i] = -1;
//	} while(++i < 256);
//	i = 0;
//	do {
//		tbl[mem2[i]] = i;
//	} while(++i < len2);
//
//	/* 検索ループ */
//	do {
//		/*{{memcmp(mem1,mem2,len2)*/
//		tmp1 = mem1;
//		tmp2 = mem2;
//		i = len2;
//		while(*tmp1++ == *tmp2++) {
//			if(!--i) {
//				return mem1;
//			}
//		}
//		/*}}memcmp(mem1,mem2,len2)*/
//
//		/* 比較窓の次の文字を参照して、比較窓の位置をずらす */
//		if(mem1 == lim1) { /* mem1の末尾+1へのアクセス防止 */
//			break;
//		}
//		mem1 += len2;
//		mem1 -= tbl[*mem1];
//	} while(mem1 <= lim1);
//
//	return NULL;
//}
//#else /*PIECE*/
//void* quick_search(const void* _mem1/*[len1]*/, int len1, const void* _mem2/*[len2]*/, int len2);
//asm("
//		.code
//		.align		1
//		.global		quick_search
//quick_search:
//		xsub		%sp, %sp, 1024			;// %sp  := tbl
//		ld.w		%r4, %sp			;// %r4  := tbl
//		;//---------------------------------------------;//
//		cmp		%r15, 0				;// if(!len2)
//		jreq		quick_search_RET0		;//   return NULL
//		;//---------------------------------------------;//
//		sub		%r13, %r15			;// %r13 := len1 -= len2
//		jrlt		quick_search_RET0		;// if(len1 < 0) return NULL
//		add		%r13, %r12			;// %r13 := lim1 = mem1 + len1
//		;//---------------------------------------------;//
//		ld.w		%r5, %sp			;// %r5  := ptr = tbl
//		ld.w		%r6, -1				;// %r6  := -1
//		xld.w		%r7, 256			;// %r7  := cnt = 256
//		 ld.w		[%r5]+, %r6			;// do { *ptr++ = -1
//		 sub		%r7, 1				;//      %r7  := cnt--
//		jrne		-2				;// } while(cnt)
//		;//---------------------------------------------;//
//		ld.w		%r5, %r14			;// %r5  := ptr = mem2
//		ld.w		%r6, 0				;// %r6  := i = 0
//		 ld.ub		%r7, [%r5]+			;// do { %r7  :=      *ptr++
//		 sla		%r7, 2				;//      %r7  :=      *ptr++ * sizeof(int)
//		 add		%r7, %r4			;//      %r7  := &tbl[*ptr++]
//		 ld.w		[%r7], %r6			;//               tbl[*ptr++] = i
//		 add		%r6, 1				;//      %r6  := i++
//		 cmp		%r6, %r15			;//
//		jrne		-6				;// } while(i != len2)
//		;//---------------------------------------------;//
//quick_search_LOOP:						;// do {
//		ld.w		%r5, %r12			;//   %r5  := tmp1 = mem1
//		ld.w		%r6, %r14			;//   %r6  := tmp2 = mem2
//		ld.w		%r7, %r15			;//   %r7  := i    = len2
//		 ld.ub		%r10, [%r5]+			;//   do { %r10 := *tmp1++
//		 ld.ub		%r11, [%r6]+			;//        %r11 := *tmp2++
//		 cmp		%r10, %r11			;//        if(*tmp1++ != *tmp2++)
//		 jrne		quick_search_NEXT		;//          goto NEXT
//		 sub		%r7, 1				;//        %r7  := i--
//		jrne		-5				;//   } while(i)
//		jp.d		quick_search_RET		;//   return mem1
//		ld.w		%r10, %r12			;//   %r10 := mem1				*delay*
//quick_search_NEXT:						;//
//		cmp		%r12, %r13			;//   if(mem1 == lim1)
//		jreq		quick_search_RET0		;//     return NULL
//		add		%r12, %r15			;//   %r12 :=              mem1 += len2
//		ld.ub		%r5, [%r12]			;//   %r5  :=             *mem1
//		sla		%r5, 2				;//   %r5  :=             *mem1 * sizeof(int)	!INTERLOCK!
//		add		%r5, %r4			;//   %r5  :=        &tbl[*mem1]
//		ld.w		%r5, [%r5]			;//   %r5  :=         tbl[*mem1]
//		sub		%r12, %r5			;//   %r12 := mem1 -= tbl[*mem1]		!INTERLOCK!
//		cmp		%r12, %r13			;//
//		jrle		quick_search_LOOP		;// } while(mem1 <= lim1)
//		;//---------------------------------------------;//
//quick_search_RET0:
//		ld.w		%r10, 0
//quick_search_RET:
//		xadd		%sp, %sp, 1024
//		ret
//");
//#endif /*PIECE*/
//
///*---------------------------------------------------------------------------*/
//
//static int matchhere(const char* regexp, const char* text);
//static int matchstar(int c, const char* regexp, const char* text);
//
///* match: search for regexp anywhere in text */
////int match(const char* regexp, const char* text) {
////↓ * Mon Jan 03 22:48:46 JST 2011 Naoyuki Sawa
////↓ - match()→VERY_simple_RegEx_matching()に名前変更しました。
//int VERY_simple_RegEx_matching(const char* regexp, const char* text) {
//	if(regexp[0] == '^') {
//		return matchhere(regexp + 1, text);
//	}
//	do { /* must look even if string is empty */
//		if(matchhere(regexp, text)) {
//			return 1;
//		}
//	} while(*text++ != '\0');
//	return 0;
//}
//
///* matchhere: search for regexp at beginning of text */
//static int matchhere(const char* regexp, const char* text) {
//	if(regexp[0] == '\0') {
//		return 1;
//	}
//	if(regexp[1] == '*') {
//		return matchstar(regexp[0], regexp + 2, text);
//	}
//	if((regexp[0] == '$') && (regexp[1] == '\0')) {
//		return *text == '\0';
//	}
//	if((*text != '\0') && ((regexp[0] == '.') || (regexp[0] == *text))) {
//		return matchhere(regexp + 1, text + 1);
//	}
//	return 0;
//}
//
///* matchstar: search for c*regexp at beginning of text */
//static int matchstar(int c, const char* regexp, const char* text) {
//	do { /* a * matches zero or more instances */
//		if(matchhere(regexp, text)) {
//			return 1;
//		}
//	} while((*text != '\0') && ((*text++ == c) || (c == '.')));
//	return 0;
//}
//}}2015/01/06削除:「ユーティリティ：検索」を、clipmisc.*⇒clipmatc.*へ分離しました。

//{{2015/01/06削除:乱数関連の宣言と実装を、clipmisc.*⇒cliprnd.*へ分離しました。
///*****************************************************************************
// *	ユーティリティ：範囲乱数
// *****************************************************************************/
//
//#ifndef PIECE
//unsigned minimum_mask_greater_than_or_equal_to(unsigned x) {
//	unsigned y = 0;
//	while(y < x) {
//		y = (y << 1) | 1;
//	}
//	return y;
//}
//unsigned random_value_less_than_or_equal_to(unsigned x, unsigned (*generator)(void* param), void* param) {
//	unsigned mask = minimum_mask_greater_than_or_equal_to(x);
//	unsigned y;
//	do {
//		y = (*generator)(param) & mask;
//	} while(y > x);
//	return  y;
//}
//#else /*PIECE*/
//asm("
//		.align		1
//		.global		minimum_mask_greater_than_or_equal_to
//		.global		random_value_less_than_or_equal_to
//		;//-----------------------------------------------------;//
//minimum_mask_greater_than_or_equal_to:
//		;//							;// %r12  := x     ┌────────────────┐
//		ld.w		%r10, 0					;// %r10  := y = 0 │  ┌────────┐          │
//		;//							;// do {           │  ↓                │          │
//		cmp		%r10, %r12				;//     %psr[C] := c = (y < x) ? 1 : 0   │          │
//		jrult.d		-1					;//                              ┌───┴───┐  │
//		adc		%r10, %r10				;//     %psr[C] := y[31], %r10 := (y[30:0]<<1) | c ←┘		*delay*
//		;//							;// } while(c == 1)  └──────┐
//		adc		%r10, %r8				;// %r10 := (y[30:0]<<1) | y[31] ←┘
//		ret.d							;// return   y[31:0]
//		rr		%r10, 1					;// %r10 :=  y[31:0]						*delay*
//		;//-----------------------------------------------------;//
//random_value_less_than_or_equal_to:
//		pushn		%r3
//		ld.w		%r0, %r12				;// %r0  := x
//		ld.w		%r1, %r13				;// %r1  := generator
//		call.d		minimum_mask_greater_than_or_equal_to	;// %r10 := mask = minimum_mask_greater_than_or_equal_to(x)
//		ld.w		%r2, %r14				;// %r2  := param						*delay*
//		ld.w		%r3, %r10				;// %r3  := mask
//		;//							;// do {
//		call.d		%r1					;//   %r10 := y = (*generator)(param)
//		 ld.w		%r12, %r2				;//   %r12 :=                  param				*delay*
//		 and		%r10, %r3				;//   %r10 := y &= mask
//		 cmp		%r10, %r0				;// } while(y > x)
//		jrugt		-4
//		popn		%r3
//		ret
//		;//-----------------------------------------------------;//
//");
//#endif/*PIECE*/
//}}2015/01/06削除:乱数関連の宣言と実装を、clipmisc.*⇒cliprnd.*へ分離しました。

//{{2014/10/11削除:strtrim(),strescape(),strcompress()を、clipmisc.h,cからclipstr.h,cへ移動しました。今後は「ユーティリティ：文字列操作」はclipstr.h,cに追加してください。
///*****************************************************************************
// *	ユーティリティ：文字列操作
// *****************************************************************************/
//static const char strtrim_reject[]="\t\n\v\f\r ";//isspace()と同等	//asmブロックだけから参照する'定数'は、__attribute__((unused))を宣言しなくても警告が出ないようです。一方、asmブロックだけから参照する'変数'と'関数'は、__attribute__((unused))を宣言しなければ警告が出ます。
//#ifndef PIECE
//char* strtrim(const char* s, int mode, const char* reject) {
//	int c;
//	char *t, *u;
//	if(!reject) { reject = strtrim_reject; }
//	switch(mode) {
//	case 0://両端にある指定文字を除去する
//		t = strtrim(s, 1, reject);	//左端にある指定文字を除去して、途中の文字列を作成する。
//		u = strtrim(t, 2, reject);	//右端にある指定文字を除去して、結果の文字列を作成する。
//		free(t);			//左端にある指定文字を除去した、途中の文字列を削除する。
//		break;
//	case 1://左端にある指定文字を除去する
//		while(strchr(reject, *s)) { s++; }	//指定文字以外が見つかるまで、次の文字へ進める。
//		if(!(u = strdup(s))) { DIE(); }		//結果の文字列を作成する。
//		break;
//	case 2://右端にある指定文字を除去する
//		t = strchr(s, '\0');					//終端のnulの位置へ進める。
//		do { t--; } while((t >= s) && strchr(reject, *t));	//前の文字へ戻す。先頭を超えた,又は,指定文字以外が見つかったら抜ける。
//		if(!(u = strndup(s, t - s + 1))) { DIE(); }		//結果の文字列を作成する。tは1文字分前へ戻り過ぎていることに注意せよ。
//		break;
//	case 3://文字列内にある全ての指定文字を除去する
//		if(!(t = u = strdup(s))) { DIE(); }				//文字列を複製する。
//		while((c = *t++ = *s++)) { if(strchr(reject, c)) { t--; } }	//指定文字以外を前詰めでコピーする。このcaseのみ、結果の文字列より大きなメモリのままになるが、使用頻度が低いと思うので許容することにした。
//		break;
//	default:
//		DIE();
//	}
//	return u;
//}
//#else //PIECE
////アセンブラ化した目的は、コードサイズの低減です。
////コードサイズが、(C言語版=272バイト)⇒(Asm版=188バイト)に小さくなりました。
////処理速度は、メモリ確保の処理に要する時間が大きいので、元々期待できません。
//char* strtrim(const char* s, int mode, const char* reject);
//asm("
//		.code
//		.align		1
//		.global		strtrim
//strtrim:
//		pushn		%r3
//		;//%r12 := s
//		;//%r13 := mode
//		;//%r14 := reject
//		cmp		%r14, 0				;//if(!reject) { reject = strtrim_reject }
//		jrne.d		5				;//
//		 cmp		%r13, 3				;//%psr := ((unsigned)mode <=> (unsigned)3)		─┐	*delay*
//		 ext		      strtrim_reject@h		;//							　│
//		 ext		      strtrim_reject@m		;//							　│
//		 ld.w		%r14, strtrim_reject@l		;//							　│
//		jrugt		strtrim_DIE			;//if((unsigned)mode >  (unsigned)3) { goto DIE() }	←┘
//		ld.w		%r0, %r12			;//%r0  := s
//		jreq.d		strtrim_case_3			;//if((unsigned)mode == (unsigned)3) { goto case_3 }
//		ld.w		%r1, %r14			;//%r1  := reject						*delay*
//		cmp		%r13, 1				;//%psr := ((unsigned)mode <=> (unsigned)1)
//		jrugt		strtrim_case_2			;//if((unsigned)mode >  (unsigned)1) { goto case_2 }
//		jreq		strtrim_case_1			;//if((unsigned)mode == (unsigned)1) { goto case_1 }
//		;//---------------------------------------------;//
//;//strtrim_case_0:
//		;//%r0  := s			←使わない
//		;//%r1  := reject
//		;//%r12 := s
//		;//%r14 := reject
//		call.d		strtrim				;//%r10 := t = strtrim(s, 1, reject)
//		ld.w		%r13, 1				;//%r13 :=                1					*delay*
//		ld.w		%r2, %r10			;//%r2  := t
//		ld.w		%r12, %r2			;//%r12 :=             t
//		ld.w		%r13, 2				;//%r13 :=                2
//		call.d		strtrim				;//%r10 := u = strtrim(t, 2, reject)
//		ld.w		%r14, %r1			;//%r14 :=                   reject				*delay*
//		ld.w		%r3, %r10			;//%r3  := u
//		xcall.d		free				;//   free(t)
//		ld.w		%r12, %r2			;//%r12 := t							*delay*
//		jp		strtrim_return_u		;//return  u
//		;//---------------------------------------------;//
//strtrim_case_1:	
//		;//%r0  := s
//		;//%r1  := reject
//		;//%r12 := s			←使わない
//		;//%r14 := reject		←使わない
//strtrim_case_1_L10:						;//do {
//		ld.b		%r13, [%r0]+			;//%r13 :=                *s++
//		xcall.d		strchr				;//%r10 := strchr(reject, *s++)
//		ld.w		%r12, %r1			;//%r12 :=        reject					*delay*
//		cmp		%r10, 0				;//} while(strchr(reject, *s++))
//		jrne		strtrim_case_1_L10		;//
//		sub		%r0, 1				;//%r0  :=                 s--
//		jp.d		strtrim_case_2_L30		;//goto case_2_L30
//		ld.w		%r13, -1			;//%r13 := n = SIZE_MAX						*delay*
//		;//---------------------------------------------;//
//strtrim_case_2:
//		;//%r0  := s
//		;//%r1  := reject
//		;//%r12 := s
//		;//%r14 := reject		←使わない
//		xcall.d		strchr				;//%r10 := t = strchr(s, '￥0')
//		ld.w		%r13, 0				;//%r13 :=               '￥0'					*delay*
//		ld.w		%r2, %r10			;//%r2  := t
//strtrim_case_2_L10:						;//do {
//		cmp		%r2, %r0			;//     if(t-- <= s) { break }
//		jrule.d		strtrim_case_2_L20		;//
//		sub		%r2, 1				;//%r2  := t--							*delay*
//		ld.b		%r13, [%r2]			;//
//		xcall.d		strchr				;//%r10 := strchr(reject, *t)
//		ld.w		%r12, %r1			;//%r12 :=        reject					*delay*
//		cmp		%r10, 0				;//} while(strchr(reject, *t))
//		jrne		strtrim_case_2_L10		;//
//strtrim_case_2_L20:						;//
//		ld.w		%r13, %r2			;//%r13 :=     t
//		sub		%r13, %r0			;//%r13 :=     t - s
//		add		%r13, 1				;//%r13 := n = t - s + 1
//strtrim_case_2_L30:						;//
//		xcall.d		strndup				;//%r10 := u = strndup(s, n)
//		ld.w		%r12, %r0			;//%r12 :=             s					*delay*
//		cmp		%r10, 0				;//    if(!u) { DIE() }
//		jreq		strtrim_DIE			;//
//		jp.d		strtrim_return_u		;//return  u
//		ld.w		%r3, %r10			;//%r3  := u							*delay*
//		;//---------------------------------------------;//
//strtrim_case_3:
//		;//%r0  := s
//		;//%r1  := reject
//		;//%r12 := s
//		;//%r14 := reject		←使わない
//		xcall		strdup				;//%r10 := u = strdup(s, n)
//		cmp		%r10, 0				;//    if(!u) { DIE() }
//		jreq		strtrim_DIE			;//
//		ld.w		%r2, %r10			;//%r2  := t
//		ld.w		%r3, %r10			;//%r2  := u
//strtrim_case_3_L10:						;//for(;;) {
//		ld.b		%r13, [%r0]+			;//%r13 := c = *s++
//		ld.b		[%r2]+, %r13			;//*t++  = c
//		cmp		%r13, 0				;//    if(!c) { return  u }
//		jreq		strtrim_return_u		;//
//		xcall.d		strchr				;//%r10 := p = strchr(reject, c)
//		ld.w		%r12, %r1			;//%r12 :=            reject					*delay*
//		cmp		%r8, %r10			;//%psr(C) :=   !!p								┐
//		jp.d		strtrim_case_3_L10		;//										├「if(strchr(reject, c)) { t--; }」を条件分岐無しで実装する工夫
//		sbc		%r2, %r8			;//%r2  := t -= !!p						*delay*		┘
//		;//---------------------------------------------;//
//strtrim_return_u:
//		;//%r3  := u
//		ld.w		%r10, %r3			;//%r10 := u
//		popn		%r3				;//
//		ret						;//return  u
//");
//static void __attribute__((noreturn,unused))/*asmブロックから参照*/ strtrim_DIE() { DIE(); }
//#endif//PIECE
///*---------------------------------------------------------------------------*/
////アセンブラ化した目的は、コードサイズの低減です。
////コードサイズが、(C言語版=528バイト)⇒(Asm版=456バイト)に小さくなりました。(TBL_strescape[],strescape(),strcompress()の合計サイズ)
////処理速度は、メモリ確保の処理に要する時間が大きいので、元々期待できません。
//#ifdef  __GNUC__
////GCCは「\e」(非標準のエスケープシーケンス)に対応している。
//#define SIZE_strescape 13//─────────────────┐
//static const char TBL_strescape[]={//                        ↓		//asmブロックだけから参照する'定数'は、__attribute__((unused))を宣言しなくても警告が出ないようです。一方、asmブロックだけから参照する'変数'と'関数'は、__attribute__((unused))を宣言しなければ警告が出ます。
////1    2    3    4    5    6    7    8    9   10   11   12   13
//'\a','\b','\e','\f','\n','\r','\t','\v','\?','\'','\"','\\','\0',	//末尾の'\0'はstrescape()  で行うstrchr()の終端用です。エスケープ対象文字ではありません。
// 'a', 'b', 'e', 'f', 'n', 'r', 't', 'v','\?','\'','\"','\\','\0'};	//末尾の'\0'はstrcompress()で行うstrchr()の終端用です。エスケープ対象文字ではありません。
//#else //__GNUC__
////VC++6.0は「\e」(非標準のエスケープシーケンス)に対応していない。
//#define SIZE_strescape 12//─────────────────┐
//static const char TBL_strescape[]={//                        ↓
////1    2         3    4    5    6    7    8    9   10   11   12
//'\a','\b',     '\f','\n','\r','\t','\v','\?','\'','\"','\\','\0',	//末尾の'\0'はstrescape()  で行うstrchr()の終端用です。エスケープ対象文字ではありません。
// 'a', 'b',      'f', 'n', 'r', 't', 'v','\?','\'','\"','\\','\0'};	//末尾の'\0'はstrcompress()で行うstrchr()の終端用です。エスケープ対象文字ではありません。
//#endif//__GNUC__
//#ifndef PIECE
//char* strescape(const char* s, const char* need_escape) {
//	char* r = NULL;
//	for(;;) {//1周目で文字数を数え、2周目で文字を格納する
//		const char *t = s, *p;
//		      char *u = r;
//		int c;
//		while((c = *t++)) {
//			/* C言語のエスケープシーケンス */
//			if((p = strchr(TBL_strescape, c))) {		//テーブルの前半から検索
//				if(r/*2周目*/) {
//					u[0] = '\\';
//					u[1] = *(p + SIZE_strescape);	//テーブルの後半へシフト
//				}
//				u += 2;
//			/* アプリケーション定義のエスケープが必要な文字 */
//			} else if(need_escape && strchr(need_escape, c)) {
//				if(r/*2周目*/) {
//					u[0] = '\\';
//					u[1] = c;
//				}
//				u += 2;
//			/* 印字可能でない文字 */
//			} else if(!isprint(c)) {
//				if(r/*2周目*/) {
//					u[0] = '\\';
//					u[1] = '0' + ((c >> 6) & 3);	//┐
//					u[2] = '0' + ((c >> 3) & 7);	//├この後に'0'～'7'が続く場合のために常に最大の3桁を出力しておく。
//					u[3] = '0' + ((c >> 0) & 7);	//┘
//				}
//				u += 4;
//			/* それ以外 */
//			} else {
//				if(r/*2周目*/) {
//					u[0] = c;
//				}
//				u += 1;
//			}
//		}
//		if(r/*2周目*/) {
//			u[0] = '\0';
//			return r;
//		}
//		if(!(r = malloc((int)u + 1/*nul*/))) { DIE(); }
//	}
//}
//char* strcompress(const char* s, const char** endptr, const char* delim) {
//	char* r = NULL;
//	for(;;) {//1周目で文字数を数え、2周目で文字を格納する
//		const char *t = s, *p;
//		      char *u = r;
//		int c;
//		while((c = *t++) && !(delim && strchr(delim, c))) {
//			if(c != '\\') { goto L_COPY; }
//			/* '\'にnulが続く場合、'\'を破棄して処理2.を行い終了する。('\'にnulが続くのは'エスケープされた文字列'として不正だが、文字列の終端を超えないように最低限の対策を行うことにした)
//			 * 「strchr(～,'\0')」は必ず非NULLの結果になるので、strchr()を用いる判定よりも先に行わなければならないことに注意せよ。 */
//			if(!(c = *t++)) { break; }
//			/* '\'に続くC言語のエスケープシーケンス文字を、1文字に変換して出力する。 */
//			if((p = strchr(TBL_strescape + SIZE_strescape, c))) {	//テーブルの後半から検索
//				if(r/*2周目*/) { *u = *(p - SIZE_strescape); }	//テーブルの前半へシフト
//				u++;
//			/* '\'に続く8進表記(1～3桁)を、1文字に変換して出力する。 */
//			} else if((c >= '0') && (c <= '7')) {
//				int x = (c - '0');
//				if(((c = *t) >= '0') && (c <= '7')) {
//					x = (x << 3) | (c - '0'), t++;
//					if(((c = *t) >= '0') && (c <= '7')) {
//						x = (x << 3) | (c - '0'), t++;
//					}
//				}
//				if(r/*2周目*/) { *u = x; }
//				u++;
//			/* '\'に続く16進表記(1～∞桁)を、1文字に変換して出力する。 */
//			} else if((c == 'x') || (c == 'X')) {
//				int x = strtoul(t, (char**)&t, 16);
//				if(r/*2周目*/) { *u = x; }
//				u++;
//			/* 行の継続 */
//			} else if(c == '\n') {
//				/** no job **/
//			/* '\'に続くそれ以外の文字を、'\'を削除して文字のみに変換して出力する。('アプリケーション定義のエスケープが必要な文字'も含む) */
//			} else {
//L_COPY:				if(r/*2周目*/) { *u = c; }
//				u++;
//			}
//		}
//		if(r/*2周目*/) {
//			if(endptr) { *endptr = t - 1; }
//			*u = '\0';
//			return r;
//		}
//		if(!(r = malloc((int)u + 1/*nul*/))) { DIE(); }
//	}
//}
//#else //PIECE
//char* strescape(const char* s, const char* need_escape);
//asm("
//		.code
//		.align		1
//		.global		strescape
//strescape:
//		pushn		%r3
//		xsub		%sp, %sp, 8
//		xld.w		[%sp+4], %r12			;//[%sp+4] := s
//		xld.w		[%sp+0], %r13			;//[%sp+0] := need_escape
//		ld.w		%r0, 0				;//%r0  := r = NULL
//		;//---------------------------------------------;//
//strescape_L10:							;//for(;;) {
//		xld.w		%r1, [%sp+4]			;//  %r1  := t = s
//		ld.w		%r2, %r0			;//  %r2  := u = r
//		;//---------------------------------------------;//
//strescape_L20:							;//
//		ld.b		%r3, [%r1]+			;//  %r3  := c = *t++
//		cmp		%r3, 0				;//  if(!c) {
//		jrne		strescape_L30
//		cmp		%r0, 0				;//    if(!r) {
//		jrne		strescape_L25
//		add		%r2, 1				;//      %r2  :=            u + 1
//		xcall.d		malloc				;//      %r10 := r = malloc(u + 1)
//		ld.w		%r12, %r2			;//      %r12 :=            u + 1				*delay*
//		cmp		%r10, 0				;//      if(!r) { DIE() }
//		jreq		strescape_DIE
//		jp.d		strescape_L10
//		ld.w		%r0, %r10			;//      %r0  := r						*delay*
//strescape_L25:							;//    } else {
//		ld.b		[%r2], %r8			;//      *u    = '￥0'
//		ld.w		%r10, %r0			;//      return  r
//		xadd		%sp, %sp, 8
//		popn		%r3
//		ret						;//    }
//		;//---------------------------------------------;//  } else {
//strescape_L30:
//		xld.w		%r12, TBL_strescape		;//    %r12 :=            TBL_strescape
//		xcall.d		strchr				;//    %r10 := p = strchr(TBL_strescape, c))
//		ld.w		%r13, %r3			;//    %r13 :=                           c			*delay*
//		cmp		%r10, 0				;//    if(    (p = strchr(TBL_strescape, c)) {
//		jreq		strescape_L40
//		cmp		%r0, 0				;//      if(!r) { u += 2
//		jreq		strescape_ADD_2			;//      } else {
//		xld.w		%r9, 92				;//        %r9  := '￥'
//		ld.b		[%r2]+, %r9			;//        *u++  = '￥'
//		add		%r10, 13			;//        %r10 :=   p + SIZE_strescape
//		ld.b		%r9, [%r10]			;//        %r9  := *(p + SIZE_strescape)
//		ld.b		[%r2]+, %r9			;//        *u++  = *(p + SIZE_strescape)
//		jp		strescape_L20			;//      }
//		;//---------------------------------------------;//    } else
//strescape_L40:
//		xld.w		%r12, [%sp+0]			;//    %r12 := need_escape
//		cmp		%r12, 0				;//    if((    need_escape) &&
//		jreq		strescape_L50
//		xcall.d		strchr				;//    strchr( need_escape, c)) {
//		ld.w		%r13, %r3			;//    %r13 :=              c					*delay*
//		cmp		%r10, 0
//		jreq		strescape_L50
//		cmp		%r0, 0				;//      if(!r) { u += 2
//		jreq		strescape_ADD_2			;//      } else {
//		xld.w		%r9, 92				;//        %r9  := '￥'
//		ld.b		[%r2]+, %r9			;//        *u++  = '￥'
//		ld.b		[%r2]+, %r3			;//        *u++  = c
//		jp		strescape_L20			;//      }
//		;//---------------------------------------------;//    } else
//strescape_L50:
//		xcall.d		isprint				;//    if(isprint(c)) {
//		ld.w		%r12, %r3			;//    %r12 :=    c						*delay*
//		cmp		%r10, 0
//		jrne		strescape_L60
//		cmp		%r0, 0				;//      if(!r) { u += 4
//		jreq		strescape_ADD_4			;//      } else {
//		xld.w		%r9, 92				;//        %r9  := '￥'
//		ld.b		[%r2]+, %r9			;//        *u++  = '￥'
//		xand		%r5, %r3, 7			;//        %r5  :=        (c >> 0) & 7
//		add		%r5, 48				;//        %r5  := '0' + ((c >> 0) & 7)
//		sra		%r3, 3				;//        %r3  :=         c >> 3
//		xand		%r4, %r3, 7			;//        %r5  :=        (c >> 3) & 7
//		add		%r4, 48				;//        %r5  := '0' + ((c >> 3) & 7
//		sra		%r3, 3				;//        %r3  :=         c >> 6
//		xand		%r3, %r3, 3			;//        %r3  :=        (c >> 6) & 3
//		add		%r3, 48				;//        %r3  := '0' + ((c >> 6) & 3
//		ld.b		[%r2]+, %r3			;//        *u++  = '0' + ((c >> 6) & 3
//		ld.b		[%r2]+, %r4			;//        *u++  = '0' + ((c >> 3) & 7
//		ld.b		[%r2]+, %r5			;//        *u++  = '0' + ((c >> 0) & 7
//		jp		strescape_L20			;//      }
//		;//---------------------------------------------;//    } else {
//strescape_L60:
//		cmp		%r0, 0				;//      if(!r) { u += 1
//		jreq		strescape_ADD_1			;//      } else {
//		ld.b		[%r2]+, %r3			;//        *u++  = c
//		jp		strescape_L20			;//      }
//		;//---------------------------------------------;//} } }
//strescape_ADD_4:
//		add		%r2, 2				;//%r2  := u += 2 + 1 + 1
//strescape_ADD_2:
//		add		%r2, 1				;//%r2  := u +=     1 + 1
//strescape_ADD_1:
//		jp.d		strescape_L20
//		add		%r2, 1				;//%r2  := u +=         1					*delay*
//");
//static void __attribute__((noreturn,unused))/*asmブロックから参照*/ strescape_DIE() { DIE(); }
//char* strcompress(const char* s, const char** endptr, const char* delim);
//asm("
//		.code
//		.align		1
//		.global		strcompress
//strcompress:
//		pushn		%r3
//		xsub		%sp, %sp, 16
//		xld.w		[%sp+4], %r12			;//[%sp+4]  := s
//		xld.w		[%sp+8], %r13			;//[%sp+8]  := endptr
//		xld.w		[%sp+12], %r14			;//[%sp+12] := delim
//		ld.w		%r0, 0				;//%r0  := r = NULL
//		;//---------------------------------------------;//
//strcompress_L10:						;//for(;;) {
//		xld.w		%r1, [%sp+4]			;//  %r1  := t = s
//		ld.w		%r2, %r0			;//  %r2  := u = r
//		;//---------------------------------------------;//
//strcompress_L20:						;//
//		ld.b		%r3, [%r1]+			;//  %r3  := c = *t++
//		cmp		%r3, 0				;//  if(!c || (delim && strchr(delim, c))) {
//		jreq		strcompress_BREAK
//		xld.w		%r12, [%sp+12]			;//  %r12 :=                   delim
//		cmp		%r12, 0
//		jreq		strcompress_L30
//		xcall.d		strchr				;//  %r10 :=            strchr(delim, c)
//		ld.w		%r13, %r3			;//  %r13 :=                          c				*delay*
//		cmp		%r10, 0
//		jreq		strcompress_L30
//strcompress_BREAK:
//		cmp		%r0, 0				;//    if(!r) {
//		jrne		strcompress_L25
//		add		%r2, 1				;//      %r2  :=            u + 1
//		xcall.d		malloc				;//      %r10 := r = malloc(u + 1)
//		ld.w		%r12, %r2			;//      %r12 :=            u + 1				*delay*
//		cmp		%r10, 0				;//      if(!r) { DIE() }
//		jreq		strcompress_DIE
//		jp.d		strcompress_L10
//		ld.w		%r0, %r10			;//      %r0  := r						*delay*
//strcompress_L25:						;//    } else {
//		xld.w		%r9, [%sp+8]			;//      %r9  := endptr
//		cmp		%r9, 0				;//      if(endptr) {
//		jreq		3
//		 sub		%r1, 1				;//        *endptr = t - 1
//		 ld.w		[%r9], %r1			;//      }
//		ld.b		[%r2], %r8			;//      *u    = '￥0'
//		ld.w		%r10, %r0			;//      return  r
//		xadd		%sp, %sp, 16
//		popn		%r3
//		ret						;//    }
//		;//---------------------------------------------;//  } else {
//strcompress_L30:
//		xcmp		%r3, 92				;//    if(c != '￥') { goto COPY }
//		jrne		strcompress_COPY
//		ld.b		%r3, [%r1]+			;//    %r3  := c = *t++
//		cmp		%r3, 0				;//    if(!c) { goto BREAK }
//		jreq		strcompress_BREAK
//		xld.w		%r12, TBL_strescape+13		;//    %r12 :=            TBL_strescape + SIZE_strescape
//		xcall.d		strchr				;//    %r10 := p = strchr(TBL_strescape + SIZE_strescape, c))
//		ld.w		%r13, %r3			;//    %r13 :=                                            c	*delay*
//		cmp		%r10, 0				;//    if(    (p = strchr(TBL_strescape + SIZE_strescape, c)) {
//		jreq		strcompress_L40
//		cmp		%r0, 0				;//      if(!r) { u += 1
//		jreq		strcompress_ADD_1		;//      } else {
//		sub		%r10, 13			;//        %r10 :=   p - SIZE_strescape
//		ld.b		%r9, [%r10]			;//        %r9  := *(p - SIZE_strescape)
//		ld.b		[%r2]+, %r9			;//        *u++  = *(p - SIZE_strescape)
//		jp		strcompress_L20			;//      }
//		;//---------------------------------------------;//    } else
//strcompress_L40:
//		ld.w		%r4, %r3			;//    %r4  := x = c
//		sub		%r4, 48				;//    %r4  := x -= '0'
//		cmp		%r4, 7				;//    if((unsigned)x <= (unsigned)7) {
//		jrugt		strcompress_L50
//		ld.b		%r9, [%r1]			;//      %r9  := y = *t
//		sub		%r9, 48				;//      %r9  := y -= '0'
//		cmp		%r9, 7				;//      if((unsigned)y <= (unsigned)7) {
//		jrugt		strcompress_L45
//		 sla		%r4, 3				;//        %r4  := x <<= 3
//		 or		%r4, %r9			;//        %r4  := x  |= y
//		 add		%r1, 1				;//        %r1  := t++
//		 ld.b		%r9, [%r1]			;//        %r9  := y = *t
//		 sub		%r9, 48				;//        %r9  := y -= '0'
//		 cmp		%r9, 7				;//        if((unsigned)y <= (unsigned)7) {
//		 jrugt		strcompress_L45
//		  sla		%r4, 3				;//          %r4  := x <<= 3
//		  or		%r4, %r9			;//          %r4  := x  |= y
//		  add		%r1, 1				;//          %r1  := t++
//strcompress_L45:						;//      } }
//		cmp		%r0, 0				;//      if(!r) { u += 1
//		jreq		strcompress_ADD_1		;//      } else {
//		ld.b		[%r2]+, %r4			;//        *u++  = x
//		jp		strcompress_L20			;//      }
//		;//---------------------------------------------;//    } else
//strcompress_L50:
//		xand		%r9, %r3, -33			;//    if((c == 'x') || (c == 'X')) {
//		xcmp		%r9, 88
//		jrne		strcompress_L60
//		cmp		%r0, 0				;//      if(!r) { u += 1
//		jreq		strcompress_ADD_1		;//      } else {
//		ld.w		%r12, %r1			;//        %r12 :=             t
//		ld.w		%r13, %sp			;//        %r13 :=                &t
//		xld.w		[%sp+0], %r1
//		xcall.d		strtoul				;//        %r10 := x = strtoul(t, &t, 16)
//		ld.w		%r14, 16			;//        %r14 :=                    16			*delay*
//		xld.w		%r1, [%sp+0]			;//        %r1  :=                 t
//		ld.b		[%r2]+, %r10			;//        *u++  = x
//		jp		strcompress_L20			;//      }
//		;//---------------------------------------------;//    } else
//strcompress_L60:
//		cmp		%r3, 10				;//    if(c == '￥n') {
//		jreq		strcompress_L20			;//      /** no job **/
//		;//---------------------------------------------;//    } else {
//strcompress_COPY:
//		cmp		%r0, 0				;//      if(!r) { u += 1
//		jreq		strcompress_ADD_1		;//      } else {
//		ld.b		[%r2]+, %r3			;//        *u++  = c
//		jp		strcompress_L20			;//      }
//		;//---------------------------------------------;//} } }
//strcompress_ADD_1:
//		jp.d		strcompress_L20
//		add		%r2, 1				;//%r2  := u +=         1					*delay*
//");
//static void __attribute__((noreturn,unused))/*asmブロックから参照*/ strcompress_DIE() { DIE(); }
//#endif//PIECE
//}}2014/10/11削除:strtrim(),strescape(),strcompress()を、clipmisc.h,cからclipstr.h,cへ移動しました。今後は「ユーティリティ：文字列操作」はclipstr.h,cに追加してください。

/****************************************************************************
 *	コマンドライン分割
 ****************************************************************************/

#ifdef  _MSC_VER
// * Sun Nov 22 21:02:41 JST 2015 Naoyuki Sawa
// - parse_cmdline()を追加しました。
// - VC++6.0のランタイムがコマンドライン引数を分割する方法と同じ方法で、文字列を分割します。
//   Windowsでは、コマンドラインを分割するのはカーネルやシェルの役割ではなく、呼び出されたアプリケーションが行います。
//   □参照資料: C:/Program Files/Microsoft Visual Studio/VC98/CRT/SRC/STDARGV.C
// - 当関数は、merge_env_option()から利用するために作成しましたが、汎用でも利用出来ます。
//   例えば、対話的なツールで、ユーザーが入力した一行の文字列を、都度、分割する場合です。
//   そのような用途にも利用できるように、グローバル関数として公開する事にしました。
// - P/ECEで使う事は無いと思うので、Win32アプリケーションの場合だけ有効する事にしました。
char** parse_cmdline(const char* str) {
	char** argv;
	struct obstack o1;
	//Loop on each argument.
	obstack_init(&o1);
	for(;;) {
		int c, inquote = 0;	//1 = inside quotes
		struct obstack o2;
		//Skip whitespace.
		while(isspace((c = *str))) { str++; }
		//If at end of str, break loop.
		if(!c) { break; }
		//Loop through scanning one argument.
		obstack_init(&o2);
		for(;;) {
			int numslash = 0;	//num of backslashes seen
			//Rules:
			//[1] 2N   backslashes + '"' ==> N backslashes and begin/end quote	[!] Double quote inside quoted string skip first quote char and copy second.
			//[2] 2N+1 backslashes + '"' ==> N backslashes + literal '"'		[!] Double quote inside quoted string skip first quote char and copy second.
			//[3]  N   backslashes       ==> N backslashes
			while((c = *str++) == '\\') { numslash++; }
			if(c == '"') {	//[1] or [2]
				//If 2N backslashes before, start/end quote, otherwise copy literally.
				if(!(numslash & 1)) {	//[1]
					if(inquote && (*str == '"')) {	//[!]
						str++;	//Double quote inside quoted string skip first quote char and copy second.
					} else {
						c = -1;	//Don't copy quote.
						inquote = !inquote;
					}
				}
				numslash >>= 1;	//Divide numslash by two.
			}
			//Copy slashes.
			while(numslash--) { obstack_1grow(&o2, '\\'); }
			//If at end of arg, break loop.
			if(!c || (!inquote && isspace(c))) { break; }
			//Copy character into argument.
			if(c != -1) { obstack_1grow(&o2, c); }
		}
		//Null-terminate the argument.
		obstack_1grow(&o2, '\0');	//Terminate string.
		obstack_ptr_grow(&o1, memdup(obstack_base(&o2), obstack_object_size(&o2)));	//Store ptr to arg.
		obstack_free(&o2, NULL);
		//If at end of str, break loop.
		if(!c) { break; }
	}
	//We put one last argument in -- a null ptr.
	obstack_ptr_grow(&o1, NULL);
	argv = memdup(obstack_base(&o1), obstack_object_size(&o1));
	obstack_free(&o1, NULL);
	return argv;	//呼び出し側で不要になったら'strfreev(argv)'で開放して下さい。
}
// * Sun Nov 22 21:02:41 JST 2015 Naoyuki Sawa
// - 環境変数'プログラム名_OPTION'で指定されたオプション(有れば)を、コマンドライン引数にマージするようにしました。
// - main()が呼び出される前に、merge_env_option()が呼び出されます。
//   仕組みの詳細は、cliplibc.cのinit_program_invocation_name()のコメントを参照して下さい。
// * Sun May 29 21:54:56 JST 2016 Naoyuki Sawa
// - Visual C++ .NETで、main()が呼び出される前にプロセスが終了してしまう問題を修正しました。
//   詳細は、cliplibc.cの同日のコメントを参照して下さい。
//{{2016/05/29変更:Visual C++ .NETで、main()が呼び出される前にプロセスが終了してしまう問題を修正しました。
//static void merge_env_option() {
//↓2016/05/29変更:Visual C++ .NETで、main()が呼び出される前にプロセスが終了してしまう問題を修正しました。
#if     (_MSC_VER > 1200)	//Visual C++ .NETならば…
static int  merge_env_option() {
#else //(_MSC_VER > 1200)	//Visual C++ 6.0 ならば…
static void merge_env_option() {
#endif//(_MSC_VER > 1200)
//}}2016/05/29変更:Visual C++ .NETで、main()が呼び出される前にプロセスが終了してしまう問題を修正しました。
	char fname[MAX_FNAME], *str;
	//グローバル変数'__argv'から、コマンドライン引数を取得する。
	char** argv1 = __argv;
	//'プログラム名_OPTION'を大文字化して、環境変数を取得する。
	// - 例えば'C:\Home\Share\sample.exe'の場合、環境変数'SAMPLE_OPTION'を取得する。
	splitpath(argv1[0], NULL, NULL, fname, NULL);
	strupr(fname);
	strcat(fname, "_OPTION");
	str = getenv(fname);
	//環境変数が有れば…
	if(str) {
		//VC++6.0のランタイムがコマンドライン引数を分割する方法と同じ方法で、文字列を分割します。
		char** argv2 = parse_cmdline(str);
		struct obstack o;
		//環境変数を分割したコマンドライン引数を、元のコマンドライン引数のコマンド名([0])の後にマージする。
		obstack_init(&o);
		obstack_ptr_grow(&o, *argv1++);
//{{2017/05/07修正:merge_env_option()にて、不正なメモリ開放を行ってヒープを破壊してしまっていた、重大なバグを修正しました。
//		while(*argv2) { obstack_ptr_grow(&o, *argv2++); }
//		while(*argv1) { obstack_ptr_grow(&o, *argv1++); }
//↓2017/05/07修正:merge_env_option()にて、不正なメモリ開放を行ってヒープを破壊してしまっていた、重大なバグを修正しました。
// * Sun May 07 09:13:01 JST 2017 Naoyuki Sawa
// - merge_env_option()にて、不正なメモリ開放を行ってヒープを破壊してしまっていた、重大なバグを修正しました。
//   詳細は、以下の通りです。
// - merge_env_option()の最後でfree(argv2)を行っているので、parse_cmdline()から返されたargv2は変更してはいけません。
//   にもかかわらず、これまでのmerge_env_option()の実装では、argv2を直接インクリメントして進めてしまっていました。
//   そのため、merge_env_option()の最後のfree(argv2)は、不正なメモリ開放であり、ヒープを破壊してしまっていました。
// - 今回、以下のように呼び出した時に一般保護エラーが発生した問題を追いかけて、このバグに気付きました。
//   │env.exe WIN32=1 DTEXDEFC_OPTION="-n -a" cmd.exe /C CALL MkTexDef.bat tmp\TexDef.txt
//   上記の呼び出しで必ず一般保護エラーが再現するわけではなく、ある程度大きなスクリプトでガーベージコレクトが発生した時だけ再現します。
//   Boehm GCによってヒープ破壊を検出して欲しい所ですが、デバッグ版でもリリース版でも検出されず、いきなり落ちるようです。
// - 今回、バグを修正した事により、ライブラリ側の問題は解決したはずです。
//   ただし、これまでバグを含んだライブラリをリンクして作成したツールは、全てこのバグを内包しています。
//   当ライブラリのmerge_env_option()実装後に、当ライブラリを使用してビルドしたツールは、全てリビルドする必要が有ります。
//   しかしながら、対象となるツールの数が多過ぎるので、一度に全部ではなく、優先度の高いツールから、順次、リビルドして行こうと思います。
//   優先度の高いツールとは、「env.exe ????????_OPTION=～」を使う等の方法で(それには限りませんが)、コマンドライン引数のマージを使う事が多いツールです。
//   具体的には、/clip/tool/MkTexDef.bat等の、「/clip/tool/Mk??????.bat」から呼び出されるツール群です。
//   ともかく、ツールにバグを抱えたまま使用し続けるのは危険ですから、出来るだけ早く、全て、リビルドしなければいけません。	→→→→→→→→→→→→→→→→{{2017/05/08コメント追記:リビルド作業の進捗については、/clip/tool/BuildTools/ライブラリのバグ修正に伴う、ツールのリビルド作業について.txt を参照して下さい。}}	{{2017/05/09コメント追記:リビルド作業を完了しました。}}
		{
			int i;
			for(i = 0; argv2[i]; i++) { obstack_ptr_grow(&o, argv2[i]); }
			for(i = 0; argv1[i]; i++) { obstack_ptr_grow(&o, argv1[i]); }
		}
//}}2017/05/07修正:merge_env_option()にて、不正なメモリ開放を行ってヒープを破壊してしまっていた、重大なバグを修正しました。
		obstack_ptr_grow(&o, NULL);
		//マージしたコマンドライン引数を、グローバル変数'__argv','__argc'に格納する。
		__argv = memdup(obstack_base(&o), obstack_object_size(&o));
		__argc = strv_length(__argv);
		obstack_free(&o, NULL);
	    //{{---
	    //	strfreev(argv2);
	    //↓argv2のポインタ配列はもう不要なので開放して良いが、文字列は__argvがまだ参照しているので開放してはいけない。
		free(argv2);	//{{2017/05/07コメント追記:parse_cmdline()から返されたargv2を変更せずに、ここまで維持しなければいけません。これまでは間違って、変更したポインタを解放していました。本日、修正しました。}}
	    //}}---
	}
//{{2016/05/29追加:Visual C++ .NETで、main()が呼び出される前にプロセスが終了してしまう問題を修正しました。
#if     (_MSC_VER > 1200)	//Visual C++ .NETならば…
	return 0;	//VC++2015では、main()が呼び出される前に実行する関数が0を返すと、main()を呼び出さずに終了する。VC++6.0では、main()が呼び出される前に実行する関数の戻り値は検査されない。
#endif//(_MSC_VER > 1200)
//}}2016/05/29追加:Visual C++ .NETで、main()が呼び出される前にプロセスが終了してしまう問題を修正しました。
}
//{{2016/09/07追加:64ビット版では、「#pragma section(".CRT$XIU", long, read)」を追加しました。
#ifdef  _WIN64
#pragma section(".CRT$XIU", long, read)	//x64ではこの指定を追加しないと初期化関数が呼び出されません。詳細は/clip/test.win/keep/開発メモ.txtの'Thu Aug 11 23:59:25 JST 2016'のコメントを参照して下さい。
#endif//_WIN64
//}}2016/09/07追加:64ビット版では、「#pragma section(".CRT$XIU", long, read)」を追加しました。
#pragma data_seg(".CRT$XIU")	//'#pragma data_seg(".CRT$XCU")'でも構いません。
//{{2016/08/16変更:merge_env_option()が確実に実行されるように、「#pragma comment(linker, "/INCLUDE:_pmerge_env_option")」を追加しました。
//static void* /*!!const不可!!*/ pmerge_env_option/*変数名は関係無いので何でも良い*/ = merge_env_option;	//このポインタが".CRT$XI?"セグメント内に配置されて、mainCRTStartup()がポインタの指す関数を呼び出します。
//↓2016/08/16変更:merge_env_option()が確実に実行されるように、「#pragma comment(linker, "/INCLUDE:_pmerge_env_option")」を追加しました。
// * Tue Aug 16 22:54:46 JST 2016 Naoyuki Sawa
// - merge_env_option()が確実に実行されるように、「#pragma comment(linker, "/INCLUDE:_pmerge_env_option")」を追加しました。
//   具体的には、clipmisc.c内のpmerge_env_option変数をローカル変数からグローバル変数に変更し、その変数がアプリケーションに常にリンクされるように、clipmisc.h内に上記のプラグマを追加しました。
//   そうした理由は、以下の通りです。
// - 本日、エラー停止処理とトレース出力処理を、clipmisc.h,clipmisc.cから、clipdie.h,clipdie.cへ分離した事に伴い、当モジュールで定義されるグローバルシンボルが大分少なくなりました。
//   これまでは、当モジュールがdie()等の必ず参照されるグローバルシンボルを含んでいたので、当モジュールは必ずリンクされ、merge_env_option()もまず確実に呼び出されていたのですが、
//   本日の変更によって、die()等が別モジュールへ移動し、当モジュールで定義されるグローバルシンボルをアプリケーションが(直接,又は,間接的に)参照するか、やや心配になって来ました。
//   実験したところ、本日時点のモジュール構成で、最小限のアプリケーションでも、当モジュールはリンクされ、merge_env_option()は呼び出されるようです。(EnterCS等が参照されているためかと思います)
//   とは言え、偶然に依存するのも心許無いので、今のうちに、merge_env_option()が確実に実行されるようにしておく事にしました。
//   その方法としては、pmerge_env_optionを明示的に参照する事によって、merge_env_option()が確実に実行されるようにしました。
//   pmerge_env_optionを明示的に参照する方法は、下記のプラグマを利用しました。
//   □「MSDN ライブラリ Microsoft Visual Studio 6.0 - comment」より:
//   │linker
//   │オブジェクトファイルにリンカオプションを記録します。
//   │このコメント型を使うと、[プロジェクト設定]ダイアログボックスの[リンク]タブでオプションを指定する代わりにリンカオプションを指定できます。
//   │たとえば、次のように/includeオプションを指定して、強制的にシンボルを取り込むことができます。
//   │#pragma comment(linker, "/include:__mySymbol")
// - 「#pragma comment(linker, "/INCLUDE:pmerge_env_option")」ではなく、「#pragma comment(linker, "/INCLUDE:_pmerge_env_option")」とする必要が有る事に注意して下さい。
//   変数pmerge3_env_optionはCリンケージなので、リンカのシンボル名としては先頭に「_」が一つ付与されるからです。
//   例えば上のMSDN ライブラリの例の場合、元の変数名は「_mySymbol」で、シンボル名としては「_」を一つ付与して「__mySymbol」になったのだろうと推測されます。
/*static*/ void* /*!!const不可!!*/ pmerge_env_option/*変数名は関係無いので何でも良い*/ = merge_env_option;	//このポインタが".CRT$XI?"セグメント内に配置されて、mainCRTStartup()がポインタの指す関数を呼び出します。
//}}2016/08/16変更:merge_env_option()が確実に実行されるように、「#pragma comment(linker, "/INCLUDE:_pmerge_env_option")」を追加しました。
#pragma data_seg()		//元のセグメントに戻す。忘れないで!!
#endif//_MSC_VER
