$NetBSD: patch-aa,v 1.2 1999/06/08 09:27:27 sakamoto Exp $ ●●●●● GNU grep version 2.0 + multi-byte extension 1.04 ●●●●● ●●●●● Jun. 2, 1994 by t^2 ●●●●● このファイルは GNU grep version 2.0 (grep-2.0) のソースコードから, そ のマルチバイト文字対応版 grep-2.0+mb1.04 のソースコードを生成するため の差分を含んでいます. grep-2.0 のソースを展開してあるディレクトリで % patch -p1 < このファイル などとしてパッチを当ててください. その後 README.MB を読んでください. 〒810 福岡市中央区梅光園団地 7-207 TEL/FAX: 092-731-4025 (TEL/FAX 自動切替え) 092-724-6342 (TEL のみ) E-mail: NBC02362@niftyserve.or.jp t^2 (谷本孝浩) diff -ru2N grep-2.0/ChangeLog.MB grep+mb1.04/ChangeLog.MB --- grep-2.0/ChangeLog.MB Thu Jan 1 09:00:00 1970 +++ grep+mb1.04/ChangeLog.MB Thu Jun 2 17:01:42 1994 @@ -0,0 +1,219 @@ +Thu Jun 2 16:58:03 1994 Takahiro Tanimoto (tt@isaac) + + * Version 2.0 + multi-byte extension 1.04 released. + +Sat Mar 5 16:30:16 1994 Takahiro Tanimoto (tt@isaac) + + * README.MSC: PC-9800 シリーズ用 MS-C 6.00A の, ワイルドカード展 + 開ルーチンのバグに対処した. 以前の stdargv.diff をこれに統合し, + 削除した. (Thanks to 福浩邦さん ) + +Thu Aug 19 04:26:09 1993 Takahiro Tanimoto (tt@isaac) + + * regex.c (re_compile_fastmap): charset_not の fastmap の作成処 + 理が間違っていて, regex の fastmap を使用する場合 (e?grep では + fastmap を使用していないため, この問題は表面には現れない), 正規 + 表現の先頭の [^A] や [^a] に例えば B がマッチしなかった. + (Thanks to 小屋良祐さん ) + +Tue Aug 10 01:29:05 1993 Takahiro Tanimoto (tt@isaac) + + * regex.c (set_list_bits): 文字クラス中のマルチバイト文字の最適 + 化で, 区間終点の更新処理部分にバグがあり, [A-CE-GB-D] を最 + 適化すると [A-G] だが, これが [A-E] となってしまっていた. + ただし, regex ではなく dfa が使用される場合にはこのバグは表面に + は現れない. + +Fri Jul 23 03:22:13 1993 Takahiro Tanimoto (tt@isaac) + + * Version 2.0 + multi-byte extension 1.03 released. + + * DEFS.dos: strcmpi を stricmp に変更. + + * grep.c (main): MS-DOS の場合, argv[0] を加工した文字列へのポイ + ンタを argv[0] へもセットする. getopt が出力するメッセージも加 + 工された文字列となる. + + * grep.c (main): MS-C 6.00A の stdargv.asm のバグをフィックスし + たため, argv[0] == "" のときの処理を削除した. + + * stdargv.diff: 追加. + +Tue Jul 13 07:04:13 1993 Takahiro Tanimoto (tt@isaac) + + * Version 2.0 + multi-byte extension 1.02 released. + +Mon Jul 12 00:20:36 1993 Takahiro Tanimoto (tt@isaac) + + * grep.c: HAVE_STRCASECMP が #define されていないとき, 一方の文 + 字列だけを小文字にしてから比較する関数を定義していたが, 使い方が + 悪かった. それを strcasecmp() と同じものに変更した. + + * DEFS.dos: HAVE_STRCMPI を #define する代わりに, + HAVE_STRCASECMP を #define し, strcasecmp を strcmpi に #define + した. + +Sat Jul 10 01:05:04 1993 Takahiro Tanimoto (tt@isaac) + + * Version 2.0 + multi-byte extension 1.01 released. + + * grep.c (main): MSDOS の場合, argv[0] を小文字にして prog にセッ + トする. また, 拡張子は取り除く. + + * obstack.h: chunk_size の型を size_t から unsigned に変更. + old-C の場合, size_t が定義されていない状態となったため. + + * regex.h: 定数の後に U, UL をつけると old-C でコンパイルできな + い. これらをキャストに変更した. + + * regex.h: RE_DUP_MAX の定義を 16 ビット int のマシンでもオーバ + フローしない書き方に修正. + + * obstack.h: struct obstack のメンバ chunk_size の型を size_t と + した. PTR_INT_TYPE を外部から #define できるようにした. MSDOS + で SMALL MODEL 以外の場合, __PTR_TO_INT, __INT_TO_PTR とともに, + ポインタと long を変換するようにした. + + * grep.c (fillbuf, grep): read() の返り値の正負によるエラーチェッ + クを, -1 に等しいかどうかで行うように変更. + + * grep.c: totalcc, totalnl を unsigned long に変更し, prline() + 中の printf() の書式を合わせた. + + * DEFS.dos: BUFSALLOC を 4096 に #define. (See reset() in + grep.c.) + + * getpagesize.h: MSDOS の場合, ページサイズは 4096 とした. + + * dfa.c: STDC_HEADERS または HAVE_STRING_H のとき, bcopy, bzero + をマクロ展開する. + +Fri Jul 9 13:16:50 1993 Takahiro Tanimoto (tt@isaac) + + * mbc.c, mbc.h, ...: ismbchar() をモジュール毎に独立して定義する + のをやめ, モジュールを追加した. + + * search.c (Fexecute): fgrep をマルチバイト文字に対応させた. + +Wed Jul 7 17:02:33 1993 Takahiro Tanimoto (tt@isaac) + + * kwset.c (bmexec): 8 ビットクリーンでないところを修正. + + * ベースを grep-2.0 へ変更. + +Sun Jul 4 08:48:12 1993 Takahiro Tanimoto (tt@isaac) + + * regex.c (re_match_2): オリジナルのバグ. maybe_finalize_jump + の処理中, start_memory/stop_memory をスキップするところで, 引数 + のスキップをしていないバグを修正. 例えば "([a-n]+).*\1" が正し + く "abcxyzab" にマッチするようになった. + +Sat Jul 3 06:51:33 1993 Takahiro Tanimoto (tt@isaac) + + * Version 1.6 + multi-byte extension 1.00 released. + +Sat Jul 3 04:29:14 1993 Takahiro Tanimoto (tt at pc98) + + * grep.c (bufprev): -b オプションで表示するバイトオフセットを + long にするために bufprev を long とした. bufprev 以外は変更し + ていないため, 1 行のサイズが int の範囲を越えると正しく処理され + ない. また, DOS では CR+LF を 1 バイトとしてカウントしてしまう. + (手抜き) + + * regex.c (re_match_2): 文字クラスの処理中の 16 ビット int で正 + 常動作しない部分を修正. + + * regex.c (re_exec): re_search() への最後の引数を 0 から NULL へ + 修正. + + * regex.c (re_match): re_match_2() への2番目の引数を 0 から + NULL へ修正. + + * regex.c (re_search): re_search_2() への2番目の引数を 0 から + NULL へ修正. + + * grep.c (main): MS-C の setargv のバグのせいで, grep "\\" foo + とすると argv[0] == "" となってしまう. argv[0] == "" のときは強 + 制的に "grep" または "egrep" をセットするようにした. + +Fri Jul 2 19:25:58 1993 Takahiro Tanimoto (tt at pc98) + + * grep.c (main): 変数 prog の設定を DOS 用に修正した. その際, + オリジナルのやり方はまずかったので修正した. + + * grep.c: MSDOS のとき errno と sys_errlist の宣言をしないように + 修正した. + + * regex.c (set_list_bits): 使用していなかった変数を削除. + + * Makefile.msc: DOS サポートのため追加. + +Fri Jun 11 04:14:22 1993 Takahiro Tanimoto (tt@isaac) + + * grep.c: version 文字列が古いままだった. + +Tue May 25 00:10:49 1993 Takahiro Tanimoto (tt@isaac) + + * Version 1.6 + multi-byte extension 0.02 released. + +Mon May 24 15:57:31 1993 Takahiro Tanimoto (tt@isaac) + + * regex.c (re_search_2): 後方へ advance する際のバグを修正. + +Sat May 22 02:03:41 1993 Takahiro Tanimoto (tt@isaac) + + * regex.c (re_compile_fastmap): exactn で translate するのをやめ + た. re_compile_pattern で一度 translate されているはず. + + * regex.c (re_match_2): exactn の処理部分で, #if 0 を #if 1 にし + た場合, 正しい処理を行っていなかったのを修正. + +Fri May 21 20:04:07 1993 Takahiro Tanimoto (tt@isaac) + + * regex.[ch]: mbcharset, mbcharset_not を廃止. 代わりに + charset, charset_not がマルチバイト文字をも保持する. + + * grep.c (main): 下記の変更に伴って, "^.*(" ... ")" を付加する処 + 理を削除した. + + * dfa.c (regcompile): searchflag が ON のとき, 正規表現を "^.*(" + ... ")" としてコンパイルするようにした. 以前は grep.c の中で同 + じことを行っていた. + + * dfa.c (lex): 文字クラスでマルチバイト文字の1文字目の集合から, + シングルバイト文字を除外する処理を追加した. + + * dfa.c (lex): 文字クラスでシングルバイト文字の上限が間違ってい + たのを修正した. + +Wed May 19 01:27:07 1993 Takahiro Tanimoto (tt@isaac) + + * regex.c: !__STDC__ のときに const を #define. + + * dfa.h: オリジナルでは !STDC_HEADERS のときに const を #define + していたが, これを !__STDC__ のときに #define するように変更した. + + * configure.in: bcopy(), memmove() のチェックを追加. + + * dfa.c (reginit): cs_tok[] の初期化を追加した. -i フラグを付け + た場合の不具合を修正. + +Tue May 18 18:14:04 1993 Takahiro Tanimoto (tt@albert) + + * dfa.h: regex.h での RE_MBCTYPE_??? の値と一致させた. + + * regex.[ch] (RE_TRANSLATED_RANGE): mbsed-0.01 で行った拡張を輸 + 入した. + +Sat May 15 04:27:32 1993 Takahiro Tanimoto (tt@isaac) + + * マルチバイト文字対応版が一通り完成した. + + +Local Variables: +mode: indented-text +left-margin: 8 +fill-column: 72 +fill-prefix: " " +version-control: never +End: diff -ru2N grep-2.0/DEFS.dos grep+mb1.04/DEFS.dos --- grep-2.0/DEFS.dos Thu Jan 1 09:00:00 1970 +++ grep+mb1.04/DEFS.dos Fri Jul 23 03:23:31 1993 @@ -0,0 +1,15 @@ +#define STDC_HEADERS 1 +#define HAVE_STRING_H 1 +#define HAVE_MEMCHR 1 +#define HAVE_STRERROR 1 +#define HAVE_MEMMOVE 1 +#define HAVE_STRCASECMP 1 +#define strcasecmp stricmp + +#define BUFSALLOC 4096 + +#ifndef M_I86SM +#define __PTR_TO_INT(P) ((long)(P)) +#define __INT_TO_PTR(P) ((char *)(P)) +#define PTR_INT_TYPE long +#endif diff -ru2N grep-2.0/MANIFEST.MB grep+mb1.04/MANIFEST.MB --- grep-2.0/MANIFEST.MB Thu Jan 1 09:00:00 1970 +++ grep+mb1.04/MANIFEST.MB Sat Mar 5 16:37:46 1994 @@ -0,0 +1,11 @@ +ChangeLog.MB Revision history of multi-byte extension to grep. +DEFS.dos Definitions for DOS. +MANIFEST.MB This file. +Makefile.msc Makefile for MS-C version 6. +README.MB Documentation for multi-byte extension. +README.MSC Patch for source/startup/... of MS-C 6.00A +mbc.c Multi-byte char handler. +mbc.h Interface to mbc.c. +tests/batgen.awk DOS version of scriptgen.awk. +tests/check.bat DOS version of check.sh +tests/spencer.dos Input for batgen. diff -ru2N grep-2.0/Makefile.in grep+mb1.04/Makefile.in --- grep-2.0/Makefile.in Mon May 3 05:54:24 1993 +++ grep+mb1.04/Makefile.in Mon Jul 12 02:02:28 1993 @@ -16,4 +16,7 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# Multi-byte extension added May, 1993 by t^2 (Takahiro Tanimoto) +# Last change: Jul. 12, 1993 by t^2 + SHELL = /bin/sh @@ -40,4 +43,11 @@ DEFS=-DGREP @DEFS@ +# Things you might set to MBCTYPE_DEF to spec. default multi-byte char type. +# -DEUC will make default multi-byte char type EUC and +# -DSJIS SJIS. +# If you do not set EUC/SJIS, grep assumes no multi-byte +# char as default. +MBCTYPE_DEF=-DEUC + # Extra libraries. LIBS=@LIBS@ @@ -69,9 +79,9 @@ #### End of system configuration section. #### -SRCS=grep.c getopt.c regex.c dfa.c kwset.c obstack.c search.c -OBJS=grep.o getopt.o regex.o dfa.o kwset.o obstack.o search.o +SRCS=grep.c getopt.c regex.c dfa.c kwset.c obstack.c search.c mbc.c +OBJS=grep.o getopt.o regex.o dfa.o kwset.o obstack.o search.o mbc.o .c.o: - $(CC) $(CFLAGS) $(DEFS) -I$(srcdir) -c $< + $(CC) $(CFLAGS) $(DEFS) $(MBCTYPE_DEF) -I$(srcdir) -c $< all: grep check.done @@ -120,7 +130,9 @@ dist: V=`sed -n '/version\\[/s/.*\\([0-9][0-9]*\\.[0-9]*\\).*/\\1/p' \ + grep.c`+mb`sed -n '/^ + multi-byte/s/[^0-9]*\\([0-9.]*\\).*/\\1/p' \ grep.c`; \ mkdir grep-$$V; mkdir grep-$$V/tests; \ - for f in `awk '{print $$1}' MANIFEST`; do ln $$f grep-$$V/$$f; done; \ + for f in `awk '{print $$1}' MANIFEST MANIFEST.MB`; \ + do ln $$f grep-$$V/$$f; done; \ tar cvhf - grep-$$V | gzip > grep-$$V.tar.z; \ rm -fr grep-$$V @@ -132,2 +144,3 @@ kwset.o obstack.o: obstack.h regex.o search.o: regex.h +grep.o regex.o dfa.o search.o mbc.o: mbc.h diff -ru2N grep-2.0/Makefile.msc grep+mb1.04/Makefile.msc --- grep-2.0/Makefile.msc Thu Jan 1 09:00:00 1970 +++ grep+mb1.04/Makefile.msc Fri Jul 23 04:03:17 1993 @@ -0,0 +1,138 @@ +# Generated automatically from Makefile.in by configure. +# Makefile for GNU grep +# Copyright (C) 1992 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +# Multi-byte extension added May, 1993 by t^2 (Takahiro Tanimoto) +# Last change: Jul. 23, 1993 by t^2 + +#### Start of system configuration section. #### + +srcdir=. +VPATH=. + +AWK=gawk +INSTALL=cp +INSTALL_PROGRAM=$(INSTALL) +INSTALL_DATA=$(INSTALL) + +CC=cl -nologo -D__STDC__ -AL +LINT=lint + +# Things you might add to DEFS: +# -DSTDC_HEADERS If you have ANSI C headers and libraries. +# -DHAVE_UNISTD_H If you have unistd.h. +# -DUSG If you have System V/ANSI C string +# and memory functions and headers. +# -D__CHAR_UNSIGNED__ If type `char' is unsigned. +# gcc defines this automatically. +# +# For DOS, add those to DEFS.dos. + +# Things you might set to MBCTYPE_DEF to spec. default multi-byte char type. +# -DEUC will make default multi-byte char type EUC and +# -DSJIS SJIS. +# If you do not set EUC/SJIS, grep assumes no multi-byte +# char as default. +MBCTYPE_DEF=-DSJIS + +# Extra libraries. +LIBS=setargv/noe/st:30000 +ALLOCA= + +CFLAGS=-Ox +LDFLAGS=$(CFLAGS) + +prefix= +exec_prefix=$(prefix) + +# Prefix for installed program, normally empty or `g'. +binprefix= +# Prefix for installed man page, normally empty or `g'. +manprefix= + +# Where to install executables. +bindir=$(exec_prefix)/bin + +# Where to install man pages. +mandir=$(prefix)/man/man1 + +# Extension for man pages. +manext=1 + +# How to make a hard link. +LN=cp + +#### End of system configuration section. #### + +SRCS=grep.c getopt.c regex.c dfa.c kwset.c obstack.c search.c mbc.c +OBJS=grep.obj getopt.obj regex.obj dfa.obj kwset.obj obstack.obj search.obj mbc.obj + +.c.obj: + cat DEFS.dos $< > $*_.c + $(CC) $(CFLAGS) $(MBCTYPE_DEF) -I$(srcdir) -c -Fo$@ $*_.c + rm $*_.c + +all: grep.exe check.don + +# For Saber C. +grep.loa: $(SRCS) + #load $(CFLAGS) $(DEFS) -I$(srcdir) (SRCS) + +# For Lint. +grep.lin: $(SRCS) + $(LINT) $(CFLAGS) $(DEFS) -I$(srcdir) $(SRCS) + +install: all + $(INSTALL_PROGRAM) grep.exe $(bindir)/$(binprefix)grep.exe + rm -f $(bindir)/$(binprefix)egrep.exe + $(LN) $(bindir)/$(binprefix)grep.exe $(bindir)/$(binprefix)egrep.exe + rm -f $(bindir)/$(binprefix)fgrep.exe + $(LN) $(bindir)/$(binprefix)grep.exe $(bindir)/$(binprefix)fgrep.exe + +check: + tests\check + echo done >check.don + +check.don: grep.exe + tests\check + echo done >check.don + +grep.exe: $(OBJS) + echo $(OBJS:.obj =.obj+)+>link.tmp + echo $(LIBS)>>link.tmp + echo $@/noi;>>link.tmp + link @link.tmp + rm link.tmp + +clean: + rm -f grep.exe *.obj check.don tmp.bat tmp.in khadafy.out + +mostlycl: clean + +distclea: clean + rm -f Makefile config.sta + +realclea: distclea + rm -f TAGS + +# Some header file dependencies that really ought to be automatically deduced. +dfa.obj search.obj: dfa.h +grep.obj search.obj: grep.h +kwset.obj search.obj: kwset.h +kwset.obj obstack.obj: obstack.h +regex.obj search.obj: regex.h +grep.obj regex.obj dfa.obj search.obj mbc.obj: mbc.h diff -ru2N grep-2.0/README.MB grep+mb1.04/README.MB --- grep-2.0/README.MB Thu Jan 1 09:00:00 1970 +++ grep+mb1.04/README.MB Thu Jun 2 17:03:37 1994 @@ -0,0 +1,327 @@ +●●●●● GNU grep version 2.0 + multi-byte extension 1.04 ●●●●● +●●●●● Jun. 2, 1994 by t^2 ●●●●● + + grep-2.0+mb1.04 -- マルチバイト文字対応版 GNU grep + +●概要 + + GNU プロジェクトによる grep, egrep, fgrep (以下単に grep) をマルチバ + イト文字対応化したものです. + +●使用法 + + grep からの拡張部分だけを説明します. + + 増えたオプションは以下の通りです. + + -Wctype=ASCII + マルチバイト文字を考慮しません. このオプションを使用した場 + 合, grep のオリジナルと同じ動作になるはずです. + + -Wctype=EUC + マルチバイト文字として EUC を認識します. + + -Wctype=SJIS + マルチバイト文字として Shift-JIS を認識します. + + MS-DOS 以外のシステムで, Makefile(.in)? を書き換えずにインストー + ルした場合, デフォルトでは EUC を認識します. MS-DOS ではデフォ + ルトで Shift-JIS を認識します. + +● GREM104.LZH (MS-DOS 版実行形式を含むアーカイブ) について (それ以外の + 形態で入手された方は無視してください) + + 1. アーカイブに含まれているファイル + + オリジナルから全く手を加えていないファイル + + AUTHORS オリジナルのソースに含まれている AUTHORS + CHANGELO オリジナルのソースに含まれている ChangeLog + COPYING オリジナルのソースに含まれている COPYING + MANIFEST オリジナルのソースに含まれている MANIFEST + NEWS オリジナルのソースに含まれている NEWS + PROJECTS オリジナルのソースに含まれている PROJECTS + README オリジナルのソースに含まれている README + + grep+mb 用のファイル + + CHANGELO.MB grep+mb の変更履歴 + README.MB このファイル + + MS-DOS 版 grep+mb 用のファイル + + GREP.CAT オリジナルのソースに含まれているマニュアルページ. + grep.man を GNU roff でフォーマットしたもの. + GREP.EXE MS-DOS 版 grep-2.0+mb1.04 の実行形式 + READMAN.SED sed を持っている人へおまけ + (sed -f readman.sed grep.cat) + + 2. GREP.EXE について + + grep-2.0+mb1.04 を MS-C 6.00A でコンパイルしたものです. + + デフォルトで Shift-JIS 漢字コードを含むパターンやテキストを処理 + できます. + + setargv.obj を組み込んでありますので, MS-DOS でポピュラーなタイ + プのワイルドカードが使用できます. UNIX の csh ライクなワイルド + カード展開ルーチンを用意しようかとも思ったのですが, MS-DOS の他 + のコマンドとの整合性が取れないし, オリジナルをなるべく尊重したかっ + たので断念しました. + + 3. インストール + + GREP.EXE は, grep はもちろん, egrep, fgrep の機能を含んでいます. + grep に -E オプションを与えると egrep の動作, -F オプションを与 + えると fgrep の動作をします. また, GREP.EXE を EGREP.EXE, + FGREP.EXE という名前でコピーして egrep, fgrep として起動すると, + その名前にふさわしい動作をします. ハードディスクに余裕のない方 + 以外は, + + A>copy grep.exe a:\bin + A>copy grep.exe a:\bin\egrep.exe + A>copy grep.exe a:\bin\fgrep.exe + + などとしてご使用になられることをお勧めします. どうしてもハード + ディスクの無駄使いをしたくなければ, + + @echo off + grep -E %1 %2 %3 %4 %5 %6 %7 %8 %9 + + などのバッチファイルを作成するという手もあります. + + 4. コマンドライン引数について + + 前述したとおり MS-C の setargv.obj をリンクしていますので, その + 仕様に従わなければなりません. + + 1つ1つの引数は空白で区切ります. 引数に空白, ", \, <, >, | を + 含むときはクォーティングが必要です. その方法は COMMAND.COM のバ + グ臭い仕様と, さらに setargv.obj にも問題があり, かなり難しいの + でここでは説明を省きます. 各自研究してください. 一番簡単なのは, + 検索パターンをファイルにして + + grep -f ファイル名 + + とすることです. + + 5. マニュアル + + roff 系のフォーマッタを使えない人のために GNU roff でフォーマッ + ト済みのマニュアルを用意しました. ボールドフェース, アンダーラ + イン対応の less などでお読みください. エディタなどでは ^H が入っ + ていて読みにくいと思います. + + s/.^H//g + + という sed のプログラムに通せば, 通常のテキストファイルが得られ + ます. (^H というのはコントロールコードを直接埋めこむという意味 + です.) + +●インストール (MS-DOS 以外) + + デフォルトのマルチバイト文字の設定は, Makefile.in の中で指定します. + デフォルトを Shift-JIS とする場合と, デフォルトでマルチバイト文字を + 使用しない場合は Makefile.in の MBCTYPE_DEF マクロの定義をそれぞれ以 + 下のように変えてください. + + MBCTYPE_DEF=-DSJIS (デフォルトで Shift-JIS の場合) + MBCTYPE_DEF= (デフォルトで使用しない場合) + + いずれの場合でも起動時のオプションによりマルチバイト文字コードの選択 + が可能です. + + その他の作業は, オリジナルの grep と同様ですので INSTALL をお読みく + ださい. + +●インストール (MS-DOS 版. ここでいうインストールというのは, ソースから + のインストールのことです) + + MS-C 6.00A を使用して, デフォルトで Shift-JIS を認識する grep を作成 + する場合は, README.MSC に目を通して, 必要ならライブラリにパッチを当 + てた後, + + A>nmake -f makefile.msc + + とするだけでOKです. grep.exe を作成後, 自動的にテストを行います. + その際, grep からのエラーメッセージがいくつか表示されますが, それは + 異常ではありません. エラーを含むパターンを渡した時に, 終了ステータ + スが 2 となることを確認しているだけです. 本当に異常があった場合は + "Spencer test #nn faild" (nn は数字) と表示されます. + + テストにパスしたら, grep.exe を適当なディレクトリにコピーしてくださ + い. その際, 名前を egrep.exe, fgrep.exe と変えるだけで, それぞれ + egrep, fgrep の動作をします. そこで, 例えば a:\bin へインストールす + る場合, + + A>copy grep.exe a:\bin + A>copy grep.exe a:\bin\egrep.exe + A>copy grep.exe a:\bin\fgrep.exe + + などとします. + + その他の処理系を使用する場合や, デフォルトを Shift-JIS 以外にする場 + 合は Makefile.msc を参考に Makefile を書いてください. なお, テストに + は awk (gawk) が必要です. + +●バグ + + 1. いわゆる JIS には対応していません. 将来対応する予定もありません. + + 2. マルチバイト文字コードはあまり厳格には考えていません. + + EUC 1バイト目 ... 0x80 - 0xff + EUC 2バイト目 ... 0x01 - 0xff (0x0a を除く) + + Shift-JIS 1バイト目 ... 0x80 - 0x9f, 0xe0 - 0xff + Shift-JIS 2バイト目 ... 0x01 - 0xff (0x0a を除く) + + として処理しています. 半角カナも使えます. EUC の SS3 (0x8f) に + 始まる3バイトコードは使えません. (私はこれをサポートしているシ + ステムを見たことがない...) + + 3. -b オプションで表示されるバイトオフセットは DOS の場合 CR+LF を 1 + としてカウントした値になります. (手抜き) + +●アルゴリズム (dfa.[ch] のマルチバイト文字対応化) + + 以前は漠然と, DFA を直接 EUC や Shift-JIS のような文字種の多いコード + セットに対応させるのは, 非常に難しいと思っていました. ところがある + 日, 自作ライブラリのテスト用に, 正規表現を DFA へ変換する簡単なプロ + グラムを書いたときに, 突然うまいアイディアが閃いたのです. マルチバ + イト文字といえども結局はバイトの並びです. マルチバイト文字を, すべ + てバイト単位に分解して, 正規表現を作ってしまえばよかったのです. + + 言葉ではうまく表現できないので, 以下の記号を使用し, どういうふうにバ + イト単位に分解しているのか, 例を挙げます. + + a, b, c ... シングルバイト文字. + x, y, z ... マルチバイト文字の1文字目. + + . (任意の1文字) + ==> [a-c]|[x-z][a-z] + + (シングルバイト文字か, またはマルチバイト文字の1文字目と + 任意の1文字の連接.) + + [xb-zx] (xb から zx の範囲のマルチバイト文字) + ==> x[b-z]|y[a-z]|z[a-x] + + yb* + ==> (yb)* + + 実際には正規表現を作り出すのではなく, 正規表現を分解したトークンを直 + 接生成しています. この辺, 興味がある方はソースを見たほうが早いと思 + います. (あまりエレガントではありませんのでソースをじっくり見られる + のは恥ずかしい気もしますが...) + + これだけでは, 例えばあるテキストから xy という文字を探そうとすると, + xxyy のような文字の並びにまで反応してしまいます. そこで, マルチバイ + トモードのときには必ず "^.*(" + ユーザパターン + ")" として処理しま + す. '.*' により, '.' はマルチバイト文字の一部にはマッチしませんから, + 頭出しできるわけです. + +● dfa.[ch], regex.[ch] の拡張仕様 + + dfa.[ch], regex.[ch] モジュールは mbc.[ch] モジュールに依存していま + す. また, これはオリジナルの仕様ですが, dfa.[ch] を使用する場合は + regex.h の定義が必要です. + + マルチバイト文字のタイプは, mbc.[ch] の mbcinit() で設定します. + mbc.h に定義されているマクロ MBCTYPE_ASCII, MBCTYPE_EUC, + MBCTYPE_SJIS のいずれかを mbcinit() に渡してください. + + dfa.[ch] は, パターンのコンパイル時にだけ, この mbc.[ch] の設定を参 + 照します. パターンマッチングの際は, コンパイル時に設定されていた, + マルチバイト文字のタイプを検索します. + + 一方, regex.[ch] は, パターンコンパイル時, マッチング時の両方で + mbc.[ch] の設定を参照します. が, この両者で mbc.[ch] の設定を変更す + ることはできません. つまり, Shift-JIS で記述されたパターンを, EUC + テキストから検索するといった動作はできません. 注意してください. + + マルチバイト文字対応に伴って注意すべき正規表現を以下に記します. + + . 任意の1バイト文字, 正当なマルチバイト文字にマッチします. + 「正当なマルチバイト文字」とは, マルチバイト文字の1文字 + 目に, '\0' または '\n' 以外が続く文字のことです. + + [x-y] 文字コード (内部表現) が x から y の範囲にある任意の1文 + 字にマッチします. これも . と同じく, 正当でない文字には + マッチしません. + + [^x-y] 文字コード (内部表現) が x から y の範囲にない任意の1文 + 字にマッチします. 正当でない文字にもマッチします. + + マルチバイト文字の内部表現は単に1バイト目を上位バイト, 2バイト目を + 下位バイトとした16ビット符号なし整数です. Shift-JIS でも EUC でも + + 1バイト ASCII 文字 < 半角カナ文字 < 全角文字 + + という大小関係が成り立っています. + +●その他 + + 1. オリジナルの GNU grep の著作権は Free Software Foundation, Inc. + が有しています. パッチ部分 (grep-mb.diff) の著作権は私 (t^2) が有 + しています. + + 2. GNU grep のソースコードは各所の ftp サイト, もしくは Nifty-serve + の FUNIX のデータライブラリから入手可能です. GNU grep から + grep+mb への差分 grep-mb.diff は, 私が FUNIX へ登録し, 堂園和郎氏 + (dohzono@sdsft.kme.mei.co.jp) が fj.sources へポストしてくださっ + ています. + + 3. 差分 grep-mb.diff の再配布は自由です. これに関しては FSF の規定に + 従う必要もありません. しかし差分を適用した結果のソースコード, お + よび実行形式での再配布の際は GNU GENERAL PUBLIC LICENSE (COPYING + 参照) に従ってください. + + grep+mb に何らかの改変を加えたものを再配布する際も, GNU GENERAL + PUBLIC LICENSE に従うように注意してください. また grep+mb に含ま + れるコード (dfa.[ch] や regex.[ch]) を利用したプログラムを配布す + る際も GNU GENERAL PUBLIC LICENSE の該当部分に従ってください. + + また義務ではありませんが再配布される方は事後にでも連絡をください. + そして可能な限り, 新しいバージョンへのアップデートに努め, 利用者 + からの連絡が私に届くように配慮してください. + + 4. このプログラムは無保証です. + + 5. grep+mb に何らかの不具合が発生した場合, (FSF や, オリジナルの作者 + ではなく) 私に連絡してください. 配布した人が希望している場合は, + その人に連絡してください. + + 6. ご質問/ご要望/お叱り, その他も大歓迎です. できるかぎりサポートし + ます. + +●謝辞 + + 原作者および FSF に感謝します. + + ドキュメント作成に関して助言をくださった堂園和郎氏 + (dohzono@sdsft.kme.mei.co.jp) に感謝します. + + これまで転載/バグ報告をくださった方々に感謝します. 実名を挙げさせて + 頂きたかったのですがハードディスクのトラブルでほとんどのメールを消失 + させてしまいました. + + 最後に, 貴重なディスクスペースを grep+mb のために割いてご使用頂いて + いるすべての利用者の方々に感謝します. + +●「私」の連絡先 + + 〒810 福岡市中央区梅光園団地 7-207 (注: 転居しました) + TEL/FAX: 092-731-4025 (TEL/FAX 自動切替え) + 092-724-6342 (TEL のみ) + E-mail: NBC02362@niftyserve.or.jp 谷本孝浩 + +# Local variables: +# mode: indented-text +# indent-tabs-mode: nil +# tab-stop-list: (4 8 16 24 32 40 48 56 64 72 80) +# left-margin: 4 +# fill-column: 72 +# fill-prefix: " " +# version-control: never +# End: diff -ru2N grep-2.0/README.MSC grep+mb1.04/README.MSC --- grep-2.0/README.MSC Thu Jan 1 09:00:00 1970 +++ grep+mb1.04/README.MSC Sat Mar 5 16:14:14 1994 @@ -0,0 +1,99 @@ +PC-9801 用 MS-C version 6.00A の引数のセットアップルーチンにはバグがあり +ます. + +#include + +int +main(int argc, char **argv) +{ + int i; + + for (i = 0; i <= argc; i++) + printf("argv[%d] == %s\n", i, argv[i]); + return 0; +} + +をコンパイル, リンクした FOO.EXE に + + A>foo "\\" abc + +などの引数を渡して実行すると, バグが確認できます. また, ワイルドカード +展開ルーチンにもバグがあり, 上記のプログラムを SETARGV.OBJ とともにリン +クして + + A>foo \DOS\*.com + +などの引数で実行すると, おかしな展開の仕方をしてしまいます. + +このバグは SOURCE/STARTUP 下の DOS/STDARGV.ASM および WILD.C に以下のパッ +チを当てると修正できるようです. パッチを当てて STARTUP.BAT でコンパイル +してください. その後, 例えばラージモデル用のライブラリを修正する場合, +L/DOS/STDARGV.OBJ, L/DOS/_SETARGV.OBJ, L/WILD.OBJ をそれぞれ +KSTDARGV.OBJ, _KSTARGV.OBJ, KWILD.OBJ とリネームし, + + lib \msc6\lib\llibce.lib-+dos\kstdargv.obj-+dos\_kstargv.obj-+kwild.obj; + +などとしてモジュールを更新してください. 念のためこの作業を行う前に, + + lib \msc6\lib\llibce.lib*kstdargv.obj*_kstargv.obj*kwild.obj; + +などで, kstdargv.obj, _kstargv.obj, kwild.obj のバックアップをとって置く +といいでしょう. + +なお, このパッチは当然のことながら無保証です. + +Mar. 5, 1994 t^2 + +*** stdargv.org Mon Oct 8 19:50:46 1990 +--- stdargv.asm Thu Jul 22 17:50:44 1993 +*************** +*** 409,415 **** + shr cx,1 + adc dx,cx ; add 1 for every pair of backslashes + test al,1 ; plus 1 for the " if odd number of \ +! jz arg310 ; [J1] + jmp arg210 ; [J1] + ; + ; Command line is fully parsed - compute number of bytes needed +--- 409,415 ---- + shr cx,1 + adc dx,cx ; add 1 for every pair of backslashes + test al,1 ; plus 1 for the " if odd number of \ +! jnz arg310 ; ! Jul.21.93 t^2 + jmp arg210 ; [J1] + ; + ; Command line is fully parsed - compute number of bytes needed + +*** wild.org Mon Oct 8 19:49:48 1990 +--- wild.c Sat Mar 5 00:42:12 1994 +*************** +*** 186,197 **** + char *ptr2 = arg; // [J1] + + if(ptr != arg) { // [J1] +! while(ptr2 + 1 != ptr && *ptr2 != SLASHCHAR && *ptr2 != FWDSLASHCHAR +! && *ptr2 != ':') { // [J1] + if(iskanji(*ptr2)) ptr2++; // [J1] + ptr2++; // [J1] + } // [J1] +! ptr = ptr2; // [J1] + } // [J1] + + if (*ptr == ':' && ptr != arg+1) /* weird name, just add it as is */ +--- 186,201 ---- + char *ptr2 = arg; // [J1] + + if(ptr != arg) { // [J1] +! char *ptr3 = arg; +! +! while (ptr2 < ptr) { +! if (*ptr2 == SLASHCHAR || *ptr2 == FWDSLASHCHAR +! || *ptr2 == ':') +! ptr3 = ptr2; + if(iskanji(*ptr2)) ptr2++; // [J1] + ptr2++; // [J1] + } // [J1] +! ptr = ptr3; + } // [J1] + + if (*ptr == ':' && ptr != arg+1) /* weird name, just add it as is */ diff -ru2N grep-2.0/configure grep+mb1.04/configure --- grep-2.0/configure Sat May 22 13:20:23 1993 +++ grep+mb1.04/configure Fri Jul 9 13:05:45 1993 @@ -566,5 +566,5 @@ fi -for func in getpagesize memchr strerror valloc +for func in getpagesize memchr strerror valloc bcopy memmove strcasecmp do trfunc=HAVE_`echo $func | tr '[a-z]' '[A-Z]'` diff -ru2N grep-2.0/configure.in grep+mb1.04/configure.in --- grep-2.0/configure.in Sat May 22 13:20:16 1993 +++ grep+mb1.04/configure.in Fri Jul 9 13:05:32 1993 @@ -12,5 +12,5 @@ AC_SIZE_T AC_ALLOCA -AC_HAVE_FUNCS(getpagesize memchr strerror valloc) +AC_HAVE_FUNCS(getpagesize memchr strerror valloc bcopy memmove strcasecmp) AC_CHAR_UNSIGNED AC_CONST diff -ru2N grep-2.0/dfa.c grep+mb1.04/dfa.c --- grep-2.0/dfa.c Mon May 31 08:02:20 1993 +++ grep+mb1.04/dfa.c Sat Jul 10 01:17:14 1993 @@ -18,4 +18,6 @@ /* Written June, 1988 by Mike Haertel Modified July, 1988 by Arthur David Olson to assist BMG speedups */ +/* Multi-byte extension added May, 1993 by t^2 (Takahiro Tanimoto) + Last change: Jul. 10, 1993 by t^2 */ #include @@ -35,4 +37,8 @@ #undef index #define index strchr +#undef bcopy +#define bcopy(s, d, n) memcpy(d, s, n) +#undef bzero +#define bzero(d, n) memset(d, 0, n) #else #include @@ -71,4 +77,5 @@ #include "dfa.h" #include "regex.h" +#include "mbc.h" #if __STDC__ @@ -141,5 +148,8 @@ fprintf(stderr, "END"); else if (t < NOTCHAR) - fprintf(stderr, "%c", t); + if (t & 0x80) + fprintf(stderr, "0x%02x", (unsigned char)t); + else + fprintf(stderr, "%c", t); else { @@ -239,4 +249,16 @@ } +static int +isemptyset(s) + charclass s; +{ + int i; + + for (i = 0; i < CHARCLASS_INTS; i++) + if (s[i]) + return 0; + return 1; +} + /* A pointer to the current dfa is kept here during parsing. */ static struct dfa *dfa; @@ -259,5 +281,6 @@ /* Syntax bits controlling the behavior of the lexical analyzer. */ -static int syntax_bits, syntax_bits_set; +static unsigned long syntax_bits; +static int syntax_bits_set; /* Flag for case-folding letters into sets. */ @@ -267,5 +290,5 @@ void dfasyntax(bits, fold) - int bits; + unsigned long bits; int fold; { @@ -289,4 +312,66 @@ static int minrep, maxrep; /* Repeat counts for {m,n}. */ +static charclass cs_cset[8]; +static token cs_tok[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + +static enum { + MBEXTTOK_NONE = -1, + MBEXTTOK_NOTCHAR = 256, + MBEXTTOK_ORMBC = MBEXTTOK_NOTCHAR, + MBEXTTOK_ORMBC_NL, + MBEXTTOK_CLASS, + MBEXTTOK_INVCLASS, +} mbexttok = MBEXTTOK_NONE; + +static charclass mbcset_set; +static charclass mbcset_all; +static charclass mbcset[128]; /* 128*256/8 = 4 Kbytes */ + +/* 頻繁に使用される (と思われる) 文字集合をトークンとして返す. + n = 0 ... 1バイト文字全体の集合. + 1 ... 2バイト文字の1バイト目全体の集合. + 2 ... 2バイト文字の2バイト目全体の集合. + +4 ... '\n'を除外しない. */ +static token +setcodeset(n) + int n; +{ + token c; + + if (!cs_tok[n]) { + zeroset(cs_cset[n]); + switch (n) { + case 0: + case 4: + /* 1バイト文字全体の集合. */ + for (c = 0; c < NOTCHAR; c++) + if (ismbchar(c)) + setbit(c, cs_cset[n]); + notset(cs_cset[n]); + break; + case 1: + case 5: + /* 2バイト文字の1文字目全体の集合. */ + for (c = 0; c < NOTCHAR; c++) + if (ismbchar(c)) + setbit(c, cs_cset[n]); + break; + case 2: + case 6: + /* 2バイト文字の2文字目全体の集合. */ + notset(cs_cset[n]); + break; + } + if (!(n & 4)) { + if (syntax_bits & RE_DOT_NOT_NULL || n != 0) + clrbit('\0', cs_cset[n]); + if (!(syntax_bits & RE_DOT_NEWLINE) || n != 0) + clrbit('\n', cs_cset[n]); + } + cs_tok[n] = CSET + charclass_index(cs_cset[n]); + } + return cs_tok[n]; +} + /* Note that characters become unsigned here. */ #define FETCH(c, eoferr) \ @@ -362,4 +447,5 @@ it means that just about every case begins with "if (backslash) ...". */ + mbexttok = MBEXTTOK_NONE; for (i = 0; i < 2; ++i) { @@ -543,14 +629,19 @@ if (backslash) goto normal_char; + if (current_mbctype != MBCTYPE_ASCII) + mbexttok = MBEXTTOK_ORMBC; + laststart = 0; + return setcodeset(0); + + case 'w': + if (!backslash) + goto normal_char; zeroset(ccl); - notset(ccl); - if (!(syntax_bits & RE_DOT_NEWLINE)) - clrbit('\n', ccl); - if (syntax_bits & RE_DOT_NOT_NULL) - clrbit('\0', ccl); + for (c2 = 0; c2 < NOTCHAR; ++c2) + if (ISALNUM(c2)) + setbit(c2, ccl); laststart = 0; return lasttok = CSET + charclass_index(ccl); - case 'w': case 'W': if (!backslash) @@ -558,8 +649,7 @@ zeroset(ccl); for (c2 = 0; c2 < NOTCHAR; ++c2) - if (ISALNUM(c2)) + if (!ISALNUM(c2) && !ismbchar(c2)) setbit(c2, ccl); - if (c == 'W') - notset(ccl); + mbexttok = MBEXTTOK_ORMBC_NL; laststart = 0; return lasttok = CSET + charclass_index(ccl); @@ -579,4 +669,6 @@ do { + unsigned char ch = 0, c2h = 0; + /* Nobody ever said this had to be fast. :-) Note that if we're looking at some other [:...:] @@ -599,4 +691,8 @@ if (c == '\\' && (syntax_bits & RE_BACKSLASH_ESCAPE_IN_LISTS)) FETCH(c, "Unbalanced ["); + if (ismbchar(c)) { + ch = (unsigned char)c; + FETCH(c, "Multi-byte char incomplete"); + } FETCH(c1, "Unbalanced ["); if (c1 == '-') @@ -616,19 +712,83 @@ && (syntax_bits & RE_BACKSLASH_ESCAPE_IN_LISTS)) FETCH(c2, "Unbalanced ["); + if (ismbchar(c2)) { + c2h = (unsigned char)c2; + FETCH(c2, "Multi-byte char incomplete"); + } FETCH(c1, "Unbalanced ["); } } - else + else { + c2h = ch; c2 = c; - while (c <= c2) - { - setbit(c, ccl); - if (case_fold) - if (ISUPPER(c)) - setbit(tolower(c), ccl); - else if (ISLOWER(c)) - setbit(toupper(c), ccl); - ++c; + } + if (ch < c2h || (ch == c2h && c <= c2)) { + if (ch == 0) { + ch = (unsigned char)c2; + if (c2h > 0) + ch = NOTCHAR - 1; + for (; (unsigned char)c <= ch; c++) { + setbit(c, ccl); + if (case_fold) { + if (ISUPPER(c)) + setbit(tolower(c), ccl); + else if (ISLOWER(c)) + setbit(toupper(c), ccl); + } + } + ch = 0x80; + c = 0x00; } + if (ch <= c2h) { + if (mbexttok < 0) { + mbexttok = MBEXTTOK_CLASS; + zeroset(mbcset_set); + zeroset(mbcset_all); + } + if (ch < c2h && c != 0x00) { /* 最初の半端 */ + int t; + + if (ismbchar(ch) + && ((t = tstbit(ch, mbcset_set)) + || !tstbit(ch, mbcset_all))) { + if (!t) { + setbit(ch, mbcset_set); + zeroset(mbcset[ch - 0x80]); + } + for (; c < NOTCHAR; c++) + setbit(c, mbcset[ch - 0x80]); + } + ch++; + c = 0x00; + } + if (ch < c2h || (ch == c2h && c == 0x00 && c2 == 0xff)) { + if (c == 0x00 && c2 == 0xff) + c2h++; + for (; ch < c2h; ch++) + if (ismbchar(ch)) { + clrbit(ch, mbcset_set); + setbit(ch, mbcset_all); + } + if (c == 0x00 && c2 == 0xff) + c2h--; + c = 0x00; + } + if (ch <= c2h) { + int t; + + /* ここでは必ず c <= c2 となっている. */ + if (ismbchar(ch) + && ((t = tstbit(ch, mbcset_set)) + || !tstbit(ch, mbcset_all))) { + if (!t) { + setbit(ch, mbcset_set); + zeroset(mbcset[ch - 0x80]); + } + for (; c <= c2; c++) + setbit(c, mbcset[ch - 0x80]); + } + } + } + } skip: ; @@ -640,5 +800,20 @@ if (syntax_bits & RE_HAT_LISTS_NOT_NEWLINE) clrbit('\n', ccl); + if (mbexttok == MBEXTTOK_CLASS) { + mbexttok = MBEXTTOK_INVCLASS; + if (!isemptyset(mbcset_set)) { + for (c = 0x80; c <= 0xff; c++) + if (tstbit(c, mbcset_set)) + notset(mbcset[c - 0x80]); + } + notset(mbcset_all); + } + else + mbexttok = MBEXTTOK_ORMBC_NL; } + if (current_mbctype != MBCTYPE_ASCII) + for (c = 0x80; c <= 0xff; c++) + if (ismbchar(c)) + clrbit(c, ccl); laststart = 0; return lasttok = CSET + charclass_index(ccl); @@ -647,4 +822,8 @@ normal_char: laststart = 0; + if (ismbchar(c)) { + FETCH(mbexttok, "Multi-byte char incomplete"); + return c; + } if (case_fold && ISALPHA(c)) { @@ -746,5 +925,67 @@ atom() { - if ((tok >= 0 && tok < NOTCHAR) || tok >= CSET || tok == BACKREF + if (mbexttok >= 0) { + if (mbexttok < MBEXTTOK_NOTCHAR) { + addtok(tok); + addtok(mbexttok); + addtok(CAT); + } + else + switch (mbexttok) { + case MBEXTTOK_ORMBC: + case MBEXTTOK_ORMBC_NL: + addtok(tok); + if (mbexttok == MBEXTTOK_ORMBC) { + addtok(setcodeset(1)); + addtok(setcodeset(2)); + } + else { + addtok(setcodeset(5)); + addtok(setcodeset(6)); + } + addtok(CAT); + addtok(OR); + break; + case MBEXTTOK_CLASS: + case MBEXTTOK_INVCLASS: + { + token c; + + addtok(tok); + if (!isemptyset(mbcset_set)) + for (c = 0x80; c <= 0xff; c++) + if (tstbit(c, mbcset_set)) { + /* Make sure all bits in mbcset_all valid. */ + clrbit(c, mbcset_all); + addtok(c); + if (mbexttok == MBEXTTOK_CLASS) { + clrbit('\n', mbcset[c - 0x80]); + clrbit('\0', mbcset[c - 0x80]); + } + else { + setbit('\n', mbcset[c - 0x80]); + setbit('\0', mbcset[c - 0x80]); + } + addtok(CSET + charclass_index(mbcset[c - 0x80])); + addtok(CAT); + addtok(OR); + } + if (!isemptyset(mbcset_all)) { + addtok(CSET + charclass_index(mbcset_all)); + if (mbexttok == MBEXTTOK_CLASS) + addtok(setcodeset(2)); + else + addtok(setcodeset(6)); + addtok(CAT); + addtok(OR); + } + } + break; + default: + break; + } + tok = lex(); + } + else if ((tok >= 0 && tok < NOTCHAR) || tok >= CSET || tok == BACKREF || tok == BEGLINE || tok == ENDLINE || tok == BEGWORD || tok == ENDWORD || tok == LIMWORD || tok == NOTLIMWORD) @@ -1904,4 +2145,6 @@ d->musts = 0; + + bzero(cs_tok, sizeof cs_tok); } @@ -1916,8 +2159,8 @@ if (case_fold) /* dummy folding in service of dfamust() */ { - char *copy; + char *copy, *p; int i; - copy = malloc(len); + p = copy = malloc(len + 7); if (!copy) dfaerror("out of memory"); @@ -1925,23 +2168,61 @@ /* This is a kludge. */ case_fold = 0; + if (current_mbctype != MBCTYPE_ASCII && searchflag) { + *p++ = '^'; + *p++ = '.'; + *p++ = '*'; + if (!(syntax_bits & RE_NO_BK_PARENS)) + *p++ = '\\'; + *p++ = '('; + } for (i = 0; i < len; ++i) if (ISUPPER(s[i])) - copy[i] = tolower(s[i]); + *p++ = tolower((unsigned char)s[i]); else - copy[i] = s[i]; + *p++ = s[i]; + if (current_mbctype != MBCTYPE_ASCII && searchflag) { + if (!(syntax_bits & RE_NO_BK_PARENS)) + *p++ = '\\'; + *p++ = ')'; + } dfainit(d); - dfaparse(copy, len, d); - free(copy); + dfaparse(copy, p - copy, d); dfamust(d); d->cindex = d->tindex = d->depth = d->nleaves = d->nregexps = 0; + bzero(cs_tok, sizeof cs_tok); case_fold = 1; - dfaparse(s, len, d); + if (current_mbctype != MBCTYPE_ASCII && searchflag) { + bcopy(s, copy + (syntax_bits & RE_NO_BK_PARENS ? 4 : 5), len); + dfaparse(copy, p - copy, d); + } + else + dfaparse(s, len, d); dfaanalyze(d, searchflag); + free(copy); } else { dfainit(d); - dfaparse(s, len, d); + if (current_mbctype != MBCTYPE_ASCII && searchflag) { + char *copy, *p; + + p = copy = malloc(len + 7); + *p++ = '^'; + *p++ = '.'; + *p++ = '*'; + if (!(syntax_bits & RE_NO_BK_PARENS)) + *p++ = '\\'; + *p++ = '('; + bcopy(s, p, len); + p += len; + if (!(syntax_bits & RE_NO_BK_PARENS)) + *p++ = '\\'; + *p++ = ')'; + dfaparse(copy, p - copy, d); + free(copy); + } + else + dfaparse(s, len, d); dfamust(d); dfaanalyze(d, searchflag); diff -ru2N grep-2.0/dfa.h grep+mb1.04/dfa.h --- grep-2.0/dfa.h Mon Apr 12 06:17:22 1993 +++ grep+mb1.04/dfa.h Wed Jul 7 17:02:13 1993 @@ -15,4 +15,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* Multi-byte extension added May, 1993 by t^2 (Takahiro Tanimoto) + Last change: Jul. 7, 1993 by t^2 */ /* Written June, 1988 by Mike Haertel */ @@ -306,5 +308,5 @@ /* dfasyntax() takes two arguments; the first sets the syntax bits described earlier in this file, and the second sets the case-folding flag. */ -extern void dfasyntax(int, int); +extern void dfasyntax(unsigned long, int); /* Compile the given string of the given length into the given struct dfa. diff -ru2N grep-2.0/getpagesize.h grep+mb1.04/getpagesize.h --- grep-2.0/getpagesize.h Fri May 21 14:18:58 1993 +++ grep+mb1.04/getpagesize.h Sat Jul 10 02:19:10 1993 @@ -1,2 +1,4 @@ +/* Multi-byte extension added Jul., 1993 by t^2 (Takahiro Tanimoto) + Last change: Jul. 10, 1993 by t^2 */ #ifdef BSD #ifndef BSD4_1 @@ -35,5 +37,9 @@ #endif /* no EXEC_PAGESIZE */ #else /* !HAVE_SYS_PARAM_H */ +#ifndef MSDOS #define getpagesize() 8192 /* punt totally */ +#else +#define getpagesize() 4096 +#endif #endif /* !HAVE_SYS_PARAM_H */ #endif /* no _SC_PAGESIZE */ diff -ru2N grep-2.0/grep.c grep+mb1.04/grep.c --- grep-2.0/grep.c Sun May 23 14:52:52 1993 +++ grep+mb1.04/grep.c Thu Jun 2 17:01:53 1994 @@ -17,4 +17,6 @@ Written July 1992 by Mike Haertel. */ +/* Multi-byte extension added May, 1993 by t^2 (Takahiro Tanimoto) + Last change: Jun. 2, 1994 by t^2 */ #include @@ -22,6 +24,8 @@ #ifndef errno +#ifndef MSDOS extern int errno; #endif +#endif #ifdef STDC_HEADERS @@ -59,4 +63,5 @@ #include "getpagesize.h" #include "grep.h" +#include "mbc.h" #undef MAX @@ -315,6 +320,6 @@ cc = read(bufdesc, buffer + bufsalloc, bufalloc - bufsalloc); #endif - if (cc > 0) - buflim = buffer + bufsalloc + cc; + if (cc != -1) + buflim = buffer + bufsalloc + (unsigned)cc; else buflim = buffer + bufsalloc; @@ -332,10 +337,10 @@ /* Internal variables to keep track of byte count, context, etc. */ -static size_t totalcc; /* Total character count before bufbeg. */ +static unsigned long totalcc; /* Total character count before bufbeg. */ static char *lastnl; /* Pointer after last newline counted. */ static char *lastout; /* Pointer after last character output; NULL if no character has been output or if it's conceptually before bufbeg. */ -static size_t totalnl; /* Total newline count before lastnl. */ +static unsigned long totalnl; /* Total newline count before lastnl. */ static int pending; /* Pending lines of output. */ @@ -363,5 +368,5 @@ { nlscan(beg); - printf("%d%c", ++totalnl, sep); + printf("%lu%c", ++totalnl, sep); lastnl = lim; } @@ -519,5 +524,5 @@ for (;;) { - if (fillbuf(save) < 0) + if (fillbuf(save) == -1) { error(filename, errno); @@ -564,8 +569,10 @@ } -static char version[] = "GNU grep version 2.0"; +static char version[] = "GNU grep version 2.0\ + + multi-byte extension 1.04"; #define USAGE \ - "usage: %s [-[[AB] ]] [-[CEFGVchilnqsvwx]] [-[ef]] []\n" + "usage: %s [-[[AB] ]] [-[CEFGVchilnqsvwx]] [-W ctype=...]\n\ + [-[ef]] []\n" static void @@ -594,4 +601,32 @@ } +#ifndef HAVE_STRCASECMP + +static int +#ifdef __STDC__ +strcasecmp(const char *s1, const char *s2) +#else +strcasecmp(s1, s2) + char *s1, *s2; +#endif +{ + unsigned char c1, c2; + + while ((c1 = *s1++)) { + if ((unsigned char)(c1 - 'A') <= (unsigned char)('Z' - 'A')) + c1 += 'a' - 'A'; + c2 = *s2++; + if ((unsigned char)(c2 - 'A') <= (unsigned char)('Z' - 'A')) + c2 += 'a' - 'A'; + if (c1 != c2) { + --s2; + break; + } + } + return c1 - (unsigned char)*s2; +} + +#endif + int main(argc, argv) @@ -607,7 +642,27 @@ extern int optind; - prog = argv[0]; - if (prog && strrchr(prog, '/')) - prog = strrchr(prog, '/') + 1; + if ((prog = argv[0]) && prog[0]) { + char c, *p; +#ifdef MSDOS + static char progname[8 + 1]; +#endif + + for (p = prog; (c = *p++); ) + if (c == '/' +#ifdef MSDOS + || c == '\\' || c == ':' +#endif + ) + prog = p; +#ifdef MSDOS + for (p = progname; p < &progname[8] && (c = *prog++) && c != '.'; ) { + if ((unsigned char)(c - 'A') <= (unsigned char)('Z' - 'A')) + c += 'a' - 'A'; + *p++ = c; + } + *p++ = '\0'; + prog = argv[0] = progname; +#endif + } keys = NULL; @@ -620,5 +675,5 @@ matcher = NULL; - while ((opt = getopt(argc, argv, "0123456789A:B:CEFGVX:bce:f:hiLlnqsvwxy")) + while ((opt = getopt(argc, argv, "0123456789A:B:CEFGVX:bce:f:hiLlnqsvwxyW:")) != EOF) switch (opt) @@ -747,4 +802,19 @@ case 'x': match_lines = 1; + break; + case 'W': + if (strcasecmp(optarg, "ctype=ASCII") == 0) { + mbcinit(MBCTYPE_ASCII); + break; + } + if (strcasecmp(optarg, "ctype=EUC") == 0) { + mbcinit(MBCTYPE_EUC); + break; + } + if (strcasecmp(optarg, "ctype=SJIS") == 0) { + mbcinit(MBCTYPE_SJIS); + break; + } + fatal("unknown argument to -Wctype", 0); break; default: diff -ru2N grep-2.0/kwset.c grep+mb1.04/kwset.c --- grep-2.0/kwset.c Mon May 3 04:26:20 1993 +++ grep+mb1.04/kwset.c Fri Jul 9 14:54:46 1993 @@ -19,4 +19,6 @@ The author may be reached (Email) at the address mike@ai.mit.edu, or (US mail) as Mike Haertel c/o Free Software Foundation. */ +/* Multi-byte extension added Jul, 1993 by t^2 (Takahiro Tanimoto) + Last change: Jul. 9, 1993 by t^2 */ /* The algorithm implemented by these routines bears a startling resemblence @@ -592,5 +594,5 @@ if (d != 0) continue; - if (tp[-2] == gc) + if (U(tp[-2]) == gc) { for (i = 3; i <= len && U(tp[-i]) == U(sp[-i]); ++i) diff -ru2N grep-2.0/mbc.c grep+mb1.04/mbc.c --- grep-2.0/mbc.c Thu Jan 1 09:00:00 1970 +++ grep+mb1.04/mbc.c Fri Jul 9 14:38:28 1993 @@ -0,0 +1,98 @@ +/* Functions for multi-byte support. + Created for grep multi-byte extension Jul., 1993 by t^2 (Takahiro Tanimoto) + Last change: Jul. 9, 1993 by t^2 */ +#include "mbc.h" + +static const unsigned char mbctab_ascii[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const unsigned char mbctab_euc[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static const unsigned char mbctab_sjis[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +#ifdef EUC +const unsigned char *mbctab = mbctab_euc; +int current_mbctype = MBCTYPE_EUC; +#else +#ifdef SJIS +const unsigned char *mbctab = mbctab_sjis; +int current_mbctype = MBCTYPE_SJIS; +#else +const unsigned char *mbctab = mbctab_ascii; +int current_mbctype = MBCTYPE_ASCII; +#endif +#endif + +void +#ifdef __STDC__ +mbcinit(int mbctype) +#else +mbcinit(mbctype) + int mbctype; +#endif +{ + switch (mbctype) { + case MBCTYPE_ASCII: + mbctab = mbctab_ascii; + current_mbctype = MBCTYPE_ASCII; + break; + case MBCTYPE_EUC: + mbctab = mbctab_euc; + current_mbctype = MBCTYPE_EUC; + break; + case MBCTYPE_SJIS: + mbctab = mbctab_sjis; + current_mbctype = MBCTYPE_SJIS; + break; + } +} diff -ru2N grep-2.0/mbc.h grep+mb1.04/mbc.h --- grep-2.0/mbc.h Thu Jan 1 09:00:00 1970 +++ grep+mb1.04/mbc.h Fri Jul 9 14:40:03 1993 @@ -0,0 +1,38 @@ +#ifndef MBC_H +#define MBC_H 1 +/* Definitions for multi-byte support. + Created for grep multi-byte extension Jul., 1993 by t^2 (Takahiro Tanimoto) + Last change: Jul. 9, 1993 by t^2 */ + +#ifndef const +#ifndef __STDC__ +#ifdef __GNUC__ +#define const __const__ +#define volatile __volatile__ +#else +#define const +#define volatile +#endif +#endif +#endif + +#ifndef _ +#ifdef __STDC__ +#define _(x) x +#else +#define _(x) () +#endif +#endif + +#define MBCTYPE_ASCII 0 +#define MBCTYPE_EUC 1 +#define MBCTYPE_SJIS 2 + +extern const unsigned char *mbctab; +extern int current_mbctype; + +void mbcinit _((int)); + +#define ismbchar(c) mbctab[(unsigned char)c] + +#endif /* !MBC_H */ diff -ru2N grep-2.0/obstack.h grep+mb1.04/obstack.h --- grep-2.0/obstack.h Sat May 22 11:55:23 1993 +++ grep+mb1.04/obstack.h Sat Jul 10 04:47:06 1993 @@ -15,4 +15,6 @@ along with this program; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* Multi-byte extension added Jul., 1993 by t^2 (Takahiro Tanimoto) + Last change: Jul. 10, 1993 by t^2 */ /* Summary: @@ -136,4 +138,5 @@ #endif +#ifndef PTR_INT_TYPE #ifdef __STDC__ #define PTR_INT_TYPE ptrdiff_t @@ -141,4 +144,5 @@ #define PTR_INT_TYPE long #endif +#endif struct _obstack_chunk /* Lives at front of each chunk. */ @@ -151,5 +155,5 @@ struct obstack /* control current object in current chunk */ { - long chunk_size; /* preferred size to allocate chunks in */ + unsigned chunk_size; /* preferred size to allocate chunks in */ struct _obstack_chunk* chunk; /* address of current struct obstack_chunk */ char *object_base; /* address of object we are building */ diff -ru2N grep-2.0/regex.c grep+mb1.04/regex.c --- grep-2.0/regex.c Fri May 21 14:11:40 1993 +++ grep+mb1.04/regex.c Thu Aug 19 04:37:03 1993 @@ -19,4 +19,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* Multi-byte extension added May, 1993 by t^2 (Takahiro Tanimoto) + Last change: Aug. 19, 1993 by t^2 */ /* AIX requires this to be the first thing in the file. */ @@ -54,6 +56,33 @@ #define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) #endif +#ifdef HAVE_MEMMOVE #ifndef bcopy -#define bcopy(s, d, n) memcpy ((d), (s), (n)) +#define bcopy(s, d, n) memmove ((d), (s), (n)) +#endif +#else +#ifndef HAVE_BCOPY +static void +#ifdef __STDC__ +bcopy (const void *s0, void *d0, size_t n) +#else +bcopy (s, d, n) + const void *s0; + void *d; + size_t n; +#endif +{ + const char *s = s0; + char *d = d0; + + if (s < d) { + s += n, d += n; + while (n--) + *--d = *--s; + } + else + while (n--) + *d++ = *s++; +} +#endif #endif #ifndef bzero @@ -124,4 +153,5 @@ /* Get the interface, including the syntax bits. */ #include "regex.h" +#include "mbc.h" /* isalpha etc. are used for the character classes. */ @@ -462,4 +492,19 @@ #endif /* DEBUG */ + +#define STORE_MBC(p, c) \ + ((p)[0] = (unsigned char) ((c) >> 8), (p)[1] = (unsigned char) (c)) +#define STORE_MBC_AND_INCR(p, c) \ + (*(p)++ = (unsigned char) ((c) >> 8), *(p)++ = (unsigned char) (c)) + +#define EXTRACT_MBC(p) \ + ((unsigned char) (p)[0] << 8 | (unsigned char) (p)[1]) +#define EXTRACT_MBC_AND_INCR(p) \ + ((p) += 2, (unsigned char) (p)[-2] << 8 | (unsigned char) (p)[-1]) + +#define EXTRACT_UNSIGNED(p) \ + ((unsigned char) (p)[0] | (unsigned char) (p)[1] << 8) +#define EXTRACT_UNSIGNED_AND_INCR(p) \ + ((p) += 2, (unsigned char) (p)[-2] | (unsigned char) (p)[-1] << 8) /* If DEBUG is defined, Regex prints many voluminous messages about what @@ -558,4 +603,8 @@ { putchar ('/'); + if (ismbchar (*p) && 2 <= mcnt) { + printf ("/%.2s", (char *) p), p += 2, --mcnt; + continue; + } printchar (*p++); } @@ -618,7 +667,14 @@ printchar (last); - putchar (']'); - p += 1 + *p; + { + unsigned short i, size; + + size = EXTRACT_UNSIGNED_AND_INCR (p); + for (i = 0; i < size; i++) + printf ("%.2s-%.2s", (char *) p, (char *) p + 2), + p += 4; + } + putchar (']'); } break; @@ -779,5 +835,5 @@ printf ("not_bol: %d\t", bufp->not_bol); printf ("not_eol: %d\t", bufp->not_eol); - printf ("syntax: %d\n", bufp->syntax); + printf ("syntax: %lu\n", bufp->syntax); /* Perhaps we should print the translate table? */ } @@ -878,5 +934,7 @@ static boolean at_begline_loc_p (), at_endline_loc_p (); static boolean group_in_compile_stack (); +#if 0 static reg_errcode_t compile_range (); +#endif /* Fetch the next character in the uncompiled pattern---translating it @@ -887,5 +945,6 @@ do {if (p == pend) return REG_EEND; \ c = (unsigned char) *p++; \ - if (translate) c = translate[c]; \ + if (translate && !ismbchar (c)) \ + c = (unsigned char) translate[(unsigned char) c]; \ } while (0) @@ -905,5 +964,7 @@ `char *', to avoid warnings when a string constant is passed. But when we use a character as a subscript we must make it unsigned. */ -#define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d)) +#define TRANSLATE(d) (translate \ + ? (unsigned char) translate[(unsigned char) (d)] \ + : (d)) @@ -1075,4 +1136,159 @@ || STREQ (string, "cntrl") || STREQ (string, "blank")) +/* Handle charset(_not)?. + + Structure of charset(_not)? in compiled pattern. + + struct { + unsinged char id; charset(_not)? + unsigned char sbc_size; + unsigned char sbc_map[sbc_size]; same as original up to here. + unsigned short mbc_size; number of intervals. + struct { + unsigned short beg; beginning of interval. + unsigned short end; end of interval. + } intervals[mbc_size]; + }; */ + +static reg_errcode_t +#ifdef __STDC__ +set_list_bits (unsigned short c1, unsigned short c2, + reg_syntax_t syntax, unsigned char *b, const char *translate) +#else +set_list_bits (c1, c2, syntax, b, translate) + unsigned short c1, c2; + reg_syntax_t syntax; + unsigned char *b; + const char *translate; +#endif +{ + unsigned char sbc_size = b[-1]; + unsigned short mbc_size = EXTRACT_UNSIGNED (&b[sbc_size]); + unsigned short beg, end, upb; + + if (c1 > c2) + return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; + if (c1 < 1 << BYTEWIDTH) { + upb = c2; + if (1 << BYTEWIDTH <= upb) + upb = (1 << BYTEWIDTH) - 1; /* The last single-byte char */ + if (sbc_size <= upb / BYTEWIDTH) { + /* Allocate maximum size so it never happens again. */ + /* NOTE: memcpy() would not work here. */ + bcopy (&b[sbc_size], &b[(1 << BYTEWIDTH) / BYTEWIDTH], 2 + mbc_size*4); + bzero (&b[sbc_size], (1 << BYTEWIDTH) / BYTEWIDTH - sbc_size); + b[-1] = sbc_size = (1 << BYTEWIDTH) / BYTEWIDTH; + } + if (!translate) { + for (; c1 <= upb; c1++) + if (!ismbchar (c1)) + SET_LIST_BIT (c1); + } + else + for (; c1 <= upb; c1++) + if (!ismbchar (c1)) + SET_LIST_BIT (TRANSLATE (c1)); + if (c2 < 1 << BYTEWIDTH) + return REG_NOERROR; + c1 = 0x8000; /* The first wide char */ + } + b = &b[sbc_size + 2]; + + /* intervals[beg] + ●----------● ●----------● + c1 + ○----------------------● + + 上図のような区間のインデックス beg を決定する. */ + for (beg = 0, upb = mbc_size; beg < upb; ) { + unsigned short mid = (beg + upb) >> 1; + + if (c1 - 1 > EXTRACT_MBC (&b[mid*4 + 2])) + beg = mid + 1; + else + upb = mid; + } + + /* intervals[end] + ●-------● ●----------● + c2 + ●---------------○ + + 上図のような区間のインデックス end を決定する. */ + for (end = beg, upb = mbc_size; end < upb; ) { + unsigned short mid = (end + upb) >> 1; + + if (c2 >= EXTRACT_MBC (&b[mid*4]) - 1) + end = mid + 1; + else + upb = mid; + } + + if (beg != end) { + /* 既存の区間を少なくとも1つ統合する場合, + 区間の始点, 終点を修正する. */ + if (c1 > EXTRACT_MBC (&b[beg*4])) + c1 = EXTRACT_MBC (&b[beg*4]); + if (c2 < EXTRACT_MBC (&b[end*4 - 2])) + c2 = EXTRACT_MBC (&b[end*4 - 2]); + } + if (end < mbc_size && end != beg + 1) + /* 追加される区間の後ろに既存の区間を移動する. */ + /* NOTE: memcpy() would not work here. */ + bcopy (&b[end*4], &b[(beg + 1)*4], (mbc_size - end)*4); + STORE_MBC (&b[beg*4 + 0], c1); + STORE_MBC (&b[beg*4 + 2], c2); + mbc_size += beg + 1 - end; + STORE_NUMBER (&b[-2], mbc_size); + return REG_NOERROR; +} + +static int +#ifdef __STDC__ +is_in_list (unsigned short c, const unsigned char *b) +#else +is_in_list (c, b) + unsigned short c; + const unsigned char *b; +#endif +{ + unsigned short size; + int in = (re_opcode_t) b[-1] == charset_not; + + size = *b++; + if (c < 1 << BYTEWIDTH) { + if (c / BYTEWIDTH < size && b[c / BYTEWIDTH] & 1 << c % BYTEWIDTH) + in = !in; + } + else { + unsigned short i, j; + + b += size + 2; + size = EXTRACT_UNSIGNED (&b[-2]); + + /* intervals[i] + ●-------● ●--------● + c + ○----------------● + + 上図のような区間のインデックス i を決定する. */ + for (i = 0, j = size; i < j; ) { + unsigned short k = (i + j) >> 1; + + if (c > EXTRACT_MBC (&b[k*4 + 2])) + i = k + 1; + else + j = k; + } + if (i < size && EXTRACT_MBC (&b[i*4]) <= c + /* [...] から, 無効なマルチバイト文字を除外する. ここでは簡単の + ため2バイト目が '\n' または '\0' だけを無効とした. [^...] + の場合は, 逆に無効なマルチバイト文字をマッチさせる. */ + && ((unsigned char) c != '\n' && (unsigned char) c != '\0')) + in = !in; + } + return in; +} + /* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. Returns one of error codes defined in `regex.h', or zero for success. @@ -1385,4 +1601,6 @@ { boolean had_char_class = false; + unsigned short c, c1; + int last_char = -1; if (p == pend) return REG_EBRACK; @@ -1390,5 +1608,6 @@ /* Ensure that we have enough space to push a charset: the opcode, the length count, and the bitset; 34 bytes in all. */ - GET_BUFFER_SPACE (34); + /* + 2 + 4 for mbcharset(_not)? with just one interval. */ + GET_BUFFER_SPACE (34 + 2 + 4); laststart = b; @@ -1407,5 +1626,5 @@ /* Clear the whole map. */ - bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); + bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH + 2); /* charset_not matches newline according to a syntax bit. */ @@ -1417,7 +1636,14 @@ for (;;) { + int size; + if (p == pend) return REG_EBRACK; - PATFETCH (c); + if ((size = EXTRACT_UNSIGNED (&b[(1 << BYTEWIDTH) / BYTEWIDTH]))) + /* Ensure the space is enough to hold another interval + of multi-byte chars in charset(_not)?. */ + GET_BUFFER_SPACE (32 + 2 + size*4 + 4); + + PATFETCH_RAW (c); /* \ might escape characters inside [...] and [^...]. */ @@ -1426,6 +1652,16 @@ if (p == pend) return REG_EESCAPE; - PATFETCH (c1); - SET_LIST_BIT (c1); + PATFETCH_RAW (c1); + if (ismbchar (c1)) { + unsigned char c2; + + PATFETCH_RAW (c2); + c1 = c1 << 8 | c2; + (void) set_list_bits (c1, c1, syntax, b, translate); + last_char = c1; + continue; + } + SET_LIST_BIT (TRANSLATE (c1)); + last_char = c1; continue; } @@ -1442,4 +1678,11 @@ return REG_ERANGE; + if (ismbchar (c)) { + unsigned char c2; + + PATFETCH_RAW (c2); + c = c << 8 | c2; + } + /* Look ahead to see if it's a range when the last thing was a character: if this is a hyphen not at the @@ -1447,10 +1690,25 @@ operator. */ if (c == '-' +#if 0 /* The original was: */ && !(p - 2 >= pattern && p[-2] == '[') && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') +#else /* I wonder why he did not write like this. + Have we got any problems? */ + && p != p1 + 1 +#endif && *p != ']') { - reg_errcode_t ret - = compile_range (&p, pend, translate, syntax, b); + reg_errcode_t ret; + + assert (last_char >= 0); + PATFETCH_RAW (c1); + if (ismbchar (c1)) { + unsigned char c2; + + PATFETCH_RAW (c2); + c1 = c1 << 8 | c2; + } + ret = set_list_bits (last_char, c1, syntax, b, translate); + last_char = c1; if (ret != REG_NOERROR) return ret; } @@ -1461,7 +1719,15 @@ /* Move past the `-'. */ - PATFETCH (c1); - - ret = compile_range (&p, pend, translate, syntax, b); + PATFETCH_RAW (c1); + + PATFETCH_RAW (c1); + if (ismbchar (c1)) { + unsigned char c2; + + PATFETCH_RAW (c2); + c1 = c1 << 8 | c2; + } + ret = set_list_bits (c, c1, syntax, b, translate); + last_char = c1; if (ret != REG_NOERROR) return ret; } @@ -1474,5 +1740,5 @@ char str[CHAR_CLASS_MAX_LENGTH + 1]; - PATFETCH (c); + PATFETCH_RAW (c); c1 = 0; @@ -1534,4 +1800,7 @@ } had_char_class = true; +#ifdef DEBUG + last_char = -1; +#endif } else @@ -1540,7 +1809,13 @@ while (c1--) PATUNFETCH; +#if 0 /* The original was: */ SET_LIST_BIT ('['); SET_LIST_BIT (':'); +#else /* I think this is the right way. */ + SET_LIST_BIT (TRANSLATE ('[')); + SET_LIST_BIT (TRANSLATE (':')); +#endif had_char_class = false; + last_char = ':'; } } @@ -1548,5 +1823,6 @@ { had_char_class = false; - SET_LIST_BIT (c); + (void) set_list_bits (c, c, syntax, b, translate); + last_char = c; } } @@ -1556,5 +1832,9 @@ while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) b[-1]--; - b += b[-1]; + if (b[-1] != (1 << BYTEWIDTH) / BYTEWIDTH) + bcopy (&b[(1 << BYTEWIDTH) / BYTEWIDTH], &b[b[-1]], + 2 + EXTRACT_UNSIGNED (&b[(1 << BYTEWIDTH) / BYTEWIDTH])*4); + b += b[-1] + 2 + EXTRACT_UNSIGNED (&b[b[-1]])*4; + break; } break; @@ -2023,5 +2303,6 @@ not to translate; but if we don't translate it it will never match anything. */ - c = TRANSLATE (c); + if (!ismbchar (c)) + c = TRANSLATE (c); goto normal_char; } @@ -2032,4 +2313,11 @@ /* Expects the character in `c'. */ normal_char: + + c1 = 0; + if (ismbchar (c)) { + c1 = c; + PATFETCH_RAW (c); + } + /* If no exactn currently being built. */ if (!pending_exact @@ -2039,5 +2327,6 @@ /* We have only one byte following the exactn for the count. */ - || *pending_exact == (1 << BYTEWIDTH) - 1 + || *pending_exact >= (c1 ? (1 << BYTEWIDTH) - 2 + : (1 << BYTEWIDTH) - 1) /* If followed by a repetition operator. */ @@ -2059,4 +2348,8 @@ } + if (c1) { + BUF_PUSH (c1); + (*pending_exact)++; + } BUF_PUSH (c); (*pending_exact)++; @@ -2184,5 +2477,5 @@ at_endline_loc_p (p, pend, syntax) const char *p, *pend; - int syntax; + reg_syntax_t syntax; { const char *next = p; @@ -2220,4 +2513,5 @@ +#if 0 /* We use set_list_bits() now. */ /* Read the ending character of a range (in a bracket expression) from the uncompiled pattern *P_PTR (which ends at PEND). We assume the @@ -2275,4 +2569,5 @@ return REG_NOERROR; } +#endif /* Failure stack declarations and macros; both re_compile_fastmap and @@ -2638,18 +2933,65 @@ case charset: + /* NOTE: Charset for single-byte chars never contain + multi-byte char. See set_list_bits(). */ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) fastmap[j] = 1; + { + unsigned short size; + unsigned char c, end; + + p += p[-1] + 2; + size = EXTRACT_UNSIGNED (&p[-2]); + for (j = 0; j < size; j++) + /* set bits for 1st bytes of multi-byte chars. */ + for (c = (unsigned char) p[j*4], + end = (unsigned char) p[j*4 + 2]; + c <= end; c++) + /* NOTE: Charset for multi-byte chars might contain + single-byte chars. We must reject them. */ + if (ismbchar (c)) + fastmap[c] = 1; + } break; case charset_not: + /* S: set of all single-byte chars. + M: set of all first bytes that can start multi-byte chars. + s: any set of single-byte chars. + m: any set of first bytes that can start multi-byte chars. + + We assume S+M = U. + ___ _ _ + s+m = (S*s+M*m). */ /* Chars beyond end of map must be allowed. */ + /* NOTE: Charset_not for single-byte chars might contain + multi-byte chars. See set_list_bits(). */ for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) - fastmap[j] = 1; + if (!ismbchar (j)) + fastmap[j] = 1; for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) - fastmap[j] = 1; + if (!ismbchar (j)) + fastmap[j] = 1; + { + unsigned short size; + unsigned short c, beg; + + p += p[-1] + 2; + size = EXTRACT_UNSIGNED (&p[-2]); + c = 0x00; + for (j = 0; j < size; j++) { + for (beg = (unsigned char) p[j*4 + 0]; c <= beg; c++) + if (ismbchar (c)) + fastmap[c] = 1; + c = (unsigned char) p[j*4 + 2]; + } + for (beg = 0xff; c <= beg; c++) + if (ismbchar (c)) + fastmap[c] = 1; + } break; @@ -2964,4 +3306,5 @@ register int lim = 0; int irange = range; + unsigned char c; if (startpos < size1 && startpos + range >= size1) @@ -2973,11 +3316,23 @@ inside the loop. */ if (translate) - while (range > lim - && !fastmap[(unsigned char) - translate[(unsigned char) *d++]]) + while (range > lim) { + c = *d++; + if (ismbchar (c)) { + if (fastmap[c]) + break; + d++; + range -= 2; + continue; + } + if (fastmap[(unsigned char) translate[c]]) + break; range--; + } else - while (range > lim && !fastmap[(unsigned char) *d++]) + while (range > lim && (c = *d++, !fastmap[c])) { + if (ismbchar (c)) + d++, range--; range--; + } startpos += irange - range; @@ -3012,11 +3367,34 @@ else if (range > 0) { - range--; - startpos++; + const char *d = ((startpos >= size1 ? string2 - size1 : string1) + + startpos); + + if (ismbchar (*d)) { + range--, startpos++; + if (!range) + break; + } + range--, startpos++; } else { - range++; - startpos--; + range++, startpos--; + { + const char *s, *d, *p; + + if (startpos < size1) + s = string1, d = string1 + startpos; + else + s = string2, d = string2 + startpos - size1; + for (p = d; p-- > s && ismbchar(*p); ) + /* --p >= s だと 80[12]?86 で動かない可能性がある. (huge + model 以外で, s のオフセットが 0 だった場合.) */ + ; + if (!((d - p) & 1)) { + if (!range) + break; + range++, startpos--; + } + } } } @@ -3578,6 +3956,19 @@ do { + unsigned char c; + PREFETCH (); - if (translate[(unsigned char) *d++] != (char) *p++) + c = *d++; + if (ismbchar (c)) { + if (c != (unsigned char) *p++ + || !--mcnt /* パターンが正しくコンパイルさ + れている限り, このチェックは + 冗長だが念のため. */ + || d == dend + || (unsigned char) *d++ != (unsigned char) *p++) + goto fail; + continue; + } + if ((unsigned char) translate[c] != (unsigned char) *p++) goto fail; } @@ -3588,6 +3979,26 @@ do { +#if 0 + /* 他の部分では, string1 と string2 にマルチバイト文字 + が跨るのを許していない. このことを速度を犠牲にして + もチェックする場合は, ここと次の `#if 0' を `#if 1' + に変えること. */ + unsigned char c; + +#endif PREFETCH (); +#if 0 + c = *d++; + if (ismbchar (c)) { + if (c != (unsigned char) *p++ + || !--mcnt + || d == dend) + goto fail; + c = *d++; + } + if (c != (unsigned char) *p++) goto fail; +#else if (*d++ != (char) *p++) goto fail; +#endif } while (--mcnt); @@ -3602,4 +4013,14 @@ PREFETCH (); + if (ismbchar (*d)) { + if (d + 1 == dend || d[1] == '\n' || d[1] == '\0') + /* 無効なマルチバイト文字にはマッチさせない. ここでは, 簡 + 単のため2バイト目が '\n', '\0' のものだけを無効とする. */ + goto fail; + SET_REGS_MATCHED (); + DEBUG_PRINT2 (" Matched `%d'.\n", EXTRACT_MBC (&d[0])); + d += 2; + break; + } if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') @@ -3616,19 +4037,23 @@ case charset_not: { - register unsigned char c; - boolean not = (re_opcode_t) *(p - 1) == charset_not; + register unsigned short c; + boolean not; - DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); + DEBUG_PRINT2 ("EXECUTING charset%s.\n", + (re_opcode_t) *(p - 1) == charset_not ? "_not" : ""); PREFETCH (); - c = TRANSLATE (*d); /* The character to match. */ + c = (unsigned char) *d; + if (ismbchar (c)) { + c <<= 8; + if (d + 1 != dend) + c |= (unsigned char) d[1]; + } + else + c = TRANSLATE (c); /* The character to match. */ - /* Cast to `unsigned' instead of `unsigned char' in case the - bit list is a full 32 bytes long. */ - if (c < (unsigned) (*p * BYTEWIDTH) - && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) - not = !not; + not = is_in_list (c, p); - p += 1 + *p; + p += 1 + *p + 2 + EXTRACT_UNSIGNED (&p[1 + *p])*4; if (!not) goto fail; @@ -3636,4 +4061,6 @@ SET_REGS_MATCHED (); d++; + if (d != dend && c >= 1 << BYTEWIDTH) + d++; break; } @@ -3801,5 +4228,5 @@ /* xx why this test? */ - if ((int) old_regend[r] >= (int) regstart[r]) + if (old_regend[r] >= regstart[r]) regend[r] = old_regend[r]; } @@ -4052,5 +4479,5 @@ || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) { - register unsigned char c + register unsigned short c = *p2 == (unsigned char) endline ? '\n' : p2[2]; p1 = p + mcnt; @@ -4069,13 +4496,10 @@ || (re_opcode_t) p1[3] == charset_not) { - int not = (re_opcode_t) p1[3] == charset_not; - - if (c < (unsigned char) (p1[4] * BYTEWIDTH) - && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) - not = !not; + if (ismbchar (c)) + c = c << 8 | p2[3]; - /* `not' is equal to 1 if c would match, which means + /* `is_in_list()' is TRUE if c would match, which means that we can't change to pop_failure_jump. */ - if (!not) + if (!is_in_list (c, p1 + 4)) { p[-3] = (unsigned char) pop_failure_jump; @@ -4632,8 +5056,15 @@ char *translate; { - register unsigned char *p1 = s1, *p2 = s2; + register unsigned char *p1 = s1, *p2 = s2, c; while (len) { - if (translate[*p1++] != translate[*p2++]) return 1; + c = *p1++; + if (ismbchar(c)) { + if (c != *p2++ || !--len || *p1++ != *p2++) + return 1; + } + else + if (translate[c] != translate[*p2++]) + return 1; len--; } @@ -4778,5 +5209,5 @@ { reg_errcode_t ret; - unsigned syntax + reg_syntax_t syntax = (cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; diff -ru2N grep-2.0/regex.h grep+mb1.04/regex.h --- grep-2.0/regex.h Fri May 21 14:11:43 1993 +++ grep+mb1.04/regex.h Sat Jul 10 04:38:03 1993 @@ -17,4 +17,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* Multi-byte extension added May, 1993 by t^2 (Takahiro Tanimoto) + Last change: Jul. 10, 1993 by t^2 */ #ifndef __REGEXP_LIBRARY_H__ @@ -36,9 +38,9 @@ the definitions shifted by one from the previous bit; thus, when we add or remove a bit, only one other definition need change. */ -typedef unsigned reg_syntax_t; +typedef unsigned long reg_syntax_t; /* If this bit is not set, then \ inside a bracket expression is literal. If set, then such a \ quotes the following character. */ -#define RE_BACKSLASH_ESCAPE_IN_LISTS (1) +#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long)1) /* If this bit is not set, then + and ? are operators, and \+ and \? are @@ -206,5 +208,5 @@ #undef RE_DUP_MAX #endif -#define RE_DUP_MAX ((1 << 15) - 1) +#define RE_DUP_MAX ((int)(((unsigned)1 << 15) - 1)) @@ -397,4 +399,10 @@ #define _RE_ARGS(args) () + +#ifdef __GNUC__ +#define const __const__ +#else +#define const +#endif #endif /* not __STDC__ */ diff -ru2N grep-2.0/search.c grep+mb1.04/search.c --- grep-2.0/search.c Mon May 3 06:02:00 1993 +++ grep+mb1.04/search.c Fri Jul 9 14:55:21 1993 @@ -17,4 +17,6 @@ Written August 1992 by Mike Haertel. */ +/* Multi-byte extension added Jul., 1993 by t^2 (Takahiro Tanimoto) + Last change: Jul. 9, 1993 by t^2 */ #include @@ -61,4 +63,5 @@ #include "kwset.h" #include "regex.h" +#include "mbc.h" #define NCHAR (UCHAR_MAX + 1) @@ -434,8 +437,9 @@ char **endp; { - register char *beg, *try, *end; + register char *beg, *try, *end, *p, *lim; register size_t len; struct kwsmatch kwsmatch; + lim = buf; for (beg = buf; beg <= buf + size; ++beg) { @@ -456,4 +460,8 @@ if (try > buf && WCHAR((unsigned char) try[-1])) break; + for (p = try; p-- > lim && ismbchar(*p); ) + ; + if (!((try - p) & 1)) + break; if (try + len < buf + size && WCHAR((unsigned char) try[len])) { @@ -464,6 +472,12 @@ goto success; } - else - goto success; + else { + for (p = beg; p-- > lim && ismbchar(*p); ) + ; + if ((beg - p) & 1) + goto success; + if (lim + 1 < beg) + lim = beg - 1; + } } diff -ru2N grep-2.0/tests/batgen.awk grep+mb1.04/tests/batgen.awk --- grep-2.0/tests/batgen.awk Thu Jan 1 09:00:00 1970 +++ grep+mb1.04/tests/batgen.awk Sat Jul 10 02:10:24 1993 @@ -0,0 +1,10 @@ +BEGIN { print "@echo off"; } +$0 !~ /^#/ && NF == 3 { + printf "echo #%d --\n", ++n + print "set R=0"; + print "echo " $3 ">tmp.in"; + print "grep -E -e \"" $2 "\" tmp.in >nul"; + print "if errorlevel 1 set R=1"; + print "if errorlevel 2 set R=2"; + printf "if not %R% == " $1 " echo Spencer test #%d failed\n", n +} diff -ru2N grep-2.0/tests/check.bat grep+mb1.04/tests/check.bat --- grep-2.0/tests/check.bat Thu Jan 1 09:00:00 1970 +++ grep+mb1.04/tests/check.bat Fri Jul 9 17:05:30 1993 @@ -0,0 +1,14 @@ +@echo off +rem +rem Regression test for GNU e?grep. +rem + +rem The Khadafy test is brought to you by Scott Anderson . . . +grep -E -f tests/khadafy.reg tests/khadafy.lin > khadafy.out +fc tests\khadafy.lin khadafy.out + +rem . . . and the following by Henry Spencer. + +gawk -F: -f tests/batgen.awk tests/spencer.dos > tmp.bat + +tmp diff -ru2N grep-2.0/tests/spencer.dos grep+mb1.04/tests/spencer.dos --- grep-2.0/tests/spencer.dos Thu Jan 1 09:00:00 1970 +++ grep+mb1.04/tests/spencer.dos Sat Jul 10 02:12:59 1993 @@ -0,0 +1,122 @@ +0:abc:abc +1:abc:xbc +1:abc:axc +1:abc:abx +0:abc:xabcy +0:abc:ababc +0:ab*c:abc +0:ab*bc:abc +0:ab*bc:abbc +0:ab*bc:abbbbc +0:ab+bc:abbc +1:ab+bc:abc +1:ab+bc:abq +0:ab+bc:abbbbc +0:ab?bc:abbc +0:ab?bc:abc +1:ab?bc:abbbbc +0:ab?c:abc +0:^abc$:abc +1:^abc$:abcc +0:^abc:abcc +1:^abc$:aabc +0:abc$:aabc +0:^:abc +0:$:abc +0:a.c:abc +0:a.c:axc +0:a.*c:axyzc +1:a.*c:axyzd +1:a[bc]d:abc +0:a[bc]d:abd +1:a[b-d]e:abd +0:a[b-d]e:ace +0:a[b-d]:aac +0:a[-b]:a- +0:a[b-]:a- +1:a[b-a]:- +2:a[]b:- +2:a[:- +0:a]:a] +0:a[]]b:a]b +0:a[^bc]d:aed +1:a[^bc]d:abd +0:a[^-b]c:adc +1:a[^-b]c:a-c +1:a[^]b]c:a]c +0:a[^]b]c:adc +0:ab|cd:abc +0:ab|cd:abcd +0:()ef:def +0:()*:- +1:*a:- +0:^*:- +0:$*:- +1:(*)b:- +1:$b:b +2:a\\:- +0:a\(b:a(b +0:a\(*b:ab +0:a\(*b:a((b +1:a\x:a\x +2:abc):- +2:(abc:- +0:((a)):abc +0:(a)b(c):abc +0:a+b+c:aabbabc +0:a**:- +0:a*?:- +0:(a*)*:- +0:(a*)+:- +0:(a|)*:- +0:(a*|b)*:- +0:(a+|b)*:ab +0:(a+|b)+:ab +0:(a+|b)?:ab +0:[^ab]*:cde +0:(^)*:- +0:(ab|)*:- +2:)(:- +1:abc: +1:abc: +0:a*: +0:([abc])*d:abbbcd +0:([abc])*bcd:abcd +0:a|b|c|d|e:e +0:(a|b|c|d|e)f:ef +0:((a*|b))*:- +0:abcd*efg:abcdefg +0:ab*:xabyabbbz +0:ab*:xayabbbz +0:(ab|cd)e:abcde +0:[abhgefdc]ij:hij +1:^(ab|cd)e:abcde +0:(abc|)ef:abcdef +0:(a|b)c*d:abcd +0:(ab|ab*)bc:abc +0:a([bc]*)c*:abc +0:a([bc]*)(c*d):abcd +0:a([bc]+)(c*d):abcd +0:a([bc]*)(c+d):abcd +0:a[bcd]*dcdcde:adcdcde +1:a[bcd]+dcdcde:adcdcde +0:(ab|a)b*c:abc +0:((a)(b)c)(d):abcd +0:[A-Za-z_][A-Za-z0-9_]*:alpha +0:^a(bc+|b[eh])g|.h$:abh +0:(bc+d$|ef*g.|h?i(j|k)):effgz +0:(bc+d$|ef*g.|h?i(j|k)):ij +1:(bc+d$|ef*g.|h?i(j|k)):effg +1:(bc+d$|ef*g.|h?i(j|k)):bcdd +0:(bc+d$|ef*g.|h?i(j|k)):reffgz +1:((((((((((a)))))))))):- +0:(((((((((a))))))))):a +1:multiple words of text:uh-uh +0:multiple words:multiple words, yeah +0:(.*)c(.*):abcde +1:\((.*),:(.*)\) +1:[k]:ab +0:abcd:abcd +0:a(bc)d:abcd +0:a[-]?c:ac +0:(....).*\1:beriberi