1 #define GLUE_HELPER(x, y) x ## _ ## y 2 #define GLUE(x, y) GLUE_HELPER(x, y) 3 #define TOSTRING(x) #x 4 5 static const char *GLUE(make_string, TYPE_FUNC)(TYPE value, int base) 6 { 7 static char buffer[66]; 8 char *s; /* allows 64-bit base 2 value with minus and null */ 9 TYPEU valuetemp; 10 11 /* build number string in proper base, work backwards, starting with null */ 12 s = buffer + sizeof(buffer); 13 *--s = 0; 14 15 /* fill in the digits */ 16 valuetemp = (value < 0) ? -value : value; 17 do 18 { 19 *--s = "0123456789abcdefghijklmnopqrstuvwxyz"[valuetemp % base]; 20 valuetemp /= base; 21 } while (valuetemp); 22 23 /* add sign if needed */ 24 if (value < 0) 25 *--s = '-'; 26 27 return s; 28 } 29 30 static void GLUE(e, TYPE_FUNC)(int n, const char *s, TYPE result, int base) 31 { 32 /* watch out: don't overwrite the static buffer in make_string */ 33 printf("Subtest %s, error %d, errno=%d, s=\"%s\", base=%d, ", TOSTRING(TYPE_FUNC), n, errno, s, base); 34 printf("result=%s\n", GLUE(make_string, TYPE_FUNC)(result, base)); 35 e(7); 36 } 37 38 static void GLUE(test_string, TYPE_FUNC)(const char *s, TYPE value, int base) 39 { 40 char *end; 41 TYPE result; 42 43 /* must convert the entire string, resulting in the requested value */ 44 result = TYPE_FUNC(s, &end, base); 45 if (result != value) GLUE(e, TYPE_FUNC)(1, s, result, base); 46 if (*end) GLUE(e, TYPE_FUNC)(2, s, result, base); 47 } 48 49 static void GLUE(test_value_with_base, TYPE_FUNC)(TYPE value, int base) 50 { 51 const char *s; 52 53 /* convert to string, then convert back */ 54 s = GLUE(make_string, TYPE_FUNC)(value, base); 55 GLUE(test_string, TYPE_FUNC)(s, value, base); 56 } 57 58 static void GLUE(test_value, TYPE_FUNC)(TYPE value) 59 { 60 int base; 61 62 /* let's get all our bases covered */ 63 for (base = 2; base <= 36; base++) 64 GLUE(test_value_with_base, TYPE_FUNC)(value, base); 65 } 66 67 static void GLUE(test, TYPE_FUNC)(void) 68 { 69 int base, i; 70 TYPE value, valuenext; 71 72 /* check 0x0000.... and 0xffff.... */ 73 value = 0; 74 for (i = 0; i < 0x10000; i++) 75 { 76 /* test current value */ 77 GLUE(test_value, TYPE_FUNC)(value); 78 GLUE(test_value, TYPE_FUNC)(-value); 79 value++; 80 } 81 82 /* check 0x8000.... and 0x7fff.... */ 83 value = 0; 84 value = ((~value) << 1) >> 1; 85 for (i = 0; i < 0x10000; i++) 86 { 87 /* test current value */ 88 GLUE(test_value, TYPE_FUNC)(value); 89 GLUE(test_value, TYPE_FUNC)(-value); 90 value++; 91 } 92 93 /* check powers of possible bases */ 94 for (base = 2; base <= 36; base++) 95 { 96 value = 1; 97 while (1) 98 { 99 /* test current value with offsets */ 100 for (i = -36; i <= 36; i++) 101 { 102 GLUE(test_value, TYPE_FUNC)(value + i); 103 GLUE(test_value, TYPE_FUNC)(-value + i); 104 } 105 106 /* stop after overflow */ 107 valuenext = value * base; 108 if (valuenext <= value) 109 break; 110 111 value = valuenext; 112 } 113 } 114 115 /* automatic base */ 116 GLUE(test_string, TYPE_FUNC)("10", 10, 0); 117 GLUE(test_string, TYPE_FUNC)("010", 010, 0); 118 GLUE(test_string, TYPE_FUNC)("010", 010, 8); 119 GLUE(test_string, TYPE_FUNC)("0x10", 0x10, 0); 120 GLUE(test_string, TYPE_FUNC)("0X10", 0X10, 0); 121 GLUE(test_string, TYPE_FUNC)("0x10", 0x10, 16); 122 GLUE(test_string, TYPE_FUNC)("0X10", 0X10, 16); 123 124 /* ignore plus sign, leading spaces and zeroes */ 125 GLUE(test_string, TYPE_FUNC)("10", 10, 10); 126 GLUE(test_string, TYPE_FUNC)("010", 10, 10); 127 GLUE(test_string, TYPE_FUNC)("0010", 10, 10); 128 GLUE(test_string, TYPE_FUNC)(" 10", 10, 10); 129 GLUE(test_string, TYPE_FUNC)(" 010", 10, 10); 130 GLUE(test_string, TYPE_FUNC)(" 0010", 10, 10); 131 GLUE(test_string, TYPE_FUNC)("\t10", 10, 10); 132 GLUE(test_string, TYPE_FUNC)("\t010", 10, 10); 133 GLUE(test_string, TYPE_FUNC)("\t0010", 10, 10); 134 GLUE(test_string, TYPE_FUNC)(" \t10", 10, 10); 135 GLUE(test_string, TYPE_FUNC)(" \t010", 10, 10); 136 GLUE(test_string, TYPE_FUNC)(" \t0010", 10, 10); 137 GLUE(test_string, TYPE_FUNC)("+10", 10, 10); 138 GLUE(test_string, TYPE_FUNC)("+010", 10, 10); 139 GLUE(test_string, TYPE_FUNC)("+0010", 10, 10); 140 GLUE(test_string, TYPE_FUNC)(" +10", 10, 10); 141 GLUE(test_string, TYPE_FUNC)(" +010", 10, 10); 142 GLUE(test_string, TYPE_FUNC)(" +0010", 10, 10); 143 GLUE(test_string, TYPE_FUNC)("\t+10", 10, 10); 144 GLUE(test_string, TYPE_FUNC)("\t+010", 10, 10); 145 GLUE(test_string, TYPE_FUNC)("\t+0010", 10, 10); 146 GLUE(test_string, TYPE_FUNC)(" \t+10", 10, 10); 147 GLUE(test_string, TYPE_FUNC)(" \t+010", 10, 10); 148 GLUE(test_string, TYPE_FUNC)(" \t+0010", 10, 10); 149 } 150 151 #undef GLUE_HELPER 152 #undef GLUE 153 #undef TOSTRING 154