/*
 *	regexp.c
 *
 *	Bell V8 正規表現
 *
 *	* Mon Aug 22 21:52:16 JST 2016 Naoyuki Sawa
 *	- 1st リリース。
 *	- Bell V8 正規表現です。(http://kaworu.jpn.org/doc/FreeBSD/jman/man3/regexp.3.php)
 *	  POSIX.2 正規表現ではありません。(http://linuxjm.osdn.jp/html/LDP_man-pages/man7/regex.7.html)
 *	  POSIX.2 正規表現は複雑でコードサイズも大きくなるので、Bell V8 正規表現で済ませる事にしました。
 *	- MINIX 1.7.5 のソース(http://download.minix3.org/previous-versions/gzipped/Intel-1.7.5.tar.gz)に含まれている、
 *	  /Intel-1.7.5/SYS/src/lib/other/regexp.c等を元に、高速化処理を削除して単純化して作成しました。
 *	* Tue Aug 23 21:53:38 JST 2016 Naoyuki Sawa
 *	- 下記三点の変更を行いました。
 *	  アプリケーションの観点からは、変更の影響は有りません。
 *	  ①regcomp()の1パス目を判定する方法を変更しました。
 *	  │これまでは、(regcode == &regdummy)で判定していましたが、regdummyを廃止し、(regcode == (void*)-1)で判定するようにしました。
 *	  │前者ならは機械語で複数命令掛かりますが、後者ならば1命令で判定出来るので、速度もコードサイズも効率が良くなるはずだからです。
 *	  ②regcomp()のエラー処理を変更しました。
 *	  │これまでは、エラーを検出したサブルーチンがNULLを返し、それを伝播させて行く事によって、エラー処理を行っていました。
 *	  │変更後は、エラーを検出したサブルーチンがregfail()経由でlongjmp()を投入し、regcomp()がキャッチするようにしました。
 *	  │この変更により、サブルーチンの戻り値を判定する処理が簡略化出来て、全体の見通しが良くなりました。
 *	  │詳細は、regfail()関数内のコメント,及び,regcomp()の処理を参照して下さい。
 *	  ③regcomp()が実行中に参照するグローバル変数を廃止し、スタックフレーム上のST_RegComp型変数を引数で渡すようにしました。
 *	  │regexec()が実行中に参照するグローバル変数を廃止し、スタックフレーム上のST_RegExec型変数を引数で渡すようにしました。
 *	  │この変更により、regcomp(),及び,regexec()が、再入可能(マルチスレッド対応)となりました。
 *	* Sun Sep 04 21:41:17 JST 2016 Naoyuki Sawa
 *	- 「#pragma warning(disable:...)」～「#pragma warning(default:...)」を、「#pragma warning(push)」「#pragma warning(disable:...)」～「#pragma warning(pop)」に変更しました。
 *	  詳細は、clipstd.h の同日のコメントを参照して下さい。
 *	* Mon Oct 10 23:41:22 JST 2016 Naoyuki Sawa
 *	- regcomp(),regexec(),regsub()をマルチバイト対応しました。
 *	  1バイト文字か2バイト文字かにかかわらず1バイト目の判定だけで済む箇所が多かったので、全ての箇所の文字処理を変更する必要は有りませんでした。
 *	  従って、変更箇所は意外と少なくて済みました。
 */
#include "clip.h"
/*****************************************************************************
 *	定数、マクロ、構造体
 *****************************************************************************/
//Definition		number		operand?	meaning
#undef  END
#define END		 0		//no		End of program.
#undef  BOL
#define BOL		 1		//no		Match "" at beginning of line.
#undef  EOL
#define EOL		 2		//no		Match "" at end of line.
#undef  ANY
#define ANY		 3		//no		Match any one character.
#undef  ANYOF
#define ANYOF		 4		//str		Match any character in this string.
#undef  ANYBUT
#define ANYBUT		 5		//str		Match any character not in this string.
#undef  BRANCH
#define BRANCH		 6		//node		Match this alternative, or the next...
#undef  BACK
#define BACK		 7		//no		Match "", "next" ptr points backward.
#undef  EXACTLY
#define EXACTLY		 8		//str		Match this string.
#undef  NOTHING
#define NOTHING		 9		//no		Match empty string.
#undef  OPEN
#define OPEN		10		//no		Mark this point in input as start of #n.
//      OPEN+1		11
//      OPEN+2		12
//      OPEN+3		13
//      OPEN+4		14
//      OPEN+5		15
//      OPEN+6		16
//      OPEN+7		17
//      OPEN+8		18
//      OPEN+9		19
#undef  CLOSE
#define CLOSE		20		//no		Analogous to OPEN.
//      CLOSE+1		21
//      CLOSE+2		22
//      CLOSE+3		23
//      CLOSE+4		24
//      CLOSE+5		25
//      CLOSE+6		26
//      CLOSE+7		27
//      CLOSE+8		28
//      CLOSE+9		29
/*--------------------------------------------------------------------------*/
#undef  OP
#define OP(p)		(*(p))
#undef  OPERAND
#define OPERAND(p)	((p)+3)
/*--------------------------------------------------------------------------*/
#undef  ISMULT
#define ISMULT(c)	(((c) == '*') || ((c) == '+') || ((c) == '?'))
#undef  META
#define META		"^$.[()|*+?\\"		//‘]’は含めない事に注意せよ。
/*--------------------------------------------------------------------------*/
typedef struct _ST_RegExp {
//public:
	char*		startp[NSUBEXP];
	char*		endp[NSUBEXP];
//private:
	unsigned char	program[0];
} ST_RegExp;
/*--------------------------------------------------------------------------*/
//Work variables for regcomp().
typedef struct _ST_RegComp {
	jmp_buf			regenv;		//regfail() -> regcomp().
	const unsigned char*	regparse;	//Input-scan pointer.
	int			regnpar;	//() count.
	unsigned char*		regcode;	//Code-emit pointer; (void*)-1 = don't.
	int			regsize;	//Code size.
} ST_RegComp;
/*--------------------------------------------------------------------------*/
//Work variables for regexec().
typedef struct _ST_RegExec {
	const unsigned char*	reginput;	//String-input pointer.
	const unsigned char*	regbol;		//Beginning of input, for ^ check.
	const unsigned char**	regstartp;	//Pointer to startp array.
	const unsigned char**	regendp;	//Ditto for endp.
} ST_RegExec;
/*****************************************************************************
 *	ローカル関数宣言
 *****************************************************************************/
