NAME
|
SOURCE
|
popen
|
システムコマンドのpopenをKLICに移植したもの。
またしても、強引なソース。
自分的には、インラインでリストを作る練習。
サンプルコードの使いかたは、
引数に文字列型で、"ls"とかすると、
その結果を改行を要素の区切りとした
リストが返る。
まぁ実行してみれば一目瞭然。
サンプルコード
:- module main.
main :- unix:argv([Command | _]),popen(Command,Out),print(Out).
print([]).
print([R|_R]) :- true | io:outstream([print(R),nl]),print(_R).
popen(Command,Out) :- popen(Command,Out,_).
popen(Command,Out,X) :- inline:"
{
#include <stdio.h>
#include <string.h>
extern char *convert_klic_string_to_c_string();
extern q convert_c_string_to_klic_string();
extern q *do_shallow_unify();
#define KLIC2C convert_klic_string_to_c_string
#define C2KLIC convert_c_string_to_klic_string
q data;
q newcons;
q newvar;
q temp = data;
q kstr;
char str[512],*ptr,*command = KLIC2C(%0);
FILE *fp;
if((fp=popen(command,\"r\"))==NULL){
fprintf(stderr,\"error!!!\\n\");
exit(-1);
}
while(1){
fgets(str,512,fp);
if(feof(fp)){
break;
}
ptr=strchr(str,\'\\n\');
if(ptr!=NULL){
*ptr=\'\\0\';
}
kstr = C2KLIC(str, allocp);
allocp = heapp;
newcons = makecons(allocp);
newvar = allocp[0] = makeref(&allocp[0]);
allocp[1] = kstr;
allocp += 2;
allocp = do_shallow_unify(allocp, temp, newcons);
temp = newvar;
}
allocp = do_shallow_unify(allocp, temp, NILATOM);
heapp = allocp;
%1 = data;
}":[Command+object(byte_string),X+any] |
Out = X.
|
STRING to INT
|
インラインコードを使用して、
無理矢理、文字列をKL1整数データにする。
↓がそのインラインコード
char2int(String,Int) :- inline:"
%1= makeint(atoi(convert_klic_string_to_c_string(%0)));
":[String+any,Int0-int] |
Int = Int0.
atoi()はC言語の関数、
makeint()はKLICが提供するマクロで、
整数nをKL1整数データにする。
サンプルコード
:- module main.
main :-
String="12345",
char2int(String,Int),
check(Int).
check(Int) :- integer(Int) | builtin:print(Int).
char2int(String,Int) :- inline:"
%1= makeint(atoi(convert_klic_string_to_c_string(%0)));
":[String+any,Int0-int] |
Int = Int0.
Stringを"1234t"にすると、1234が出力され、
"12r45e6"では、12が出力される。
|
PSUSとsignal
|
例題
:- module main.
main :- true |
unix:unix([signal_stream(14,normal(R))]),
test(R),
io:outstream([print(U),nl]).
test([R|Rs]) :- wait(R) |
io:outstream([print('signal '),print(R),print(' occured'),nl]),
builtin:print([R|Rs]),
unix:exit(0).
signal_stream(Sig,normal(R))は、UNIXシグナルを捕捉する述語で、
Sig で捕捉するシグナル番号を指定し、そのシグナルを受け取ると
R をそのシグナル番号で具体化する。
このプログラムを走らせるとどうなるかというと
io:outstream([print(U),nl])
というところで必ず PSUS がおきる事がわかる。
通常はこのまま PSUS が起きて KLIC ランタイムが
例外処理をするはずである。
しかし、実際はシグナル 14 を受けとって終了する。
また、このプログラムは U=7,14 を 13 として走らせると、
本来なら正常に終了することが予想されるが、
実際は、PSUS が起きて終了する。
なぜPSUSが起きるかというと test(R) という
ゴールが R が具体化されないために永久中断をおこすからである。
ではこのまま 13-->14 にしてみると、
こんどはシグナル 14 を受け取って終了する。
以上の実験が何を示しているかというと
PSUS はシグナル 14 で受け取れるということ、
つまり内部でタイムアウトしていることが分かる。
全ての PSUS がこれで捕捉できているのはまだ調査中である。
また、signal_stream()という述語の使い方にも、問題があることが分かる。
この述語はシグナルを受け取ると R を具体化していく
のだから、受け取った後の処理は当然、R を利用した
test() のようなゴールを用意することになるのであろう。
しかし、シグナルが起きなければ当然、R は具体化されない。
R が具体化されなければ後処理用に用意されたゴールは
永久中断をおこす。例題のプログラムにあるように、
unix:exit(0)という述語を書かないと、
シグナル捕捉後はKLICランタイムが正常終了しない。
これは、例外を発生したゴールが
ゴールキューに残留している為であろうと思うが、
現在調査中である。
|