ColdFire V1 - ラインエディタらしきもの [ColdFire (ColdeFire) V1]
シリアル・インターフェースを拡張してライン・エディタを作りました。
ソースコード
/* * $Source: /mnt/cvs/rep/CW/CFQE20/Sources/main.c,v $ * $Id: main.c,v 1.3 2008/02/03 02:10:58 noritan Exp $ */ #include <hidef.h> /* for EnableInterrupts macro */ #include "derivative.h" /* include peripheral declarations */ // 定数の宣言 #define BUF_LENGTH (72) #define TEXT_LENGTH (4096) // 大域変数の宣言 char lineBuf[BUF_LENGTH]; // ラインバッファ char *linePoint; // ラインポインタ char textBuf[TEXT_LENGTH]; // テキスト領域 char *textEnd; // テキスト終端ポインタ // お便利関数の宣言 int getc(void); void putc(int ch); void puts(const char *s); char *getLine(void); int getNumber(void); void insertLine(int lineno, char *line); void removeLineByNo(int lineno); char *findLine(int lineno); void listLines(void); void putNumber(int lineno); // メイン関数 void main(void) { int nLine; // 入力した数値 // SOPT1を設定する // COPは停止させる SOPT1 = 0 | SOPT1_WAITE_MASK // WAIT命令を許可 | SOPT1_RSTOPE_MASK // RSTO*出力を使う | SOPT1_BKGDPE_MASK // BKGDポートを使う | SOPT1_RSTPE_MASK ; // RESET*入力を使う // ICSを設定する // REFCLK = 31,250Hz // DCO = 48,000,000Hz // BUSCLK = DCO / 2 = 24,000,000Hz ICSTRM = NVICSTRM; ICSSC_FTRIM = NVFTRIM_FTRIM; ICSC2_BDIV = 0; // BDIV 1/1 ICSSC_DRST_DRS = 2; // FLL x1536 // SCI1を設定する // BAUD = 115200 // BR = BUSCLK / BAUD / 16 = 13 SCI1BD_SBR = 13; // クロック分周比 SCI1C2_TE = 1; // 送信機能を有効にする SCI1C2_RE = 1; // 受信機能を有効にする // テキストエリアの初期化 textBuf[0] = -1; textEnd = &textBuf[0]; EnableInterrupts; /* enable interrupts */ /* include your code here */ for(;;) { puts("\n*READY"); // プロンプトを表示する linePoint = getLine(); // 一行受信する nLine = getNumber(); // 数値を取り出す if (nLine < 0) { // 数値がない時には puts("*ERROR*"); // エラー表示 } else if (nLine == 0) { // 数値が0の時には、 listLines(); // リストを表示する } else if (!*linePoint) { // 数値だけの時には、 removeLineByNo(nLine); // 削除 } else { // それ以外は、 insertLine(nLine, linePoint); // 挿入処理 } } /* loop forever */ /* please make sure that you never leave main */ } // char *getLine(void) : // 一行受信ルーチン // ラインバッファの先頭を返す char *getLine(void) { char *p; // バッファポインタ char c; // 一文字バッファ for (;;) { putc(':'); // プロンプト出力 p = lineBuf; // バッファの先頭を指示 for (;;) { c = (char)getc(); // 一文字受け取り if (c == 8) { // Back Spaceの処理 putc(c); // カーソルをもどす p--; // 一文字戻す // ポインタがバッファの先頭に達したら、 // プロンプト出力からやりなおす。 if (p < lineBuf) break; } else if (c == '\n') { // Enterの処理 putc(c); // 改行出力 *p = 0; // 文字列末文字を書き込む return lineBuf; // バッファへのポインタを返す } else if (c < ' ') { // その他のコントロール文字 continue; // 単に無視する } else if (c == 127) { // DELETE文字の処理 putc('\n'); // 改行出力 break; // プロンプト出力からやりなおす } else { // 通常の文字の処理 putc(c); // エコーバック *p++ = c; // バッファに書き込む // バッファを使い切ったら、 if (p >= &lineBuf[BUF_LENGTH-1]) { putc('\n'); // 改行出力 break; // プロンプト出力からやりなおす } } } } } // int getc(void) : // 一文字受信ルーチン int getc(void) { int ch; // 文字バッファ // 受信バッファがいっぱいになるのを待つ while (!SCI1S1_RDRF) { // Do nothing } ch = SCI1D; // 一文字受け取る if (ch == '\r') { // Enterキーは、 ch = '\n'; // 行末文字に変換する } return ch; // 受け取った文字を返す } // void putc(int ch) : // 一文字送信ルーチン void putc(int ch) { if (ch == '\n') { // 行末文字の前にCRを付ける // 送信バッファが空くのを待つ while (!SCI1S1_TDRE) { // Do nothing } SCI1D = '\r'; // SCIにCR文字を送信する } // 送信バッファが空くのを待つ while (!SCI1S1_TDRE) { // Do nothing } SCI1D = (byte)ch; // SCIに一文字送信する } // void puts(const char *s) : // 文字列送信ルーチン void puts(const char *s) { while (*s) { // 文字列末でなければ、 putc(*s++); // 一文字送信する } } // int getNumber(void) : // ラインポインタの位置から数値を取り出す int getNumber(void) { int n = 0; // 数値 if (!isdigit(*linePoint)) { // 数字がなければ、 return -1; // -1 を返す } while (isdigit(*linePoint)) { // 数値の十進変換 n = n * 10 + ((*linePoint) - '0'); linePoint++; } return n; // 数値を返す } // void putNumber(int n) : // 数値の表示 - ZERO SUPPRESS は省略。 void putNumber(int n) { int m = 10000; // 着目する桁 while (m > 0) { // 一の位まで表示する putc((n / m) + '0'); // 着目桁の表示 n %= m; // 残りの桁の部分 m /= 10; // 着目桁の移動 } } // int getLineNo(line) // 行番号を取り出す int getLineNo(char *line) { return *((word *)line); } // char *nextLine(line) // 次の行にスキップする char *nextLine(char *line) { char *s; for (s = line + 2; *s++; ) { } return s; } // void removeLine(line) // ポインタで指示する行を削除する。 void removeLine(char *line) { const char *s; char *p; // 削除 p = (char *)line; s = nextLine(line); while (s < textEnd) { *p++ = *s++; } *p = *s; textEnd = p; } // char *findLine(lineno) // 行をさがす char *findLine(int lineno) { char *s; // 行を探す s = textBuf; for (;;) { // テキスト末端に到達 if (s >= textEnd) { break; } // 行番号を検証。 if (getLineNo(s) >= lineno) { // 行位置発見 break; } // 次の行にスキップ s = nextLine(s); } return s; } // void insertLine(lineno, line) : // 行挿入 void insertLine(int lineno, char *line) { char *s; char *p; char *pInsert; int length; // 挿入候補位置を探す pInsert = findLine(lineno); // 行番号を検証。 if (getLineNo(pInsert) == lineno) { // 置換 // 置換後の文字数差を計算する。 length = strlen(line) - strlen(&pInsert[2]); if (length > 0) { // 場所を拡張して挿入する if (textEnd - textBuf + length > TEXT_LENGTH) { // バッファ・オーバフロー pInsert = 0; } else { // 拡張 p = textEnd + length; s = textEnd; while (s >= pInsert) { *p-- = *s--; } textEnd += length; } } else if (length < 0) { // 場所を縮小して挿入する s = nextLine(pInsert); p = s + length; while (s <= textEnd) { *p++ = *s++; } textEnd += length; } else { // 上書き } } else { // バッファ・チェック length = strlen(line) + 3; if (textEnd - textBuf + length > TEXT_LENGTH) { // バッファ・オーバフロー pInsert = 0; } else { // 丸ごと拡張して挿入する p = textEnd + length; s = textEnd; while (s >= pInsert) { *p-- = *s--; } textEnd += length; } } // 挿入位置が見つからなければ、何もしない。 if (!pInsert) { return; } // 挿入開始 p = pInsert; // 行番号を書き込む *((word *)p) = (word)lineno; p += 2; // 本体を書き込む for (s = line; *s; ) { *p++ = *s++; } // 行末を書き込む *p++ = 0; } // void removeLineByNo(lineno) // 与えられた行番号の行を削除する void removeLineByNo(int lineno) { char *s; // 削除位置を探す s = findLine(lineno); // 行番号部分を比較する if (getLineNo(s) == lineno) { removeLine(s); } } // void listLines(void) // リスト出力 void listLines(void) { char *p; // テキスト終端まで表示する。 for (p = textBuf; p < textEnd; ) { // 行番号表示 putNumber(getLineNo(p)); p += 2; // 本文表示 while (*p) { putc(*p++); } putc('\n'); // 行末をスキップする p++; } }
使ってみよう
このラインエディタは、昔懐かしいインターフェースで構成されています。
*READY:10 i=1,100 *READY:0 00010 i=1,100 *READY:20 ?=i *READY:30 @=i+1 *READY:40 #=-1 *READY:0 00010 i=1,100 00020 ?=i 00030 @=i+1 00040 #=-1 *READY:20 *READY:0 00010 i=1,100 00030 @=i+1 00040 #=-1 *READY:20 ??=i *READY:0 00010 i=1,100 00020 ??=i 00030 @=i+1 00040 #=-1 *READY:20 ?$=i *READY:0 00010 i=1,100 00020 ?$=i 00030 @=i+1 00040 #=-1 *READY:20 ?=i *READY:0 00010 i=1,100 00020 ?=i 00030 @=i+1 00040 #=-1 *READY:???=i *READY:0 00010 i=1,100 00020 ???=i 00030 @=i+1 00040 #=-1 *READY:
putc/getcの実装時には、DEMOQE128を使いましたが、 それ以降のプログラムを作るのに、実機は使用していません。 すべて、CodeWarriorのシミュレータだけを使っています。
次は、インタプリタだな。
コメント 0