/*	
 *	clipmisc.c
 *
 *	エラー処理、その他いろいろです。
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2015 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)を追加しました。
 */
#include "clip.h"

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

//{{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.*へ分離しました。

/*****************************************************************************
 *	エラー処理
 *****************************************************************************/

//{{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			; }
");
#else /*PIECE*/
/* * __declspec(noreturn)は、.hファイルの関数宣言に付加するだけで良いようです。
 *   .cファイルの関数定義には、付加してもしなくても同じみたいです。(実験より)
 *   GCCの__attribute__((noreturn))が、関数定義には付加できないことに合わせて、
 *   __declspec(noreturn)も、関数定義には付加しないことにしました。
 * * GCCは、__attribute__((noreturn))を付加した関数が、誤って処理を返した場合、
 *   コンパイル時に警告を表示します。
 *   Visual C++は、__declspec(noreturn)を付加した関数が、誤って処理を返しても、
 *   コンパイル時に警告を表示しないので、注意が必要です。
 */
/*__declspec(noreturn)*/ void
die(const char* fmt, ...)
{
	va_list ap;
	va_start(ap, fmt);
	vfprintf(stderr, fmt, ap);
	va_end(ap);
    //{{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);
}

//{{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に追加してください。
