Natural Tiny Shell (NT-Shell) library is a tiny shell library for a small embedded system. The interface is really simple. You should only know ntshell_execute in ntshell.h. So you can port it to any embedded system easily. Please enjoy your small embedded system with it. :)

Dependents:   NaturalTinyShell_TestProgram

Committer:
shintamainjp
Date:
Sun May 22 02:51:35 2011 +0000
Revision:
0:7147d6024de8
Initial version.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
shintamainjp 0:7147d6024de8 1 /**
shintamainjp 0:7147d6024de8 2 * @file ntshell.c
shintamainjp 0:7147d6024de8 3 * @author Shinichiro Nakamura
shintamainjp 0:7147d6024de8 4 * @brief 小規模組み込みシステム向けのシェルシステムの実装。
shintamainjp 0:7147d6024de8 5 */
shintamainjp 0:7147d6024de8 6
shintamainjp 0:7147d6024de8 7 /*
shintamainjp 0:7147d6024de8 8 * ===============================================================
shintamainjp 0:7147d6024de8 9 * Natural Tiny Shell (NT-Shell)
shintamainjp 0:7147d6024de8 10 * Version 0.0.6
shintamainjp 0:7147d6024de8 11 * ===============================================================
shintamainjp 0:7147d6024de8 12 * Copyright (c) 2010-2011 Shinichiro Nakamura
shintamainjp 0:7147d6024de8 13 *
shintamainjp 0:7147d6024de8 14 * Permission is hereby granted, free of charge, to any person
shintamainjp 0:7147d6024de8 15 * obtaining a copy of this software and associated documentation
shintamainjp 0:7147d6024de8 16 * files (the "Software"), to deal in the Software without
shintamainjp 0:7147d6024de8 17 * restriction, including without limitation the rights to use,
shintamainjp 0:7147d6024de8 18 * copy, modify, merge, publish, distribute, sublicense, and/or
shintamainjp 0:7147d6024de8 19 * sell copies of the Software, and to permit persons to whom the
shintamainjp 0:7147d6024de8 20 * Software is furnished to do so, subject to the following
shintamainjp 0:7147d6024de8 21 * conditions:
shintamainjp 0:7147d6024de8 22 *
shintamainjp 0:7147d6024de8 23 * The above copyright notice and this permission notice shall be
shintamainjp 0:7147d6024de8 24 * included in all copies or substantial portions of the Software.
shintamainjp 0:7147d6024de8 25 *
shintamainjp 0:7147d6024de8 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
shintamainjp 0:7147d6024de8 27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
shintamainjp 0:7147d6024de8 28 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
shintamainjp 0:7147d6024de8 29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
shintamainjp 0:7147d6024de8 30 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
shintamainjp 0:7147d6024de8 31 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
shintamainjp 0:7147d6024de8 32 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
shintamainjp 0:7147d6024de8 33 * OTHER DEALINGS IN THE SOFTWARE.
shintamainjp 0:7147d6024de8 34 * ===============================================================
shintamainjp 0:7147d6024de8 35 */
shintamainjp 0:7147d6024de8 36
shintamainjp 0:7147d6024de8 37 #include "ntshell.h"
shintamainjp 0:7147d6024de8 38 #include "ntlibc.h"
shintamainjp 0:7147d6024de8 39
shintamainjp 0:7147d6024de8 40 #define VERSION_MAJOR 0 /**< メジャー番号。 */
shintamainjp 0:7147d6024de8 41 #define VERSION_MINOR 0 /**< マイナー番号。 */
shintamainjp 0:7147d6024de8 42 #define VERSION_RELEASE 6 /**< リリース番号。 */
shintamainjp 0:7147d6024de8 43
shintamainjp 0:7147d6024de8 44 /**
shintamainjp 0:7147d6024de8 45 * @brief 処理で用いるデータ構造体。
shintamainjp 0:7147d6024de8 46 *
shintamainjp 0:7147d6024de8 47 * @details
shintamainjp 0:7147d6024de8 48 * vtparseはユーザデータのポインタを設定することができる。
shintamainjp 0:7147d6024de8 49 * Natural Tiny Shellはこれを使って自身の処理で必要な情報を保持する。
shintamainjp 0:7147d6024de8 50 */
shintamainjp 0:7147d6024de8 51 typedef struct {
shintamainjp 0:7147d6024de8 52 text_editor_t *editor;
shintamainjp 0:7147d6024de8 53 text_history_t *history;
shintamainjp 0:7147d6024de8 54 int suggest_index;
shintamainjp 0:7147d6024de8 55 char suggest_source[TEXTEDITOR_MAXLEN];
shintamainjp 0:7147d6024de8 56 int (*func_read)(char *buf, int cnt);
shintamainjp 0:7147d6024de8 57 int (*func_write)(const char *buf, int cnt);
shintamainjp 0:7147d6024de8 58 int (*func_cb)(const char *text);
shintamainjp 0:7147d6024de8 59 } ntshell_user_data_t;
shintamainjp 0:7147d6024de8 60
shintamainjp 0:7147d6024de8 61 #define SUGGEST_INDEX(vtp) \
shintamainjp 0:7147d6024de8 62 ((ntshell_user_data_t *)(vtp)->user_data)->suggest_index
shintamainjp 0:7147d6024de8 63 #define SUGGEST_SOURCE(vtp) \
shintamainjp 0:7147d6024de8 64 ((ntshell_user_data_t *)(vtp)->user_data)->suggest_source
shintamainjp 0:7147d6024de8 65
shintamainjp 0:7147d6024de8 66 /**
shintamainjp 0:7147d6024de8 67 * @brief テキストエディタを取得する。
shintamainjp 0:7147d6024de8 68 *
shintamainjp 0:7147d6024de8 69 * @param vtp vtparse構造体。
shintamainjp 0:7147d6024de8 70 */
shintamainjp 0:7147d6024de8 71 #define GET_EDITOR(vtp) \
shintamainjp 0:7147d6024de8 72 ((ntshell_user_data_t *)(vtp)->user_data)->editor
shintamainjp 0:7147d6024de8 73
shintamainjp 0:7147d6024de8 74 /**
shintamainjp 0:7147d6024de8 75 * @brief テキストヒストリを取得する。
shintamainjp 0:7147d6024de8 76 *
shintamainjp 0:7147d6024de8 77 * @param vtp vtparse構造体。
shintamainjp 0:7147d6024de8 78 */
shintamainjp 0:7147d6024de8 79 #define GET_HISTORY(vtp) \
shintamainjp 0:7147d6024de8 80 ((ntshell_user_data_t *)(vtp)->user_data)->history
shintamainjp 0:7147d6024de8 81
shintamainjp 0:7147d6024de8 82 /**
shintamainjp 0:7147d6024de8 83 * @brief シリアルポートから読み込む。
shintamainjp 0:7147d6024de8 84 *
shintamainjp 0:7147d6024de8 85 * @param vtp vtparse構造体。
shintamainjp 0:7147d6024de8 86 * @param buf 読み込みバッファ。
shintamainjp 0:7147d6024de8 87 * @param cnt 読み込み文字数。
shintamainjp 0:7147d6024de8 88 */
shintamainjp 0:7147d6024de8 89 #define SERIAL_READ(vtp,buf,cnt) \
shintamainjp 0:7147d6024de8 90 ((ntshell_user_data_t *)(vtp)->user_data)->func_read(buf, cnt)
shintamainjp 0:7147d6024de8 91
shintamainjp 0:7147d6024de8 92 /**
shintamainjp 0:7147d6024de8 93 * @brief シリアルポートへ書き込む。
shintamainjp 0:7147d6024de8 94 *
shintamainjp 0:7147d6024de8 95 * @param vtp vtparse構造体。
shintamainjp 0:7147d6024de8 96 * @param buf 書き込みバッファ。
shintamainjp 0:7147d6024de8 97 * @param cnt 書き込み文字数。
shintamainjp 0:7147d6024de8 98 */
shintamainjp 0:7147d6024de8 99 #define SERIAL_WRITE(vtp,buf,cnt) \
shintamainjp 0:7147d6024de8 100 ((ntshell_user_data_t *)(vtp)->user_data)->func_write(buf, cnt)
shintamainjp 0:7147d6024de8 101
shintamainjp 0:7147d6024de8 102 /**
shintamainjp 0:7147d6024de8 103 * @brief コールバックを呼び出す。
shintamainjp 0:7147d6024de8 104 *
shintamainjp 0:7147d6024de8 105 * @param vtp vtparse構造体。
shintamainjp 0:7147d6024de8 106 * @param text コールバック関数へ渡す文字列。
shintamainjp 0:7147d6024de8 107 */
shintamainjp 0:7147d6024de8 108 #define CALLBACK(vtp, text) \
shintamainjp 0:7147d6024de8 109 ((ntshell_user_data_t *)(vtp)->user_data)->func_cb(text)
shintamainjp 0:7147d6024de8 110
shintamainjp 0:7147d6024de8 111 /**
shintamainjp 0:7147d6024de8 112 * @brief テキストヒストリで1つ後ろを辿る。
shintamainjp 0:7147d6024de8 113 *
shintamainjp 0:7147d6024de8 114 * @param parser パーサー。
shintamainjp 0:7147d6024de8 115 * @param action アクション。
shintamainjp 0:7147d6024de8 116 * @param ch 入力文字。
shintamainjp 0:7147d6024de8 117 */
shintamainjp 0:7147d6024de8 118 static void actfunc_history_prev(
shintamainjp 0:7147d6024de8 119 vtparse_t *parser,
shintamainjp 0:7147d6024de8 120 vtparse_action_t action,
shintamainjp 0:7147d6024de8 121 unsigned char ch) {
shintamainjp 0:7147d6024de8 122 if (text_history_read_point_prev(GET_HISTORY(parser))) {
shintamainjp 0:7147d6024de8 123 char txt[TEXTHISTORY_MAXLEN];
shintamainjp 0:7147d6024de8 124 int n = text_history_read(GET_HISTORY(parser), &txt[0], sizeof(txt));
shintamainjp 0:7147d6024de8 125 if (0 < n) {
shintamainjp 0:7147d6024de8 126 SERIAL_WRITE(parser, "\x1b[2K", 4);
shintamainjp 0:7147d6024de8 127 SERIAL_WRITE(parser, "\x1b[80D", 5);
shintamainjp 0:7147d6024de8 128 SERIAL_WRITE(parser, ">", 1);
shintamainjp 0:7147d6024de8 129 SERIAL_WRITE(parser, txt, n);
shintamainjp 0:7147d6024de8 130 text_editor_set_text(GET_EDITOR(parser), txt);
shintamainjp 0:7147d6024de8 131 }
shintamainjp 0:7147d6024de8 132 }
shintamainjp 0:7147d6024de8 133 }
shintamainjp 0:7147d6024de8 134
shintamainjp 0:7147d6024de8 135 /**
shintamainjp 0:7147d6024de8 136 * @brief テキストヒストリで1つ前を辿る。
shintamainjp 0:7147d6024de8 137 *
shintamainjp 0:7147d6024de8 138 * @param parser パーサー。
shintamainjp 0:7147d6024de8 139 * @param action アクション。
shintamainjp 0:7147d6024de8 140 * @param ch 入力文字。
shintamainjp 0:7147d6024de8 141 */
shintamainjp 0:7147d6024de8 142 static void actfunc_history_next(
shintamainjp 0:7147d6024de8 143 vtparse_t *parser,
shintamainjp 0:7147d6024de8 144 vtparse_action_t action,
shintamainjp 0:7147d6024de8 145 unsigned char ch) {
shintamainjp 0:7147d6024de8 146 if (text_history_read_point_next(GET_HISTORY(parser))) {
shintamainjp 0:7147d6024de8 147 char txt[TEXTHISTORY_MAXLEN];
shintamainjp 0:7147d6024de8 148 int n = text_history_read(GET_HISTORY(parser), &txt[0], sizeof(txt));
shintamainjp 0:7147d6024de8 149 if (0 < n) {
shintamainjp 0:7147d6024de8 150 SERIAL_WRITE(parser, "\x1b[2K", 4);
shintamainjp 0:7147d6024de8 151 SERIAL_WRITE(parser, "\x1b[80D", 5);
shintamainjp 0:7147d6024de8 152 SERIAL_WRITE(parser, ">", 1);
shintamainjp 0:7147d6024de8 153 SERIAL_WRITE(parser, txt, n);
shintamainjp 0:7147d6024de8 154 text_editor_set_text(GET_EDITOR(parser), txt);
shintamainjp 0:7147d6024de8 155 }
shintamainjp 0:7147d6024de8 156 }
shintamainjp 0:7147d6024de8 157 }
shintamainjp 0:7147d6024de8 158
shintamainjp 0:7147d6024de8 159 /**
shintamainjp 0:7147d6024de8 160 * @brief カーソルを左へ移動させる。
shintamainjp 0:7147d6024de8 161 *
shintamainjp 0:7147d6024de8 162 * @param parser パーサー。
shintamainjp 0:7147d6024de8 163 * @param action アクション。
shintamainjp 0:7147d6024de8 164 * @param ch 入力文字。
shintamainjp 0:7147d6024de8 165 */
shintamainjp 0:7147d6024de8 166 static void actfunc_cursor_left(
shintamainjp 0:7147d6024de8 167 vtparse_t *parser,
shintamainjp 0:7147d6024de8 168 vtparse_action_t action,
shintamainjp 0:7147d6024de8 169 unsigned char ch) {
shintamainjp 0:7147d6024de8 170 if (text_editor_cursor_left(GET_EDITOR(parser))) {
shintamainjp 0:7147d6024de8 171 SERIAL_WRITE(parser, "\x1b[1D", 4);
shintamainjp 0:7147d6024de8 172 }
shintamainjp 0:7147d6024de8 173 }
shintamainjp 0:7147d6024de8 174
shintamainjp 0:7147d6024de8 175 /**
shintamainjp 0:7147d6024de8 176 * @brief カーソルを右へ移動させる。
shintamainjp 0:7147d6024de8 177 *
shintamainjp 0:7147d6024de8 178 * @param parser パーサー。
shintamainjp 0:7147d6024de8 179 * @param action アクション。
shintamainjp 0:7147d6024de8 180 * @param ch 入力文字。
shintamainjp 0:7147d6024de8 181 */
shintamainjp 0:7147d6024de8 182 static void actfunc_cursor_right(
shintamainjp 0:7147d6024de8 183 vtparse_t *parser,
shintamainjp 0:7147d6024de8 184 vtparse_action_t action,
shintamainjp 0:7147d6024de8 185 unsigned char ch) {
shintamainjp 0:7147d6024de8 186 if (text_editor_cursor_right(GET_EDITOR(parser))) {
shintamainjp 0:7147d6024de8 187 SERIAL_WRITE(parser, "\x1b[1C", 4);
shintamainjp 0:7147d6024de8 188 }
shintamainjp 0:7147d6024de8 189 }
shintamainjp 0:7147d6024de8 190
shintamainjp 0:7147d6024de8 191 /**
shintamainjp 0:7147d6024de8 192 * @brief エンターキーの処理を実行する。
shintamainjp 0:7147d6024de8 193 *
shintamainjp 0:7147d6024de8 194 * @param parser パーサー。
shintamainjp 0:7147d6024de8 195 * @param action アクション。
shintamainjp 0:7147d6024de8 196 * @param ch 入力文字。
shintamainjp 0:7147d6024de8 197 */
shintamainjp 0:7147d6024de8 198 static void actfunc_enter(
shintamainjp 0:7147d6024de8 199 vtparse_t *parser,
shintamainjp 0:7147d6024de8 200 vtparse_action_t action,
shintamainjp 0:7147d6024de8 201 unsigned char ch) {
shintamainjp 0:7147d6024de8 202 char txt[TEXTEDITOR_MAXLEN];
shintamainjp 0:7147d6024de8 203 text_editor_get_text(GET_EDITOR(parser), &txt[0], sizeof(txt));
shintamainjp 0:7147d6024de8 204 text_editor_clear(GET_EDITOR(parser));
shintamainjp 0:7147d6024de8 205 text_history_write(GET_HISTORY(parser), txt);
shintamainjp 0:7147d6024de8 206 SERIAL_WRITE(parser, "\r\n", 2);
shintamainjp 0:7147d6024de8 207 CALLBACK(parser, txt);
shintamainjp 0:7147d6024de8 208 SERIAL_WRITE(parser, ">", 1);
shintamainjp 0:7147d6024de8 209 }
shintamainjp 0:7147d6024de8 210
shintamainjp 0:7147d6024de8 211 /**
shintamainjp 0:7147d6024de8 212 * @brief キャンセルキーの処理を実行する。
shintamainjp 0:7147d6024de8 213 * @details
shintamainjp 0:7147d6024de8 214 * 一般的なOSのCTRL+C処理はシグナルを発行し、受信したプロセスが
shintamainjp 0:7147d6024de8 215 * 中断処理を実行する。
shintamainjp 0:7147d6024de8 216 * ここでのキャンセルは見た目を再現したもので、
shintamainjp 0:7147d6024de8 217 * 入力中の文字列を破棄してカーソルを新しい入力に備えて復帰させるものだ。
shintamainjp 0:7147d6024de8 218 *
shintamainjp 0:7147d6024de8 219 * @param parser パーサー。
shintamainjp 0:7147d6024de8 220 * @param action アクション。
shintamainjp 0:7147d6024de8 221 * @param ch 入力文字。
shintamainjp 0:7147d6024de8 222 */
shintamainjp 0:7147d6024de8 223 static void actfunc_cancel(
shintamainjp 0:7147d6024de8 224 vtparse_t *parser,
shintamainjp 0:7147d6024de8 225 vtparse_action_t action,
shintamainjp 0:7147d6024de8 226 unsigned char ch) {
shintamainjp 0:7147d6024de8 227 SERIAL_WRITE(parser, "^C\r\n", 4);
shintamainjp 0:7147d6024de8 228 text_editor_clear(GET_EDITOR(parser));
shintamainjp 0:7147d6024de8 229 SERIAL_WRITE(parser, ">", 1);
shintamainjp 0:7147d6024de8 230 }
shintamainjp 0:7147d6024de8 231
shintamainjp 0:7147d6024de8 232 /**
shintamainjp 0:7147d6024de8 233 * @brief 挿入処理を実行する。
shintamainjp 0:7147d6024de8 234 *
shintamainjp 0:7147d6024de8 235 * @param parser パーサー。
shintamainjp 0:7147d6024de8 236 * @param action アクション。
shintamainjp 0:7147d6024de8 237 * @param ch 入力文字。
shintamainjp 0:7147d6024de8 238 */
shintamainjp 0:7147d6024de8 239 static void actfunc_insert(
shintamainjp 0:7147d6024de8 240 vtparse_t *parser,
shintamainjp 0:7147d6024de8 241 vtparse_action_t action,
shintamainjp 0:7147d6024de8 242 unsigned char ch) {
shintamainjp 0:7147d6024de8 243
shintamainjp 0:7147d6024de8 244 /*
shintamainjp 0:7147d6024de8 245 * 入力があった場合、入力補完状態から抜ける。
shintamainjp 0:7147d6024de8 246 */
shintamainjp 0:7147d6024de8 247 SUGGEST_INDEX(parser) = -1;
shintamainjp 0:7147d6024de8 248
shintamainjp 0:7147d6024de8 249 /*
shintamainjp 0:7147d6024de8 250 * テキストエディタを使って文字を文字列に挿入する。
shintamainjp 0:7147d6024de8 251 */
shintamainjp 0:7147d6024de8 252 if (text_editor_insert(GET_EDITOR(parser), ch)) {
shintamainjp 0:7147d6024de8 253 char txt[TEXTEDITOR_MAXLEN];
shintamainjp 0:7147d6024de8 254 int len = text_editor_get_text(GET_EDITOR(parser), &txt[0], sizeof(txt));
shintamainjp 0:7147d6024de8 255 int pos = text_editor_cursor_get_position(GET_EDITOR(parser));
shintamainjp 0:7147d6024de8 256 SERIAL_WRITE(parser, (char *)&ch, sizeof(ch));
shintamainjp 0:7147d6024de8 257 int n = len - pos;
shintamainjp 0:7147d6024de8 258 if (n > 0) {
shintamainjp 0:7147d6024de8 259 int i;
shintamainjp 0:7147d6024de8 260 SERIAL_WRITE(parser, txt + pos, len - pos);
shintamainjp 0:7147d6024de8 261 for (i = 0; i < n; i++) {
shintamainjp 0:7147d6024de8 262 SERIAL_WRITE(parser, "\x1b[1D", 4);
shintamainjp 0:7147d6024de8 263 }
shintamainjp 0:7147d6024de8 264 }
shintamainjp 0:7147d6024de8 265 }
shintamainjp 0:7147d6024de8 266 }
shintamainjp 0:7147d6024de8 267
shintamainjp 0:7147d6024de8 268 /**
shintamainjp 0:7147d6024de8 269 * @brief バックスペース処理を実行する。
shintamainjp 0:7147d6024de8 270 *
shintamainjp 0:7147d6024de8 271 * @param parser パーサー。
shintamainjp 0:7147d6024de8 272 * @param action アクション。
shintamainjp 0:7147d6024de8 273 * @param ch 入力文字。
shintamainjp 0:7147d6024de8 274 */
shintamainjp 0:7147d6024de8 275 static void actfunc_backspace(
shintamainjp 0:7147d6024de8 276 vtparse_t *parser,
shintamainjp 0:7147d6024de8 277 vtparse_action_t action,
shintamainjp 0:7147d6024de8 278 unsigned char ch) {
shintamainjp 0:7147d6024de8 279 if (text_editor_backspace(GET_EDITOR(parser))) {
shintamainjp 0:7147d6024de8 280 char txt[TEXTEDITOR_MAXLEN];
shintamainjp 0:7147d6024de8 281 SERIAL_WRITE(parser, "\x1b[1D", 4);
shintamainjp 0:7147d6024de8 282 int len = text_editor_get_text(GET_EDITOR(parser), &txt[0], sizeof(txt));
shintamainjp 0:7147d6024de8 283 int pos = text_editor_cursor_get_position(GET_EDITOR(parser));
shintamainjp 0:7147d6024de8 284 int n = len - pos;
shintamainjp 0:7147d6024de8 285 if (n > 0) {
shintamainjp 0:7147d6024de8 286 int i;
shintamainjp 0:7147d6024de8 287 SERIAL_WRITE(parser, txt + pos, len - pos);
shintamainjp 0:7147d6024de8 288 SERIAL_WRITE(parser, " ", 1);
shintamainjp 0:7147d6024de8 289 for (i = 0; i < n + 1; i++) {
shintamainjp 0:7147d6024de8 290 SERIAL_WRITE(parser, "\x1b[1D", 4);
shintamainjp 0:7147d6024de8 291 }
shintamainjp 0:7147d6024de8 292 } else {
shintamainjp 0:7147d6024de8 293 SERIAL_WRITE(parser, " ", 1);
shintamainjp 0:7147d6024de8 294 SERIAL_WRITE(parser, "\x1b[1D", 4);
shintamainjp 0:7147d6024de8 295 }
shintamainjp 0:7147d6024de8 296 }
shintamainjp 0:7147d6024de8 297 }
shintamainjp 0:7147d6024de8 298
shintamainjp 0:7147d6024de8 299 /**
shintamainjp 0:7147d6024de8 300 * @brief 入力補完処理を実行する。
shintamainjp 0:7147d6024de8 301 *
shintamainjp 0:7147d6024de8 302 * @param parser パーサー。
shintamainjp 0:7147d6024de8 303 * @param action アクション。
shintamainjp 0:7147d6024de8 304 * @param ch 入力文字。
shintamainjp 0:7147d6024de8 305 */
shintamainjp 0:7147d6024de8 306 static void actfunc_suggest(
shintamainjp 0:7147d6024de8 307 vtparse_t *parser,
shintamainjp 0:7147d6024de8 308 vtparse_action_t action,
shintamainjp 0:7147d6024de8 309 unsigned char ch) {
shintamainjp 0:7147d6024de8 310 char buf[TEXTEDITOR_MAXLEN];
shintamainjp 0:7147d6024de8 311 if (SUGGEST_INDEX(parser) < 0) {
shintamainjp 0:7147d6024de8 312 /*
shintamainjp 0:7147d6024de8 313 * 入力補完モードにこれから入る場合。
shintamainjp 0:7147d6024de8 314 * 現在の入力文字列を元に補完候補を取得する。
shintamainjp 0:7147d6024de8 315 */
shintamainjp 0:7147d6024de8 316 if (text_editor_get_text(
shintamainjp 0:7147d6024de8 317 GET_EDITOR(parser),
shintamainjp 0:7147d6024de8 318 SUGGEST_SOURCE(parser),
shintamainjp 0:7147d6024de8 319 sizeof(SUGGEST_SOURCE(parser))) > 0) {
shintamainjp 0:7147d6024de8 320 SUGGEST_INDEX(parser) = 0;
shintamainjp 0:7147d6024de8 321 if (text_history_find(
shintamainjp 0:7147d6024de8 322 GET_HISTORY(parser),
shintamainjp 0:7147d6024de8 323 SUGGEST_INDEX(parser),
shintamainjp 0:7147d6024de8 324 SUGGEST_SOURCE(parser),
shintamainjp 0:7147d6024de8 325 buf,
shintamainjp 0:7147d6024de8 326 sizeof(buf)) == 0) {
shintamainjp 0:7147d6024de8 327 // 候補が見つかればテキストを設定して、インデックスをメモする。
shintamainjp 0:7147d6024de8 328 int n = ntlibc_strlen((const char *)buf);
shintamainjp 0:7147d6024de8 329 SERIAL_WRITE(parser, "\x1b[2K", 4);
shintamainjp 0:7147d6024de8 330 SERIAL_WRITE(parser, "\x1b[80D", 5);
shintamainjp 0:7147d6024de8 331 SERIAL_WRITE(parser, ">", 1);
shintamainjp 0:7147d6024de8 332 SERIAL_WRITE(parser, buf, n);
shintamainjp 0:7147d6024de8 333 text_editor_set_text(GET_EDITOR(parser), buf);
shintamainjp 0:7147d6024de8 334 } else {
shintamainjp 0:7147d6024de8 335 // 候補がなければ入力補完モードから抜ける。
shintamainjp 0:7147d6024de8 336 SUGGEST_INDEX(parser) = -1;
shintamainjp 0:7147d6024de8 337 }
shintamainjp 0:7147d6024de8 338 }
shintamainjp 0:7147d6024de8 339 } else {
shintamainjp 0:7147d6024de8 340 /*
shintamainjp 0:7147d6024de8 341 * 既に入力補完モードに入っている場合、
shintamainjp 0:7147d6024de8 342 * 次の候補を探して見つかればテキストとして設定する。
shintamainjp 0:7147d6024de8 343 */
shintamainjp 0:7147d6024de8 344 SUGGEST_INDEX(parser) = SUGGEST_INDEX(parser) + 1;
shintamainjp 0:7147d6024de8 345 if (text_history_find(
shintamainjp 0:7147d6024de8 346 GET_HISTORY(parser),
shintamainjp 0:7147d6024de8 347 SUGGEST_INDEX(parser),
shintamainjp 0:7147d6024de8 348 SUGGEST_SOURCE(parser),
shintamainjp 0:7147d6024de8 349 buf,
shintamainjp 0:7147d6024de8 350 sizeof(buf)) == 0) {
shintamainjp 0:7147d6024de8 351 // 候補が見つかればテキストを設定する。
shintamainjp 0:7147d6024de8 352 int n = ntlibc_strlen((const char *)buf);
shintamainjp 0:7147d6024de8 353 SERIAL_WRITE(parser, "\x1b[2K", 4);
shintamainjp 0:7147d6024de8 354 SERIAL_WRITE(parser, "\x1b[80D", 5);
shintamainjp 0:7147d6024de8 355 SERIAL_WRITE(parser, ">", 1);
shintamainjp 0:7147d6024de8 356 SERIAL_WRITE(parser, buf, n);
shintamainjp 0:7147d6024de8 357 text_editor_set_text(GET_EDITOR(parser), buf);
shintamainjp 0:7147d6024de8 358 } else {
shintamainjp 0:7147d6024de8 359 // 候補が見つからなければ元の入力文字列に戻し、入力補完モードから抜ける。
shintamainjp 0:7147d6024de8 360 int n = ntlibc_strlen(SUGGEST_SOURCE(parser));
shintamainjp 0:7147d6024de8 361 SERIAL_WRITE(parser, "\x1b[2K", 4);
shintamainjp 0:7147d6024de8 362 SERIAL_WRITE(parser, "\x1b[80D", 5);
shintamainjp 0:7147d6024de8 363 SERIAL_WRITE(parser, ">", 1);
shintamainjp 0:7147d6024de8 364 SERIAL_WRITE(parser, SUGGEST_SOURCE(parser), n);
shintamainjp 0:7147d6024de8 365 text_editor_set_text(GET_EDITOR(parser), SUGGEST_SOURCE(parser));
shintamainjp 0:7147d6024de8 366 SUGGEST_INDEX(parser) = -1;
shintamainjp 0:7147d6024de8 367 }
shintamainjp 0:7147d6024de8 368 }
shintamainjp 0:7147d6024de8 369 }
shintamainjp 0:7147d6024de8 370
shintamainjp 0:7147d6024de8 371 static void actfunc_cursor_head(
shintamainjp 0:7147d6024de8 372 vtparse_t *parser,
shintamainjp 0:7147d6024de8 373 vtparse_action_t action,
shintamainjp 0:7147d6024de8 374 unsigned char ch) {
shintamainjp 0:7147d6024de8 375 SERIAL_WRITE(parser, "\x1b[80D", 5);
shintamainjp 0:7147d6024de8 376 SERIAL_WRITE(parser, ">", 1);
shintamainjp 0:7147d6024de8 377 text_editor_cursor_head(GET_EDITOR(parser));
shintamainjp 0:7147d6024de8 378 }
shintamainjp 0:7147d6024de8 379
shintamainjp 0:7147d6024de8 380 static void actfunc_cursor_tail(
shintamainjp 0:7147d6024de8 381 vtparse_t *parser,
shintamainjp 0:7147d6024de8 382 vtparse_action_t action,
shintamainjp 0:7147d6024de8 383 unsigned char ch) {
shintamainjp 0:7147d6024de8 384 char buf[TEXTEDITOR_MAXLEN];
shintamainjp 0:7147d6024de8 385 int len;
shintamainjp 0:7147d6024de8 386 text_editor_get_text(GET_EDITOR(parser), buf, sizeof(buf));
shintamainjp 0:7147d6024de8 387 len = ntlibc_strlen((const char *)buf);
shintamainjp 0:7147d6024de8 388 SERIAL_WRITE(parser, "\x1b[80D", 5);
shintamainjp 0:7147d6024de8 389 SERIAL_WRITE(parser, ">", 1);
shintamainjp 0:7147d6024de8 390 SERIAL_WRITE(parser, buf, len);
shintamainjp 0:7147d6024de8 391 text_editor_cursor_tail(GET_EDITOR(parser));
shintamainjp 0:7147d6024de8 392 }
shintamainjp 0:7147d6024de8 393
shintamainjp 0:7147d6024de8 394 /**
shintamainjp 0:7147d6024de8 395 * @brief アクションテーブルのデータ構造体。
shintamainjp 0:7147d6024de8 396 * @details
shintamainjp 0:7147d6024de8 397 * アクションは状態と入力文字によって与えられる。
shintamainjp 0:7147d6024de8 398 * アクションに対する関数もここで定義する。
shintamainjp 0:7147d6024de8 399 */
shintamainjp 0:7147d6024de8 400 typedef struct {
shintamainjp 0:7147d6024de8 401 vtparse_action_t action;
shintamainjp 0:7147d6024de8 402 unsigned char ch;
shintamainjp 0:7147d6024de8 403 void (*func)(
shintamainjp 0:7147d6024de8 404 vtparse_t *parser,
shintamainjp 0:7147d6024de8 405 vtparse_action_t action,
shintamainjp 0:7147d6024de8 406 unsigned char ch);
shintamainjp 0:7147d6024de8 407 } ntshell_action_table_t;
shintamainjp 0:7147d6024de8 408
shintamainjp 0:7147d6024de8 409 /**
shintamainjp 0:7147d6024de8 410 * @brief アクションに対する処理関数テーブル。
shintamainjp 0:7147d6024de8 411 * @details
shintamainjp 0:7147d6024de8 412 * やってくるコードは仮想端末側の処理に依存する。
shintamainjp 0:7147d6024de8 413 * よって様々なプラットフォームの様々な仮想端末で試すと良い。
shintamainjp 0:7147d6024de8 414 *
shintamainjp 0:7147d6024de8 415 * <table>
shintamainjp 0:7147d6024de8 416 * <th>
shintamainjp 0:7147d6024de8 417 * <td>Platform</td>
shintamainjp 0:7147d6024de8 418 * <td>Tools</td>
shintamainjp 0:7147d6024de8 419 * </th>
shintamainjp 0:7147d6024de8 420 * <tr>
shintamainjp 0:7147d6024de8 421 * <td>Windows</td>
shintamainjp 0:7147d6024de8 422 * <td>Hyper Terminal, Poderossa, TeraTerm</td>
shintamainjp 0:7147d6024de8 423 * </tr>
shintamainjp 0:7147d6024de8 424 * <tr>
shintamainjp 0:7147d6024de8 425 * <td>Linux</td>
shintamainjp 0:7147d6024de8 426 * <td>minicom, screen, kermit</td>
shintamainjp 0:7147d6024de8 427 * </tr>
shintamainjp 0:7147d6024de8 428 * </table>
shintamainjp 0:7147d6024de8 429 */
shintamainjp 0:7147d6024de8 430 static const ntshell_action_table_t action_table[] = {
shintamainjp 0:7147d6024de8 431 {VTPARSE_ACTION_EXECUTE, 0x01, actfunc_cursor_head},
shintamainjp 0:7147d6024de8 432 {VTPARSE_ACTION_EXECUTE, 0x02, actfunc_cursor_left},
shintamainjp 0:7147d6024de8 433 {VTPARSE_ACTION_EXECUTE, 0x03, actfunc_cancel},
shintamainjp 0:7147d6024de8 434 {VTPARSE_ACTION_EXECUTE, 0x05, actfunc_cursor_tail},
shintamainjp 0:7147d6024de8 435 {VTPARSE_ACTION_EXECUTE, 0x06, actfunc_cursor_right},
shintamainjp 0:7147d6024de8 436 {VTPARSE_ACTION_EXECUTE, 0x08, actfunc_backspace},
shintamainjp 0:7147d6024de8 437 {VTPARSE_ACTION_EXECUTE, 0x09, actfunc_suggest},
shintamainjp 0:7147d6024de8 438 {VTPARSE_ACTION_EXECUTE, 0x0d, actfunc_enter},
shintamainjp 0:7147d6024de8 439 {VTPARSE_ACTION_EXECUTE, 0x0e, actfunc_history_next},
shintamainjp 0:7147d6024de8 440 {VTPARSE_ACTION_EXECUTE, 0x10, actfunc_history_prev},
shintamainjp 0:7147d6024de8 441 {VTPARSE_ACTION_CSI_DISPATCH, 0x41, actfunc_history_prev},
shintamainjp 0:7147d6024de8 442 {VTPARSE_ACTION_CSI_DISPATCH, 0x42, actfunc_history_next},
shintamainjp 0:7147d6024de8 443 {VTPARSE_ACTION_CSI_DISPATCH, 0x43, actfunc_cursor_right},
shintamainjp 0:7147d6024de8 444 {VTPARSE_ACTION_CSI_DISPATCH, 0x44, actfunc_cursor_left},
shintamainjp 0:7147d6024de8 445 {VTPARSE_ACTION_PRINT, 0x7f, actfunc_backspace},
shintamainjp 0:7147d6024de8 446 };
shintamainjp 0:7147d6024de8 447
shintamainjp 0:7147d6024de8 448 /**
shintamainjp 0:7147d6024de8 449 * @brief パーサーに対するコールバック関数。
shintamainjp 0:7147d6024de8 450 * @details vtparseモジュールのコールバック関数に従った実装である。
shintamainjp 0:7147d6024de8 451 *
shintamainjp 0:7147d6024de8 452 * @param parser パーサー。
shintamainjp 0:7147d6024de8 453 * @param action アクション。
shintamainjp 0:7147d6024de8 454 * @param ch キャラクタ。
shintamainjp 0:7147d6024de8 455 */
shintamainjp 0:7147d6024de8 456 void parser_callback(
shintamainjp 0:7147d6024de8 457 vtparse_t *parser,
shintamainjp 0:7147d6024de8 458 vtparse_action_t action,
shintamainjp 0:7147d6024de8 459 unsigned char ch) {
shintamainjp 0:7147d6024de8 460 ntshell_action_table_t *p;
shintamainjp 0:7147d6024de8 461 int i;
shintamainjp 0:7147d6024de8 462 const int ACTTBLSIZ = sizeof(action_table) / sizeof(action_table[0]);
shintamainjp 0:7147d6024de8 463
shintamainjp 0:7147d6024de8 464 /*
shintamainjp 0:7147d6024de8 465 * 制御コードに対する処理はテーブルから探す。
shintamainjp 0:7147d6024de8 466 */
shintamainjp 0:7147d6024de8 467 p = (ntshell_action_table_t *)action_table;
shintamainjp 0:7147d6024de8 468 for (i = 0; i < ACTTBLSIZ; i++) {
shintamainjp 0:7147d6024de8 469 if ((p->action == action) && (p->ch == ch)) {
shintamainjp 0:7147d6024de8 470 p->func(parser, action, ch);
shintamainjp 0:7147d6024de8 471 return;
shintamainjp 0:7147d6024de8 472 }
shintamainjp 0:7147d6024de8 473 p++;
shintamainjp 0:7147d6024de8 474 }
shintamainjp 0:7147d6024de8 475
shintamainjp 0:7147d6024de8 476 /*
shintamainjp 0:7147d6024de8 477 * 通常の文字列は入力として扱う。
shintamainjp 0:7147d6024de8 478 */
shintamainjp 0:7147d6024de8 479 if (VTPARSE_ACTION_PRINT == action) {
shintamainjp 0:7147d6024de8 480 actfunc_insert(parser, action, ch);
shintamainjp 0:7147d6024de8 481 }
shintamainjp 0:7147d6024de8 482 }
shintamainjp 0:7147d6024de8 483
shintamainjp 0:7147d6024de8 484 /**
shintamainjp 0:7147d6024de8 485 * @brief Natural Tiny Shellのバージョンを返す。
shintamainjp 0:7147d6024de8 486 * @details 返すバージョンはリリースバージョンである。
shintamainjp 0:7147d6024de8 487 *
shintamainjp 0:7147d6024de8 488 * @param major メージャーバージョン。
shintamainjp 0:7147d6024de8 489 * @param minor マイナーバージョン。
shintamainjp 0:7147d6024de8 490 * @param release リリースバージョン。
shintamainjp 0:7147d6024de8 491 */
shintamainjp 0:7147d6024de8 492 void ntshell_version(int *major, int *minor, int *release)
shintamainjp 0:7147d6024de8 493 {
shintamainjp 0:7147d6024de8 494 *major = VERSION_MAJOR;
shintamainjp 0:7147d6024de8 495 *minor = VERSION_MINOR;
shintamainjp 0:7147d6024de8 496 *release = VERSION_RELEASE;
shintamainjp 0:7147d6024de8 497 }
shintamainjp 0:7147d6024de8 498
shintamainjp 0:7147d6024de8 499 /**
shintamainjp 0:7147d6024de8 500 * @brief Natural Tiny Shellを実行する。
shintamainjp 0:7147d6024de8 501 * @details この関数は実行を返さない。
shintamainjp 0:7147d6024de8 502 *
shintamainjp 0:7147d6024de8 503 * @param parser VT100パーサー。
shintamainjp 0:7147d6024de8 504 * @param editor テキストエディタ。
shintamainjp 0:7147d6024de8 505 * @param history テキストヒストリ。
shintamainjp 0:7147d6024de8 506 * @param func_read シリアルリード関数。
shintamainjp 0:7147d6024de8 507 * @param func_write シリアルライト関数。
shintamainjp 0:7147d6024de8 508 * @param func_cb コールバック関数。
shintamainjp 0:7147d6024de8 509 */
shintamainjp 0:7147d6024de8 510 void ntshell_execute(
shintamainjp 0:7147d6024de8 511 ntshell_t *p,
shintamainjp 0:7147d6024de8 512 int (*func_read)(char *buf, int cnt),
shintamainjp 0:7147d6024de8 513 int (*func_write)(const char *buf, int cnt),
shintamainjp 0:7147d6024de8 514 int (*func_cb)(const char *text))
shintamainjp 0:7147d6024de8 515 {
shintamainjp 0:7147d6024de8 516 /*
shintamainjp 0:7147d6024de8 517 * vtparseはユーザデータへのポインタを設定できるようになっている。
shintamainjp 0:7147d6024de8 518 * Natural Tiny Shellはこれを利用してテキストエディタやヒストリ、
shintamainjp 0:7147d6024de8 519 * リード関数やライト関数、コールバック関数を処理の中で使用できる
shintamainjp 0:7147d6024de8 520 * ようにしてある。
shintamainjp 0:7147d6024de8 521 */
shintamainjp 0:7147d6024de8 522 ntshell_user_data_t user_data;
shintamainjp 0:7147d6024de8 523
shintamainjp 0:7147d6024de8 524 user_data.editor = &(p->editor);
shintamainjp 0:7147d6024de8 525 user_data.history = &(p->history);
shintamainjp 0:7147d6024de8 526 user_data.func_read = func_read;
shintamainjp 0:7147d6024de8 527 user_data.func_write = func_write;
shintamainjp 0:7147d6024de8 528 user_data.func_cb = func_cb;
shintamainjp 0:7147d6024de8 529
shintamainjp 0:7147d6024de8 530 p->parser.user_data = &user_data;
shintamainjp 0:7147d6024de8 531
shintamainjp 0:7147d6024de8 532 /*
shintamainjp 0:7147d6024de8 533 * 各モジュールを初期化する。
shintamainjp 0:7147d6024de8 534 */
shintamainjp 0:7147d6024de8 535 vtparse_init(&(p->parser), parser_callback);
shintamainjp 0:7147d6024de8 536 text_editor_init(GET_EDITOR(&(p->parser)));
shintamainjp 0:7147d6024de8 537 text_history_init(GET_HISTORY(&(p->parser)));
shintamainjp 0:7147d6024de8 538 SUGGEST_INDEX(&(p->parser)) = -1;
shintamainjp 0:7147d6024de8 539
shintamainjp 0:7147d6024de8 540 /*
shintamainjp 0:7147d6024de8 541 * ユーザ入力ループ。
shintamainjp 0:7147d6024de8 542 */
shintamainjp 0:7147d6024de8 543 SERIAL_WRITE(&(p->parser), ">", 1);
shintamainjp 0:7147d6024de8 544 while(1)
shintamainjp 0:7147d6024de8 545 {
shintamainjp 0:7147d6024de8 546 unsigned char ch;
shintamainjp 0:7147d6024de8 547 SERIAL_READ(&(p->parser), (char *)&ch, sizeof(ch));
shintamainjp 0:7147d6024de8 548 vtparse(&(p->parser), &ch, sizeof(ch));
shintamainjp 0:7147d6024de8 549 }
shintamainjp 0:7147d6024de8 550 }
shintamainjp 0:7147d6024de8 551