\section{システム関数}
\markright{\arabic{section}. システム関数}

\subsection{メモリ管理}
メモリ管理の設計は、オブジェクト指向言語の柔軟性と効率性にたいへん
影響を及ぼす。
Euslispは、{\bf フィボナッチバディ法}を基本に統一した方法で
オブジェクトをメモリに割り当てる。
この方法は、chunkと呼ばれる大きなメモリのプールを小さなセルに分割する。
それぞれのセルは、サイズが等しくなく、フィボナッチ数がそれぞれ割り当てられる。
chunkメモリは、{\tt symbol, cons, string, float-vector}などのような
様々な型のオブジェクトのための同次なデータ容器である。
それらのサイズはchunkと一致する長さである。
chunkは、固定、動的、再配置可能、交替可能などのような
どんな特別な属性も持っていない。
EusLispのヒープメモリは、chunkの集合である。そして、
ヒープはUNIXより新しいchunkを得ることにより動的に拡張することができる。
%In other words, there is no need to estimate the total amount of memory
%before EusLisp is invoked.
拡張は、動作中に自動的に発生するかあるいはユーザーが{\bf system:alloc}関数を
呼び出すことにより発生する。
自動的に処理されるとき、使用可能なメモリサイズは合計のヒープサイズの
約25\%に保つ。%by default,
この比率は、{\bf sys:*gc-margin*}パラメータに0.1から0.9までの値を設定
することにより変更することができる。

すべてのヒープメモリを使いきったとき、mark-and-sweep型のガーベージコレクション(GC)
を始める。
ルート（パッケージ，クラスやスタック）からアクセス可能なセルは，
同じアドレスのままである。
他のアクセス不可能なセルは、矯正されfree-listsにリンクされる。
GCの間にコピーやコンパクト化は発生しない。
ガーベージされるセルが矯正されるとき、その隣接セルがfreeかどうかチェックされる。
そして、できるだけ大きなセルを構成するようにマージされる。
しかしながら、このマージは、ときどき意味の無いものになる。
なぜなら、もっとも頻繁に呼び出されるメモリアロケータである{\tt cons}が、
そのマージされたセルを最も小さなセルに分割することを要求するからである。
したがって、Euslispは{\tt cons}の高速化のためにマージされないある特定の量の
ヒープを残すことを許可している。
この比率は、{\bf sys:*gc-merge*}パラメータによって決定される。その値のデフォルトは
0.3である。
{\bf sys:*gc-merge*}に大きな値を設定することにより、マージされないヒープを多く残す。
これは、{\tt cons}が要求されるとき、buddy-cellの分割が滅多に起こらないので、{\tt cons}の性能を改善する。
これは、また3次元ベクトルのような相対的に小さなセルのアロケーションについて
すべて成り立つ。

{\bf sys:gc}は、明示的にガーベージコレクターを呼び出す。
そして、ヒープに配置された空いているワード数と全体のワード数（バイト数ではない）を示す2つの整数の
リストを返す。

もし、実行中に"fatal error: stack overflow"が報告され、
そのエラーが無限ループあるいは再帰処理によるものでないと確信するならば、
{\bf sys:newstack}でLispのスタックの大きさを拡張すれば回避できる。
{\bf sys:newstack}を設定する前には、{\bf reset}を実行しなければならない。
なぜなら、
スペシャルバインドと{\bf unwind-protect}の整理用の書式が
現在のスタックの中からすべて捨てられるためである。

新しいスタックが配置された後、オープニングメッセージを表示するところから
実行を始める。
デフォルトのスタックサイズは、16Kwordである。
Lispのスタックは、システムのスタックと別物である。
前者は、ヒープ上に配置され、後者は、オペレーティングシステムによって
スタックセグメント内に配置される。
もし、"segmentation fault"エラーが発生したならば、システムのスタックが小さいことに
より発生したことが考えられる。
cshのコマンド{\tt limit}で、システムのスタックサイズを増加することにより、
解決できる可能性がある。

{\bf sys:reclaim}と{\bf sys:reclaim-tree}関数は、オブジェクトにより占有されているセルを
メモリマネージャーに戻す。そのため、ガーベージコレクションを呼び出すことなしに
その後も再使用をすることができる。
しかし、それらのセルが他のセルから参照されていないことが確実でなければならない。

{\bf memory-report}と{\bf room}関数は、メモリの使用に関する統計を
セルのサイズやクラスによりソートして表示する。

%A user who tries to use {\bf address} and {\bf peek, poke} functions must be
%familiar with the structure of EusLisp data objects.
{\bf address}は、オブジェクトのバイト換算したアドレスを返す。
このアドレスはプロセスに独自のものであるから、
この関数はハッシュテーブルが使用するハッシュ関数に有用である。