//Forward declarations for regcomp()'s friends.
__declspec(noreturn) static void regfail(ST_RegComp* pRegComp, const char* errmsg) __attribute__((noreturn));
static unsigned char* regprogram(ST_RegComp* pRegComp, int paren, int* pHasWidth);
static unsigned char* regbranch(ST_RegComp* pRegComp, int* pHasWidth);
static unsigned char* regpiece(ST_RegComp* pRegComp, int* pHasWidth);
static unsigned char* regatom(ST_RegComp* pRegComp, int* pHasWidth);
static unsigned char* regnode(ST_RegComp* pRegComp, int op);
static void regchar(ST_RegComp* pRegComp, int c);
static void reginsert(ST_RegComp* pRegComp, int op, unsigned char* operand);
static void regtail(ST_RegComp* pRegComp, unsigned char* p, unsigned char* val);
static void regoptail(ST_RegComp* pRegComp, unsigned char* p, unsigned char* val);
//Forward declarations for regexec()'s friends.
static int regtry(ST_RegExec* pRegExec, ST_RegExp* prog, const unsigned char* string);
static int regmatch(ST_RegExec* pRegExec, unsigned char* p, int indent/*DEBUG*/);
static unsigned char* regnext(unsigned char* p);
#ifdef  DEBUG
static char* regprop(int op);
#endif//DEBUG
/*****************************************************************************
 *	
 *****************************************************************************/
