#include #include #include #define HIST_NO (10) /* 保存する履歴の数 */ #define PROMPT "> " /* プロンプト */ /* コマンド一覧 */ #define CMD_EXIT "exit" /* 終了 */ #define CMD_HISTORY "history" /* 履歴表示 */ #define CMD_REQUEST "request" /* 変換処理開始要求 */ #define CMD_DISPLAY "display" /* 変換結果表示 */ #define CMD_BANG '#' /* コマンド置換制御 */ #define TMO_GETBLK (3000) /* 不足時の待ち時間 */ /* 可変長メモリプール */ #define BUFSZ (80) /* 入力用バッファサイズ */ #define MPLSZ ((BUFSZ*HIST_NO)/2) /* MPL全体のサイズ */ /* ^^ → わざと少なくしてある */ LOCAL ID mplid; /* 可変長メモリプールID */ LOCAL B* hist[HIST_NO]; /* 履歴へのポインタ */ LOCAL INT idx; /* 次の履歴登録位置 */ #define IDX(x) ((x)%HIST_NO) /* 履歴配列指定用 */ IMPORT char* strcpy( char *dst, const char *src ); IMPORT size_t strlen( const char *s ); IMPORT int strcmp( const char *s1, const char *s2 ); #define isdigit(c) (('0'<=(c))&&((c)<='9')) INT atoi( B *str ) /* 文字列 → 整数 */ { INT i = 0; while( isdigit(*str) ){ i = i*10 + (*str++ - '0'); } return i; } void itoa3( INT val, B *str ) /* 整数 → 文字列(3桁) */ { INT i; for( i = 2; i >= 0; i-- ){ /* 最大3桁 */ *(str+i) = val % 10 + '0'; val /= 10; } /* '\0' は追加していないので注意! */ } ER getCommand(B **cmdBuf ) /* コマンドの入力 */ { UB buf[BUFSZ]; /* 入力用の固定バッファ */ B *blk; INT size; /* 入力された文字数 */ ER ercd; tm_putstring( (UB*)PROMPT ); /* プロンプトを出力 */ size = tm_getline(buf); /* コンソールから入力 */ if( size == 0 ){ /* 改行のみ */ return 0; } if( size < 0 ){ /* Ctrl-C 入力 → 終了 */ strcpy( buf, CMD_EXIT ); size = sizeof(CMD_EXIT); } size++; /* 終端の '\0' 分を追加 */ ercd = tk_get_mpl( mplid, size, &blk, TMO_GETBLK ); if( ercd == E_OK ){ strcpy( blk, buf ); /* 新しい入力を保存 */ *cmdBuf = blk; /* メモリブロックを返す */ }else{ tm_putstring( "Can't get memory block!\n" ); size = ercd; } return size; /* 入力コマンドサイズ */ } ER replaceCommand( B **p_cmdBuf ) /* コマンドの置換 */ { INT reqIdx; /* 要求された履歴 */ B *cmdBuf = *p_cmdBuf; /* 入力されたコマンド */ B *newCmd; /* 置換した場合の領域 */ INT size; /* 置換した場合のサイズ */ ER ercd; if( *cmdBuf != CMD_BANG ){ /* 置換不要 */ return E_OK; } cmdBuf++; if( *cmdBuf == CMD_BANG ){ /* 1つ前 */ reqIdx = idx - 1; }else if( isdigit(*cmdBuf) ){ /* + "数字" */ reqIdx = atoi(cmdBuf) - 1 + HIST_NO; }else if( (*cmdBuf == '-') && isdigit(*(cmdBuf+1)) ){ reqIdx = idx - atoi(cmdBuf+1); } if( (reqIdx < (idx - HIST_NO))||(idx <= reqIdx) ){ tm_putstring( "Out of range!\n" ); return E_PAR; } size = strlen(hist[IDX(reqIdx)]) + 1; /* 確保すべきサイズ */ ercd = tk_get_mpl( mplid, size, &newCmd, TMO_GETBLK ); if( ercd < 0 ){ tm_putstring( "Can't get memory block!\n" ); }else{ tk_rel_mpl( mplid, *p_cmdBuf ); /* 置換指示文字列は破棄 */ *p_cmdBuf = newCmd; strcpy( newCmd, hist[IDX(reqIdx)] ); tm_putstring( newCmd ); tm_putstring( "\n" ); } return ercd; } void commandHistory(void) /* 履歴の表示 */ { B preStr[] = "[000] "; INT i; for( i = idx - (HIST_NO-1); i <= idx; i++ ){ if( *hist[IDX(i)] != '\0' ){ itoa3( i - (HIST_NO-1), &preStr[1] ); tm_putstring( preStr ); tm_putstring( hist[IDX(i)] ); tm_putstring( "\n" ); } } } ER commandRequest( B* cmd ) /* 変換要求 */ { /* リスト2で追加 */ return E_OK; } void commandDisplay(void) /* 変換結果の表示 */ { /* リスト2で追加 */ } ER executeCommand( B *cmdBuf ) /* コマンドの実行 */ { ER ercd = E_OK; if( !strcmp( cmdBuf, CMD_HISTORY ) ){ /* 履歴の表示 */ commandHistory(); } else if( !strncmp( cmdBuf, CMD_REQUEST, sizeof(CMD_REQUEST)-1 ) ){ ercd = commandRequest( cmdBuf ); /* 変換要求 */ } else if( !strcmp( cmdBuf, CMD_DISPLAY ) ){ commandDisplay(); /* 変換結果の表示 */ }else{ ercd = E_PAR; tm_putstring( "NO SUCH COMMAND\n" ); } return ercd; } void createTranslateTask(void) { /* リスト2で追加 */ } EXPORT INT usermain( void ) { CONST T_CMPL cmpl = { NULL, TA_TFIFO, MPLSZ }; B *cmdBuf; INT i; ER ercd; /*--------------*/ /* 初期化 */ /*--------------*/ mplid = tk_cre_mpl( &cmpl ); for( i = 0; i < HIST_NO; i++ ){ tk_get_mpl( mplid, 1, &cmdBuf, TMO_FEVR ); *cmdBuf = '\0'; hist[i] = cmdBuf; /* ダミーのメモリブロックを追加 */ } idx = HIST_NO; createTranslateTask(); /* 変換用タスクの生成 */ /*--------------*/ /* 主ループ */ /*--------------*/ while( 1 ){ ercd = getCommand( &cmdBuf ); /* コンソールから入力 */ if( ercd <= 0 ){ /* エラー or 改行のみ */ continue; } if( !strcmp( cmdBuf, CMD_EXIT ) ){ /* 終了確認 */ break;/*while*/ /* → ループから脱出 */ } ercd = replaceCommand( &cmdBuf );/* 再実行用の置換 */ if( ercd < 0 ){ tm_putstring( "Replace error\n" ); continue; } tk_rel_mpl( mplid, hist[IDX(idx)] ); hist[IDX(idx)] = cmdBuf; /* コマンドの入替 */ executeCommand( cmdBuf ); /* コマンドの実行 */ idx++; /* 次の履歴登録位置 */ }/*while*/ /*--------------*/ /* 終了処理 */ /*--------------*/ for( i = 0; i < HIST_NO; i++ ){ tk_rel_mpl( mplid, hist[i] ); /* メモリブロックを解放 */ } tk_del_mpl( mplid ); /* メモリプールを削除 */ return 1; }