{\bf peek}と{\bf poke}は、メモリから直接データを読み書きできる関数である。
アクセスする型は、{\tt :char, :byte, :short, :long, :integer, :float, :double}
のどれかにすべきである。
例えば、{\tt (SYS:PEEK (+ 2 (SYS:ADDRESS '(a b))) :short)}は、
{\tt cons}セルのクラスID（ふつう１である）を返す。

'{\bf list-all-}'を名前の前に付けている幾つかの関数がある。
これらの関数は、システムのリソースあるいは環境のリストを返し、
動的なデバッグに有用である。

\begin{refdesc}

\funcdesc{sys:gc}{}{
ガーベージコレクションを実行する。割り当てられている中で空いているワード数および全体のワード数
のリストを返す。}

\vardesc{sys:*gc-hook*}{
ガーベージコレクションを実行する時に呼ばれる関数を定義する。}

\funcdesc{sys:gctime}{}{
3つの整数のリストを返す。1つは、ＧＣを呼び出した回数。
2つは、セルをマーキングするために使用した時間（1ユニットに1/60秒）。
3つが、矯正（マーキングを外し、マージする）のために使用した時間。}

\funcdesc{sys:alloc}{size}{
ヒープに少なくとも{\em size}ワードのメモリを配置し、
実際に配置されたワード数を返す。}

\funcdesc{sys:newstack}{size}{
現在のスタックを廃棄し、{\em size}ワードの新しいスタックを配置する。}

\vardesc{sys:*gc-merge*}{
メモリ管理用のパラメータ。
{\bf *gc-merge*}は、GCによりマージされずに残すヒープメモリの比率を示す。
このマージされない領域は、すぐに{\bf cons}のような小さなセルに満たされる。
デフォルトの値は、0.3である。
この値を0.4のように大きくすると、マージされない空きヒープが40\%であることを
示し、consのためには役立つが、実数ベクトルやエッジや面などのような大きなセル
の確保には、害を及ぼす。}

\vardesc{sys:*gc-margin*}{
メモリ管理用のパラメータ。
{\bf *gc-margin*}は、全体のヒープに対する空きヒープの比率を決定する。
メモリは、UNIXから獲得したものであるため、空き空間はこの比率より
小さくならない。
デフォルトは、0.25であり、GCの際に25\%以上の
空き空間が維持されることを意味する。}

\funcdesc{sys:reclaim}{object}{
ごみとして{\em object}を廃棄する。
そのオブジェクトは、他のどのオブジェクトからも絶対に参照されないことが
保証されなければならない。}

\funcdesc{sys:reclaim-tree}{object}{
{\em object}から通過できるsymbolを除いてすべてのオブジェクトを矯正する。}

\funcdesc{sys::bktrace}{num}{
Lispのスタックの{\em num}番目の深さの情報をトレースして表示する。}

\funcdesc{sys:memory-report}{\&optional strm}{
セルのサイズでソートしたメモリ使用のテーブルを{\em strm}ストリームに出力する。}

\funcdesc{sys:room}{output-stream}{
クラスで整列したメモリ配置の情報を出力する。}

\funcdesc{sys:address}{object}{
プロセスのメモリ空間内にある{\em object}のアドレスを返す。
%This information is useful when it is sent to a user-coded C function.
}

\funcdesc{sys:peek}{[vector] address type}{
{\em address}で指定されたメモリ位置のデータを読みだし、
それを整数として返す。
{\em type}は、{\bf :char, :byte, :short, :long, :float, :double}の内の１つである。
もし、{\em vector}が与えられなかったなら、
そのアドレスは、UNIXの処理空間として扱われる。
例えば、Sunにおいてa.outのヘッダーは{\tt \#x2000}に置かれるため、
{\tt (sys:peek \#x2000 :short)}はmagic number（ふつうは{\tt \#o403})を返す。
Solaris2は、ELFヘッダーを{\tt \#10000}に置くため、
{\tt (sys:peek \#x10000 :long)}が"ELF"を表現する文字列である
{\tt \#xff454c46}を返す。
もし、{\em vector}が与えられたならば、それは{\bf foreign-string}であり、
アドレスは{\em vector}の起点からのオフセットとして認識される。
{\tt (sys:peek "123456" 2 :short)}は、"34"を表現する
short wordを返す。({\tt \#x3334(13108)}である)

アドレス位置については十分注意すること。
{\tt short, integer, long. float, double word}を奇数アドレスから読み出すと、
"bus error"になる。}

\funcdesc{sys:poke}{value [vector] address value-type}{
{\em value}を{\em address}で指定された位置に書き込む。
プロセスのメモリ空間内のどこでも書き込むことができるため、
特に注意をしなければならない。
プロセスの空間の外へ書き込んだなら、
確実に"segmentation fault"が発生する。
{\tt short, integer, long. float, double word}を奇数アドレスに書き込んだ
場合、"bus error"が発生する。}

\funcdesc{sys:list-all-chunks}{}{
配置されたすべてのヒープのchunkをリストアップする。
他に有用な実行関数はない。}

\funcdesc{sys:object-size}{obj}{
{\em obj}からアクセス可能なセルとワードの数を計算する。
{\em obj}から参照可能なすべてのオブジェクトが探索される。
そして、3つの数のリストが返される。
1つ目は、セルの数。2つ目は、これらのオブジェクトに論理的に配置されたワード数（
すなわち、ユーザーからアクセスできるワード数）。
3つ目は、物理的に配置されたワード数。
これは、ヘッダーとメモリ管理のための特別なスロットを含む。
探索は、symbolで停止する。すなわち、{\tt property-list}あるいは{\tt print-name string}のような
symbolから参照されるオブジェクトは、カウントされない。}

\end{refdesc}

\newpage
\subsection{UNIXシステムコール}

EusLispは、UNIXオペレーティングシステムのシステムコールとライブラリ関数とに
直接関連する関数を取りそろえている。
これらの関数の詳細については、UNIX system interface (2)を調べること。
{\tt *unix-package*}に定義されているこれらの低レベル関数の使用は、
ときどき危険をはらむ。
できるだけ他のパッケージに定義されている高レベル関数を使用すること。
例えば、{\tt unix:socket, unix:bind, unix:connect}などの代わりに\ref{IPC}節に
記述されているIPC機能を使用すること。

\subsubsection{時間}
\begin{refdesc}

\funcdesc{unix:ptimes}{}{
経過時間、システム時間、ユーザー時間、サブプロセスのシステム時間とサブプロセスのユーザー時間
の5つの要素を持つリストを返す。
この関数は旧いので、{\bf unix:getrusage}の使用を推奨する。}

\funcdesc{unix:runtime}{}{
プロセスのシステムとユーザー時間の合計を返す。
単位は、1/60秒である。}

\funcdesc{unix:localtime}{}{
現在の時間と月日を整数ベクトルで返す。
要素は、秒、分、時、日、月（0から始まることに注意）、年（1900からの経過年数）、曜日（0が日曜日、6が土曜日）、年内の通し日数（0から始まる）、夏時間がセットされているか、サポートされている時間帯である。

{\tt ex.) unix:localtime => \#(10 27 12 8 10 116 2 312 nil (``JST'' ``JST''))}
}

\funcdesc{unix:asctime}{tm\_intvector}{
整数ベクトルで表現されるローカル時間を文字列表現に変換する。
{\tt (unix:asctime (unix:localtime))}は、現在の実際の時間の文字列
表現を返す。}

\end{refdesc}

\subsubsection{プロセス}
\begin{refdesc}

\funcdesc{unix:getpid}{}{
このプロセスのプロセスID(16ビット整数)を返す。}

\funcdesc{unix:getppid}{}{
親プロセスのプロセスIDを返す。}

\funcdesc{unix:getpgrp}{}{
このプロセスのグループIDを返す。}

\funcdesc{unix:setpgrp}{}{
新しいプロセスのグループIDを設定する。}

\funcdesc{unix:getuid}{}{
このプロセスのユーザーIDを返す。}

\funcdesc{unix:geteuid}{}{
このプロセスの使用可能なユーザーIDを返す。}

\funcdesc{unix:getgid}{}{
このプロセスのユーザーグループIDを返す。}

\funcdesc{unix:getegid}{}{
このプロセスの使用可能なユーザーグループIDを返す。}

\funcdesc{unix:setuid}{integer}{
このプロセスの使用可能なユーザーIDを設定する。}

\funcdesc{unix:setgid}{integer}{
このプロセスの使用可能なユーザーグループIDを設定する。}


\funcdesc{unix:fork}{}{
他のEuslispを作成する。サブプロセスに0が返され、
親プロセスにforkされたプロセスのpidが返される。
パイプで接続されたプロセスを作成するためには、\ref{UnixProcess}節に書かれている
{\bf system:piped-fork}を使用すること。}

\funcdesc{unix:vfork}{}{
他のEuslispをforkし、その新しいEuslispのプロセスが終了するまで親プロセスの実行を
一時停止する。}

\funcdesc{unix:exec}{path}{
Euslispから他のプログラムへ実行を移す。}

\funcdesc{unix:wait}{}{
サブプロセスの中の１つのプロセスの終了を待つ。}

\funcdesc{unix::exit}{code}{
実行を終了し、{\em code}を終了状態として返す。
ゼロは通常の終了を意味する。}

\vardesc{sys:*exit-hook*}{
プロセスが終了する直前に呼ばれる関数を定義する。}

\funcdesc{unix:getpriority}{which who}{
このプロセスが持つ最大の優先順位を返す。
{\em which}は、0(プロセス)、1(プロセスグループ)、2(ユーザー)のうちの
1つである。}

\funcdesc{unix:setpriority}{which who priority}{
{\em which}と{\em who}で決定されるリソースの優先順位を{\em priority}に設定する。
{\em which}は、0,1,2の内の1つである。
{\em who}は、{\em which}から相対的に解釈される
($which=0$ならプロセスを示し、$which=1$ならプロセスグループを示し、
$which=2$ならユーザーのIDを示す)。
{\em who}がゼロのとき、現在のプロセス、プロセスグループ、ユーザーを示す。
Euslispプロセスに低い優先順位を指定することは、大きい値を設定することであり、
これはプロセスを不利にする。
{\tt (unix:setpriority 0 0 10)}は、優先順位を10に設定する。}

\funcdesc{unix:getrusage}{who}{
{\em who}プロセスについてのシステムリソースの使用情報のリストを返す。
要素は、以下のような順番になっている。
もっと多くの情報が、{\bf lisp:rusage}より得られる。}
{\small
\begin{verbatim}
    float ru_utime (sec.) /* user time used */
    float ru_stime (sec.) /* system time used */
    int  ru_maxrss;       /* maximum resident set size */
    int  ru_ixrss;        /* currently 0 */
    int  ru_idrss;        /* integral resident set size */
    int  ru_isrss;        /* currently 0 */
    int  ru_minflt;       /* page faults without physical I/O */
    int  ru_majflt;       /* page faults with physical I/O */
    int  ru_nswap;        /* number of swaps */
    int  ru_inblock;      /* block input operations */
    int  ru_oublock;      /* block output operations */
    int  ru_msgsnd;       /* messages sent */
    int  ru_msgrcv;       /* messages received */
    int  ru_nsignals;     /* signals received */
    int  ru_nvcsw;        /* voluntary context switches */
    int  ru_nivcsw;       /* involuntary context switches */
\end{verbatim}
}

\funcdesc{unix:system}{\&optional command}{
サブシェルで{\em command}を実行する。
{\em command}は、Bourn-shellで認識されるものでなければならない。}

\funcdesc{unix:getenv}{env-var}{
{\em env-var}の環境変数の値を返す。}

\funcdesc{unix:putenv}{env}{
プロセスの環境変数リストに{\em env}を追加する。
{\em env}は、{\tt "VARIABLE=value"}のように変数と値の等価を表す文字列である。}

\funcdesc{unix:sleep}{time}{
{\em time}秒間このプロセスの実行を一時停止する。}

\funcdesc{unix:usleep}{time}{
{\em time}マイクロ秒間このプロセスを一時停止する。
({\bf u}は、マイクロを表現する。)
{\bf usleep}は、Solaris2あるいは他のSystem5系のシステムには実現されていない。}

\end{refdesc}

\subsubsection{ファイルシステムと入出力}
\begin{refdesc}

\funcdesc{unix:uread}{stream \&optional buffer size}{
{\em stream}から{\em size}バイト読み込む。
{\em stream}は、ストリームオブジェクトあるいはファイルディスクリプタ(fd)を
表現する整数である。
もし、{\em buffer}が与えられるとき、入力はそこに蓄積される。
そうでないならば、入力は{\em stream}のバッファに蓄積される。
したがって、もし{\em stream}がfdなら、{\em buffer}は与えられなければならない。
{\bf unix:uread}は、新しい文字列バッファを配置しない。
{\bf unix:uread}は、実際に読み込まれたバイト数を返す。}

\funcdesc{unix:write}{stream string \&optional size}{
{\em stream}に{\em string}の{\em size}バイトを書き込む。
もし、{\em size}が省略されたならば、{\em string}の全部の長さが出力される。}

\fundesc{unix:fcntl}{stream command argument}

\fundesc{unix:ioctl}{stream command buffer}

\fundesc{unix:ioctl\_}{stream command1 command2}

\fundesc{unix:ioctl\_R}{stream command1 command2 buffer \&optional size}

\fundesc{unix:ioctl\_W}{stream command1 command2 buffer \&optional size}

\fundesc{unix:ioctl\_WR}{stream command1 command2 buffer \&optional size}

\funcdesc{unix:uclose}{fd}{
{\em fd}で指定されるファイルをクローズする。}

\funcdesc{unix:dup}{fd}{
{\em fd}で指定されるファイルディスクリプタを２重化して返す。}

\funcdesc{unix:pipe}{}{
パイプを作成する。このパイプの入出力ストリームを返す。}

\funcdesc{unix:lseek}{stream position \&optional (whence 0)}{
{\em stream}のファイルポインタを{\em whence}から{\em position}の
位置に設定する。}

\funcdesc{unix:link}{path1 path2}{
hardリンクを作る。}

\funcdesc{unix:unlink}{path}{
{\em path}で指定されたファイルのhardリンクを取り去る。
もし、ファイルに参照が残っていないなら、削除される。}

\funcdesc{unix:mknod}{path mode}{
ファイルシステムにinodeを作る。
{\em path}は、{\bf pathname}オブジェクトでなく文字列でなければならない。}

\funcdesc{unix:mkdir}{path mode}{
ファイルシステムにディレクトリを作る。
{\em path}は、{\bf pathname}オブジェクトでなく文字列でなければならない。}

\funcdesc{unix:access}{path mode}{
{\em path}へのアクセス権利をチェックする。}

\funcdesc{unix:stat}{path}{
{\em path}のinode情報を得て、以下に示す整数のリストを返す。}
{\small
\begin{verbatim}
  st_ctime	; file last status change time
  st_mtime	; file last modify time
  st_atime	; file last access time
  st_size	; total size of file, in bytes
  st_gid	; group ID of owne
  st_uid	; user ID of owner
  st_nlink	; number of hard links to the file
  st_rdev	; the device identifier (special files only)
  st_dev	; device file resides on
  st_ino	; the file serial number
  st_mode	; file mode
\end{verbatim}
}

\funcdesc{unix:chdir}{path}{
現在のディレクトリを{\em path}に変更する。}

\funcdesc{unix:getwd}{}{
現在のディレクトリを返す。}

\funcdesc{unix:chmod}{path integer}{
{\em path}のアクセスモード(permission)を変更する。}

\funcdesc{unix:chown}{path integer}{
{\em path}ファイルのオーナーを変更する。}

\funcdesc{unix:isatty}{stream-or-fd}{
もし、{\em stream-or-fd}がTTY型のデバイス(シリアルポートあるいは仮想TTY)に接続されているなら
Tを返す。}

\funcdesc{unix:msgget}{key mode}{
{\em key}によってアドレスされるメッセージキューを作成し、配置する。}

\fundesc{unix:msgsnd}{qid buf \&optional msize mtype flag}

\fundesc{unix:msgrcv}{qid buf \&optional mtype flag}

\funcdesc{unix:socket}{domain type \&optional proto}{
{\em domain}に定義されている名前を持ち{\em type}を抽象型とするソケットを作成する。
{\em type}は、1 (SOCK\_STREAM),
2 (SOCK\_DGRAM), 3 (SOCK\_RAW), 4 (SOCK\_RDM), 5 (SOCK\_SEQPACKET)の内の1つである。}

\funcdesc{unix:bind}{socket name}{
{\em name}と{\em socket}を関連付ける。
もし、ソケットがUNIX領域内で定義されているならば、{\em name}は、UNIXのパス名でなければならない。}

\funcdesc{unix:connect}{socket addr}{
{\em socket}と{\em addr}で指定される他のソケットを接続する。}

\funcdesc{unix:listen}{socket \&optional backlog}{
{\em socket}から接続要求を受け始める。
{\em backlog}は、接続の確定を待つためのキューの長さを指定する。}

\funcdesc{unix:accept}{socket}{
{\em socket}から接続要求を受け、両方向にメッセージを交換できるファイルディスクリプタ
を返す。}

\funcdesc{unix:recvfrom}{socket \&optional mesg from flag}{
{\em socket}からデータを書いたメッセージを受ける。
そのソケットは、{\bf unix:bind}により名前を割り当てられなければならない。
{\em mesg}は、入ってきたメッセージが蓄積されるための文字列である。
もし、{\em mesg}が与えられたならば、{\bf unix:recvfrom}は受け取ったバイト数を返す。
もし省略されたなら、メッセージを蓄積するための新しい文字列を作成し、
その文字列を返す。}

\funcdesc{unix:sendto}{socket addr mesg \&optional len flag}{
{\em addr}によって指定される他のソケットへデータの書かれたメッセージを送る。
{\em socket}は、名前が割り当てられてないデータ書き込み型のソケットでなければならない。
{\em mesg}は、送るための文字列であり、{\em len}は文字列の最初から
数えたメッセージの長さである。
もし、省略されたなら、すべての文字列を送る。}

\funcdesc{unix:getservbyname}{servicename}{
{\tt /etc/services}あるいはNISデータベースに記録されている{\em servicename}
のサービス番号を返す。}

\funcdesc{unix:gethostbyname}{hostname}{
{\em hostname}のipアドレスとアドレス型のリストを返す。
(一般にいつも AF\_INET==2).}

\funcdesc{unix:syserrlist}{errno}{
{\em errno}のエラーコードに対するエラー情報が記述された文字列を返す。}

\end{refdesc}


\subsubsection{シグナル}

\begin{refdesc}

\funcdesc{unix:signal}{signal func \&optional option}{
{\em signal}に対してシグナルハンドラー{\em func}をインストールする。
BSD4.2システムにおいて、システムコール処理の間に捕まえたシグナルは、
システムコールのリトライに起因する。
これは、もしその処理がシステムコールの呼び出しを発行するならば、
シグナルを無視することを意味する。
もし、{\em option=2}が指定されたならば、シグナルはsystem-5の手法で
処理される。そのシグナルは、システムコールの失敗に起因する。}

\funcdesc{unix:kill}{pid signal}{
{\em pid}で名前付けされるプロセスに{\em signal}を送る。}

\funcdesc{unix:pause}{}{
シグナルが到着するまでこのプロセスの実行を一時停止する。}

\funcdesc{unix:alarm}{time}{
{\em time}秒後にアラーム時計シグナル(SIGALRM 14)を送る。
{\em time}=0で{\bf unix:alarm}を呼び出すと、アラーム時計をリセットする。}

\funcdesc{unix:ualarm}{time}{
{\em time}がマイクロ秒単位であることを除いて{\bf unix:alarm}と同じである。
{\bf ualarm}は、Solaris2あるいはSystem5系のシステムに実現されていない。}

\funcdesc{unix:getitimer}{timer}{
{\em timer}は、0 ({\tt ITIMER\_REAL}), 1 ({\tt ITIMER\_VIRTUAL}),
2({\tt ITIMER\_PROF})の内の１つである。
秒単位の時間(timer)と間隔(interval)の2つの要素を持つリストを返す。}

\funcdesc{unix:setitimer}{timer value interval}{
{\em timer}に{\em value}と{\em interval}を設定する。
{\em timer}は、0 ({\tt ITIMER\_REAL}), 1 ({\tt ITIMER\_VIRTUAL}),
2({\tt ITIMER\_PROF})の内の１つである。
{\tt ITIMER\_REAL}は、{\em value}が終了したとき、SIGALRMを発行する。
{\tt ITIMER\_VIRTUAL}は、SIGVTALRMを発行し、
{\tt ITIMER\_PROF}は、SIGPROFを発行する。}

\funcdesc{unix:select}{inlist outlist exceptlist timeout}{
{\em inlist, outlist}と{\em exceptlist}は、ファイルディスクリプタ
を示すビットベクトルである。そのファイルディスクリプタの入出力イベント
は、テストされなければならない。
例えば、もし{\em inlist}={\tt \#b0110}で{\em outlist}={\tt \#b100}で
{\em exceptlist}=NILであるなら、
fd=1あるいはfd=2で読み込み可能かあるいはfd=2で書き込み可能であるかどうかをテストする。
{\em timeout}は、{\bf unix:select}が待つために許される秒数を指定する。
{\em inlist}で指定されているポートの1つに入力データが現れるかあるいは
{\em outlist}に指定されるポートの1つに書き込み可能となるかあるいは
{\em exceptlist}で指定されるポートの1つに例外条件が起こるとすぐに
{\bf unix:select}は、{\em inlist, outlist, exceptlist}のそれぞれにおいて
アクセス可能なポートとして設定されたポートの中で、入力処理可能なポート番号を返す。}

\funcdesc{unix:select-read-fd}{read-fdset timeout}{
入出力の選択は、ふつう入力処理のときのみ意味がある。
{\bf unix:select-read-fd}は、
{\tt select fdset nil nil timeout}の速記法である。
{\em read-fdset}は、ビットベクトルでなく、設定された読み込みfdを指定する整数である。}

\end{refdesc}

\subsubsection{マルチスレッド}
スレッド内でシグナルを生成することはできない。
したがって、1つのシグナルスタックと1つのタイマーがEuslispのプロセスの
中で実現されている。
Solaris2の上では、メインの最上位レベルが分割されたスレッド内で実行する。

\begin{refdesc}

\funcdesc{unix:thr-self}{}{
現在実行されているスレッドのID(整数)を返す。}

\funcdesc{unix:thr-getprio}{id}{
{\em id}で指定されたスレッドの実行優先順位を返す。}

\funcdesc{unix:thr-setprio}{id newprio}{
{\em id}で指定されたスレッドの実行優先順位に{\em newprio}を設定する。
{\em newprio}が小さい数値の場合、優先順位が高いことを意味する。
言い替えれば、
{\em newprio}よりも大きな数値を持つスレッドは、CPUにアクセスされることが
少なくなる。
ユーザーは、実行優先順位をプロセスの値（普通はゼロ）よりも高く
することはできない。}

\funcdesc{unix:thr-getconcurrency}{}{
並列に実行できるスレッドの数で表現される
並列度(整数)を返す。}

\funcdesc{unix:thr-setconcurrency}{concurrency}{
{\em concurrency}の値は、プロセス内のLWPの数である。
もし、{\em concurrensy}がデフォルトの1ならば、
生成されたたくさんのスレッドがすべて実行可能であったとしても
順番に1つのLWPに割り当てられる。
もし、プログラムがマルチプロセッサマシン上で実行され、
同時に複数のCPUを利用したいならば、
{\em concurrency}に1より大きい値を設定しなければならない。
{\em concurrency}に大きな値を設定すると、オペレーティングシステムの
リソースをたくさん消費する。普通、{\em concurrency}はプロセッサの数
と同じかあるいは小さくすべきである。}

\funcdesc{unix:thr-create}{func arg-list \&optional (size 64*1024)}{
{\em size}ワードのlispスタックを持ち、{\em size}バイトのCスタック持つ
新しいスレッドを作成し、そのスレッド内で{\em arg-list}に{\em func}を適用する。
スレッドは、どんな結果も呼びだし側に返すことができない。
この関数の使用は避けること。}

\end{refdesc}


\subsubsection{低レベルメモリ管理}
\begin{refdesc}

\funcdesc{unix:malloc}{integer}{
Euslispのメモリ空間の外にメモリを配置する。}

\funcdesc{unix:free}{integer}{
{\bf unix:malloc}で配置されたメモリブロックを開放する。}

\fundesc{unix:valloc}{integer}

\fundesc{unix:mmap}{address length protection share stream offset}

\fundesc{unix:munmap}{address length}

\fundesc{unix:vadvise}{integer}

\end{refdesc}

\subsubsection{IOCTL}
Unixはターミナルデバイスを{\tt ioctl}の2番目の引数に命令を設定することにより
制御することができるが、Euslispはインクルードファイルの参照や命令コードとしての
引数の論理和を省略するために、関数で備えている。
詳しい内容は、Unixの{\tt  termio}のマニュアルを参照すること。

ターミナルの入出力制御には、TIOC*とTC*という2つの命令系がある。
自分のオペレーティングシステムにこれらの関数が実現されているがどうか
について気を付けなさい。
基本的に、BSD系はTIOC*の入出力をサポートし、System5系がTC*を
サポートしている。
\begin{description}
\item{SunOS 4.1} TIOC*とTC*の両方サポート
\item{Solaris2} TC*のみサポート
\item{mips, ultrix?} TIOC*のみサポート
\end{description}
\begin{refdesc}

\funcdesc{unix:tiocgetp}{stream \&optional sgttybuf}{
パラメータを得る。}

\funcdesc{unix:tiocsetp}{stream sgttybuf}{
パラメータを設定する。}

\fundesc{unix:tiocsetn}{stream \&optional sgttybuf}

\fundesc{unix:tiocgetd}{stream \&optional sgttybuf}

\funcdesc{unix:tiocflush}{stream}{
バッファをすべて出力する。}

\funcdesc{unix:tiocgpgrp}{stream integer}{
プロセスのグループIDを得る。}

\funcdesc{unix:tiocspgrp}{stream integer}{
プロセスのグループIDを設定する。}

\fundesc{unix:tiocoutq}{stream integer}

\fundesc{unix:fionread}{stream integer}

\fundesc{unix:tiocsetc}{stream buf}

\fundesc{unix:tioclbis}{stream buf}

\fundesc{unix:tioclbic}{stream buf}

\fundesc{unix:tioclset}{stream buf}

\fundesc{unix:tioclget}{stream buf}

\funcdesc{unix:tcseta}{stream buffer}{
ターミナルパラメータをすぐに設定する。}

\funcdesc{unix:tcsets}{stream buffer}{
ターミナルパラメータを設定する。}

\funcdesc{unix:tcsetsw}{stream buffer}{
出力として列をなす全ての文字を転送した後、ターミナルパラメータを設定する。}

\funcdesc{unix:tcsetsf}{stream buffer}{
出力として列をなす全ての文字を転送し、
入力として列をなす全ての文字列を廃棄した
後、ターミナルパラメータを設定する。}

\fundesc{unix:tiocsetc}{stream buffer}

\fundesc{unix:tcsetaf}{stream buffer}

\fundesc{unix:tcsetaw}{stream buffer}

\fundesc{unix:tcgeta}{stream buffer}

\fundesc{unix:tcgets}{stream buffer}

\fundesc{unix:tcgetattr}{stream buffer}

\fundesc{unix:tcsetattr}{stream buffer}

\end{refdesc}

\subsubsection{キーインデックスファイル}
近年UNIXは、キーインデックスファイルの管理のために{\bf dbm}あるいは{\bf ndbm}
ライブラリを提供する。このライブラリを使用することにより、
キーとデータの組みで構成されるデータベースを構築することができる。
以下に示す関数は、{\tt clib/ndbm.c}に定義されている。
Sunにおいて、そのファイルは、{\tt cc -c -Dsun4 -Bstatic}でコンパイルし、
{\tt (load "clib/ndbm" :ld-option "-lc")}でEuslispにロードすること。

\begin{refdesc}

\funcdesc{dbm-open}{dbname mode flag}{
{\bf dbm-open}は、データベースファイルを作るときと、そのデータベースに読み込み／書き込み
をするとき、最初に呼び出されなければならない。
{\em dbname}は、データベースの名前である。
実際に、ndbm managerは{\tt ".pag"}と{\tt ".dir"}の拡張子を持つ
2つのファイルを作成する。
{\em mode}は、ファイルのオープンモードを指定する。0は読み込み専用、1は書き込み専用、
2は読み書き用を示す。また、最初にファイルを作成するときは、{\tt \#x200}を論理和すべきである。
{\em flag}は、{\bf chmod}で変更されるアクセス許可を与える。
{\tt \#o666}あるいは{\tt \#o664}が、{\em flag}に適している。
{\bf dbm-open}は、そのデータベースを確認するための整数を返す。
この値は、他のdbm関数によってデータベースを確認するために使用される。
言い換えれば、同時に幾つかのデータベースをオープンすることができる。}

\funcdesc{dbm-store}{db key datum mode}{
{\em key}と{\em datum}の組み合わせを{\em db}に蓄積する。
{\em db}は、データベースを確認するための整数である。
{\em key}と{\em datum}は文字列である。
{\em mode}は0(挿入)あるいは1(置き換え)のどちらかである。}

\funcdesc{dbm-fetch}{db key}{
{\em db}の中の{\em key}に関連付けられているデータを呼び出す。}

\end{refdesc}

\newpage
\subsection{\label{UnixProcess}UNIXプロセス}
EuslispからUNIX命令を実行ために{\bf unix:system}関数を使用すること。
{\bf piped-fork}は、標準出力を標準入力がパイプを通してEuslispの双方向ストリームに
接続されるサブプロセスを作成する。
{\bf piped-fork}はストリームを返す。
以下に示す関数は、{\tt "wc"}を使用することにより、ファイルに含まれる行の数を
数えるものである。
\begin{verbatim}
(defun count-lines (file) (read (piped-fork "wc" file)))
\end{verbatim}

次の例は、他のワークステーション"etlic0"の上にeusプロセスを作成し、
分散計算をするためのポートを提供する。

\begin{verbatim}
(setq ic0eus (piped-fork "rsh" "etlic0" "eus"))
(format ic0eus "(list 1 2 3)~%")
(read ic0eus) --> (1 2 3)
\end{verbatim}

ソースコードを修正するために、Euslispから{\tt ez}を呼び出すことができる。
スクリーンエディターezは、メッセージキューを通してEuslispと接続する。
もし、既にezプロセスをEuslispと並列に実行しているならば、
{\bf ez}はezプロセスを再スタートし、ターミナル制御を得る。
ezの中で{\tt esc-P}あるいは{\tt esc-M}命令を発行することにより、
テキストは戻され、Euslispで評価される。
ファイルに少しの変更を加えたとき、全部のファイルをロードする必要がないので、
デバッグするのにこれは便利である。
emacsの上でも{\tt M-X run-lisp}命令でおなじことが可能である。

\begin{refdesc}

\funcdesc{cd}{\&optional (dir (unix:getenv "HOME"))}{
現在のディレクトリを変更する。}

\funcdesc{ez}{\&optional key}{
ezエディターの画面に入る。それからLisp書式を読み込み、
評価する。}

\funcdesc{piped-fork}{\&optional (exec) \&rest args}{
プロセスをforkし、両方向ストリームをEuslispとサブプロセスの間に作る。}

\funcdesc{rusage}{}{
このプロセスのリソースの使用状況を表示する。}

\end{refdesc}

\newpage

\subsection{Ｃで書かれたLisp関数の追加}

ファイルに含まれるCを重く参照したり、行列にしばしばアクセスするような
プログラムにおいては、Euslispで記述するよりはむしろCあるいは他の言語で
記述した方が効率が良く、記述もわかり易い。
EusLispは、Cで書かれたプログラムをリンクする方法を備えている。

もしCで書かれたEuslispの関数を定義したいならば、
Euslispで呼び出しできるCの関数はそれぞれ、３つの引き数を受けるように書かれなければ
ならない。環境へのポインタと受け取る引き数の数とlispの引数領域を示す
ポインタの3つである。
これらの引数は、{\tt c/eus.h}の中のマクロによって参照されるため、
{\tt ctx, n, argv}と名付けられねばならない。
Cのプログラムは、{\tt *eusdir*/c/eus.h}をincludeしなければならない。
プログラマーは、そこに書かれた型やマクロに精通していなければならない。
エントリ関数名には、ソースファイルのbasenameを付けなければならない。

任意の数の実数の算術平均を計算するCの関数AVERAGEのサンプルコードは、
以下に示す通りである。
この例において、引数から実数値を得る方法、実数のポインタを作る方法、
特殊変数AVERAGEにポインタを設定する方法やエントリ関数{\tt ave}に
関数やsymbolを定義する方法を知ることができる。
{\tt 'cc -c -Dsun4 -DSolaris2 -K pic'}でこのプログラムをコンパイルする。
{\tt c/eus.h}内の正しい定義を選択するために、{\tt -Dsun4}や{\tt -DSolaris2}
が必要である。
{\tt -K pic}は、ロード可能な共有オブジェクトのために、位置に依存するコードを
Cコンパイラで生成させるために必要である。
その後、コンパイルの結果である'.o'ファイルがEuslispにロードすることができる。
もっと完全な例は{\tt *eusdir*/clib/*.c}に置かれている。
これらの例は、ここで書かれた方法で定義され、ロードされる。

\begin{verbatim}
/* ave.c */
/* (average &rest numbers) */
#include "/usr/local/eus/c/eus.h"
static pointer AVESYM;
pointer AVERAGE(ctx,n,argv)
context *ctx;
int n;
pointer argv[];
{ register int i;
  float sum=0.0, a, av;
  pointer result;
  numunion nu;
  for (i=0; i<n; i++) {
    a=ckfltval(argv[i]);
    sum += a;} /*get floating value from args*/
  av=sum/n;
  result=makeflt(av);
  AVESYM->c.sym.speval=result;  /*kindly set the result in symbol*/
  return(result);}

ave(ctx,n,argv)
context *ctx;
int n;
pointer argv[];
{ char *p;
  p="AVERAGE";
  defun(ctx,p,argv[0],AVERAGE);
  AVESYM=intern(ctx,p,strlen(p),userpkg); /* make a new symbol*/
  }

\end{verbatim}

\subsection{他言語インターフェース}

Euslispとのリンクを考慮していないCの関数もEuslispにロードすることができる。
これらの関数は、他言語関数と呼ばれる。
そのようなプログラムは{\bf load-foreign}マクロによりロードされる。
そのマクロは、{\bf foreign-module}のインスタンスを返す。
オブジェクトファイルの中の外部symbol定義は、モジュールオブジェクトの中に
登録されている。
{\bf defforeign}は、Euslispから呼び出すための
C関数に対するエントリーを作るために使用される。
{\bf defun-c-callable}は、Cから呼び出し可能なlisp関数を定義する。
呼び出し可能なCの関数は、パラメータを変換し関連するEuslispの関数へ制御を移すために
{\em pod-code}と呼ばれる特別なコードを持つ。
{\bf pod-address}は、この特別なコードのアドレスを返す。
そのアドレスはCの関数に通知されるべきである。

これは、CのプログラムのサンプルとEuslispへの関数インターフェースである。
\begin{verbatim}
/* C program named cfunc.c*/

static int (*g)();	/* variable to store Lisp function entry */

double sync(x)
double x;
{ extern double sin();
  return(sin(x)/x);}

char *upperstring(s)
char *s;
{ char *ss=s;
  while (*s) { if (islower(*s)) *s=toupper(*s); s++;}
  return(ss);}

int setlfunc(f)      /* remember the argument in g just to see */
int (*f)();          /* how Lisp function can be called from C */
{ g=f;}

int callfunc(x)      /* apply the Lisp function saved in g to the arg.*/
int x;
{ return((*g)(x));}

;;;; Example program for EusLisp's foreign language interface
;;;; make foreign-module
(setq m (load-foreign "cfunc.o"))

;; define foreign functions so that they can be callable from lisp
(defforeign sync m "sync" (:float) :float)
(defforeign toupper m "upperstring" (:string) :string)
(defforeign setlfunc m "setlfunc" (:integer) :integer)
(defforeign callfunc m "callfunc" (:integer) :integer)

;; call them
(sync 1.0)	--> 0.841471
(print (toupper "abc123"))  --> "ABC123"

;; define a test function which is callable from C.
(defun-c-callable TEST ((a :integer)) :integer
      (format t "TEST is called, arg=~s~%" a)
      (* a a))    ;; return the square of the arg
;;  call it from C
;;setlfunc remembers the entry address of Lisp TEST function.
(setlfunc (pod-address (intern "TEST")))
(callfunc 12)  --> TEST is called, arg=12  144
\end{verbatim}
  
Euslispのデータ表現は、以下に示す方法でCのデータ表現に変換される。
EusLispの30ビット整数（文字列を含む）は、符号拡張され、スタックを通してCの関数に渡される。
30ビット実数は、倍精度実数(double)に拡張され、スタックを通して渡される。
文字列と整数ベクトルと実数ベクトルについては、その最初の要素のアドレスのみが
スタックに渡され、行列自体はコピーされない。
Euslispには、2次元以上の配列を渡す方法がない。
2次元以上の配列はすべての要素を線形に保持する1次元ベクトルを持つ。
このベクトルは、{\bf array-entity}マクロにより得られる。
もし、2次元行列をFORTRANのサブルーチンに送る場合、FORTRANにおいて列と行が反対となっているため
その行列を転置しなければならないことに注意すること。

実数のEuslisp表現は、いつも単精度であるので、倍精度の実数のベクトルに渡すとき変換を要する。
変換関数、{\bf double2float}と{\bf float2double}は、この目的でclib/double.cの中に定義されている。
例えば、もし3x3の実数行列があり、CFのいう名のCの関数にそれを倍精度実数の行列として渡したいなら、
以下のように使用すればよい。
\begin{verbatim}
     (setq mat (make-matrix 3 3))
     (CF (float2double (array-entity mat)))
\end{verbatim}

Cの構造体は、{\bf defstruct}マクロにより定義することができる。
{\bf defstruct}は、次のようなフィールド定義書式によりstruct-nameを受け取る。

\begin{verbatim}
     (defcstruct <struct-name>
        {(<field> <type> [*] [size])}*)
\end{verbatim}
たとえば、以下に示す構造体の定義は、つぎの{\bf defstruct}によって表現される。
\begin{verbatim}
     /* C definition */
     struct example {
        char  a[2];
        short b;
        long  *c;
        float *d[2];};

     /* equivalent EusLisp definition */
     (defcstruct example
        (a :char 2)
        (b :short)
        (c :long *)
        (d :float * 2))
\end{verbatim}

\begin{refdesc}

\macrodesc{load-foreign}{objfile \&key symbol-input symbol-output (symbol-file objfile) ld-option)}{
Euslisp以外の言語で書かれたオブジェクトモジュールをロードする。
Solaris2において、{\bf load-foreign}は{\em :entry}パラメータにnull文字列を
与えた{\bf load}を呼び出す。
コンパイルされたコードのオブジェクトが返される。
この結果は、後に{\bf defforeign}を呼び出すことによって
モジュールの中の関数のエントリーを作ることが
必要である。
ライブラリーは{\em ld-option}に指定することができる。
しかしながら、ライブラリの中に定義されたsymbolはデフォルトのsymbol-outputファイルで
獲得することができない。
ライブラリで定義された関数の呼び出しをEuslispに許可するために、
{\em symbol-output}と{\em symbol-file}が明示的に与えられなければならない。
（もし、{\em objfile}からのみそれらを参照するならば、これらの引き数は必要ない。）
{\bf load-foreign}は、指定されたライブラリとグローバル変数と一緒に{\em objfile}をEuslispのコアにリンクし、
リンクされたオブジェクトを{\em symbol-output}に書き込む。
それから、{\em symbol-file}の中のsymbolは、検索され、他言語モジュールの中にリストアップされる。
{\em symbol-file}のデフォルトが{\em objfile}であるので、もし{\em symbol-file}が与えられないなら、
{\em objfile}に定義されているsymbolのみ認識される。
{\em objfile}とライブラリの両方のグローバルエントリーをすべて見るために、
{\bf load-foreign}の最初のプロセスリンクの結果であるリンクされた(マージされた)symbolテーブル
は確かめられなければならない。このような理由で、{\em symbol-output}と{\em symbol-file}の両方に
同一のファイル名を与えなければならない。

以下に示されるように、中間のsymbolファイルは{\bf unix:unlink}によって
削除することができる。
しかしながら、もし同じライブラリを参照する２つ以上の他言語モジュールをロードするとき、
ライブラリの2重化を避けたいなら、{\em symbol-output}引き数を使用しなければならない。
上記の例として、"linpack.a"のすべての関数をロードしており、
次に"linpack.a"の関数を呼び出している他のファイル"linapp.o"を呼びだそうとしていると仮定する。
次の{\bf load-foreign}呼び出しは、"euslinpack"をunlinkする前に発行しなければならない
{\tt (load-foreign "linapp.o" :symbol-input "euslinpack")}。
{\bf load-foreign}と{\bf defforeign}のもっと完全な例は、{\tt *eusdir*/llib/linpack.l}で
見ることができる。
}
\begin{quote}
\begin{verbatim}
(setq linpack-module
    (load-foreign "/usr/local/eus/clib/linpackref.o"
        :ld-option  "-L/usr/local/lib -llinpack -lF77 -lm -lc"
        :symbol-output "euslinpack"
        :symbol-file "euslinpack"
        ))
(unix:unlink "euslinpack")
\end{verbatim}
\end{quote}

\macrodesc{defforeign}{funcname module cname paramspec resulttype}{
他言語モジュールの中の関数エントリーを作る。
{\em funcname}は、Euslispに作られるsymbolである。
{\em module}は、{\bf load-foreign}によって返されるコンパイルされたコードのオブジェクトである。
{\em cname}は、他言語プログラムの中で定義されているCの関数の名前である。
その名前は"\_myfunc"のような文字列である。
%Sunのccでは、無条件に関数名の前に"\_"が付けられることに注意。
{\em paramspec}は、パラメータの型指定のリストである。
それは、EuslispからCの関数に引き数を渡すときに、データの型変換と強制(coercion)を行うために使用される。
データ変換がなかったり、あるいは型チェックが必要ないとき、{\em paramspec}はNILで構わない。
{\tt :integer, :float, :string}, {\tt (:string n)}の内の１つが{\em resulttype}に与えられなければならない。
{\tt :integer}は、Cの関数がchar,short,int(long)のいずれかを返すことを意味する。
{\tt :float}は、返す値がfloatあるいはdoubleのときに指定する。
{\tt :string}は、C関数がstringへのポインターを返すことを意味し、
EuslispはEuslispの文字列に変更するためにstringにlong-wordのヘッダーを追加する。
文字列の長さは{\bf strlen}によって見つけられる。
stringの直前に書き込まれるヘッダーは、悲惨な結果を引き起こすことがあることに注意。
もう一方で、{\tt (:string n)}は、安全だが遅い。なぜなら、
{\bf n}の長さを持つEuslispの文字列が新しく作成され、Cの文字列の内容が
そこにコピーされるからである。
{\tt (:string 4)}は、整数へのポインターを返すCの関数に使用できる。
FORTRANユーザーは、FORTRANの関数あるいはサブルーチンのあらゆる引き数は、
call-by-refferenceによって渡されることに注意すべきである。
したがって、1つの整数あるいは実数型の引き数でさえFORTRANへ
渡される前に整数ベクトルあるいは実数ベクトルに
置かれなければならない。}

\macrodesc{defun-c-callable}{funcname paramspec resulttype \&rest body}{
他言語のコードから呼び出すことができるEuslispの関数を定義する。
{\em funcname}は、Euslispの関数として定義されているsymbolである。
{\em paramspec}は、{\bf defforeign}の中の型指定のリストである。
{\bf defforeign}のparamspecと違い、{\bf defun-c-callable}のparamspecは、
関数が引き数を全く受け取らない場合以外、省略することができない。
{\tt :integer}は、int,char,shortのすべての型に使用すべきである。
{\tt :float}は、floatとdoubleに使用する。
{\em resulttype}は、Lisp関数の型である。
{\em resulttype}は、型のチェックあるいは整数から実数に型の強制を
必要とする場合を除いて、省略することができる。
{\em body}は、この関数がCから呼び出されるとき、実行されるlisp表現である。
{\bf defun-c-callable}で定義されている関数は、Lisp表現からでも
呼び出すことができる。
{\bf defun-c-callable}は{\em funcname}を返す。
その返り値は、symbolのようであるが、そうではなく、symbolのサブクラスである
{\bf foreign-pod}のインスタンスである。}

\funcdesc{pod-address}{funcname}{
{\bf defun-c-callable}で定義されたCで呼び出し可能なLisp関数{\em funcname}における
他言語とEuslispとのインターフェースコードのアドレスを返す。
これは、他言語プログラムにLisp関数の位置を知らせるために使用される。}

\macrodesc{array-entity}{array-of-more-than-one-dimension}{
多次元配列の要素を保持する１次元ベクトルを返す。
これは、多次元あるいは一般の配列を他言語に渡すために必要である。
しかし、１次元のベクトルは直接渡すことができる。}

\funcdesc{float2double}{float-vector \&optional doublevector}{
{\tt float-vector}を倍精度実数の表現に変換する。
その結果は、{\tt float-vector}であるが、最初の引き数の長さの２倍になっている。}

\funcdesc{double2float}{doublevector \&optional float-vector}{
倍精度実数表現が単精度の{\tt float-vector}に変換される。}

\end{refdesc}
\newpage
