OSDN Git Service

直前のコミット漏れ
[mochi/master.git] / src / kernel / Debug / DebugLog.c
1 /******************************************************************************/
2 /* src/kernel/Debug/DebugLog.c                                                */
3 /*                                                                 2018/10/20 */
4 /* Copyright (C) 2017-2018 Mochi.                                             */
5 /******************************************************************************/
6 /******************************************************************************/
7 /* インクルード                                                               */
8 /******************************************************************************/
9 /* 共通ヘッダ */
10 #include <stdarg.h>
11 #include <stdint.h>
12 #include <string.h>
13
14 /* 外部モジュールヘッダ */
15 #include <Cmn.h>
16 #include <hardware/Vga/Vga.h>
17
18 /* 内部モジュールヘッダ */
19 #include "DebugLog.h"
20
21
22 /******************************************************************************/
23 /* 定義                                                                       */
24 /******************************************************************************/
25 /* 長さ定義 */
26 #define LOG_LENGTH_ID      (  8 )   /** 識別子文字数 */
27 #define LOG_LENGTH_LINENUM (  4 )   /** 行番号文字数 */
28
29 /** カーソル位置アドレス計算 */
30 #define LOG_CURSOR_ADDR( __ROW, __COLUMN )                  \
31     ( ( uint8_t * ) ( VGA_M3_VRAM_ADDR +                    \
32                       ( __ROW ) * VGA_M3_COLUMN * 2 +       \
33                       ( __COLUMN ) * 2                ) )
34
35 /** 文字色取得マクロ */
36 #define LOG_ATTR_FG( __BASE )           ( __BASE & 0x0F )
37
38 /** 背景色取得マクロ */
39 #define LOG_ATTR_BG( __BASE )           ( __BASE & 0xF0 )
40
41 /** 文字色変更マクロ */
42 #define LOG_ATTR_FG_CHG( __BASE, __FG ) ( LOG_ATTR_BG( __BASE ) | ( __FG ) )
43
44 /** 背景色変更マクロ */
45 #define LOG_ATTR_BG_CHG( __BASE, __BG ) ( LOG_ATTR_FG( __BASE ) | ( __BG ) )
46
47 /* 変換指定子フラグ */
48 #define LOG_FLAG_LEFT      ( 0x01 ) /* 左寄せ       */
49 #define LOG_FLAG_SIGN      ( 0x02 ) /* 符号表示     */
50 #define LOG_FLAG_SPACE     ( 0x04 ) /* 正数符号空白 */
51 #define LOG_FLAG_ALTERNATE ( 0x08 ) /* 代替形式     */
52 #define LOG_FLAG_ZERO      ( 0x10 ) /* 0埋め        */
53 #define LOG_FLAG_UPPERCASE ( 0x20 ) /* 大文字       */
54 #define LOG_FLAG_UNSIGNED  ( 0x40 ) /* 符号無       */
55
56 /* デバッグトレースログ出力マクロ */
57 #ifdef DEBUG_LOG_ENABLE
58 #define DEBUG_LOG( ... )                \
59     DebugLogOutput( CMN_MODULE_DBG_LOG, \
60                     __LINE__,           \
61                     __VA_ARGS__ )
62 #else
63 #define DEBUG_LOG( ... )
64 #endif
65
66 /** 識別子変換テーブル型 */
67 typedef struct {
68     uint32_t moduleId;                  /**< モジュール・サブモジュール識別子 */
69     char     str[ LOG_LENGTH_ID + 1 ];  /**< 識別文字列                       */
70 } logIdTrans_t;
71
72 /** ログ管理テーブル型 */
73 typedef struct {
74     uint32_t row;       /**< カーソル行 */
75     uint32_t column;    /**< カーソル列 */
76     uint8_t  attr;      /**< 文字属性   */
77 } logTbl_t;
78
79
80 /******************************************************************************/
81 /* ローカル変数定義                                                           */
82 /******************************************************************************/
83 #ifdef DEBUG_LOG_ENABLE
84 /** 識別子変換テーブル */
85 const static logIdTrans_t gIdTransTbl[ CMN_MODULE_NUM + 1 ] = {
86     { CMN_MODULE_INIT_INIT,     "INI-INIT" },   /* 初期化制御(初期化)       */
87     { CMN_MODULE_DEBUG_INIT,    "DBG-INIT" },   /* デバッグ制御(初期化)     */
88     { CMN_MODULE_DEBUG_LOG,     "DBG-LOG " },   /* デバッグ制御(ログ)       */
89     { CMN_MODULE_MEMMNG_INIT,   "MEM-INIT" },   /* メモリ管理(初期化)       */
90     { CMN_MODULE_MEMMNG_GDT,    "MEM-GDT " },   /* メモリ管理(GDT)          */
91     { CMN_MODULE_MEMMNG_AREA,   "MEM-AREA" },   /* メモリ管理(領域)         */
92     { CMN_MODULE_MEMMNG_PAGE,   "MEM-PAGE" },   /* メモリ管理(ページ)       */
93     { CMN_MODULE_MEMMNG_CTRL,   "MEM-CTRL" },   /* メモリ管理(制御)         */
94     { CMN_MODULE_TASKMNG_INIT,  "TSK-INIT" },   /* タスク管理(初期化)       */
95     { CMN_MODULE_TASKMNG_TSS,   "TSK-TSS " },   /* タスク管理(TSS)          */
96     { CMN_MODULE_TASKMNG_SCHED, "TSK-SCHD" },   /* タスク管理(スケジューラ) */
97     { CMN_MODULE_TASKMNG_TASK,  "TSK-TASK" },   /* タスク管理(タスク)       */
98     { CMN_MODULE_TASKMNG_ELF,   "TSK-ELF " },   /* タスク管理(ELFローダ)    */
99     { CMN_MODULE_TASKMNG_PROC,  "TSK-PROC" },   /* タスク管理(プロセス)     */
100     { CMN_MODULE_INTMNG_INIT,   "INT-INIT" },   /* 割込管理(初期化)         */
101     { CMN_MODULE_INTMNG_PIC,    "INT-PIC " },   /* 割込管理(PIC)            */
102     { CMN_MODULE_INTMNG_IDT,    "INT-IDT " },   /* 割込管理(IDT)            */
103     { CMN_MODULE_INTMNG_HDL,    "INT-HDL " },   /* 割込管理(ハンドラ)       */
104     { CMN_MODULE_INTMNG_CTRL,   "INT-CTRL" },   /* 割込管理(ハードウェア)   */
105     { CMN_MODULE_TIMERMNG_INIT, "TIM-INIT" },   /* タイマ管理(初期化)       */
106     { CMN_MODULE_TIMERMNG_CTRL, "TIM-CTRL" },   /* タイマ管理(制御)         */
107     { CMN_MODULE_TIMERMNG_PIT,  "TIM-PIT " },   /* タイマ管理(PIT)          */
108     { CMN_MODULE_ITCCTRL_INIT,  "ITC-INIT" },   /* タスク間通信制御(初期化) */
109     { CMN_MODULE_ITCCTRL_MSG,   "ITC-MSG " },   /* タスク間通信制御(メッセージ) */
110     { CMN_MODULE_IOCTRL_INIT,   "IOC-INIT" },   /* 入出力制御(初期化)       */
111     { CMN_MODULE_IOCTRL_PORT,   "IOC-PORT" },   /* 入出力制御(I/Oポート)    */
112     { 0,                        "UNKNOWN " }  };/* 終端                     */
113
114 /** 数字変換表 */
115 static char gNumTransTbl[ 2 ][ 17 ] = { "0123456789abcdef",
116                                         "0123456789ABCDEF"  };
117
118 #endif
119
120 /** ログ管理テーブル */
121 static logTbl_t gLogTbl;
122
123
124 /******************************************************************************/
125 /* ローカル関数プロトタイプ宣言                                               */
126 /******************************************************************************/
127 #ifdef DEBUG_LOG_ENABLE
128
129 /* 数値取得 */
130 static CmnRet_t LogGetNum( char     *pStr,
131                            uint32_t *pValue,
132                            uint32_t *pLength );
133
134 /* 書式付き文字列出力(可変長引数型) */
135 static void LogOutput( char *pFormat,
136                        ...            );
137
138 /* 書式付き文字列出力(可変長引数リスト型) */
139 static void LogOutputByVaList( char     *pFormat,
140                                va_list  vaList    );
141
142 /* 一文字出力 */
143 static void LogOutputChar( char c );
144
145 /* 整数出力 */
146 static void LogOutputNumber( uint32_t value,
147                              uint32_t base,
148                              uint32_t flags,
149                              int32_t  width  );
150
151 /* 文字列出力 */
152 static void LogOutputString( char *pStr );
153
154 /* ESCコード処理 */
155 static uint32_t LogProcEscape( char *pStr );
156
157 /* 文字属性エスケープシーケンス処理 */
158 static void LogProcEscapeAttr( uint32_t funcNo );
159
160 /* 変換指定子処理 */
161 static uint32_t LogProcFormat( char    *pFormat,
162                                va_list *pVaList  );
163
164 #endif
165
166
167 /******************************************************************************/
168 /* グローバル関数定義                                                         */
169 /******************************************************************************/
170 /******************************************************************************/
171 /**
172  * @brief       ログ管理初期化
173  * @details     ログ管理サブモジュールの初期化を行う。
174  */
175 /******************************************************************************/
176 void DebugLogInit( void )
177 {
178     /* ログ管理テーブル初期化 */
179     memset( &gLogTbl, 0, sizeof ( logTbl_t ) );
180     
181     /* 文字属性設定 */
182     gLogTbl.attr = VGA_M3_ATTR_FG_WHITE  |  /* 白色文字属性 */
183                    VGA_M3_ATTR_FG_BRIGHT |  /* 明色文字属性 */
184                    VGA_M3_ATTR_BG_BLACK;    /* 黒色背景属性 */
185     
186     return;
187 }
188
189
190 /******************************************************************************/
191 /**
192  * @brief       トレースログ出力
193  * @details     デバッグトレースログオプションが有効の時、画面にトレースログ出
194  *              力を行う。
195  * 
196  * @param[in]   moduleId モジュール・サブモジュール識別子
197  *                  - CMN_MODULE_INIT_INIT     初期化制御(初期化)
198  *                  - CMN_MODULE_DEBUG_INIT    デバッグ制御(初期化)
199  *                  - CMN_MODULE_DEBUG_LOG     デバッグ制御(ログ管理)
200  *                  - CMN_MODULE_MEMMNG_INIT   メモリ管理(初期化)
201  *                  - CMN_MODULE_MEMMNG_GDT    メモリ管理(GDT管理)
202  *                  - CMN_MODULE_MEMMNG_AREA   メモリ管理(メモリ領域管理)
203  *                  - CMN_MODULE_MEMMNG_PAGE   メモリ管理(ページ管理)
204  *                  - CMN_MODULE_MEMMNG_CTRL   メモリ管理(メモリ制御)
205  *                  - CMN_MODULE_TASKMNG_INIT  タスク管理(初期化)
206  *                  - CMN_MODULE_TASKMNG_TSS   タスク管理(TSS管理)
207  *                  - CMN_MODULE_TASKMNG_SCHED タスク管理(スケジューラ)
208  *                  - CMN_MODULE_TASKMNG_TASK  タスク管理(タスク管理)
209  *                  - CMN_MODULE_TASKMNG_ELF   タスク管理(ELFローダ)
210  *                  - CMN_MODULE_TASKMNG_PROC  タスク管理(プロセス管理)
211  *                  - CMN_MODULE_INTMNG_INIT   割込管理(初期化)
212  *                  - CMN_MODULE_INTMNG_PIC    割込管理(PIC管理)
213  *                  - CMN_MODULE_INTMNG_IDT    割込管理(IDT管理)
214  *                  - CMN_MODULE_INTMNG_HDL    割込管理(ハンドラ管理)
215  *                  - CMN_MODULE_TIMERMNG_INIT タイマ管理(初期化)
216  *                  - CMN_MODULE_TIMERMNG_PIT  タイマ管理(PIT管理) *                  - CMN_MODULE_ITCCTRL_INIT  タスク間通信制御(初期化)
217  *                  - CMN_MODULE_ITCCTRL_MSG   タスク間通信制御(メッセージ制御)
218  * @param[in]   lineNum  行番号
219  * @param[in]   *pFormat トレースログ
220  * 
221  * @note        デバッグトレースログオプションの有効化は、コンパイルオプション
222  *              にて「DEBUG_LOG_ENABLE」マクロを定義する事で行う。
223  */
224 /******************************************************************************/
225 void DebugLogOutput( uint32_t moduleId,
226                      uint32_t lineNum,
227                      char     *pFormat,
228                      ...                )
229 {
230 #ifdef DEBUG_LOG_ENABLE
231     va_list  vaList;    /* 可変長引数リスト         */
232     uint32_t row;       /* カーソル行               */
233     uint32_t column;    /* カーソル列               */
234     uint32_t moduleIdx; /* 変換テーブルインデックス */
235     
236     /* 可変長引数リスト設定 */
237     va_start( vaList, pFormat );
238     
239     /* カーソル列初期化 */
240     gLogTbl.column = 0;
241     
242     /* カーソル行範囲判定 */
243     if ( gLogTbl.row >= VGA_M3_ROW ) {
244         /* 上限越え */
245         
246         /* カーソル行設定 */
247         gLogTbl.row = VGA_M3_ROW - 1;
248         
249         /* 画面スクロール */
250         for ( row = 0; row < ( VGA_M3_ROW - 1 ); row++ ) {
251             /* 一行コピー */
252             memcpy( LOG_CURSOR_ADDR( row, 0 ),
253                     LOG_CURSOR_ADDR( row + 1, 0 ),
254                     VGA_M3_COLUMN * 2 );
255         }
256         
257         /* 最下行初期化 */
258         for ( column = 0; column < VGA_M3_COLUMN; column++ ) {
259             /* 一文字設定 */
260             LOG_CURSOR_ADDR( row, column )[ 0 ] = ' ';
261             LOG_CURSOR_ADDR( row, column )[ 1 ] =
262                 VGA_M3_ATTR_FG_WHITE  |     /* 白色文字属性 */
263                 VGA_M3_ATTR_FG_BRIGHT |     /* 明色文字属性 */
264                 VGA_M3_ATTR_BG_BLACK;       /* 黒色背景属性 */
265         }
266     }
267     
268     /* モジュール・サブモジュール識別子変換 */
269     for ( moduleIdx = 0; moduleIdx < CMN_MODULE_NUM; moduleIdx++ ) {
270         /* 識別子変換テーブル一致判定 */
271         if ( gIdTransTbl[ moduleIdx ].moduleId == moduleId ) {
272             /* 一致 */
273             break;
274         }
275     }
276     
277     /* モジュール・サブモジュール識別子、行番号出力 */
278     LogOutput( "\033[32m%s:%04u \033[0m",
279                gIdTransTbl[ moduleIdx ].str,
280                lineNum % 10000               );
281     
282     /* トレースログ出力 */
283     LogOutputByVaList( pFormat, vaList );
284     
285     /* カーソル行更新 */
286     gLogTbl.row++;
287     
288     /* 可変長引数リスト解放 */
289     va_end( vaList );
290     
291 #endif
292     return;
293 }
294
295
296 /******************************************************************************/
297 /* ローカル関数定義                                                           */
298 /******************************************************************************/
299 #ifdef DEBUG_LOG_ENABLE
300 /******************************************************************************/
301 /**
302  * @brief       数値取得
303  * @details     数字文字列から数値を取得する。
304  * 
305  * @param[in]   *pStr    文字列
306  * @param[out]  *pVaule  数値
307  * @param[out]  *pLength 数字文字列長
308  * 
309  * @retval      CMN_SUCCESS 正常終了
310  * @retval      CMN_FAILURE 異常終了(数字文字列無し)
311  * 
312  * @note        「DEBUG_LOG_ENABLE」マクロが定義されている場合に有効となる。
313  */
314 /******************************************************************************/
315 static CmnRet_t LogGetNum( char     *pStr,
316                            uint32_t *pValue,
317                            uint32_t *pLength )
318 {
319     /* 初期化 */
320     *pValue  = 0;
321     *pLength = 0;
322     
323     /* 一文字毎に繰り返す */
324     while ( pStr[ *pLength ] != '\0' ) {
325         /* 数値判別 */
326         if ( ( '0' <= pStr[ *pLength ] ) && ( pStr[ *pLength ] <= '9' ) ) {
327             /* 数値 */
328             *pValue = *pValue * 10 + pStr[ *pLength ] - '0';
329             
330         } else {
331             /* 数値以外 */
332             
333             break;
334         }
335         
336         /* 文字列長更新 */
337         ( *pLength )++;
338     }
339     
340     /* 文字列長判定 */
341     if ( *pLength == 0 ) {
342         /* 数値無 */
343         
344         return CMN_FAILURE;
345     }
346     
347     return CMN_SUCCESS;
348 }
349 #endif
350
351
352 #ifdef DEBUG_LOG_ENABLE
353 /******************************************************************************/
354 /**
355  * @brief       書式付き文字列出力(可変長引数型)
356  * @details     画面に可変長引数型書式付き文字列を出力する。
357  * 
358  * @param[in]   *pFormat 書式付き文字列
359  * @param[in]   ...      可変長引数
360  * 
361  * @note        「DEBUG_LOG_ENABLE」マクロが定義されている場合に有効となる。
362  */
363 /******************************************************************************/
364 static void LogOutput( char *pFormat,
365                        ...            )
366 {
367     va_list vaList; /* 可変長引数リスト */
368     
369     /* 可変長引数リスト設定 */
370     va_start( vaList, pFormat );
371     
372     /* 書式付き文字列出力 */
373     LogOutputByVaList( pFormat, vaList );
374     
375     /* 可変長引数リスト解放 */
376     va_end( vaList );
377     
378     return;
379 }
380 #endif
381
382
383 #ifdef DEBUG_LOG_ENABLE
384 /******************************************************************************/
385 /**
386  * @brief       書式付き文字列出力(可変長引数リスト型)
387  * @details     画面に可変長引数リスト型書式付き文字列を出力する。
388  * 
389  * @param[in]   *pFormat 書式付き文字列
390  * @param[in]   vaList   可変長引数リスト
391  * 
392  * @note        「DEBUG_LOG_ENABLE」マクロが定義されている場合に有効となる。
393  */
394 /******************************************************************************/
395 static void LogOutputByVaList( char     *pFormat,
396                                va_list  vaList    )
397 {
398     uint32_t idx;   /* インデックス */
399     
400     /* 初期化 */
401     idx = 0;
402     
403     /* 一文字毎に繰り返し */
404     while ( pFormat[ idx ] != '\0' ) {
405         /* 文字判定 */
406         switch ( pFormat[ idx ] ) {
407             case '%':
408                 /* 変換指定子 */
409                 
410                 /* インデックス更新 */
411                 idx++;
412                 
413                 /* 変換指定処理 */
414                 idx += LogProcFormat( &pFormat[ idx ], &vaList );
415                 
416                 break;
417                 
418             case '\033':
419                 /* ESCコード */
420                 
421                 /* インデックス更新 */
422                 idx++;
423                 
424                 /* ESCコード処理 */
425                 idx += LogProcEscape( &pFormat[ idx ] );
426                 
427                 break;
428                 
429             default:
430                 /* その他 */
431                 
432                 /* 一文字出力 */
433                 LogOutputChar( pFormat[ idx ] );
434                 
435                 /* インデックス更新 */
436                 idx++;
437                 
438                 break;
439         }
440     }
441     
442     return;
443 }
444 #endif
445
446
447 #ifdef DEBUG_LOG_ENABLE
448 /******************************************************************************/
449 /**
450  * @brief       一文字出力
451  * @details     画面に一文字出力する。
452  * 
453  * @param[in]   c 文字コード
454  * 
455  * @note        「DEBUG_LOG_ENABLE」マクロが定義されている場合に有効となる。
456  */
457 /******************************************************************************/
458 static void LogOutputChar( char c )
459 {
460     uint8_t *pCursor;   /* カーソル */
461     
462     /* カーソル列チェック */
463     if ( gLogTbl.column >= VGA_M3_COLUMN ) {
464         /* 行数超 */
465         
466         return;
467     }
468     
469     /* カーソル設定 */
470     pCursor = LOG_CURSOR_ADDR( gLogTbl.row, gLogTbl.column );
471     
472     /* 画面出力 */
473     pCursor[ 0 ] = ( uint8_t ) c;   /* 文字コード */
474     pCursor[ 1 ] = gLogTbl.attr;    /* 文字属性   */
475     
476     /* カーソル更新 */
477     gLogTbl.column++;
478     
479     return;
480 }
481 #endif
482
483
484 #ifdef DEBUG_LOG_ENABLE
485 /******************************************************************************/
486 /**
487  * @brief       整数出力
488  * @details     整数を画面に出力する。
489  * 
490  * @param[in]   value 数値
491  * @param[in]   base  進数
492  *                  - 8  8進数
493  *                  - 10 10進数
494  *                  - 16 16進数
495  * @param[in]   flags フラグ
496  *                  - LOG_FLAG_LEFT      左寄せ
497  *                  - LOG_FLAG_SIGN      符号表示
498  *                  - LOG_FLAG_SPACE     正数符号空白
499  *                  - LOG_FLAG_ALTERNATE 代替形式
500  *                  - LOG_FLAG_ZERO      0埋め
501  *                  - LOG_FLAG_UNSIGNED  符号無
502  * @param[in]   width 最小フィールド幅
503  *                  - 0~80
504  * 
505  * @note        「DEBUG_LOG_ENABLE」マクロが定義されている場合に有効となる。
506  */
507 /******************************************************************************/
508 static void LogOutputNumber( uint32_t value,
509                              uint32_t base,
510                              uint32_t flags,
511                              int32_t  width  )
512 {
513     char     buffer[ VGA_M3_COLUMN ];   /* 出力バッファ     */
514     char     *pTrans;                   /* 数字変換表       */
515     int32_t  length;                    /* バッファ文字列長 */
516     uint32_t tmp;                       /* 一時変数         */
517     uint32_t idx;                       /* インデックス     */
518     
519     /* 初期化 */
520     memset( buffer, '0', sizeof ( buffer ) );
521     length = 0;
522     tmp    = value;
523     
524     /* 最小フィールド幅範囲チェック */
525     if ( ( width < 0 ) && ( VGA_M3_COLUMN <= width ) ) {
526         /* 0未満、LOG_LENGTH_COLUMN超過 */
527         
528         /* 最小フィールド幅初期化 */
529         width = 0;
530     }
531     
532     /* 左寄せフラグ判定 */
533     if ( ( flags & LOG_FLAG_LEFT ) != 0 ) {
534         /* 左寄せフラグ有 */
535         
536         /* 0フラグ無効化 */
537         flags = flags & ~LOG_FLAG_ZERO;
538     }
539     
540     /* 符号無フラグ判定 */
541     if ( ( flags & LOG_FLAG_UNSIGNED ) == 0 ) {
542         /* 符号無フラグ無 */
543         
544         /* 負数判定 */
545         if ( ( ( int32_t ) tmp ) < 0 ) {
546             /* 負数 */
547             
548             /* 正数化 */
549             tmp = ( uint32_t ) ( ( ( int32_t ) tmp ) * -1 );
550         }
551         
552     } else {
553         /* 符号無フラグ有 */
554         
555         /* フラグ無効化 */
556         flags &= ~LOG_FLAG_SIGN;    /* 符号表示     */
557         flags &= ~LOG_FLAG_SPACE;   /* 正数符号空白 */
558     }
559     
560     /* 大文字フラグ判定 */
561     if ( ( flags & LOG_FLAG_UPPERCASE ) == 0 ) {
562         /* 大文字フラグ無 */
563         
564         /* 数字変換表設定 */
565         pTrans = gNumTransTbl[ 0 ];
566         
567     } else {
568         /* 大文字フラグ有 */
569         
570         /* 数字変換表設定 */
571         pTrans = gNumTransTbl[ 1 ];
572     }
573     
574     /* 代替形式フラグ判定 */
575     if ( ( flags & LOG_FLAG_ALTERNATE ) != 0 ) {
576         /* 代替表示フラグ有 */
577         
578         /* 進数判定 */
579         if ( base == 8 ) {
580             /* 8進数 */
581             
582             /* 最小フィールド幅から代替形式出力分減算 */
583             width -= 1;
584             
585         } else if ( base == 16 ) {
586             /* 16進数 */
587             
588             /* 最小フィールド幅から代替形式出力分減算 */
589             width -= 2;
590         }
591     }
592     
593     /* 符号表示フラグ、正数符号空白フラグ判定 */
594     if ( ( ( flags & LOG_FLAG_SIGN  ) != 0 ) ||
595          ( ( flags & LOG_FLAG_SPACE ) != 0 )    ) {
596         /* 符号表示フラグ有、または、正数符号空白フラグ有 */
597         
598         /* 最小フィールド幅から符号出力分減算 */
599         width -= 1;
600     }
601     
602     /* 一桁毎に繰り返し */
603     do {
604         /* 一桁文字列変換 */
605         buffer[ length++ ] = pTrans[ tmp % base ];
606         
607         /* 値更新 */
608         tmp /= base;
609         
610     } while ( tmp != 0 );
611     
612     /* 0埋めフラグ、最小フィールド幅判定 */
613     if ( ( ( flags & LOG_FLAG_ZERO ) != 0      ) &&
614          ( width                     >  length )    ) {
615         /* 0埋めフラグ有、かつ、最小フィールド幅未満 */
616         
617         /* 最小フィールド幅合わせ */
618         length = width;
619     }
620     
621     /* 代替形式フラグ判定 */
622     if ( ( flags & LOG_FLAG_ALTERNATE ) != 0 ) {
623         /* 代替表示フラグ有 */
624         
625         /* 進数判定 */
626         if ( base == 8 ) {
627             /* 8進数 */
628             
629             /* 0をバッファ出力 */
630             buffer[ length++ ] = '0';
631             
632         } else if ( base == 16 ) {
633             /* 16進数 */
634             
635             /* 0xをバッファ出力 */
636             buffer[ length++ ] = 'x';
637             buffer[ length++ ] = '0';
638         }
639     }
640     
641     /* 符号表示フラグ・正数判定 */
642     if ( ( ( flags & LOG_FLAG_SIGN ) != 0 ) &&
643          ( ( int32_t ) value         >= 0 )    ) {
644         /* 符号表示フラグ有、かつ、正数 */
645         buffer[ length++ ] = '+';
646     }
647     
648     /* 正数符号空白フラグ・正数判定 */
649     if ( ( ( flags & LOG_FLAG_SPACE ) != 0 ) &&
650          ( ( int32_t ) value          >= 0 )    ) {
651         /* 正数符号空白フラグ有、かつ、正数 */
652         buffer[ length++ ] = ' ';
653     }
654     
655     /* 符号表示フラグ・正数符号空白フラグ・負数判定 */
656     if ( ( ( ( flags & LOG_FLAG_SIGN  ) != 0 ) ||
657            ( ( flags & LOG_FLAG_SPACE ) != 0 )    ) &&
658          ( ( int32_t ) value < 0                  )    ) {
659         /* 符号表示または正数符号空白フラグ有、かつ、負数 */
660         buffer[ length++ ] = '-';
661     }
662     
663     /* 左寄せフラグ、最小フィールド幅判定 */
664     if ( ( ( flags & LOG_FLAG_LEFT ) == 0      ) &&
665          ( width                     >  length )    ) {
666         /* 左寄せフラグ無、かつ、最小フィールド幅未満 */
667         
668         /* 空白挿入 */
669         for ( idx = 0; idx < ( uint32_t ) ( width - length ); idx++ ) {
670             /* 一文字出力 */
671             LogOutputChar( ' ' );
672         }
673     }
674     
675     /* バッファ出力 */
676     for ( idx = 0; idx < ( uint32_t ) length; idx++ ) {
677         /* 一文字出力 */
678         LogOutputChar( buffer[ ( uint32_t ) length - idx - 1 ] );
679     }
680     
681     /* 左寄せフラグ判定 */
682     if ( ( ( flags & LOG_FLAG_LEFT ) != 0      ) &&
683          ( width                     >  length )    ) {
684         /* 左寄せフラグ有、かつ、最小フィールド幅未満 */
685         
686         /* 空白挿入 */
687         for ( idx = 0; idx < ( uint32_t ) ( width - length ); idx++ ) {
688             /* 一文字出力 */
689             LogOutputChar( ' ' );
690         }
691     }
692     
693     return;
694 }
695 #endif
696
697
698 #ifdef DEBUG_LOG_ENABLE
699 /******************************************************************************/
700 /**
701  * @brief       文字列出力
702  * @details     文字列を画面に出力する。
703  * 
704  * @param[in]   pStr 文字列
705  * 
706  * @note        「DEBUG_LOG_ENABLE」マクロが定義されている場合に有効となる。
707  */
708 /******************************************************************************/
709 static void LogOutputString( char *pStr )
710 {
711     uint32_t idx;   /* インデックス */
712     
713     /* 初期化 */
714     idx = 0;
715     
716     /* 一文字毎に繰り返し */
717     while ( pStr[ idx ] != '\0' ) {
718         /* 文字判定 */
719         switch ( pStr[ idx ] ) {
720             case '\033':
721                 /* ESCコード */
722                 
723                 /* インデックス更新 */
724                 idx++;
725                 
726                 /* ESCコード処理 */
727                 idx += LogProcEscape( &pStr[ idx ] );
728                 
729                 break;
730                 
731             default:
732                 /* 他 */
733                 
734                 /* 一文字出力 */
735                 LogOutputChar( pStr[ idx ] );
736                 
737                 /* インデックス更新 */
738                 idx++;
739                 
740                 break;
741         }
742     }
743     
744     return;
745 }
746 #endif
747
748
749 #ifdef DEBUG_LOG_ENABLE
750 /******************************************************************************/
751 /**
752  * @brief       ESCコード処理
753  * @details     ESCコードを処理する。
754  * 
755  * @param[in]   *pStr エスケープシーケンス
756  * 
757  * @return      エスケープシーケンス文字数
758  * 
759  * @note        - 「DEBUG_LOG_ENABLE」マクロが定義されている場合に有効となる。
760  *              - 画面制御エスケープシーケンスには対応しない。
761  */
762 /******************************************************************************/
763 static uint32_t LogProcEscape( char *pStr )
764 {
765     CmnRet_t ret;       /* 関数戻り値   */
766     uint32_t idx;       /* インデックス */
767     uint32_t value;     /* 数値         */
768     uint32_t length;    /* 文字列長     */
769     
770     /* 初期化 */
771     idx    = 1;
772     value  = 0;
773     length = 0;
774     
775     /* エスケープシーケンスチェック */
776     if ( pStr[ 0 ] != '['  ) {
777         /* エスケープシーケンスでない */
778         
779         return 0;
780     }
781     
782     /* 数値取得 */
783     ret = LogGetNum( &pStr[ idx ], &value, &length );
784     
785     /* 取得結果判定 */
786     if ( ret == CMN_SUCCESS ) {
787         /* 成功 */
788         
789         /* インデックス更新 */
790         idx += length;
791     }
792     
793     /* エスケープシーケンス種別判定 */
794     switch ( pStr[ idx ] ) {
795         case 'm':
796             /* 文字属性 */
797             
798             /* 文字属性エスケープシーケンス処理 */
799             LogProcEscapeAttr( value );
800             
801             /* 文字列長設定 */
802             length = idx + 1;
803             
804             break;
805             
806         default:
807             /* 他 */
808             
809             /* 文字列長設定 */
810             length = idx;
811             
812             break;
813     }
814     
815     return length;
816 }
817 #endif
818
819
820 #ifdef DEBUG_LOG_ENABLE
821 /******************************************************************************/
822 /**
823  * @brief       文字属性エスケープシーケンス処理
824  * @details     文字属性のエスケープシーケンスを処理する。
825  * 
826  * @param[in]   funcNo 機能番号
827  *                  - 0  属性初期化
828  *                  - 1  文字強調
829  *                  - 4  下線
830  *                  - 7  反転
831  *                  - 30 黒色文字
832  *                  - 31 赤色文字
833  *                  - 32 緑色文字
834  *                  - 33 黄色文字
835  *                  - 34 青色文字
836  *                  - 35 紫色文字
837  *                  - 36 水色文字
838  *                  - 37 白色文字
839  *                  - 39 標準色文字
840  *                  - 40 黒色背景
841  *                  - 41 赤色背景
842  *                  - 42 緑色背景
843  *                  - 43 黄色背景
844  *                  - 44 青色背景
845  *                  - 45 紫色背景
846  *                  - 46 水色背景
847  *                  - 47 白色背景
848  *                  - 49 標準色背景
849  * 
850  * @note        - 「DEBUG_LOG_ENABLE」マクロが定義されている場合に有効となる。
851  *              - 文字強調、下線は対応しない。
852  */
853 /******************************************************************************/
854 static void LogProcEscapeAttr( uint32_t funcNo )
855 {
856     uint8_t attr;   /* 文字属性 */
857     
858     /* 機能番号判定 */
859     switch ( funcNo ) {
860         case 0:
861             /* 属性初期化 */
862             
863             gLogTbl.attr = VGA_M3_ATTR_FG_WHITE  |  /* 白色文字属性 */
864                            VGA_M3_ATTR_FG_BRIGHT |  /* 明色文字属性 */
865                            VGA_M3_ATTR_BG_BLACK;    /* 黒色背景属性 */
866             
867             break;
868             
869         case 7:
870             /* 反転 */
871             
872             /* 反転 */
873             attr  = ( LOG_ATTR_BG( gLogTbl.attr ) >> 4 ) |
874                     VGA_M3_ATTR_FG_BRIGHT;
875             attr &= ( LOG_ATTR_FG( gLogTbl.attr ) << 4 ) & ~VGA_M3_ATTR_BLINK;
876             
877             /* 設定 */
878             gLogTbl.attr = attr;
879             
880             break;
881             
882         case 30:
883             /* 黒色文字 */
884             gLogTbl.attr =
885                 LOG_ATTR_FG_CHG( gLogTbl.attr,
886                                  VGA_M3_ATTR_FG_BLACK | VGA_M3_ATTR_FG_BRIGHT );
887             break;
888             
889         case 31:
890             /* 赤色文字 */
891             gLogTbl.attr =
892                 LOG_ATTR_FG_CHG( gLogTbl.attr,
893                                  VGA_M3_ATTR_FG_RED | VGA_M3_ATTR_FG_BRIGHT );
894             break;
895             
896         case 32:
897             /* 緑色文字 */
898             gLogTbl.attr =
899                 LOG_ATTR_FG_CHG( gLogTbl.attr,
900                                  VGA_M3_ATTR_FG_GREEN | VGA_M3_ATTR_FG_BRIGHT );
901             break;
902             
903         case 33:
904             /* 黄色文字 */
905             gLogTbl.attr =
906                 LOG_ATTR_FG_CHG( gLogTbl.attr,
907                                  VGA_M3_ATTR_FG_BROWN | VGA_M3_ATTR_FG_BRIGHT );
908             break;
909             
910         case 34:
911             /* 青色文字 */
912             gLogTbl.attr =
913                 LOG_ATTR_FG_CHG( gLogTbl.attr,
914                                  VGA_M3_ATTR_FG_BLUE | VGA_M3_ATTR_FG_BRIGHT );
915             break;
916             
917         case 35:
918             /* 紫色文字 */
919             gLogTbl.attr =
920                 LOG_ATTR_FG_CHG( gLogTbl.attr,
921                                  VGA_M3_ATTR_FG_PURPLE | 
922                                      VGA_M3_ATTR_FG_BRIGHT );
923             break;
924             
925         case 36:
926             /* 水色文字 */
927             gLogTbl.attr =
928                 LOG_ATTR_FG_CHG( gLogTbl.attr,
929                                  VGA_M3_ATTR_FG_CYAN | VGA_M3_ATTR_FG_BRIGHT );
930             break;
931             
932         case 37:
933             /* 白色文字 *//* FALL THROUGH */
934         case 39:
935             /* 標準色文字 */
936             gLogTbl.attr =
937                 LOG_ATTR_FG_CHG( gLogTbl.attr,
938                                  VGA_M3_ATTR_FG_WHITE | VGA_M3_ATTR_FG_BRIGHT );
939             break;
940             
941         case 40:
942             /* 黒色背景 *//* FALL THROUGH */
943         case 49:
944             /* 標準色背景 */
945             gLogTbl.attr = LOG_ATTR_BG_CHG( gLogTbl.attr,
946                                             VGA_M3_ATTR_BG_BLACK );
947             break;
948             
949         case 41:
950             /* 赤色背景 */
951             gLogTbl.attr = LOG_ATTR_BG_CHG( gLogTbl.attr, VGA_M3_ATTR_BG_RED );
952             break;
953             
954         case 42:
955             /* 緑色背景 */
956             gLogTbl.attr = LOG_ATTR_BG_CHG( gLogTbl.attr, VGA_M3_ATTR_BG_RED );
957             break;
958             
959         case 43:
960             /* 黄色背景 */
961             gLogTbl.attr = LOG_ATTR_BG_CHG( gLogTbl.attr,
962                                             VGA_M3_ATTR_BG_BROWN );
963             break;
964             
965         case 44:
966             /* 青色背景 */
967             gLogTbl.attr = LOG_ATTR_BG_CHG( gLogTbl.attr, VGA_M3_ATTR_BG_BLUE );
968             break;
969             
970         case 45:
971             /* 紫色背景 */
972             gLogTbl.attr = LOG_ATTR_BG_CHG( gLogTbl.attr,
973                                             VGA_M3_ATTR_BG_PURPLE );
974             break;
975             
976         case 46:
977             /* 水色背景 */
978             gLogTbl.attr = LOG_ATTR_BG_CHG( gLogTbl.attr, VGA_M3_ATTR_BG_CYAN );
979             break;
980             
981         case 47:
982             /* 白色背景 */
983             gLogTbl.attr = LOG_ATTR_BG_CHG( gLogTbl.attr,
984                                             VGA_M3_ATTR_BG_WHITE );
985             break;
986             
987         default:
988             /* 他 */
989             break;
990     }
991     
992     return;
993 }
994 #endif
995
996
997 #ifdef DEBUG_LOG_ENABLE
998 /******************************************************************************/
999 /**
1000  * @brief       変換指定子処理
1001  * @details     変換指定子を処理する。
1002  * 
1003  * @param[in]   *pFormat 変換指定子
1004  * @param[in]   vaList   可変長引数リスト
1005  * 
1006  * @note        - 「DEBUG_LOG_ENABLE」マクロが定義されている場合に有効となる。
1007  *              - 精度、長さ修飾子は未対応。
1008  */
1009 /******************************************************************************/
1010 static uint32_t LogProcFormat( char    *pFormat,
1011                                va_list *pVaList  )
1012 {
1013     uint32_t idx;       /* インデックス     */
1014     uint32_t width;     /* 最小フィールド幅 */
1015     uint32_t flags;     /* フラグ           */
1016     uint32_t length;    /* 文字列長         */
1017     CmnRet_t ret;       /* 関数戻り値       */
1018     
1019     /* 初期化 */
1020     idx    = 0;
1021     flags  = 0;
1022     width  = 0;
1023     length = 0;
1024     
1025     /* フラグ判定 */
1026     while ( 1 ) {
1027         switch ( pFormat[ idx ] ) {
1028             case '-':
1029                 /* 左寄せ */
1030                 idx++;                      /* インデックス更新 */
1031                 flags |= LOG_FLAG_LEFT;     /* フラグ設定       */
1032                 continue;
1033                 
1034             case '+':
1035                 /* 符号表示 */
1036                 idx++;                      /* インデックス更新 */
1037                 flags |= LOG_FLAG_SIGN;     /* フラグ設定       */
1038                 continue;
1039                 
1040             case ' ':
1041                 /* 正数符号空白 */
1042                 idx++;                      /* インデックス更新 */
1043                 flags |= LOG_FLAG_SPACE;    /* フラグ設定       */
1044                 continue;
1045                 
1046             case '#':
1047                 /* 代替形式 */
1048                 idx++;                      /* インデックス更新 */
1049                 flags |= LOG_FLAG_ALTERNATE;/* フラグ設定       */
1050                 continue;
1051                 
1052             case '0':
1053                 /* 0埋め */
1054                 idx++;                      /* インデックス更新 */
1055                 flags |= LOG_FLAG_ZERO;     /* フラグ設定       */
1056                 continue;
1057                 
1058             case '\0':
1059                 /* 終端 */
1060                 return 0;
1061                 
1062             default:
1063                 /* 他 */
1064                 break;
1065         }
1066         break;
1067     }
1068     
1069     /* 最小フィールド幅取得 */
1070     ret = LogGetNum( &pFormat[ idx ], &width, &length );
1071     
1072     /* 取得結果判定 */
1073     if ( ret == CMN_SUCCESS ) {
1074         /* 最小フィールド幅有り */
1075         
1076         /* インデックス更新 */
1077         idx += length;
1078     }
1079     
1080     /* 変換指定子判定 */
1081     switch ( pFormat[ idx ] ) {
1082         case 'u':
1083             /* 10進符号無整数 *//* FALL THROUGH */
1084             
1085             /* フラグ設定 */
1086             flags |= LOG_FLAG_UNSIGNED;     /* 符号無 */
1087             
1088         case 'd':
1089             /* 10進符号付整数 *//* FALL THROUGH */
1090         case 'i':
1091             /* 10進符号付整数 */
1092             
1093             /* 10進整数出力 */
1094             LogOutputNumber( va_arg( *pVaList, uint32_t ), 10, flags, width );
1095             
1096             /* 文字列長設定 */
1097             length = 1;
1098             
1099             break;
1100             
1101         case 'o':
1102             /* 8進符号無整数 */
1103             
1104             /* フラグ設定 */
1105             flags |= LOG_FLAG_UNSIGNED;     /* 符号無 */
1106             
1107             /* 8進整数出力 */
1108             LogOutputNumber( va_arg( *pVaList, uint32_t ), 8, flags, width );
1109             
1110             /* 文字列長設定 */
1111             length = 1;
1112             
1113             break;
1114             
1115         case 'X':
1116             /* 16進符号無整数(大文字) *//* FALL THROUGH */
1117             
1118             /* フラグ設定 */
1119             flags |= LOG_FLAG_UNSIGNED;     /* 符号無 */
1120             flags |= LOG_FLAG_UPPERCASE;    /* 大文字 */
1121             
1122         case 'x':
1123             /* 16進符号無整数(小文字) */
1124             
1125             /* フラグ設定 */
1126             flags |= LOG_FLAG_UNSIGNED;     /* 符号無 */
1127             
1128             /* 16進整数出力 */
1129             LogOutputNumber( va_arg( *pVaList, uint32_t ), 16, flags, width );
1130             
1131             /* 文字列長設定 */
1132             length = 1;
1133             
1134             break;
1135             
1136         case 'c':
1137             /* 文字 */
1138             
1139             /* 一文字出力 */
1140             LogOutputChar( ( char ) va_arg( *pVaList, int ) );
1141             
1142             /* 文字列長設定 */
1143             length = 1;
1144             
1145             break;
1146             
1147         case 's':
1148             /* 文字列 */
1149             
1150             /* 文字列出力 */
1151             LogOutputString( va_arg( *pVaList, char * ) );
1152             
1153             /* 文字列長設定 */
1154             length = 1;
1155             
1156             break;
1157             
1158         case 'p':
1159             /* ポインタ */
1160             
1161             /* フラグ設定 */
1162             flags |= LOG_FLAG_ALTERNATE;    /* 代替表示 */
1163             flags |= LOG_FLAG_UNSIGNED;     /* 符号無   */
1164             
1165             /* 16進整数出力 */
1166             LogOutputNumber( va_arg( *pVaList, uint32_t ), 16, flags, width );
1167             
1168             /* 文字列長設定 */
1169             length = 1;
1170             
1171             break;
1172             
1173         case '%':
1174             /* % */
1175             
1176             /* 一文字出力 */
1177             LogOutputChar( '%' );
1178             
1179             /* 文字列長設定 */
1180             length = 1;
1181             
1182             break;
1183             
1184         default:
1185             /* 他 */
1186             
1187             /* 文字列長設定 */
1188             length = 0;
1189             
1190             break;
1191     }
1192     
1193     return idx + length;
1194 }
1195 #endif
1196
1197
1198 /******************************************************************************/