xprintfは組み込み用に特化したコンパクトなprintfとサポート関数群です。標準入出力関数のサポートされない組み込みシステムにおいて、既存の入出力デバイス(UARTやLCD)に結合することにより、それらに対してprintfで簡単に整形文字列を出力することができます。このため、LCDやUARTなどに手軽に整形出力したいときや、デバッグ・メンテナンス・コンソールなどに有効です。
xprintfは構成オプション(xprintf.h内に定義)で必要な機能のみ組み込むことでモジュールサイズを削減することができます。例としてCortex-M3でのコンパイル結果を次の表に示します。(gcc -Os) なお、long longと浮動小数点は、C99を必要とします。
| 機能 | .text |
|---|---|
| 基本出力 | 789 |
| long long | +91 |
| 浮動小数点 | +1027 |
| 入力 | +238 |
組み込み用printfモジュールは、次に示す関数を提供します。
/*----------------------------------------------/ / xputc - 1文字出力 /----------------------------------------------*/ void xputc ( int chr /* 出力文字(0-255) */ ); void xfputc ( void(*func)(int), /* 出力デバイスの出力関数へのポインタ */ int chr /* 出力する文字(0-255) */ );
/*----------------------------------------------/ / xputs - 文字列の出力 /----------------------------------------------*/ void xputs ( const char* str /* 出力するASCIZ文字列へのポインタ(終端の'\0'は出力されません) */ ); void xfputs ( void(*func)(int), /* 出力デバイスの出力関数へのポインタ */ const char* str /* 出力するASCIZ文字列へのポインタ(終端の'\0'は出力されません) */ );
/*----------------------------------------------/ / xprintf - 書式付き文字列出力 /----------------------------------------------*/ void xprintf ( /* デフォルト出力デバイスへの書式付き文字列出力 */ const char* fmt, /* 書式文字列へのポインタ */ ... /* オプションの引数... */ ); void xfprintf ( /* 指定出力デバイスへの書式付き文字列出力 */ void(*func)(int), /* 出力デバイスの出力関数へのポインタ */ const char* fmt, /* 書式文字列へのポインタ */ ... /* オプションの引数... */ ); void xsprintf ( /* メモリ上に書式付き文字列(ASCIZ)を出力 */ char* buff, /* 文字列出力バッファへのポインタ */ const char* fmt, /* 書式文字列へのポインタ */ ... /* オプションの引数... */ );
/*----------------------------------------------/ / put_dump - 1行のバイナリ・ダンプを出力 /----------------------------------------------*/ void put_dump ( const void* buff, /* 出力する配列へのポインタ */ unsigned long adr, /* 行頭に表示するアドレス値 */ int cnt, /* 出力する要素数 */ int width /* 要素のサイズ (1, 2, 4) */ );
書式制御命令は次に示すように標準ライブラリのサブセットとなっています。
%[フラグ][最小幅][精度][サイズ]タイプ
| タイプ | フォーマット | 引数 | 生成文字列長(パディング含まず) |
|---|---|---|---|
| d | 符号付き10進数 | int, long, long long | 1~11(ll指定時は20)文字。 |
| u | 符号なし10進数 | 1~10(ll指定時は20)文字。 | |
| o | 符号なし8進数 | 1~11(ll指定時は22)文字。 | |
| x X | 符号なし16進数 | 1~8(ll指定時は16)文字。 | |
| b | 符号なし2進数 | 1~32(ll指定時も下位32桁まで)文字。 | |
| c | キャラクタ | int | 1文字。 |
| s | 文字列 | char* | xsprintfで入力文字列長が不明のときは適切な最大幅を指定すること。 ヌルポインタは文字列長0と見なされる。 |
| f | 浮動小数点 (固定桁) | double | 1~31文字、文字数が31を越える場合は"±OV"、非数は"NaN", 無限大は"±INF"。 |
| e E | 浮動小数点 (指数) | 4~31文字、文字数が31を越える場合や指数が+99を越える場合は"±OV"。 |
使用例:
xprintf("%d", 1234); /* "1234" */
xprintf("%6d,%3d%%", -200, 5); /* " -200, 5%" */
xprintf("%-6u", 100); /* "100 " */
xprintf("%ld", 12345678); /* "12345678" */
xprintf("%llu", 0x100000000); /* "4294967296" <XF_USE_LLI> */
xprintf("%lld", -1LL); /* "-1" <XF_USE_LLI> */
xprintf("%04x", 0xA3); /* "00a3" */
xprintf("%08lX", 0x123ABC); /* "00123ABC" */
xprintf("%016b", 0x550F); /* "0101010100001111" */
xprintf("%*d", 6, 100); /* " 100" */
xprintf("%s", "abcdefg"); /* "abcdefg" */
xprintf("%5s", "abc"); /* " abc" */
xprintf("%-5s", "abc"); /* "abc " */
xprintf("%.5s", "abcdefg"); /* "abcde" */
xprintf("%-5.2s", "abcdefg"); /* "ab " */
xprintf("%c", 'a'); /* "a" */
xprintf("%12f", 10.0); /* " 10.000000" <XF_USE_FP> */
xprintf("%.4E", 123.45678); /* "1.2346E+02" <XF_USE_FP> */
/*----------------------------------------------/ / xgets - 入力デバイスから1行入力 /----------------------------------------------*/ int xgets ( /* 結果: 0:EOF, 1:1行確定 */ char* buff, /* 入力バッファへのポインタ */ int len /* 入力バッファのサイズ(文字数) */ );
/*----------------------------------------------/ / xatoi - 整数文字列の数値を取得 /----------------------------------------------*/ /* "123 -5 0x3ff 0b1111 0377 1.5 " ^ 1st call returns 123 and next ptr ^ 2nd call returns -5 and next ptr ^ 3rd call returns 1023 and next ptr ^ 4th call returns 15 and next ptr ^ 5th call returns 255 and next ptr ^ 6th call fails and returns 0 */ int xatoi ( /* 0:失敗, 1:成功 */ char** str, /* 対象の文字列を指すポインタへのポインタ */ long* res /* 結果をストアする変数へのポインタ */ );
/*----------------------------------------------/ / xatof - 実数文字列の数値を取得 /----------------------------------------------*/ /* "123 -5.75 .6 +8.88E+5 1e-6 . " ^ 1st call returns 1.23e2 and next ptr ^ 2nd call returns -5.75e0 and next ptr ^ 3rd call returns 6e-1 and next ptr ^ 4th call returns 8.88e5 and next ptr ^ 5th call returns 1e-6 and next ptr ^ 6th call fails and returns 0 */ int xatof ( /* 0:失敗, 1:成功 */ char** str, /* 対象の文字列を指すポインタへのポインタ */ double* res /* 結果をストアする変数へのポインタ */ );
UARTやLCDなどの出力デバイスに結合するには、デフォルト出力デバイスとしてモジュールのグローバル変数xfunc_outputに、そのデバイスの1文字出力関数へのポインタを代入するだけでOKです。これにより、xputc/xputs/xprintf/put_dump関数の出力は指定された関数に渡されます。xfputc/xfputs/xfprintf/xsprintf関数の出力先は、それぞれの引数で直接指定されます。この設定のためマクロも用意されているので、例えば、void uart1_putc (uint8_t chr);に結合する場合、xdev_out(uart1_putc);とすればOKです。出力関数が複数の引数をとる場合や単純な1文字出力が無い場合は、グルー関数を間にかませる必要があるかも知れません。
UARTなどの入力デバイスに結合するには、デフォルト入力デバイスとしてモジュールのグローバル変数xfunc_inputに、そのデバイスの1文字読み出し関数へのポインタを代入するだけでOKです。(設定マクロを使用した例:xdev_in(uart1_getc);) xgets関数はデフォルト入力デバイスからライン入力を行います。xfgets関数は入力関数を引数で直接指定します。読みだされた文字は、順にバッファにストアされます。'\r'、'\b'以外の制御文字は無視されます。'\r'が読み出されると読み出しを終了してxgets関数は1を返します。'\r'はバッファにはストアされず、文字列は'\0'で終端されます。通常、入力があるまで読み出し関数は制御を返しませんが、入力デバイスはコンソールに限られるわけではない(ファイルに結合した例もあります)ので、入力ストリームの終端が明確なときは-1を返すべきです。これにより、xgets関数は中断して0を返すので、アプリケーションがストリーム終端を知ることが可能になります。
/* デバイス出力関数の型 */ void output_func ( int chr /* 出力文字(0-255) */ );
/* デバイス入力関数の型 */ int input_func (void); /* 0-255:読み出した文字, -1:入力ストリームの終端 */