#include <stdio.h>
int print1(const char *, unsigned long int);
int printIntData(char, size_t, char, unsigned long int);
int printInt(char, size_t, char, unsigned long int); /* fmt:未使用(将来への拡張性のために引数として入れておく)*/
int printHex(char, size_t, char, unsigned long int);
int myprintData(size_t, unsigned long int, const unsigned char *, int);
int main(void)
{
int n;
n = print1("%0lx", 258120); /* printHex(FLAG_ZERO, SIZE_4BYTE, HEX_LOWERCASE, 258120); */
printf("\n n= %d\n", n);
n = print1("%#0lx", 258120); /* printHex(FLAG_BOTH, SIZE_4BYTE, HEX_LOWERCASE, 258120); */
printf("\n n= %d\n", n);
n = print1("%#0hd", -32768); /* printHex(FLAG_BOTH, SIZE_2BYTE, HEX_UPPERCASE, 10); */
printf("\n n= %d\n", n);
return(0);
}
#define EOS ('\0')
#define ERROR_RETURN (-1)
#define FLAG_NONE (0)
#define FLAG_ZERO (1)
#define FLAG_SHARP (2)
#define FLAG_BOTH (FLAG_SHARP | FLAG_ZERO)
#define SIZE_1BYTE (1)
#define SIZE_2BYTE (2)
#define SIZE_4BYTE (4)
#define HEX_LOWERCASE (0)
#define HEX_UPPERCASE (1)
#define DECIMAL (2)
int print1(const char *format, unsigned long int data)
{
int ret;
char flag;
size_t n;
char fmt;
char *p;
int c;
ret = ERROR_RETURN;
flag = FLAG_NONE;
n = SIZE_4BYTE;
p = (char *)format;
if ((c=*p++) != '%') {
return(ret);
}
/* フラグ */
while ((c=*p++) != EOS) {
if (c == '#') {
flag |= FLAG_SHARP;
} else if (c == '0') {
flag |= FLAG_ZERO;
} else {
break;
}
}
if (c == EOS) {
return(ret);
}
/* length */
if (c == 'l') {
n = SIZE_4BYTE;
c = *p++;
} else if (c == 'h') {
if ((c = *p++) == 'h') {
n = SIZE_1BYTE;
c = *p++; /* 警告が出るが無視してよい */
} else {
n = SIZE_2BYTE;
}
}
/* format */
if (c!= EOS) {
long int sdata;
switch (c) {
case 'x':
ret = printIntData(flag, n, HEX_LOWERCASE, data);
break;
case 'X':
ret = printIntData(flag, n, HEX_UPPERCASE, data);
break;
case 'u':
ret = printIntData(FLAG_NONE, n, DECIMAL, data);
break;
case 'd':
sdata = (long int)data;
if (sdata >=0) {
ret = printIntData(FLAG_NONE, n, DECIMAL, data);
} else {
sdata = -sdata;
ret = printIntData(FLAG_SHARP, n, DECIMAL, (unsigned long int)sdata);
}
break;
default:
break;
}
} else {
/* error: format not specified */
}
return(ret);
}
int printIntData(char flag, size_t n, char fmt, unsigned long int data)
{
if ((fmt == HEX_LOWERCASE) || (fmt == HEX_UPPERCASE)) {
return(printHex(flag, n, fmt, data));
} else if (fmt == DECIMAL) {
return(printInt(flag, n, fmt, data));
} else {
return(ERROR_RETURN);
}
}
/* 32-bit integer の最大は 4294967295,つまり,10桁 */
#define MAX_DIGIT (10)
#define BASE10 (10)
int printInt(char flag, size_t n, char fmt, unsigned long int data)
{
char digit[MAX_DIGIT];
unsigned long int quot;
int i;
int num;
num = 0;
if ((flag == FLAG_SHARP) || (flag == FLAG_BOTH)) {
putchar('-');
++num;
}
if (n == SIZE_2BYTE) {
data &= 0xffff;
} else if (n == SIZE_1BYTE) {
data &= 0xff;
}
i = 0;
while ((quot = data / BASE10) != 0) {
digit[i++] = '0' + (data - quot *BASE10);
data = quot;
}
putchar('0' + data);
++num;
if (i != 0) {
while (i) {
--i;
putchar(digit[i]);
++num;
}
}
return(num);
}
#define BASE16 (16)
const unsigned char hexUpperCase[BASE16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
const unsigned char hexLowerCase[BASE16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
#define MASK4BITS (16-1)
int printHex(char flag, size_t n, char fmt, unsigned long int data)
{
int suppress0; /* 1: 先頭からの'0'データ表示を省略 */
int add0x; /* 1: 表記法'0x'を付加 */
int num, ret;
suppress0 = 1; /* default */
add0x = 0; /* default */
num = 0;
ret = ERROR_RETURN;
if ((flag >= FLAG_NONE) && (flag <= FLAG_BOTH)) {
if ((flag == FLAG_NONE) || (flag == FLAG_SHARP)) {
suppress0 = 1;
} else {
if (data == 0) {
suppress0 = 1; /* special case */
} else {
suppress0 = 0;
}
}
if ((flag == FLAG_NONE) || (flag == FLAG_ZERO)) {
add0x = 0;
} else {
add0x = 1;
}
} else {
/* ignore; use default value */
}
if (fmt == HEX_LOWERCASE) {
if (add0x) {
putchar('0');
putchar('x');
num += 2;
}
ret = myprintData(n, data, hexLowerCase, suppress0);
} else if (fmt == HEX_UPPERCASE) {
if (add0x) {
putchar('0');
putchar('X');
num += 2;
}
ret = myprintData(n, data, hexUpperCase, suppress0);
} else {
/* error: not support */;
}
if (ret < 0) {
return(ret);
} else {
return(ret+num);
}
}
int myprintData(size_t n, unsigned long int data, const unsigned char tbl[], int suppress0)
{
unsigned char c, b4;
int non0;
int num;
non0 = 0;
num = 0;
if (n == SIZE_1BYTE) {
c = (unsigned char)data;
b4 = c >> 4;
if ((suppress0 == 1) && (b4 == 0)) {
/* suppress */
} else {
putchar(tbl[b4]);
++num;
}
putchar(tbl[c&MASK4BITS]);
++num;
} else if (n == SIZE_2BYTE) {
c = (unsigned char)(data >> 8);
b4 = c >> 4;
if ((suppress0 == 1) && (!non0) && (b4 == 0)) {
/* suppress */
} else {
non0 = 1;
putchar(tbl[b4]);
++num;
}
b4 = c & MASK4BITS;
if ((suppress0 == 1) && (!non0) && (b4 == 0)) {
/* suppress */
} else {
non0 = 1;
putchar(tbl[b4]);
++num;
}
c = (unsigned char)data;
b4 = c >> 4;
if ((suppress0 == 1) && (!non0) && (b4 == 0)) {
/* suppress */
} else {
putchar(tbl[b4]);
++num;
}
putchar(tbl[c&MASK4BITS]);
++num;
} else if (n == SIZE_4BYTE) {
c = (unsigned char)(data >> 24);
b4 = c >> 4;
if ((suppress0 == 1) && (!non0) && (b4 == 0)) {
/* suppress */
} else {
non0 = 1;
putchar(tbl[b4]);
++num;
}
b4 = c & MASK4BITS;
if ((suppress0 == 1) && (!non0) && (b4 == 0)) {
/* suppress */
} else {
non0 = 1;
putchar(tbl[b4]);
++num;
}
c = (unsigned char)(data >> 16);
b4 = c >> 4;
if ((suppress0 == 1) && (!non0) && (b4 == 0)) {
/* suppress */
} else {
non0 = 1;
putchar(tbl[b4]);
++num;
}
b4 = c & MASK4BITS;
if ((suppress0 == 1) && (!non0) && (b4 == 0)) {
/* suppress */
} else {
non0 = 1;
putchar(tbl[b4]);
++num;
}
c = (unsigned char)(data >> 8);
b4 = c >> 4;
if ((suppress0 == 1) && (!non0) && (b4 == 0)) {
/* suppress */
} else {
non0 = 1;
putchar(tbl[b4]);
++num;
}
b4 = c & MASK4BITS;
if ((suppress0 == 1) && (!non0) && (b4 == 0)) {
/* suppress */
} else {
non0 = 1;
putchar(tbl[b4]);
++num;
}
c = (unsigned char)data;
b4 = c >> 4;
if ((suppress0 == 1) && (!non0) && (b4 == 0)) {
/* suppress */
} else {
putchar(tbl[b4]);
++num;
}
putchar(tbl[c&MASK4BITS]);
++num;
} else {
return(ERROR_RETURN);
}
return(num);
}