regexp* regcomp(const char* exp) {
	ST_RegExp* volatile/*警告抑制*/ prog = NULL;	//volatileを付けないと、gcc33.exeで「warning: variable `prog' might be clobbered by `longjmp' or `vfork'」という警告が出ます。関連情報として、clipseh.hの「2015/10/11に行った修正内容についての説明」を参照して下さい。
	ST_RegComp stRegComp;
	if(!exp) { DIE(); }	//引数が不正。呼び出し側のバグです。
	//正規表現のコンパイル処理を実行する。
	if(!setjmp(stRegComp.regenv)) {
		int bHasWidth;
		//1パス目でコード全体のサイズを求める。
		stRegComp.regparse	= exp;			//Input-scan pointer.
		stRegComp.regnpar	= 1;			//() count.	\0に相当する暗黙の()が有るものと見なす。
		stRegComp.regcode	= (void*)-1;		//Code-emit pointer; (void*)-1 = don't.
		stRegComp.regsize	= 0;			//Code size.
		regprogram(&stRegComp, 0/*paren*/, &bHasWidth);
		//ノード間の距離を符号無しハーフワードで表すために、コード全体のサイズがUSHRT_MAX以下でなくてはならない。
		// - 厳密には、"next"が指し示すノード間の距離がUSHRT_MAX以下であれば、コード全体のサイズがUSHRT_MAXを超えていても構わないのだが、
		//   実用上は、コード全体のサイズをUSHRT_MAX以下に制限しても問題無いだろう。
		if(stRegComp.regsize > USHRT_MAX) { regfail(&stRegComp, "regexp too big"); }
		//メモリを確保する。
		prog = malloc(sizeof(ST_RegExp) + stRegComp.regsize);
		if(!prog) { regfail(&stRegComp, "out of space"); }
		//2パス目でコードを生成する。
		stRegComp.regparse	= exp;			//Input-scan pointer.
		stRegComp.regnpar	= 1;			//() count.	\0に相当する暗黙の()が有るものと見なす。
		stRegComp.regcode	= prog->program;	//Code-emit pointer; (void*)-1 = don't.
		regprogram(&stRegComp, 0/*paren*/, &bHasWidth);
		if((stRegComp.regcode - prog->program) != stRegComp.regsize) { DIE(); }	//1パス目で求めたコード全体のサイズと、2パス目で実際に生成したコードサイズは一致するはずです。もし違っていたら、当モジュールのバグです。
	//もし途中でエラーが発生して、regerror()が終了せずに処理を返した場合は、確実にメモリを解放してNULLを返す。
	} else {
		free(prog/*NULL可*/);
		prog = NULL;
	}
	return (regexp*)prog;
}
/*--------------------------------------------------------------------------*/
//エラー処理
static void regfail(ST_RegComp* pRegComp, const char* errmsg) {
	//デフォルトの,又は,アプリケーション定義の、regerror()を呼び出す。
	regerror(errmsg);
	//regerror()がexit()やabort()等を呼び出して終了したら、ここへは到達しない。
	//regerror()が処理を返した場合は、regcomp()へロングジャンプしてNULLを返す。
	longjmp(pRegComp->regenv, 1);
}
/*--------------------------------------------------------------------------*/
//正規表現は、‘|’で区切られた、0以上のブランチです。
//ブランチの1つと一致するものと一致します。
static unsigned char* regprogram(ST_RegComp* pRegComp, int paren, int* pHasWidth) {
	unsigned char *ret, *br, *ender;
	int no, bHasWidth;
	//暫定的に、少なくとも1文字以上にマッチする事を示すフラグをセットしておく。
	*pHasWidth = 1;
	//Make an OPEN node, if parenthesized.
	if(paren) {
		if(pRegComp->regnpar >= NSUBEXP) { regfail(pRegComp, "too many ()"); }
		no = pRegComp->regnpar;	//no=1～9
		pRegComp->regnpar++;
		//'('ノードを作成し、ブランチ全体の先頭ノードと見なす。(この時点では'('ノードの"next"フィールドは未設定です。)
		ret = regnode(pRegComp, OPEN + no);
	} else {
		no = 0;		//not actually used, keep compiler quiet.
		ret = NULL;
	}
	//Pick up the branches, linking them together.
	br = regbranch(pRegComp, &bHasWidth);	//BRANCHノード,及び,それに連なる一連のノードを作成する。(この時点では先頭のBRANCHノードの"next"フィールドは未設定です。)
	if(paren) {
		//'('ノードの"next"フィールドを、取得したブランチの最初のBRANCHノードへリンクする。
		regtail(pRegComp, ret, br);	//OPEN -> first.
	} else {
		//取得した一連のノードの先頭のBRANCHノードを、ブランチ全体の先頭ノードと見なす。
		ret = br;
	}
	//空文字にマッチするブランチが有れば、少なくとも1文字以上にマッチする事を示すフラグをクリアする。
	*pHasWidth &= bHasWidth;
	//‘|’で区切られた、次のブランチが有れば…
	while(*pRegComp->regparse == '|') {
		//‘|’の次へ進める。
		pRegComp->regparse++;
		//BRANCHノード,及び,それに連なる一連のノードを作成する。(この時点では先頭のBRANCHノードの"next"フィールドは未設定です。)
		br = regbranch(pRegComp, &bHasWidth);
		//ブランチ全体の先頭ノードから辿って、最後のBRANCHノードの次に、取得した一連のノードの先頭のBRANCHノードをリンクする。
		regtail(pRegComp, ret, br);	//BRANCH -> BRANCH.
		//空文字にマッチするブランチが有れば、少なくとも1文字以上にマッチする事を示すフラグをクリアする。
		*pHasWidth &= bHasWidth;
	}
	//Make a closing node, and hook it on the end.
	ender = regnode(pRegComp, paren ? (CLOSE + no) : END);	//')'ノード,又は,ENDノードを作成する。
	regtail(pRegComp, ret, ender);				//ブランチ全体の先頭ノードから辿って、最後のBRANCHノードの次に、')'ノード,又は,ENDノードをリンクする。
	//Hook the tails of the branches to the closing node.
	if(pRegComp->regcode != (void*)-1) {	//2パス目でのみ実行する。1パス目では実際にコードを生成していないので、この処理は実行出来ない。
		for(br = ret; br; br = regnext(br)) {
			regoptail(pRegComp, br, ender);		//各ブランチの最後のノードから、')'ノード,又は,ENDノードへのリンクを作成する。
		}
	}
	//Check for proper termination.
	if(paren) {
		if(*pRegComp->regparse != ')') { regfail(pRegComp, "unmatched ()"); }
		pRegComp->regparse++;
	} else {
		if(*pRegComp->regparse == ')') { regfail(pRegComp, "unmatched ()"); }
		if(*pRegComp->regparse != '\0') { regfail(pRegComp, "junk on end"); }	//"Can't happen".
	}
	return ret;
}
/*--------------------------------------------------------------------------*/
//ブランチは、0以上の連結したピースです。
//最初に一致したものと一致した後で、次に一致したものと一致します
static unsigned char* regbranch(ST_RegComp* pRegComp, int* pHasWidth) {
	unsigned char *ret, *chain;
	int bHasWidth;
	//暫定的に、少なくとも1文字以上にマッチする事を示すフラグをクリアしておく。
	*pHasWidth = 0;
	//ブランチのノードを作成する。
	ret = regnode(pRegComp, BRANCH);
	//入力文字列の終端に到達するか、‘|’,‘)’が出現するまで…
	chain = NULL;	//前のピース
	while((*pRegComp->regparse != '\0') && (*pRegComp->regparse != '|') && (*pRegComp->regparse != ')')) {
		//ピースを取得する。
		unsigned char* latest = regpiece(pRegComp, &bHasWidth);
		//少なくとも1文字以上にマッチする事を示すフラグをマージする。
		*pHasWidth |= bHasWidth;
		//前のピースが有れば、前のピースの最後のノードの"next"に、このピースを連結する。
		if(chain) { regtail(pRegComp, chain, latest); }
		//前のピースを記憶する。
		chain = latest;
	}
	//ピースが一つも無ければ、空のブランチとする。
	if(!chain) { regnode(pRegComp, NOTHING); }
	//ここで、ブランチのノードの"next"から、最初のピースへリンクしてはいけない事に注意せよ。
	// - ブランチのノードの"next"からリンクする先は、そのブランチの最初のピースではなく、次のブランチ,又は,')',又は,ENDです。
	//   ブランチのノードの"next"からリンクする処理は、当関数ではなく、regprogram()に有ります。
	// - 要するに、当関数が返す構造は、以下にようになっています。(実際にはpieceというノードの種類は無いので、EXACTLY等です。)
	//   │BRANCH{next=0},piece1{next=piece2},piece2{next=piece3},piece3{next=0}
	return ret;
}
/*--------------------------------------------------------------------------*/
//ピースは、‘*’,‘+’,‘?’が続くことがあるアトムです。
//‘*’が続くアトムは、アトムの0以上の一致のシーケンスと一致します。
//‘+’が続くアトムは、アトムの1以上の一致のシーケンスと一致します。
//‘?’が続くアトムは、アトムの一致、またはnullストリングと一致します。
static unsigned char* regpiece(ST_RegComp* pRegComp, int* pHasWidth) {
	unsigned char *ret, *next;
	//アトムを取得する。
	ret = regatom(pRegComp, pHasWidth);
	//‘*’,‘+’,‘?’が続いていなければ、アトムを返す。
	if(!ISMULT(*pRegComp->regparse)) { return ret; }
	//"()*"や"()+"ならば、エラーとする。
	if(!*pHasWidth && (*pRegComp->regparse != '?')) { regfail(pRegComp, "*+ operand could be empty"); }
	//"()*"や"()?"ならば、少なくとも1文字以上にマッチする事を示すフラグをクリアする。
	//"()+"ならば、少なくとも1文字以上にマッチする事を示すフラグをセットする。
	*pHasWidth = (*pRegComp->regparse == '+');
	//‘*’,‘+’,‘?’によって…
	switch(*pRegComp->regparse++) {
	default:DIE();	//バグ
	case '*':
		//Emit x* as (x&|), where & means "self".
		reginsert(pRegComp, BRANCH, ret);			//Either x	BRANCH1,atom										reginsert()する前はretはatomを指しているが、reginsert()した後はretはBRANCHを指している事に注意せよ。
		regoptail(pRegComp, ret, regnode(pRegComp, BACK));	//and loop	BRANCH1,atom{next=BACK},BACK
		regoptail(pRegComp, ret, ret);				//back		BRANCH1,atom{next=BACK},BACK{next=BRANCH1}
		regtail(pRegComp, ret, regnode(pRegComp, BRANCH));	//or		BRANCH1{next=BRANCH2},atom{next=BACK},BACK{next=BRANCH1},BRANCH2
		regtail(pRegComp, ret, regnode(pRegComp, NOTHING));	//null.		BRANCH1{next=BRANCH2},atom{next=BACK},BACK{next=BRANCH1},BRANCH2{next=NOTHING},NOTHING
		break;
	case '+':
		//Emit x+ as x(&|), where & means "self".
		next = regnode(pRegComp, BRANCH);			//Either	atom,BRANCH1
		regtail(pRegComp, ret, next);				//		atom{next=BRANCH1},BRANCH1
		regtail(pRegComp, regnode(pRegComp, BACK), ret);	//loop back	atom{next=BRANCH1},BRANCH1,BACK{next=atom}
		regtail(pRegComp, next, regnode(pRegComp, BRANCH));	//or		atom{next=BRANCH1},BRANCH1{next=BRANCH2},BACK{next=atom},BRANCH2
		regtail(pRegComp, ret, regnode(pRegComp, NOTHING));	//null.		atom{next=BRANCH1},BRANCH1{next=BRANCH2},BACK{next=atom},BRANCH2{next=NOTHING},NOTHING
		break;
	case '?':
		//Emit x? as (x|).
		reginsert(pRegComp, BRANCH, ret);			//Either x	BRANCH1,atom										reginsert()する前はretはatomを指しているが、reginsert()した後はretはBRANCHを指している事に注意せよ。
		regtail(pRegComp, ret, regnode(pRegComp, BRANCH));	//or		BRANCH1{next=BRANCH2},atom,BRANCH2
		next = regnode(pRegComp, NOTHING);			//null.		BRANCH1{next=BRANCH2},atom,BRANCH2,NOTHING
		regtail(pRegComp, ret, next);				//		BRANCH1{next=BRANCH2},atom,BRANCH2{next=NOTHING},NOTHING				ここで"next"が設定されるノードは、atomではなくBRANCH2である事に注意せよ。regtail()はnextを辿って行くので、BRANCH1から開始してatomには到達しないからです。
		regoptail(pRegComp, ret, next);				//		BRANCH1{next=BRANCH2},atom{next=NOTHING},BRANCH2{next=NOTHING},NOTHING
		break;
	}
	//‘*’,‘+’,‘?’の後に‘*’,‘+’,‘?’が有れば、エラーとする。
	if(ISMULT(*pRegComp->regparse)) { regfail(pRegComp, "nested *+?"); }
	return ret;
}
/*--------------------------------------------------------------------------*/
//アトムは、
//括弧で囲まれた正規表現(正規表現の一致と一致する)、
//範囲(下記参照)、
//‘.’(1キャラクタと一致する)、
//‘^’(入力ストリングの最初のnullストリングと一致する)、
//‘$’(入力ストリングの最後のnullストリングと一致する)、
//1キャラクタが続く‘\’(そのキャラクタと一致する)、
//その他の意味がない1キャラクタ(そのキャラクタと一致する)です。
static unsigned char* regatom(ST_RegComp* pRegComp, int* pHasWidth) {
	unsigned char* ret;
	int bHasWidth;
	//暫定的に、少なくとも1文字以上にマッチする事を示すフラグをクリアしておく。
	*pHasWidth = 0;
	//次の文字によって…
	switch(*pRegComp->regparse++) {
	case '^':
		{
			ret = regnode(pRegComp, BOL);
		}
		break;
	case '$':
		{
			ret = regnode(pRegComp, EOL);
		}
		break;
	case '.':
		{
			ret = regnode(pRegComp, ANY);
			//少なくとも1文字以上にマッチする事を示すフラグをセットする。
			*pHasWidth = 1;
		}
		break;
	case '[':
		{
//{{2016/10/10追加:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			const unsigned char* start;
//}}2016/10/10追加:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			int class, classend;
			//‘[’の直後の文字が‘^’ならば、否定文字クラスとする。
			if(*pRegComp->regparse == '^') {
				ret = regnode(pRegComp, ANYBUT);	//Complement of range.
				pRegComp->regparse++;			//‘^’の次へ進める。
			} else {
				ret = regnode(pRegComp, ANYOF);
			}
//{{2016/10/10追加:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			//mbsdec()のために、"[",又は,"[^"の直後(文字クラスの一文字目)の位置を記憶しておく。
			start = pRegComp->regparse;
//}}2016/10/10追加:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			//文字クラスの最初の文字が‘-’,‘]’ならば…
			if((*pRegComp->regparse == '-') || (*pRegComp->regparse == ']')) {
				//‘-’,‘]’をメタキャラクタと見なさずに、文字クラスの一部として登録する。
				regchar(pRegComp, *pRegComp->regparse++);
			}
			//‘]’に到達するまで…
			while(*pRegComp->regparse != ']') {
				//文字クラスが閉じていなければ、エラーとする。
				if(*pRegComp->regparse == '\0') { regfail(pRegComp, "unmatched []"); }
				//文字クラスの最初の文字以外で‘-’が出現したら…
				if(*pRegComp->regparse == '-') {
					//‘-’の次へ進める。
					pRegComp->regparse++;
					//文字クラスが閉じていなければ、エラーとする。
					if(*pRegComp->regparse == '\0') { regfail(pRegComp, "unmatched []"); }
					//‘-’が文字クラスの最後の文字ならば…
					if(*pRegComp->regparse == ']') {
						//‘-’をメタキャラクタと見なさずに、文字クラスの一部として登録する。
						regchar(pRegComp, '-');
					//‘-’が文字クラスの最後の文字でなければ…
					} else {
//{{2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
//						//範囲の最初の文字コード+1を求める。
//						// - +1する理由は、最初の文字コードは前のループで登録済みだからです。
//						class    = *(pRegComp->regparse - 2) + 1;
//						//範囲の最後の文字コードを求める。
//						classend = *(pRegComp->regparse++);
//↓2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
						//範囲の最初の文字コード+1を求める。
						// - +1する理由は、最初の文字コードは前のループで登録済みだからです。
						class    = mbsnextc(mbsdec(start, pRegComp->regparse - 1/*'-'*/)) + 1;
						//範囲の最後の文字コードを求める。
						classend = mbsnextc(pRegComp->regparse);
						pRegComp->regparse = mbsinc(pRegComp->regparse);
						//上位バイトが一致しない範囲は不可とする事にした。
						// - そうしないと、上位バイトがismbbleadでなかったり,下位バイトがismbbtrailでない、不正な2バイト文字コードが登録される恐れが有るからです。
						//   実際の所、2バイト文字を含む文字範囲を指定する事は、あまり望ましくありません。(上記のルールに反しなければ、一応、可能ではありますが…)
						if(((class - 1) >> 8) != (classend >> 8)) { regfail(pRegComp, "invalid [] range"); }
//}}2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
						//範囲が不正ならば、エラーとする。
						if((class - 1) > classend) { regfail(pRegComp, "invalid [] range"); }
						//範囲の文字を、全て登録する。
						while(class <= classend) { regchar(pRegComp, class++); }
					}
				//メタキャラクタ以外ならば…
				} else {
					//文字を登録する。
					// - 範囲の最初の文字も、ここで登録される。
//{{2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
//					regchar(pRegComp, *pRegComp->regparse++);
//↓2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
					regchar(pRegComp, mbsnextc(pRegComp->regparse));	//1バイト文字,又は,2バイト文字を取得して、登録する。
					pRegComp->regparse = mbsinc(pRegComp->regparse);	//1バイト文字,又は,2バイト文字の、次の位置へ進める。
//}}2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
				}
			}
			//文字クラスの終端を登録する。
			regchar(pRegComp, '\0');
			//‘]’の次へ進める。
			pRegComp->regparse++;
			//少なくとも1文字以上にマッチする事を示すフラグをセットする。
			*pHasWidth = 1;
		}
		break;
	case '(':
		{
			//‘(’～‘)’の中をパースする。
			ret = regprogram(pRegComp, 1/*paren*/, &bHasWidth);
			//少なくとも1文字以上にマッチする事を示すフラグをマージする。
			*pHasWidth |= bHasWidth;
		}
		break;
	case '\0':
	case ')':
	case '|':
		{
			regfail(pRegComp, "internal urp");	//Supposed to be caught earlier.
		}
		break;
	case '*':
	case '+':
	case '?':
		{
			//空文字の後に‘*’,‘+’,‘?’が有れば、エラーとする。
			regfail(pRegComp, "*+? follows nothing");
		}
		break;
	case '\\':
		{
			//‘\’の後に文字が無ければ、エラーです。
			if(*pRegComp->regparse == '\0') { regfail(pRegComp, "trailing \\"); }
			//‘\’の後の文字を登録する。
			ret = regnode(pRegComp, EXACTLY);
//{{2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
//			regchar(pRegComp, *pRegComp->regparse++);
//↓2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			regchar(pRegComp, mbsnextc(pRegComp->regparse));	//1バイト文字,又は,2バイト文字を取得して、登録する。
			pRegComp->regparse = mbsinc(pRegComp->regparse);	//1バイト文字,又は,2バイト文字の、次の位置へ進める。
//}}2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			regchar(pRegComp, '\0');
			//少なくとも1文字以上にマッチする事を示すフラグをセットする。
			*pHasWidth = 1;
		}
		break;
	default:
		{
			int len, ender;
			//文字列の先頭位置へ戻る。
			pRegComp->regparse--;
			//メタキャラクタ以外で構成されている文字列の長さを求める。
//{{2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
//			len = strcspn(pRegComp->regparse, META);
//↓2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			len = mbscspn(pRegComp->regparse, META);
//}}2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			if(len < 1) { DIE(); }	//起こり得ないはず。
			//文字列を終端させたメタキャラクタの文字を取得する。
			ender = *(pRegComp->regparse + len);
//{{2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
//			//文字列が2文字以上で、文字列を終端させたメタキャラクタが‘*’,‘+’,‘?’のいずれかならば、それらの対象となる文字を含めない。
//			if((len > 1) && ISMULT(ender)) { len--; }	//Back off clear of *+? operand.
//↓2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			//文字列を終端させたメタキャラクタが‘*’,‘+’,‘?’のいずれかならば…
			if(ISMULT(ender)) {
				//文字列の最後の文字へのポインタを取得する。
				const unsigned char* last = mbsdec(pRegComp->regparse, pRegComp->regparse + len);
				if(last < pRegComp->regparse) { DIE(); }	//起こり得ないはず。
				//文字列が、1バイト文字1文字でも,2バイト文字1文字でもなければ…
				if(last != pRegComp->regparse) {
					//文字列の最後の文字(=‘*’,‘+’,‘?’の対象となる文字)を、文字列から除外する。
					len = last - pRegComp->regparse;
				}
			}
//}}2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			if(len < 1) { DIE(); }	//起こり得ないはず。
			//文字列を登録する。
			ret = regnode(pRegComp, EXACTLY);
//{{2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
//			do { regchar(pRegComp, *pRegComp->regparse++); } while(--len);
//↓2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			{
				const unsigned char* end = pRegComp->regparse + len;
				do {
					regchar(pRegComp, mbsnextc(pRegComp->regparse));	//1バイト文字,又は,2バイト文字を取得して、登録する。
					pRegComp->regparse = mbsinc(pRegComp->regparse);	//1バイト文字,又は,2バイト文字の、次の位置へ進める。
				} while(pRegComp->regparse < end);
				if(pRegComp->regparse != end) { DIE(); }	//起こり得ないはず。
			}
//}}2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			regchar(pRegComp, '\0');
			//少なくとも1文字以上にマッチする事を示すフラグをセットする。
			*pHasWidth = 1;
		}
		break;
	}
	return ret;
}
/*--------------------------------------------------------------------------*/
//コードの末尾に、コードを生成する。
static unsigned char* regnode(ST_RegComp* pRegComp, int op) {
	//1パス目ならば、コードサイズだけを増やして、コードを生成しない。
	if(pRegComp->regcode == (void*)-1) {	//1パス目
		pRegComp->regsize += 3;
		return pRegComp->regcode;
	}
	*pRegComp->regcode++ = op;
	*pRegComp->regcode++ = 0;	//┬Null "next" pointer.
	*pRegComp->regcode++ = 0;	//┘
	return pRegComp->regcode - 3;
}
/*--------------------------------------------------------------------------*/
//コードの末尾に、文字を追加する。
static void regchar(ST_RegComp* pRegComp, int c) {
//{{2016/10/10追加:regcomp(),regexec(),regsub()をマルチバイト対応しました。
#ifdef  DEBUG
	//引数cに2バイト文字が指定されたら…
	if(c > UCHAR_MAX) {
		//正しい2バイト文字である事を確認する。
		if(!ismbblead(c >> 8) || !ismbbtrail(c)) { DIE(); }
	//引数cに1バイト文字が指定されたら…
	} else {
		//正しい1バイト文字である事を確認する。
		if(ismbblead(c)) { DIE(); }
	}
#endif//DEBUG
//}}2016/10/10追加:regcomp(),regexec(),regsub()をマルチバイト対応しました。
	//1パス目ならば、コードサイズだけを増やして、コードを生成しない。
	if(pRegComp->regcode == (void*)-1) {	//1パス目
//{{2016/10/10追加:regcomp(),regexec(),regsub()をマルチバイト対応しました。
		if(c > UCHAR_MAX) { pRegComp->regsize++; }
//}}2016/10/10追加:regcomp(),regexec(),regsub()をマルチバイト対応しました。
		pRegComp->regsize++;
	} else {
//{{2016/10/10追加:regcomp(),regexec(),regsub()をマルチバイト対応しました。
		if(c > UCHAR_MAX) { *pRegComp->regcode++ = (c >> 8); }
//}}2016/10/10追加:regcomp(),regexec(),regsub()をマルチバイト対応しました。
		*pRegComp->regcode++ = c;
	}
}
/*--------------------------------------------------------------------------*/
//生成済みのコードの途中の、operandの位置以降を3バイト後ろにずらし、空いた位置にコードを生成する。
static void reginsert(ST_RegComp* pRegComp, int op, unsigned char* operand) {
	unsigned char *src, *dst;
	//1パス目ならば、コードサイズだけを増やして、コードを生成しない。
	if(pRegComp->regcode == (void*)-1) {	//1パス目
		pRegComp->regsize += 3;
		return;
	}
	//生成済みのコードの途中の、operandの位置以降を3バイト後ろにずらし、空いた位置にコードを生成する。
	src = pRegComp->regcode;
	pRegComp->regcode += 3;
	dst = pRegComp->regcode;
	while(src > operand) { *--dst = *--src; }
	*operand++ = op;	//Op node, where operand used to be.
	*operand++ = 0;		//┬Null "next" pointer.
	*operand++ = 0;		//┘
}
/*--------------------------------------------------------------------------*/
//ノードpから開始して、"next"フィールドが設定されていない、最後のノードを見つける。
//最後のノードの"next"フィールドに、最後のノードとノードvalのオフセットを格納する。
static void regtail(ST_RegComp* pRegComp, unsigned char* p, unsigned char* val) {
	int offset;
	//1パス目ならば何もしない。
	// - この関数は、既存のコードの"next"フィールドを書き換えるだけなので、コードサイズを求める処理には関係有りません。
	//   この関数は、既存のコードを辿る処理を含むので、コードを生成していない1パス目ではこれ以降の処理は実行出来ません。
	if(p == (void*)-1) { return; }	//1パス目
	//pから検索を開始して、"next"フィールドが設定されていない、最後のノードを見つける。
	for(;;) {
		unsigned char* next = regnext(p);
		if(!next) { break; }
		p = next;
	}
	//"next"フィールドが設定されていない最後のノードが'BACK'ならば…
	if(OP(p) == BACK) {
		//引数valで指定されたノードから、最後のノードへの、オフセットを求める。
		offset = p - val;
		if((unsigned)offset > USHRT_MAX) { DIE(); }	//1パス目でコード全体のサイズがUSHRT_MAX以下である事を確認済みなので、ノード間の距離がUSHRT_MAXを超えることは起こり得ないはず。もしここでエラー停止したら当モジュールのバグです。
	//"next"フィールドが設定されていない最後のノードが'BACK'以外ならば…
	} else {
		//最後のノードから、引数valで指定されたノードへの、オフセットを求める。
		offset = val - p;
		if((unsigned)offset > USHRT_MAX) { DIE(); }	//1パス目でコード全体のサイズがUSHRT_MAX以下である事を確認済みなので、ノード間の距離がUSHRT_MAXを超えることは起こり得ないはず。もしここでエラー停止したら当モジュールのバグです。
	}
	//最後のノードの"next"フィールドを設定する。
	p[1] = offset >> 8;	//┬符号無し16ビットBE
	p[2] = offset;		//┘
}
/*--------------------------------------------------------------------------*/
//ノードpのオペランドのノードに対して、regtail()を呼び出す。
//ノードpがBRANCHノード以外ならば、オペランドが無いか,又は,オペランドはノードではないので、何もしない。
//(ノードpがBRANCHノード以外となるケースは、regprogram()から、'(',')',ENDに対して呼び出される場合のみだと思う。)
// - この関数は名前が悪いと思います。
//   最初、'reg-OPerator-tail'の略だと思っていて、何をする関数なのか理解出来ずに悩みました。
//   正しくは、'reg-OPerand-tail'の略です。
//   ブランチの一連のノードの最後のノードから、ノードvalへのリンクを作成するための関数です。
static void regoptail(ST_RegComp* pRegComp, unsigned char* p, unsigned char* val) {
	//"Operandless" and "op != BRANCH" are synonymous in practice.
	if((p == (void*)-1) || (OP(p) != BRANCH)) { return; }	//元ソースには(!p)を除外する判断も入っていたが、当関数が(!p)で呼び出される事は無いはずなので、(!p)を除外する判断は不要だろう。多分、元ソースはエラーをNULLで伝播して行くために、(!p)を除外しているのだろう。当実装では、エラーはlongjmp()で処理するので、ここで(!p)を除外する判断は不要だ。
	regtail(pRegComp, OPERAND(p), val);
}
/*****************************************************************************
 *	
 *****************************************************************************/
