/*
 *	regexp.h
 *
 *	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等を元に、高速化処理を削除して単純化して作成しました。
 *	* Mon Nov 13 23:52:13 JST 2017 Naoyuki Sawa
 *	- 独自拡張のstrdup_regsub_np()を追加しました。
 *	  strdup_regsub_np()を追加した理由は、以下の通りです。
 *	- 標準仕様のregsub()では、出力バッファdestの容量を指定出来ないため、regsub()がdestの容量を超えて文字を格納する事を確実に回避する方法が有りません。
 *	  そのためこれまでは、アプリケーション側で大きな容量のdestを確保してregsub()を呼び出すしか方法が無く、却って、必要以上にメモリを消費していました。
 *	  上記の問題を回避するために、既存のstrdup_*()系の関数と同様に、自動的に必要な容量のバッファを確保して、結果を格納する関数を追加する事にしました。
 *	  strdup_regsub_np()は独自拡張であり、Bell V8 正規表現の標準仕様ではないので、関数名サフィックス'np'('not portable')を付与しました。
 *	* Thu Nov 16 23:42:50 JST 2017 Naoyuki Sawa
 *	- 独自拡張のregcaseexec_np()を追加しました。
 *	  POSIX.2 正規表現ならば、regcomp()のcflags引数のREG_ICASEで指定出来るのですが、Bell V8 正規表現の関数にはフラグ指定が無いので、関数を分けました。
 *	  regcomp()を分ける方法も考えたのですが、regexec()でのマッチング実行時に切り替えられる方が便利だと思ったので、regexec()を分ける事にしました。
 */
#ifndef __REGEXP_H__
#define __REGEXP_H__
#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus
/*****************************************************************************
 *	
 *****************************************************************************/
