JH8CHUのホームページ>Tiny言語>VTLによるマイクロ・エディタ

VTLによるマイクロ・エディタ


β版のソース公開。(2016/05/14)。
誤記訂正。(2016/05/15)。
s、l コマンドのメッセージ変更。(2016/06/01)。
  1. 免責事項


  2. マイクロ・エディタの概要


  3. コマンド一覧

  4. メモリマップ

      VTLの配列のメモリ・マップです。
      入力バッファとテキスト領域は常にバイト・サイズでアクセスしますので、
      VTLの拡張仕様である変数^と変数\を使用します。

      テキストの編集を行う作業領域の使い方に特徴があります。
      下図のように行ポインタより下(後)の部分は、作業領域の末尾側からつめられています。
      このため、まだ使用されていない空き領域が作業領域の途中にあります。
      このようにすると、ポインタの位置に行を挿入するときポインタUPの位置から挿入しますが
      挿入位置より後ろの行を移動する必要がありません。
      また、ポインタの位置から行を削除する場合、ポインタDNを後ろ側に移動するだけで
      削除行より後ろのテキストを前につめる必要がありません。
      逆に、ポインタを移動する場合に、上部分から下部分へ、または下部分から上部分への
      テキストの移動が発生します。

      なお、現在行のポインタは下部分の先頭行にあるように見えます。
      現在行がテキストの最終にあり、下部分の行数が0の場合、
      現在行を表示すると「(EOT)」と表示されます(これはオリジナルにはない仕様です)。


      ■ s、l コマンドで使用する領域の詳細。
        この領域はワード・サイズでアクセスします。
        エントリーは16ありますので、メモリ・サイズとしては32バイトです。

        マイクロ・エディタではテキストのセーブとロードにVTLの機能を
        そのまま使用しています。このため、
        編集したテキストは固定長で論理セクタに格納します。
        そうすると、論理セクタからテキストをロードした場合、
        テキストの大きさや、行数に関する情報がないと、編集が再開出来なくなります。
        そこで、テキストの大きさや、行数に関する情報をこの領域に格納し
        テキスト本体と一緒に論理セクタに格納します。
        テキストをロードするとき、全て上部分に移動するため、(B-D)と下部分の行数は
        なくても良いのですが、現状、一応格納するようにしています。
        (B-Dと下部分の行数はつねに0が格納されます。)


  5. データ構造

      オリジナルのマイクロ・エディタでは文字コードは7ビットであり、残りの1ビットを
      行間マークとして使用していますが、本エディタでは文字コードは8bitのASCIIコード
      そのものであり、行末には区切り文字(0x00)があるものとします。
      また、下図の例では、現在行は6行目になります。



  6. 変数の割当

      パラメータ・スタックを使用しなかったので、一部の変数を使いまわししており
      処理が少し汚くなっております。(^^;

      変数名割当機能備考
      Aファイル用作業領域の先頭(TOP) 
      Bファイル用作業領域の末尾(BOTM) 
      Cポインタ(UP) 
      Dポインタ(DN) 
      E上部分の行数(OVER) 
      F下部分の行数(UNDR) 
      G入力バッファの先頭番地(BUF) 
      Pパラメータ・スタック・ポインタ(未使用) 
      Rリターン・スタック・ポインタ 
      Tr、fコマンド処理内で使用 
      UサブルーチンDLT1、CMPL、FND1内などで使用 
      VサブルーチンDLT1、CMPL、FND1内などで使用 
      Wn、p、fコマンドなどで使用 
      Xサブルーチン内で消費 
      Yサブルーチン内で消費 
      Zサブルーチン内で消費 

  7. 処理ルーチン一覧

    配列内の文字列のアドレスは、全てバイト・アドレスです。
    行番号名称入力出力処理備考
    1000PSHR X:RSに積む値---変数Xをリターンスタックにプッシュします。
    サブルーチンの冒頭で変数!に格納されたメインルーチンへ
    の戻りアドレスをリターンスタックに積むときに使用します。
     
    1100RET ------サブルーチンからメインルーチンに戻ります。そのために
    リターンスタックに格納された戻りアドレスを変数「#」に
    代入します。
     
    1400ACPTG:文字列を格納する
     配列の先頭
    X:入力した文字数 キーボードから文字列を入力し、入力バッファ
    (先頭は変数G)以降の配列に格納します。
    Xに文字列末尾の0x00は含みません。
     
    1500DISP Y: 文字列のアドレス-1--- 配列に格納された文字列を画面に出力します。
    文字列の位置は変数Y+1から
    区切り文字0x00までです。
     
    1600DISP1 Y: 文字列のアドレス-1--- 配列に格納された文字列を画面に出力します。
    文字列の位置は変数Y+1から
    区切り文字0x00までです。変数Yが
    BOTM(変数B)に達しているときは何も表示しません。
     
    2000DTOBY: 文字列のアドレスZ: 変換した数値 変数Yからの文字列を符号なし整数に変換し
    変数Zに返します。数値に変換出来ないときは
    Z=0が返されます。
     
    2200INS2Y:挿入文字列アドレス
    Z:挿入文字数
    --- 1行挿入処理します。  
    2400MVUP------ ポインタを1行Move upします。  
    2600DOWN------ ポインタを1行Move downします。  
    2800NXT2W:スイッチ
    Z:下げる行数
    --- ポインタをZ行Move downします。
    W=0のとき、移動後のポインタ位置の行のみ表示。
    W=1のとき、ポインタを1行下げる毎に行を表示。
     
    3000DLT1Z:削除する行数--- ポインタのある行からZ行を削除します。  
    3200CMPLU:比較文字列のアドレス
    V:比較文字列のアドレス
    X=0:文字列は
     一致しない。
    X=1:文字列は
     一致した。
    文字列の先頭アドレスを示すポインタUとポインタVの
    で示される二つの文字列を比較し、一致するか
    どうか判定します。比較はU側の文字列に
    区切り文字0x00が出現する位置までです。
     
    3500FND1T:検索文字列のアドレス
    W:検索される
    文字列のアドレス
    X=0:一致する文字列
     見つからなかった。
    X=1:一致する文字列
     見つかった。
    ポインタTで示される文字列がポインタWで示される
    文字列に含まれるか、検索します。
    文字列の終わりはどらも区切り文字0x00までです。
     
    10000EDIT---X:入力文字数
    Y:コマンドの次のアドレス
    エディターのメイン・ループ。プロンプト>を表示した後に
    コマンドを入力して、各コマンド処理にに分岐します。
     
    11000INSRX:挿入文字数
    Y:コマンドの次アドレス
    --- i コマンドを実行します。
     
    12000BACKY:コマンドの次アドレス--- b コマンドを実行します。
     
    13000NEXTY:コマンドの次アドレス--- n コマンドを実行します。
     
    14000TPY:コマンドの次アドレス--- t コマンドを実行します。
     
    15000PRINY:コマンドの次アドレス--- p コマンドを実行します。
     
    16000APND------ a コマンドを実行します。
     
    17000DELTY:コマンドの次アドレス--- d コマンドを実行します。
     
    18000RTYPX:挿入文字数
    Y:コマンドの次アドレス
    --- r コマンドを実行します。
     
    19000SAVEX:入力文字数
    Y:コマンドの次アドレス
    --- s コマンドを実行します。
     
    20000LOADX:入力文字数
    Y:コマンドの次アドレス
    --- l コマンドを実行します。
     
    21000FIND------ f コマンドを実行します。
     
    22000CHNGY:コマンドの次アドレス--- g コマンドを実行します。【制作中止の予定】
     
    100START------ エディタで使用する変数を初期化して
    エディタを開始します。
     

  8. 処理詳細

    1. PSHR
      (1)機能
      行番号名称入力出力処理備考
      1000PSHR X:RSに積む値---変数Xをリターンスタックにプッシュします。
      サブルーチンの冒頭で変数!に格納されたメインルーチンへ
      の戻りアドレスをリターンスタックに積むときに使用します。
       

      (2)処理内容
        VTLではサブルーチンがメインルーチンに戻る際に必要となる戻りアドレスが
        変数!に格納されていますが、変数!が破壊されてもよいようにサブルーチンの
        冒頭で戻りアドレスをリターン・スタックに格納するために使用します。
        本ルーチンを呼び出すことにより変数!が破壊されてしまうため
        戻りアドレスは変数Xに格納してから、本ルーチンを呼び出します。
        なお本ルーチンを使用したときは、サブルーチンから戻るときに、 RETを使用します。

      (3)ソース・リスト
        1000 R=R-1
        1010 :R)=X
        1020 #=!

        [解説]
        1000 リターン・スタックのポインタをデクリメント
        1010 変数X(戻り行番号)をリターン・スタックに格納
        1020 このルーチンを呼び出したサブルーチンに戻る

    2. RET
      (1)機能
      行番号名称入力出力処理備考
      1100RET ------サブルーチンからメインルーチンに戻ります。そのために
      リターンスタックに格納された戻りアドレスを変数「#」に
      代入します。
       

      (2)処理内容
        PSHRルーチンを呼び出して戻りアドレスを リターン・スタックに
        格納したサブルーチンがメイン・ルーチンに戻るときに使用します。
        そのために、リターンスタックに格納された戻りアドレスを
        変数「#」に代入します。

      (3)ソース・リスト
        1100 !=:R)
        1110 R=R+1
        1120 #=!

        [解説]
        1100 リターン・スタックに積まれたメイン・ルーチンの戻り行番号を変数!に戻す。
        1110 リターン・スタックのポインタをデクリメント
        1120 メイン・ルーチンにジャンプ

    3. ACPT
      (1)機能
      行番号名称入力出力処理備考
      1400ACPTG:文字列を格納する
       配列の先頭
      X:入力した文字数 キーボードから文字列を入力し、入力バッファ
      (先頭は変数G)以降の配列に格納します。
      Xに文字列末尾の0x00は含みません。
       

      (2)処理内容
        キーボードから文字列を入力し配列に格納します。
        配列の先頭アドレスは変数Gで指定します。
        なお、配列のアドレスはバイト・アドレスになります。
        入力された文字列の終わりに文字列の終わりを示す(区切り文字)
        0x00が追加されます。
        戻り値として変数Xに入力された文字列の文字数が設定されます。
        Xの文字数には区切り文字は含みません。
        (空行入力時はX=0です)

      (3)ソース・リスト
        1400 ^=G
        1410 X=$
        1420 #=!

        [解説]
        1400 文字列を格納する配列のポインタを設定。(変数^はVTLの変数)
        1410 文字列を入力し、入力文字数を変数Xに格納。(変数$はVTLの変数)
        1420 このルーチンを呼び出したサブルーチンに戻る

    4. DISP
      (1)機能
      行番号名称入力出力処理備考
      1500DISP Y: 文字列のアドレス-1--- 配列に格納された文字列を画面に出力します。
      文字列の位置は変数Y+1から
      区切り文字0x00までです。
       

      (2)処理内容
        配列に格納された文字列を画面に出力します。
        表示する文字列の先頭は変数Yで指定しますが、
        実際に表示される文字列の位置はY+1からです。
        文字列の終わりには区切り文字(0x00)が必要です。
        なお、配列のアドレスはバイト・アドレスになります。

      (3)ソース・リスト
        1500 X=!
        1510 #=1000
        1520 ^=Y+1
        1530 #=(\=0)*1570
        1540 $=\
        1550 Y=Y+1
        1560 #=1520
        1570 ?=""
        1580 #=1100

        [解説]
        1500 戻り行番号を
        1510 リターン・スタックに積む。
        1520 表示文字のある配列のバイト・アドレスを、バイト・アクセスのポインタに設定。
        1530 文字が区切り文字なら表示終了。
        1540 ポインタの位置の文字を1文字表示。
        1550 ポインタをひとつ進める。
        1560 文字列表示のためのループ。
        1570 改行を表示して、
        1580 メイン・ルーチンに戻る。

    5. DISP1
      (1)機能
      行番号名称入力出力処理備考
      1600DISP1 配列に格納された文字列を画面に出力します。
      文字列の位置は変数Y+1から
      区切り文字0x00までです。変数Yが
      BOTM(変数B)に達しているときは何も表示しません。
       

      (2)処理内容
        配列に格納された文字列を画面に出力します。
        表示する文字列の先頭は変数Yで指定しますが、
        実際に表示される文字列の位置はY+1からです。
        文字列の終わりには区切り文字(0x00)が必要です。
        ポインタ(変数Y)がファイル用作業領域の末尾(BOTM)に
        達している場合はポインタは移動せず、「(EOT)」と表示して、
        メイン・ルーチンに戻ります(EOTの表示はオリジナルにはありません)。
        なお、配列のアドレスはバイト・アドレスになります。

      (3)ソース・リスト
        1600 X=!
        1610 #=1000
        1620 #=(Y>B)*1650
        1630 #=1500
        1640 #=1100
        1650 ?="(EOF)"
        1660 #=1100

        [解説]
        1600 戻り行番号を
        1610 リターン・スタックに積む。
        1620 表示する文字列のポインタがBOTM(変数B)に達したらポインタは移動しない。
        1630 ポインタ(変数Y)の位置の文字列を表示する。
        1640 メイン・ルーチンに戻る。
        1650 テキストの終わりであること(EOT)を表示する。
        1660 メイン・ルーチンに戻る。

    6. DTOB
      (1)機能
      行番号名称入力出力処理備考
      2000DTOBY: 文字列のアドレスZ: 変換した数値 変数Yからの文字列を符号なし整数に変換し
      変数Zに返します。数値に変換出来ないときは
      Z=0が返されます。
       

      (2)処理内容
        文字列を数値に変換します。
        変換は、最初に数値以外の文字が現れるまで続けらます。


      (3)ソース・リスト
        2000 X=!
        2010 #=1000
        2020 Z=0
        2030 ^=Y
        2040 X=\-48
        2050 #=(X<9)*2080
        2070 #=1100
        2080 Z=Z*10+X
        2090 Y=Y+1
        2100 #=2030

        [解説]
        2000 戻り行番号を
        2010 リターン・スタックに積む。
        2020 結果を格納する変数Zをクリア。
        2030 文字列のポインタをVTLの変数^に格納し、
        2040 その位置の文字(バイト)が48("0")〜57("9")なら、
        2050 その文字は数字である。
        2060 (削除)
        2070 数字以外の文字があれば変換終了。
        2080 変換済の数値は桁上げし、次の数値を変換済の数値に足す。
        2090 文字列のポインタを更新し、
        2100 変換のループを回る。

    7. INS2
      (1)機能
      行番号名称入力出力処理備考
      2200INS2Y:挿入文字列アドレス
      Z:挿入文字数
      --- 1行挿入処理します。  

      (2)処理内容
        作業領域の上部分に文字列を挿入します。
        マイクロ・エディタでは常にポインタ行より前の行が作業領域の上部分となっているため
        挿入する行は常に上部分の空位置を示すポインタ(変数C)の位置から挿入することになります。


        文字列を挿入することにより、作業領域が不足する場合は「PAN」と
        表示します。「PAN」の意味が不明ですが、オリジナルのマイクロ・エディタ
        の仕様に合わせました。(^^;

      (3)ソース・リスト
        2200 X=!
        2210 #=1000
        2220 #=((C+Z)<(D+1))*2250
        2230 ?="PAN"
        2240 #=1100
        2250 ^=Y
        2260 X=\
        2270 ^=C
        2280 \=X
        2290 Y=Y+1
        2300 C=C+1
        2310 Z=Z-1
        2320 #=((Z=0)=0)*2250
        2330 E=E+1
        2340 #=1100

        [解説]
        2200 戻り行番号を
        2210 リターン・スタックに積む。
        2220 行を挿入したとき、作業領域がオーバーフローしないかチェック。
        2230 オーバーフローとなるなら「PAN」と表示して、
        2240 メイン・ルーチンに戻る。
        2250 ここから挿入処理。コピー元の文字を
        2260 変数Xに代入し、
        2270 コピー先となる上部分のポインタ(変数C)の位置に
        2280 文字をコピーする。
        2290 コピー元のポインタを更新。
        2300 コピー先のポインタを更新。
        2310 コピーする文字列の長さとなるカウンタをデクリメント。
        2320 コピーが終了していないならループ。
        2330 1行追加したので、上部分の行数をインクリメント。
        2340 メイン・ルーチンに戻る。

    8. MVUP
      行番号名称入力出力処理備考
      2400MVUP------ ポインタを1行Move upします。  

      (2)処理内容
        ポインタを1行Move upするために、上部分のテキストを1行分下部分に移動します。
        1行移動したことの確認は、移動元の上部分の更に1行前の区切り文字(0x00)を
        見つけることにより行いますが(プログラム:2520行目)、上部分が1行しか
        なかった場合は、上部分のポインタ(変数C)が作業領域の先頭(変数A)に達したことで
        判定します(プログラム:2510行目)。このとき、VTLの<の表記は実際は≦のこと
        なので、C<Aの判定はC+1≦AとVTLでは記述しています。
        なお、ここの処理では上部分の行数(変数E)と下部分の行数(変数F)は更新しません。

      (3)ソース・リスト
        2400 X=!
        2410 #=1000
        2420 #=(C<A)*2540
        2430 C=C-1
        2440 ^=C
        2450 X=\
        2460 ^=D
        2470 D=D-1
        2480 \=X
        2490 C=C-1
        2500 ^=C
        2510 #=((C+1)<A)*2530
        2520 #=((\=0)=0)*2450
        2530 C=C+1
        2540 #=1100

        [解説]
        2400 戻り行番号を
        2410 リターン・スタックに積む。
        2420 上部分のポインタ(変数C)が作業領域の先頭(変数A)以下の場合は
           これ以上戻れないので何もせず、メイン・ルーチンに戻ります。
        2430 上部分のテキストの最終アドレスは変数C-1です。
        2440 その位置の文字を
        2450 変数Xに代入します。
        2460 下部分のポインタ(変数D)の位置に文字をコピーするためにポインタ^を設定し
        2470 下部分のポインタ(変数D)を更新し、
        2480 文字を下部分にコピーします。
        2490 下部分のポインタ(変数D)も更新し
        2500 次のコピーに備えてポインタ^を設定しますが、
        2510 もし上部分ポインタ(変数C)が作業領域の先頭(変数A)より小さいなら終了。
        2520 前の行の終わり(区切り文字)でなければ文字の移動を継続。
        2530 上部分ポインタ(変数C)は文字列の最終アドレスなので、空領域の先頭に戻してから
        2540 メイン・ルーチンに戻る。

    9. DOWN
      行番号名称入力出力処理備考
      2600DOWN------ ポインタを1行Move downします。  

      (2)処理内容
        ポインタを1行Move Downするために、下部分のテキストを1行上部分に移動します。
        1行移動したことの確認は、移動する行自身の区切り文字(0x00)を見つければよいので
        (プログラム:2690行目)、Move upの処理よりはいくらか簡単になります。
        また、上部分の行数(変数E)と下部分の行数(変数F)は更新しません。

      (3)ソース・リスト
        2600 X=!
        2610 #=1000
        2620 #=(D>B)*2700
        2630 D=D+1
        2640 ^=D
        2650 X=\
        2660 ^=C
        2670 C=C+1
        2680 \=X
        2690 #=((X=0)=0)*2620
        2700 #=1100

        [解説]
        2600 戻り行番号を
        2610 リターン・スタックに積む。
        2620 下部分のポインタ(変数D)が作業領域の末尾(変数B)以上の場合は
           これ以上ポインタは進めないので何もせず、メイン・ルーチンに戻ります。
        2630 下部分のポインタ(変数D)+1が下部分のテキストの先頭です。
        2640 それをバイト・アクセスのVTLポインタ変数^に代入し
        2650 そのポインタ位置の文字を変数Xに代入。
        2660 移動先となる上部分の空き領域の先頭となるポインタ(変数C)の位置を^に代入し
        2670 ポインタCを更新してから
        2680 文字をコピーする。
        2690 コピーは文字列の先頭から実施するので、区切り文字があれば行の移動は終了。
        2700 メイン・ルーチンに戻る。

    10. NXT2
      行番号名称入力出力処理備考
      2800NXT2W:スイッチ
      Z:下げる行数
      --- ポインタをZ行Move downします。
      W=0のとき、移動後のポインタ位置の行のみ表示。
      W=1のとき、ポインタを1行下げる毎に行を表示。
       

      (2)処理内容
        変数Zで指定された行数、行ポインタを進めます(move down)。
        その際、変数Wが0なら、移動後のポインタ位置の行のみ表示します。
        変数Wが0でないならば、移動前の行の位置から行を進める度に
        全ての行を表示し、移動後の位置まで表示します。
        表示される行数は(Z+1)行です。

      (3)ソース・リスト
        2800 X=!
        2810 #=1000
        2830 #=(Z<F)*2850
        2840 Z=F
        2850 E=E+Z
        2860 F=F-Z
        2870 #=(Z=0)*2940
        2880 Y=D
        2890 #=(W=0)*2910
        2900 #=1600
        2910 #=2600
        2920 Z=Z-1
        2930 #=2870
        2940 Y=D
        2950 #=1600
        2960 #=1100

        [解説]
        2800 戻り行番号を
        2810 リターン・スタックに積む。
        2830 指定した戻り行Zと上部分の行数Fを比較し
        2840 小さい方を戻る行数Zとする。
        2850 Z行戻るため、下部分の行数をZ増やし、
        2860 上部分の行数をZ減らす。
        2870 行ポインタをZ行move downするためのカウンタが0ならmove down終了。
        2880 下部分のアドレスのポインタを変数Yに設定し、行ポインタ行を表示する準備。
        2890 スイッチW=0なら、行ポインタの位置の行は表示しない。
        2900 行ポインタのある位置の行を表示する。そのアドレスは変数Y+1である。
        2910 ポインタを1行Move downする。
        2920 ループ・カウンタを更新。
        2930 指定した行数move downするまでループする。
        2940 下部分のアドレスのポインタを変数Yに設定し、行ポインタ行を表示する準備。
        2950 行ポインタの位置の行を表示する。表示アドレスの先頭は変数Y+1。
        2960 メイン・ルーチンに戻る。

    11. DLT1
      行番号名称入力出力処理備考
      3000DLT1Z:削除する行数--- ポインタのある行からZ行を削除します。  

      (2)処理内容
        現在行から変数Zで指定された行数を削除します。
        削除の手順は下記となります。

        (1)まず、現在の上部分のポインタUP(変数C)と上部分の行数(変数E)とを
          それぞれ、変数Uと変数Vに退避します。


        (2)次に、行ポインタを削除する行数(変数Z)進めます。
          これにより、下部分から上部分にテキストがZ行移動します。


        (3)最後に、変数Uと変数Vに退避してあった処理開始前の
          上部分のポインタUPと上部分の行数である変数Cと変数Eに
          それぞれ書き戻します。これにより、上部分に移動してきた
          Z行分が削除されます。


      (3)ソース・リスト
        3000 X=!
        3010 #=1000
        3020 U=C
        3030 V=E
        3040 W=0
        3050 #=2800
        3060 C=U
        3070 E=V
        3080 #=1100

        [解説]
        3000 戻り行番号を
        3010 リターン・スタックに積む。
        3020 上部分のポインタUP(変数C)を変数Uに退避。
        3030 上部分の行数(変数E)を変数Vに退避。
        3040 移動した後の行ポインタの位置のみを表示するスイッチWを設定。
        3050 変数Zで指定した行数、行ポインタを進める。
        3060 退避した上部分のポインタUP(変数C)を書き戻す。
        3070 退避した上部分の行数(変数E)を書き戻す。
        3080 削除は終了。メイン・ルーチンに戻る。

    12. CMPL
      行番号名称入力出力処理備考
      3200CMPLU:比較文字列のアドレス
      V:比較文字列のアドレス
      X=0:文字列は
       一致しない。
      X=1:文字列は
       一致した。
      文字列の先頭アドレスを示すポインタUとポインタVの
      で示される二つの文字列を比較し、一致するか
      どうか判定します。比較はU側の文字列に
      区切り文字0x00が出現する位置までです。
       

      (2)処理内容
        文字列の先頭アドレスを示すポインタUとポインタVの
        で示される二つの文字列を比較し、一致するか
        どうか判定します。比較はU側の文字列に
        区切り文字0x00が出現する位置までです。
        V側の文字列に先に0x00が現れた場合は不一致です。
        また、どちらの文字列も0x00しかない場合も不一致です。
        このルーチンは文字列検索の処理(FND1)で使用されます。

      (3)ソース・リスト
        3200 X=!
        3210 #=1000
        3220 ^=U
        3230 Y=\
        3240 ^=V
        3250 #=((Y+\)=0)*3300
        3260 ^=U
        3270 Y=\
        3280 ^=V
        3290 Z=\
        3300 #=(Y=0)*3380
        3310 #=(Z=0)*3330
        3320 #=(Y=Z)*3350
        3330 X=0
        3340 #=1100
        3350 U=U+1
        3360 V=V+1
        3370 #=3260
        3380 X=1
        3390 #=1100

        [解説]
        3200 戻り行番号を
        3210 リターン・スタックに積む。
        3220 最初に検索文字列の
        3230 先頭文字と、
        3240 検索される文字列の先頭文字を調べて、
        3250 二つの文字列がどちらも区切り文字(0x00)のみなら文字列は不一致。
        3260 ここから、ループ処理。検索文字列から
        3270 1文字取り出し、変数Yへ。
        3280 検索される文字列から
        3290 1文字づつ取り出して変数Zへ。。
        3300 検索文字列に区切り文字0x00が現れたならば文字列が見つかった。
        3310 検索される文字列に区切り文字0x00が現れたならば見つからなかった。
        3320 比較した文字が一致したら、次の文字を調べる。
        3330 見つからなかったなら、変数X=0を設定して
        3340 メイン・ルーチンに戻る。
        3350 次の文字を調べるために検索文字列側のポインタを更新。
        3360 検索される文字列側のポインタも更新。
        3370 次の文字を調べるためにループ。
        3380 文字列が見つかった場合は、変数X=1を設定して
        3390 メイン・ルーチンに戻る。

    13. FND1
      行番号名称入力出力処理備考
      3500FND1T:検索文字列のアドレス
      W:検索される
      文字列のアドレス
      X=0:一致する文字列
       見つからなかった。
      X=1:一致する文字列
       見つかった。
      ポインタTで示される文字列がポインタWで示される
      文字列に含まれるか、検索します。
      文字列の終わりはどらも区切り文字0x00までです。
       

      (2)処理内容
        ポインタUで示される文字列が、ポインタVで示される文字列の中に
        含まれているか検索します。
        ふたつの文字列がどちらも区切り文字0x00しかなかった場合は
        不一致と見なされます。


      (3)ソース・リスト
        3500 X=!
        3510 #=1000
        3520 U=T
        3530 V=W
        3540 #=3200
        3550 #=(X=1)*1100
        3560 ^=W
        3570 #=(\=0)*3600
        3580 W=W+1
        3590 #=3520
        3600 X=0
        3610 #=1100

        [解説]
        3500 戻り行番号を
        3510 リターン・スタックに積む。
        3520 検索文字列の比較開始位置を初期化(変数U)。
        3530 検索される文字列の比較開始位置を初期化(変数V)。
        3540 文字列Uと文字列Vを比較。
        3550 一致したら、文字列は見つかった。変数X=1のままリターン。
        3560 検索される文字列(変数W)の検索位置の文字が0x00なら見つからなかった。
        3570 文字列Wの終わりに達したか。
        3580 検索される文字列の比較開始位置を1文字ずらして再び比較する準備。
        3590 検索処理のループ。
        3600 文字列は見つからなかったので変数X=0を代入して、
        3610 メイン・ルーチンに戻る。

    14. EDIT
      行番号名称入力出力処理備考
      10000EDIT---X:入力文字数
      Y:コマンドの次のアドレス
      エディターのメイン・ループ。プロンプト>を表示した後に
      コマンドを入力して、各コマンド処理にに分岐します。
       

      (2)処理内容
        プロンプト「>」を表示して、コマンドの入力を待ちます。
        コマンドが入力されると、最初の1文字からコマンドの種類を判定し
        それぞれのコマンド処理に分岐します。
        変数Xにはコマンドとして入力された文字数が設定されています。

      (3)ソース・リスト
        10000 ?=">";
        10010 #=1400
        10020 Y=G
        10030 ^=Y
        10040 Y=Y+1
        10050 #=(\=97)*16000
        10060 #=(\=98)*12000
        10080 #=(\=100)*17000
        10090 #=(\=101)*50000
        10100 #=(\=102)*21000
        10130 #=(\=105)*11000
        10160 #=(\=108)*20000
        10180 #=(\=110)*13000
        10200 #=(\=112)*15000
        10210 #=(\=113)*50000
        10220 #=(\=114)*18000
        10230 #=(\=115)*19000
        10240 #=(\=116)*14000
        10250 #=(\=122)*20000
        10300 #=10000

        [解説]
        10000 コマンド入力を待つため、プロンプト">"を表示。
        10010 コマンドを入力。結果は入力バッファに格納。
        10020 入力バッファの先頭アドレス(G)をポインタとなる変数Yにコピー。
        10030 入力バッファの先頭をバイトで読みだすため、VTLのポインタ^に変数Yをコピー。
        10040 入力バッファのポインタ変数Yを更新。
        10050 入力コマンドが"a"(97)ならaコマンド処理へ。
        10060 入力コマンドが"b"(98)ならbコマンド処理へ。
        10080 入力コマンドが"d"(100)ならdコマンド処理へ。
        10090 入力コマンドが"e"(101)ならエディタ終了。
        10100 入力コマンドが"f"(102)ならfコマンド処理へ。
        10130 入力コマンドが"i"(105)ならiコマンド処理へ。
        10160 入力コマンドが"l"(108)ならlコマンド処理へ。
        10180 入力コマンドが"n"(110)ならnコマンド処理へ。
        10200 入力コマンドが"p"(112)ならpコマンド処理へ。
        10210 入力コマンドが"q"(113)ならエディタ終了。
        10220 入力コマンドが"r"(114)ならrコマンド処理へ。
        10230 入力コマンドが"s"(115)ならsコマンド処理へ。
        10240 入力コマンドが"t"(116)ならtコマンド処理へ。
        10250 (削除予定)
        10300 それら以外の文字なら無視してエディタの入力待ちへ。

    15. INSR
      行番号名称入力出力処理備考
      11000INSRX:挿入文字数
      Y:コマンドの次アドレス
      --- i コマンドを実行します。
       

      (2)処理内容
        iコマンドでは、コマンド名称のiの文字に続く文字列を行ポインタの位置に挿入します。
        iコマンド開始時のテキスト・バッファの状態は下図となっています。


        挿入する文字列はiの次から区切り文字の0x00までです。
        変数Xにはコマンドとして入力された文字列の長さが設定されていますが
        このXには区切り文字は含まず、逆にコマンド名称のiの1文字の長さを含みます。
        結局、挿入文字列の長さは、変数Xの値そのままとなります。

        「i」の文字の次がEnterである場合は入力モードとなり
        連続して文字列の行を入力します。入力は、文頭にとじ括弧「)」が入力
        されると終了します。オリジナルのマイクロ・エディタではEnterでしたが
        これでは空行を入力することが出来ないため、文頭に現れる可能性の低い
        とじ括弧「)」で終了するよう仕様変更しました。
        なお、置換コマンド(rコマンド)を使用すると、行頭に「)」を入力する
        ことは可能です。

        行を挿入した後の行ポインタの位置は、挿入された行の次の行になります。

      (3)ソース・リスト
        11000 Z=X+1-1
        11010 #=(X=1)*11040
        11020 #=2200
        11030 #=10000
        11040 #=1400
        11050 Y=G
        11060 ^=Y
        11070 #=(\=41)*10000
        11080 Z=X+1
        11090 #=2200
        11100 #=11040

        [解説]
        11000 挿入文字数を変数Zに設定。変数Xは区切り文字0x00を含まないので
            +1したが、コマンド名称「i」を含んでいるので-1した。
        11010 入力文字列の長さが1とゆうことはコマンド名称の後に、すぐにEnter
            が入力されたのであるから、入力モードに入る。
        11020 1行挿入する。挿入する文字数はZ、挿入する文字の元は変数Yである。
        11030 1行挿入が終了し、コマンド入力に戻る。
        11040 挿入する文字列を1行入力する。
        11050 挿入する文字列の先頭アドレスを変数Yに設定。
        11060 挿入する文字列の先頭がとじ括弧(46)なら
        11070 入力モードを終了してコマンド待ちに戻る。
        11080 挿入する文字列の長さは区切り文字(0x00)を加えて、変数X+1となる。
        11090 1行挿入処理。
        11100 入力モードのループ。次の入力文字列を入力する。

    16. BACK
      行番号名称入力出力処理備考
      12000BACKY:コマンドの次アドレス--- b コマンドを実行します。
       

      (2)処理内容
        指定した行数、行ポインタを戻します。
        最初にコマンドで指定された行数を求め、変数Zに代入します。
        Z回行ポインタを戻したたら(move up)最後にポインタの位置の行を
        表示して処理を終了します。

      (3)ソース・リスト
        12000 #=2000
        12010 #=(Z<E)*12030
        12020 Z=E
        12030 E=E-Z
        12040 F=F+Z
        12050 #=(Z=0)*12090
        12060 #=2400
        12070 Z=Z-1
        12080 #=12050
        12090 Y=D
        12100 #=1600
        12110 #=10000

        [解説]
        12000 入力バッファのコマンドの次のアドレスを数値に変換。結果は変数Z。
        12010 ポインタより上部分の行数Eと戻る行数Zを比較して、
        12020 小さい方を戻る行数Zとする。
        12030 ポインタより上部分の行数Eから戻る行数Zを引き、
        12040 ポインタより下部分の行数Fに戻る行数Zを足す。
        12050 ポインタ移動の開始。移動は終了か?
        12060 終了していなければ1行戻る。
        12070 戻る行数を1減らして、
        12080 ポインタ移動のためループする。
        12090 ポインタ位置の行表示のために、下部分のポインタD(DN)を変数Yにコピーし、
        12110 Y+1からの文字列を表示する。
        12120 bコマンドは終了した。



    17. NEXT
      行番号名称入力出力処理備考
      13000NEXTY:コマンドの次アドレス--- n コマンドを実行します。
       

      (2)処理内容
        指定した行数、行ポインタを進めます。
        最初にコマンドで指定された行数を求め、変数Zに代入します。
        Z回行ポインタを戻したたら(move up)最後にポインタの位置の行を
        表示して処理を終了します。
        Z行ポインタを進める処理は、サブルーチンのNXT2を使用します。
        その際、最終行のみ表示するためスイッチWは0を設定します。

      (3)ソース・リスト
        13000 #=2000
        13010 W=0
        13020 #=2800
        13030 #=10000

        [解説]
        13000 入力バッファのコマンドの次のアドレスを数値に変換。結果は変数Z。
        13010 行ポインタ更新時、最後の行のみ表示する。
        13020 ポインタの行数をZ行下げる。
        13030 nコマンドを終了。

    18. TP
      行番号名称入力出力処理備考
      14000TPY:コマンドの次アドレス--- t コマンドを実行します。
       

      (2)処理内容
        ポインタをテキストの先頭から指定した行の位置に移動します。

        現在行がNであるとき、上部分の変数EはE=N-1です。
        すなわち、N=E+1が現在行となります。

        tコマンドにより先頭からZ行目に移動するとき、移動先が現在行より
        前の位置にある場合の戻り行数は下図により、(E+1)-Z行戻ればよいことになります。


        次に、tコマンドによる移動先が現在行より先(進んだ位置)にある場合は、
        下図により、Z-(E+1)=Z-E-1行戻ればよいことになります。


        実際に移動する処理は、移動する行数を変数Zに代入した後、
        戻るときはbコマンド、進むときははnコマンドに飛んで処理します。

      (3)ソース・リスト
        14000 #=2000
        14020 #=(Z>(E+1))*14050
        14030 Z=E-Z+1
        14040 #=12010
        14050 Z=Z-E-1
        14060 #=13010

        [解説]
        14000 入力バッファのコマンドの次のアドレスを数値に変換。結果は変数Z。
        14010 (削除)
        14020 移動先は現在行より先か?
        14030 戻りなら、戻る行数を計算し変数Zに代入。
        14040 Z行戻る処理(bコマンド内)に分岐。
        14050 先に進むなら、現在行より進む行数を計算し、変数Zに代入。
        14060 Z行進む処理(nコマンド内)に分岐。

    19. PRIN
      行番号名称入力出力処理備考
      15000PRINY:コマンドの次アドレス--- p コマンドを実行します。
       

      (2)処理内容
        現在行から、行を表示しながら、指定行ポインタを進めます。
        nコマンドとは、毎行表示する/しないのスイッチである
        変数Wの設定値が異なるだけです。

      (3)ソース・リスト
        15000 #=2000
        15010 W=1
        15020 #=2800
        15030 #=10000

        [解説]
        15000 入力バッファのコマンドの次のアドレスを数値に変換。結果は変数Z。
        15010 行ポインタ更新時、行を下げる毎に表示するためにスイッチW=1を設定。
        15020 ポインタをZ行、下に下げる。
        15030 pコマンドを終了。

    20. APND
      行番号名称入力出力処理備考
      16000APND------ a コマンドを実行します。
       

      (2)処理内容
        編集中のテキストの最終から行を追加します。
        まず、行ポインタを最終行に移動します。
        このとき、最終行が表示されますが、aコマンドでは最終行は
        つねに(EOT)が表示されます。
        その後、iコマンドの入力モードの処理に分岐します。

      (3)ソース・リスト
        16000 W=0
        16010 Z=F
        16020 #=2800
        16030 #=11040

        [解説]
        16000 最終行を表示するためスイッチW=0を設定。(実際はつねに(EOT)が表示される。)
        16010 現在行から最終行に移動するため、下部分の行数(変数F)を移動行数(変数Z)に代入。
        16020 最終行に移動するサブルーチン。
        16030 入力モードに分岐。

    21. DELT
      行番号名称入力出力処理備考
      17000DELTY:コマンドの次アドレス--- d コマンドを実行します。
       

      (2)処理内容
        現在行から指定行数削除します。
        削除の実際の処理はサブルーチンDLT1で実施します。

      (3)ソース・リスト
        17000 #=2000
        17010 #=3000
        17020 #=10000

        [解説]
        17000 指定する行数を取り出す。結果は変数Zにある。
        17010 現在行から変数Zの行数を削除。
        17020 エディタに戻る。

    22. RTYP
      行番号名称入力出力処理備考
      18000RTYPX:挿入文字数
      Y:コマンドの次アドレス
      --- r コマンドを実行します。
       

      (2)処理内容
        現在行の文字列を、新しい文字列で置き換えます。
        新しい文字列は複数行入力することは出来ません。
        最初に現在行を1行削除しますが、削除のサブルーチン(DLT1:行番号3000)
        では変数X、Y、U、Vが破壊されるため、挿入処理に必要な変数Xと変数Yを
        それぞれ変数Sと変数Tに退避します。
        少し汚いプログラムですが、ここだけ、データ・スタックを用意するのも
        面倒なため、このようにしました。
        削除処理と挿入処理の具体的な手順は、dコマンドとiコマンドを参照してください。

      (3)ソース・リスト
        18000 S=Y
        18010 T=X
        18020 Z=1
        18030 #=3000
        18040 Z=T
        18050 Y=S
        18060 #=2200
        18070 #=10000

        [解説]
        18000 コマンドの次のアドレス(変数Y)を変数Sに退避。
        18010 挿入する文字数(変数X)を変数Tに退避。
        18020 削除する行数を変数Zに設定。
        18030 現在行を削除。
        18040 挿入する文字数を変数Zに代入。
        18050 挿入す文字列の先頭アドレス(バイトアドレス)を変数Yに代入。
        18060 現在行に1行挿入。
        18070 rコマンド終了。エディタのコマンド入力に戻る。

    23. SAVE
      行番号名称入力出力処理備考
      19000SAVEX:入力文字数
      Y:コマンドの次アドレス
      --- s コマンドを実行します。
       

      (2)処理内容
        編集中のテキストをサイズ情報や行数情報とともに指定した
        論理セクタに格納します。論理セクタに格納する前に、
        全て、上部分に移動します。これは、編集を再開するために
        論理セクタからテキストをロードする場合、作業領域のサイズが
        異なる場合、下部分を移動する必要が発生するため、
        その必要がないようするためです。

        編集中のテキストをサイズ情報や行数情報は配列経由で
        アクセスするためワード・アクセスとなっています。
        この領域についてはメモリ・マップ のs、l コマンドで使用する領域の詳細
        も参照してください。

      (3)ソース・リスト
        19000 #=(X=1)*10000
        19010 #=2000
        19015 ?="Save Text"
        19020 T=Z
        19030 W=0
        19040 Z=F
        19050 #=2800
        19070 U=p
        19080 V=q
        19090 p=&+(H*2)
        19100 q=T
        19110 :H)=C-A
        19120 :H+1)=B-D
        19130 :H+2)=E
        19140 :H+3)=F
        19150 s=s
        19160 p=U
        19170 q=V
        19180 #=10000

        [解説]
        19000 論理セクタ番号の指定がなければ、コマンド実行しない。
        19010 指定された論理セクタ番号を変数Zに求める。
        19015 sコマンド実行メッセージ。
        19020 変数Zの論理セクタ番号を変数Tに退避。
        19030 テキスト移動後、最終行のみ表示のための指示スイッチ。
            このあとNXT2を呼出したとき参照される。
        19040 編集中のテキストを全て、
        19050 上部分に移動する。移動後「EOT」が表示されるが、sコマンドでは本来不要。
        19060 (削除)
        19070 現在設定されているVTLのシステム変数pを変数Uに退避。
        19080 現在設定されているVTLのシステム変数qを変数Vに退避。
        19090 セーブするテキスト作業領域のアドレスをVTLのシステム変数pに設定。
        19100 指定した論理セクタの番号をVTLのシステム変数qに設定。
        19110 上部分のポインタ(UP)(変数C)の作業領域の先頭(変数A)からの相対アドレスを
            論理セクタの情報として設定。
        19120 下部分のポインタ(DN)(変数D)の作業領域の末尾(変数B)からの距離を
            論理セクタの情報として設定。
        19130 上部分の行数(変数E)をセーブする論理セクタの情報として設定。
        19140 下部分の行数(変数F)をセーブする論理セクタの情報として設定。
        19150 システム変数pで指定したアドレスからの【後報】バイトを
            システム変数qで指定した論理セクタへセーブ。
        19160 変数Uに退避したVTLのシステム変数pを復帰。
        19170 変数Vに退避したVTLのシステム変数qを復帰。
        19180 エディタのコマンド入力に戻る。

    24. LOAD
      行番号名称入力出力処理備考
      20000LOADX:入力文字数
      Y:コマンドの次アドレス
      --- l コマンドを実行します。
       

      (2)処理内容
        指定した論理セクタから編集テキストを配列にロードします。
        論理セクタからテキストをロードする場合、ロードされるデータは
        固定長となるため、テキスト本体と一緒に格納されていた
        テキストの大きさや行数の情報からエディタの動作の再開に必要な
        ポインタやカウンタの情報(変数A〜D)も設定します。

      (3)ソース・リスト
        20000 #=(X=1)*10000
        20010 #=2000
        20015 ?="Load Text"
        20020 U=p
        20030 V=q
        20040 p=&+(H*2)
        20050 q=Z
        20060 l=l
        20070 C=:H)+A
        20080 D=B-:H+1)
        20090 E=:H+2)
        20100 F=:H+3)
        20110 p=U
        20120 q=V
        20130 #=10000

        [解説]
        20000 論理セクタ番号の指定がなければ、コマンド実行しない。
        20010 指定された論理セクタ番号を変数Zに求める。
        20015 lコマンド実行メッセージ。 (表示位置検討中)
        20020 現在設定されているVTLのシステム変数pを変数Uに退避。
        20030 現在設定されているVTLのシステム変数qを変数Vに退避。
        20040 テキストをロードする作業領域のアドレスをVTLのシステム変数pに設定。
        20050 指定した論理セクタの番号をVTLのシステム変数qに設定。
        20060 システム変数qで指定した論理セクタを、システム変数pで指定したアドレスにロード。
        20070 ロードした論理セクタの情報から、上部分のポインタ(UP)を変数Cに設定。
        20080 ロードした論理セクタの情報から、下部分のポインタ(DN)を変数Dに設定。
        20090 ロードした論理セクタの情報から、上部分の行数を変数Eに設定。
        20100 ロードした論理セクタの情報から、下部分の行数を変数Fに設定。
        20110 変数Uに退避したVTLのシステム変数pを復帰。
        20120 変数Vに退避したVTLのシステム変数qを復帰。
        20130 エディタのコマンド入力に戻る。

    25. FIND
      行番号名称入力出力処理備考
      21000FIND------ f コマンドを実行します。
       

      (2)処理内容
        文字列を検索するコマンドです。
        検索は、現在行から開始し、先(テキストの終わり方向)に向かって
        実行されます。見つからなかった場合、行ポインタはテキストの終わり(EOT)
        の位置となります。オリジナルのマイクロ・エディタでは、検索文字列は
        行頭にある文字列のみでしたが、さすがにこの仕様では使いづらいため、
        行の任意の位置に検索文字列があった場合でも検索出来るようにしました。

      (3)ソース・リスト
        21000 T=G+1
        21010 W=D+1
        21020 #=3500
        21030 #=(X=1)*21100
        21040 #=(F=0)*10000
        21050 #=2600
        21060 F=F-1
        21070 E=E+1
        21080 #=21000
        21100 Y=D
        21110 #=1500
        21120 #=10000

        [解説]
        21000 検索する文字列のポインタを変数Tに代入。(Yは破壊されるためGから代入)
        21010 検索される文字列(現在行である下部分のテキストの先頭)のポインタを変数Wに代入
        21020 ポインタTからの文字列が、ポインタWからの文字列に含まれるか検索。
        21030 文字列が見つかれば、変数X=1。その行が現在行となる。
        21040 下部分の行数が0になったら検索文字列は見つからなかったのでコマンド終了。
        21050 次の行の検索のため、現在行を1行進める。
        21060 次の行の検索のため、下部分の行数を1引く。
        21070 同様に上部分の行数を1足す。
        21080 次の行内を検索するため、ループ。
        21100 見つかった文字列のある行が現在行となったので、
        21110 その現在行を表示する。(表示はY+1から)
        21120 エディタのコマンド待ちに戻る。

    26. CHNG
      行番号名称入力出力処理備考
      22000CHNGY:コマンドの次アドレス--- g コマンドを実行します。
       

      (2)処理内容
        このコマンドの制作は止める予定です。

      (3)ソース・リスト

        [解説]

    27. START
      行番号名称入力出力処理備考
      100START------ エディタで使用する変数を初期化して
      エディタを開始します。
       

      (2)処理内容
        エディタで使用する定数・変数を初期化します。
        変数AとBの設定値はまだ暫定です。

      (3)ソース・リスト
        100 H=50
        110 A=H*2+32
        200 B=A+4096-32-1
        300 C=A
        400 D=B
        500 E=0
        600 F=0
        700 G=0
        800 #=9000

        9000 R=H
        9010 ?="Micro Editor"

        [解説]
        100
        110
        200
        300
        400
        500
        600
        700
        800

        9000 スタック・ポインタを初期化します。
        9010 マイクロ・エディタの開始のメッセージです。オリジナルにはありません。
           この後、10000行からエディタの処理に接続します。



JH8CHUのホームページ>Tiny言語>VTLによるマイクロ・エディタ


Copyright (C)2016 Masahiro.Matsuda(JH8CHU), all rights reserved.