int regexec(regexp* prog, const char* string) {
	ST_RegExec stRegExec;
	//Be paranoid...
	if(!prog || !string) { DIE(); }	//引数が不正。呼び出し側のバグです。
	//Mark beginning of line for ^.
	stRegExec.regbol = string;
	//Messy cases: unanchored match.
//{{2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
//	do {
//		if(regtry(&stRegExec, (ST_RegExp*)prog, string)) { return 1; }	//(string=="")可
//	} while(*string++);							//(string=="")だったならばループを抜ける。
//↓2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
	for(;;) {
		if(regtry(&stRegExec, (ST_RegExp*)prog, string)) { return 1; }	//(string=="")可
		if(!*string) { break; }						//(string=="")だったならばループを抜ける。
		string = mbsinc(string);					//比較する位置を次の文字へ進める。
	}
//}}2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
	//Failure.
	return 0;
}
/*--------------------------------------------------------------------------*/
//0 failure, 1 success
static int regtry(ST_RegExec* pRegExec, ST_RegExp* prog, const unsigned char* string) {
//{{このmemset()の使い方は全く正しいにもかかわらずVC++6.0では警告出るので一時的に警告を抑制して回避する。
#ifdef  _MSC_VER
//{{2016/09/04変更:「#pragma warning(disable:...)」～「#pragma warning(default:...)」を、「#pragma warning(push)」「#pragma warning(disable:...)」～「#pragma warning(pop)」に変更しました。
//#pragma warning(disable:4090)	//'function' : 'const' 修飾子は異なります。
//#pragma warning(disable:4022)	//'memset' : 1 番目の実引数のﾎﾟｲﾝﾀの型が、仮引数のﾎﾟｲﾝﾀの型と異なります。
//↓2016/09/04変更:「#pragma warning(disable:...)」～「#pragma warning(default:...)」を、「#pragma warning(push)」「#pragma warning(disable:...)」～「#pragma warning(pop)」に変更しました。
#pragma warning(push)
#pragma warning(disable:4090)	//'function' : 'const' 修飾子は異なります。
#pragma warning(disable:4022)	//'memset' : 1 番目の実引数のﾎﾟｲﾝﾀの型が、仮引数のﾎﾟｲﾝﾀの型と異なります。
//}}2016/09/04変更:「#pragma warning(disable:...)」～「#pragma warning(default:...)」を、「#pragma warning(push)」「#pragma warning(disable:...)」～「#pragma warning(pop)」に変更しました。
#endif//_MSC_VER
	memset(prog->startp, 0, sizeof prog->startp);
	memset(prog->endp,   0, sizeof prog->endp  );
#ifdef  _MSC_VER
//{{2016/09/04変更:「#pragma warning(disable:...)」～「#pragma warning(default:...)」を、「#pragma warning(push)」「#pragma warning(disable:...)」～「#pragma warning(pop)」に変更しました。
//#pragma warning(default:4090)	//'function' : 'const' 修飾子は異なります。
//#pragma warning(default:4022)	//'memset' : 1 番目の実引数のﾎﾟｲﾝﾀの型が、仮引数のﾎﾟｲﾝﾀの型と異なります。
//↓2016/09/04変更:「#pragma warning(disable:...)」～「#pragma warning(default:...)」を、「#pragma warning(push)」「#pragma warning(disable:...)」～「#pragma warning(pop)」に変更しました。
#pragma warning(pop)
//}}2016/09/04変更:「#pragma warning(disable:...)」～「#pragma warning(default:...)」を、「#pragma warning(push)」「#pragma warning(disable:...)」～「#pragma warning(pop)」に変更しました。
#endif//_MSC_VER
//}}このmemset()の使い方は全く正しいにもかかわらずVC++6.0では警告出るので一時的に警告を抑制して回避する。
	pRegExec->reginput  = string;
	pRegExec->regstartp = (const unsigned char**)prog->startp;
	pRegExec->regendp   = (const unsigned char**)prog->endp;
	if(!regmatch(pRegExec, prog->program, 0/*DEBUG*/)) { return 0; }
	pRegExec->regstartp[0] = string;
	pRegExec->regendp[0] = pRegExec->reginput;
	return 1;
}
/*--------------------------------------------------------------------------*/
//0 failure, 1 success
static int regmatch(ST_RegExec* pRegExec, unsigned char* p, int indent/*DEBUG*/) {
	while(p) {
		unsigned char* next = regnext(p);	//Next node.
#ifdef  DEBUG
		if(regnarrate) {
			int op = OP(p);
			fprintf(stderr, "%*s%s", indent * 2/*調整可*/, "", regprop(op));
			if((op == ANYOF) || (op == ANYBUT) || (op == EXACTLY)) {
				fprintf(stderr, "(%s)", OPERAND(p));
			}
			fputc('\n', stderr);
		}
#endif//DEBUG
		switch(OP(p)) {
		default:DIE();	//memory corruption
		case END:
			return 1;	//Success!
		case BOL:
			if(pRegExec->reginput != pRegExec->regbol) { return 0; }
			break;
		case EOL:
			if(*pRegExec->reginput != '\0') { return 0; }
			break;
		case ANY:
			if(*pRegExec->reginput == '\0') { return 0; }
//{{2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
//			pRegExec->reginput++;
//↓2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			pRegExec->reginput = mbsinc(pRegExec->reginput);
//}}2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			break;
		case ANYOF:
//{{2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
//			if((*pRegExec->reginput == '\0') || !strchr(OPERAND(p), *pRegExec->reginput)) { return 0; }
//			pRegExec->reginput++;
//↓2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			if((*pRegExec->reginput == '\0') || !mbschr(OPERAND(p), mbsnextc(pRegExec->reginput))) { return 0; }
			pRegExec->reginput = mbsinc(pRegExec->reginput);
//}}2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			break;
		case ANYBUT:
//{{2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
//			if((*pRegExec->reginput == '\0') ||  strchr(OPERAND(p), *pRegExec->reginput)) { return 0; }
//			pRegExec->reginput++;
//↓2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			if((*pRegExec->reginput == '\0') ||  mbschr(OPERAND(p), mbsnextc(pRegExec->reginput))) { return 0; }
			pRegExec->reginput = mbsinc(pRegExec->reginput);
//}}2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			break;
		case BRANCH:
			{
				if(OP(next) == BRANCH) {
					do {
						const unsigned char* save = pRegExec->reginput;
						if(regmatch(pRegExec, OPERAND(p), indent + 1)) { return 1; }
						pRegExec->reginput = save;
						p = regnext(p);
					} while(p && (OP(p) == BRANCH));
					return 0;
				}
				next = OPERAND(p);	//Avoid recursion.
			}
			break;
		case BACK:
			/** no job **/
			break;
		case EXACTLY:
			{
				unsigned char* operand = OPERAND(p);
				int len = strlen(operand);
				if(strncmp(operand, pRegExec->reginput, len)) { return 0; }	//{{2016/10/10コメント追記:一致不一致だけの比較なので、_mbsncmp()を使わなくてもstrncmp()で大丈夫です。}}
				pRegExec->reginput += len;
			}
			break;
		case NOTHING:
			/** no job **/
			break;
	//不要	case OPEN+0:	//\0はregtry()で明示的に処理するので、OPEN+0のノードは生成されない。
		case OPEN+1:
		case OPEN+2:
		case OPEN+3:
		case OPEN+4:
		case OPEN+5:
		case OPEN+6:
		case OPEN+7:
		case OPEN+8:
		case OPEN+9:
			{
				int no = OP(p) - OPEN;
				const unsigned char* save = pRegExec->reginput;
				if(!regmatch(pRegExec, next, indent + 1)) { return 0; }
				//Don't set startp if some later invocation of the same parentheses already has.
				// - 繰り返しの中に()が有る場合、一番最後にマッチした部分を記憶するという意味です。
				//   例えば、文字列"ABC"に対して、正規表現/(.)+/を適用した場合、\1は"C"を指します。
				if(!pRegExec->regstartp[no]) { pRegExec->regstartp[no] = save; }
				return 1;
			}
			break;
	//不要	case CLOSE+0:	//\0はregtry()で明示的に処理するので、CLOSE+0のノードは生成されない。
		case CLOSE+1:
		case CLOSE+2:
		case CLOSE+3:
		case CLOSE+4:
		case CLOSE+5:
		case CLOSE+6:
		case CLOSE+7:
		case CLOSE+8:
		case CLOSE+9:
			{
				int no = OP(p) - CLOSE;
				const unsigned char* save = pRegExec->reginput;
				if(!regmatch(pRegExec, next, indent + 1)) { return 0; }
				//Don't set endp if some later invocation of the same parentheses already has.
				// - 繰り返しの中に()が有る場合、一番最後にマッチした部分を記憶するという意味です。
				//   例えば、文字列"ABC"に対して、正規表現/(.)+/を適用した場合、\1は"C"を指します。
				if(!pRegExec->regendp[no]) { pRegExec->regendp[no] = save; }
				return 1;
			}
			break;
		}
		p = next;
	}
	//We get here only if there's trouble -- normally "case END" is the terminating point.
	DIE();
}
/*--------------------------------------------------------------------------*/
//ノードpの"next"フィールドを辿って、次のノードを返す。
//"next"フィールドが設定されていなければ、NULLを返す。
// - 元ソースでは、当関数がregcomp()の1パス目に呼び出された場合は、ダミーとしてNULLを返すようになっていたが、判り辛かった。
//   そこで、呼び出し側にて、当関数をregcomp()の1パス目では呼び出さないように変更して、当関数内での1パス目の判定を削除した。
// - 尚、実際に判定を追加する必要が生じたのは、regprogram()内の「for(br = ret; br; br = regnext(br)) {」の箇所だけであった。
//   それ以外の箇所(と言ってもregtail()だけだが)では、元々、regcomp()の1パス目ではregnext()を呼び出さないようになっていた。
static unsigned char* regnext(unsigned char* p) {
	int offset;
	offset = (p[1] << 8) | p[2];	//符号無し16ビットBE
	if(!offset) { return NULL; }
	if(OP(p) == BACK) {
		return p - offset;
	} else {
		return p + offset;
	}
}
/*****************************************************************************
 *	
 *****************************************************************************/
