RVTLの紹介と使い方
rvtl は Tiny Basic系のプログラミング環境です。アセンブラで作成しているため、 20キロバイトほどの非常に小さいプログラムですが、豊富な機能を持っています。
BASIC言語系のインタプリタ、エディタ、コマンドラインのヒストリ機能とファイル名補完、 組み込みコマンドとしてLinuxの基本コマンド(ls, cat, cd, mkdir, rm, mount, unmount, chmod, mv, rmdir, sync, pwd) や上級者向けコマンド (chroot, pivot_root, swapon, swapoff, exec)、そしてグラフィックで比較的簡単にゲームを作成できるように フレームバッファに対するパターン転送 (スプライト描画)、ライン描画などの コマンドも用意されています。擬似乱数の生成には高速で上質な Mersenne Twister を 使用しています。
Linux カーネル 2.0 から 2.6 さえあれば、ディストリビューションの種類に関係なく 実行できます。
rvtl は特殊な文法 (基本的にすべて代入文) を持つCASUAL や VTL の子孫と なる言語です。 特殊といっても、日本では、GAME III が有名です。古くから 趣味でプログラミングしていた人には懐かしい言語ではないかと思います。 ラベルを使えるように文法を拡張しています。文法が単純なためインタープリタ でも高速に動作します。マシン環境に依存しますが、1秒間に100万命令程度は 実行できると思います。
rvtl は、歴史的な価値だけでなく、緊急時の限られた資源で実用となるような 機能を持っています。 rvtl を init プロセスとして使って Linux カーネルに 20キロバイト程度の initrd.gz を加えた 1FDLinux を作成することもできます。 カーネルの機能を制限すれば 720K の 1FDLinux も可能かもしれません。
若干の制限はありますが、rvtl は子プロセスの起動、パイプ、リダイレクト といったシェルとしての機能も持っています。 先頭行を #!/usr/bin/rvtl として実行パーミッションを付加するとシェルスクリプトとして使うことも できます。
- 2010/02/28
- 最近のLinuxカーネル(i386, x86_64) にはセキュリティを向上させるために、Address Space Layout Randomization というものが実装されています。プロセスで使うアドレス空間を起動する度にランダムに配置するものです。 rvtl-3.03以前のrvtlは影響を受けてしまいます。特にメモリを多く使う rvtlwiki では、 sys_brkでメモリを追加取得しているため、「Segmentation fault」が発生します。 rvtl-3.03以前でも以下のコマンドでヒープ領域のランダム化を抑止すれば正常に動作します。
- rvtlのASLR対応版
- rvtlのi386版 (rvtl-3.04)を brk randomization に対応するように変更しました。 変更点は rvtlのプログラムコード領域 と配列領域をBSSセグメントから ヒープ領域への移動です。 今のところARMやPowerPCのカーネルはASLR対応になっていないのでi386版だけです。
# echo 1 >/proc/sys/kernel/randomize_va_space
ダウンロード
rvtl-3.04.tar.gz (123KB)
- ver.3.03 から ver.3.04 の変更点
- Linuxカーネルの Address Space Layout Randomization に対応。
- ver.3.02a から ver.3.03 の変更点
- |ud を追加 (URL デコード)
- |ve で % にバージョン番号を返す。
- A*=e のコピーバイト数上限を 256KB に変更。
- A*=A の場合はコピーせずバイト数を%に返す。
- 文字列出力を効率化
- $*=A の文字数制限の撤廃
- ver.3.02 から ver.3.02a の変更点
- |zz (システムコール) で Segmentation fault を修正
- ver.3.01 から ver.3.02 の変更点
- カーネル2.6でフレームバッファが使用できないのを修正
- 外部コマンドの起動ができなかったのを修正
- 環境変数の読み込み「\\式」を追加
- サンプルプログラムの追加、修正
- ver.3.00 から ver.3.01 の変更点
- )=""、(=""、<=""、>="" の動作不良の修正
- 引数のファイルの再読み込み現象の修正
- 数値入力、文字列入力時のヒストリ、ファイル名補完の行頭ずれを修正
- A*="文字列" の機能追加
- サンプルプログラムの追加、修正
- ver.2.02 から ver.3.01 の変更点
- ラベル参照の不具合を修正
- 式のエラー表示を改善
- コマンドライン引数の一部を rvtl から参照可能とした。
- ファイル名先頭アドレスを指定するファイルの読み書きコマンドを追加
- 文字列のコピーと1行入力を追加
- 文字列のアドレスを引数とする組み込みコマンドを追加
- 点の描画コマンドを追加
- サンプルプログラムの整理
- ドキュメントの改訂
64bit Linux(x86-64) 用はこちらのページ。
Linux Zaurus (ARM) 用はこちらのページ。
玄箱(PowerPC) 用はこちらのページ。
rvtlで書いたWikiエンジンはこちらのページ。
rvtlで書いたコンパイラ(rvtlc)はこちらのページ
インストールとアンインストール
rvtl を展開したディレクトリで ./rvtl と入力するだけで、共有ライブラリや カーネルのバージョンに関係なく使用できます。より便利に使うには、パスの 通ったディレクトリに rvtl をコピーすることをお勧めします。 デフォルトではシェルスクリプトとして使う場合を考えて /usr/bin に置くように しています。
# cp rvtl /usr/bin
Linux カーネルの 2.0 から 2.6 のどのカーネルを使っていても rvtl の バイナリをコピーするだけで使うことができます。あえてアセンブルする場合は、 nasm-0.98 が使用できる環境で make して下さい。 スーパーユーザで make install すると /usr/bin に rvtl がコピー されます。
rvtl を rvtlw という名で起動すると、rvtlのプログラムが終了(#=-1)したり エラーでrvtl自身が終了します。 シンボリックリンクを次のように作成すると rvtlw で起動できます。
# cd /usr/bin # ln -s rvtl rvtlw
rvtl のアンインストールは単に rvtl を削除するだけです。
簡単なプログラム
rvtl は BASICのコマンドを記号で置き換えたような言語です。 最近の言語にはない特徴として、各行の先頭には行番号を必要としています。 慣習では、10単位の行番号を使います。後から行を挿入する時に備えるため です。後ほど行番号を整形するプログラムを紹介します。
rvtlを起動すると次のように表示されます。
$ rvtl RVTL v.3.04 2010/02/28, Copyright 2002-2010 Jun Mizutani RVTL may be copied under the terms of the GNU General Public License. <0140> _
「<0140>」はプロンプトで、このあとに rvtl のプログラムを入力、編集したり、 実行するコマンドを入力します。<>内の数値はプロセスIDの16進数表示となって います。子プロセスで rvtl を起動している場合や /etc/init として動作して いる場合の識別に使いますが、通常は気にする必要はありません。
プロンプト以降にコマンドやプログラムを入力します。ここでは簡単な編集機能 があり、左右矢印キー、ctrl-F、ctrl-Bでカーソル移動、ctrl-D でカーソル位置 の文字を削除します。ctrl-H、BackSpaceはカーソルの直前の文字を削除します。 上下矢印キー、ctrl-N、ctrl-Pでヒストリーに保持されている最新の異なる16行 を呼び出すことができます。TABキーでファイル名補完が働きます。
入力行の最初 (空白を除く) が数字ならば、プログラムとしてメモリに格納 されます。プロンプトのあとに次のように入力してみてください。 入力されたプログラムは行番号の順に自動的に整列されます。行を挿入する には、すでに入力されて行番号の間の行番号をつけます。例えば、行40と 行50の間に挿入するには行番号として 45 を使います。
10 "A=" A=? /
20 "B=" B=? /
30 "A+B=" ?=A+B /
40 "A-B=" ?=A-B /
50 "A*B=" ?=A*B /
60 "A/B=" ?=A/B /
70 "Hit Any Key (q:quit) :" C=$ /
80 ;=(C='q')|(C='Q') #=-1
90 #=10
ダブルクォート「"」で囲まれた文字列は、そのまま表示されます。A=? は BASIC のINPUT文に相当して、キーボードから入力された数値を変数 A に 代入します。 「/」は改行を出力します。 ?=A+B などは「?=」に続く式の 値を10進数で表示します。行番号 70 の C=$ はキーボ−ドから1文字入力 して、変数 C に格納するコマンドです。コマンドとコマンドの区切りは1つ 以上の空白(半角スペース)で、コマンド内 (例えば式中) に空白を使うこと はできません。行番号 80 の「;=」は IF 文に相当して、続く式を計算して 結果が 0 ならば次の行の実行に移ります。計算結果が 0 以外なら同じ行の 命令を実行します。この場合は入力文字が「q」または「Q」のときEND文で ある #=-1 を実行してプログラムは終了します。行番号 90 の #=10 は GOTO文に相当して、「#=」に続く式を計算して結果の行番号にジャンプします。
入力したプログラムを確認するには、プロンプト「<xxxx> 」のあとに プログラムリストを表示するコマンドである 0 (ゼロ)を入力します。 30-60 のように行番号30から行番号60までを部分的にリストを表示する こともできます。50+4 のように指定した場合は、行番号50から4行を表示 します。「10」のように番号だけを入力すると、その番号と同じ行番号の 行が削除されます。変更したい行がある場合は、「40!」のように行番号の 直後に「!」をつけると、「40 "A-B=" ?=A-B /」のように表示されて編集 (修正) ができます。(プログラムの編集を参照)
実行するには 「#=1」と入力します。実行中のプログラムを強制的に終了 させる場合は ctrl-C (コントロールキーとCを同時に押す) を入力すると プロンプトを表示します。
rvtl 自身を終了するには「~ (チルダ) 」を入力して Enter を押します。 「~」の入力は日本語キーボードでは、シフトキーを押しながら「^」または シフトキーを押しながら「半角/全角」(英語モードの場合)で入力できます。
vtl ディレクトリの fb_demo.vtl はフレームバッファを操作する機能の デモです。bmp ファイルをロードするため、vtl ディレクトリに移動した後 に実行してください。フレームバッファを使ったグラフィックのプログラム も高速に実行できます。
プログラムの編集
入力行の先頭(空白を除く)が数字の場合は、数字を行番号として認識して 編集モードになります。行番号の直後に入力される記号によって、プログラムの 表示、編集、挿入、削除ができます。
- 行番号 0 ならプログラム全体を表示します。
- 行番号の直後が - なら指定範囲内の行を表示します。(例 100-200)
- 行番号の直後が + なら行番号以降の20行を表示します。
+ の後ろに表示行数を指定できます。(例 100+30) - 行番号の直後が ! なら指定した行番号の行を編集することができます。
このとき行番号を変更すると、変更した行が別に挿入され、元の行は
そのまま残ります。
左右矢印キー、ctrl-F、ctrl-Bでカーソル移動、ctrl-D でカーソル位置の 文字を削除します。ctrl-H、BackSpaceはカーソルの直前の文字を削除 します。上下矢印キー、ctrl-N、ctrl-Pでヒストリーに保持されている 最新の異なる16行を呼び出すことができます。
- 同じ行番号の行が存在すれば入力された行と置換します。
- 入力された行と同じ行番号がなければ入力された行を挿入します。
- 行が行番号のみの場合は対応する行を削除します。
コマンドの解説
rvtl のコマンドを BASIC のコマンドを見出しとして説明します。 行番号つけたプログラムを #=1 で実行する間接モードと、プロンプトのあと 行番号なしで直接実行する直接モードがあります。FOR-NEXT、DO-UNTIL、 GOSUBは間接モード専用ですが、その他のコマンドはどちらのモードでも 実行できます。以下の説明の内、Aは任意の変数、e と n は任意の式を 表しています。
コメント
: の後は、コメントとして行末まで無視されます。 #! もコメントとみなされます。プログラムの先頭行に次のように記述して おいて、実行権限をつけておくとシェルスクリプトやPerlのスクリプトの ように直接実行できます。
#!/usr/bin/rvtl
100 A=?
110 B=?
120 ?=A+B
代入文
右辺の式の値を左辺の変数に代入します。
200 A=B/100+12
代入文の特殊な形式として文字列からなる配列(255文字まで)を別の 領域の配列にコピーする命令があります。配列のためのメモリ領域を 確保しておく必要があります。文字列定数を代入する形式もあります。 実行後、% に文字数を返します。 文字列を直接指定した場合は 256 バイト以内に限定されます。
200 A*=e : 256 キロバイトまで
210 B*="ABCDEFG" : 256 バイト以内
コマンドライン引数をコピーする場合は範囲チェックをOFF「[=0」に した後に実行してください。
200 [=0 A*=\0 [=1
コピー先とコピー元のアドレスが同じ場合はコピーは実行されず、 % に文字が 0 となるまでの文字数を返します。文字列長を求めることが できます。
200 A*=A ?=%
PRINT文
標準出力に数値や文字を書き出す命令です。
| ?=e | 式の値を10進数で出力。 |
| ?(n)=e | 式の値を10進数を n 桁右寄せで出力。 |
| ?[n]=+e | 式の値を10進数を上位桁を0で埋めた n 桁で出力。 |
| ?$=e | 式の値を16進数2桁で出力。 |
| ?#=e | 式の値を16進数4桁で出力。 |
| ??=e | 式の値を16進数8桁で出力。 |
| ?*=e | 式の値を符号無し10進数で出力。 |
| ?{n}=e | 式の値を8進数n桁で出力。 |
| ?!n!=e | 式の値の下位を2進数n桁で出力。 |
| $=e | 式の値を文字コードとして出力。 |
| $$=e | 式の値を2文字の文字コードとして出力。 |
| $#=e | 式の値を4文字の文字コードとして出力。 |
| $*=e | 式の値を先頭アドレスとするASCIIZ文字列を出力。 |
| "STR" | 文字列を出力。 |
| / | 改行を出力。 |
| .=e | 空白を式 e の値の数だけ出力。 |
INPUT文
入力した値を変数に代入する命令です。
| A=? | 10進数値入力(非数値の場合0が入力)。 |
| A=$ | 1文字入力。 |
| A=@ | リアルタイム文字入力。入力がない場合は0が返ります。 |
| A*=$$ | Aの示すアドレスに1行入力(編集機能付き)。 入力文字数が % に返ります。 |
GOTO文
指定した行番号にジャンプします。 #=^Label のように飛び先をラベルとした場合はラベル宣言(^Label) した行の次の行にジャンプします。
例:
#=100
#=^STOP
行番号の部分に式を記述できます。(例 #=N*10+2000)
IF文
式の値が偽(0) なら次の行から実行します。真の場合は次の文を 実行します。
例:
;=e "A=" A=?
GOSUB文
指定した行番号にジャンプします。飛び先で ](リターン文)が実行 されると次の文から実行が再開されます。 !=^Label のように飛び先をラベルとした場合はラベル宣言(^Label) した行の次の行にジャンプします。
例:
!=100
!=^LINE
行番号の部分に式を記述できます。(例 #=N*10+2000)
RETURN文
GOSUB文(!=)の次の命令に戻ります。GOSUB - RETURN は最大32回 ネストすることができます。
例:
100 ^SUB
110 "do something"
120 ]
FOR - NEXT文
FOR文は代入文にカンマと終了値を加えた形式で記述します。 NEXT文は @=A+1 のようにFOR文で使った変数を@=の直後に置きます。 増分は +1 以外の値も可能です。また乗算を使用することもできます。 通常、繰り返し回数が決まっている場合に使います。
100 A=1,10
110 "do something"
120 @=A+1
1行中にFOR-NEXTループを置くこともできます。この例では 1 から 10 までの数値を順に詰めて表示して最後に改行します。
100 A=1,10 ?=A @=A+1 /
次のように降順にすることもできます。
100 A=10,1
110 "do something " ?=A /
120 @=A-1
DO - UNTIL文
UNTIL文の式 e の値が偽(0)の場合には @ (DO) に戻ります。 真(0以外)なら次の文を実行します。NEXT文と異なり式を括弧で囲む 必要があります。繰り返し回数が実行するまでわからない場合に 便利です。
100 @
110 "do something"
120 @=(e)
END 文
実行中のrvtlのプログラムを停止します。rvtl自身は終了しません。
#=-1
NEW コマンド
行番号付きでメモリに格納された rvtl のプログラムを消去します。
&=0
SAVE コマンド
rvtlプログラムをファイル名を指定してファイルに出力します。
<="ファイル名"
LOAD コマンド
ファイル名で指定された rvtlプログラムをロードします。すでに メモリに格納されているプログラムは消去されずにロードしたプログラム が挿入されます。必要ならば NEW (&=0) を先に実行してください。
>="ファイル名"
LIST コマンド
プログラムのリスト表示と編集のためのコマンドです。
| 0 | rvtlプログラム全体のリスト |
| 100- | 行番号100以降すべてのリスト |
| 100-500 | 行番号100以降500までのリスト |
| 100+ | 行番号100以降の20行のリスト |
| 100+30 | 行番号100以降の30行のリスト |
| 100! | 行番号100の1行を表示して編集 |
RUN コマンド
直接モードで GOTO文を使ってrvtlのプログラムを実行します。 実行開始行番号を指定することができます。通常は #=1 とします。 実行中のプログラムを強制的に停止させるにはコントロールキー を押しながらC (ctrl-C) を押します。
#=1
ファイル書き出し
{ (ファイル先頭位置) と } (ファイル末位置) で指定した範囲を ""に囲まれたファイル名のファイルとして書き込みます。 0で終了する文字列の先頭アドレスを渡す形式も使用できます。
(="ファイル名"
(*=A
ファイル読み込み
""に囲まれたファイル名のファイルを { (ファイル先頭位置) で指定 されたメモリアドレスに読み込みます。読み込んだファイルサイズは }-{ (ファイル末位置 - ファイル先頭位置) で求めることができます。 0で終了する文字列の先頭アドレスを渡す形式も使用できます。
)="ファイル名"
)*=A
ファイル先頭を設定
ファイル書き出しコマンドの書き込み先頭位置を設定します。
{=e
ファイル末を設定
ファイル書き出しコマンドの書き込み最終位置を設定します。
}=e
メモリ最終(brk)を設定
メモリ最終(brk)を変更することができます。例えば *=*+10000 では メモリを10000バイト広げられます。
子プロセスの起動
子プロセスを起動します。実行ファイル名はフルパスで指定して下さい。 | を使ったパイプと > による出力のリダイレクトが可能です。
,="/bin/ls -lt | /usr/bin/grep e >test.txt" "DONE" /
上記のようにコマンドの後ろに文が続かない場合は、次のような 省略記法が使えます。
, /bin/ls -lt | /usr/bin/grep e >test.txt
0で終了する文字列の先頭アドレスを渡す形式も使用できます。 文字列の先頭アドレスを変数に設定した後に実行します。
,*=A
配列範囲チェック
配列を使って任意のメモリアドレスにアクセスすることができます。 デフォルト( [=1 )では , から * の範囲のメモリ以外にアクセスすると 範囲チェックによりエラーとなりますが、[=0 を実行するとエラーに なりません。必要な部分のみを [=0 と [=1 で囲むようにします。 フレームバッファを使う場合や文字列のコピーでコマンドライン引数を 参照する場合(A*=\0等)には必須ですが、不正な領域にアクセスすると セグメンテーションフォルトにより rvtl が終了してしまうことに注意 して下さい。
100 [=0
110 f[200]=$FFFFFFFF
120 [=1
擬似乱数シード設定
乱数は rvtl の起動直後には毎回同じ系列で生成されるため、rvtl の 起動後には常に同じ乱数が帰ります。いつも異なる乱数を生成する ためには、擬似乱数のシード (ネタ?) に別の値を設定します。 例えば、擬似乱数のシードを現在時間のマイクロ秒に設定「A=_ `=%」 すると起動のたびに予想できない異なる系列の乱数列を生成することが できます。
`=e
コード先頭アドレス設定
rvtl のプログラムを格納する領域の先頭は、rvtl の起動時に決定した 変更できない値「,」がコード先頭アドレス「=」に設定されています。 メモリ内に複数のプログラムを格納してコード先頭アドレス「=」を 変更することで複数のプログラムを切り替えて使えます。
==e
マイクロ秒単位の sleep
停止時間をマイクロ秒単位で与えてプログラムを一時停止します。 マシンの処理速度が異なっても同じタイミングで動作させたい場合など に使用します。
_=e
rvtlの終了
チルダ「~」で rvtl 自身の実行を終了します。 「~」の入力は、シフトキーを押しながら「^」、またはシフトキーを 押しながら「半角/全角」で入力できます。
変数と配列
変数は32ビットの数値を格納する単純変数と 1,2,4 バイトの値を扱う配列変数 があります。
単純変数は A から Z と a から z までの 52 個の変数を使うことができます。 変数名は 1 文字だけですが、冗長型として Integer, Command, ok などのよう に長い名前を使うことができます。 この場合には I と Integer は同じものと みなされることに注意してください。単純変数を格納する領域はあらかじめ 用意されています。
配列は C 言語の配列のように配列を格納する領域の先頭アドレスを配列名に設定 しておく必要があります。以下の例では変数Aに空きメモリ先頭アドレスを代入し、 変数Bには変数Aより100バイト大きい値を設定しています。これで変数Aは100 バイトの領域を配列として使用できます。1バイト配列では A(99)まで、2バイト 配列では A{49}まで、4バイト配列ではA[24]までが B(0) と重ならないでアクセス できます。配列 B は残りの空きメモリをすべて使用可能です。システム変数「*」 は rvtl のプログラムの大きさ + 空きメモリ = 256Kバイトが初期値になって いますが、システム変数「*」を再設定すればメモリの許す限りの領域をアクセス できます。
100 A=&
110 B=A+100
120 A(99)=123
130 B[5]=456
140 ?=B[5]
rvtl を実行中のプロセスのメモリイメージ
変数は変数専用スタックに格納(プッシュ)することができます。例えば +ABC の 場合は、変数が A、B、C の順にスタックに保存されます。1文字以上の長さの 変数名の場合でも先頭の1文字だけを指定します。スタックから戻す(ポップ)場合は -CBA とプッシュした順の逆に戻します。 サブルーチンの先頭で使う変数をプッシュ、リターンの前でポップすることで、 変数を局所変数として再帰的にサブルーチンを呼び出すことができるようになります。 「+=式」で式の値を変数を介さず変数スタックに格納することができます。 また、式中で「;」を参照すると変数スタックトップを返します(ポップ)。
関数
式中で関数の値を使用するには、rvtl ではシステム変数を参照する形式になります。 値を参照できるシステム変数には次のものがあります。
| # | 実行中の行番号を保持 |
|---|---|
| % | 直前の除算の剰余、直前の _ 参照の usec、文字列コピーの文字数を保持 |
| & | コードの最終使用アドレス+1 |
| ) | 読み込みサイズ保持 |
| * | メモリ最終位置を保持 |
| = | プログラム先頭アドレス |
| [ | 配列範囲チェック |
| ^ | ラベルの次行先頭アドレス |
| _ | 秒単位のUNIX時間を返します。同時にマイクロ秒が % に設定されます。 |
| { | ファイル先頭位置 |
| | | エラーコード保持 |
| } | ファイル末位置 |
| , | アクセス可能先頭アドレス |
| ` | Mersenne Twister による乱数を返す。 |
| . | コンソールの大きさ(ウィンドウサイズ)を上位16ビットに幅、下位16ビットに高さを文字単位で返します。 |
| ; | 変数スタックトップを返します(ポップ)。 |
| _ | 現在の秒を返し、% にマイクロ秒を返す。 |
| ? | 標準入力から10進数値を得る。 |
| $ | 標準入力から文字を得る。 |
| @ | 標準入力から文字を得る。入力がなければ 0 を返す。 |
| \式 | 式の示す番号の引数文字列の先頭アドレスを返す。番号は0から。 |
| \\式 | 式の示す番号の環境変数文字列の先頭アドレスを返す。番号は0から。 |
式
式は、数値、単純変数または配列変数と以下の演算子で構成され、32ビットの 値を返します。演算子の優先順位は ( ) 内が優先され、単項演算子と関数が 次に優先されます。 算術演算子と比較演算子は同じ優先順位として扱われ、左から右に順次実行さ れます。乗算と除算も加減算と同じ優先順位であることに注意してください。
通常の計算では、乗算と除算は加減算に優先されないことに注意すれば十分で すが、A=B*--+(10-20) のように複雑な式の例を考えて見ます。
最初に B と乗算する数値または変数があることが認識されます。その値に対し ては符号反転する必要があることが記憶されます。さらに符号反転、さらに 絶対値を求めることを記憶します。その後 ()内に優先的に処理する必要のある 式があるため、(10-20)を評価して -10 という結果を得ます。これまでに記憶 してきた処理を順次実行することで ( の前の + により絶対値の 10 が得られ、 2度の符号反転の結果、結局 10 という値をBと乗算することがわかります。 結果として、A=B*10 という計算になります。
算術演算子
| A+B | 加算 |
| A-B | 減算 |
| A*B | 乗算 |
| A/B | 除算 |
| A&B | ビット論理積 |
| A\B | 無符号除算 |
| A^B | 排他的論理和 |
| A|B | ビット論理和 |
| A>>B | 右シフト |
| A<<B | 左シフト |
単項演算子
| -A | Aの符号反転 |
| +A | Aの絶対値 |
比較演算子
| A=B | A と B が等しければ 1 を返し、それ以外は 0 を返す。 |
| A<B | A が B より小さければ 1 を返し、それ以外は 0 を返す。 |
| A>B | A が B より大きければ 1 を返し、それ以外は 0 を返す。 |
| A>=B | A が B が以上ならば 1 を返し、それ以外は 0 を返す。 |
| A<=B | A が B が以下ならば 1 を返し、それ以外は 0 を返す。 |
| A<>B | A と B が等しくなければ 1 を返し、それ以外は 0 を返す。 |
組み込みコマンド
rvtl はコマンドを ,="/usr/bin/bash" のように実行することができますが、 最低限必要なコマンドを組み込みコマンドとして持っています。 Linux のコマンドのうち rm、ls、cd、chmod、chroot、pwd、exec、mkdir、 mv、rmdir、sync、mount、umount、cat、swapon、swapoff、pivot_root に 相当する組み込みコマンドがあります。
まずは、比較的使用頻度の高いコマンドです。rvtl をシェルスクリプトとして 使う場合や、rvtl 中から ,="/usr/bin/ls -l" を実行するのが面倒な場合に使 います。
|ls*=A のように組み込みコマンドに続けて「*=式」とすると式の値を先頭 アドレスとするASCIIZ文字列 (0で終わる文字列) を組み込みコマンドの 引数として渡すことができます。|sy や |fb? のように引数を必要としない コマンドでは使えません。
【注意】 引数を必要とする組み込みコマンドは、行末までが引数と判断されます。 組み込みコマンドの後ろに文(マルチステートメント)を置かないように して下さい。
ファイルの内容表示
cat コマンドに相当します。 指定したファイルの内容を表示します。
|ca file
カレントディレクトリ内容の表示
ls コマンドに相当します。 カレントディレクトリのファイルを表示します。8進数で表した パーミッション、ファイルサイズ、ファイル名の順で表示します。 |ls /usr のようにディレクトリを指定することもできます。
カレントディレクトリの移動
cd コマンドに相当します。 カレントディレクトリを指定したディレクトリに移動します。
|cd /etc
パーミッションの変更
chmod コマンドに相当します。 ファイルまたはディレクトリのパーミッションを変更します。 パーミッションは8進数で指定します。
|cm 755 tmp.txt
ディレクトリの作成
mkdir コマンドに相当します。 指定したディレクトリを作成します。
ファイル名の変更、ファイルの移動
mv コマンドに相当します。 指定したファイル名の変更、またはファイルを移動します。
|mv file1 file2
|mv file ./dir
ディレクトリの削除
rmdir コマンドに相当します。 指定したディレクトリを削除します。
|rd dir
カレントディレクトリの表示
pwd コマンドに相当します。 カレントディレクトリを表示します。
|cw
ファイルの削除
rm コマンドに相当します。 指定したファイルを削除します。
|rm file
ファイルシステムのマウント
mount コマンドに相当します。 通常、スーパユーザ(root) で実行する必要があります。 mountコマンドと同様にファイルシステムのマウントしますが、 引数の与え方が異なります。|mo /dev/hda3 /mnt ext2 や マウント済みのファイルシステムは |ca /proc/mounts での確認できます。
|mo /dev/hda3 /mnt vfat → Windows
|mo /dev/hda1 /mnt ext2 → Linux 標準
|mo /dev/hdc5 /mnt reiserfs → reiserfs
|mo none /proc proc → /proc
|mo /dev/hdb /mnt iso9660 r → CD-ROM (読出しのみ)
ファイルシステムのアンマウント
umount コマンドに相当します。 通常、スーパユーザ(root) で実行する必要があります。 マウントしているファイルシステムをアンマウントします。 |um の引数にデバイス名 (/dev/hda2等) は指定できません。マウントポイント (ディレクトリ名) を指定してください。
|um /mnt
|um /mnt/cdrom
ディスクへの強制書き込み
sync コマンドに相当します。 変更されたファイルをディスクキャッシュからハードディスクなどの デバイスに保存します。
|sy
ルートディレクトリの変更
chroot コマンドに相当します。 ルートディレクトリを変更します。
|cr /mnt
外部コマンドの実行
exec コマンドに相当します。 exec を実行します。rvtlのプロセスが指定されたファイルのプロセスに 置き換わります。
|ex /sbin/init
ルートファイルシステムの変更
pivot_root コマンドに相当します。 カレントプロセスのルートファイルシステムを第2引数に指定した ディレクトリに変更して、第1引数に指定したディレクトリを新しい ルートファイルシステムにします。 たとえば、フロッピーディスクから rvtl 自身を/sbin/initとして起動 した後、ルートファイルシステムをマウントしたハードディスクに変更して、 そのマウントポイントを新しいルートファイルシステムに変更して、 そこにある「本当の」/sbin/init を exec するような場合に使用します。
【実行例】
<0126> |mo /dev/hdc5 /mnt reiserfs
Mount
<0126> |cd /mnt
Change Directory to /mnt
<0126> |pv /mnt /mnt
Pivot Root
<0126> |ex /sbin/init
スワップ領域のオープン
swapon コマンドに相当します。 スワップ領域をオープンします。
【実行例】
<0126> |so /dev/hda3
Swap On
スワップ領域クローズ
swapoff コマンドに相当します。 スワップ領域クローズ
【実行例】
<0126> |sf /dev/hda3
Swap Off
システムコールの実行
変数 a, b, c, d, e, f を引数としてシステムコールを実行します。 変数 a にはシステムコール番号、b が第1引数、c が第2引数、 あとは同様に第5引数まで指定できます。
|zz
URLデコード
URLエンコードされた文字列をデコードします。
u[0] URLエンコード文字列の先頭設定
u[1] 変更範囲の文字数を設定
u[2] デコード後の文字列先頭を設定
u[3] デコード後の文字数を返す
rvtlのバージョン
|ve を実行すると、% にrvtlのバージョンを返します。
【実行例】
<086B> |ve ?=%
30300
フレームバッファ用組み込みコマンド
フレームバッファを使うための組み込みコマンドがあります。|fbo, |fbc, |fbs はカーネルがフレームバッファをサポートしていない場合はエラーと なります。それ以外の描画命令はフレームバッファのメモリに対して描画する だけでなく、任意のメモリ領域に対しても実行できます。メモリ中に確保した オフスクリーン領域に対して描画して、フレームバッファに転送することも できます。メモリ領域に対して一括して値を書き込む場合や、メモリのコピー として使用できます。|fb 命令に与える引数は、各々決まった配列変数を として渡します。 命令を使用する前に配列用の領域を確保しておく必要が あります。「m=& l=m+64 t=l+64 r=t+64 」のように各配列に一律に64バイト 確保しておけば十分です(変数の解説参照)。サンプルの fbinfo.vtl、line.vtl、 pat.vtl を参考にしてください。
フレームバッファのオープン
|fbo
実行後フレームバッファが使える状態ならば、変数 f にフレームバッファ の先頭アドレス、変数 g の示すアドレスから55個220バイトのVirtual Screen Information と Physical Screen Informationが設定されます。 f, g ともに rvtl が用意しているアドレスが返されるため、配列用のメモリ を確保する必要はありません。 フレームバッファにアクセスする前に [=0 を実行して、アクセス範囲 チェックをOFFにする必要があります。 フレームバッファが有効でない場合には [ENODEV] No such device と表示 されて終了します。
VESA Mode
depth | color | 640x480 800x600 1024x768 1280x1024
------+-------+--------+---------+---------+---------
15bit | 32k | 310 313 316 319
16bit | 64k | 311 314 317 31A
32bit | 16M | 312 315 318 31B
フレームバッファに関する情報は配列 g[] から取得することができます。
Frame Buffer Virtual Screen Information
[ 0] x resolution : g[0]
[ 1] y resolution : g[1]
[ 2] x res virtual : g[2]
[ 3] y res virtual : g[3]
[ 4] x offset : g[4]
[ 5] y offset : g[5]
[ 6] bits/pixel : g[6]
[ 7] grayscale : g[7]
[ 8] RED offset : g[8]
[ 9] length : g[9]
[10] msb_right : g[10]
[11] GREEN offset : g[11]
[12] length : g[12]
[13] msb_right : g[13]
[14] BLUE offset : g[14]
[15] length : g[15]
[16] msb_right : g[16]
[17] TRANSP offset : g[17]
[18] length : g[18]
[19] msb_right : g[19]
[20] nonstd : g[20]
[21] activate : g[21]
[22] height : g[22]
[23] width : g[23]
[24] accel_flags : g[24]
[25] pixclock : g[25]
[26] left margin : g[26]
[27] right margin : g[27]
[28] upper margin : g[28]
[29] lower margin : g[29]
[30] hsync length : g[30]
[31] vsync length : g[31]
[32] sync : g[32]
[33] vmode : g[33]
Frame Buffer Physical Screen Information
[40] ID string : g(160) .. g(175)
[44] frame buffer mem start : g[44]
[45] frame buffer mem length : g[45]
[46] frame buffer type : g[46]
[47] interleave : g[47]
[48] frame buffer visual : g[48]
[49] x pan step : g{99}
[49] y pan step : g{100}
[50] y wrap step : g{101}
[51] line length (bytes) : g[51]
[52] Memory Mapped I/O start : g[52]
[53] Memory Mapped I/O length: g[53]
[54] acceleration type : g[54]
フレームバッファのクローズ
|fbc
|fbo でオープンしたフレームバッファをクローズする場合に 使用します。
フレームバッファの設定変更
|fbs
|fbo で返される g 配列にフレームバッファの設定を書いてから 呼び出します。
点の描画
|fbd
フレームバッファに点を描画します。配列 d に必要な値を 設定して呼び出します。 d[0]=f とするとフレームバッファに対する操作となります。 d[0] にメモリアドレスを設定するとメモリに対しての描画 になり、バックバッファに対する書き込みが可能です。
| d[0] = addr | 描画領域先頭アドレス |
| d[1] = x | 転送先のX座標 |
| d[2] = y | 転送先のY座標 |
| d[3] = Color | 色 |
| d[4] = ScrX | 転送先X方向のバイト数 |
| d[5] = Depth | 1ピクセルのバイト数 |
塗りつぶし
|fbf
フレームバッファを指定した色で塗りつぶします。 配列 m に必要な値を設定して呼び出します。 フレームバッファをクリアする場合などに使用します。 m[0]=f とするとフレームバッファに対する操作となります。 m[0] にメモリアドレスを設定するとメモリに対しての描画 になり、バックバッファに対する書き込みが可能です。
| m[0] = addr | メモリフィル先頭アドレス |
| m[1] = offset | オフセット(バイト) |
| m[2] = length | 長さ(ピクセル) |
| m[3] = color | 色 |
| m[4] = Depth | bits/pixel |
ライン描画
|fbl
フレームバッファに指定した色の線を描画します。 配列 l (英小文字のエル) に必要な値を設定して呼び出します。 l[0]=f とするとフレームバッファに対する操作となります。 l[6]、l[7] は内部で使用する作業領域です。指定する必要はありません。 l[0] にメモリアドレスを設定するとメモリに対しての描画 になり、バックバッファに対する書き込みが可能です。
| l[0] = addr | 描画領域先頭アドレス |
| l[1] = x | 始点のX座標 |
| l[2] = y | 始点のY座標 |
| l[3] = x | 終点のY座標 |
| l[4] = y | 終点のY座標 |
| l[5] = col | ラインの色 |
| l[6] = incr1 | 作業領域 |
| l[7] = incr2 | 作業領域 |
パターン転送
|fbp
メモリアドレス mem を先頭に格納されているパターン(画像)を addr に 転送します。 配列 p に必要な値を設定して呼び出します。 p[0]=f とするとフレームバッファに対する操作となります。 p[0] にメモリアドレスを設定するとメモリに対しての描画 になり、バックバッファに対する書き込みが可能です。
| p[0] = addr | 転送先アドレス |
| p[1] = x | 転送先のX座標 |
| p[2] = y | 転送先のY座標 |
| p[3] = PatW | パターンの幅 |
| p[4] = PatH | パターンの高さ |
| p[5] = mem | パターンの格納アドレス |
| p[6] = ScrX | X方向のバイト数 |
| p[7] = Depth | 1ピクセルのバイト数 |
パターン転送2
|fbt
メモリアドレス mem を先頭に格納されているパターン(画像)を addr に 転送します。転送元(mem) の画像の一部を転送します。 配列 t に必要な値を設定して呼び出します。 t[0]=f とするとフレームバッファに対する操作となります。さらに t[5]=f とした場合はフレームバッファ内で矩形領域をコピーします。転送元と 転送先が重なった場合の動作は保証されません。 t[0] にメモリアドレスを設定するとメモリに対しての描画 になり、バックバッファに対する書き込みが可能です。
| t[0] = addr | 転送先アドレス |
| t[1] = x | 転送先のX座標 |
| t[2] = y | 転送先のY座標 |
| t[3] = PatW | パターンの幅 |
| t[4] = PatH | パターンの高さ |
| t[5] = mem | パターンの格納アドレス先頭 |
| t[6] = ScrX | 転送先のX方向のバイト数 |
| t[7] = Depth | 1ピクセルのバイト数 |
| t[8] = x2 | 転送元のX座標 |
| t[9] = y2 | 転送元のY座標 |
| t[10]= ScrX2 | 転送元のX方向のバイト数 |
マスク付きパターン転送
|fbq
スプライトをフレームバッファに描画します。 配列 q に必要な値を設定して呼び出します。 q[8] で転送しない色を指定できる他は |fbp と同じです。 背景画像に対してパターンを重ねる場合に使用します。 q[0] にメモリアドレスを設定するとメモリに対しての描画 になり、バックバッファに対する書き込みが可能です。
| q[0] = addr | 転送先アドレス |
| q[1] = x | 転送先のX座標 |
| q[2] = y | 転送先のY座標 |
| q[3] = PatW | パターンの幅 |
| q[4] = PatH | パターンの高さ |
| q[5] = Color | パターンの格納アドレス |
| q[6] = ScrX | X方向のバイト数 |
| q[7] = Depth | 1ピクセルのバイト数 |
| q[8] = Mask | マスク色 |
矩形領域の塗りつぶし
|fbr
|fbf と似ていますが、任意の矩形領域を一定の色で塗りつぶします。 配列 r に必要な値を設定して呼び出します。 r[0] にメモリアドレスを設定するとメモリに対しての描画 になり、バックバッファに対する書き込みが可能です。
| r[0] = addr | 転送先アドレス |
| r[1] = x | 転送先のX座標 |
| r[2] = y | 転送先のY座標 |
| r[3] = PatW | 領域の幅 |
| r[4] = PatH | 領域の高さ |
| r[5] = Color | 塗りつぶす色 |
| r[6] = ScrX | X方向のバイト数 |
| r[7] = Depth | 1ピクセルのバイト数 |
メモリコピー
|fbm
メモリを c[0] で指定したアドレスから c[1] で指定したアドレスへ c[2] バイトコピーします。大量の転送を rvtl で記述すると遅い場合に 使用します。フレームバッファ以外の一般のメモリ転送にも使用できます。 転送する領域が重なっていても使用できます。
| c[0] = source | 転送元先頭アドレス |
| c[1] = dest | 転送先先頭アドレス |
| c[2] = length | 転送バイト数 |
上級者向けの機能
rvtl のコマンドラインで指定した rvtl のプログラムは、そのままメモリに 格納されるのではなく、コンソール(キーボード)から入力するように処理され ます。つまり、行番号は整列されている必要がなく、行番号が「ばらばら」でも メモリには整列されて格納されます。また、#=1 (RUN) や &=0 (NEW) のように 行番号なしで直接実行するコマンドを記述することが可能です。
例えば:
20 #=-1 : プログラム終了
10 "Hello world!" / : 文字列を出力して改行
0 : リスト出力
<="hello2.vtl" : リストをhello2.vtl というファイル名で保存
/ : 改行出力
#=1 : プログラムを実行
~ : rvtl の終了
のように書かれたファイル(hello1.vtl)を実行すると、次の結果となります。
jm:~/rvtl-3.02a/vtl$ rvtl hello1.vtl
10 "Hello world!" / : 文字列を出力して改行
20 #=-1 : プログラム終了
hello2.vtl
Hello world!
jm:~/rvtl-3.02a/vtl$
rvtl にはプログラムの先頭アドレスを変更する機能もあります。メモリ中に 複数のプログラムを格納して、切り替えて実行することもできます。 先頭アドレスは 「=」システム変数に格納されているため、これを書き換える ことで実現します。デフォルトのプログラムの先頭アドレスは「,」に格納され ていて、書き換えることはできません。「=」システム変数の初期値は「,」です。 「==,」が実行されていると考えてください。ここで「==,+2000」と実行したと します。これは、「プログラム先頭アドレスをデフォルトのアドレスに2000を 加えた位置に変更する」という意味になります。実際に「==,+2000」を実行すると、 「&=0 required.」と表示されます。適当にプログラムの先頭アドレスを変更した ためにプログラムの終了アドレス(の後ろ)が決められないため、「NEWを実行しろ!」 といってきています。「&=0」を実行して、プログラムを何か入力してください。 例えば「100 "Start"」とします。「#=1」で実行して、「==,」でデフォルトの プログラム先頭アドレスに戻り、再度「==,+2000」を実行すると、今度は 「&=0 required.」と表示されません。「0」でリスト表示をすると、
100 "Start"
と表示されます。前に入力したプログラムがそのまま認識されています。 ==<アドレス> を実行して、プログラム先頭アドレスを変更した場合に、すでに 有効なプログラムが存在する場合には、そのプログラムの終了アドレスも認識 されて実行できるようになります。
rvtlのプログラムをシェルスクリプトとして直接実行するためには、 先頭行に #!/usr/bin/rvtl を付加します。# の前に空白などを挿入しないで 下さい。rvtl の格納場所が異なる場合は #!/usr/bin/rvtl などと します。以下のプログラムを script.vtl というファイル名で保存して、 chmod 755 script.vtl のようにパーミッションを実行可能に変更します。
#!/usr/bin/rvtl 10 "test" / 20 ?=12345 / #=1 ~
実行すると行番号の付いた 2行のrvtlのプログラムがメモリ中に保存され、 #=1 で実行、~ で終了のように動作します。
jm:~/rvtl-3.02a/vtl$ ./script.vtl test 12345 jm:~/rvtl-3.02a/vtl$
コマンドライン引数
rvtl の起動時に rvtl のプログラムを引数として与えることができます。 rvtl は起動とともにプログラムを読み込みます。このとき複数の rvtl プログラムを指定すると順に読み込みプログラムで使用している行番号に したがってメモリ中に混ざった形で格納されます。引数として与える プログラムとして、行番号を付けない形式の「#=1」実行、「~」終了、 「0」リストなどを含んだファイルを指定することもできます。 サンプルプログラムの run.vtl の内容は「#=1」だけ、runq.vtl は 「#=1」と「~」のファイルになっています。
$ rvtl abc.vtl runq.vtl
とコマンドラインで指定すると、abc.vtl を実行して、rvtl自身も終了 することができます。
rvtl のプログラムにコマンドラインから文字列を与えることもできます。 コマンドライン引数の先頭が「-」である引数の後ろは、プログラム中で \0、\1 のように引数の文字列の先頭アドレスを参照することができます。 引数文字列は rvtl のプロセスのスタック領域を示しているため、 配列として参照したり、文字列コピー (例えば A*=\0) を実行する前には 範囲チェックをOFF ([=0) にしない場合に「Out of Range」エラーになる ことに注意してください。
次のプログラムを arg.vtl というファイル名で保存しているとします。
100 I=0 : 最初の引数 110 [=0 : 範囲チェックを OFF 120 @ : 繰り返し (DO) 130 S=\I : 引数の先頭アドレス 140 ;=S(0)<>0 $*=S / : 引数を表示 150 I=I+1 : 次の引数 160 @=(S(0)=0) : 空文字列なら繰り返しを終了 170 [=1 : 範囲チェックを ON に戻す 160 #=-1 : 実行終了
S=\I の部分で「-」の後ろの引数を参照しています。 行番号 110 の「[=0」は、1バイト配列で引数文字列 \I が空文字列 (行末の 0 のみ) を示す場合
「-」という引数の後に適当に引数を与えて実行します。
$ rvtl arg.vtl runq.vtl - abc xyz arg.vtl
スクリプトに引数を与えることができます。rvtl のプログラムは「-」の後ろの コマンドライン引数を 「\式」の形式で参照することができます。最初の引数は 「\0」となります。「\式」の値は引数文字列の先頭アドレスになり、空白で 区切られた引数はそれぞれ0で終わる文字列としてアクセスできます。
#!/usr/bin/rvtl 100 $*=\0 / : 最初の引数を表示 110 |ls*=\0 : ファイルリストを表示 #=1 : 実行して ~ : 終了
ls.vtlが上の内容のファイルの場合
$ ./ls.vtl - /etc
で「/etc」を表示した後、ファイルリストが表示されます。
jm:~/rvtl-3.02a/vtl$ rvtl ls.vtl - /etc
この場合もまったく同じ動作をします。
rvtlコマンドの引数は rvtlのスクリプトファイルとなりますが、「-」 (実際は先頭の文字が「-」の引数) に続く引数は rvtlコマンド自身では 処理されず、rvtl のプログラムで使用されます。 「-」以降の引数は、\0、\1、\2、のように「\」の後に式を書くことで 参照することができます。存在しない(指定していない) 引数は常に空文字列 (内容が行末の 0 のみの文字列) のアドレスを返します。 引数の個数を求める場合には以下のように空文字列までの個数を求めます。
200 i=0
210 [=0
220 @
230 A=\i
240 i=i+1
250 @=(A(0)=0)
260 [=1
270 ?=i
rvtl を /sbin/init (プロセスIDが1) として使う場合に、/etc/init.vtl が存在すると起動時に自動的に読み込まれます。 1FDLinux や CD-ROMブートで rvtl をブートローダ代わりに使う例は http://www.mztn.org/ を参照してください。
プログラム例とリナンバ
rvtl 自身にはリナンバ(行番号の整理)機能はありません。rvtlが自分自身を 書きなおしてリナンバすることができます。GOTO (#=) や GOSUB (!=) の飛び先 にラベルのみを使って行番号を指定していない場合には、次のプログラムを リナンバしたいプログラム(の最後部)にマージして #=90000 のように実行すれば リナンバできます。
rvtl のプログラムは、メモリに次のような形式で格納されています。
NextPtr(4), LineNo(4), Source Text(行番号を除く), 0
o NextPtr は次の行へのバイトオフセット.
o NextPtr が $FFFFFFFF の時は最終行
90010 Z=# : 行番号を保存 90020 N== : コード領域先頭 90030 S=1000 : 行番号開始番号 90040 ;=N[1]>=Z #=-1 : renum.vtl 自身は処理しない 90050 S=S/10 : 新行番号は10番おきに設定 90060 @ 90070 N[1]=S+I*10 : 新行番号 90080 N=N+N[0] I=I+1 : 次行先頭 90090 @=((N[0]<0)+(N[1]>=Z)) : 最後の行まで処理したか?
一方、GOTO (#=) や GOSUB (!=) の飛び先に行番号を使っている場合には、 もう少し複雑な処理が必要です。#=10 を #=1010 のように置換する場合には 行の長さが変化します。行番号の長さの変化に追従するのは面倒なので、 次のプログラムではリナンバした結果を標準出力に書き出しています。 やはり、リナンバしたいプログラム(の最後部)にマージして #=90000 のように 実行すればリナンバした結果が表示されます。これでは表示だけなので、 標準出力をファイルにリダイレクトします。
1) リナンバしたいプログラムをファイルに書き出し
<="xxx.vtl"
2) リナンバを実行
,="./rvtl xxx.vtl renum.vtl > xxx2.vtl"
90000 Z=# : 行番号を保存 90010 :--------------- Renumber ----------------------------------- 90020 : renum.vtl 2003/09/22 Jun Mizutani 90030 : ,="./rvtl xxx.vtl renum.vtl > xxx2.vtl" 90040 :------------------------------------------------------------ 90050 : 90060 T== : コード領域先頭 90070 N=T : Nは行先頭ポインタを最初の行に設定 90080 B=& : 2500行分の旧行番号 90090 C=B+10000 : 2500行分の新行番号 90100 : 90110 S=1000 : 行番号開始番号 90120 ;=N[1]>=Z #=-1 : renum.vtl 自身は処理しない 90130 I=0 : 行番号テーブルのインデックス 90140 S=S/10 : 新行番号は10番おきに設定 90150 @ 90160 B[I]=N[1] : 旧行番号 90170 C[I]=S+I*10 : 新行番号 90180 N=N+N[0] : 次行先頭 90190 I=I+1 : 行番号テーブルインデックス更新 90200 @=((N[0]<0)+(N[1]>=Z)) : 最後の行まで処理したか? 90210 Q=I-1 90220 : !=^TableList 90230 N=T : 行先頭ポインタを最初の行に設定 90240 I=0 : 行内の位置 90250 @ 90260 ?=C[I] " " : 行番号出力 90270 K=8 : コード行頭 90280 F=0 90290 @ 90300 H=N(K) ;=H<>0 $=H : 1文字出力 90310 ;=((H='"')+(H=':'))*(F=0) F=1 #=^skip0 90320 ;=(H='"')*(F=1) F=0 : コメント、文字列中は無視 90330 ^skip0 90340 ;=((H='#')+(H='!'))*((N(K-1)=' ')+(K=8))*(F=0) !=^Replace 90350 K=K+1 : 次の文字 90360 @=(H=0) : 行末まで繰返す 90370 N=N+N[0] / : 次行先頭 90380 I=I+1 90390 @=((N[0]<0)+(N[1]>=Z)) : 最後の行まで処理したか? 90400 #=-1 90410 : 90420 ^Replace 90430 ;=N(K+1)<>'=' ] : GOTOまたはGOSUBでなければ戻る 90440 K=K+1 : 次の文字 90450 $=N(K) K=K+1 : = 出力 90460 ;=N(K)='-' "-" ] : 負数(#=-1)の場合は何もしない 90470 ;=N(K)='^' "^" ] : ラベルなら何もしない 90480 L=0 : 10進数字文字列を数値に変換 90490 @ 90500 H=N(K) ;=(H>='0')*(H<='9') L=L*10+(H-'0') 90510 K=K+1 90520 @=((H<'0')+(H>'9')) 90530 : / "L=" ?=L / 90540 J=0 : 行番号テーブルをスキャン 90550 @ 90560 ;=B[J]=L L=C[J] J=Q #=^skip1 : 同じ番号なら置換 90570 ;=B[J]>L L=C[J] J=Q : 同一番号が無ければ次 90580 ^skip1 90590 J=J+1 90600 @=(J>=Q) : 見つけたら終り 90610 ?=L $=H K=K-1 90620 ] 90630 ^TableList 90640 J=0,Q : 行番号テーブルの表示 90650 ?(6)=B[J] " " ?(6)=C[J] / 90660 @=J+1 #=1 ~
制限
| 変数スタックに積むことのできる変数の最大個数 | 1024 |
| サブルーチンのネスト+ (ループのネストx 2) | 最大32 |
| プログラム + データ用のメモリの初期値 | 256 キロバイト |
| 使用可能なラベルの最大数 | 1024 |
ファイルの構成
| COPYING | ライセンス(GPL) |
| gpl.text | ライセンスの日本語訳 |
| Readme.txt | この文書 |
| rvtl_ref.txt | rvtlの機能一覧 |
| rvtl | rvtl の実行プログラム |
| source/ | rvtl のアセンブリソース |
| vtl/ | rvtl のサンプルプログラム |
最新情報
この文書以外の情報やサンプルプログラム、rvtlの最新情報は http://www.mztn.org/ を参照して下さい。
rvtl を使ってプログラムを作成された方は mizutani.jun@nifty.ne.jp まで お知らせください。http://www.mztn.org/ で紹介させて頂きます。
ライセンス
このソフトはフリーソフトウェアです. GNU General Pulic Licenceにしたがって 自由に使用,配布,改変して頂いてかまいません。 GNU General Pulic Licence の詳細はCOPYINGを参照して下さい. GNU General Pulic Licence の日本語訳は gpl.text です.
著作権は私(水谷 純, mizutani.jun@nifty.ne.jp)が保有しています。
本ソフトウェアによって生じた損害について著作者は責任を負いません。 また、著作者はバージョンアップの義務を負いません。