• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

タグ
未設定

よく使われているワード(クリックで追加)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

シェルスクリプト言語xyzshのソースコード。


コミットメタ情報

リビジョン12a1d8fd6621a6637a81cd8d639722458767c8b9 (tree)
日時2013-01-31 20:40:07
作者ab25q <ab25cq@gmai...>
コミッターab25q

ログメッセージ

1.3.3

変更サマリ

差分

--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,13 +1,27 @@
11
2-2013 January version 1.3.3
2+2013 31th January version 1.3.3
33
4- 1. Modified configure.in and Makfile.in especially for related docdir and sysconfdir
4+ 1. Modified configure.in and Makfile.in especially for related with docdir and sysconfdir
55
66 2. Added XYZSH_DOCDIR for help.xyzsh. Remained XYZSH_DATAROOTDIR.
77
8- 3. After runned on command line, changed "HIT ANY KEY" working.
8+ 3. Fixed job title problem.
99
10- 4. Fixed job title problem.
10+ 4. Added C extension mechanism which loads dynamic library from searched path. See USAGE or USAGE.ja. Cutted off migemo and made it as C extension.
11+
12+ 5. Added migemo completion for Japanese.
13+
14+ 6. Added "-regex" option to "index" and "rindex" command. Added "-no-regex" option to "sub" and "split" command.
15+
16+ 7. Checked on Ubuntu 64 bit.
17+
18+ 8. You can set return code of "return" command.
19+
20+ > def fun ( return 1 )
21+ > fun
22+ return code is 1
23+
24+ 9. Modified completion working especially tilde completion..
1125
1226 2013 20th January version 1.3.2
1327
--- a/Makefile.in
+++ b/Makefile.in
@@ -21,6 +21,7 @@ INSTALL=@INSTALL@
2121 CFLAGS=@CFLAGS@
2222 LIBS=@LIBS@
2323 OBJ=@OBJ@
24+EXTOBJ=@EXTOBJ@
2425 LIBXYZSHSO=@LIBXYZSHSO@
2526 LIBXYZSHSO1=@LIBXYZSHSO1@
2627 LIBXYZSHA=@LIBXYZSHA@
@@ -28,11 +29,17 @@ LIBXYZSHASTRIP=@LIBXYZSHASTRIP@
2829 DESTDIR=
2930 SYSTEM_MIGEMODIR=@SYSTEM_MIGEMODIR@
3031 SO_VERSION=@SO_VERSION@
32+EXTDIR=@EXTDIR@
3133
3234 ##########################################################
33-all: lib xyzsh
35+# main
36+##########################################################
37+all: lib xyzsh extension
3438 rm -f install
3539
40+xyzsh: config.h src/main.c $(LIBXYZSHSO) $(LIBXYZSHA)
41+ $(CC) -o xyzsh src/main.c $(CFLAGS:-static=) -lxyzsh $(LIBS)
42+
3643 lib: $(LIBXYZSHSO1) $(LIBXYZSHA)
3744 rm -f install
3845
@@ -53,15 +60,6 @@ lib-dest-install:
5360 if [ "$(LIBXYZSHSO)" = libxyzsh.so ]; then ln -s -f libxyzsh.so.$(SO_VERSION) "$(DESTDIR)/$(libdir)"/libxyzsh.so.1; elif [ "$(LIBXYZSHSO)" = libxyzsh.dylib ]; then ln -s -f libxyzsh.$(SO_VERSION).dylib "$(DESTDIR)/$(libdir)"/libxyzsh.1.dylib; fi
5461 if [ "$(LIBXYZSHSO)" = libxyzsh.so ]; then ln -s -f libxyzsh.so.$(SO_VERSION) "$(DESTDIR)/$(libdir)"/libxyzsh.so; elif [ "$(LIBXYZSHSO)" = libxyzsh.dylib ]; then ln -s -f libxyzsh.$(SO_VERSION).dylib "$(DESTDIR)/$(libdir)"/libxyzsh.dylib; fi
5562
56-clean:
57- rm -fR xyzsh xyzsh.dSYM src/*.o libxyzsh* xyzsh.exe* config.log config.status *.stackdump autom4te.cache
58-
59-distclean:
60- rm -fR xyzsh xyzsh.dSYM src/*.o libxyzsh* config.h Makefile xyzsh.exe* config.log config.status *.stackdump autom4te.cache
61-
62-xyzsh: config.h src/main.c $(LIBXYZSHSO) $(LIBXYZSHA)
63- $(CC) -o xyzsh src/main.c $(CFLAGS:-static=) -lxyzsh $(LIBS)
64-
6563 ########################################################
6664 # xyzsh libraries
6765 ########################################################
@@ -87,18 +85,20 @@ libxyzsh.dylib: libxyzsh.$(SO_VERSION).dylib
8785 cp libxyzsh.$(SO_VERSION).dylib libxyzsh.1.dylib
8886 cp libxyzsh.$(SO_VERSION).dylib libxyzsh.dylib
8987
90-permission:
91- chmod 644 *
92- chmod 755 .git man src configure
93- chmod 644 src/*.c
94- chmod 644 src/xyzsh/*.h
95-
9688 #########################################################
97-# install
89+# Object files
9890 #########################################################
9991 $(OBJ): src/xyzsh/xyzsh.h src/xyzsh/block.h src/xyzsh/curses.h src/xyzsh/debug.h src/xyzsh/hash.h src/xyzsh/kanji.h src/xyzsh/list.h src/xyzsh/string.h src/xyzsh/vector.h Makefile configure
10092
10193 #########################################################
94+# Extension
95+#########################################################
96+extension: $(EXTOBJ)
97+
98+src/ext/migemo.so: src/ext/migemo.c
99+ gcc -shared src/ext/migemo.c -o src/ext/migemo.so -lmigemo -lxyzsh $(LIBS) $(CFLAGS)
100+
101+#########################################################
102102 # install
103103 #########################################################
104104 install: lib-install
@@ -132,6 +132,9 @@ normal-install:
132132 $(INSTALL) -m 644 completion.xyzsh "$(sysconfdir)"
133133 $(INSTALL) -m 644 help.xyzsh "$(sysconfdir)"
134134 $(INSTALL) -m 644 read_history.xyzsh "$(sysconfdir)"
135+ mkdir -p "$(DESTDIR)/$(EXTDIR)"
136+ $(INSTALL) -m 755 src/ext/migemo.so "$(EXTDIR)"
137+ $(INSTALL) -m 644 src/ext/migemo.so.xyzsh "$(EXTDIR)"
135138
136139 dest-install:
137140 mkdir -p "$(DESTDIR)/$(bindir)";
@@ -160,4 +163,52 @@ dest-install:
160163 $(INSTALL) -m 644 completion.xyzsh "$(DESTDIR)/$(sysconfdir)"
161164 $(INSTALL) -m 644 help.xyzsh "$(DESTDIR)/$(sysconfdir)"
162165 $(INSTALL) -m 644 read_history.xyzsh "$(DESTDIR)/$(sysconfdir)"
166+ mkdir -p "$(DESTDIR)/$(EXTDIR)"
167+ $(INSTALL) -m 755 src/ext/migemo.so "$(DESTDIR)/$(EXTDIR)"
168+ $(INSTALL) -m 644 src/ext/migemo.so.xyzsh "$(DESTDIR)/$(EXTDIR)"
169+
170+#########################################################
171+# uninstall
172+#########################################################
173+uninstall:
174+ rm -f $(includedir)/block.h
175+ rm -f $(includedir)/curses.h
176+ rm -f $(includedir)/debug.h
177+ rm -f $(includedir)/hash.h
178+ rm -f $(includedir)/kanji.h
179+ rm -f $(includedir)/list.h
180+ rm -f $(includedir)/string.h
181+ rm -f $(includedir)/vector.h
182+ rm -f $(includedir)/xyzsh.h
183+ rmdir $(includedir)
184+ rm -f $(docdir)/USAGE
185+ rm -f $(docdir)/USAGE.ja
186+ rm -f $(docdir)/README
187+ rm -f $(docdir)/README.ja
188+ rm -f $(docdir)/CHANGELOG
189+ rmdir $(docdir)
190+ rm -f $(bindir)/xyzsh
191+ rm -f $(mandir)/man1/xyzsh.1
192+ rm -f $(sysconfdir)/xyzsh.xyzsh
193+ rm -f $(sysconfdir)/completion.xyzsh
194+ rm -f $(sysconfdir)/help.xyzsh
195+ rm -f $(sysconfdir)/read_history.xyzsh
196+ rmdir $(sysconfdir)
163197
198+#########################################################
199+# permission
200+#########################################################
201+permission:
202+ chmod 644 *
203+ chmod 755 .git man src configure
204+ chmod 644 src/*.c
205+ chmod 644 src/xyzsh/*.h
206+
207+########################################################
208+# clean
209+########################################################
210+clean:
211+ rm -fR xyzsh xyzsh.dSYM src/*.o libxyzsh* xyzsh.exe* config.log config.status *.stackdump autom4te.cache .DS_Store src/ext/*.so src/ext/*.o src/ext/migemo.dSYM
212+
213+distclean:
214+ rm -fR xyzsh xyzsh.dSYM src/*.o libxyzsh* config.h Makefile xyzsh.exe* config.log config.status *.stackdump autom4te.cache .DS_Store src/ext/*.so src/ext/*.o src/ext/migemo.dSYM
--- a/README
+++ b/README
@@ -161,12 +161,14 @@ Used files
161161 /usr/local/etc/xyzsh/completion.xyzsh --> a source completion setting file
162162 /usr/local/etc/xyzsh/help.xyzsh --> a source help setting file
163163 /usr/local/etc/xyzsh/read_history.xyzsh --> a source which reads command line history
164+ /usr/local/lib/xyzsh/*.so --> xyzsh C extension library
164165 ~/.xyzsh/xyzsh.xyzsh --> a source user setting file. xyzsh read this after /usr/local/etc/xyzsh.xyzsh
165166 ~/.xyzsh/history --> a command line history file
166167 ~/.xyzsh/macro --> macro which is runned by typing C-x on command line uses this file
167168 ~/.xyzsh/jump --> jump inner command uses this file
168169 ~/.xyzsh/menu --> menu inner command uses this file
169170 ~/.xyzsh/program --> program list which is entried to root object
171+ ~/.xyzsh/lib/*.so --> xyzsh C extension library for user
170172
171173 Encoding and Line field
172174 xyzsh script source file must be written with UTF-8 encode and LF Linefield. But, xyzsh can treat UTF8, EUCJP, and SJIS encodings and can treat LF, CR, LFCR line fields. (EUCJP and SJIS are for Japanese)
--- a/README.ja
+++ b/README.ja
@@ -149,7 +149,7 @@ xyzsh シェルスクリプト言語
149149 日本人向けのオプション
150150
151151 --with-migemo
152- migemo_match内部コマンドを作成します。
152+ migemo::match内部コマンドをC拡張ライブラリとして作成します。
153153 --with-migemo-dir
154154 デフォルトでは/usr, /usr/localで検索されるmigemoのインストール先を指定します。
155155 これも管理者権限がない場合で自分のホームディレクトリにmigemoをインストールした場合には必要になるでしょう。
@@ -198,6 +198,7 @@ xyzshが使用するファイル
198198 /usr/local/etc/xyzsh/completion.xyzsh --> 補完関係の設定ファイル
199199 /usr/local/etc/xyzsh/help.xyzsh --> ヘルプ関連の設定ファイル
200200 /usr/local/etc/xyzsh/read_history.xyzsh --> コマンドラインのヒストリを読み込む設定ファイル
201+ /usr/local/lib/xyzsh/*.so --> xyzshのC拡張ライブラリ
201202 ~/.xyzsh/xyzsh.xyzsh --> /usr/local/etc/xyzsh.xyzshの後に呼ばれるユーザーの設定ファイル
202203 ~/.xyzsh/history --> コマンドライン履歴が保存されたファイル
203204 ~/.xyzsh/macro --> コマンドラインでControl-xを押した場合に表示されるワンライナーの一覧。
@@ -208,6 +209,7 @@ xyzshが使用するファイル
208209 ~/.xyzsh/menu --> menu内部コマンドを実行したときに表示されるワンライナーの一覧。
209210 ~/.xyzsh/program --> sys::を省略したい外部プログラムの一覧。このファイルに外部プログラム名を追加して
210211 rehashコマンドを実行すれば、sys::を省略することができるようになる。
212+ ~/.xyzsh/lib/*.so --> ユーザーがインストールしたxyzshのC拡張ライブラリ
211213
212214 エンコードと改行コードについて
213215
--- a/USAGE
+++ b/USAGE
@@ -8,7 +8,7 @@
88
99 Ofcourse, on interactive shell, it helps you to type with completion.
1010
11- Taget users are who has mastered bash, sed/awk, perl, python, ruby and want to seek somemore. If you don't master these tools, you should learn these tools before using xyzsh.
11+ Taget users are who has mastered bash, sed/awk, perl, python, ruby and want to seek somemore. If you don't master these tools, you should learn these tools before using xyzsh because these tools are installed on many systems.
1212
1313 I can't take resposbility on your works with xyzsh. I recommend that you use this on your personal systems.
1414
@@ -16,8 +16,6 @@
1616
1717 You can get this on the internet belows
1818
19- Develop version http://code.google.com/p/xyzsh/
20-
2119 Stable version http://sourceforge.jp/projects/xyzsh
2220 Develop version http://sourceforge.jp/projects/xyzsh/scm/git/xyzsh/
2321
@@ -688,3 +686,12 @@
688686
689687 help (command name)
690688
689+3.6 C extension library
690+
691+ About how to load C language extension library. Searched path is 3 step. First searched it from /usr/local/xyzsh/(pathname) or (installed prefix path)/(pathname), next searched it from ~/lib/(pathname), and finaly searched it from (absolute pathname or relative pathname). You can't ommit the file name extesion.
692+ About how to make C language extension library. I made migemo C extension. See src/ext/migemo.c. You need to define dl_init and dl_final. dl_init is called on "load -dynamic-library" command called. dl_final is called on xyzsh exited. You can compile the C extension source like below
693+
694+ gcc -shared src/ext/migemo.c -o src/ext/migemo.so -lmigemo -lxyzsh $(LIBS) $(CFLAGS)
695+
696+ Xyzsh reads a xyzsh source which is (dynamic library file).xyzsh on running "load -dynamic-library". You can write help, completion settings, and son initialize function on it.
697+
--- a/USAGE.ja
+++ b/USAGE.ja
@@ -12,7 +12,7 @@
1212
1313 対象とするユーザーとしては、bashやperl, python, ruby, sed, awkなど一通りマスターしたけれども
1414 「もっと何か無いかな?」 と思っておられる方です。
15- 初心者は最初にbashやperlなどを学んだほうがいいと思います。
15+ 初心者の方は最初にbashやperlなどを学んだほうがいいと思います。
1616 (大抵のシステムではそちらがインストールされているので)
1717
1818 使用に当たっては、このプログラムによって被る結果には自分で責任を持つことをお願いします。
@@ -739,13 +739,13 @@
739739 error-data
740740 data
741741
742-3.2 複数行のテキストの取り扱い
742+3.3 複数行のテキストの取り扱い
743743
744744 xyzshで複数行のテキストを一つの変数に入力したい場合は-Laオプションを使ってください。
745745 \aが行の区切りとして扱われ、結果\n,\r\n,\rなどを単なるテキストとして処理でき、複数行のテキストを扱えます。
746746 少し複雑なコードとなりますがpコマンドでデバッグすれば、理解できるかと思います。
747747
748-3.3 コマンドライン補完
748+3.4 コマンドライン補完
749749
750750 コマンドライン補完にはreadlineを使っているので、ほぼbashと同じように使うことができます。
751751
@@ -758,13 +758,24 @@
758758
759759 rlオブジェクトを使って補完のプログラム中にreadlineを操作できます。rl::helpを見てください。
760760
761-3.4 ヘルプ
761+3.5 ヘルプ
762762
763763 help コマンド名
764764
765765 でコマンドの使い方を見ることができます。各コマンドのオプションなどはそちらで調べてください。
766766
767-3.5 xyzshの組み込みについて
767+3.6 C拡張ライブラリ
768+
769+ C拡張ライブラリはload -dynamic-libraryを使って呼び出せます。サーチパスは/usr/local/lib/xyzsh/"ファイル名"(xyzshをインストールしたディレクトリ/lib/xyzsh/"ファイル名")を探して無いなら、~/lib/"ファイル名"を探し、それでもないなら、"ファイル名(絶対パス、または相対パス)"を探します。拡張子は省略してはいけません。
770+ 作り方について。migemoがC拡張ライブラリとなってます。詳しくはsrc/ext/migemo.cを見てください。dl_initとdl_finalを定義する必要があります。dl_initはload -dynamic-libraryをするときに呼ばれます。dl_finalはxyzshが終了するときに呼ばれます。拡張ライブラリのコンパイルは
771+
772+ gcc -shared src/ext/migemo.c -o src/ext/migemo.so -lmigemo -lxyzsh $(LIBS) $(CFLAGS)
773+
774+ などとすれば良いです。$(LIBS)と$(CFLAGS)は自分で定義する必要があります。
775+
776+ 拡張ライブラリと同じ名前 + .xyzshのソースファイルはload時に自動的に読み込まれます。ヘルプや補完などをそこに書くことができます。
777+
778+3.7 xyzshの組み込みについて
768779
769780 xyzshのメモリ管理について。xyzshはGCとスタックとmalloc&freeの3つのオブジェクトのメモリ管理を行なってます。しかし、以下の制限があります。
770781 GCで作り出されるオブジェクトはマークをさせるためにgRootObjectかgXyzshObjectから辿れるようにしなければなりません。(GCで管理されてgRootObjectかgXyzshObjectから辿れるコンテナオブジェクトに格納される必要がある)。でなければ、sweepで消されてしまいます。sweepは一定回数コードを実行すると自動的に実行されます。
--- a/completion.xyzsh
+++ b/completion.xyzsh
@@ -1,6 +1,6 @@
11
22 def xyzsh_quote (
3- | sub -global ' |\\|"|\$|\*|\?|\[|\]|\{|\}|\&|\;|\(|\)|-' ( | add -number 0 \\ )
3+ | sub -global ' |\\|"|\$|\*|\?|\[|\]|\{|\}|\&|\;|\(|\)' ( | add -number 0 \\ )
44 )
55
66 def xyzsh_dequote (
@@ -23,22 +23,28 @@ def program_completion (
2323 )
2424 )
2525
26-compl::run( object rl )
27-
28-completion rl::help (
29- rl::self | egrep native\ function\$ | root::scan '(^.+?):' | each ( | chomp | quote | pomch )
30-)
31-
32-root | egrep ': native function$' | egrep -v '^run: native function$|^show: native function$' | scan '(^.+):' | add sub\nsplit\nscan\n | each (
33- | var -local command
26+def file_completion (
27+ | split '(?<!\\) +' | lines -1 | var -local inputing
3428
35- help $command | lines 1..-1 | scan '^-[a-zA-Z0-9-]+' |chomp| add -number 0 $command\a | hash -append -La COMPLETION_OPTIONS
29+ if(inputing | index -quiet /) (
30+ sys::dirname $(inputing |chomp| if (|rows -1 | = /) ( |add aaa ) else ( | print ) ) | var -local DIR
3631
37- print <<<EOS
38- completion "$command" (
39- hash COMPLETION_OPTIONS -key "$command"
32+ eval "ls $DIR" | each (
33+ | if (|chomp | add -number 0 $DIR/ | -d) (
34+ |chomp | add -number 0 $DIR/ | xyzsh_quote | add / | pomch
35+ ) else (
36+ |chomp | add -number 0 $DIR/ | xyzsh_quote | pomch
37+ )
38+ )
39+ ) else (
40+ ls | each (
41+ | if (|chomp| -d) (
42+ | chomp | xyzsh_quote | add / | pomch
43+ ) else (
44+ |chomp| xyzsh_quote | pomch
45+ )
46+ )
4047 )
41-EOS | eval
4248 )
4349
4450 class object_completion (
@@ -68,6 +74,18 @@ class object_completion (
6874 )
6975 )
7076
77+root | egrep ': native function$' | egrep -v '^run: native function$|^show: native function$' | scan '(^.+):' | add sub\nsplit\nscan\n | each (
78+ | var -local command
79+
80+ help $command | lines 1..-1 | scan '^-[a-zA-Z0-9-]+' |chomp| add -number 0 $command\a | hash -append -La COMPLETION_OPTIONS
81+
82+ print <<<EOS
83+ completion "$command" (
84+ hash COMPLETION_OPTIONS -key "$command"
85+ )
86+EOS | eval
87+)
88+
7189 completion var (
7290 | object_completion var
7391 hash COMPLETION_OPTIONS -key var
@@ -175,3 +193,19 @@ completion kill (
175193 rl::clear_screen
176194 )
177195
196+completion load (
197+ | if(| index -quiet "-dynamic-library" ) (
198+ ls $XYZSH_EXT_PATH | (| print -read-from-error; | print) | egrep '.so$'
199+ ls ~/.xyzsh/lib | ( | print -read-from-error; | print ) | grep '.so$'
200+ ) else (
201+ | file_completion
202+ hash COMPLETION_OPTIONS -key load
203+ )
204+)
205+
206+root::compl::run( root::object rl )
207+
208+completion rl::help (
209+ rl::self | egrep native\ function\$ | egrep -v 'run|show' | root::scan '(^.+?):' | each ( | chomp | quote | pomch )
210+)
211+
--- a/configure
+++ b/configure
@@ -621,6 +621,8 @@ ac_includes_default="\
621621
622622 ac_subst_vars='LTLIBOBJS
623623 LIBOBJS
624+EXTDIR
625+EXTOBJ
624626 EGREP
625627 GREP
626628 CPP
@@ -3041,6 +3043,7 @@ fi
30413043 #####################################################################
30423044 # check operating systems
30433045 #####################################################################
3046+EXTDIR='$(libdir)/xyzsh/'
30443047 SO_VERSION=1.7.0
30453048
30463049 { $as_echo "$as_me:${as_lineno-$LINENO}: checking Operating System" >&5
@@ -3049,7 +3052,7 @@ $as_echo_n "checking Operating System... " >&6; }
30493052 OBJ="src/gc.o src/stack.o src/string.o src/list.o src/kanji.o src/debug.o src/hash.o src/vector.o src/block.o src/fun.o src/class.o src/completion.o src/xyzsh.o src/parser.o src/run.o src/readline.o src/curses.o src/cmd_base.o src/cmd_obj.o src/cmd_file.o src/cmd_str.o src/cmd_ary.o src/cmd_condition.o src/interface.o src/object.o src/uobject.o src/cmd_num.o src/cmd_curses.o src/fd.o src/nfun.o src/extprog.o"
30503053
30513054
3052-CFLAGS='-DSYSCONFDIR="\"${sysconfdir}/\"" -DDOCDIR="\"${docdir}/\"" -DSYSTEM_MIGEMODIR="\"${SYSTEM_MIGEMODIR}\""'
3055+CFLAGS='-DSYSCONFDIR="\"${sysconfdir}/\"" -DDOCDIR="\"${docdir}/\"" -DSYSTEM_MIGEMODIR="\"${SYSTEM_MIGEMODIR}\"" -DEXTDIR="\"${EXTDIR}\""'
30533056
30543057 if test `uname -s` = "Darwin"; then
30553058 echo "Darwin"
@@ -3847,6 +3850,8 @@ then
38473850 exit
38483851 fi
38493852
3853+EXTOBJ=
3854+
38503855 #####################################################################
38513856 # math settings
38523857 #####################################################################
@@ -3972,7 +3977,7 @@ if test $ENABLE_MIGEMO = 1
39723977 then
39733978 ac_fn_c_check_header_mongrel "$LINENO" "migemo.h" "ac_cv_header_migemo_h" "$ac_includes_default"
39743979 if test "x$ac_cv_header_migemo_h" = xyes; then :
3975- LIBS="$LIBS -lmigemo"; $as_echo "#define HAVE_MIGEMO_H 1" >>confdefs.h
3980+ EXTOBJ="$EXTOBJ src/ext/migemo.so"; $as_echo "#define HAVE_MIGEMO_H 1" >>confdefs.h
39763981
39773982 else
39783983 exit
@@ -3983,6 +3988,8 @@ fi
39833988
39843989
39853990
3991+
3992+
39863993 ##########################################################################
39873994 # type checking
39883995 ###########################################################################
--- a/configure.in
+++ b/configure.in
@@ -32,6 +32,7 @@ AC_SUBST(SYSTEM_MIGEMODIR)
3232 #####################################################################
3333 # check operating systems
3434 #####################################################################
35+EXTDIR='$(libdir)/xyzsh/'
3536 SO_VERSION=1.7.0
3637 AC_SUBST(SO_VERSION)
3738 AC_MSG_CHECKING(Operating System)
@@ -39,7 +40,7 @@ AC_MSG_CHECKING(Operating System)
3940 OBJ="src/gc.o src/stack.o src/string.o src/list.o src/kanji.o src/debug.o src/hash.o src/vector.o src/block.o src/fun.o src/class.o src/completion.o src/xyzsh.o src/parser.o src/run.o src/readline.o src/curses.o src/cmd_base.o src/cmd_obj.o src/cmd_file.o src/cmd_str.o src/cmd_ary.o src/cmd_condition.o src/interface.o src/object.o src/uobject.o src/cmd_num.o src/cmd_curses.o src/fd.o src/nfun.o src/extprog.o"
4041 AC_SUBST(OBJ)
4142
42-CFLAGS='-DSYSCONFDIR="\"${sysconfdir}/\"" -DDOCDIR="\"${docdir}/\"" -DSYSTEM_MIGEMODIR="\"${SYSTEM_MIGEMODIR}\""'
43+CFLAGS='-DSYSCONFDIR="\"${sysconfdir}/\"" -DDOCDIR="\"${docdir}/\"" -DSYSTEM_MIGEMODIR="\"${SYSTEM_MIGEMODIR}\"" -DEXTDIR="\"${EXTDIR}\""'
4344
4445 if test `uname -s` = "Darwin"; then
4546 echo "Darwin"
@@ -234,6 +235,8 @@ then
234235 exit
235236 fi
236237
238+EXTOBJ=
239+
237240 #####################################################################
238241 # math settings
239242 #####################################################################
@@ -261,10 +264,12 @@ AC_HAVE_LIBRARY(onig, [ LIBS="$LIBS -lonig"; ], [ exit ])
261264 ###########################################################################
262265 if test $ENABLE_MIGEMO = 1
263266 then
264- AC_CHECK_HEADER(migemo.h, [LIBS="$LIBS -lmigemo"; AC_DEFINE(HAVE_MIGEMO_H, 1)], [ exit ])
267+ AC_CHECK_HEADER(migemo.h, [EXTOBJ="$EXTOBJ src/ext/migemo.so"; AC_DEFINE(HAVE_MIGEMO_H, 1)], [ exit ])
265268 fi
266269
270+AC_SUBST(EXTOBJ)
267271 AC_SUBST(LIBS)
272+AC_SUBST(EXTDIR)
268273
269274 ##########################################################################
270275 # type checking
--- a/help.xyzsh
+++ b/help.xyzsh
@@ -137,7 +137,7 @@ if (条件式1) (ブロック1) (条件式2) (ブロック2) ... (条件式x) (
137137 -
138138 条件式が真ならば対応するブロックを実行する。もし全部の条件式が偽なら最後のブロックを実行する
139139 -
140-return
140+return (リターンコード)
141141 -
142142 関数かクラスを実行中なら、途中で抜ける
143143 -
@@ -175,6 +175,8 @@ print 文字列1 文字列2, ..., 文字列x
175175 load ファイル名 引数1 引数2 ... 引数X
176176 -
177177 スクリプトファイルを実行する。ローカル変数は初期化される。ARGVに引数が入っている。
178+
179+-dynamic-library C言語による拡張ライブラリをロードする。サーチパスは/usr/local/lib/xyzsh/"ファイル名"(xyzshをインストールしたディレクトリ/lib/xyzsh/"ファイル名")を探して無いなら、~/lib/"ファイル名"を探す、それでもないなら、"ファイル名(絶対パス、または相対パス)"を探す。拡張子は省略してはならない。
178180 -
179181 eval (ブロック|文字列)
180182 -
@@ -436,6 +438,8 @@ sort (ブロック)
436438
437439 -offsets マッチした位置(インデックス)の始点と終点を出力する(グループ化された文字列も含む)
438440 -verbose マッチした位置(インデックス)を出力する
441+-ignore-case 大文字と小文字を無視する
442+-multi-line 複数行にまたがる、正規表現を許す。(パフォーマンスは落ちる)
439443 -byte バイトコードとして処理する
440444 -utf8 UTF8コードとして処理する
441445 -sjis SJISコードとして処理する
@@ -741,8 +745,10 @@ index 文字列
741745 -
742746 パイプから文字列を検索して見つかったインデックスを返すフィルター。
743747
748+-regex 正規表現で検索する
744749 -quiet 見つかった位置を出力しない。戻り値のみ設定する
745750 -ignore-case 大文字と小文字を無視する
751+-multi-line 複数行にまたがる、正規表現を許す。(パフォーマンスは落ちる)
746752 -number 数値 文字列の検索を開始する位置を設定する
747753 -count 数値 検索する回数を設定する
748754 -byte バイトコードとして処理する
@@ -755,8 +761,10 @@ rindex 文字列
755761 パイプから文字列を検索して見つかったインデックスを返すフィルター。
756762 末尾から検索する。
757763
764+-regex 正規表現で検索する
758765 -quiet 見つかった位置を出力しない。戻り値のみ設定する
759766 -ignore-case 大文字と小文字を無視する
767+-multi-line 複数行にまたがる、正規表現を許す。(パフォーマンスは落ちる)
760768 -number 数値 文字列の検索を開始する位置を設定する
761769 -count 数値 検索する回数を設定する
762770 -byte バイトコードとして処理する
@@ -851,9 +859,15 @@ b
851859
852860 変換回数はグローバル変数SUB_COUNTに代入される。
853861
862+-no-regex 正規表現じゃなくて普通の文字列としてパターンを使う
863+-ignore-case 大文字と小文字を無視する
854864 -multi-line 複数行にまたがる、正規表現を許す。(パフォーマンスは落ちる)
855865 -global 普通なら各行に一回のみ変換を行うが、これを付けると各行何回も変換を行う
856866 -quiet 変換結果を出力しない。戻り値と変換結果を格納した変数のみ設定する。
867+-byte バイトコードとして処理する
868+-utf8 UTF8コードとして処理する
869+-sjis SJISコードとして処理する
870+-eucjp EUCJPコードとして処理する
857871 -Lw 改行コードをCRLFとして処理する
858872 -Lm 改行コードをCRとして処理する
859873 -Lu 改行コードをLFとして処理する
@@ -875,7 +889,12 @@ scan 正規表現 (変換文字列|ブロック)
875889 最後にマッチした文字列 LAST_MATCH
876890 マッチした文字列の数 MATCH_NUMBER
877891
892+-ignore-case 大文字と小文字を無視する
878893 -multi-line 複数行にまたがる、正規表現を許す。(パフォーマンスは落ちる)
894+-byte バイトコードとして処理する
895+-utf8 UTF8コードとして処理する
896+-sjis SJISコードとして処理する
897+-eucjp EUCJPコードとして処理する
879898 -Lw 改行コードをCRLFとして処理する
880899 -Lm 改行コードをCRとして処理する
881900 -Lu 改行コードをLFとして処理する
@@ -890,6 +909,8 @@ split 正規表現
890909 パイプから得たテキストを正規表現にマッチする部分を区切りとして分解する。分解結果は複数行の文字列として出力される。
891910 正規表現が省略されたら、"\s+"が設定される。
892911
912+-no-regex 正規表現じゃなくて普通の文字列としてパターンを使う
913+-ignore-case 大文字と小文字を無視する
893914 -multi-line 複数行にまたがる、正規表現を許す。(パフォーマンスは落ちる)
894915 -byte バイトコードとして処理する
895916 -utf8 UTF8コードとして処理する
@@ -1053,7 +1074,7 @@ if (condition1) (block1) (condition2) (block2)...(conditioni X) (block X) (the l
10531074 -
10541075 If the result of condition is true, run conresponding block. If the all result of conditions, runthe last of blocks.
10551076 -
1056-return
1077+return (return code)
10571078 -
10581079 If running function or class, exited from it.
10591080 -
@@ -1089,6 +1110,8 @@ If you use this for filter, outputs the inout then.
10891110 load (script file name) (argument1) (argument2) ... (argument X)
10901111 -
10911112 Run the script file. Local variable stackframe is initialized, and local variable array "ARGV" has the arguments.
1113+
1114+-dynamic-library load C language extension library. Searched path is 3 step. First searched it from /usr/local/xyzsh/(pathname) or (installed prefix path)/(pathname), next searched it from ~/lib/(pathname), and finaly searched it from (absolute pathname or relative pathname). You can't ommit the file name extesion.
10921115 -
10931116 eval (block|string)
10941117 -
@@ -1347,6 +1370,8 @@ Matched number --> MATCH_NUMBER
13471370
13481371 -offsets Output all maching points.
13491372 -verbose Output maching point(index).
1373+-ignore-case Ignore case.
1374+-multi-line Allow to write multiline matching regex, but the performance is less than normal.
13501375 -byte assume text encode as byte code.
13511376 -utf8 assume text encode as utf-8 code.
13521377 -sjis assume text encode as SJIS code.
@@ -1616,8 +1641,10 @@ index (string)
16161641 -
16171642 It is a filter for outputing the index with searching the string position.
16181643
1644+-regex search with regex
16191645 -quiet No output, but set return code.
16201646 -ignore-case Ignore case.
1647+-multi-line Allow to write multiline matching regex, but the performance is less than normal.
16211648 -number (number) Set the first position on searching string.
16221649 -count 数値 Set the searching count.
16231650 -byte assume text encode as byte code.
@@ -1630,8 +1657,10 @@ rindex (string)
16301657 It is a filter for outputing the index with searching the string position.
16311658 Searching from the tail.
16321659
1660+-regex search with regex
16331661 -quiet No output, but set return code.
16341662 -ignore-case Ignore case.
1663+-multi-line Allow to write multiline matching regex, but the performance is less than normal.
16351664 -number (number) Set the first position on searching string.
16361665 -count 数値 Set the searching count.
16371666 -byte assume text encode as byte code.
@@ -1729,6 +1758,8 @@ b
17291758
17301759 You can get the count of searching to use the local variable "SUB_COUNT"
17311760
1761+-no-regex Don't use regex for pattern. Use it as text.
1762+-ignore-case ignore case
17321763 -multi-line Allow to write multiline matching regex, but the performance is less than normal.
17331764 -global Allow to match at several times in a line.
17341765 -quiet No output, but set return code and the local variables.
@@ -1736,6 +1767,10 @@ You can get the count of searching to use the local variable "SUB_COUNT"
17361767 -Lm Processing with CR line field
17371768 -Lu Processing with LF line field
17381769 -La Processing with BEL line field
1770+-byte assume text encode as byte code.
1771+-utf8 assume text encode as utf-8 code.
1772+-sjis assume text encode as SJIS code.
1773+-eucjp assume text encode as EUCJP code.
17391774 -
17401775 scan (regex|block)
17411776 -
@@ -1753,7 +1788,12 @@ Postmatched string --> POSTMATCH
17531788 Lastmatched string --> LAST_MATCH
17541789 Matched number --> MATCH_NUMBER
17551790
1791+-ignore-case ignore case
17561792 -multi-line Allow to write multiline matching regex, but the performance is less than normal.
1793+-byte assume text encode as byte code.
1794+-utf8 assume text encode as utf-8 code.
1795+-sjis assume text encode as SJIS code.
1796+-eucjp assume text encode as EUCJP code.
17571797 -Lw Processing with CRLF line field
17581798 -Lm Processing with CR line field
17591799 -Lu Processing with LF line field
@@ -1769,6 +1809,8 @@ split (regex)
17691809 It is a filter for spliting pipe data with regex.
17701810 If you omit the argument, xyzsh set "\s+" for it.
17711811
1812+-no-regex Don't use regex for pattern. Use it as text.
1813+-ignore-case ignore case
17721814 -multi-line Allow to write multiline matching regex, but the performance is less than normal.
17731815 -byte assume text encode as byte code.
17741816 -utf8 assume text encode as utf-8 code.
@@ -1865,6 +1907,10 @@ rl::run(
18651907 object help ( Help )
18661908
18671909 print <<<'EOS'
1910+point
1911+-
1912+カーソル位置を出力する
1913+-
18681914 point_move (number)
18691915 -
18701916 コンプレッション時のカーソル移動
@@ -1873,13 +1919,17 @@ clear_screen
18731919 -
18741920 コンプレッション時のスクリーンクリア
18751921 -
1922+replace_line (text) (cursor point)
1923+-
1924+コンプレッション時のテキストの置き換え
1925+-
18761926 delete_text (start index) (end index)
18771927 -
18781928 コンプレッション時のテキスト削除
18791929 -
1880-insert_text
1930+insert_text (text)
18811931 -
1882-コンプレッション時のテキスト挿入。テキストはパイプから得られる
1932+コンプレッション時のテキスト挿入。
18831933 -
18841934 write_history (file name)
18851935 -
@@ -1891,6 +1941,10 @@ read_history (file name)
18911941 EOS | help::set_helps_ja
18921942
18931943 print <<<'EOS'
1944+point
1945+-
1946+output cursor position.
1947+-
18941948 point_move (number)
18951949 -
18961950 cursor move on completion.
@@ -1903,9 +1957,13 @@ delete_text (start index) (end index)
19031957 -
19041958 delete editing line on completion.
19051959 -
1906-insert_text
1960+replace_line (text) (cursor point)
1961+-
1962+replace editing line on completion.
1963+-
1964+insert_text (text)
19071965 -
1908-add string which is getting pipe data to editing line on completion.
1966+add string to editing line on completion.
19091967 -
19101968 write_history (file name)
19111969 -
--- a/src/cmd_base.c
+++ b/src/cmd_base.c
@@ -208,8 +208,17 @@ BOOL cmd_if(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
208208
209209 BOOL cmd_return(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
210210 {
211- runinfo->mRCode = RCODE_RETURN;
212- return FALSE;
211+ if(runinfo->mArgsNumRuntime >= 2) {
212+ uchar code = atoi(runinfo->mArgsRuntime[1]);
213+ runinfo->mRCode = RCODE_RETURN | code;
214+
215+ return FALSE;
216+ }
217+ else {
218+ runinfo->mRCode = RCODE_RETURN;
219+
220+ return FALSE;
221+ }
213222 }
214223
215224 BOOL cmd_subshell(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
@@ -290,7 +299,7 @@ BOOL cmd_try(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
290299 if(runinfo->mBlocksNum == 2) {
291300 int rcode = 0;
292301 if(!run(runinfo->mBlocks[0], nextin, nextout, &rcode, runinfo->mCurrentObject, runinfo->mRunningObject)) {
293- if(rcode == RCODE_NFUN_FALSE || rcode == RCODE_BREAK || rcode == RCODE_RETURN || rcode == RCODE_EXIT) {
302+ if(rcode == RCODE_NFUN_FALSE || rcode == RCODE_BREAK || rcode & RCODE_RETURN || rcode == RCODE_EXIT) {
294303 runinfo->mRCode = rcode;
295304 return FALSE;
296305 }
@@ -379,7 +388,15 @@ BOOL cmd_sweep(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
379388
380389 BOOL cmd_load(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
381390 {
382- if(runinfo->mArgsNumRuntime >= 2) {
391+ if(sRunInfo_option(runinfo, "-dynamic-library")) {
392+ if(!load_so_file(runinfo->mArgsRuntime[1], nextin, nextout, runinfo))
393+ {
394+ return FALSE;
395+ }
396+
397+ runinfo->mRCode = 0;
398+ }
399+ else if(runinfo->mArgsNumRuntime >= 2) {
383400 runinfo->mRCode = 0;
384401 if(!load_file(runinfo->mArgsRuntime[1], nextin, nextout, runinfo, runinfo->mArgsRuntime + 2, runinfo->mArgsNumRuntime -2))
385402 {
--- a/src/cmd_condition.c
+++ b/src/cmd_condition.c
@@ -713,148 +713,3 @@ BOOL cmd_condition_re(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
713713 return TRUE;
714714 }
715715
716-#if defined(HAVE_MIGEMO_H)
717-#include <migemo.h>
718-
719-static migemo* gMigemo;
720-static regex_t* gReg;
721-
722-void migemo_init()
723-{
724- char buf[PATH_MAX];
725- char migemodir[PATH_MAX];
726- gMigemo = migemo_open(NULL);
727-
728- snprintf(migemodir, PATH_MAX, "%s", SYSTEM_MIGEMODIR);
729-
730- snprintf(buf, PATH_MAX, "%s/utf-8/migemo-dict", migemodir);
731- if(migemo_load(gMigemo, MIGEMO_DICTID_MIGEMO, buf) == MIGEMO_DICTID_INVALID) {
732- fprintf(stderr, "%s is not found\n", buf);
733- exit(1);
734- }
735- snprintf(buf, PATH_MAX, "%s/utf-8/roma2hira.dat", migemodir);
736- if(migemo_load(gMigemo, MIGEMO_DICTID_ROMA2HIRA, buf) == MIGEMO_DICTID_INVALID) {
737- fprintf(stderr, "%s is not found\n", buf);
738- exit(1);
739- }
740- snprintf(buf, PATH_MAX, "%s/utf-8/hira2kata.dat", migemodir);
741- if(migemo_load(gMigemo, MIGEMO_DICTID_HIRA2KATA, buf) == MIGEMO_DICTID_INVALID) {
742- fprintf(stderr, "%s is not found\n", buf);
743- exit(1);
744- }
745- snprintf(buf, PATH_MAX, "%s/utf-8/han2zen.dat", migemodir);
746- if(migemo_load(gMigemo, MIGEMO_DICTID_HAN2ZEN, buf) == MIGEMO_DICTID_INVALID) {
747- fprintf(stderr, "%s is not found\n", buf);
748- exit(1);
749- }
750-}
751-
752-void migemo_final()
753-{
754- onig_end();
755- migemo_close(gMigemo);
756- if(gReg) onig_free(gReg);
757- gReg = NULL;
758-}
759-
760-BOOL cmd_migemo_match(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
761-{
762- BOOL quiet = sRunInfo_option(runinfo, "-quiet");
763-
764- if(runinfo->mFilter && runinfo->mArgsNumRuntime == 2) {
765- runinfo->mRCode = RCODE_NFUN_FALSE;
766- char* target = SFD(nextin).mBuf;
767- char* regex = runinfo->mArgsRuntime[1];
768-
769- if(regex[0] == 0) {
770- runinfo->mRCode = 0;
771- if(!quiet) {
772- char buf[1024];
773- int n = snprintf(buf, 1024, "0%d\n", (int)strlen(target));
774- if(!fd_write(nextout, buf, n)) {
775- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
776- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
777- return FALSE;
778- }
779- }
780- }
781- else {
782- OnigUChar * p = migemo_query(gMigemo, regex);
783- if(p == NULL) {
784- err_msg("migemo query failed", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
785- migemo_release(gMigemo, (unsigned char*) p);
786- return FALSE;
787- }
788-
789- /// modify query ///
790- char* p2 = MALLOC(strlen(p)*2 + 1);
791-
792- char* _p = p;
793- char* _p2 = p2;
794-
795- while(*_p) {
796- if(*_p == '+') {
797- *_p2++ = '\\';
798- *_p2++ = *_p++;
799- }
800- else {
801- *_p2++ = *_p++;
802- }
803- }
804- *_p2 = 0;
805-
806- /// make regex ///
807- regex_t* reg;
808- OnigErrorInfo err_info;
809-
810- int r = onig_new(&reg, p2, p2 + strlen(p2), ONIG_OPTION_DEFAULT, ONIG_ENCODING_UTF8, ONIG_SYNTAX_DEFAULT, &err_info);
811-
812- FREE(p2);
813- migemo_release(gMigemo, (unsigned char*) p);
814-
815- if(r != ONIG_NORMAL && r != 0) {
816- err_msg("regex of migemo query failed", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
817- onig_free(reg);
818- return FALSE;
819- }
820-
821- OnigRegion* region = onig_region_new();
822- int r2 = onig_search(reg, target, target + strlen(target), target, target + strlen(target), region, ONIG_OPTION_NONE);
823-
824- if(r2 == 0) {
825- runinfo->mRCode = 0;
826- if(!quiet) {
827- char buf[1024];
828- int n = snprintf(buf, 1024, "%d\n%d\n", region->beg[0], region->end[0]);
829- if(!fd_write(nextout, buf, n)) {
830- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
831- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
832- onig_region_free(region, 1);
833- onig_free(reg);
834- return FALSE;
835- }
836- }
837- }
838- else {
839- if(!quiet) {
840- char buf[1024];
841- int n = snprintf(buf, 1024, "-1\n-1\n");
842- if(!fd_write(nextout, buf, n)) {
843- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
844- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
845- onig_region_free(region, 1);
846- onig_free(reg);
847- return FALSE;
848- }
849- }
850- }
851-
852- onig_region_free(region, 1);
853- onig_free(reg);
854- }
855- }
856-
857- return TRUE;
858-}
859-
860-#endif
--- a/src/cmd_obj.c
+++ b/src/cmd_obj.c
@@ -767,7 +767,7 @@ BOOL cmd_var(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
767767 sObject* tmp = access_object3(runinfo->mArgsRuntime[i], &current);
768768
769769 if(tmp && sRunInfo_option(runinfo, "-local") && !sRunInfo_option(runinfo, "-force")) {
770- err_msg("can't overwrite other the same name variable. Use -force option", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
770+ err_msg("this name of local variable hides global variable name. Use -force option", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
771771 return FALSE;
772772 }
773773
@@ -1115,7 +1115,7 @@ BOOL cmd_ary(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
11151115 sObject* tmp = access_object3(runinfo->mArgsRuntime[1], &current);
11161116
11171117 if(tmp && sRunInfo_option(runinfo, "-local") && !sRunInfo_option(runinfo, "-force")) {
1118- err_msg("can't overwrite other the same name variable. Use -force option", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1118+ err_msg("this name of local variable hides global variable name. Use -force option", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
11191119 return FALSE;
11201120 }
11211121
@@ -1374,7 +1374,7 @@ BOOL cmd_hash(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
13741374 sObject* tmp = access_object3(runinfo->mArgsRuntime[1], &current);
13751375
13761376 if(tmp && sRunInfo_option(runinfo, "-local") && !sRunInfo_option(runinfo, "-force")) {
1377- err_msg("can't overwrite other the same name variable. Use -force option", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1377+ err_msg("this name of local variable hides global variable name. Use -force option", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
13781378 return FALSE;
13791379 }
13801380
--- a/src/cmd_str.c
+++ b/src/cmd_str.c
@@ -338,7 +338,8 @@ BOOL cmd_x(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
338338 return TRUE;
339339 }
340340
341-BOOL cmd_index(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
341+
342+BOOL cmd_lc(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
342343 {
343344 enum eKanjiCode code = gKanjiCode;
344345 if(sRunInfo_option(runinfo, "-byte")) {
@@ -354,205 +355,96 @@ BOOL cmd_index(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
354355 code = kEucjp;
355356 }
356357
357- /// output
358358 if(runinfo->mFilter) {
359- if(runinfo->mArgsNumRuntime == 2) {
360- char* target = SFD(nextin).mBuf;
361-
362- char* word = runinfo->mArgsRuntime[1];
363-
364- /// get starting point ///
365- int start;
366- char* number;
367- if(number = sRunInfo_option_with_argument(runinfo, "-number")) {
368- start = atoi(number);
369-
370- int len = str_kanjilen(code, target);
371- if(len < 0) {
372- err_msg("invalid target string", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
373- return FALSE;
374- }
375-
376- if(start < 0) {
377- start += len;
378- if(start < 0) start = 0;
379- }
380- if(start >= len) {
381- start = len -1;
382- if(start < 0) start = 0;
383- }
384- }
385- else {
386- start = 0;
387- }
388-
389- /// get search count ///
390- int match_count;
391- char* count;
392- if(count = sRunInfo_option_with_argument(runinfo, "-count")) {
393- match_count = atoi(count);
394- if(match_count <= 0) { match_count = 1; }
395- }
396- else {
397- match_count = 1;
398- }
399-
400- char* start_byte = str_kanjipos2pointer(code, target, start);
401- char* p = start_byte;
402- char* result = NULL;
403- if(sRunInfo_option(runinfo, "-ignore-case")) {
404- while(p < start_byte + strlen(start_byte)) {
405- if(gXyzshSigInt) {
406- gXyzshSigInt = FALSE;
407- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
408- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
409- return FALSE;
410- }
411-
412- result = strcasestr(p, word);
413- if(result) {
414- match_count--;
415- if(match_count == 0) {
416- break;
417- }
418- p = result+strlen(word);
419- }
420- else {
421- break;
422- }
423- }
424- }
425- else {
426- while(p < start_byte + strlen(start_byte)) {
427- if(gXyzshSigInt) {
428- gXyzshSigInt = FALSE;
429- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
430- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
431- return FALSE;
432- }
433-
434- result = strstr(p, word);
435- if(result) {
436- match_count--;
437- if(match_count == 0) {
438- break;
439- }
440- p = result+strlen(word);
441- }
442- else {
443- break;
444- }
445- }
446- }
447-
448- char msg[64];
449- int size;
450- if(result == NULL || match_count !=0) {
451- size = snprintf(msg, 64, "-1");
452- runinfo->mRCode = RCODE_NFUN_FALSE;
453- }
454- else {
455- int c = str_pointer2kanjipos(code, target, result);
456- size = snprintf(msg, 64, "%d", c);
359+ sObject* str = STRING_NEW_STACK(SFD(nextin).mBuf);
360+ string_tolower(str, code);
457361
458- if(SFD(nextin).mBufLen == 0) {
459- runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
460- }
461- else {
462- runinfo->mRCode = 0;
463- }
464- }
362+ if(!fd_write(nextout, string_c_str(str), string_length(str))) {
363+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
364+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
365+ return FALSE;
366+ }
465367
466- /// Ω–Œœ ///
467- if(!sRunInfo_option(runinfo, "-quiet")) {
468- if(!fd_write(nextout, msg, size)) {
469- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
470- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
471- return FALSE;
472- }
473- if(!fd_write(nextout, "\n", 1)) {
474- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
475- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
476- return FALSE;
477- }
478- }
368+ if(SFD(nextin).mBufLen == 0) {
369+ runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
370+ }
371+ else {
372+ runinfo->mRCode = 0;
479373 }
480374 }
481375
482376 return TRUE;
483377 }
484378
485-static char* strstr_back(char* p, char* start, char* word, char* sname, int sline, char* command)
379+BOOL cmd_uc(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
486380 {
487- int n = strlen(word);
381+ enum eKanjiCode code = gKanjiCode;
382+ if(sRunInfo_option(runinfo, "-byte")) {
383+ code = kByte;
384+ }
385+ else if(sRunInfo_option(runinfo, "-utf8")) {
386+ code = kUtf8;
387+ }
388+ else if(sRunInfo_option(runinfo, "-sjis")) {
389+ code = kSjis;
390+ }
391+ else if(sRunInfo_option(runinfo, "-eucjp")) {
392+ code = kEucjp;
393+ }
488394
489- while(p >= start) {
490- BOOL flg = TRUE;
491- int i;
492- for(i=-1; i>=-n; i--) {
493- if(p[i] != word[n+i]) {
494- flg = FALSE;
495- break;
496- }
395+ if(runinfo->mFilter) {
396+ sObject* str = STRING_NEW_STACK(SFD(nextin).mBuf);
397+ string_toupper(str, code);
497398
498- if(gXyzshSigInt) {
499- err_msg("interrupt", sname, sline, command);
500- gXyzshSigInt = FALSE;
501- return NULL;
502- }
399+ if(!fd_write(nextout, string_c_str(str), string_length(str))) {
400+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
401+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
402+ return FALSE;
503403 }
504404
505- if(flg) {
506- return p -n;
405+ if(SFD(nextin).mBufLen == 0) {
406+ runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
507407 }
508408 else {
509- p--;
409+ runinfo->mRCode = 0;
510410 }
511411 }
512412
513- return NULL;
413+ return TRUE;
514414 }
515415
516-static char* strcasestr_back(char* p, char* start, char* word, char* sname, int sline, char* command)
416+BOOL cmd_chomp(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
517417 {
518- int n = strlen(word);
519-
520- while(p >= start) {
521- BOOL flg = TRUE;
522- int i;
523- for(i=-1; i>=-n; i--) {
524- if(isascii(p[i]) && isascii(word[n+i])) {
525- if(tolower(p[i]) != tolower(word[n+i])) {
526- flg = FALSE;
527- break;
528- }
418+ if(runinfo->mFilter) {
419+ sObject* str = STRING_NEW_STACK(SFD(nextin).mBuf);
420+ if(string_chomp(str)) {
421+ if(SFD(nextin).mBufLen == 0) {
422+ runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
529423 }
530424 else {
531- if(p[i] != word[n+i]) {
532- flg = FALSE;
533- break;
534- }
425+ runinfo->mRCode = 0;
535426 }
536-
537- if(gXyzshSigInt) {
538- gXyzshSigInt = FALSE;
539- err_msg("interrupt", sname, sline, command);
540- return NULL;
427+ }
428+ else {
429+ if(SFD(nextin).mBufLen == 0) {
430+ runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
431+ }
432+ else {
433+ runinfo->mRCode = 1;
541434 }
542435 }
543436
544- if(flg) {
545- return p -n;
546- }
547- else {
548- p--;
437+ if(!fd_write(nextout, string_c_str(str), string_length(str))) {
438+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
439+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
440+ return FALSE;
549441 }
550442 }
551443
552- return NULL;
444+ return TRUE;
553445 }
554446
555-BOOL cmd_rindex(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
447+BOOL cmd_chop(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
556448 {
557449 enum eKanjiCode code = gKanjiCode;
558450 if(sRunInfo_option(runinfo, "-byte")) {
@@ -568,303 +460,51 @@ BOOL cmd_rindex(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
568460 code = kEucjp;
569461 }
570462
571- /// output
572463 if(runinfo->mFilter) {
573- if(runinfo->mArgsNumRuntime == 2) {
574- char* target = SFD(nextin).mBuf;
575- char* word = runinfo->mArgsRuntime[1];
576-
577- /// get starting point ///
578- int len = str_kanjilen(code, target);
579- if(len < 0) {
580- err_msg("invalid target string", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
581- return FALSE;
582- }
464+ sObject* str = STRING_NEW_STACK(SFD(nextin).mBuf);
583465
584- int start;
585- char* number;
586- if(number = sRunInfo_option_with_argument(runinfo, "-number")) {
587- start = atoi(number);
466+ if(code == kByte) {
467+ char* s = string_c_str(str);
468+ const int len = strlen(s);
469+
470+ if(len >= 2 && s[len-2] == '\r' && s[len-1] == '\n')
471+ {
472+ string_trunc(str, len-2);
588473
589- if(start < 0) {
590- start += len;
591- if(start < 0) start = 0;
474+ if(SFD(nextin).mBufLen == 0) {
475+ runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
592476 }
593- if(start >= len) {
594- start = len -1 ;
595- if(start < 0) start = 0;
477+ else {
478+ runinfo->mRCode = 0;
596479 }
597480 }
598- else {
599- start = len -1;
600- if(start < 0) start = 0;
601- }
602-
603- /// get search count ///
604- int match_count;
605- char* count;
606- if(count = sRunInfo_option_with_argument(runinfo, "-count")) {
607- match_count = atoi(count);
608- if(match_count <= 0) { match_count = 1; }
609- }
610- else {
611- match_count = 1;
612- }
613-
614-
615- char* start_byte = str_kanjipos2pointer(code, target, start+1);
616- char* p = start_byte;
617- char* result = NULL;
618- if(sRunInfo_option(runinfo, "-ignore-case")) {
619- while(p>=target) {
620- result = strcasestr_back(p, target, word, runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
621-
622- if(gXyzshSigInt) {
623- gXyzshSigInt = FALSE;
624- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
625- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
626- return FALSE;
627- }
481+ else if(len >= 1) {
482+ string_trunc(str, len-1);
628483
629- if(result != NULL) {
630- match_count--;
631- if(match_count == 0) {
632- break;
633- }
634- p = result - 1;
635- }
636- else {
637- break;
638- }
484+ if(SFD(nextin).mBufLen == 0) {
485+ runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
486+ }
487+ else {
488+ runinfo->mRCode = 0;
639489 }
640490 }
641491 else {
642- while(p>=target) {
643- result = strstr_back(p, target, word, runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
644-
645- if(gXyzshSigInt) {
646- gXyzshSigInt = FALSE;
647- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
648- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
649- return FALSE;
650- }
651-
652- if(result != NULL) {
653- match_count--;
654- if(match_count == 0) {
655- break;
656- }
657- p = result - 1;
658- }
659- else {
660- break;
661- }
492+ if(SFD(nextin).mBufLen == 0) {
493+ runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
494+ }
495+ else {
496+ runinfo->mRCode = 1;
662497 }
663498 }
499+ }
500+ else {
501+ char* s = string_c_str(str);
502+ const int len = str_kanjilen(code, s);
664503
665- char msg[64];
666- int size;
667- if(result == NULL || match_count !=0) {
668- size = snprintf(msg, 64, "-1");
669- runinfo->mRCode = RCODE_NFUN_FALSE;
670- }
671- else {
672- int c = str_pointer2kanjipos(code, target, result);
673- size = snprintf(msg, 64, "%d", c);
504+ char* last_char_head = str_kanjipos2pointer(code, s, len-1);
505+ string_erase(str, last_char_head-s, s + strlen(s) - last_char_head);
674506
675- if(SFD(nextin).mBufLen == 0) {
676- runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
677- }
678- else {
679- runinfo->mRCode = 0;
680- }
681- }
682-
683- /// Ω–Œœ ///
684- if(!sRunInfo_option(runinfo, "-quiet")) {
685- if(!fd_write(nextout, msg, size)) {
686- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
687- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
688- return FALSE;
689- }
690- if(!fd_write(nextout, "\n", 1)) {
691- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
692- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
693- return FALSE;
694- }
695- }
696- }
697- }
698-
699- return TRUE;
700-}
701-
702-BOOL cmd_lc(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
703-{
704- enum eKanjiCode code = gKanjiCode;
705- if(sRunInfo_option(runinfo, "-byte")) {
706- code = kByte;
707- }
708- else if(sRunInfo_option(runinfo, "-utf8")) {
709- code = kUtf8;
710- }
711- else if(sRunInfo_option(runinfo, "-sjis")) {
712- code = kSjis;
713- }
714- else if(sRunInfo_option(runinfo, "-eucjp")) {
715- code = kEucjp;
716- }
717-
718- if(runinfo->mFilter) {
719- sObject* str = STRING_NEW_STACK(SFD(nextin).mBuf);
720- string_tolower(str, code);
721-
722- if(!fd_write(nextout, string_c_str(str), string_length(str))) {
723- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
724- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
725- return FALSE;
726- }
727-
728- if(SFD(nextin).mBufLen == 0) {
729- runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
730- }
731- else {
732- runinfo->mRCode = 0;
733- }
734- }
735-
736- return TRUE;
737-}
738-
739-BOOL cmd_uc(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
740-{
741- enum eKanjiCode code = gKanjiCode;
742- if(sRunInfo_option(runinfo, "-byte")) {
743- code = kByte;
744- }
745- else if(sRunInfo_option(runinfo, "-utf8")) {
746- code = kUtf8;
747- }
748- else if(sRunInfo_option(runinfo, "-sjis")) {
749- code = kSjis;
750- }
751- else if(sRunInfo_option(runinfo, "-eucjp")) {
752- code = kEucjp;
753- }
754-
755- if(runinfo->mFilter) {
756- sObject* str = STRING_NEW_STACK(SFD(nextin).mBuf);
757- string_toupper(str, code);
758-
759- if(!fd_write(nextout, string_c_str(str), string_length(str))) {
760- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
761- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
762- return FALSE;
763- }
764-
765- if(SFD(nextin).mBufLen == 0) {
766- runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
767- }
768- else {
769- runinfo->mRCode = 0;
770- }
771- }
772-
773- return TRUE;
774-}
775-
776-BOOL cmd_chomp(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
777-{
778- if(runinfo->mFilter) {
779- sObject* str = STRING_NEW_STACK(SFD(nextin).mBuf);
780- if(string_chomp(str)) {
781- if(SFD(nextin).mBufLen == 0) {
782- runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
783- }
784- else {
785- runinfo->mRCode = 0;
786- }
787- }
788- else {
789- if(SFD(nextin).mBufLen == 0) {
790- runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
791- }
792- else {
793- runinfo->mRCode = 1;
794- }
795- }
796-
797- if(!fd_write(nextout, string_c_str(str), string_length(str))) {
798- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
799- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
800- return FALSE;
801- }
802- }
803-
804- return TRUE;
805-}
806-
807-BOOL cmd_chop(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
808-{
809- enum eKanjiCode code = gKanjiCode;
810- if(sRunInfo_option(runinfo, "-byte")) {
811- code = kByte;
812- }
813- else if(sRunInfo_option(runinfo, "-utf8")) {
814- code = kUtf8;
815- }
816- else if(sRunInfo_option(runinfo, "-sjis")) {
817- code = kSjis;
818- }
819- else if(sRunInfo_option(runinfo, "-eucjp")) {
820- code = kEucjp;
821- }
822-
823- if(runinfo->mFilter) {
824- sObject* str = STRING_NEW_STACK(SFD(nextin).mBuf);
825-
826- if(code == kByte) {
827- char* s = string_c_str(str);
828- const int len = strlen(s);
829-
830- if(len >= 2 && s[len-2] == '\r' && s[len-1] == '\n')
831- {
832- string_trunc(str, len-2);
833-
834- if(SFD(nextin).mBufLen == 0) {
835- runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
836- }
837- else {
838- runinfo->mRCode = 0;
839- }
840- }
841- else if(len >= 1) {
842- string_trunc(str, len-1);
843-
844- if(SFD(nextin).mBufLen == 0) {
845- runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
846- }
847- else {
848- runinfo->mRCode = 0;
849- }
850- }
851- else {
852- if(SFD(nextin).mBufLen == 0) {
853- runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
854- }
855- else {
856- runinfo->mRCode = 1;
857- }
858- }
859- }
860- else {
861- char* s = string_c_str(str);
862- const int len = str_kanjilen(code, s);
863-
864- char* last_char_head = str_kanjipos2pointer(code, s, len-1);
865- string_erase(str, last_char_head-s, s + strlen(s) - last_char_head);
866-
867- if(len > 0) {
507+ if(len > 0) {
868508 if(SFD(nextin).mBufLen == 0) {
869509 runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
870510 }
@@ -1132,498 +772,1315 @@ BOOL cmd_printf(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
1132772 return TRUE;
1133773 }
1134774
1135-BOOL cmd_sub(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
775+BOOL cmd_add(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
1136776 {
1137- BOOL quiet = sRunInfo_option(runinfo, "-quiet");
1138-
1139- if(runinfo->mFilter && (runinfo->mArgsNumRuntime == 3 || runinfo->mArgsNumRuntime == 2 && runinfo->mBlocksNum >= 1)) {
1140- sObject* block;
1141- sObject* nextin2;
1142- sObject* nextout2;
777+ enum eKanjiCode code = gKanjiCode;
778+ if(sRunInfo_option(runinfo, "-byte")) {
779+ code = kByte;
780+ }
781+ else if(sRunInfo_option(runinfo, "-utf8")) {
782+ code = kUtf8;
783+ }
784+ else if(sRunInfo_option(runinfo, "-sjis")) {
785+ code = kSjis;
786+ }
787+ else if(sRunInfo_option(runinfo, "-eucjp")) {
788+ code = kEucjp;
789+ }
1143790
1144- if(runinfo->mBlocksNum >= 1) {
1145- block = runinfo->mBlocks[0];
1146- nextin2 = FD_NEW_STACK();
1147- nextout2 = FD_NEW_STACK();
791+ if(runinfo->mFilter && runinfo->mArgsNumRuntime == 2) {
792+ char* arg = runinfo->mArgsRuntime[1];
793+ int number;
794+ char* argument;
795+ if(argument = sRunInfo_option_with_argument(runinfo, "-number")) {
796+ number = atoi(argument);
797+ }
798+ else if(argument = sRunInfo_option_with_argument(runinfo, "-index")) {
799+ number = atoi(argument);
1148800 }
1149801 else {
1150- block = NULL;
802+ number = -1;
1151803 }
1152804
1153- BOOL global = sRunInfo_option(runinfo, "-global");
805+ const int len = str_kanjilen(code, SFD(nextin).mBuf);
1154806
1155- char* regex = runinfo->mArgsRuntime[1];
1156- char* destination = runinfo->mArgsRuntime[2];
807+ if(number < 0) {
808+ number += len + 1;
809+ if(number < 0) number = 0;
810+ }
1157811
1158- int sub_count = 0;
812+ if(number < len) {
813+ int point = str_kanjipos2pointer(code, SFD(nextin).mBuf, number) - SFD(nextin).mBuf;
814+ if(!fd_write(nextout, SFD(nextin).mBuf, point)) {
815+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
816+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
817+ return FALSE;
818+ }
819+ if(!fd_write(nextout, arg, strlen(arg))) {
820+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
821+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
822+ return FALSE;
823+ }
824+ if(!fd_write(nextout, SFD(nextin).mBuf + point, SFD(nextin).mBufLen - point)) {
825+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
826+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
827+ return FALSE;
828+ }
829+ }
830+ else {
831+ if(!fd_write(nextout, SFD(nextin).mBuf, SFD(nextin).mBufLen)) {
832+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
833+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
834+ return FALSE;
835+ }
836+ if(!fd_write(nextout, arg, strlen(arg))) {
837+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
838+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
839+ return FALSE;
840+ }
841+ }
1159842
1160- regex_t* reg;
843+ if(SFD(nextin).mBufLen == 0) {
844+ runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
845+ }
846+ else {
847+ runinfo->mRCode = 0;
848+ }
849+ }
850+
851+ return TRUE;
852+}
853+
854+BOOL cmd_del(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
855+{
856+ enum eKanjiCode code = gKanjiCode;
857+ if(sRunInfo_option(runinfo, "-byte")) {
858+ code = kByte;
859+ }
860+ else if(sRunInfo_option(runinfo, "-utf8")) {
861+ code = kUtf8;
862+ }
863+ else if(sRunInfo_option(runinfo, "-sjis")) {
864+ code = kSjis;
865+ }
866+ else if(sRunInfo_option(runinfo, "-eucjp")) {
867+ code = kEucjp;
868+ }
869+
870+
871+ if(runinfo->mFilter && runinfo->mArgsNumRuntime == 2) {
872+ char* arg = runinfo->mArgsRuntime[1];
873+ int index = atoi(arg);
874+
875+ int number;
876+ char* argument;
877+ if(argument = sRunInfo_option_with_argument(runinfo, "-number")) {
878+ number = atoi(argument);
879+ }
880+ else if(argument = sRunInfo_option_with_argument(runinfo, "-index")) {
881+ number = atoi(argument);
882+ }
883+ else {
884+ number = 1;
885+ }
886+
887+ const int len = str_kanjilen(code, SFD(nextin).mBuf);
888+
889+ if(index < 0) {
890+ index += len;
891+ if(index < 0) index = 0;
892+ }
893+ if(index >= len) {
894+ index = len -1;
895+ if(index < 0) index = 0;
896+ }
897+
898+ int point = str_kanjipos2pointer(code, SFD(nextin).mBuf, index) - SFD(nextin).mBuf;
899+
900+ if(!fd_write(nextout, SFD(nextin).mBuf, point)) {
901+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
902+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
903+ return FALSE;
904+ }
905+ if(index + number < len) {
906+ char* point = str_kanjipos2pointer(code, SFD(nextin).mBuf, index + number);
907+ if(!fd_write(nextout, point, strlen(point))) {
908+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
909+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
910+ return FALSE;
911+ }
912+ }
913+
914+ if(SFD(nextin).mBufLen == 0) {
915+ runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
916+ }
917+ else {
918+ runinfo->mRCode = 0;
919+ }
920+ }
921+
922+ return TRUE;
923+}
924+
925+BOOL cmd_rows(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
926+{
927+ enum eKanjiCode code = gKanjiCode;
928+ if(sRunInfo_option(runinfo, "-byte")) {
929+ code = kByte;
930+ }
931+ else if(sRunInfo_option(runinfo, "-utf8")) {
932+ code = kUtf8;
933+ }
934+ else if(sRunInfo_option(runinfo, "-sjis")) {
935+ code = kSjis;
936+ }
937+ else if(sRunInfo_option(runinfo, "-eucjp")) {
938+ code = kEucjp;
939+ }
940+
941+ if(runinfo->mFilter && runinfo->mArgsNumRuntime > 1 && runinfo->mBlocksNum <= runinfo->mArgsNumRuntime-1) {
942+ if(SFD(nextin).mBufLen == 0) {
943+ runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
944+ }
945+ else {
946+ runinfo->mRCode = 0;
947+ }
948+
949+ int i;
950+ for(i=1; i<runinfo->mArgsNumRuntime; i++) {
951+ char* arg = runinfo->mArgsRuntime[i];
952+ char* p;
953+ if(p = strstr(arg, "..")) {
954+ char buf[128+1];
955+ char buf2[128+1];
956+ const int len = p - arg;
957+ const int len2 = arg + strlen(arg) - (p + 2);
958+ if(len < 128 || len2 < 128) {
959+ memcpy(buf, arg, len);
960+ buf[len] = 0;
961+
962+ memcpy(buf2, p + 2, len2);
963+ buf2[len2] = 0;
964+ }
965+ else {
966+ err_msg("invalid range", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
967+ return FALSE;
968+ }
969+
970+ const int kanjilen = str_kanjilen(code, SFD(nextin).mBuf);
971+ if(kanjilen > 0) {
972+ int first = atoi(buf);
973+ int second = atoi(buf2);
974+
975+ if(first < 0) {
976+ first += kanjilen;
977+ if(first < 0) first = 0;
978+ }
979+ if(second < 0) {
980+ second += kanjilen;
981+ if(second < 0) second = 0;
982+ }
983+ if(first >= kanjilen) {
984+ first = kanjilen -1;
985+ if(first < 0) first = 0;
986+ }
987+ if(second >= kanjilen) {
988+ second = kanjilen -1;
989+ if(second < 0) second = 0;
990+ }
991+
992+ /// make table to indexing access ///
993+ char** array = MALLOC(sizeof(char*)*(kanjilen+1));
994+ if(code == kByte) {
995+ int k;
996+ for(k=0; k<kanjilen; k++) {
997+ array[k] = SFD(nextin).mBuf + k;
998+ }
999+ array[k] = SFD(nextin).mBuf + k;
1000+ }
1001+ else if(code == kUtf8) {
1002+ char* p = SFD(nextin).mBuf;
1003+
1004+ int k;
1005+ for(k=0; k<kanjilen; k++) {
1006+ array[k] = p;
1007+ if(((unsigned char)*p) > 127) {
1008+ const int size = ((*p & 0x80) >> 7) + ((*p & 0x40) >> 6) + ((*p & 0x20) >> 5) + ((*p & 0x10) >> 4);
1009+ p+=size;
1010+ }
1011+ else {
1012+ p++;
1013+ }
1014+ }
1015+ array[k] = p;
1016+ }
1017+ else {
1018+ char* p = SFD(nextin).mBuf;
1019+
1020+ int k;
1021+ for(k=0; k<kanjilen; k++) {
1022+ const int size = is_kanji(code, *p) ? 2 : 1;
1023+ array[k] = p;
1024+ p+=size;
1025+ }
1026+ array[k] = p;
1027+ }
1028+
1029+ if(first < second) {
1030+ sObject* nextin2 = FD_NEW_STACK();
1031+
1032+ int j;
1033+ for(j=first; j<=second; j++) {
1034+ fd_clear(nextin2);
1035+
1036+ if(!fd_write(nextin2, array[j], array[j+1] -array[j])) {
1037+ err_msg("interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1038+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1039+ FREE(array);
1040+ return FALSE;
1041+ }
1042+
1043+ if(i-1 < runinfo->mBlocksNum) {
1044+ int rcode = 0;
1045+ if(!run(runinfo->mBlocks[i-1], nextin2, nextout, &rcode, runinfo->mCurrentObject, runinfo->mRunningObject)) {
1046+ runinfo->mRCode = rcode;
1047+ FREE(array);
1048+ return FALSE;
1049+ }
1050+ runinfo->mRCode = rcode;
1051+ }
1052+ else {
1053+ if(!fd_write(nextout, SFD(nextin2).mBuf, SFD(nextin2).mBufLen))
1054+ {
1055+ err_msg("interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1056+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1057+ FREE(array);
1058+ return FALSE;
1059+ }
1060+ runinfo->mRCode = 0;
1061+ }
1062+ }
1063+ }
1064+ else {
1065+ sObject* nextin2 = FD_NEW_STACK();
1066+
1067+ int j;
1068+ for(j=first; j>=second; j--) {
1069+ fd_clear(nextin2);
1070+
1071+ if(!fd_write(nextin2, array[j], array[j+1]-array[j])) {
1072+ err_msg("interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1073+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1074+ FREE(array);
1075+ return FALSE;
1076+ }
1077+
1078+ if(i-1 < runinfo->mBlocksNum) {
1079+ int rcode = 0;
1080+ if(!run(runinfo->mBlocks[i-1], nextin2, nextout, &rcode, runinfo->mCurrentObject, runinfo->mRunningObject)) {
1081+ runinfo->mRCode = rcode;
1082+ FREE(array);
1083+ return FALSE;
1084+ }
1085+ runinfo->mRCode = rcode;
1086+ }
1087+ else {
1088+ if(!fd_write(nextout, SFD(nextin2).mBuf, SFD(nextin2).mBufLen))
1089+ {
1090+ err_msg("interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1091+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1092+ FREE(array);
1093+ return FALSE;
1094+ }
1095+ runinfo->mRCode = 0;
1096+ }
1097+ }
1098+ }
1099+
1100+ FREE(array);
1101+ }
1102+ }
1103+ else {
1104+ const int len = str_kanjilen(code, SFD(nextin).mBuf);
1105+ int num = atoi(arg);
1106+
1107+ if(num < 0) {
1108+ num += len;
1109+ if(num < 0) num = 0;
1110+ }
1111+ if(num >= len) {
1112+ num = len -1;
1113+ if(num < 0) num = 0;
1114+ }
1115+
1116+ sObject* nextin2 = FD_NEW_STACK();
1117+
1118+ char* str = str_kanjipos2pointer(code, SFD(nextin).mBuf, num);
1119+ char* str2 = str_kanjipos2pointer(code, str, 1);
1120+ if(!fd_write(nextin2, str, str2 -str)) {
1121+ err_msg("interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1122+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1123+ return FALSE;
1124+ }
1125+
1126+ if(i-1 < runinfo->mBlocksNum) {
1127+ int rcode = 0;
1128+ if(!run(runinfo->mBlocks[i-1], nextin2, nextout, &rcode, runinfo->mCurrentObject, runinfo->mRunningObject)) {
1129+ runinfo->mRCode = rcode;
1130+ return FALSE;
1131+ }
1132+ runinfo->mRCode = rcode;
1133+ }
1134+ else {
1135+ if(!fd_write(nextout, SFD(nextin2).mBuf, SFD(nextin2).mBufLen))
1136+ {
1137+ err_msg("interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1138+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1139+ return FALSE;
1140+ }
1141+ runinfo->mRCode = 0;
1142+ }
1143+ }
1144+ }
1145+ }
1146+
1147+ return TRUE;
1148+}
1149+
1150+BOOL cmd_scan(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
1151+{
1152+ char* field = "\n";
1153+ if(sRunInfo_option(runinfo, "-Lw")) {
1154+ field = "\r\n";
1155+ }
1156+ else if(sRunInfo_option(runinfo, "-Lm")) {
1157+ field = "\r";
1158+ }
1159+ else if(sRunInfo_option(runinfo, "-Lu")) {
1160+ field = "\n";
1161+ }
1162+ else if(sRunInfo_option(runinfo, "-La")) {
1163+ field = "\a";
1164+ }
1165+
1166+ if(runinfo->mFilter && runinfo->mArgsNumRuntime == 2) {
1167+ sObject* block;
1168+ sObject* nextin2;
1169+
1170+ if(runinfo->mBlocksNum >= 1) {
1171+ block = runinfo->mBlocks[0];
1172+ nextin2 = FD_NEW_STACK();
1173+ }
1174+ else {
1175+ block = NULL;
1176+ }
1177+
1178+ int match_count = 0;
1179+ char* regex = runinfo->mArgsRuntime[1];
1180+
1181+ regex_t* reg;
11611182 int r = get_onig_regex(&reg, runinfo, regex);
11621183
11631184 if(r == ONIG_NORMAL) {
1164- char* p = SFD(nextin).mBuf;
1185+ char* target = SFD(nextin).mBuf;
1186+ char* p = SFD(nextin).mBuf;
1187+ char* end = SFD(nextin).mBuf + strlen(SFD(nextin).mBuf);
1188+ while(p < end) {
1189+ OnigRegion* region = onig_region_new();
1190+ int r2 = onig_search(reg, target
1191+ , target + strlen(target)
1192+ , p
1193+ , p + strlen(p)
1194+ , region, ONIG_OPTION_NONE);
1195+
1196+ if(r2 >= 0) {
1197+ match_count++;
1198+
1199+ if(block) {
1200+ fd_clear(nextin2);
1201+
1202+ /// no group ///
1203+ if(region->num_regs == 1) {
1204+ const int n = region->end[0] - region->beg[0];
1205+
1206+ if(!fd_write(nextin2, target + region->beg[0], n)) {
1207+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1208+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1209+ onig_free(reg);
1210+ onig_region_free(region, 1);
1211+ return FALSE;
1212+ }
1213+ if(!fd_write(nextin2, field, strlen(field))) {
1214+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1215+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1216+ onig_free(reg);
1217+ onig_region_free(region, 1);
1218+ return FALSE;
1219+ }
1220+ }
1221+ /// group ///
1222+ else {
1223+ int i;
1224+ for (i=1; i<region->num_regs; i++) {
1225+ const int size = region->end[i] - region->beg[i];
1226+
1227+ if(!fd_write(nextin2, target + region->beg[i], size)) {
1228+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1229+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1230+ onig_free(reg);
1231+ onig_region_free(region, 1);
1232+ return FALSE;
1233+ }
1234+
1235+ if(i==region->num_regs-1) {
1236+ if(!fd_write(nextin2, field, strlen(field))) {
1237+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1238+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1239+ onig_free(reg);
1240+ onig_region_free(region, 1);
1241+ return FALSE;
1242+ }
1243+ }
1244+ else {
1245+ if(!fd_write(nextin2, "\t", 1)) {
1246+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1247+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1248+ onig_free(reg);
1249+ onig_region_free(region, 1);
1250+ return FALSE;
1251+ }
1252+ }
1253+ }
1254+ }
1255+
1256+ clear_matching_info_variable();
1257+
1258+ const int size = region->beg[0] - (p - target);
1259+ if(size > 0) {
1260+ uobject_put(gRootObject, "PREMATCH", STRING_NEW_GC3(p, size, FALSE));
1261+ }
1262+
1263+ const int size2 = region->end[0] - region->beg[0];
1264+
1265+ uobject_put(gRootObject, "MATCH", STRING_NEW_GC3(target + region->beg[0], size2, FALSE));
1266+ uobject_put(gRootObject, "0", STRING_NEW_GC3(target + region->beg[0], size2, FALSE));
1267+
1268+ const int n = strlen(target)-region->end[0];
1269+ if(n > 0) {
1270+ uobject_put(gRootObject, "POSTMATCH", STRING_NEW_GC3(target + region->end[0], n, FALSE));
1271+ }
1272+
1273+ int i;
1274+ for (i=1; i<region->num_regs; i++) {
1275+ const int size = region->end[i] - region->beg[i];
1276+
1277+ char name[16];
1278+ snprintf(name, 16, "%d", i);
1279+
1280+ uobject_put(gRootObject, name, STRING_NEW_GC3(target + region->beg[i], size, FALSE));
1281+ }
1282+
1283+ if(region->num_regs > 0) {
1284+ const int n = region->num_regs -1;
1285+
1286+ const int size = region->end[n] - region->beg[n];
1287+
1288+ uobject_put(gRootObject, "LAST_MATCH", STRING_NEW_GC3(target + region->beg[n], size, FALSE));
1289+ }
1290+
1291+ char buf[128];
1292+ snprintf(buf, 128, "%d", region->num_regs);
1293+ uobject_put(gRootObject, "MATCH_NUMBER", STRING_NEW_GC(buf, FALSE));
1294+
1295+ int rcode = 0;
1296+ if(!run(block, nextin2, nextout, &rcode, runinfo->mCurrentObject, runinfo->mRunningObject)) {
1297+ runinfo->mRCode = rcode;
1298+ onig_region_free(region, 1);
1299+ onig_free(reg);
1300+ return FALSE;
1301+ }
1302+ }
1303+ else {
1304+ /// no group ///
1305+ if(region->num_regs == 1) {
1306+ const int n = region->end[0] - region->beg[0];
1307+
1308+ if(!fd_write(nextout, target + region->beg[0], n)) {
1309+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1310+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1311+ onig_free(reg);
1312+ onig_region_free(region, 1);
1313+ return FALSE;
1314+ }
1315+ if(!fd_write(nextout, field, strlen(field))) {
1316+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1317+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1318+ onig_free(reg);
1319+ onig_region_free(region, 1);
1320+ return FALSE;
1321+ }
1322+ }
1323+ /// group ///
1324+ else {
1325+ int i;
1326+ for (i=1; i<region->num_regs; i++) {
1327+ const int size = region->end[i] - region->beg[i];
1328+
1329+ if(!fd_write(nextout, target + region->beg[i], size)) {
1330+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1331+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1332+ onig_free(reg);
1333+ onig_region_free(region, 1);
1334+ return FALSE;
1335+ }
1336+
1337+ if(i==region->num_regs-1) {
1338+ if(!fd_write(nextout, field, strlen(field))) {
1339+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1340+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1341+ onig_free(reg);
1342+ onig_region_free(region, 1);
1343+ return FALSE;
1344+ }
1345+ }
1346+ else {
1347+ if(!fd_write(nextout, "\t", 1)) {
1348+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1349+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1350+ onig_free(reg);
1351+ onig_region_free(region, 1);
1352+ return FALSE;
1353+ }
1354+ }
1355+ }
1356+ }
1357+ }
1358+
1359+ p = SFD(nextin).mBuf + region->end[0];
1360+ }
1361+ else {
1362+ p++;
1363+ }
1364+
1365+ onig_region_free(region, 1);
1366+ }
1367+
1368+ onig_free(reg);
1369+
1370+ char buf[128];
1371+ snprintf(buf, 128, "%d", match_count);
1372+ uobject_put(gRootObject, "MATCH_COUNT", STRING_NEW_GC(buf, FALSE));
1373+
1374+ if(match_count > 0) {
1375+ if(SFD(nextin).mBufLen == 0) {
1376+ runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
1377+ }
1378+ else {
1379+ runinfo->mRCode = 0;
1380+ }
1381+ }
1382+ else {
1383+ runinfo->mRCode = RCODE_NFUN_FALSE;
1384+ }
1385+ }
1386+ else {
1387+ err_msg("invalid regex", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1388+ return FALSE;
1389+ }
1390+ }
11651391
1166- sObject* sub_str = STRING_NEW_STACK("");
1392+ return TRUE;
1393+}
11671394
1168- while(1) {
1169- OnigRegion* region = onig_region_new();
1170- OnigErrorInfo err_info;
1395+BOOL cmd_index(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
1396+{
1397+ enum eKanjiCode code = gKanjiCode;
1398+ if(sRunInfo_option(runinfo, "-byte")) {
1399+ code = kByte;
1400+ }
1401+ else if(sRunInfo_option(runinfo, "-utf8")) {
1402+ code = kUtf8;
1403+ }
1404+ else if(sRunInfo_option(runinfo, "-sjis")) {
1405+ code = kSjis;
1406+ }
1407+ else if(sRunInfo_option(runinfo, "-eucjp")) {
1408+ code = kEucjp;
1409+ }
11711410
1411+ if(sRunInfo_option(runinfo, "-regex")) {
1412+ if(runinfo->mFilter) {
1413+ if(runinfo->mArgsNumRuntime == 2) {
11721414 char* target = SFD(nextin).mBuf;
1415+ char* regex = runinfo->mArgsRuntime[1];
11731416
1174- const int point = p - target;
1175- int r2 = onig_search(reg, target
1176- , target + strlen(target)
1177- , p
1178- , p + strlen(p)
1179- , region, ONIG_OPTION_NONE);
1417+ regex_t* reg;
1418+ int r = get_onig_regex(&reg, runinfo, regex);
11801419
1181- if(r2 == ONIG_MISMATCH) {
1182- onig_region_free(region, 1);
1420+ if(r == ONIG_NORMAL) {
1421+ /// get starting point ///
1422+ int start;
1423+ char* number;
1424+ if(number = sRunInfo_option_with_argument(runinfo, "-number")) {
1425+ start = atoi(number);
11831426
1184- if(!quiet) {
1185- if(!fd_write(nextout, p, strlen(p))) {
1186- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1187- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1188- onig_free(reg);
1427+ int len = str_kanjilen(code, target);
1428+ if(len < 0) {
1429+ err_msg("invalid target string", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
11891430 return FALSE;
11901431 }
1191- }
1192- break;
1193- }
1194- else {
1195- /// make distination ///
1196- string_put(sub_str, "");
1197-
1198- if(block) {
1199- clear_matching_info_variable();
12001432
1201- const int size = region->beg[0] - (p - target);
1202- if(size > 0) {
1203- uobject_put(gRootObject, "PREMATCH", STRING_NEW_GC3(p, size, FALSE));
1433+ if(start < 0) {
1434+ start += len;
1435+ if(start < 0) start = 0;
1436+ }
1437+ if(start >= len) {
1438+ start = len -1;
1439+ if(start < 0) start = 0;
12041440 }
1441+ }
1442+ else {
1443+ start = 0;
1444+ }
12051445
1206- const int size2 = region->end[0] - region->beg[0];
1207-
1208- uobject_put(gRootObject, "MATCH", STRING_NEW_GC3(target + region->beg[0], size2, FALSE));
1209- uobject_put(gRootObject, "0", STRING_NEW_GC3(target + region->beg[0], size2, FALSE));
1446+ /// get search count ///
1447+ int match_count;
1448+ char* count;
1449+ if(count = sRunInfo_option_with_argument(runinfo, "-count")) {
1450+ match_count = atoi(count);
1451+ if(match_count <= 0) { match_count = 1; }
1452+ }
1453+ else {
1454+ match_count = 1;
1455+ }
12101456
1211- const int n = strlen(target)-region->end[0];
1212- if(n > 0) {
1213- uobject_put(gRootObject, "POSTMATCH", STRING_NEW_GC3(target + region->end[0], n, FALSE));
1457+ char* start_byte = str_kanjipos2pointer(code, target, start);
1458+ char* p = start_byte;
1459+ char* result = NULL;
1460+ while(p < start_byte + strlen(start_byte)) {
1461+ if(gXyzshSigInt) {
1462+ gXyzshSigInt = FALSE;
1463+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1464+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1465+ return FALSE;
12141466 }
12151467
1216- int i;
1217- for (i=1; i<region->num_regs; i++) {
1218- const int size = region->end[i] - region->beg[i];
1468+ OnigRegion* region = onig_region_new();
1469+ OnigErrorInfo err_info;
12191470
1220- char name[16];
1221- snprintf(name, 16, "%d", i);
1471+ const int point = p - target;
1472+ int r2 = onig_search(reg, target
1473+ , target + strlen(target)
1474+ , p
1475+ , p + strlen(p)
1476+ , region, ONIG_OPTION_NONE);
12221477
1223- uobject_put(gRootObject, name, STRING_NEW_GC3(target + region->beg[i], size, FALSE));
1478+ if(r2 == ONIG_MISMATCH) {
1479+ onig_region_free(region, 1);
1480+ break;
12241481 }
12251482
1226- if(region->num_regs > 0) {
1227- const int n = region->num_regs -1;
1483+ if(r2 >= 0) {
1484+ result = target + region->beg[0];
12281485
1229- const int size = region->end[n] - region->beg[n];
1486+ match_count--;
1487+ if(match_count == 0) {
1488+ break;
1489+ }
1490+ p = target + region->beg[0] + 1;
12301491
1231- uobject_put(gRootObject, "LAST_MATCH", STRING_NEW_GC3(target + region->beg[n], size, FALSE));
1492+ onig_region_free(region, 1);
1493+ }
1494+ else {
1495+ onig_region_free(region, 1);
1496+ break;
12321497 }
1498+ }
12331499
1234- char buf[128];
1235- snprintf(buf, 128, "%d", region->num_regs);
1236- uobject_put(gRootObject, "MATCH_NUMBER", STRING_NEW_GC(buf, FALSE));
1500+ char msg[64];
1501+ int size;
1502+ if(result == NULL || match_count !=0) {
1503+ size = snprintf(msg, 64, "-1");
1504+ runinfo->mRCode = RCODE_NFUN_FALSE;
1505+ }
1506+ else {
1507+ int c = str_pointer2kanjipos(code, target, result);
1508+ size = snprintf(msg, 64, "%d", c);
12371509
1238- fd_clear(nextin2);
1239- fd_clear(nextout2);
1510+ if(SFD(nextin).mBufLen == 0) {
1511+ runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
1512+ }
1513+ else {
1514+ runinfo->mRCode = 0;
1515+ }
1516+ }
12401517
1241- if(!fd_write(nextin2, target + region->beg[0], region->end[0]-region->beg[0])) {
1242- err_msg("interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1518+ if(!sRunInfo_option(runinfo, "-quiet")) {
1519+ if(!fd_write(nextout, msg, size)) {
1520+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
12431521 runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1244- onig_region_free(region, 1);
1245- onig_free(reg);
12461522 return FALSE;
12471523 }
1248-
1249- int rcode = 0;
1250- if(!run(block, nextin2, nextout2, &rcode, runinfo->mCurrentObject, runinfo->mRunningObject)) {
1251- runinfo->mRCode = rcode;
1252- onig_region_free(region, 1);
1253- onig_free(reg);
1524+ if(!fd_write(nextout, "\n", 1)) {
1525+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1526+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
12541527 return FALSE;
12551528 }
1256-
1257- string_put(sub_str, SFD(nextout2).mBuf);
12581529 }
1259- else {
1260- char* p2 = destination;
1261-
1262- while(*p2) {
1263- if(*p2 == '\\') {
1264- if(*(p2+1) == '\\') {
1265- p2+=2;
1266- string_push_back2(sub_str , '\\');
1267- }
1268- else if(*(p2+1) >= '0' && *(p2+1) <= '9') {
1269- int n = *(p2+1) - '0';
1270-
1271- if(n < region->num_regs) {
1272- p2+=2;
1273-
1274- const int size = region->end[n] - region->beg[n];
1275-
1276- string_push_back3(sub_str, target + region->beg[n], size);
1277- }
1278- else {
1279- string_push_back2(sub_str, *p2++);
1280- string_push_back2(sub_str , *p2++);
1281- }
1282- }
1283- else if(*(p2+1) == '&') {
1284- p2 += 2;
1285-
1286- const int size = region->end[0] - region->beg[0];
1287-
1288- string_push_back3(sub_str, target + region->beg[0], size);
1289- }
1290- else if(*(p2+1) == '`') {
1291- p2+=2;
1530+ }
1531+ else {
1532+ err_msg("invalid regex", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1533+ return FALSE;
1534+ }
12921535
1293- string_push_back3(sub_str, target, region->beg[0]);
1294- }
1295- else if(*(p2+1) == '\'') {
1296- p2+=2;
1536+ onig_free(reg);
1537+ }
1538+ }
1539+ }
1540+ else {
1541+ if(runinfo->mFilter) {
1542+ if(runinfo->mArgsNumRuntime == 2) {
1543+ char* target = SFD(nextin).mBuf;
12971544
1298- string_push_back(sub_str, target + region->end[0]);
1299- }
1300- else if(*(p2+1) == '+') {
1301- p2+=2;
1545+ char* word = runinfo->mArgsRuntime[1];
13021546
1303- if(region->num_regs > 0) {
1304- const int n = region->num_regs - 1;
1547+ /// get starting point ///
1548+ int start;
1549+ char* number;
1550+ if(number = sRunInfo_option_with_argument(runinfo, "-number")) {
1551+ start = atoi(number);
13051552
1306- const int size = region->end[n] - region->beg[n];
1553+ int len = str_kanjilen(code, target);
1554+ if(len < 0) {
1555+ err_msg("invalid target string", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1556+ return FALSE;
1557+ }
13071558
1308- string_push_back3(sub_str, target + region->beg[n], size);
1309- }
1310- }
1311- else {
1312- string_push_back2(sub_str, *p2++);
1313- }
1314- }
1315- else {
1316- string_push_back2(sub_str, *p2++);
1317- }
1318- }
1559+ if(start < 0) {
1560+ start += len;
1561+ if(start < 0) start = 0;
1562+ }
1563+ if(start >= len) {
1564+ start = len -1;
1565+ if(start < 0) start = 0;
13191566 }
1567+ }
1568+ else {
1569+ start = 0;
1570+ }
13201571
1321- if(!quiet) {
1322- if(!fd_write(nextout, p, region->beg[0]-point)) {
1572+ /// get search count ///
1573+ int match_count;
1574+ char* count;
1575+ if(count = sRunInfo_option_with_argument(runinfo, "-count")) {
1576+ match_count = atoi(count);
1577+ if(match_count <= 0) { match_count = 1; }
1578+ }
1579+ else {
1580+ match_count = 1;
1581+ }
1582+
1583+ char* start_byte = str_kanjipos2pointer(code, target, start);
1584+ char* p = start_byte;
1585+ char* result = NULL;
1586+ if(sRunInfo_option(runinfo, "-ignore-case")) {
1587+ while(p < start_byte + strlen(start_byte)) {
1588+ if(gXyzshSigInt) {
1589+ gXyzshSigInt = FALSE;
13231590 err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
13241591 runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1325- onig_region_free(region, 1);
1326- onig_free(reg);
13271592 return FALSE;
13281593 }
1329- if(!fd_write(nextout, string_c_str(sub_str), string_length(sub_str))) {
1594+
1595+ result = strcasestr(p, word);
1596+ if(result) {
1597+ match_count--;
1598+ if(match_count == 0) {
1599+ break;
1600+ }
1601+ p = result+strlen(word);
1602+ }
1603+ else {
1604+ break;
1605+ }
1606+ }
1607+ }
1608+ else {
1609+ while(p < start_byte + strlen(start_byte)) {
1610+ if(gXyzshSigInt) {
1611+ gXyzshSigInt = FALSE;
13301612 err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
13311613 runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1332- onig_region_free(region, 1);
1333- onig_free(reg);
13341614 return FALSE;
13351615 }
1336- }
1337-
1338- sub_count++;
13391616
1340- if(region->beg[0] == region->end[0]) {
1341- char buf[2];
1342- buf[0] = target[region->beg[0]];
1343- buf[1] = 0;
1344-
1345- if(!quiet) {
1346- if(!fd_write(nextout, buf, 1)) {
1347- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1348- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1349- onig_region_free(region, 1);
1350- onig_free(reg);
1351- return FALSE;
1617+ result = strstr(p, word);
1618+ if(result) {
1619+ match_count--;
1620+ if(match_count == 0) {
1621+ break;
13521622 }
1623+ p = result+strlen(word);
13531624 }
1354-
1355- p = target + region->end[0] + 1;
1356-
1357- if(p > target + strlen(target)) {
1625+ else {
13581626 break;
13591627 }
13601628 }
1629+ }
1630+
1631+ char msg[64];
1632+ int size;
1633+ if(result == NULL || match_count !=0) {
1634+ size = snprintf(msg, 64, "-1");
1635+ runinfo->mRCode = RCODE_NFUN_FALSE;
1636+ }
1637+ else {
1638+ int c = str_pointer2kanjipos(code, target, result);
1639+ size = snprintf(msg, 64, "%d", c);
1640+
1641+ if(SFD(nextin).mBufLen == 0) {
1642+ runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
1643+ }
13611644 else {
1362- p= target + region->end[0];
1645+ runinfo->mRCode = 0;
13631646 }
1647+ }
13641648
1365- onig_region_free(region, 1);
1366-
1367- if(!global && !quiet) {
1368- if(!fd_write(nextout, p, strlen(p))) {
1369- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1370- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1371- onig_free(reg);
1372- return FALSE;
1373- }
1374- break;
1649+ if(!sRunInfo_option(runinfo, "-quiet")) {
1650+ if(!fd_write(nextout, msg, size)) {
1651+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1652+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1653+ return FALSE;
1654+ }
1655+ if(!fd_write(nextout, "\n", 1)) {
1656+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1657+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1658+ return FALSE;
13751659 }
13761660 }
13771661 }
13781662 }
1663+ }
13791664
1380- onig_free(reg);
1665+ return TRUE;
1666+}
13811667
1382- char buf[128];
1383- snprintf(buf, 128, "%d", sub_count);
1384- uobject_put(gRootObject, "SUB_COUNT", STRING_NEW_GC(buf, FALSE));
1668+static char* strstr_back(char* p, char* start, char* word, char* sname, int sline, char* command)
1669+{
1670+ int n = strlen(word);
13851671
1386- if(sub_count > 0) {
1387- if(SFD(nextin).mBufLen == 0) {
1388- runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
1672+ while(p >= start) {
1673+ BOOL flg = TRUE;
1674+ int i;
1675+ for(i=-1; i>=-n; i--) {
1676+ if(p[i] != word[n+i]) {
1677+ flg = FALSE;
1678+ break;
1679+ }
1680+
1681+ if(gXyzshSigInt) {
1682+ err_msg("interrupt", sname, sline, command);
1683+ gXyzshSigInt = FALSE;
1684+ return NULL;
1685+ }
1686+ }
1687+
1688+ if(flg) {
1689+ return p -n;
1690+ }
1691+ else {
1692+ p--;
1693+ }
1694+ }
1695+
1696+ return NULL;
1697+}
1698+
1699+static char* strcasestr_back(char* p, char* start, char* word, char* sname, int sline, char* command)
1700+{
1701+ int n = strlen(word);
1702+
1703+ while(p >= start) {
1704+ BOOL flg = TRUE;
1705+ int i;
1706+ for(i=-1; i>=-n; i--) {
1707+ if(isascii(p[i]) && isascii(word[n+i])) {
1708+ if(tolower(p[i]) != tolower(word[n+i])) {
1709+ flg = FALSE;
1710+ break;
1711+ }
13891712 }
13901713 else {
1391- runinfo->mRCode = 0;
1714+ if(p[i] != word[n+i]) {
1715+ flg = FALSE;
1716+ break;
1717+ }
1718+ }
1719+
1720+ if(gXyzshSigInt) {
1721+ gXyzshSigInt = FALSE;
1722+ err_msg("interrupt", sname, sline, command);
1723+ return NULL;
13921724 }
13931725 }
1726+
1727+ if(flg) {
1728+ return p -n;
1729+ }
13941730 else {
1395- runinfo->mRCode = RCODE_NFUN_FALSE;
1731+ p--;
13961732 }
13971733 }
13981734
1399- return TRUE;
1735+ return NULL;
14001736 }
14011737
1402-BOOL cmd_scan(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
1738+BOOL cmd_rindex(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
14031739 {
1404- char* field = "\n";
1405- if(sRunInfo_option(runinfo, "-Lw")) {
1406- field = "\r\n";
1740+ enum eKanjiCode code = gKanjiCode;
1741+ if(sRunInfo_option(runinfo, "-byte")) {
1742+ code = kByte;
14071743 }
1408- else if(sRunInfo_option(runinfo, "-Lm")) {
1409- field = "\r";
1744+ else if(sRunInfo_option(runinfo, "-utf8")) {
1745+ code = kUtf8;
14101746 }
1411- else if(sRunInfo_option(runinfo, "-Lu")) {
1412- field = "\n";
1747+ else if(sRunInfo_option(runinfo, "-sjis")) {
1748+ code = kSjis;
14131749 }
1414- else if(sRunInfo_option(runinfo, "-La")) {
1415- field = "\a";
1750+ else if(sRunInfo_option(runinfo, "-eucjp")) {
1751+ code = kEucjp;
14161752 }
1417-
1418- if(runinfo->mFilter && runinfo->mArgsNumRuntime == 2) {
1419- sObject* block;
1420- sObject* nextin2;
1421-
1422- if(runinfo->mBlocksNum >= 1) {
1423- block = runinfo->mBlocks[0];
1424- nextin2 = FD_NEW_STACK();
1425- }
1426- else {
1427- block = NULL;
1428- }
1429-
1430- int match_count = 0;
1431- char* regex = runinfo->mArgsRuntime[1];
1432-
1433- regex_t* reg;
1434- int r = get_onig_regex(&reg, runinfo, regex);
14351753
1436- if(r == ONIG_NORMAL) {
1437- char* target = SFD(nextin).mBuf;
1438- char* p = SFD(nextin).mBuf;
1439- char* end = SFD(nextin).mBuf + strlen(SFD(nextin).mBuf);
1440- while(p < end) {
1441- OnigRegion* region = onig_region_new();
1442- int r2 = onig_search(reg, target
1443- , target + strlen(target)
1444- , p
1445- , p + strlen(p)
1446- , region, ONIG_OPTION_NONE);
1754+ if(sRunInfo_option(runinfo, "-regex")) {
1755+ if(runinfo->mFilter) {
1756+ if(runinfo->mArgsNumRuntime == 2) {
1757+ char* target = SFD(nextin).mBuf;
1758+ char* regex = runinfo->mArgsRuntime[1];
14471759
1448- if(r2 >= 0) {
1449- match_count++;
1760+ regex_t* reg;
1761+ int r = get_onig_regex(&reg, runinfo, regex);
14501762
1451- if(block) {
1452- fd_clear(nextin2);
1763+ if(r == ONIG_NORMAL) {
1764+ /// get starting point ///
1765+ int len = str_kanjilen(code, target);
1766+ if(len < 0) {
1767+ err_msg("invalid target string", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1768+ return FALSE;
1769+ }
14531770
1454- /// no group ///
1455- if(region->num_regs == 1) {
1456- const int n = region->end[0] - region->beg[0];
1771+ int start;
1772+ char* number;
1773+ if(number = sRunInfo_option_with_argument(runinfo, "-number")) {
1774+ start = atoi(number);
14571775
1458- if(!fd_write(nextin2, target + region->beg[0], n)) {
1459- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1460- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1461- onig_free(reg);
1462- onig_region_free(region, 1);
1463- return FALSE;
1464- }
1465- if(!fd_write(nextin2, field, strlen(field))) {
1466- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1467- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1468- onig_free(reg);
1469- onig_region_free(region, 1);
1470- return FALSE;
1471- }
1776+ if(start < 0) {
1777+ start += len;
1778+ if(start < 0) start = 0;
14721779 }
1473- /// group ///
1474- else {
1475- int i;
1476- for (i=1; i<region->num_regs; i++) {
1477- const int size = region->end[i] - region->beg[i];
1478-
1479- if(!fd_write(nextin2, target + region->beg[i], size)) {
1480- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1481- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1482- onig_free(reg);
1483- onig_region_free(region, 1);
1484- return FALSE;
1485- }
1780+ if(start >= len) {
1781+ start = len -1 ;
1782+ if(start < 0) start = 0;
1783+ }
1784+ }
1785+ else {
1786+ start = len -1;
1787+ if(start < 0) start = 0;
1788+ }
14861789
1487- if(i==region->num_regs-1) {
1488- if(!fd_write(nextin2, field, strlen(field))) {
1489- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1490- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1491- onig_free(reg);
1492- onig_region_free(region, 1);
1493- return FALSE;
1494- }
1495- }
1496- else {
1497- if(!fd_write(nextin2, "\t", 1)) {
1498- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1499- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1500- onig_free(reg);
1501- onig_region_free(region, 1);
1502- return FALSE;
1503- }
1504- }
1505- }
1790+ /// get search count ///
1791+ int match_count;
1792+ char* count;
1793+ if(count = sRunInfo_option_with_argument(runinfo, "-count")) {
1794+ match_count = atoi(count);
1795+ if(match_count <= 0) { match_count = 1; }
1796+ }
1797+ else {
1798+ match_count = 1;
1799+ }
1800+
1801+ char* start_byte = str_kanjipos2pointer(code, target, start);
1802+ char* p = start_byte;
1803+ char* result = NULL;
1804+ while(p>=target) {
1805+ if(gXyzshSigInt) {
1806+ gXyzshSigInt = FALSE;
1807+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1808+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1809+ return FALSE;
15061810 }
15071811
1508- clear_matching_info_variable();
1812+ OnigRegion* region = onig_region_new();
1813+ OnigErrorInfo err_info;
15091814
1510- const int size = region->beg[0] - (p - target);
1511- if(size > 0) {
1512- uobject_put(gRootObject, "PREMATCH", STRING_NEW_GC3(p, size, FALSE));
1815+ int r2 = onig_search(reg, target
1816+ , target + strlen(target)
1817+ , p
1818+ , target
1819+ , region, ONIG_OPTION_NONE);
1820+
1821+ if(r2 == ONIG_MISMATCH) {
1822+ onig_region_free(region, 1);
1823+ break;
15131824 }
15141825
1515- const int size2 = region->end[0] - region->beg[0];
1826+ if(r2 >= 0) {
1827+ result = target + region->beg[0];
15161828
1517- uobject_put(gRootObject, "MATCH", STRING_NEW_GC3(target + region->beg[0], size2, FALSE));
1518- uobject_put(gRootObject, "0", STRING_NEW_GC3(target + region->beg[0], size2, FALSE));
1829+ match_count--;
1830+ if(match_count == 0) {
1831+ break;
1832+ }
1833+ p = target + region->beg[0] - 1;
15191834
1520- const int n = strlen(target)-region->end[0];
1521- if(n > 0) {
1522- uobject_put(gRootObject, "POSTMATCH", STRING_NEW_GC3(target + region->end[0], n, FALSE));
1835+ onig_region_free(region, 1);
1836+ }
1837+ else {
1838+ onig_region_free(region, 1);
1839+ break;
15231840 }
1841+ }
15241842
1525- int i;
1526- for (i=1; i<region->num_regs; i++) {
1527- const int size = region->end[i] - region->beg[i];
1843+ char msg[64];
1844+ int size;
1845+ if(result == NULL || match_count !=0) {
1846+ size = snprintf(msg, 64, "-1");
1847+ runinfo->mRCode = RCODE_NFUN_FALSE;
1848+ }
1849+ else {
1850+ int c = str_pointer2kanjipos(code, target, result);
1851+ size = snprintf(msg, 64, "%d", c);
15281852
1529- char name[16];
1530- snprintf(name, 16, "%d", i);
1853+ if(SFD(nextin).mBufLen == 0) {
1854+ runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
1855+ }
1856+ else {
1857+ runinfo->mRCode = 0;
1858+ }
1859+ }
15311860
1532- uobject_put(gRootObject, name, STRING_NEW_GC3(target + region->beg[i], size, FALSE));
1861+ if(!sRunInfo_option(runinfo, "-quiet")) {
1862+ if(!fd_write(nextout, msg, size)) {
1863+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1864+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1865+ return FALSE;
1866+ }
1867+ if(!fd_write(nextout, "\n", 1)) {
1868+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1869+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1870+ return FALSE;
15331871 }
1872+ }
1873+ }
1874+ else {
1875+ err_msg("invalid regex", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1876+ return FALSE;
1877+ }
1878+ }
1879+ }
1880+ }
1881+ else {
1882+ if(runinfo->mFilter) {
1883+ if(runinfo->mArgsNumRuntime == 2) {
1884+ char* target = SFD(nextin).mBuf;
1885+ char* word = runinfo->mArgsRuntime[1];
15341886
1535- if(region->num_regs > 0) {
1536- const int n = region->num_regs -1;
1887+ /// get starting point ///
1888+ int len = str_kanjilen(code, target);
1889+ if(len < 0) {
1890+ err_msg("invalid target string", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1891+ return FALSE;
1892+ }
15371893
1538- const int size = region->end[n] - region->beg[n];
1894+ int start;
1895+ char* number;
1896+ if(number = sRunInfo_option_with_argument(runinfo, "-number")) {
1897+ start = atoi(number);
15391898
1540- uobject_put(gRootObject, "LAST_MATCH", STRING_NEW_GC3(target + region->beg[n], size, FALSE));
1541- }
1899+ if(start < 0) {
1900+ start += len;
1901+ if(start < 0) start = 0;
1902+ }
1903+ if(start >= len) {
1904+ start = len -1 ;
1905+ if(start < 0) start = 0;
1906+ }
1907+ }
1908+ else {
1909+ start = len -1;
1910+ if(start < 0) start = 0;
1911+ }
15421912
1543- char buf[128];
1544- snprintf(buf, 128, "%d", region->num_regs);
1545- uobject_put(gRootObject, "MATCH_NUMBER", STRING_NEW_GC(buf, FALSE));
1913+ /// get search count ///
1914+ int match_count;
1915+ char* count;
1916+ if(count = sRunInfo_option_with_argument(runinfo, "-count")) {
1917+ match_count = atoi(count);
1918+ if(match_count <= 0) { match_count = 1; }
1919+ }
1920+ else {
1921+ match_count = 1;
1922+ }
15461923
1547- int rcode = 0;
1548- if(!run(block, nextin2, nextout, &rcode, runinfo->mCurrentObject, runinfo->mRunningObject)) {
1549- runinfo->mRCode = rcode;
1550- onig_region_free(region, 1);
1551- onig_free(reg);
1924+
1925+ char* start_byte = str_kanjipos2pointer(code, target, start+1);
1926+ char* p = start_byte;
1927+ char* result = NULL;
1928+ if(sRunInfo_option(runinfo, "-ignore-case")) {
1929+ while(p>=target) {
1930+ result = strcasestr_back(p, target, word, runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1931+
1932+ if(gXyzshSigInt) {
1933+ gXyzshSigInt = FALSE;
1934+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1935+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
15521936 return FALSE;
15531937 }
1554- }
1555- else {
1556- /// no group ///
1557- if(region->num_regs == 1) {
1558- const int n = region->end[0] - region->beg[0];
15591938
1560- if(!fd_write(nextout, target + region->beg[0], n)) {
1561- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1562- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1563- onig_free(reg);
1564- onig_region_free(region, 1);
1565- return FALSE;
1566- }
1567- if(!fd_write(nextout, field, strlen(field))) {
1568- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1569- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1570- onig_free(reg);
1571- onig_region_free(region, 1);
1572- return FALSE;
1939+ if(result != NULL) {
1940+ match_count--;
1941+ if(match_count == 0) {
1942+ break;
15731943 }
1944+ p = result - 1;
15741945 }
1575- /// group ///
15761946 else {
1577- int i;
1578- for (i=1; i<region->num_regs; i++) {
1579- const int size = region->end[i] - region->beg[i];
1580-
1581- if(!fd_write(nextout, target + region->beg[i], size)) {
1582- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1583- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1584- onig_free(reg);
1585- onig_region_free(region, 1);
1586- return FALSE;
1587- }
1947+ break;
1948+ }
1949+ }
1950+ }
1951+ else {
1952+ while(p>=target) {
1953+ result = strstr_back(p, target, word, runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
15881954
1589- if(i==region->num_regs-1) {
1590- if(!fd_write(nextout, field, strlen(field))) {
1591- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1592- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1593- onig_free(reg);
1594- onig_region_free(region, 1);
1595- return FALSE;
1596- }
1597- }
1598- else {
1599- if(!fd_write(nextout, "\t", 1)) {
1600- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1601- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1602- onig_free(reg);
1603- onig_region_free(region, 1);
1604- return FALSE;
1605- }
1606- }
1955+ if(gXyzshSigInt) {
1956+ gXyzshSigInt = FALSE;
1957+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1958+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1959+ return FALSE;
1960+ }
1961+
1962+ if(result != NULL) {
1963+ match_count--;
1964+ if(match_count == 0) {
1965+ break;
16071966 }
1967+ p = result - 1;
1968+ }
1969+ else {
1970+ break;
16081971 }
16091972 }
1973+ }
16101974
1611- p = SFD(nextin).mBuf + region->end[0];
1975+ char msg[64];
1976+ int size;
1977+ if(result == NULL || match_count !=0) {
1978+ size = snprintf(msg, 64, "-1");
1979+ runinfo->mRCode = RCODE_NFUN_FALSE;
16121980 }
16131981 else {
1614- p++;
1982+ int c = str_pointer2kanjipos(code, target, result);
1983+ size = snprintf(msg, 64, "%d", c);
1984+
1985+ if(SFD(nextin).mBufLen == 0) {
1986+ runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
1987+ }
1988+ else {
1989+ runinfo->mRCode = 0;
1990+ }
16151991 }
16161992
1617- onig_region_free(region, 1);
1993+ /// Ω–Œœ ///
1994+ if(!sRunInfo_option(runinfo, "-quiet")) {
1995+ if(!fd_write(nextout, msg, size)) {
1996+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1997+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1998+ return FALSE;
1999+ }
2000+ if(!fd_write(nextout, "\n", 1)) {
2001+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2002+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2003+ return FALSE;
2004+ }
2005+ }
16182006 }
2007+ }
2008+ }
16192009
1620- onig_free(reg);
2010+ return TRUE;
2011+}
2012+
2013+BOOL cmd_sub(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
2014+{
2015+ BOOL quiet = sRunInfo_option(runinfo, "-quiet");
2016+ BOOL ignore = sRunInfo_option(runinfo, "-ignore-case");
2017+
2018+ if(sRunInfo_option(runinfo, "-no-regex")) {
2019+ if(runinfo->mFilter && runinfo->mArgsNumRuntime == 3) {
2020+ BOOL global = sRunInfo_option(runinfo, "-global");
2021+
2022+ char* word = runinfo->mArgsRuntime[1];
2023+ char* destination = runinfo->mArgsRuntime[2];
2024+ const int destination_len = strlen(destination);
2025+
2026+ int sub_count = 0;
2027+
2028+ char* target = SFD(nextin).mBuf;
2029+ char* p = target;
2030+
2031+ while(1) {
2032+ char* result = strstr(p, word);
2033+ if(ignore) {
2034+ result = strcasestr(p, word);
2035+ }
2036+ else {
2037+ result = strstr(p, word);
2038+ }
2039+
2040+ if(result == NULL) {
2041+ if(!quiet) {
2042+ if(!fd_write(nextout, p, strlen(p))) {
2043+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2044+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2045+ return FALSE;
2046+ }
2047+ }
2048+ break;
2049+ }
2050+
2051+ if(!quiet) {
2052+ if(!fd_write(nextout, p, result - p)) {
2053+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2054+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2055+ return FALSE;
2056+ }
2057+ if(!fd_write(nextout, destination, destination_len)) {
2058+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2059+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2060+ return FALSE;
2061+ }
2062+ }
2063+
2064+ p = result + strlen(word);
2065+ sub_count++;
2066+
2067+ if(!global) {
2068+ if(!quiet) {
2069+ if(!fd_write(nextout, p, strlen(p))) {
2070+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2071+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2072+ return FALSE;
2073+ }
2074+ }
2075+ break;
2076+ }
2077+ }
16212078
16222079 char buf[128];
1623- snprintf(buf, 128, "%d", match_count);
1624- uobject_put(gRootObject, "MATCH_COUNT", STRING_NEW_GC(buf, FALSE));
2080+ snprintf(buf, 128, "%d", sub_count);
2081+ uobject_put(gRootObject, "SUB_COUNT", STRING_NEW_GC(buf, FALSE));
16252082
1626- if(match_count > 0) {
2083+ if(sub_count > 0) {
16272084 if(SFD(nextin).mBufLen == 0) {
16282085 runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
16292086 }
@@ -1636,181 +2093,199 @@ BOOL cmd_scan(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
16362093 }
16372094 }
16382095 }
2096+ else {
2097+ if(runinfo->mFilter && (runinfo->mArgsNumRuntime == 3 || runinfo->mArgsNumRuntime == 2 && runinfo->mBlocksNum >= 1)) {
2098+ sObject* block;
2099+ sObject* nextin2;
2100+ sObject* nextout2;
16392101
1640- return TRUE;
1641-}
2102+ if(runinfo->mBlocksNum >= 1) {
2103+ block = runinfo->mBlocks[0];
2104+ nextin2 = FD_NEW_STACK();
2105+ nextout2 = FD_NEW_STACK();
2106+ }
2107+ else {
2108+ block = NULL;
2109+ }
16422110
1643-BOOL cmd_split(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
1644-{
1645- char* field = "\n";
1646- eLineField lf = gLineField;
1647- if(sRunInfo_option(runinfo, "-Lw")) {
1648- lf = kCRLF;
1649- field = "\r\n";
1650- }
1651- else if(sRunInfo_option(runinfo, "-Lm")) {
1652- lf = kCR;
1653- field = "\r";
1654- }
1655- else if(sRunInfo_option(runinfo, "-Lu")) {
1656- lf = kLF;
1657- field = "\n";
1658- }
1659- else if(sRunInfo_option(runinfo, "-La")) {
1660- lf = kBel;
1661- field = "\a";
1662- }
2111+ BOOL global = sRunInfo_option(runinfo, "-global");
16632112
1664- enum eKanjiCode code = gKanjiCode;
1665- if(sRunInfo_option(runinfo, "-byte")) {
1666- code = kByte;
1667- }
1668- else if(sRunInfo_option(runinfo, "-utf8")) {
1669- code = kUtf8;
1670- }
1671- else if(sRunInfo_option(runinfo, "-sjis")) {
1672- code = kSjis;
1673- }
1674- else if(sRunInfo_option(runinfo, "-eucjp")) {
1675- code = kEucjp;
1676- }
2113+ char* regex = runinfo->mArgsRuntime[1];
2114+ char* destination = runinfo->mArgsRuntime[2];
16772115
1678- if(runinfo->mFilter) {
1679- char* regex;
2116+ int sub_count = 0;
16802117
1681- if(runinfo->mArgsNumRuntime == 1) {
1682- regex = "\\s+";
1683- }
1684- else if(runinfo->mArgsNumRuntime >= 2) {
1685- regex = runinfo->mArgsRuntime[1];
1686- }
2118+ regex_t* reg;
2119+ int r = get_onig_regex(&reg, runinfo, regex);
16872120
1688- regex_t* reg;
1689- int r = get_onig_regex(&reg, runinfo, regex);
2121+ if(r == ONIG_NORMAL) {
2122+ char* p = SFD(nextin).mBuf;
16902123
1691- if(r == ONIG_NORMAL) {
1692- char* target;
1693- char* p = target = SFD(nextin).mBuf;
2124+ sObject* sub_str = STRING_NEW_STACK("");
16942125
1695- int split_count = 0;
2126+ while(1) {
2127+ OnigRegion* region = onig_region_new();
2128+ OnigErrorInfo err_info;
16962129
1697- while(1) {
1698- OnigRegion* region = onig_region_new();
2130+ char* target = SFD(nextin).mBuf;
16992131
1700- int r2 = onig_search(reg, target
1701- , target + strlen(target)
1702- , p, p + strlen(p)
1703- , region, ONIG_OPTION_NONE);
1704-
1705- if(r2 == ONIG_MISMATCH) {
1706- onig_region_free(region, 1);
2132+ const int point = p - target;
2133+ int r2 = onig_search(reg, target
2134+ , target + strlen(target)
2135+ , p
2136+ , p + strlen(p)
2137+ , region, ONIG_OPTION_NONE);
17072138
1708- if(*p) {
1709- if(!fd_write(nextout, p, strlen(p))) {
1710- err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1711- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1712- onig_free(reg);
1713- return FALSE;
1714- }
1715- }
2139+ if(r2 == ONIG_MISMATCH) {
2140+ onig_region_free(region, 1);
17162141
1717- if(!fd_write(nextout, field, strlen(field))) {
1718- err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1719- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1720- onig_free(reg);
1721- return FALSE;
2142+ if(!quiet) {
2143+ if(!fd_write(nextout, p, strlen(p))) {
2144+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2145+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2146+ onig_free(reg);
2147+ return FALSE;
2148+ }
2149+ }
2150+ break;
17222151 }
1723- break;
1724- }
1725- else {
1726- split_count++;
2152+ else {
2153+ /// make distination ///
2154+ string_put(sub_str, "");
17272155
1728- if(region->beg[0] == region->end[0]) {
1729- if(target + region->beg[0] == p) {
1730- char* end_byte = str_kanjipos2pointer(code, p, 1);
1731- int size = end_byte - p;
2156+ if(block) {
2157+ clear_matching_info_variable();
17322158
2159+ const int size = region->beg[0] - (p - target);
17332160 if(size > 0) {
1734- if(!fd_write(nextout, p, size)) {
1735- err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1736- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1737- onig_region_free(region, 1);
1738- onig_free(reg);
1739- return FALSE;
1740- }
2161+ uobject_put(gRootObject, "PREMATCH", STRING_NEW_GC3(p, size, FALSE));
2162+ }
17412163
1742- if(!fd_write(nextout, field, strlen(field))) {
1743- err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1744- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1745- onig_region_free(region, 1);
1746- onig_free(reg);
1747- return FALSE;
1748- }
2164+ const int size2 = region->end[0] - region->beg[0];
17492165
1750- p += size;
1751- }
1752- else {
1753- onig_region_free(region, 1);
2166+ uobject_put(gRootObject, "MATCH", STRING_NEW_GC3(target + region->beg[0], size2, FALSE));
2167+ uobject_put(gRootObject, "0", STRING_NEW_GC3(target + region->beg[0], size2, FALSE));
17542168
1755- break;
2169+ const int n = strlen(target)-region->end[0];
2170+ if(n > 0) {
2171+ uobject_put(gRootObject, "POSTMATCH", STRING_NEW_GC3(target + region->end[0], n, FALSE));
17562172 }
1757- }
1758- else {
1759- int size = region->beg[0] - (p-target);
17602173
1761- if(size > 0) {
1762- if(!fd_write(nextout, p, size)) {
1763- err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1764- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1765- onig_region_free(region, 1);
1766- onig_free(reg);
1767- return FALSE;
1768- }
2174+ int i;
2175+ for (i=1; i<region->num_regs; i++) {
2176+ const int size = region->end[i] - region->beg[i];
17692177
1770- if(!fd_write(nextout, field, strlen(field))) {
1771- err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1772- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1773- onig_region_free(region, 1);
1774- onig_free(reg);
1775- return FALSE;
1776- }
2178+ char name[16];
2179+ snprintf(name, 16, "%d", i);
2180+
2181+ uobject_put(gRootObject, name, STRING_NEW_GC3(target + region->beg[i], size, FALSE));
17772182 }
1778- else if(size == 0) {
1779- if(!fd_write(nextout, field, strlen(field))) {
1780- err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1781- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1782- onig_region_free(region, 1);
1783- onig_free(reg);
1784- return FALSE;
1785- }
2183+
2184+ if(region->num_regs > 0) {
2185+ const int n = region->num_regs -1;
2186+
2187+ const int size = region->end[n] - region->beg[n];
2188+
2189+ uobject_put(gRootObject, "LAST_MATCH", STRING_NEW_GC3(target + region->beg[n], size, FALSE));
17862190 }
17872191
1788- p = target + region->end[0];
1789- }
1790- }
1791- else {
1792- int size = region->beg[0] - (p-target);
2192+ char buf[128];
2193+ snprintf(buf, 128, "%d", region->num_regs);
2194+ uobject_put(gRootObject, "MATCH_NUMBER", STRING_NEW_GC(buf, FALSE));
17932195
1794- if(size > 0) {
1795- if(!fd_write(nextout, p, size)) {
1796- err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2196+ fd_clear(nextin2);
2197+ fd_clear(nextout2);
2198+
2199+ if(!fd_write(nextin2, target + region->beg[0], region->end[0]-region->beg[0])) {
2200+ err_msg("interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
17972201 runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
17982202 onig_region_free(region, 1);
17992203 onig_free(reg);
18002204 return FALSE;
18012205 }
18022206
1803- if(!fd_write(nextout, field, strlen(field))) {
1804- err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2207+ int rcode = 0;
2208+ if(!run(block, nextin2, nextout2, &rcode, runinfo->mCurrentObject, runinfo->mRunningObject)) {
2209+ runinfo->mRCode = rcode;
2210+ onig_region_free(region, 1);
2211+ onig_free(reg);
2212+ return FALSE;
2213+ }
2214+
2215+ string_put(sub_str, SFD(nextout2).mBuf);
2216+ }
2217+ else {
2218+ char* p2 = destination;
2219+
2220+ while(*p2) {
2221+ if(*p2 == '\\') {
2222+ if(*(p2+1) == '\\') {
2223+ p2+=2;
2224+ string_push_back2(sub_str , '\\');
2225+ }
2226+ else if(*(p2+1) >= '0' && *(p2+1) <= '9') {
2227+ int n = *(p2+1) - '0';
2228+
2229+ if(n < region->num_regs) {
2230+ p2+=2;
2231+
2232+ const int size = region->end[n] - region->beg[n];
2233+
2234+ string_push_back3(sub_str, target + region->beg[n], size);
2235+ }
2236+ else {
2237+ string_push_back2(sub_str, *p2++);
2238+ string_push_back2(sub_str , *p2++);
2239+ }
2240+ }
2241+ else if(*(p2+1) == '&') {
2242+ p2 += 2;
2243+
2244+ const int size = region->end[0] - region->beg[0];
2245+
2246+ string_push_back3(sub_str, target + region->beg[0], size);
2247+ }
2248+ else if(*(p2+1) == '`') {
2249+ p2+=2;
2250+
2251+ string_push_back3(sub_str, target, region->beg[0]);
2252+ }
2253+ else if(*(p2+1) == '\'') {
2254+ p2+=2;
2255+
2256+ string_push_back(sub_str, target + region->end[0]);
2257+ }
2258+ else if(*(p2+1) == '+') {
2259+ p2+=2;
2260+
2261+ if(region->num_regs > 0) {
2262+ const int n = region->num_regs - 1;
2263+
2264+ const int size = region->end[n] - region->beg[n];
2265+
2266+ string_push_back3(sub_str, target + region->beg[n], size);
2267+ }
2268+ }
2269+ else {
2270+ string_push_back2(sub_str, *p2++);
2271+ }
2272+ }
2273+ else {
2274+ string_push_back2(sub_str, *p2++);
2275+ }
2276+ }
2277+ }
2278+
2279+ if(!quiet) {
2280+ if(!fd_write(nextout, p, region->beg[0]-point)) {
2281+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
18052282 runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
18062283 onig_region_free(region, 1);
18072284 onig_free(reg);
18082285 return FALSE;
18092286 }
1810- }
1811- else if(size == 0) {
1812- if(!fd_write(nextout, field, strlen(field))) {
1813- err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2287+ if(!fd_write(nextout, string_c_str(sub_str), string_length(sub_str))) {
2288+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
18142289 runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
18152290 onig_region_free(region, 1);
18162291 onig_free(reg);
@@ -1818,39 +2293,59 @@ BOOL cmd_split(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
18182293 }
18192294 }
18202295
1821- p = target + region->end[0];
1822- }
2296+ sub_count++;
18232297
1824- if(region->num_regs > 1) {
1825- /// group strings ///
1826- int i;
1827- for(i=1; i<region->num_regs; i++) {
1828- const int size = region->end[i]-region->beg[i];
1829- if(size > 0) {
1830- if(!fd_write(nextout, target + region->beg[i], size)) {
1831- err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1832- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1833- onig_region_free(region, 1);
1834- onig_free(reg);
1835- return FALSE;
1836- }
2298+ if(region->beg[0] == region->end[0]) {
2299+ char buf[2];
2300+ buf[0] = target[region->beg[0]];
2301+ buf[1] = 0;
18372302
1838- if(!fd_write(nextout, field, strlen(field))) {
1839- err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2303+ if(!quiet) {
2304+ if(!fd_write(nextout, buf, 1)) {
2305+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
18402306 runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
18412307 onig_region_free(region, 1);
18422308 onig_free(reg);
18432309 return FALSE;
18442310 }
18452311 }
2312+
2313+ p = target + region->end[0] + 1;
2314+
2315+ if(p > target + strlen(target)) {
2316+ break;
2317+ }
2318+ }
2319+ else {
2320+ p= target + region->end[0];
2321+ }
2322+
2323+ onig_region_free(region, 1);
2324+
2325+ if(!global && !quiet) {
2326+ if(!fd_write(nextout, p, strlen(p))) {
2327+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2328+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2329+ onig_free(reg);
2330+ return FALSE;
2331+ }
2332+ break;
18462333 }
18472334 }
18482335 }
1849-
1850- onig_region_free(region, 1);
2336+ }
2337+ else {
2338+ err_msg("invalid regex", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2339+ return FALSE;
18512340 }
18522341
1853- if(split_count > 0) {
2342+ onig_free(reg);
2343+
2344+ char buf[128];
2345+ snprintf(buf, 128, "%d", sub_count);
2346+ uobject_put(gRootObject, "SUB_COUNT", STRING_NEW_GC(buf, FALSE));
2347+
2348+ if(sub_count > 0) {
18542349 if(SFD(nextin).mBufLen == 0) {
18552350 runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
18562351 }
@@ -1859,97 +2354,35 @@ BOOL cmd_split(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
18592354 }
18602355 }
18612356 else {
1862- runinfo->mRCode = 1;
2357+ runinfo->mRCode = RCODE_NFUN_FALSE;
18632358 }
18642359 }
1865-
1866- onig_free(reg);
18672360 }
18682361
18692362 return TRUE;
18702363 }
18712364
1872-BOOL cmd_add(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
2365+BOOL cmd_split(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
18732366 {
1874- enum eKanjiCode code = gKanjiCode;
1875- if(sRunInfo_option(runinfo, "-byte")) {
1876- code = kByte;
1877- }
1878- else if(sRunInfo_option(runinfo, "-utf8")) {
1879- code = kUtf8;
2367+ char* field = "\n";
2368+ eLineField lf = gLineField;
2369+ if(sRunInfo_option(runinfo, "-Lw")) {
2370+ lf = kCRLF;
2371+ field = "\r\n";
18802372 }
1881- else if(sRunInfo_option(runinfo, "-sjis")) {
1882- code = kSjis;
2373+ else if(sRunInfo_option(runinfo, "-Lm")) {
2374+ lf = kCR;
2375+ field = "\r";
18832376 }
1884- else if(sRunInfo_option(runinfo, "-eucjp")) {
1885- code = kEucjp;
2377+ else if(sRunInfo_option(runinfo, "-Lu")) {
2378+ lf = kLF;
2379+ field = "\n";
18862380 }
1887-
1888- if(runinfo->mFilter && runinfo->mArgsNumRuntime == 2) {
1889- char* arg = runinfo->mArgsRuntime[1];
1890- int number;
1891- char* argument;
1892- if(argument = sRunInfo_option_with_argument(runinfo, "-number")) {
1893- number = atoi(argument);
1894- }
1895- else if(argument = sRunInfo_option_with_argument(runinfo, "-index")) {
1896- number = atoi(argument);
1897- }
1898- else {
1899- number = -1;
1900- }
1901-
1902- const int len = str_kanjilen(code, SFD(nextin).mBuf);
1903-
1904- if(number < 0) {
1905- number += len + 1;
1906- if(number < 0) number = 0;
1907- }
1908-
1909- if(number < len) {
1910- int point = str_kanjipos2pointer(code, SFD(nextin).mBuf, number) - SFD(nextin).mBuf;
1911- if(!fd_write(nextout, SFD(nextin).mBuf, point)) {
1912- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1913- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1914- return FALSE;
1915- }
1916- if(!fd_write(nextout, arg, strlen(arg))) {
1917- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1918- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1919- return FALSE;
1920- }
1921- if(!fd_write(nextout, SFD(nextin).mBuf + point, SFD(nextin).mBufLen - point)) {
1922- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1923- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1924- return FALSE;
1925- }
1926- }
1927- else {
1928- if(!fd_write(nextout, SFD(nextin).mBuf, SFD(nextin).mBufLen)) {
1929- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1930- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1931- return FALSE;
1932- }
1933- if(!fd_write(nextout, arg, strlen(arg))) {
1934- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1935- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1936- return FALSE;
1937- }
1938- }
1939-
1940- if(SFD(nextin).mBufLen == 0) {
1941- runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
1942- }
1943- else {
1944- runinfo->mRCode = 0;
1945- }
2381+ else if(sRunInfo_option(runinfo, "-La")) {
2382+ lf = kBel;
2383+ field = "\a";
19462384 }
19472385
1948- return TRUE;
1949-}
1950-
1951-BOOL cmd_del(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
1952-{
19532386 enum eKanjiCode code = gKanjiCode;
19542387 if(sRunInfo_option(runinfo, "-byte")) {
19552388 code = kByte;
@@ -1964,283 +2397,274 @@ BOOL cmd_del(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
19642397 code = kEucjp;
19652398 }
19662399
1967-
1968- if(runinfo->mFilter && runinfo->mArgsNumRuntime == 2) {
1969- char* arg = runinfo->mArgsRuntime[1];
1970- int index = atoi(arg);
1971-
1972- int number;
1973- char* argument;
1974- if(argument = sRunInfo_option_with_argument(runinfo, "-number")) {
1975- number = atoi(argument);
1976- }
1977- else if(argument = sRunInfo_option_with_argument(runinfo, "-index")) {
1978- number = atoi(argument);
1979- }
1980- else {
1981- number = 1;
1982- }
1983-
1984- const int len = str_kanjilen(code, SFD(nextin).mBuf);
1985-
1986- if(index < 0) {
1987- index += len;
1988- if(index < 0) index = 0;
1989- }
1990- if(index >= len) {
1991- index = len -1;
1992- if(index < 0) index = 0;
1993- }
2400+ if(runinfo->mFilter) {
2401+ if(sRunInfo_option(runinfo, "-no-regex")) {
2402+ char* word;
19942403
1995- int point = str_kanjipos2pointer(code, SFD(nextin).mBuf, index) - SFD(nextin).mBuf;
1996-
1997- if(!fd_write(nextout, SFD(nextin).mBuf, point)) {
1998- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
1999- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2000- return FALSE;
2001- }
2002- if(index + number < len) {
2003- char* point = str_kanjipos2pointer(code, SFD(nextin).mBuf, index + number);
2004- if(!fd_write(nextout, point, strlen(point))) {
2005- err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2006- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2007- return FALSE;
2404+ if(runinfo->mArgsNumRuntime == 1) {
2405+ word = " ";
2406+ }
2407+ else if(runinfo->mArgsNumRuntime >= 2) {
2408+ word = runinfo->mArgsRuntime[1];
20082409 }
2009- }
20102410
2011- if(SFD(nextin).mBufLen == 0) {
2012- runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
2013- }
2014- else {
2015- runinfo->mRCode = 0;
2016- }
2017- }
2411+ char* target;
2412+ char* p = target = SFD(nextin).mBuf;
20182413
2019- return TRUE;
2020-}
2414+ int split_count = 0;
20212415
2022-BOOL cmd_rows(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
2023-{
2024- enum eKanjiCode code = gKanjiCode;
2025- if(sRunInfo_option(runinfo, "-byte")) {
2026- code = kByte;
2027- }
2028- else if(sRunInfo_option(runinfo, "-utf8")) {
2029- code = kUtf8;
2030- }
2031- else if(sRunInfo_option(runinfo, "-sjis")) {
2032- code = kSjis;
2033- }
2034- else if(sRunInfo_option(runinfo, "-eucjp")) {
2035- code = kEucjp;
2036- }
2416+ while(1) {
2417+ char* result;
2418+ if(sRunInfo_option(runinfo, "-ignore-case")) {
2419+ result = strcasestr(p, word);
2420+ }
2421+ else {
2422+ result = strstr(p, word);
2423+ }
2424+
2425+ if(result == NULL) {
2426+ if(*p) {
2427+ if(!fd_write(nextout, p, strlen(p))) {
2428+ err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2429+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2430+ return FALSE;
2431+ }
2432+ }
20372433
2038- if(runinfo->mFilter && runinfo->mArgsNumRuntime > 1 && runinfo->mBlocksNum <= runinfo->mArgsNumRuntime-1) {
2039- if(SFD(nextin).mBufLen == 0) {
2040- runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
2041- }
2042- else {
2043- runinfo->mRCode = 0;
2044- }
2434+ if(!fd_write(nextout, field, strlen(field))) {
2435+ err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2436+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2437+ return FALSE;
2438+ }
2439+ break;
2440+ }
2441+ else {
2442+ split_count++;
20452443
2046- int i;
2047- for(i=1; i<runinfo->mArgsNumRuntime; i++) {
2048- char* arg = runinfo->mArgsRuntime[i];
2049- char* p;
2050- if(p = strstr(arg, "..")) {
2051- char buf[128+1];
2052- char buf2[128+1];
2053- const int len = p - arg;
2054- const int len2 = arg + strlen(arg) - (p + 2);
2055- if(len < 128 || len2 < 128) {
2056- memcpy(buf, arg, len);
2057- buf[len] = 0;
2444+ if(!fd_write(nextout, p, result - p)) {
2445+ err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2446+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2447+ return FALSE;
2448+ }
20582449
2059- memcpy(buf2, p + 2, len2);
2060- buf2[len2] = 0;
2450+ if(!fd_write(nextout, field, strlen(field))) {
2451+ err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2452+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2453+ return FALSE;
2454+ }
2455+
2456+ p = result + strlen(word);
2457+ }
2458+ }
2459+
2460+ if(split_count > 0) {
2461+ if(SFD(nextin).mBufLen == 0) {
2462+ runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
20612463 }
20622464 else {
2063- err_msg("invalid range", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2064- return FALSE;
2465+ runinfo->mRCode = 0;
20652466 }
2467+ }
2468+ else {
2469+ runinfo->mRCode = 1;
2470+ }
2471+ } else {
2472+ char* regex;
20662473
2067- const int kanjilen = str_kanjilen(code, SFD(nextin).mBuf);
2068- if(kanjilen > 0) {
2069- int first = atoi(buf);
2070- int second = atoi(buf2);
2474+ if(runinfo->mArgsNumRuntime == 1) {
2475+ regex = "\\s+";
2476+ }
2477+ else if(runinfo->mArgsNumRuntime >= 2) {
2478+ regex = runinfo->mArgsRuntime[1];
2479+ }
20712480
2072- if(first < 0) {
2073- first += kanjilen;
2074- if(first < 0) first = 0;
2075- }
2076- if(second < 0) {
2077- second += kanjilen;
2078- if(second < 0) second = 0;
2079- }
2080- if(first >= kanjilen) {
2081- first = kanjilen -1;
2082- if(first < 0) first = 0;
2083- }
2084- if(second >= kanjilen) {
2085- second = kanjilen -1;
2086- if(second < 0) second = 0;
2087- }
2481+ regex_t* reg;
2482+ int r = get_onig_regex(&reg, runinfo, regex);
20882483
2089- /// make table to indexing access ///
2090- char** array = MALLOC(sizeof(char*)*(kanjilen+1));
2091- if(code == kByte) {
2092- int k;
2093- for(k=0; k<kanjilen; k++) {
2094- array[k] = SFD(nextin).mBuf + k;
2095- }
2096- array[k] = SFD(nextin).mBuf + k;
2097- }
2098- else if(code == kUtf8) {
2099- char* p = SFD(nextin).mBuf;
2484+ if(r == ONIG_NORMAL) {
2485+ char* target;
2486+ char* p = target = SFD(nextin).mBuf;
21002487
2101- int k;
2102- for(k=0; k<kanjilen; k++) {
2103- array[k] = p;
2104- if(((unsigned char)*p) > 127) {
2105- const int size = ((*p & 0x80) >> 7) + ((*p & 0x40) >> 6) + ((*p & 0x20) >> 5) + ((*p & 0x10) >> 4);
2106- p+=size;
2107- }
2108- else {
2109- p++;
2488+ int split_count = 0;
2489+
2490+ while(1) {
2491+ OnigRegion* region = onig_region_new();
2492+
2493+ int r2 = onig_search(reg, target
2494+ , target + strlen(target)
2495+ , p, p + strlen(p)
2496+ , region, ONIG_OPTION_NONE);
2497+
2498+ if(r2 == ONIG_MISMATCH) {
2499+ onig_region_free(region, 1);
2500+
2501+ if(*p) {
2502+ if(!fd_write(nextout, p, strlen(p))) {
2503+ err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2504+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2505+ onig_free(reg);
2506+ return FALSE;
21102507 }
21112508 }
2112- array[k] = p;
2113- }
2114- else {
2115- char* p = SFD(nextin).mBuf;
21162509
2117- int k;
2118- for(k=0; k<kanjilen; k++) {
2119- const int size = is_kanji(code, *p) ? 2 : 1;
2120- array[k] = p;
2121- p+=size;
2510+ if(!fd_write(nextout, field, strlen(field))) {
2511+ err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2512+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2513+ onig_free(reg);
2514+ return FALSE;
21222515 }
2123- array[k] = p;
2516+ break;
21242517 }
2518+ else {
2519+ split_count++;
21252520
2126- if(first < second) {
2127- sObject* nextin2 = FD_NEW_STACK();
2521+ if(region->beg[0] == region->end[0]) {
2522+ if(target + region->beg[0] == p) {
2523+ char* end_byte = str_kanjipos2pointer(code, p, 1);
2524+ int size = end_byte - p;
21282525
2129- int j;
2130- for(j=first; j<=second; j++) {
2131- fd_clear(nextin2);
2526+ if(size > 0) {
2527+ if(!fd_write(nextout, p, size)) {
2528+ err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2529+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2530+ onig_region_free(region, 1);
2531+ onig_free(reg);
2532+ return FALSE;
2533+ }
21322534
2133- if(!fd_write(nextin2, array[j], array[j+1] -array[j])) {
2134- err_msg("interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2135- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2136- FREE(array);
2137- return FALSE;
2138- }
2535+ if(!fd_write(nextout, field, strlen(field))) {
2536+ err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2537+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2538+ onig_region_free(region, 1);
2539+ onig_free(reg);
2540+ return FALSE;
2541+ }
21392542
2140- if(i-1 < runinfo->mBlocksNum) {
2141- int rcode = 0;
2142- if(!run(runinfo->mBlocks[i-1], nextin2, nextout, &rcode, runinfo->mCurrentObject, runinfo->mRunningObject)) {
2143- runinfo->mRCode = rcode;
2144- FREE(array);
2145- return FALSE;
2543+ p += size;
2544+ }
2545+ else {
2546+ onig_region_free(region, 1);
2547+
2548+ break;
21462549 }
2147- runinfo->mRCode = rcode;
21482550 }
21492551 else {
2150- if(!fd_write(nextout, SFD(nextin2).mBuf, SFD(nextin2).mBufLen))
2151- {
2152- err_msg("interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2153- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2154- FREE(array);
2155- return FALSE;
2552+ int size = region->beg[0] - (p-target);
2553+
2554+ if(size > 0) {
2555+ if(!fd_write(nextout, p, size)) {
2556+ err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2557+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2558+ onig_region_free(region, 1);
2559+ onig_free(reg);
2560+ return FALSE;
2561+ }
2562+
2563+ if(!fd_write(nextout, field, strlen(field))) {
2564+ err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2565+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2566+ onig_region_free(region, 1);
2567+ onig_free(reg);
2568+ return FALSE;
2569+ }
21562570 }
2157- runinfo->mRCode = 0;
2571+ else if(size == 0) {
2572+ if(!fd_write(nextout, field, strlen(field))) {
2573+ err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2574+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2575+ onig_region_free(region, 1);
2576+ onig_free(reg);
2577+ return FALSE;
2578+ }
2579+ }
2580+
2581+ p = target + region->end[0];
21582582 }
21592583 }
2160- }
2161- else {
2162- sObject* nextin2 = FD_NEW_STACK();
2163-
2164- int j;
2165- for(j=first; j>=second; j--) {
2166- fd_clear(nextin2);
2584+ else {
2585+ int size = region->beg[0] - (p-target);
21672586
2168- if(!fd_write(nextin2, array[j], array[j+1]-array[j])) {
2169- err_msg("interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2170- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2171- FREE(array);
2172- return FALSE;
2173- }
2587+ if(size > 0) {
2588+ if(!fd_write(nextout, p, size)) {
2589+ err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2590+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2591+ onig_region_free(region, 1);
2592+ onig_free(reg);
2593+ return FALSE;
2594+ }
21742595
2175- if(i-1 < runinfo->mBlocksNum) {
2176- int rcode = 0;
2177- if(!run(runinfo->mBlocks[i-1], nextin2, nextout, &rcode, runinfo->mCurrentObject, runinfo->mRunningObject)) {
2178- runinfo->mRCode = rcode;
2179- FREE(array);
2596+ if(!fd_write(nextout, field, strlen(field))) {
2597+ err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2598+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2599+ onig_region_free(region, 1);
2600+ onig_free(reg);
21802601 return FALSE;
21812602 }
2182- runinfo->mRCode = rcode;
21832603 }
2184- else {
2185- if(!fd_write(nextout, SFD(nextin2).mBuf, SFD(nextin2).mBufLen))
2186- {
2187- err_msg("interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2604+ else if(size == 0) {
2605+ if(!fd_write(nextout, field, strlen(field))) {
2606+ err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
21882607 runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2189- FREE(array);
2608+ onig_region_free(region, 1);
2609+ onig_free(reg);
21902610 return FALSE;
21912611 }
2192- runinfo->mRCode = 0;
21932612 }
2194- }
2195- }
21962613
2197- FREE(array);
2198- }
2199- }
2200- else {
2201- const int len = str_kanjilen(code, SFD(nextin).mBuf);
2202- int num = atoi(arg);
2614+ p = target + region->end[0];
2615+ }
22032616
2204- if(num < 0) {
2205- num += len;
2206- if(num < 0) num = 0;
2207- }
2208- if(num >= len) {
2209- num = len -1;
2210- if(num < 0) num = 0;
2211- }
2617+ if(region->num_regs > 1) {
2618+ /// group strings ///
2619+ int i;
2620+ for(i=1; i<region->num_regs; i++) {
2621+ const int size = region->end[i]-region->beg[i];
2622+ if(size > 0) {
2623+ if(!fd_write(nextout, target + region->beg[i], size)) {
2624+ err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2625+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2626+ onig_region_free(region, 1);
2627+ onig_free(reg);
2628+ return FALSE;
2629+ }
22122630
2213- sObject* nextin2 = FD_NEW_STACK();
2631+ if(!fd_write(nextout, field, strlen(field))) {
2632+ err_msg("singal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2633+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2634+ onig_region_free(region, 1);
2635+ onig_free(reg);
2636+ return FALSE;
2637+ }
2638+ }
2639+ }
2640+ }
2641+ }
22142642
2215- char* str = str_kanjipos2pointer(code, SFD(nextin).mBuf, num);
2216- char* str2 = str_kanjipos2pointer(code, str, 1);
2217- if(!fd_write(nextin2, str, str2 -str)) {
2218- err_msg("interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2219- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2220- return FALSE;
2643+ onig_region_free(region, 1);
22212644 }
22222645
2223- if(i-1 < runinfo->mBlocksNum) {
2224- int rcode = 0;
2225- if(!run(runinfo->mBlocks[i-1], nextin2, nextout, &rcode, runinfo->mCurrentObject, runinfo->mRunningObject)) {
2226- runinfo->mRCode = rcode;
2227- return FALSE;
2646+ if(split_count > 0) {
2647+ if(SFD(nextin).mBufLen == 0) {
2648+ runinfo->mRCode = RCODE_NFUN_NULL_INPUT;
2649+ }
2650+ else {
2651+ runinfo->mRCode = 0;
22282652 }
2229- runinfo->mRCode = rcode;
22302653 }
22312654 else {
2232- if(!fd_write(nextout, SFD(nextin2).mBuf, SFD(nextin2).mBufLen))
2233- {
2234- err_msg("interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2235- runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
2236- return FALSE;
2237- }
2238- runinfo->mRCode = 0;
2655+ runinfo->mRCode = 1;
22392656 }
22402657 }
2658+ else {
2659+ err_msg("invalid regex", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
2660+ return FALSE;
2661+ }
2662+
2663+ onig_free(reg);
22412664 }
22422665 }
22432666
22442667 return TRUE;
22452668 }
22462669
2670+
--- /dev/null
+++ b/src/ext/migemo.c
@@ -0,0 +1,198 @@
1+#include "config.h"
2+#include <errno.h>
3+#include <time.h>
4+#include <stdlib.h>
5+#include <fcntl.h>
6+#include <libgen.h>
7+#include <stdio.h>
8+#include <string.h>
9+#include <unistd.h>
10+#include <math.h>
11+#include <oniguruma.h>
12+#include <sys/stat.h>
13+#include <signal.h>
14+#include <limits.h>
15+#include <dirent.h>
16+#include <migemo.h>
17+
18+#include "xyzsh/xyzsh.h"
19+
20+static migemo* gMigemo;
21+static sObject* gMigemoCache;
22+
23+static void migemo_init()
24+{
25+ char buf[PATH_MAX];
26+ char migemodir[PATH_MAX];
27+ gMigemo = migemo_open(NULL);
28+
29+ snprintf(migemodir, PATH_MAX, "%s", SYSTEM_MIGEMODIR);
30+
31+ snprintf(buf, PATH_MAX, "%s/utf-8/migemo-dict", migemodir);
32+ if(migemo_load(gMigemo, MIGEMO_DICTID_MIGEMO, buf) == MIGEMO_DICTID_INVALID) {
33+ fprintf(stderr, "%s is not found\n", buf);
34+ exit(1);
35+ }
36+ snprintf(buf, PATH_MAX, "%s/utf-8/roma2hira.dat", migemodir);
37+ if(migemo_load(gMigemo, MIGEMO_DICTID_ROMA2HIRA, buf) == MIGEMO_DICTID_INVALID) {
38+ fprintf(stderr, "%s is not found\n", buf);
39+ exit(1);
40+ }
41+ snprintf(buf, PATH_MAX, "%s/utf-8/hira2kata.dat", migemodir);
42+ if(migemo_load(gMigemo, MIGEMO_DICTID_HIRA2KATA, buf) == MIGEMO_DICTID_INVALID) {
43+ fprintf(stderr, "%s is not found\n", buf);
44+ exit(1);
45+ }
46+ snprintf(buf, PATH_MAX, "%s/utf-8/han2zen.dat", migemodir);
47+ if(migemo_load(gMigemo, MIGEMO_DICTID_HAN2ZEN, buf) == MIGEMO_DICTID_INVALID) {
48+ fprintf(stderr, "%s is not found\n", buf);
49+ exit(1);
50+ }
51+}
52+
53+static void migemo_final()
54+{
55+ onig_end();
56+ migemo_close(gMigemo);
57+
58+ hash_it* it = hash_loop_begin(gMigemoCache);
59+ while(it) {
60+ regex_t* reg = hash_loop_item(it);
61+ onig_free(reg);
62+
63+ it = hash_loop_next(it);
64+ }
65+ hash_delete_on_malloc(gMigemoCache);
66+}
67+
68+BOOL cmd_migemo_match(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
69+{
70+ BOOL quiet = sRunInfo_option(runinfo, "-quiet");
71+
72+ if(runinfo->mFilter && runinfo->mArgsNumRuntime == 2) {
73+ runinfo->mRCode = RCODE_NFUN_FALSE;
74+ char* target = SFD(nextin).mBuf;
75+ char* regex = runinfo->mArgsRuntime[1];
76+
77+ if(regex[0] == 0) {
78+ runinfo->mRCode = 0;
79+ if(!quiet) {
80+ char buf[1024];
81+ int n = snprintf(buf, 1024, "0%d\n", (int)strlen(target));
82+ if(!fd_write(nextout, buf, n)) {
83+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
84+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
85+ return FALSE;
86+ }
87+ }
88+ }
89+ else {
90+ regex_t* reg = hash_item(gMigemoCache, regex);
91+
92+ if(reg == NULL) {
93+ OnigUChar * p = migemo_query(gMigemo, regex);
94+ if(p == NULL) {
95+ err_msg("migemo query failed", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
96+ migemo_release(gMigemo, (unsigned char*) p);
97+ return FALSE;
98+ }
99+
100+ /// modify query ///
101+ char* p2 = MALLOC(strlen(p)*2 + 1);
102+
103+ char* _p = p;
104+ char* _p2 = p2;
105+
106+ while(*_p) {
107+ if(*_p == '+') {
108+ *_p2++ = '\\';
109+ *_p2++ = *_p++;
110+ }
111+ else {
112+ *_p2++ = *_p++;
113+ }
114+ }
115+ *_p2 = 0;
116+
117+ /// make regex ///
118+ OnigErrorInfo err_info;
119+
120+ int r = onig_new(&reg, p2, p2 + strlen(p2), ONIG_OPTION_DEFAULT, ONIG_ENCODING_UTF8, ONIG_SYNTAX_DEFAULT, &err_info);
121+
122+ if(r != ONIG_NORMAL && r != 0) {
123+ err_msg("regex of migemo query failed", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
124+ onig_free(reg);
125+ FREE(p2);
126+ migemo_release(gMigemo, (unsigned char*) p);
127+ return FALSE;
128+ }
129+
130+ FREE(p2);
131+ migemo_release(gMigemo, (unsigned char*) p);
132+ }
133+
134+ OnigRegion* region = onig_region_new();
135+ int r2 = onig_search(reg, target, target + strlen(target), target, target + strlen(target), region, ONIG_OPTION_NONE);
136+
137+ if(r2 >= 0) {
138+ runinfo->mRCode = 0;
139+ if(!quiet) {
140+ char buf[1024];
141+ int n = snprintf(buf, 1024, "%d\n%d\n", region->beg[0], region->end[0]);
142+ if(!fd_write(nextout, buf, n)) {
143+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
144+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
145+ onig_region_free(region, 1);
146+ onig_free(reg);
147+ return FALSE;
148+ }
149+ }
150+ }
151+ else {
152+ if(!quiet) {
153+ char buf[1024];
154+ int n = snprintf(buf, 1024, "-1\n-1\n");
155+ if(!fd_write(nextout, buf, n)) {
156+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
157+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
158+ onig_region_free(region, 1);
159+ onig_free(reg);
160+ return FALSE;
161+ }
162+ }
163+ }
164+
165+ onig_region_free(region, 1);
166+
167+ /// Migemo querry which is only one character is very heavy, so get cache.
168+ if(strlen(regex) <= 2) {
169+ hash_put(gMigemoCache, regex, reg);
170+ }
171+ else {
172+ onig_free(reg);
173+ }
174+ }
175+ }
176+
177+ return TRUE;
178+}
179+
180+int dl_init()
181+{
182+ migemo_init();
183+ sObject* migemo_object = UOBJECT_NEW_GC(8, gRootObject, "migemo", TRUE);
184+ uobject_init(migemo_object);
185+ uobject_put(gRootObject, "migemo", migemo_object);
186+ uobject_put(migemo_object, "match", NFUN_NEW_GC(cmd_migemo_match, NULL, TRUE));
187+ gMigemoCache = HASH_NEW_MALLOC(100);
188+
189+ return 0;
190+}
191+
192+int dl_final()
193+{
194+ migemo_final();
195+
196+ return 0;
197+}
198+
--- /dev/null
+++ b/src/ext/migemo.so.dSYM/Contents/Info.plist
@@ -0,0 +1,20 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+<plist version="1.0">
4+ <dict>
5+ <key>CFBundleDevelopmentRegion</key>
6+ <string>English</string>
7+ <key>CFBundleIdentifier</key>
8+ <string>com.apple.xcode.dsym.migemo.so</string>
9+ <key>CFBundleInfoDictionaryVersion</key>
10+ <string>6.0</string>
11+ <key>CFBundlePackageType</key>
12+ <string>dSYM</string>
13+ <key>CFBundleSignature</key>
14+ <string>????</string>
15+ <key>CFBundleShortVersionString</key>
16+ <string>1.0</string>
17+ <key>CFBundleVersion</key>
18+ <string>1</string>
19+ </dict>
20+</plist>
Binary files /dev/null and b/src/ext/migemo.so.dSYM/Contents/Resources/DWARF/migemo.so differ
--- /dev/null
+++ b/src/ext/migemo.so.xyzsh
@@ -0,0 +1,151 @@
1+
2+print "welcome to migemo.so dynamic library. You can read help type with \"migemo::help 'command name'\""\n
3+
4+compl::run( root::object migemo )
5+
6+completion migemo::help (
7+ migemo::self | egrep native\ function\$ | egrep -v 'run|show' | root::scan '(^.+?):' | each ( | chomp | quote | pomch )
8+)
9+
10+migemo::run(
11+ object help ( Help )
12+
13+ print <<<'EOS'
14+match (migemo クエリー)
15+-
16+パイプからの入力とmigemoクエリーを比較してマッチしたなら、そのマッチした文字範囲のバイト数を返す。
17+
18+-quiet リターンコードだけ返し、出力は返さない
19+EOS | help::set_helps_ja
20+
21+ print <<<'EOS'
22+match (migemo querry)
23+-
24+Compare migemo querry with input from pipe data and output the string ranges.
25+
26+-quiet no output. you can get only return code.
27+EOS | help::set_helps
28+)
29+
30+class MigemoCompletion (
31+ def common_head (
32+ | each (
33+ | chomp| length -utf8
34+ ) | max | var -local max_length
35+
36+ print 0 | var -local point
37+
38+ while(true) (
39+ | each (
40+ | chomp | rows -utf8 0..$point | pomch
41+ ) | sys::sort | uniq | length -line-num | strip | if(| != 1) (
42+ -- point;
43+ break
44+ )
45+
46+ ++ point;
47+
48+ if(point | -ge $max_length) (
49+ -- point
50+ break
51+ )
52+ )
53+
54+ if(point | -ne -1) (
55+ | rows -utf8 0..$point
56+ )
57+ )
58+
59+ def is_all_ascii (
60+ | length -byte | var -local LEN
61+
62+ LEN | -eq $(| length -utf8)
63+ )
64+
65+ def migemo_file_completion (
66+ print $ARGV[0] | var -local inputing
67+ print $ARGV[1] | var -local editing_line
68+
69+ | each (
70+ if (inputing | =~ '.*\/[a-zA-Z]+$') (
71+ | if(|=~ '.*\/[a-zA-Z]+[^a-zA-z/]+$') (
72+ (inputing; |print) | common_head | var -local same_head
73+
74+ same_head | var -local no_migemo_string
75+ inputing | sub -no-regex $same_head '' | var -local migemo_string
76+ ) else (
77+ inputing | sub '(.*\/)[a-zA-Z]+$' '\1' | var -local no_migemo_string
78+ inputing | sub '.*\/([a-zA-Z]+)$' '\1' | var -local migemo_string
79+ )
80+ ) elif (inputing | =~ '.*\/[^a-zA-Z]+[a-zA-Z]+$') (
81+ inputing | sub '(.*\/[^a-zA-Z]+)[a-zA-Z]+$' '\1' | var -local no_migemo_string
82+ inputing | sub '.*\/[^a-zA-Z]+([a-zA-Z]+)$' '\1' | var -local migemo_string
83+ ) elif (inputing | =~ '[a-zA-Z]+$') (
84+ | if(|=~ '[a-zA-Z]+[^a-zA-z/]+$') (
85+ (inputing; |print) | common_head | var -local same_head
86+
87+ same_head | var -local no_migemo_string
88+ inputing | sub -no-regex $same_head '' | var -local migemo_string
89+ ) else (
90+ print "" | var -local no_migemo_string
91+ inputing | var -local migemo_string
92+ )
93+ ) elif (inputing | =~ '[^a-zA-Z]+[a-zA-Z]+$') (
94+ inputing | sub '([^a-zA-Z]+)[a-zA-Z]+$' '\1' | var -local no_migemo_string
95+ inputing | sub '[^a-zA-Z]+([a-zA-Z]+)$' '\1' | var -local migemo_string
96+ ) else (
97+ print "" | var -local no_migemo_string
98+ print "" | var -local migemo_string
99+ )
100+
101+ | if(| sub -no-regex $no_migemo_string '' | chomp | migemo::match $migemo_string | lines 0 | = 0\n) (
102+ | print
103+ )
104+ ) | (| common_head | var -local COMMON_HEAD; | length -line-num | var -local NUM)
105+
106+ if(COMMON_HEAD | chomp | -n && COMMON_HEAD | length | -gt $(inputing | length)) (
107+ rl::delete_text $(editing_line | rindex $inputing) $(rl::point)
108+ rl::insert_text $COMMON_HEAD
109+ if(NUM | chomp | -eq 1 && COMMON_HEAD| chomp | rows -1 | != /) ( rl::insert_text " " )
110+ )
111+ )
112+
113+ def file_completion (
114+ | split '(?<!\\) +' | lines -1 | var -local inputing
115+
116+ if(inputing | index -quiet /) (
117+ sys::dirname $(inputing|chomp| if (|rows -1 | = /) ( |add aaa ) else ( | print ) ) | var -local DIR
118+
119+ ls $(DIR|xyzsh_dequote|chomp) | each (
120+ | if (|chomp | add -number 0 $(DIR|xyzsh_dequote|chomp)/ | -d) (
121+ |chomp | xyzsh_quote | add -number 0 $DIR/ | add / | pomch
122+ ) else (
123+ |chomp | xyzsh_quote | add -number 0 $DIR/ | pomch
124+ )
125+ ) | migemo_file_completion $inputing $(|print)
126+ ) else (
127+ ls | each (
128+ | if (|chomp| -d) (
129+ | chomp | xyzsh_quote | add / | pomch
130+ ) else (
131+ |chomp | xyzsh_quote| pomch
132+ )
133+ ) | migemo_file_completion $inputing $(|print)
134+ )
135+ )
136+
137+ completion __all__ (
138+ | file_completion
139+ )
140+
141+ root::compl::run( root::object sys )
142+
143+ completion sys::__all__ (
144+ | file_completion
145+ )
146+)
147+
148+readline "Do you want to use migemo completion which is Japanese ROMAJI completion?(y/n)" | chomp | if(|=~ -ignore-case ^y) (
149+ MigemoCompletion
150+)
151+
--- /dev/null
+++ b/src/ext/migemo.so.xyzsh.bak
@@ -0,0 +1,143 @@
1+
2+print "welcome to migemo.so dynamic library. You can read help type with \"migemo::help 'command name'\""\n
3+
4+compl::run( root::object migemo )
5+
6+completion migemo::help (
7+ migemo::self | egrep native\ function\$ | egrep -v 'run|show' | root::scan '(^.+?):' | each ( | chomp | quote | pomch )
8+)
9+
10+migemo::run(
11+ object help ( Help )
12+
13+ print <<<'EOS'
14+match (migemo クエリー)
15+-
16+パイプからの入力とmigemoクエリーを比較してマッチしたなら、そのマッチした文字範囲のバイト数を返す。
17+
18+-quiet リターンコードだけ返し、出力は返さない
19+EOS | help::set_helps_ja
20+
21+ print <<<'EOS'
22+match (migemo querry)
23+-
24+Compare migemo querry with input from pipe data and output the string ranges.
25+
26+-quiet no output. you can get only return code.
27+EOS | help::set_helps
28+)
29+
30+def common_head (
31+ | each (
32+ | chomp| length -utf8
33+ ) | max | var -local max_length
34+
35+ print 0 | var -local point
36+
37+ while(true) (
38+ | each (
39+ | chomp | rows -utf8 0..$point | pomch
40+ ) | sys::sort | uniq | wc -l | strip | if(| != 1) (
41+ -- point;
42+ break
43+ )
44+
45+ ++ point;
46+
47+ if(point | -ge $max_length) (
48+ -- point
49+ break
50+ )
51+ )
52+
53+ if(point | -ne -1) (
54+ | rows -utf8 0..$point
55+ )
56+)
57+
58+def is_all_ascii (
59+ | length -byte | var -local LEN
60+
61+ LEN | -eq $(| length -utf8)
62+)
63+
64+def migemo_file_completion (
65+ print $ARGV[0] | var -local inputing
66+ print $ARGV[1] | var -local editing_line
67+
68+ if (inputing | =~ '.*\/[a-zA-Z]+') (
69+ inputing | sub '(.*\/)[a-zA-Z]+$' '\1' | var -local no_migemo_string
70+ inputing | sub '.*\/([a-zA-Z]+)$' '\1' | var -local migemo_string
71+ ) elif (inputing | =~ '.*\/[^a-zA-Z]+[a-zA-Z]+$') (
72+ inputing | sub '(.*\/[^a-zA-Z]+)[a-zA-Z]+$' '\1' | var -local no_migemo_string
73+ inputing | sub '.*\/[^a-zA-Z]+([a-zA-Z]+)$' '\1' | var -local migemo_string
74+ ) elif (inputing | =~ '[a-zA-Z]+$') (
75+ print "" | var -local no_migemo_string
76+ inputing | var -local migemo_string
77+ ) elif (inputing | =~ '[^a-zA-Z]+[a-zA-Z]+$') (
78+ inputing | sub '([^a-zA-Z]+)[a-zA-Z]+$' '\1' | var -local no_migemo_string
79+ inputing | sub '[^a-zA-Z]+([a-zA-Z]+)$' '\1' | var -local migemo_string
80+ ) else (
81+ print "" | var -local no_migemo_string
82+ print "" | var -local migemo_string
83+ )
84+
85+ | each (
86+ | if(|=~ '[a-zA-Z]+[^a-zA-z/]+$' && no_migemo_string |= \n) (
87+ (migemo_string; |print) | common_head | var -local same_head
88+
89+ | if(| sub -no-regex $no_migemo_string '' | sub -no-regex $same_head '' | chomp | migemo::match $(migemo_string|sub -no-regex $same_head '' | chomp) | lines 0 | = 0\n) (
90+ | print
91+ )
92+ ) else (
93+ | if(| sub -no-regex $no_migemo_string '' | chomp | migemo::match $migemo_string | lines 0 | = 0\n) (
94+ | print
95+ )
96+ )
97+ ) | (| common_head | var -local COMMON_HEAD; | wc -l | var -local NUM)
98+
99+ if(COMMON_HEAD | chomp | -n) (
100+ rl::delete_text $(editing_line | rindex $inputing) $(rl::point)
101+ rl::insert_text $COMMON_HEAD
102+ if(NUM | chomp | -eq 1 && COMMON_HEAD| chomp | rows -1 | != /) ( rl::insert_text " " )
103+ )
104+)
105+
106+def file_completion (
107+ | split '(?<!\\) +' | lines -1 | var -local inputing
108+
109+ if(inputing | index -quiet /) (
110+ sys::dirname $(inputing |chomp| if (|rows -1 | = /) ( |add aaa ) else ( | print ) ) | var -local DIR
111+
112+ eval "ls $DIR" | each (
113+ | if (|chomp | add -number 0 $(DIR|xyzsh_dequote|chomp)/ | -d) (
114+ |chomp | add -number 0 $DIR/ | add / | pomch
115+ ) else (
116+ |chomp | add -number 0 $DIR/ | pomch
117+ )
118+ ) | migemo_file_completion $inputing $(|print) | each (
119+ | chomp | xyzsh_quote | pomch
120+ )
121+ ) else (
122+ ls | each (
123+ | if (|chomp| -d) (
124+ | chomp | add / | pomch
125+ ) else (
126+ |chomp| pomch
127+ )
128+ ) | migemo_file_completion $inputing $(|print) | each (
129+ | chomp | xyzsh_quote | pomch
130+ )
131+ )
132+)
133+
134+completion __all__ (
135+ | file_completion
136+)
137+
138+root::compl::run( root::object sys )
139+
140+completion sys::__all__ (
141+ | file_completion
142+)
143+
--- a/src/interface.c
+++ b/src/interface.c
@@ -75,7 +75,7 @@ static char* prompt()
7575 if(rcode == RCODE_BREAK) {
7676 fprintf(stderr, "invalid break. Not in a loop\n");
7777 }
78- else if(rcode == RCODE_RETURN) {
78+ else if(rcode & RCODE_RETURN) {
7979 fprintf(stderr, "invalid return. Not in a function\n");
8080 }
8181 else if(rcode == RCODE_EXIT) {
@@ -143,6 +143,63 @@ BOOL xyzsh_run(int* rcode, sObject* block, char* source_name, fXyzshJobDone xyzs
143143 return TRUE;
144144 }
145145
146+BOOL xyzsh_eval(int* rcode, char* cmd, char* source_name, fXyzshJobDone xyzsh_job_done_, sObject* nextin, sObject* nextout, int argc, char** argv, sObject* current_object)
147+{
148+ string_put(gErrMsg, "");
149+
150+ xyzsh_job_done = xyzsh_job_done_;
151+
152+ stack_start_stack();
153+
154+ sObject* block = BLOCK_NEW_STACK();
155+ int sline = 1;
156+ if(parse(cmd, source_name, &sline, block, NULL)) {
157+ xyzsh_set_signal();
158+
159+ sObject* fun = FUN_NEW_STACK(NULL);
160+ sObject* stackframe = UOBJECT_NEW_GC(8, gXyzshObject, "_stackframe", FALSE);
161+ vector_add(gStackFrames, stackframe);
162+ //uobject_init(stackframe);
163+ SFUN(fun).mLocalObjects = stackframe;
164+
165+ sObject* argv2 = VECTOR_NEW_GC(16, FALSE);
166+ int i;
167+ for(i=0; i<argc; i++) {
168+ vector_add(argv2, STRING_NEW_GC(argv[i], FALSE));
169+ }
170+ uobject_put(SFUN(fun).mLocalObjects, "ARGV", argv2);
171+
172+ if(!run(block, nextin, nextout, rcode, current_object, fun)) {
173+ xyzsh_restore_signal_default();
174+ (void)vector_pop_back(gStackFrames);
175+
176+ stack_end_stack();
177+
178+ /// wait background job
179+ xyzsh_wait_background_job();
180+
181+ return FALSE;
182+ }
183+ xyzsh_restore_signal_default();
184+
185+ (void)vector_pop_back(gStackFrames);
186+ stack_end_stack();
187+ }
188+ else {
189+ stack_end_stack();
190+
191+ /// wait background job
192+ xyzsh_wait_background_job();
193+
194+ return FALSE;
195+ }
196+
197+ /// wait background job
198+ xyzsh_wait_background_job();
199+
200+ return TRUE;
201+}
202+
146203 static void readline_insert_text(char* cmdline, int cursor_point)
147204 {
148205 (void)rl_replace_line(cmdline, 0);
@@ -288,7 +345,7 @@ BOOL xyzsh_readline_interface_onetime(int* rcode, char* cmdline, int cursor_poin
288345 if(*rcode == RCODE_BREAK) {
289346 fprintf(stderr, "invalid break. Not in a loop\n");
290347 }
291- else if(*rcode == RCODE_RETURN) {
348+ else if(*rcode & RCODE_RETURN) {
292349 fprintf(stderr, "invalid return. Not in a function\n");
293350 }
294351 else if(*rcode == RCODE_EXIT) {
@@ -445,7 +502,7 @@ void xyzsh_readline_interface(char* cmdline, int cursor_point, char** argv, int
445502 if(rcode == RCODE_BREAK) {
446503 fprintf(stderr, "invalid break. Not in a loop\n");
447504 }
448- else if(rcode == RCODE_RETURN) {
505+ else if(rcode & RCODE_RETURN) {
449506 fprintf(stderr, "invalid return. Not in a function\n");
450507 }
451508 else if(rcode == RCODE_EXIT) {
@@ -500,7 +557,7 @@ BOOL xyzsh_load_file(char* fname, char** argv, int argc, sObject* current_object
500557 xyzsh_restore_signal_default();
501558 return FALSE;
502559 }
503- else if(runinfo.mRCode == RCODE_RETURN) {
560+ else if(runinfo.mRCode & RCODE_RETURN) {
504561 fprintf(stderr, "invalid return. Not in a function\n");
505562 xyzsh_restore_signal_default();
506563 return FALSE;
@@ -552,7 +609,7 @@ void xyzsh_opt_c(char* cmd, char** argv, int argc)
552609 if(rcode == RCODE_BREAK) {
553610 fprintf(stderr, "invalid break. Not in a loop\n");
554611 }
555- else if(rcode == RCODE_RETURN) {
612+ else if(rcode & RCODE_RETURN) {
556613 fprintf(stderr, "invalid return. Not in a function\n");
557614 }
558615 else if(rcode == RCODE_EXIT) {
--- a/src/readline.c
+++ b/src/readline.c
@@ -86,13 +86,16 @@ static char* message_completion(const char* text, int stat)
8686 string_push_back(candidate, key);
8787
8888 if(TYPE(item) == T_UOBJECT) {
89- vector_add(gCompletionArray, string_c_str(candidate));
90-
91- sObject* candidate2 = STRING_NEW_STACK(string_c_str(messages));
92- string_push_back(candidate2, key);
93- string_push_back(candidate2, "::");
89+ if(uobject_item(item, "main")) {
90+ vector_add(gCompletionArray, string_c_str(candidate));
91+ }
92+ else {
93+ sObject* candidate2 = STRING_NEW_STACK(string_c_str(messages));
94+ string_push_back(candidate2, key);
95+ string_push_back(candidate2, "::");
9496
95- vector_add(gCompletionArray, string_c_str(candidate2));
97+ vector_add(gCompletionArray, string_c_str(candidate2));
98+ }
9699 }
97100 else {
98101 vector_add(gCompletionArray, string_c_str(candidate));
@@ -282,7 +285,9 @@ static char* user_completion(const char* text, int stat)
282285
283286 if(!strncmp(text, candidate, wordlen)) {
284287 int l = strlen(candidate);
285- if(l > 2 && candidate[l-2] == ':' && candidate[l-1] == ':') {
288+ if((l > 2 && candidate[l-2] == ':' && candidate[l-1] == ':' )
289+ || (l > 1 && candidate[l-1] == '/') )
290+ {
286291 rl_completion_append_character = 0;
287292 }
288293 else {
@@ -476,7 +481,6 @@ static sObject* access_object_compl(char* name, sObject** current)
476481 }
477482 }
478483
479-
480484 char** readline_on_complete(const char* text, int start, int end)
481485 {
482486 stack_start_stack();
@@ -753,6 +757,24 @@ BOOL cmd_readline_clear_screen(sObject* nextin, sObject* nextout, sRunInfo* runi
753757 return TRUE;
754758 }
755759
760+BOOL cmd_readline_point(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
761+{
762+ if(!runinfo->mFilter) {
763+ char buf[BUFSIZ];
764+ int n = snprintf(buf, BUFSIZ, "%d\n", rl_point);
765+ if(!fd_write(nextout, buf, n)) {
766+ sCommand* command = runinfo->mCommand;
767+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, command->mArgs[0]);
768+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
769+ return FALSE;
770+ }
771+
772+ runinfo->mRCode = 0;
773+ }
774+
775+ return TRUE;
776+}
777+
756778 BOOL cmd_readline_point_move(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
757779 {
758780 if(runinfo->mArgsNumRuntime == 2) {
@@ -772,8 +794,8 @@ BOOL cmd_readline_point_move(sObject* nextin, sObject* nextout, sRunInfo* runinf
772794
773795 BOOL cmd_readline_insert_text(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
774796 {
775- if(runinfo->mFilter) {
776- (void)rl_insert_text(SFD(nextin).mBuf);
797+ if(runinfo->mArgsNumRuntime == 2) {
798+ (void)rl_insert_text(runinfo->mArgsRuntime[1]);
777799 puts("");
778800 rl_forced_update_display();
779801
@@ -805,6 +827,24 @@ BOOL cmd_readline_delete_text(sObject* nextin, sObject* nextout, sRunInfo* runin
805827 return TRUE;
806828 }
807829
830+BOOL cmd_readline_replace_line(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
831+{
832+ if(runinfo->mArgsNumRuntime == 3) {
833+ (void)rl_replace_line(runinfo->mArgsRuntime[1], 0);
834+
835+ int n = atoi(runinfo->mArgsRuntime[2]);
836+
837+ if(n < 0) n += strlen(rl_line_buffer) + 1;
838+ if(n < 0) n = 0;
839+ if(n > strlen(rl_line_buffer)) n = strlen(rl_line_buffer);
840+
841+ rl_point = n;
842+ runinfo->mRCode = 0;
843+ }
844+
845+ return TRUE;
846+}
847+
808848 BOOL cmd_readline_read_history(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
809849 {
810850 if(runinfo->mArgsNumRuntime == 2) {
@@ -827,6 +867,18 @@ BOOL cmd_readline_write_history(sObject* nextin, sObject* nextout, sRunInfo* run
827867 return TRUE;
828868 }
829869
870+char* readline_filename_completion_null_generator(const char* a, int b)
871+{
872+ return NULL;
873+}
874+
875+BOOL cmd_readline_file_name_completion_null_generator(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
876+{
877+ rl_completion_entry_function = readline_filename_completion_null_generator;
878+
879+ return TRUE;
880+}
881+
830882 static int readline_macro(int count, int key)
831883 {
832884 stack_start_stack();
@@ -853,7 +905,7 @@ static int readline_macro(int count, int key)
853905 if(rcode == RCODE_BREAK) {
854906 fprintf(stderr, "invalid break. Not in a loop\n");
855907 }
856- else if(rcode == RCODE_RETURN) {
908+ else if(rcode & RCODE_RETURN) {
857909 fprintf(stderr, "invalid return. Not in a function\n");
858910 }
859911 else if(rcode == RCODE_EXIT) {
@@ -880,53 +932,6 @@ static int readline_macro(int count, int key)
880932 return 0;
881933 }
882934
883-static int skip_quoted(const char *s, int i, char q)
884-{
885- while(s[i] && s[i]!=q)
886- {
887- if(s[i]=='\\' && s[i+1]) i++;
888- i++;
889- }
890- if(s[i]) i++;
891- return i;
892-}
893-
894-static int lftp_char_is_quoted(const char *string, int eindex)
895-{
896- int i, pass_next;
897-
898- for (i = pass_next = 0; i <= eindex; i++)
899- {
900- if (pass_next)
901- {
902- pass_next = 0;
903- if (i >= eindex)
904- return 1;
905- continue;
906- }
907- else if (string[i] == '"' || string[i] == '\'')
908- {
909- char quote = string[i];
910- i = skip_quoted (string, ++i, quote);
911- if (i > eindex)
912- return 1;
913- i--;
914- }
915- else if (string[i] == '\\')
916- {
917- pass_next = 1;
918- continue;
919- }
920- }
921- return (0);
922-}
923-
924-char* readline_filename_completion_null_generator(const char* a, int b)
925-{
926- return NULL;
927-}
928-
929-
930935 enum { COMPLETE_DQUOTE,COMPLETE_SQUOTE,COMPLETE_BSQUOTE };
931936 #define completion_quoting_style COMPLETE_BSQUOTE
932937
@@ -946,16 +951,16 @@ double_quote (char *string)
946951 {
947952 switch (c)
948953 {
949- case '$':
950- case '`':
951- if(!shell_cmd)
952- goto def;
953- case '"':
954- case '\\':
955- *r++ = '\\';
956- default: def:
957- *r++ = c;
958- break;
954+ case '$':
955+ case '`':
956+ if(!shell_cmd)
957+ goto def;
958+ case '"':
959+ case '\\':
960+ *r++ = '\\';
961+ default: def:
962+ *r++ = c;
963+ break;
959964 }
960965 }
961966
@@ -980,11 +985,11 @@ single_quote (char *string)
980985 *r++ = c;
981986
982987 if (c == '\'')
983- {
984- *r++ = '\\'; // insert escaped single quote
985- *r++ = '\'';
986- *r++ = '\''; // start new quoted string
987- }
988+ {
989+ *r++ = '\\'; // insert escaped single quote
990+ *r++ = '\'';
991+ *r++ = '\''; // start new quoted string
992+ }
988993 }
989994
990995 *r++ = '\'';
@@ -994,7 +999,7 @@ single_quote (char *string)
994999 }
9951000
9961001 static BOOL quote_glob;
997-static BOOL inhibit_tilde;
1002+//static BOOL inhibit_tilde = 0;
9981003
9991004 static char *
10001005 backslash_quote (char *string)
@@ -1007,36 +1012,43 @@ backslash_quote (char *string)
10071012 for (r = result, s = string; s && (c = *s); s++)
10081013 {
10091014 switch (c)
1010- {
1011- case '(': case ')':
1012- case '{': case '}': // reserved words
1013- case '^':
1014- case '$': case '`': // expansion chars
1015- if(!shell_cmd)
1016- goto def;
1017- case '*': case '[': case '?': case ']': //globbing chars
1018- if(!shell_cmd && !quote_glob)
1019- goto def;
1020- case ' ': case '\t': case '\n': // IFS white space
1021- case '"': case '\'': case '\\': // quoting chars
1022- case '|': case '&': case ';': // shell metacharacters
1023- case '<': case '>': case '!':
1024- *r++ = '\\';
1025- *r++ = c;
1026- break;
1027- case '~': // tilde expansion
1028- if (s == string && inhibit_tilde)
1029- *r++ = '.', *r++ = '/';
1030- goto def;
1031- case '#': // comment char
1032- if(!shell_cmd)
1033- goto def;
1034- if (s == string)
1035- *r++ = '\\';
1036- default: def:
1037- *r++ = c;
1038- break;
1039- }
1015+ {
1016+ case '(': case ')':
1017+ case '{': case '}': // reserved words
1018+ case '^':
1019+ case '$': case '`': // expansion chars
1020+ case '*': case '[': case '?': case ']': //globbing chars
1021+ case ' ': case '\t': case '\n': // IFS white space
1022+ case '"': case '\'': case '\\': // quoting chars
1023+ case '|': case '&': case ';': // shell metacharacters
1024+ case '<': case '>': case '!':
1025+ case '%':
1026+ case '#':
1027+ *r++ = '\\';
1028+ *r++ = c;
1029+ break;
1030+ case '~': // tilde expansion
1031+ //*r++ = '\\';
1032+ *r++ = c;
1033+ break;
1034+/*
1035+ if (s == string) {
1036+ goto def;
1037+
1038+ }
1039+*/
1040+ break;
1041+/*
1042+ case '#': // comment char
1043+ if(!shell_cmd)
1044+ goto def;
1045+ if (s == string)
1046+ *r++ = '\\';
1047+*/
1048+ default: def:
1049+ *r++ = c;
1050+ break;
1051+ }
10401052 }
10411053
10421054 *r = '\0';
@@ -1054,13 +1066,13 @@ quote_word_break_chars (char *text)
10541066 for (s = text, r = ret; *s; s++)
10551067 {
10561068 if (*s == '\\')
1057- {
1058- *r++ = '\\';
1059- *r++ = *++s;
1060- if (*s == '\0')
1061- break;
1062- continue;
1063- }
1069+ {
1070+ *r++ = '\\';
1071+ *r++ = *++s;
1072+ if (*s == '\0')
1073+ break;
1074+ continue;
1075+ }
10641076 if (strchr (rl_completer_word_break_characters, *s))
10651077 *r++ = '\\';
10661078 *r++ = *s;
@@ -1069,37 +1081,90 @@ quote_word_break_chars (char *text)
10691081 return ret;
10701082 }
10711083
1084+static char*
1085+bash_tilde_expand(char *s)
1086+{
1087+//puts("bash_tilde_expand");
1088+//sleep(1);
1089+ char* mtext = malloc(1024);
1090+ char* p = mtext;
1091+
1092+ s++; // ~
1093+
1094+ if(*s == '/') { // ~/
1095+ s++;
1096+
1097+ char* home = getenv("HOME");
1098+ while(*home) {
1099+ *p++ = *home++;
1100+ }
1101+ *p++ = '/';
1102+
1103+ while(*s) {
1104+ *p++ = *s++;
1105+ }
1106+ *p = 0;
1107+ }
1108+ else if(*s == 0) { // this may be never runned, paranoia
1109+ *p++ = '~';
1110+ *p = 0;
1111+ }
1112+ /// ~user/
1113+ else {
1114+ char* point = strstr(s, "/");
1115+ if(point) {
1116+ char* user_name = malloc(point -s + 1);
1117+ memcpy(user_name, s, point -s);
1118+ user_name[point -s] = 0;
1119+
1120+ struct passwd* pwd = getpwnam(user_name);
1121+
1122+ char* p2 = pwd->pw_dir;
1123+
1124+ while(*p2) {
1125+ *p++ = *p2++;
1126+ }
1127+ *p++ = '/';
1128+
1129+ s = point;
1130+ s++;
1131+ while(*s) {
1132+ *p++ = *s++;
1133+ }
1134+ *p = 0;
1135+
1136+ free(user_name);
1137+ }
1138+ else {
1139+ *p++ = '~';
1140+ while(*s) {
1141+ *p++ = *s++;
1142+ }
1143+ *p = 0;
1144+ }
1145+ }
1146+
1147+ return mtext;
1148+}
1149+
10721150 static char *
10731151 bash_quote_filename (char *s, int rtype, char *qcp)
10741152 {
1153+//puts("bash_quote_filename");
10751154 char *rtext, *mtext, *ret;
10761155 int rlen, cs;
10771156
10781157 rtext = (char *)NULL;
10791158
10801159 mtext = s;
1081-#if 0
1082- if (mtext[0] == '~' && rtype == SINGLE_MATCH)
1160+ if (mtext[0] == '~') // && rtype == SINGLE_MATCH)
10831161 mtext = bash_tilde_expand (s);
1084-#endif
10851162
10861163 cs = completion_quoting_style;
10871164 if (*qcp == '"')
10881165 cs = COMPLETE_DQUOTE;
10891166 else if (*qcp == '\'')
10901167 cs = COMPLETE_SQUOTE;
1091-#if defined (BANG_HISTORY)
1092- else if (*qcp == '\0' && history_expansion && cs == COMPLETE_DQUOTE &&
1093- history_expansion_inhibited == 0 && strchr (mtext, '!'))
1094- cs = COMPLETE_BSQUOTE;
1095-
1096- if (*qcp == '"' && history_expansion && cs == COMPLETE_DQUOTE &&
1097- history_expansion_inhibited == 0 && strchr (mtext, '!'))
1098- {
1099- cs = COMPLETE_BSQUOTE;
1100- *qcp = '\0';
1101- }
1102-#endif
11031168
11041169 switch (cs)
11051170 {
@@ -1147,12 +1212,12 @@ bash_dequote_filename (const char *text, int quote_char)
11471212 for (quoted = quote_char, p = text, r = ret; p && *p; p++)
11481213 {
11491214 if (*p == '\\')
1150- {
1151- *r++ = *++p;
1152- if (*p == '\0')
1153- break;
1154- continue;
1155- }
1215+ {
1216+ *r++ = *++p;
1217+ if (*p == '\0')
1218+ break;
1219+ continue;
1220+ }
11561221 if (quoted && *p == quoted)
11571222 {
11581223 quoted = 0;
@@ -1169,25 +1234,61 @@ bash_dequote_filename (const char *text, int quote_char)
11691234 return ret;
11701235 }
11711236
1237+static int skip_quoted(const char *s, int i, char q)
1238+{
1239+ while(s[i] && s[i]!=q)
1240+ {
1241+ if(s[i]=='\\' && s[i+1]) i++;
1242+ i++;
1243+ }
1244+ if(s[i]) i++;
1245+ return i;
1246+}
1247+
1248+static int lftp_char_is_quoted(const char *string, int eindex)
1249+{
1250+ int i, pass_next;
1251+
1252+ for (i = pass_next = 0; i <= eindex; i++)
1253+ {
1254+ if (pass_next)
1255+ {
1256+ pass_next = 0;
1257+ if (i >= eindex) {
1258+ return 1;
1259+ }
1260+ continue;
1261+ }
1262+ else if (string[i] == '"' || string[i] == '\'')
1263+ {
1264+ char quote = string[i];
1265+ i = skip_quoted (string, ++i, quote);
1266+ if (i > eindex) {
1267+ return 1;
1268+ }
1269+ i--;
1270+ }
1271+ else if (string[i] == '\\')
1272+ {
1273+ pass_next = 1;
1274+ continue;
1275+ }
1276+ }
1277+ return (0);
1278+}
1279+
11721280 void xyzsh_readline_init(BOOL runtime_script)
11731281 {
11741282 rl_attempted_completion_function = readline_on_complete;
1175-// rl_completion_entry_function = readline_filename_completion_null_generator;
1283+ //rl_completion_entry_function = readline_filename_completion_null_generator;
11761284 rl_completer_quote_characters = "\"'";
1177- rl_completer_word_break_characters = " \t\n\"'|!&;()$%<>=";
1285+ rl_completer_word_break_characters = " \t\n\"'|!&;()$<>=";
11781286 rl_completion_append_character= ' ';
1179- rl_filename_quote_characters = " \t\n\"'|!&;()$%<>:";
1287+ rl_filename_quote_characters = " \t\n\"'|!&;()$%<>[]~";
11801288 rl_filename_quoting_function = bash_quote_filename;
11811289 rl_filename_dequoting_function = (rl_dequote_func_t*)bash_dequote_filename;
1182-
11831290 rl_char_is_quoted_p = (rl_linebuf_func_t*)lftp_char_is_quoted;
11841291
1185-/*
1186- rl_comrl_filename_quote_characters = " \t\n\\'\"()$&|>";
1187- rl_completer_quote_characters = " \t\n\\'\"()$&|>";
1188- rl_basic_quote_characters = " \t\n\"'|!&;()$";
1189-*/
1190-
11911292 rl_bind_key('x'-'a'+1, readline_macro);
11921293 }
11931294
--- /dev/null
+++ b/src/readline.c.bak
@@ -0,0 +1,1243 @@
1+#include "config.h"
2+#include "xyzsh/xyzsh.h"
3+
4+#include <string.h>
5+#include <strings.h>
6+#include <stdlib.h>
7+#include <stdio.h>
8+#include <unistd.h>
9+#include <errno.h>
10+#include <fcntl.h>
11+#include <libgen.h>
12+#include <dirent.h>
13+#include <readline/readline.h>
14+#include <readline/history.h>
15+#include <oniguruma.h>
16+#include <sys/stat.h>
17+#include <sys/types.h>
18+#include <pwd.h>
19+#include <limits.h>
20+
21+static sObject* gReadlineBlock;
22+static sObject* gCompletionArray;
23+
24+static BOOL name_sort(void* left, void* right)
25+{
26+ char* lfname = left;
27+ char* rfname = right;
28+
29+ if(strcmp(lfname, ".") == 0) return TRUE;
30+ if(strcmp(lfname, "..") == 0) {
31+ if(strcmp(rfname, ".") == 0) return FALSE;
32+
33+ return TRUE;
34+ }
35+ if(strcmp(rfname, ".") == 0) return FALSE;
36+ if(strcmp(rfname, "..") == 0) return FALSE;
37+
38+ return strcasecmp(lfname, rfname) < 0;
39+}
40+
41+static sObject* gUserCompletionNextout;
42+static sObject* gReadlineCurrentObject;
43+
44+static char* message_completion(const char* text, int stat)
45+{
46+ static int index, wordlen;
47+
48+ if(stat == 0) {
49+ sStatment* statment = SBLOCK(gReadlineBlock).mStatments + SBLOCK(gReadlineBlock).mStatmentsNum - 1;
50+
51+ sCommand* command = statment->mCommands + statment->mCommandsNum-1;
52+
53+ gCompletionArray = VECTOR_NEW_STACK(16);
54+
55+ sObject* current = gReadlineCurrentObject;
56+ sObject* object;
57+
58+ sObject* messages = STRING_NEW_STACK("");
59+
60+ while(1) {
61+ object = uobject_item(current, command->mMessages[0]);
62+ if(object || current == gRootObject) break;
63+ current = SUOBJECT((current)).mParent;
64+ if(current == NULL) break;
65+ }
66+
67+ string_put(messages, command->mMessages[0]);
68+ string_push_back(messages, "::");
69+
70+ if(object && TYPE(object) == T_UOBJECT) {
71+ int i;
72+ for(i=1; i<command->mMessagesNum; i++) {
73+ object = uobject_item(object, command->mMessages[i]);
74+ if(object == NULL || TYPE(object) != T_UOBJECT) break;
75+ string_push_back(messages, command->mMessages[i]);
76+ string_push_back(messages, "::");
77+ }
78+
79+ if(object && TYPE(object) == T_UOBJECT) {
80+ uobject_it* it = uobject_loop_begin(object);
81+ while(it) {
82+ char* key = uobject_loop_key(it);
83+ sObject* item = uobject_loop_item(it);
84+
85+ sObject* candidate = STRING_NEW_STACK(string_c_str(messages));
86+ string_push_back(candidate, key);
87+
88+ if(TYPE(item) == T_UOBJECT) {
89+ if(uobject_item(item, "main")) {
90+ vector_add(gCompletionArray, string_c_str(candidate));
91+ }
92+ else {
93+ sObject* candidate2 = STRING_NEW_STACK(string_c_str(messages));
94+ string_push_back(candidate2, key);
95+ string_push_back(candidate2, "::");
96+
97+ vector_add(gCompletionArray, string_c_str(candidate2));
98+ }
99+ }
100+ else {
101+ vector_add(gCompletionArray, string_c_str(candidate));
102+ }
103+
104+ it = uobject_loop_next(it);
105+ }
106+
107+ vector_sort(gCompletionArray, name_sort);
108+ }
109+ }
110+
111+ wordlen = strlen(text);
112+ index = 0;
113+ }
114+
115+ while(index < vector_count(gCompletionArray)) {
116+ char* candidate = vector_item(gCompletionArray, index);
117+ index++;
118+
119+ if(!strncmp(text, candidate, wordlen)) {
120+ int len = strlen(candidate);
121+ if(len > 2 && candidate[len-2] == ':' && candidate[len-1] == ':') {
122+ rl_completion_append_character = 0;
123+ }
124+ else {
125+ rl_completion_append_character = ' ';
126+ }
127+ return strdup(candidate);
128+ }
129+ }
130+
131+ return NULL;
132+}
133+
134+static char* all_program_completion(const char* text, int stat)
135+{
136+ static int index, wordlen;
137+
138+ if(stat == 0) {
139+ gCompletionArray = VECTOR_NEW_STACK(16);
140+ sObject* hash = HASH_NEW_STACK(16);
141+
142+ sObject* current = gReadlineCurrentObject;
143+ while(1) {
144+ uobject_it* it = uobject_loop_begin(current);
145+ while(it) {
146+ char* key = uobject_loop_key(it);
147+ sObject* object = uobject_loop_item(it);
148+
149+ if(hash_item(hash, key) == NULL) {
150+ hash_put(hash, key, object);
151+
152+ sObject* candidate = STRING_NEW_STACK(uobject_loop_key(it));
153+ if(TYPE(object) == T_UOBJECT) {
154+ if(uobject_item(object, "main")) {
155+ vector_add(gCompletionArray, string_c_str(candidate));
156+ }
157+ else {
158+ sObject* candidate2 = STRING_NEW_STACK(uobject_loop_key(it));
159+ string_push_back(candidate2, "::");
160+ vector_add(gCompletionArray, string_c_str(candidate2));
161+ }
162+ }
163+ else {
164+ vector_add(gCompletionArray, string_c_str(candidate));
165+ }
166+ }
167+
168+ it = uobject_loop_next(it);
169+ }
170+
171+ if(current == gRootObject) break;
172+
173+ current = SUOBJECT(current).mParent;
174+
175+ if(current == NULL) break;
176+ }
177+ vector_sort(gCompletionArray, name_sort);
178+
179+ wordlen = strlen(text);
180+ index = 0;
181+ }
182+
183+ while(index < vector_count(gCompletionArray)) {
184+ char* candidate = vector_item(gCompletionArray, index);
185+ index++;
186+
187+ return strdup(candidate);
188+ }
189+
190+ return NULL;
191+}
192+
193+static char* program_completion(const char* text, int stat)
194+{
195+ static int index, wordlen;
196+
197+ if(stat == 0) {
198+ gCompletionArray = VECTOR_NEW_STACK(16);
199+ sObject* hash = HASH_NEW_STACK(16);
200+
201+ sObject* current = gReadlineCurrentObject;
202+ while(1) {
203+ uobject_it* it = uobject_loop_begin(current);
204+ while(it) {
205+ char* key = uobject_loop_key(it);
206+ sObject* object = uobject_loop_item(it);
207+
208+ if(hash_item(hash, key) == NULL) {
209+ hash_put(hash, key, object);
210+
211+ sObject* candidate = STRING_NEW_STACK(uobject_loop_key(it));
212+ if(TYPE(object) == T_UOBJECT) {
213+ if(uobject_item(object, "main")) {
214+ vector_add(gCompletionArray, string_c_str(candidate));
215+ }
216+ else {
217+ sObject* candidate2 = STRING_NEW_STACK(uobject_loop_key(it));
218+ string_push_back(candidate2, "::");
219+ vector_add(gCompletionArray, string_c_str(candidate2));
220+ }
221+ }
222+ else {
223+ vector_add(gCompletionArray, string_c_str(candidate));
224+ }
225+ }
226+
227+ it = uobject_loop_next(it);
228+ }
229+
230+ if(current == gRootObject) break;
231+
232+ current = SUOBJECT(current).mParent;
233+
234+ if(current == NULL) break;
235+ }
236+ vector_sort(gCompletionArray, name_sort);
237+
238+ wordlen = strlen(text);
239+ index = 0;
240+ }
241+
242+ while(index < vector_count(gCompletionArray)) {
243+ char* candidate = vector_item(gCompletionArray, index);
244+ index++;
245+
246+ if(!strncmp(text, candidate, wordlen)) {
247+ int len = strlen(candidate);
248+ if(len > 2 && candidate[len-2] == ':' && candidate[len-1] == ':') {
249+ rl_completion_append_character = 0;
250+ }
251+ else {
252+ rl_completion_append_character = ' ';
253+ }
254+ return strdup(candidate);
255+ }
256+ }
257+
258+ return NULL;
259+}
260+
261+static char* user_completion(const char* text, int stat)
262+{
263+ static int index, wordlen;
264+ static char text2[1024];
265+
266+ if(stat == 0) {
267+ gCompletionArray = VECTOR_NEW_STACK(16);
268+
269+ int i;
270+ for(i=0; i<vector_count(SFD(gUserCompletionNextout).mLines); i++) {
271+ sObject* candidate = STRING_NEW_STACK(vector_item(SFD(gUserCompletionNextout).mLines, i));
272+ string_chomp(candidate);
273+ vector_add(gCompletionArray, string_c_str(candidate));
274+ }
275+
276+ vector_sort(gCompletionArray, name_sort);
277+
278+ wordlen = strlen(text);
279+ index = 0;
280+ }
281+
282+ while(index < vector_count(gCompletionArray)) {
283+ char* candidate = vector_item(gCompletionArray, index);
284+ index++;
285+
286+ if(!strncmp(text, candidate, wordlen)) {
287+ int l = strlen(candidate);
288+ if((l > 2 && candidate[l-2] == ':' && candidate[l-1] == ':' )
289+ || (l > 1 && candidate[l-1] == '/') )
290+ {
291+ rl_completion_append_character = 0;
292+ }
293+ else {
294+ rl_completion_append_character = ' ';
295+ }
296+ return strdup(candidate);
297+ }
298+ }
299+
300+ return NULL;
301+}
302+
303+static char* redirect_completion(const char* text, int stat)
304+{
305+ static int index, wordlen;
306+
307+ if(stat == 0) {
308+ gCompletionArray = VECTOR_NEW_STACK(16);
309+
310+ vector_add(gCompletionArray, STRING_NEW_STACK("%>"));
311+ vector_add(gCompletionArray, STRING_NEW_STACK("%>>"));
312+
313+ vector_sort(gCompletionArray, name_sort);
314+
315+ wordlen = strlen(text);
316+ index = 0;
317+ }
318+
319+ while(index < vector_count(gCompletionArray)) {
320+ char* candidate = string_c_str((sObject*)vector_item(gCompletionArray, index));
321+ index++;
322+
323+ if(!strncmp(text, candidate, wordlen)) {
324+ rl_completion_append_character = 0;
325+ return strdup(candidate);
326+ }
327+ }
328+
329+ return NULL;
330+}
331+
332+#if !HAVE_DECL_ENVIRON
333+ extern char **environ;
334+#endif
335+
336+static char* env_completion(const char* text, int stat_)
337+{
338+ static int index, wordlen;
339+
340+ if(stat_ == 0) {
341+ gCompletionArray = VECTOR_NEW_STACK(16);
342+ sObject* hash = HASH_NEW_STACK(16);
343+
344+ char** p;
345+ for(p = environ; *p; p++) {
346+ char env_name[PATH_MAX];
347+
348+ char* p2 = env_name;
349+ char* p3 = *p;
350+
351+ while(*p3 != 0 && *p3 != '=') {
352+ *p2++ = *p3++;
353+ }
354+
355+ char* env = getenv(*p);
356+ struct stat estat;
357+ if(stat(env, &estat) >= 0) {
358+ if(S_ISDIR(estat.st_mode)) {
359+ *p2++ = '/';
360+ }
361+ }
362+ *p2 = 0;
363+
364+ sObject* string = STRING_NEW_STACK(env_name);
365+ vector_add(gCompletionArray, string_c_str(string));
366+ }
367+
368+ if(strstr((char*)text, "::")) {
369+ sObject* current = gReadlineCurrentObject;
370+ sObject* prefix = STRING_NEW_STACK("");
371+ sObject* name = STRING_NEW_STACK("");
372+
373+ split_prefix_of_object_and_name2(&current, prefix, name, (char*)text, gReadlineCurrentObject);
374+
375+ if(current && TYPE(current) == T_UOBJECT) {
376+ uobject_it* it = uobject_loop_begin(current);
377+ while(it) {
378+ char* key = uobject_loop_key(it);
379+ sObject* object = uobject_loop_item(it);
380+
381+ if(TYPE(object) == T_UOBJECT) {
382+ sObject* candidate = STRING_NEW_STACK("");
383+ string_push_back(candidate, string_c_str(prefix));
384+ string_push_back(candidate, key);
385+ string_push_back(candidate, "::");
386+
387+ vector_add(gCompletionArray, string_c_str(candidate));
388+ }
389+ else if(TYPE(object) == T_STRING || TYPE(object) == T_VECTOR || TYPE(object) == T_HASH) {
390+ sObject* candidate = STRING_NEW_STACK("");
391+ string_push_back(candidate, string_c_str(prefix));
392+ string_push_back(candidate, key);
393+
394+ vector_add(gCompletionArray, string_c_str(candidate));
395+ }
396+
397+ it = uobject_loop_next(it);
398+ }
399+ }
400+ }
401+ else {
402+ sObject* current = gReadlineCurrentObject;
403+
404+ while(1) {
405+ uobject_it* it = uobject_loop_begin(current);
406+ while(it) {
407+ char* key = uobject_loop_key(it);
408+ sObject* object = uobject_loop_item(it);
409+
410+ if(TYPE(object) == T_UOBJECT) {
411+ sObject* candidate = STRING_NEW_STACK("");
412+ string_push_back(candidate, key);
413+ string_push_back(candidate, "::");
414+
415+ vector_add(gCompletionArray, string_c_str(candidate));
416+ }
417+ else if(TYPE(object) == T_STRING || TYPE(object) == T_VECTOR || TYPE(object) == T_HASH) {
418+ sObject* candidate = STRING_NEW_STACK("");
419+ string_push_back(candidate, key);
420+
421+ vector_add(gCompletionArray, string_c_str(candidate));
422+ }
423+
424+ it = uobject_loop_next(it);
425+ }
426+
427+ if(current == gRootObject) break;
428+
429+ current = SUOBJECT(current).mParent;
430+
431+ if(current == NULL) break;
432+ }
433+ }
434+
435+ vector_sort(gCompletionArray, name_sort);
436+
437+ wordlen = strlen(text);
438+ index = 0;
439+ }
440+
441+ while(index < vector_count(gCompletionArray)) {
442+ char* candidate = vector_item(gCompletionArray, index);
443+ index++;
444+
445+ if(!strncmp(text, candidate, wordlen)) {
446+ int len = strlen(candidate);
447+ if(len > 2 && candidate[len-2] == ':' && candidate[len-1] == ':') {
448+ rl_completion_append_character = 0;
449+ }
450+ else {
451+ rl_completion_append_character = ' ';
452+ }
453+ return strdup(candidate);
454+ }
455+ }
456+
457+ return NULL;
458+}
459+
460+static void get_current_completion_object(sObject** completion_object, sObject** current_object)
461+{
462+ if(*current_object && *current_object != gRootObject) {
463+ sObject* parent_object = SUOBJECT(*current_object).mParent;
464+ get_current_completion_object(completion_object, &parent_object);
465+ if(*completion_object) *completion_object = uobject_item(*completion_object, SUOBJECT(*current_object).mName);
466+ }
467+}
468+
469+static sObject* access_object_compl(char* name, sObject** current)
470+{
471+ sObject* object;
472+
473+ while(1) {
474+ object = uobject_item(*current, name);
475+
476+ if(object || *current == gCompletionObject) { return object; }
477+
478+ *current = SUOBJECT((*current)).mParent;
479+
480+ if(*current == NULL) return NULL;;
481+ }
482+}
483+
484+char** readline_on_complete(const char* text, int start, int end)
485+{
486+ stack_start_stack();
487+
488+ gReadlineBlock = BLOCK_NEW_STACK();
489+
490+ sObject* cmdline = STRING_NEW_STACK("");
491+ string_push_back3(cmdline, rl_line_buffer, end);
492+
493+ int sline = 1;
494+ gReadlineCurrentObject = gCurrentObject;
495+ BOOL result = parse(string_c_str(cmdline), "readline", &sline, gReadlineBlock, &gReadlineCurrentObject);
496+
497+ /// in the block? get the block
498+ if(!result && (SBLOCK(gReadlineBlock).mCompletionFlags & (COMPLETION_FLAGS_BLOCK|COMPLETION_FLAGS_ENV_BLOCK))) {
499+ while(1) {
500+ if(SBLOCK(gReadlineBlock).mStatmentsNum > 0) {
501+ sStatment* statment = SBLOCK(gReadlineBlock).mStatments + SBLOCK(gReadlineBlock).mStatmentsNum - 1;
502+
503+ if(statment->mCommandsNum > 0) {
504+ sCommand* command = statment->mCommands + statment->mCommandsNum-1;
505+
506+ int num = SBLOCK(gReadlineBlock).mCompletionFlags & COMPLETION_FLAGS_BLOCK_OR_ENV_NUM;
507+
508+ if(num > 0) {
509+ if(SBLOCK(gReadlineBlock).mCompletionFlags & COMPLETION_FLAGS_ENV_BLOCK) {
510+ sEnv* env = command->mEnvs + num -1;
511+ gReadlineBlock = env->mBlock;
512+ }
513+ else {
514+ gReadlineBlock = *(command->mBlocks + num -1);
515+ }
516+ }
517+ else {
518+ break;
519+ }
520+ }
521+ else {
522+ break;
523+ }
524+ }
525+ else {
526+ break;
527+ }
528+ }
529+ }
530+
531+ if(SBLOCK(gReadlineBlock).mCompletionFlags & COMPLETION_FLAGS_TILDA) {
532+ char** result = rl_completion_matches(text, rl_username_completion_function);
533+ stack_end_stack();
534+ return result;
535+ }
536+ else if(SBLOCK(gReadlineBlock).mStatmentsNum == 0) {
537+ char** result = rl_completion_matches(text, all_program_completion);
538+ stack_end_stack();
539+ return result;
540+ }
541+ else if(SBLOCK(gReadlineBlock).mCompletionFlags & COMPLETION_FLAGS_AFTER_REDIRECT) {
542+ stack_end_stack();
543+ return NULL;
544+ }
545+ else {
546+ sStatment* statment = SBLOCK(gReadlineBlock).mStatments + SBLOCK(gReadlineBlock).mStatmentsNum - 1;
547+
548+ if(statment->mCommandsNum == 0 || SBLOCK(gReadlineBlock).mCompletionFlags & (COMPLETION_FLAGS_COMMAND_END|COMPLETION_FLAGS_STATMENT_END|COMPLETION_FLAGS_STATMENT_HEAD)) {
549+ char** result = rl_completion_matches(text, all_program_completion);
550+ stack_end_stack();
551+ return result;
552+ }
553+ else {
554+ sCommand* command = statment->mCommands + statment->mCommandsNum-1;
555+
556+ /// get user completion ///
557+ sObject* ucompletion;
558+ if(command->mArgsNum > 0) {
559+ sObject* completion_object = gCompletionObject;
560+ sObject* current_object = gCurrentObject;
561+
562+ get_current_completion_object(&completion_object, &current_object);
563+
564+ if(completion_object == NULL) completion_object = gCompletionObject;
565+
566+ sObject* object;
567+ if(command->mMessagesNum > 0) {
568+ sObject* reciever = completion_object;
569+ object = access_object_compl(command->mMessages[0], &reciever);
570+
571+ int i;
572+ for(i=1; i<command->mMessagesNum; i++) {
573+ if(object && TYPE(object) == T_UOBJECT) {
574+ object = uobject_item(object, command->mMessages[i]);
575+ }
576+ else {
577+ break;
578+ }
579+ }
580+
581+ if(object && TYPE(object) == T_UOBJECT) {
582+ ucompletion = uobject_item(object, command->mArgs[0]);
583+
584+ if(ucompletion == NULL) {
585+ ucompletion = uobject_item(object, "__all__");;
586+ }
587+ }
588+ else {
589+ ucompletion = NULL;
590+ }
591+ }
592+ else {
593+ sObject* reciever = completion_object;
594+ ucompletion = access_object_compl(command->mArgs[0], &reciever);
595+
596+ if(ucompletion == NULL) {
597+ reciever = completion_object;
598+ ucompletion = access_object_compl("__all__", &reciever);
599+ }
600+ }
601+ }
602+ else {
603+ ucompletion = NULL;
604+ }
605+
606+ /// go ///
607+ if(SBLOCK(gReadlineBlock).mCompletionFlags & COMPLETION_FLAGS_ENV) {
608+ char** result = rl_completion_matches(text, env_completion);
609+ stack_end_stack();
610+ return result;
611+ }
612+ else if(command->mArgsNum == 0
613+ || command->mArgsNum == 1 && SBLOCK(gReadlineBlock).mCompletionFlags & COMPLETION_FLAGS_INPUTING_COMMAND_NAME)
614+ {
615+ if(command->mMessagesNum > 0) {
616+ char** result = rl_completion_matches(text, message_completion);
617+ stack_end_stack();
618+ return result;
619+ }
620+ else {
621+ char** result = rl_completion_matches(text, program_completion);
622+ stack_end_stack();
623+ return result;
624+ }
625+ }
626+ else if(ucompletion && TYPE(ucompletion) == T_COMPLETION) {
627+ sObject* nextin = FD_NEW_STACK();
628+ if(!fd_write(nextin, string_c_str(cmdline), string_length(cmdline))) {
629+ stack_end_stack();
630+ return NULL;
631+ }
632+ sObject* nextout = FD_NEW_STACK();
633+
634+ sObject* fun = FUN_NEW_STACK(NULL);
635+ sObject* stackframe = UOBJECT_NEW_GC(8, gXyzshObject, "_stackframe", FALSE);
636+ vector_add(gStackFrames, stackframe);
637+ //uobject_init(stackframe);
638+ SFUN(fun).mLocalObjects = stackframe;
639+
640+ sObject* argv = VECTOR_NEW_GC(16, FALSE);
641+ if(command->mArgsNum == 1) {
642+ vector_add(argv, STRING_NEW_GC(command->mArgs[0], FALSE));
643+ vector_add(argv, STRING_NEW_GC("", FALSE));
644+ }
645+ else if(command->mArgsNum > 1) {
646+ vector_add(argv, STRING_NEW_GC(command->mArgs[0], FALSE));
647+
648+ /// if parser uses PARSER_MAGIC_NUMBER_OPTION, convert it
649+ char* str = command->mArgs[command->mArgsNum-1];
650+ char* new_str = MALLOC(strlen(str) + 1);
651+ xstrncpy(new_str, str, strlen(str) + 1);
652+ if(new_str[0] == PARSER_MAGIC_NUMBER_OPTION) {
653+ new_str[0] = '-';
654+ }
655+ vector_add(argv, STRING_NEW_GC(new_str, FALSE));
656+ FREE(new_str);
657+ }
658+ else {
659+ vector_add(argv, STRING_NEW_GC("", FALSE));
660+ vector_add(argv, STRING_NEW_GC("", FALSE));
661+ }
662+ uobject_put(SFUN(fun).mLocalObjects, "ARGV", argv);
663+
664+ int rcode = 0;
665+ xyzsh_set_signal();
666+ if(!run(SCOMPLETION(ucompletion).mBlock, nextin, nextout, &rcode, gReadlineCurrentObject, fun)) {
667+ readline_signal();
668+ fprintf(stderr, "\nrun time error\n");
669+ fprintf(stderr, "%s", string_c_str(gErrMsg));
670+ (void)vector_pop_back(gStackFrames);
671+ stack_end_stack();
672+ return NULL;
673+ }
674+ (void)vector_pop_back(gStackFrames);
675+ readline_signal();
676+
677+ eLineField lf;
678+ if(fd_guess_lf(nextout, &lf)) {
679+ fd_split(nextout, lf);
680+ } else {
681+ fd_split(nextout, kLF);
682+ }
683+
684+ gUserCompletionNextout = nextout;
685+ char** result = rl_completion_matches(text, user_completion);
686+ stack_end_stack();
687+ return result;
688+ }
689+ }
690+ }
691+
692+ stack_end_stack();
693+ return NULL;
694+}
695+
696+BOOL cmd_completion(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
697+{
698+ if(runinfo->mArgsNumRuntime >= 2) {
699+ /// input ///
700+ if(runinfo->mBlocksNum == 1) {
701+ sObject* block = runinfo->mBlocks[0];
702+
703+ int i;
704+ for(i=1; i<runinfo->mArgsNumRuntime; i++) {
705+ sObject* object = gCompletionObject;
706+ sObject* prefix = STRING_NEW_STACK("");
707+ sObject* name = STRING_NEW_STACK("");
708+
709+ split_prefix_of_object_and_name(&object, prefix, name, runinfo->mArgsRuntime[i]);
710+
711+ if(object && TYPE(object) == T_UOBJECT && string_c_str(name)[0] != 0) {
712+ uobject_put(object, string_c_str(name), COMPLETION_NEW_GC(block, FALSE));
713+ }
714+ else {
715+ err_msg("invalid variable name", runinfo->mSName, runinfo->mSLine, runinfo->mArgs[0]);
716+ return FALSE;
717+ }
718+ }
719+
720+ runinfo->mRCode = 0;
721+ }
722+ /// output ///
723+ else if(runinfo->mBlocksNum == 0) {
724+ int i;
725+ for(i=1; i<runinfo->mArgsNumRuntime; i++) {
726+ sObject* compl;
727+ if(!get_object_from_str(&compl, runinfo->mArgsRuntime[i], runinfo->mCurrentObject, runinfo->mRunningObject, runinfo)) {
728+ return FALSE;
729+ }
730+
731+ if(compl && TYPE(compl) == T_COMPLETION) {
732+ if(!run_object(compl, nextin, nextout, runinfo)) {
733+ return FALSE;
734+ }
735+ }
736+ else {
737+ err_msg("There is no object", runinfo->mSName, runinfo->mSLine, runinfo->mArgsRuntime[i]);
738+
739+ return FALSE;
740+ }
741+ }
742+
743+ runinfo->mRCode = 0;
744+ }
745+ }
746+
747+ return TRUE;
748+}
749+
750+BOOL cmd_readline_clear_screen(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
751+{
752+ mclear_immediately();
753+ rl_forced_update_display();
754+
755+ runinfo->mRCode = 0;
756+
757+ return TRUE;
758+}
759+
760+BOOL cmd_readline_point(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
761+{
762+ if(!runinfo->mFilter) {
763+ char buf[BUFSIZ];
764+ int n = snprintf(buf, BUFSIZ, "%d\n", rl_point);
765+ if(!fd_write(nextout, buf, n)) {
766+ sCommand* command = runinfo->mCommand;
767+ err_msg("signal interrupt", runinfo->mSName, runinfo->mSLine, command->mArgs[0]);
768+ runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
769+ return FALSE;
770+ }
771+
772+ runinfo->mRCode = 0;
773+ }
774+
775+ return TRUE;
776+}
777+
778+BOOL cmd_readline_point_move(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
779+{
780+ if(runinfo->mArgsNumRuntime == 2) {
781+ int n = atoi(runinfo->mArgsRuntime[1]);
782+
783+ if(n < 0) n += strlen(rl_line_buffer) + 1;
784+ if(n < 0) n = 0;
785+ if(n > strlen(rl_line_buffer)) n = strlen(rl_line_buffer);
786+
787+ rl_point = n;
788+
789+ runinfo->mRCode = 0;
790+ }
791+
792+ return TRUE;
793+}
794+
795+BOOL cmd_readline_insert_text(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
796+{
797+ if(runinfo->mArgsNumRuntime == 2) {
798+ (void)rl_insert_text(runinfo->mArgsRuntime[1]);
799+ puts("");
800+ rl_forced_update_display();
801+
802+ runinfo->mRCode = 0;
803+ }
804+
805+ return TRUE;
806+}
807+
808+BOOL cmd_readline_delete_text(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
809+{
810+ if(runinfo->mArgsNumRuntime == 3) {
811+ int n = atoi(runinfo->mArgsRuntime[1]);
812+ int m = atoi(runinfo->mArgsRuntime[2]);
813+ if(n < 0) n += strlen(rl_line_buffer) + 1;
814+ if(n < 0) n= 0;
815+ if(m < 0) m += strlen(rl_line_buffer) + 1;
816+ if(m < 0) m = 0;
817+ rl_point -= rl_delete_text(n, m);
818+ if(rl_point < 0) {
819+ rl_point = 0;
820+ }
821+ puts("");
822+ rl_forced_update_display();
823+
824+ runinfo->mRCode = 0;
825+ }
826+
827+ return TRUE;
828+}
829+
830+BOOL cmd_readline_replace_line(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
831+{
832+ if(runinfo->mArgsNumRuntime == 3) {
833+ (void)rl_replace_line(runinfo->mArgsRuntime[1], 0);
834+
835+ int n = atoi(runinfo->mArgsRuntime[2]);
836+
837+ if(n < 0) n += strlen(rl_line_buffer) + 1;
838+ if(n < 0) n = 0;
839+ if(n > strlen(rl_line_buffer)) n = strlen(rl_line_buffer);
840+
841+ rl_point = n;
842+ runinfo->mRCode = 0;
843+ }
844+
845+ return TRUE;
846+}
847+
848+BOOL cmd_readline_read_history(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
849+{
850+ if(runinfo->mArgsNumRuntime == 2) {
851+ char* fname = runinfo->mArgsRuntime[1];
852+ read_history(fname);
853+ runinfo->mRCode = 0;
854+ }
855+
856+ return TRUE;
857+}
858+
859+BOOL cmd_readline_write_history(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
860+{
861+ if(runinfo->mArgsNumRuntime == 2) {
862+ char* fname = runinfo->mArgsRuntime[1];
863+ write_history(fname);
864+ runinfo->mRCode = 0;
865+ }
866+
867+ return TRUE;
868+}
869+
870+char* readline_filename_completion_null_generator(const char* a, int b)
871+{
872+ return NULL;
873+}
874+
875+BOOL cmd_readline_file_name_completion_null_generator(sObject* nextin, sObject* nextout, sRunInfo* runinfo)
876+{
877+ rl_completion_entry_function = readline_filename_completion_null_generator;
878+
879+ return TRUE;
880+}
881+
882+static int readline_macro(int count, int key)
883+{
884+ stack_start_stack();
885+
886+ sObject* nextout2 = FD_NEW_STACK();
887+
888+ int rcode = 0;
889+ sObject* block = BLOCK_NEW_STACK();
890+ int sline = 1;
891+ if(parse("root::macro", "macro", &sline, block, NULL)) {
892+ xyzsh_set_signal();
893+
894+ sObject* fun = FUN_NEW_STACK(NULL);
895+ sObject* stackframe = UOBJECT_NEW_GC(8, gXyzshObject, "_stackframe", FALSE);
896+ vector_add(gStackFrames, stackframe);
897+ //uobject_init(stackframe);
898+ SFUN(fun).mLocalObjects = stackframe;
899+
900+ sObject* nextin2 = FD_NEW_STACK();
901+
902+ (void)fd_write(nextin2, rl_line_buffer, rl_point);
903+
904+ if(!run(block, nextin2, nextout2, &rcode, gRootObject, fun)) {
905+ if(rcode == RCODE_BREAK) {
906+ fprintf(stderr, "invalid break. Not in a loop\n");
907+ }
908+ else if(rcode == RCODE_RETURN) {
909+ fprintf(stderr, "invalid return. Not in a function\n");
910+ }
911+ else if(rcode == RCODE_EXIT) {
912+ }
913+ else {
914+ fprintf(stderr, "run time error\n");
915+ fprintf(stderr, "%s", string_c_str(gErrMsg));
916+ }
917+ }
918+ (void)vector_pop_back(gStackFrames);
919+ readline_signal();
920+ //xyzsh_restore_signal_default();
921+ }
922+ else {
923+ fprintf(stderr, "parser error\n");
924+ fprintf(stderr, "%s", string_c_str(gErrMsg));
925+ }
926+
927+ rl_insert_text(SFD(nextout2).mBuf);
928+ puts("");
929+ rl_forced_update_display();
930+ stack_end_stack();
931+
932+ return 0;
933+}
934+
935+enum { COMPLETE_DQUOTE,COMPLETE_SQUOTE,COMPLETE_BSQUOTE };
936+#define completion_quoting_style COMPLETE_BSQUOTE
937+
938+static BOOL shell_cmd;
939+
940+static char *
941+double_quote (char *string)
942+{
943+ register int c;
944+ char *result, *r, *s;
945+
946+ result = (char *)malloc (3 + (2 * strlen (string)));
947+ r = result;
948+ *r++ = '"';
949+
950+ for (s = string; s && (c = *s); s++)
951+ {
952+ switch (c)
953+ {
954+ case '$':
955+ case '`':
956+ if(!shell_cmd)
957+ goto def;
958+ case '"':
959+ case '\\':
960+ *r++ = '\\';
961+ default: def:
962+ *r++ = c;
963+ break;
964+ }
965+ }
966+
967+ *r++ = '"';
968+ *r = '\0';
969+
970+ return (result);
971+}
972+
973+static char *
974+single_quote (char *string)
975+{
976+ register int c;
977+ char *result, *r, *s;
978+
979+ result = (char *)malloc (3 + (4 * strlen (string)));
980+ r = result;
981+ *r++ = '\'';
982+
983+ for (s = string; s && (c = *s); s++)
984+ {
985+ *r++ = c;
986+
987+ if (c == '\'')
988+ {
989+ *r++ = '\\'; // insert escaped single quote
990+ *r++ = '\'';
991+ *r++ = '\''; // start new quoted string
992+ }
993+ }
994+
995+ *r++ = '\'';
996+ *r = '\0';
997+
998+ return (result);
999+}
1000+
1001+static BOOL quote_glob;
1002+static BOOL inhibit_tilde;
1003+
1004+static char *
1005+backslash_quote (char *string)
1006+{
1007+ int c;
1008+ char *result, *r, *s;
1009+
1010+ result = (char*)malloc (2 * strlen (string) + 1);
1011+
1012+ for (r = result, s = string; s && (c = *s); s++)
1013+ {
1014+ switch (c)
1015+ {
1016+ case '(': case ')':
1017+ case '{': case '}': // reserved words
1018+ case '^':
1019+ case '$': case '`': // expansion chars
1020+ if(!shell_cmd)
1021+ goto def;
1022+ case '*': case '[': case '?': case ']': //globbing chars
1023+ if(!shell_cmd && !quote_glob)
1024+ goto def;
1025+ case ' ': case '\t': case '\n': // IFS white space
1026+ case '"': case '\'': case '\\': // quoting chars
1027+ case '|': case '&': case ';': // shell metacharacters
1028+ case '<': case '>': case '!':
1029+ *r++ = '\\';
1030+ *r++ = c;
1031+ break;
1032+ case '~': // tilde expansion
1033+ if (s == string && inhibit_tilde)
1034+ *r++ = '.', *r++ = '/';
1035+ goto def;
1036+ case '#': // comment char
1037+ if(!shell_cmd)
1038+ goto def;
1039+ if (s == string)
1040+ *r++ = '\\';
1041+ default: def:
1042+ *r++ = c;
1043+ break;
1044+ }
1045+ }
1046+
1047+ *r = '\0';
1048+ return (result);
1049+}
1050+
1051+static char *
1052+quote_word_break_chars (char *text)
1053+{
1054+ char *ret, *r, *s;
1055+ int l;
1056+
1057+ l = strlen (text);
1058+ ret = (char*)malloc ((2 * l) + 1);
1059+ for (s = text, r = ret; *s; s++)
1060+ {
1061+ if (*s == '\\')
1062+ {
1063+ *r++ = '\\';
1064+ *r++ = *++s;
1065+ if (*s == '\0')
1066+ break;
1067+ continue;
1068+ }
1069+ if (strchr (rl_completer_word_break_characters, *s))
1070+ *r++ = '\\';
1071+ *r++ = *s;
1072+ }
1073+ *r = '\0';
1074+ return ret;
1075+}
1076+
1077+static char *
1078+bash_quote_filename (char *s, int rtype, char *qcp)
1079+{
1080+ char *rtext, *mtext, *ret;
1081+ int rlen, cs;
1082+
1083+ rtext = (char *)NULL;
1084+
1085+ mtext = s;
1086+#if 0
1087+ if (mtext[0] == '~' && rtype == SINGLE_MATCH)
1088+ mtext = bash_tilde_expand (s);
1089+#endif
1090+
1091+ cs = completion_quoting_style;
1092+ if (*qcp == '"')
1093+ cs = COMPLETE_DQUOTE;
1094+ else if (*qcp == '\'')
1095+ cs = COMPLETE_SQUOTE;
1096+#if defined (BANG_HISTORY)
1097+ else if (*qcp == '\0' && history_expansion && cs == COMPLETE_DQUOTE &&
1098+ history_expansion_inhibited == 0 && strchr (mtext, '!'))
1099+ cs = COMPLETE_BSQUOTE;
1100+
1101+ if (*qcp == '"' && history_expansion && cs == COMPLETE_DQUOTE &&
1102+ history_expansion_inhibited == 0 && strchr (mtext, '!'))
1103+ {
1104+ cs = COMPLETE_BSQUOTE;
1105+ *qcp = '\0';
1106+ }
1107+#endif
1108+
1109+ switch (cs)
1110+ {
1111+ case COMPLETE_DQUOTE:
1112+ rtext = double_quote (mtext);
1113+ break;
1114+ case COMPLETE_SQUOTE:
1115+ rtext = single_quote (mtext);
1116+ break;
1117+ case COMPLETE_BSQUOTE:
1118+ rtext = backslash_quote (mtext);
1119+ break;
1120+ }
1121+
1122+ if (mtext != s)
1123+ free (mtext);
1124+
1125+ if (rtext && cs == COMPLETE_BSQUOTE)
1126+ {
1127+ mtext = quote_word_break_chars (rtext);
1128+ free (rtext);
1129+ rtext = mtext;
1130+ }
1131+
1132+ rlen = strlen (rtext);
1133+ ret = (char*)malloc (rlen + 1);
1134+ strcpy (ret, rtext);
1135+
1136+ if (rtype == MULT_MATCH && cs != COMPLETE_BSQUOTE)
1137+ ret[rlen - 1] = '\0';
1138+ free (rtext);
1139+ return ret;
1140+}
1141+
1142+static char *
1143+bash_dequote_filename (const char *text, int quote_char)
1144+{
1145+ char *ret;
1146+ const char *p;
1147+ char *r;
1148+ int l, quoted;
1149+
1150+ l = strlen (text);
1151+ ret = (char*)malloc (l + 1);
1152+ for (quoted = quote_char, p = text, r = ret; p && *p; p++)
1153+ {
1154+ if (*p == '\\')
1155+ {
1156+ *r++ = *++p;
1157+ if (*p == '\0')
1158+ break;
1159+ continue;
1160+ }
1161+ if (quoted && *p == quoted)
1162+ {
1163+ quoted = 0;
1164+ continue;
1165+ }
1166+ if (quoted == 0 && (*p == '\'' || *p == '"'))
1167+ {
1168+ quoted = *p;
1169+ continue;
1170+ }
1171+ *r++ = *p;
1172+ }
1173+ *r = '\0';
1174+ return ret;
1175+}
1176+
1177+static int skip_quoted(const char *s, int i, char q)
1178+{
1179+ while(s[i] && s[i]!=q)
1180+ {
1181+ if(s[i]=='\\' && s[i+1]) i++;
1182+ i++;
1183+ }
1184+ if(s[i]) i++;
1185+ return i;
1186+}
1187+
1188+static int lftp_char_is_quoted(const char *string, int eindex)
1189+{
1190+ int i, pass_next;
1191+
1192+ for (i = pass_next = 0; i <= eindex; i++)
1193+ {
1194+ if (pass_next)
1195+ {
1196+ pass_next = 0;
1197+ if (i >= eindex)
1198+ return 1;
1199+ continue;
1200+ }
1201+ else if (string[i] == '"' || string[i] == '\'')
1202+ {
1203+ char quote = string[i];
1204+ i = skip_quoted (string, ++i, quote);
1205+ if (i > eindex)
1206+ return 1;
1207+ i--;
1208+ }
1209+ else if (string[i] == '\\')
1210+ {
1211+ pass_next = 1;
1212+ continue;
1213+ }
1214+ }
1215+ return (0);
1216+}
1217+
1218+void xyzsh_readline_init(BOOL runtime_script)
1219+{
1220+ rl_attempted_completion_function = readline_on_complete;
1221+ //rl_completion_entry_function = readline_filename_completion_null_generator;
1222+ rl_completer_quote_characters = "\"'";
1223+ rl_completer_word_break_characters = " \t\n\"'|!&;()$%<>=";
1224+ rl_completion_append_character= ' ';
1225+ rl_filename_quote_characters = " \t\n\"'|!&;()$%<>:[]";
1226+ rl_filename_quoting_function = bash_quote_filename;
1227+ rl_filename_dequoting_function = (rl_dequote_func_t*)bash_dequote_filename;
1228+// rl_char_is_quoted_p = char_is_quoted;
1229+
1230+ rl_char_is_quoted_p = (rl_linebuf_func_t*)lftp_char_is_quoted;
1231+
1232+/*
1233+ rl_comrl_filename_quote_characters = " \t\n\\'\"()$&|>";
1234+ rl_completer_quote_characters = " \t\n\\'\"()$&|>";
1235+ rl_basic_quote_characters = " \t\n\"'|!&;()$";
1236+*/
1237+
1238+ rl_bind_key('x'-'a'+1, readline_macro);
1239+}
1240+
1241+void xyzsh_readline_final()
1242+{
1243+}
--- a/src/run.c
+++ b/src/run.c
@@ -1,5 +1,6 @@
11 #include "config.h"
22
3+#include <dlfcn.h>
34 #include <errno.h>
45 #include <stdlib.h>
56 #include <assert.h>
@@ -31,6 +32,8 @@ static sObject* gRunningObjects;
3132
3233 sRunInfo* gRunInfoOfRunningObject;
3334
35+sObject* gDynamicLibraryFinals;
36+
3437 BOOL contained_in_pipe(sObject* object)
3538 {
3639 BOOL found = FALSE;
@@ -86,10 +89,22 @@ void run_init(enum eAppType app_type)
8689
8790 gRunningObjects = VECTOR_NEW_GC(10, FALSE);
8891 uobject_put(gXyzshObject, "_running_block", gRunningObjects);
92+
93+ gDynamicLibraryFinals = HASH_NEW_MALLOC(10);
8994 }
9095
9196 void run_final()
9297 {
98+ hash_it* it = hash_loop_begin(gDynamicLibraryFinals);
99+ while(it) {
100+ int (*func)() = hash_loop_item(it);
101+ if(func() != 0) {
102+ fprintf(stderr, "false in finalize");
103+ }
104+
105+ it = hash_loop_next(it);
106+ }
107+ hash_delete_on_malloc(gDynamicLibraryFinals);
93108 }
94109
95110 sObject* job_new_on_gc(char* name, pid_t pgroup, struct termios tty)
@@ -678,7 +693,10 @@ BOOL run_function(sObject* fun, sObject* nextin, sObject* nextout, sRunInfo* run
678693 int rcode = 0;
679694
680695 if(!run(SFUN(fun).mBlock, nextin, nextout, &rcode, runinfo->mCurrentObject, fun)) {
681- if(rcode != RCODE_RETURN) {
696+ if(rcode & RCODE_RETURN) {
697+ rcode = rcode & 0xff;
698+ }
699+ else {
682700 char buf[BUFSIZ];
683701 err_msg_adding("run time error", runinfo->mSName, runinfo->mSLine, command->mArgs[0]);
684702 runinfo->mRCode = rcode;
@@ -728,7 +746,7 @@ static BOOL run_completion(sObject* compl, sObject* nextin, sObject* nextout, sR
728746 if(!run(SCOMPLETION(compl).mBlock, nextin, nextout, &rcode, gRootObject, fun)) {
729747 if(rcode == RCODE_BREAK) {
730748 }
731- else if(rcode == RCODE_RETURN) {
749+ else if(rcode & RCODE_RETURN) {
732750 }
733751 else if(rcode == RCODE_EXIT) {
734752 }
@@ -1682,7 +1700,6 @@ BOOL load_file(char* fname, sObject* nextin, sObject* nextout, sRunInfo* runinfo
16821700 sCommand* command = runinfo->mCommand;
16831701 err_msg("signal interrupt16", runinfo->mSName, runinfo->mSLine, command->mArgs[0]);
16841702 runinfo->mRCode = RCODE_SIGNAL_INTERRUPT;
1685- FREE(buf);
16861703 close(fd);
16871704 return FALSE;
16881705 }
@@ -1734,3 +1751,61 @@ BOOL load_file(char* fname, sObject* nextin, sObject* nextout, sRunInfo* runinfo
17341751
17351752 return TRUE;
17361753 }
1754+
1755+BOOL load_so_file(char* fname, sObject* nextin, sObject* nextout, sRunInfo* runinfo)
1756+{
1757+ sCommand* command = runinfo->mCommand;
1758+
1759+ char path[PATH_MAX];
1760+ snprintf(path, PATH_MAX, "%s%s", EXTDIR, fname);
1761+
1762+ if(access(path, X_OK) != 0) {
1763+ char* home = getenv("HOME");
1764+ if(home) {
1765+ snprintf(path, PATH_MAX, "%s/.xyzsh/lib/%s", home, fname);
1766+ if(access(path, X_OK) != 0) {
1767+ xstrncpy(path, fname, PATH_MAX);
1768+ }
1769+ }
1770+ else {
1771+ xstrncpy(path, fname, PATH_MAX);
1772+ }
1773+ }
1774+
1775+ if(hash_item(gDynamicLibraryFinals, path) == NULL) {
1776+ void* handle = dlopen(path, RTLD_LAZY);
1777+
1778+ if(handle == NULL) {
1779+ err_msg(dlerror(), runinfo->mSName, runinfo->mSLine, command->mArgs[0]);
1780+ return FALSE;
1781+ }
1782+
1783+ int (*init_func)() = dlsym(handle, "dl_init");
1784+ int (*final_func)() = dlsym(handle, "dl_final");
1785+ if(init_func == NULL || final_func == NULL) {
1786+ err_msg("not found dl_init or dl_final", runinfo->mSName, runinfo->mSLine, command->mArgs[0]);
1787+ dlclose(handle);
1788+ return FALSE;
1789+ }
1790+
1791+ if(init_func(NULL) != 0) {
1792+ err_msg("false in initialize the dynamic library", runinfo->mSName, runinfo->mSLine, command->mArgs[0]);
1793+ dlclose(handle);
1794+ return FALSE;
1795+ }
1796+
1797+ hash_put(gDynamicLibraryFinals, path, final_func);
1798+
1799+ //dlclose(handle);
1800+
1801+ snprintf(path, PATH_MAX, "%s.xyzsh", path);
1802+ if(access(path, F_OK) == 0) {
1803+ if(!load_file(path, nextin, nextout, runinfo, NULL, 0)) {
1804+ return FALSE;
1805+ }
1806+ }
1807+ }
1808+
1809+ return TRUE;
1810+}
1811+
--- a/src/uobject.c
+++ b/src/uobject.c
@@ -115,12 +115,15 @@ void uobject_root_init(sObject* self)
115115 uobject_init(readline);
116116 uobject_put(self, "rl", readline);
117117
118+ uobject_put(readline, "file_name_completion_null_generator", NFUN_NEW_GC(cmd_readline_file_name_completion_null_generator, NULL, TRUE));
118119 uobject_put(readline, "insert_text", NFUN_NEW_GC(cmd_readline_insert_text, NULL, TRUE));
119120 uobject_put(readline, "delete_text", NFUN_NEW_GC(cmd_readline_delete_text, NULL, TRUE));
120121 uobject_put(readline, "clear_screen", NFUN_NEW_GC(cmd_readline_clear_screen, NULL, TRUE));
121122 uobject_put(readline, "point_move", NFUN_NEW_GC(cmd_readline_point_move, NULL, TRUE));
122123 uobject_put(readline, "read_history", NFUN_NEW_GC(cmd_readline_read_history, NULL, TRUE));
123124 uobject_put(readline, "write_history", NFUN_NEW_GC(cmd_readline_write_history, NULL, TRUE));
125+ uobject_put(readline, "replace_line", NFUN_NEW_GC(cmd_readline_replace_line, NULL, TRUE));
126+ uobject_put(readline, "point", NFUN_NEW_GC(cmd_readline_point, NULL, TRUE));
124127 uobject_put(self, "completion", NFUN_NEW_GC(cmd_completion, NULL, TRUE));
125128 uobject_put(self, "p", NFUN_NEW_GC(cmd_p, NULL, TRUE));
126129 uobject_put(self, "jobs", NFUN_NEW_GC(cmd_jobs, NULL, TRUE));
@@ -229,9 +232,6 @@ void uobject_root_init(sObject* self)
229232 uobject_put(self, "sort", NFUN_NEW_GC(cmd_sort, NULL, TRUE));
230233 uobject_put(self, "readline", NFUN_NEW_GC(cmd_readline, NULL, TRUE));
231234 uobject_put(self, "kanjicode", NFUN_NEW_GC(cmd_kanjicode, NULL, TRUE));
232-#if defined(HAVE_MIGEMO_H)
233- uobject_put(self, "migemo_match", NFUN_NEW_GC(cmd_migemo_match, NULL, TRUE));
234-#endif
235235
236236 uobject_put(self, "sub", NFUN_NEW_GC(cmd_sub, NULL, TRUE));
237237 uobject_put(self, "time", NFUN_NEW_GC(cmd_time, NULL, TRUE));
--- a/src/xyzsh.c
+++ b/src/xyzsh.c
@@ -35,7 +35,7 @@ void xyzsh_read_rc_core(char* path)
3535 fprintf(stderr, "invalid break. Not in a loop\n");
3636 exit(1);
3737 }
38- else if(runinfo.mRCode == RCODE_RETURN) {
38+ else if(runinfo.mRCode & RCODE_RETURN) {
3939 fprintf(stderr, "invalid return. Not in a function\n");
4040 exit(1);
4141 }
@@ -88,6 +88,8 @@ void xyzsh_init(enum eAppType app_type, BOOL no_runtime_script)
8888 setenv("XYZSH_VERSION", "1.3.3", 1);
8989 setenv("XYZSH_DOCDIR", DOCDIR, 1);
9090 setenv("XYZSH_DATAROOTDIR", DOCDIR, 1);
91+ setenv("XYZSH_EXT_PATH", EXTDIR, 1);
92+ setenv("XYZSH_SYSCONFDIR", SYSCONFDIR, 1);
9193
9294 setlocale(LC_ALL, "");
9395
@@ -121,10 +123,6 @@ void xyzsh_init(enum eAppType app_type, BOOL no_runtime_script)
121123 exit(1);
122124 }
123125
124-#if defined(HAVE_MIGEMO_H)
125- migemo_init();
126-#endif
127-
128126 if(!no_runtime_script) {
129127 xyzsh_read_rc();
130128 readline_read_history();
@@ -134,9 +132,6 @@ void xyzsh_init(enum eAppType app_type, BOOL no_runtime_script)
134132 void xyzsh_final()
135133 {
136134 readline_write_history();
137-#if defined(HAVE_MIGEMO_H)
138- migemo_final();
139-#endif
140135
141136 mcurses_final();
142137 run_final();
--- a/src/xyzsh/xyzsh.h
+++ b/src/xyzsh/xyzsh.h
@@ -567,6 +567,9 @@ BOOL cmd_objinfo(sObject* nextin, sObject* nextout, sRunInfo* runinfo);
567567 BOOL cmd_kanjicode(sObject* nextin, sObject* nextout, sRunInfo* runinfo);
568568 BOOL cmd_defined(sObject* nextin, sObject* nextout, sRunInfo* runinfo);
569569 BOOL cmd_funinfo(sObject* nextin, sObject* nextout, sRunInfo* runinfo);
570+BOOL cmd_readline_file_name_completion_null_generator(sObject* nextin, sObject* nextout, sRunInfo* runinfo);
571+BOOL cmd_readline_replace_line(sObject* nextin, sObject* nextout, sRunInfo* runinfo);
572+BOOL cmd_readline_point(sObject* nextin, sObject* nextout, sRunInfo* runinfo);
570573 BOOL cmd_readline_read_history(sObject* nextin, sObject* nextout, sRunInfo* runinfo);
571574 BOOL cmd_readline_write_history(sObject* nextin, sObject* nextout, sRunInfo* runinfo);
572575 BOOL cmd_readline_point_move(sObject* nextin, sObject* nextout, sRunInfo* runinfo);
@@ -729,13 +732,13 @@ BOOL gc_valid_object(sObject* object);
729732
730733 BOOL parse(char* p, char* sname, int* sline, sObject* block, sObject** current_object);
731734
732-#define RCODE_BREAK 256
733-#define RCODE_RETURN 257
734-#define RCODE_EXIT 258
735-#define RCODE_SIGNAL_INTERRUPT 259
736-#define RCODE_NFUN_FALSE 260
737-#define RCODE_NFUN_INVALID_USSING 261
738-#define RCODE_NFUN_NULL_INPUT 262
735+#define RCODE_BREAK 0x100
736+#define RCODE_RETURN 0x200
737+#define RCODE_EXIT 0x400
738+#define RCODE_SIGNAL_INTERRUPT 0x800
739+#define RCODE_NFUN_FALSE 0x1000
740+#define RCODE_NFUN_INVALID_USSING 0x2000
741+#define RCODE_NFUN_NULL_INPUT 0x4000
739742 //#define RCODE_COMMAND_NOT_FOUND 262
740743
741744 void xyzsh_kill_all_jobs();
@@ -753,6 +756,7 @@ extern sRunInfo* gRunInfoOfRunningObject;
753756 BOOL bufsiz_write(int fd, char* buf, int buf_len);
754757
755758 BOOL load_file(char* fname, sObject* nextin, sObject* nextout, sRunInfo* runinfo, char** argv, int argc);
759+BOOL load_so_file(char* fname, sObject* nextin, sObject* nextout, sRunInfo* runinfo);
756760
757761 int object_gc_children_mark(sObject* self);
758762
@@ -783,11 +787,6 @@ void xyzsh_read_rc_core(char* path);
783787 void run_init(enum eAppType app_type);
784788 void run_final();
785789
786-#if defined(HAVE_MIGEMO_H)
787-void migemo_init();
788-void migemo_final();
789-#endif
790-
791790 extern sObject* gPrompt;
792791 extern sObject* gDirStack;
793792
@@ -815,6 +814,7 @@ BOOL xyzsh_readline_interface_onetime(int* rcode, char* cmdline, int cursor_poin
815814 char* xyzsh_job_title(int n);
816815 int xyzsh_job_num();
817816 BOOL xyzsh_run(int* rcode, sObject* block, char* source_name, fXyzshJobDone xyzsh_job_done_, sObject* nextin, sObject* nextout, int argc, char** argv, sObject* current_object);
817+BOOL xyzsh_eval(int* rcode, char* cmd, char* source_name, fXyzshJobDone xyzsh_job_done_, sObject* nextin, sObject* nextout, int argc, char** argv, sObject* current_object);
818818
819819 void err_msg(char* msg, char* sname, int line, char* command);
820820 void err_msg_adding(char* msg, char* sname, int line, char* command);
--- a/xyzsh.xyzsh
+++ b/xyzsh.xyzsh
@@ -64,11 +64,13 @@ EOS > ~/.xyzsh/menu
6464 eval $(cat ~/.xyzsh/menu | selector | chomp)
6565 )
6666
67+# when pressing CTRL-X on cmdline, this is called
6768 def macro (
6869 if(! print ~/.xyzsh/macro | -e) (
6970 print <<<EOS
7071 whoami | chomp
7172 pwd | chomp
73+fselector -multiple | each ( | chomp | quote | pomch ) | join | chomp
7274 EOS > ~/.xyzsh/macro
7375 )
7476
@@ -88,6 +90,28 @@ def times -copy-stackframe (
8890 )
8991 )
9092
93+def max (
94+ | var -local max_value
95+ | each (
96+ if(| -gt $max_value) (
97+ | var -local max_value
98+ )
99+ )
100+
101+ max_value
102+)
103+
104+def min (
105+ | var -local min_value
106+ | each (
107+ if(| -lt $min_value ) (
108+ | var -local min_value
109+ )
110+ )
111+
112+ min_value
113+)
114+
91115 # for calling function with the caller-function arguments, options and blocks
92116 print <<<'EOS'
93117 | eval "| $FUNCTION $(ARGV|each(|chomp|quote|pomch)|join|chomp) $(OPTIONS | each -number 2 (|lines 0 ) | join|chomp) $(block -number | -gt 0 && seq $(block -number|chomp) | each (| - 1 | var num; | block $num | add \a) |chomp | each -La ( | chomp | add -number 0 \( | add -number -1 \)) | join -La)"