void regsub(const regexp* prog, const char* source, char* dest) {
	int c, no;
	if(!prog || !source || !dest) { DIE(); }	//引数が不正。呼び出し側のバグです。
//{{2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
//	while((c = *source++)) {
//↓2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
	while((c = mbsnextc(source))) {
		source = mbsinc(source);
//}}2016/10/10変更:regcomp(),regexec(),regsub()をマルチバイト対応しました。
		no = -1;
		if(c == '&') {
			no = 0;
		} else if((c == '\\') && (*source >= '0') && (*source <= '9')) {
			no = *source++ - '0';
		}
		if(no == -1) {	//Ordinary character.
			if(c == '\\' && ((*source == '&') || (*source == '\\'))) { c = *source++; }
//{{2016/10/10追加:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			if(c > UCHAR_MAX) { *dest++ = (c >> 8); }
//}}2016/10/10追加:regcomp(),regexec(),regsub()をマルチバイト対応しました。
			*dest++ = c;
		} else {
			if(prog->startp[no] && prog->endp[no]) {
				int len = prog->endp[no] - prog->startp[no];
				if((int)strnlen(prog->startp[no], len) < len) { DIE(); }	//当モジュールのバグ,又は,メモリ破損
				strncpy(dest, prog->startp[no], len);
				dest += len;
			}
		}
	}
	*dest++ = '\0';
}
/*****************************************************************************
 *	デバッグ用
 *****************************************************************************/