//□参照資料「REGEXP(3) FreeBSD ライブラリ関数マニュアル REGEXP(3)」(http://kaworu.jpn.org/doc/FreeBSD/jman/man3/regexp.3.php)
//│名称
//│		regcomp, regexec, regsub, regerror - 正規表現ハンドラ
//│
//│ライブラリ
//│		互換ライブラリ (libcompat, -lcompat)
//│
//│書式
//│		#include <regexp.h>
//│		regexp* regcomp(const char* exp);
//│		int regexec(const regexp* prog, const char* string);
//│		void regsub(const regexp* prog, const char* source, char* dest);
//│
//│解説
//│		このインタフェースは、regex(3)で置き換えられました。
//│
//│		regcomp(),regexec(),regsub(),regerror()はegrep(1)スタイルの正規表現とサポート機能を実現しています。
//│
//│		regcomp()は、正規表現をregexp()タイプの構造体にコンパイルし、その構造体のポインタを戻します。
//│		スペースはmalloc(3)で割り振られ、freeで解放されます。
//│
//│		regexec()関数は、NULLで終わるstringをprogのコンパイル済み正規表現と突き合わせます。
//│		問題がない場合は1を戻し、問題がある場合は0を戻します。
//│		また、progのstartpとendp(下記参照)の内容を調整します。
//│
//│		regexp()構造体のメンバには、最低でも以下が必要です。順番は関係ありません。
//│
//│			│char* startp[NSUBEXP];
//│			│char* endp[NSUBEXP];
//│
//│		NSUBEXPは、ヘッダファイルで10に定義されています。
//│		regexp()を使用してregexec()が問題なく実行されると、startpとendpの各ペアは、stringのサブストリングを表します。
//│		startpはサブストリングの第1キャラクタを指し、endpはサブストリングの次の第1キャラクタを指します。
//│		0番目のサブストリングは、正規表現全体と一致するstringのサブストリングです。
//│		その他は、正規表現の括弧で囲まれた表現と一致するサブストリングです。
//│		括弧で囲まれた表現には、左括弧の左から右の次数で番号が付きます。
//│
//│		regsub()関数は、progを使用して最後に実行したregexec()に従って置き換えを行ないながら、sourceをdestにコピーします。
//│		sourceの‘&’の各インスタンスは、startp[0]とendp[0]で示されるサブストリングで置き換えられます。
//│		‘\n’の各インスタンス(nは数字)は、startp[n]とendp[n]で示されるサブストリングで置き換えられます。
//│		リテラル‘&’や‘\n’をdestに配置するには、そのリテラルの前に‘\’を配置します。
//│		‘&’や‘\n’の前にリテラル‘\’を付けるには、その前に‘\’をもう1つ付けます。
//│
//│		regerror()関数は、regcomp(),regexec(),regsub()でエラーが検出されると常に呼び出されます。
//│		デフォルトのregerror()は、原因の適切なインジケータを使用し、ストリングmsgを標準エラー出力に書き込んでexit(3)を呼び出します。
//│		その他のアクションが望ましい場合、ユーザはregerror()関数を別のものと置き換えられます。
//│
//│正規表現シンタックス
//│		正規表現は、‘|’で区切られた、0以上のブランチです。
//│		ブランチの1つと一致するものと一致します。
//│
//│		ブランチは、0以上の連結したピースです。
//│		最初に一致したものと一致した後で、次に一致したものと一致します。
//│
//│		ピースは、‘*’,‘+’,‘?’が続くことがあるアトムです。
//│		‘*’が続くアトムは、アトムの0以上の一致のシーケンスと一致します。
//│		‘+’が続くアトムは、アトムの1以上の一致のシーケンスと一致します。
//│		‘?’が続くアトムは、アトムの一致、またはnullストリングと一致します。
//│
//│		アトムは、括弧で囲まれた正規表現(正規表現の一致と一致する)、範囲(下記参照)、‘.’(1キャラクタと一致する)、‘^’(入力ストリングの最初のnullストリングと一致する)、
//│		‘$’(入力ストリングの最後のnullストリングと一致する)、1キャラクタが続く‘\’(そのキャラクタと一致する)、その他の意味がない1キャラクタ(そのキャラクタと一致する)です。
//│
//│		範囲は、‘[]’で囲まれたキャラクタのシーケンスです。
//│		通常は、そのシーケンスの1キャラクタと一致します。
//│		シーケンスが‘^’で始まる場合は、シーケンスの残りのキャラクタではない1キャラクタと一致します。
//│		シーケンスの2つのキャラクタが‘-’で区切られている場合、これは、その2キャラクタに挟まれたASCIIキャラクタのリストを表します(たとえば‘[0-9]’は、任意の十進数と一致します)。
//│		シーケンスにリテラル‘]’を組み込むには、それを最初のキャラクタにします(‘^’がある場合はその次のキャラクタにします)。
//│		リテラル‘-’を組み込むには、最初か最後のキャラクタにします。
//│
//│あいまい性
//│		正規表現が入力ストリングの2つの部分と一致する場合は、最初のものと一致します。
//│		両方が同じ場所で始まっているが長さが異なる場合、または長さが同じで別々の場所で始まっている場合、現実は以下のように複雑になります。
//│
//│		一般的に、ブランチのリストの実現性は左から右に考慮されます。
//│		‘*’,‘+’,‘?’の実現性は長いものから考慮されます。
//│		ネストされたコンストラクトは外側から考慮されます。
//│		連結されたコンストラクトは左から考慮されます。
//│		選択される一致は、最初の選択肢の最初の実現性を使用するものとなります。
//│		選択肢が複数ある場合は、最初の決定に従って、次が同じ方法(最初の実現性)で行なわれます。
//│		残りも同じようになります。
//│
//│		たとえば‘(ab|a)b*c’が‘abc’と一致する方法には2つあります。
//│		最初の選択肢は、‘ab’と‘a’の間です。
//│		‘ab’が先で、問題ない一致全体をリードするので、これが選択されます。
//│		‘b’はすでに選択されているので、‘b*’は最後の実現性(空ストリング)と一致します。
//│		先の選択肢を考慮する必要があるからです。
//│
//│		‘|’が存在せず、‘*’,‘+’,‘?’が1つだけ存在する場合は、最も長い一致が選択される結果となります。
//│		‘xabbbby’で提供された‘ab*’は、‘abbbb’と一致します。
//│		‘ab*’が‘xabyabbbz’で試されると、最初のものが選択されるので、‘x’の後の‘ab’と一致することに注意してください。
//│		(実際には、一致を始める場所の決定が最初の選択肢なので、後の選択肢では、優先順位が低い代案がリードしていてもそれを考慮する必要があります。)
//│
//│戻り値
//│		regcomp()関数は、シンタックスエラー、システム制限の超越、NULLオペランドへの‘+’や‘*’の適用などのエラーが発生した場合はNULLを戻します(regerror()が開始されます)。
//│
//│関連項目
//│		ed(1), egrep(1), ex(1), expr(1), fgrep(1), grep(1), regex(3)
//│
//│歴史
//│		regcomp(), regexec(), regsub(), regerror()のコードとマニュアルページは、トロント大学で作成され、4.3-TahoeBSDに追加されました。
//│		Bell V8 regexp(3)と互換性を保つようになっていますが、Bellコードから派生したものではありません。
//│
//│バグ
//│		空のブランチと空の正規表現は、V8と互換性はありません。
//│		NULLオペランドに‘*’か‘+’を適用することに課せられる制限は、システムを単純にするためのものです。
//│		egrepの改行で区切られたブランチはサポートされていません。V8 regexp(3)でもサポートされていません。
//│		簡潔さと単純さを強調したため、それほど速くありません。単純なケースを速く処理することに注意が向けられています。
//│
//│FreeBSD 10.0 June 4, 1993 FreeBSD 10.0
/*****************************************************************************
 *	定数
 *****************************************************************************/
#define NSUBEXP		10
/*****************************************************************************
 *	構造体
 *****************************************************************************/
typedef struct regexp {
	char*		startp[NSUBEXP];
	char*		endp[NSUBEXP];
} regexp;
/*****************************************************************************
 *	グローバル関数
 *****************************************************************************/
regexp* regcomp(const char* exp);
int regexec(regexp* prog, const char* string);
void regsub(const regexp* prog, const char* source, char* dest);
void regerror(const char* errmsg);
/*****************************************************************************
 *	デバッグ用
 *****************************************************************************/
#ifdef  DEBUG
extern int regnarrate;
void regdump(const regexp* prog);
#endif//DEBUG
/*****************************************************************************
 *	独自拡張
 *****************************************************************************/
char* strdup_regsub_np(const regexp* prog, const char* source);		//{{2017/11/13追加:独自拡張のstrdup_regsub_np()を追加しました。}}
int regcaseexec_np(regexp* prog, const char* string);			//{{2017/11/16追加:独自拡張のregcaseexec_np()を追加しました。}}
#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus
#endif//__REGEXP_H__
