このF言語の関数は、このように perl の関数にみられるような sub を記述するなどの癖がありません。戻り値は中間言語としてシェルを使っているため、2つあります。1つ目は、シェルが理解することのできる文字列型(C言語の char)です。2つ目は、まれに使われることがあるそのコマンドがエラーなく終了したかどうかの終了ステータス値です。通常は文字列型を使いますから、型の明示は割愛してあります。
このF言語は、C言語と同じく関数の集合体からなっています。それらはプロセスの集合体ですから、説明するまでもなく個々に独立しています。その結果、再帰もプログラムすることができます。ここではよく再帰に用いられる『ハノイの塔』プログラムを例に上げてみます。
/* Tower of Hanoi game.
file name: hanoi
execution: func 'hanoi(n)'
n: number of discs (n≧0)
content: move discs from pole A to pole C. */
§7.制御構造
何度も述べているように、このF言語は完全なコマンドの集合からなります。したがって、if や while などの制御構造もその例外ではありません。今までのスクリプトといえば、シェル自身が独自の制御構造を持っていて、その制御構造にしたがってプログラムしなければなりません。しかし、このF言語では、従来のスクリプトでは必須となっている制御構造は存在しないのです。「それでは、プログラムできないのでは?」と思われるかも知れません。ご安心下さい。制御構造はユーザが個々に作成し、それを元にプログラムの流れを制御するのです。このとき、シェルは一切関係ありません。
現在のシェルは、コンピュータの利用環境が複雑高度となるそれに比例する形で改良が加えられ、新たな名前のシェルとして進展してきています。コンピュータの利用は、今後も更に複雑多様化するのは誰がみても明らかです。それゆえ、いずれまたユーザ・インターフェースを改良するために新たな名前のシェルが出てくるであろうとの予測が可能です。これでは、将来もシェルに振り回されるのは当然といえます。ここでは、この昔のままの発想を改め、機能を分散して必要な機能を逐次追加できるようにしてみてはどうか、という提案なのです。中でも if などの制御構造は様々なパターンが考えられ、到底1つの制御構造で処理するには無理があるその代表といえます。
/* Using IF control utility command.
file name: prg_if
execution: func 'prg_if(file_name)' */
#define /nil /dev/null
%main($file) { /* if.z はコマンドです! */
if.z -s '((func %select($file)) != 0)' '{
echo " Can not find your <$file> file!!";
}' else '{
echo;
more $file;
}'
}
%select($name) {
echo " You select the <$file> file.";
ls $file >/nil;
}
これは、あるファイルを more で参照するプログラムです。制御コマンドの if.z は、%select() 関数を実行し、エラーがなければ more 参照し、エラーならばその旨表示して終る流れを演出しています。終了ステータスによって制御の流れを変える役割を担っています。当然、人それぞれですから「見づらい」とか「ダサイ」とか思われるはずです。ここでは、無理やり if.z の文法を押し付けるつもりはありません。気に食わなければ個々に作成してそのコマンドを使えば良いのです。
この制御は、将来もこのまま使えるとは思えず、より機能が高度化すると思われます。そのとき、このコマンドとして自由に取り換えられる利点は、効率的であると同時に理にかなっているいえます。シェルをまるごと取り換える必要はありません。その時点で改良が必要な部分だけを取り換えれば良いのです。
ところであなたは、「コンピュータに命令を与えて実行させる」ことを行っていませんか?この文の流れを考えてみて下さい。それは
while (コマンドを選んで) {
commands; /* 実行させる */
}
と記述できることをご存知でしょうか。今はビジュアル・シェルが当り前になっていて、それはひとまとめのシェルであるとするのが常識となっています。でも、このF言語の考えでは、この while の部分だけを作れば良いのが分かります。実際、OS-9 のフロント・エンドは while コマンドで作られ、CUI ながらも、コマンドを打ち込むことことないスケルトン(透過)な環境が実現されています。要するに、while はそのコンピュータ・システムのフロント・エンドの性格があり、それは GUI とするマウス制御としても良いし、CUI としても良く、シェルとは独立して開発することができるのです。そしてそれは、ユーザーの自由です。
shmid や offset 値はアスキー表示されますが、32ビットの4バイト枠をいつも使い切っている訳ではありません。ここでは、Cプログラミングの負担を軽減するために、アスキー表示枠(AREA)は17バイトの定数を用いています。けれども、値が小さなときは余りの部分が出てきてしまいます。そこで、これを補うために CAN で埋めています。以上が変数の内部構造です。ではC言語でコマンドを作る場合は、その都度表示に合わせるようにしなければならないかというと、そのようなことはなく、それは以下のように定書式となっています。
#define AREA 17 /* the F pointer size */
#define CAN '\x18' /* cancel code */
char
*shmaddr, /* pointer of shared memory */
*ptr; /* user access data pointer */
int
offset, /* from shmaddr header */
shmid; /* segment ID of shared memory */
int job_sscan(int *, char *);
int get_ptr(char *, int);