#ifdef  DEBUG
int regnarrate;
/*--------------------------------------------------------------------------*/
void regdump(const regexp* _prog) {
	ST_RegExp* prog = (ST_RegExp*)_prog;
	unsigned char* p = prog->program;
	for(;;) {
		int op = OP(p);
		unsigned char* next = regnext(p);
		printf("%d:%s", p - prog->program, regprop(op));		//Where, what.
		printf("(%d)", next ? ((p - prog->program) + (next - p)) : 0);	//Next ptr.
		p = OPERAND(p);
		if((op == ANYOF) || (op == ANYBUT) || (op == EXACTLY)) {
			fputs(p, stdout);
			p += strlen(p) + 1/*'\0'*/;
		}
		putchar('\n');
		if(op == END) { break; }
	}
}
/*--------------------------------------------------------------------------*/
static char* regprop(int op) {
	static char buf[16];
	const char* s = NULL;
	switch(op) {
	default:DIE();	//バグ
	case BOL:	s = "BOL";	break;
	case EOL:	s = "EOL";	break;
	case ANY:	s = "ANY";	break;
	case ANYOF:	s = "ANYOF";	break;
	case ANYBUT:	s = "ANYBUT";	break;
	case BRANCH:	s = "BRANCH";	break;
	case BACK:	s = "BACK";	break;
	case EXACTLY:	s = "EXACTLY";	break;
	case NOTHING:	s = "NOTHING";	break;
	case END:	s = "END";	break;
//不要	case OPEN+0:	//\0はregtry()で明示的に処理するので、OPEN+0のノードは生成されない。
	case OPEN+1:
	case OPEN+2:
	case OPEN+3:
	case OPEN+4:
	case OPEN+5:
	case OPEN+6:
	case OPEN+7:
	case OPEN+8:
	case OPEN+9:	sprintf(buf, "OPEN%d", op - OPEN);	break;
//不要	case CLOSE+0:	//\0はregtry()で明示的に処理するので、CLOSE+0のノードは生成されない。
	case CLOSE+1:
	case CLOSE+2:
	case CLOSE+3:
	case CLOSE+4:
	case CLOSE+5:
	case CLOSE+6:
	case CLOSE+7:
	case CLOSE+8:
	case CLOSE+9:	sprintf(buf, "CLOSE%d", op - CLOSE);	break;
	}
	if(s) { strcpy(buf, s); }
	return buf;
}
#endif//DEBUG
