#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全体のサイズ */ /* ^^ → わざと少なくしてある */ /* 固定長メモリプール */ #define MPFSZ sizeof(T_MSGPKT) /* ブロックサイズ */ #define MPFNO (4) /* ブロック数 */ LOCAL ID mplid; /* 可変長メモリプールID */ LOCAL ID mpfid; /* 固定長メモリプールID */ LOCAL ID mbfid; /* メッセージバッファID */ LOCAL ID mbxid; /* メールボックスID */ typedef struct { /* request−display間の */ T_MSG msgque; /* 変換結果転送パケット */ B bstr[32+1]; /* ← 変換結果の本体 */ } T_MSGPKT; 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 ) /* 変換要求 */ { UW v = 0; ER ercd; cmd += sizeof(CMD_REQUEST) - 1; /* "request" をスキップ */ if( *cmd != ' ' ){ return E_PAR; } cmd++; /* " " をスキップ */ while( isdigit(*cmd) ){ /* 文字列 → UW型の数値 */ v = (v*10) + (*cmd++ - '0'); } ercd = tk_snd_mbf( mbfid, &v, sizeof(UW), TMO_POL ); return ercd; /* タスクXに処理を依頼 */ } void commandDisplay(void) /* 変換結果の表示 */ { T_MSGPKT *pkt; ER ercd; do{ /* 変換結果を全て受信 */ ercd = tk_rcv_mbx( mbxid, &pkt, TMO_POL ); if( ercd == E_OK ){ tm_putstring( pkt->bstr ); /* 結果を表示 */ tm_putstring( "\n" ); tk_rel_mpf( mpfid, pkt ); /* メモリブロックを解放 */ } }while( ercd == E_OK ); } 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 taskX( INT stacd, void *exinf ) /* タスクX : 変換関数 */ { T_MSGPKT *pkt; /* 変換結果格納パケット */ UW v; /* 変換する値 */ UW uw; /* ビット処理用 */ B *bstr; while(1){ tk_rcv_mbf( mbfid, &v, TMO_FEVR ); /* v: 変換する値 */ tk_get_mpf( mpfid, &pkt, TMO_FEVR );/* 変換結果格納用 */ bstr = pkt->bstr; for( uw = 0x80000000UL; uw > 0; uw >>= 1 ){ *bstr++ = (v & uw)? '1':'0'; /* 2進数の文字列 */ } *bstr = '\0'; tk_snd_mbx( mbxid, (T_MSG*)pkt ); } tk_exd_tsk(); /* ここには来ない */ } void createTranslateTask(void) { CONST T_CMPF cmpf = { NULL, TA_TFIFO, MPFNO, MPFSZ }; CONST T_CMBF cmbf = { NULL, TA_TFIFO, 16, sizeof(UW) }; CONST T_CMBX cmbx = { NULL, TA_TFIFO|TA_MFIFO }; CONST T_CTSK ctsk = { NULL, TA_HLNG|TA_RNG0, taskX, 1, 4*1024 }; ID taskXid; ER ercd; /* オブジェクトの生成 */ mpfid = tk_cre_mpf( &cmpf ); /* 固定長メモリプール */ mbfid = tk_cre_mbf( &cmbf ); /* メッセージバッファ */ mbxid = tk_cre_mbx( &cmbx ); /* メールボックス */ taskXid = tk_cre_tsk( &ctsk ); /* タスクの生成 */ ercd = tk_sta_tsk( taskXid, 0 ); /* タスクの起動 */ } 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; }