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ランタイムが正常終了しない。
これは、例外を発生したゴールが
ゴールキューに残留している為であろうと思うが、
現在調査中である。