シグナルハンドラの中から安全に呼び出すことのできるエラー出力関数のセットを紹介する。
printfのような書式指定機能は付いていないため、幾つかの関数をバラバラに並べて呼び出さなければならない。
実は、softiesプロジェクトで使われている mallocライブラリ内部のエラーハンドリングに用いているため、各々の関数には static宣言が付いているが、掲載したものは staticは外してある。(この mallocライブラリについては後日紹介する機会があるかも知れない。)
クラス名などのプレフィックスは付いてないため、使う場合には関数名が干渉しないか注意しなければならない。
コンパイルを通すには unistd.hのインクルードが必要となる。
例によって十分なテストは行われていないため、動作は保証しない。
改行出力
void newline() {
write(STDERR_FILENO, "\n", 1);
fsync(STDERR_FILENO);
}
文字列出力
NUL文字で終端された char配列 stringを出力する。void printString(char* string) {
if (string == null)
string = "(null)";
int length = 0;
while (string[length] != '\0')
++length;
write(STDERR_FILENO, string, length);
}
バイナリデータ中の ASCII文字列を抽出して出力
char配列 stringの lengthで指定されたバイト数分を出力する。ASCII文字で無い値はスキップされる。
void printAsciiLetters(char* string, int length) {
if (string == null)
string = "(null)";
int index = 0;
while (index < length && string[index] >= 0x20 && string[index] < 0x7f)
++index;
write(STDERR_FILENO, string, index);
}
整数出力
符号ありの整数しか扱えない。 int型が符号を含めて 16桁を超える処理系では正しく動作しない。void printInteger(int value, int length) {
char buffer[16];
if (length > 16)
length = 16;
int index = 0;
boolean negative = false;
if (value < 0) {
negative = true;
value = -value;
}
do {
buffer[15 - index++] = (value % 10) + '0';
value /= 10;
} while (value != 0 && (length == 0 || index < length));
if (negative && index <= 15)
buffer[15 - index++] = '-';
while (index < length)
buffer[15 - index++] = ' ';
write(STDERR_FILENO, &buffer[15 - index + 1], index);
}
ポインタ出力
ポインタを '0x'が先行する 16進数で出力する。 ポインタが 0xを含めて 16桁を超える処理系では正しく動作しない。void printPointer(void* pointer, int length) {
char buffer[16];
long value = (long)pointer;
if (length > 16)
length = 16;
int index = 0;
do {
int d = (int)(value & 0xf);
buffer[15 - index++] = (d < 10)
? (d + '0')
: (d - 10 + 'a');
value >>= 4;
value &= 0xfffffff;
} while (value != 0 && (length == 0 || index < length));
buffer[15 - index++] = 'x';
buffer[15 - index++] = '0';
while (index < length)
buffer[15 - index++] = ' ';
write(STDERR_FILENO, &buffer[15 - index + 1], index);
}