/*
 *	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等を元に、高速化処理を削除して単純化して作成しました。
 */
#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
#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus
#endif//__REGEXP_H__
