Differences From
Artifact [1556b70bdd]:
34 34 # define forlibc(x) x
35 35 #endif
36 36 #include <stddef.h>
37 37 #include <stdint.h>
38 38 #include <string.h>
39 39 #include <limits.h>
40 40 #define sz(x) ( sizeof (x) / sizeof (x) [0] )
41 +
41 42
42 43 enum /* constants */ {
43 44 null = 0,
44 -
45 - /* ascii address space */
46 - numspace = (0x39 - 0x30) + 1, /* 10 */
47 - alphaspace = (0x5a - 0x41) + 1, /* 26 */
48 - smallalphaspace = (0x7a - 0x61) + 1, /* 26 */
49 -
50 - /* base representations */
51 - imaxbase = numspace + alphaspace, /* 36 */
52 - maxbase = imaxbase + smallalphaspace /* 62 */
53 45 };
54 46
55 47 typedef unsigned long long word;
56 48 typedef _Bool bool;
57 49 enum { false = 0, true = 1 };
58 50
59 -typedef struct pair { uint8_t val; const char* str; } pair;
60 51
61 52 #define error_list \
62 53 e(domain, "bad argument passed for domain") \
63 54 e(find, "could not find key in table") \
64 55 e(syntax, "invalid syntax") \
65 56 e(base, "that base is out of range") \
66 57 e(overflow, "a memory overflow has occurred") \
................................................................................
69 60 typedef enum bad {
70 61 ok = 0, fail = 1,
71 62 # define e(name, desc) bad_##name,
72 63 error_list
73 64 # undef e
74 65 } bad;
75 66
76 -bad tblget(size_t stacksz, const pair* haystack, const char* needle, uint8_t* val) {
77 - for (size_t i = 0; i<stacksz; ++i) {
78 - if (strcmp(haystack[i].str, needle) == ok) {
79 - *val = haystack[i].val;
80 - return ok;
81 - }
82 - }
83 - return bad_find;
84 -}
67 +typedef enum {
68 + tbl_ok = ok, tbl_error = bad_find
69 +} tbl_error_type;
70 +typedef unsigned char tbl_word_type;
71 +#include "clib/tbl.c"
72 +typedef struct tblrow pair;
85 73
86 74 enum argument {
87 75 arg_to, arg_set, arg_base,
88 76
89 77 arg_asc,
90 78
91 79 arg_bin, arg_trn, arg_oct, arg_dec,
................................................................................
137 125 {switch_prefix, "-p"}, {switch_prefix, "--prefix"},
138 126 {switch_lowercase, "-l"}, {switch_lowercase, "--lowercase"},
139 127 {param_prefix, "-m"}, {param_prefix, "--manual-prefix"},
140 128
141 129 {arg_ebcdic, "ebcdic"},
142 130 };
143 131
144 -bad asctoi(const char* s, word* ret) {
145 - word val = 0;
146 - enum { base = 128 };
147 -
148 - for (;*s!=null;++s) {
149 - uint8_t v = *s;
150 - if (v > base) return bad_domain;
151 -
152 - val *= base;
153 - val += v;
154 - }
155 -
156 - *ret = val;
157 - return ok;
158 -}
159 -
160 -bad atoi(word base, const char* s, word* ret) {
161 - /* s must be a null-terminated ASCII numeral string */
162 - if (base > maxbase) return bad_base;
163 -
164 - /* override the default base if it's a basèd literal */
165 - if (s[0] == '@' || base == 0) return asctoi(s + (s[0]=='@'),ret);
166 - else if (s[0] == '0' && s[1] == 'x') base = 16, s += 2;
167 - else if (s[0] == '0' && s[1] == 'd') base = 10, s += 2;
168 - else if (s[0] == '0' && s[1] == 'b') base = 2, s += 2;
169 - else if (s[0] == '0' && s[1] == 't') base = 3, s += 2;
170 - else if (s[0] == '0') base = 8, s += 1;
171 -
172 - bool insens = (base <= imaxbase);
173 - word val = 0;
174 -
175 - for (;*s!=null;++s) {
176 - uint8_t v = *s;
177 - if(v >= 0x30 && v <= 0x39) v -= 0x30; else {
178 - if(v >= 0x61 && v <= 0x7a) {
179 - if (insens) v -= 0x20; else {
180 - v = numspace + alphaspace + (v - 0x61);
181 - goto checkval;
182 - }
183 - }
184 - if(v >= 0x41 && v <= 0x5a) v = numspace + (v - 0x41);
185 - else return bad_domain;
186 - }
187 - checkval: if (v >= base) return bad_domain;
188 -
189 - val *= base;
190 - val += v;
191 - }
192 -
193 - *ret = val;
194 - return ok;
195 -}
196 -
197 -/* needed for efficiency's sake, but really sucky -
198 - * this table needs to be kept in sync with the
199 - * itoa algorithm by hand. unfortunately, given C's
200 - * abject lack of metaprogramming, we have to do this
201 - * by hand. */
202 -const char baseref[] = /* numerals[10] */ "0123456789"
203 - /* bigalpha[26] */ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
204 - /* smallalpha[26] */ "abcdefghijklmnopqrstuvwxyz";
205 -_Static_assert (sizeof baseref - 1 == maxbase);
206 -
207 -bad itoasc(word val, const char* buf_start, char* buf_end, char** newbuf) {
208 - char* ptr = buf_end;
209 -
210 - *ptr-- = 0;
211 - while(val > 0) {
212 - if (ptr < buf_start) return bad_overflow;
213 - word rem = val % 128;
214 - val /= 128;
215 - *ptr-- = (char)rem;
216 - }
217 -
218 - if (newbuf != null) *newbuf = ptr + 1;
219 - return ok;
220 -}
221 -
222 -bool lowercase = false;
223 -bad itoa(word base, word val, const char* buf_start,
224 - char* buf_end, char** newbuf) {
225 -
226 - char* ptr = buf_end;
227 -
228 - if (base > maxbase) return bad_base;
229 - if (base == 0) return itoasc(val, buf_start, buf_end, newbuf);
230 -
231 - *ptr-- = 0;
232 - if (val == 0) *ptr-- = '0';
233 - else while(val > 0) {
234 - if (ptr < buf_start) return bad_overflow;
235 - word rem = val % base;
236 - val /= base;
237 - char out = baseref[rem];
238 - if (lowercase && base <= imaxbase)
239 - if (out >= 'A' && out <= 'Z')
240 - out += ('a' - 'A');
241 - *ptr-- = out;
242 - }
243 -
244 - if (newbuf != null) *newbuf = ptr + 1;
245 - return ok;
246 -}
132 +/* import the conversion utilities */
133 +typedef bad iaia_error_type;
134 +typedef word iaia_word_type;
135 +enum /* iaia synonyms */ {
136 + iaia_e_ok = ok,
137 + iaia_e_domain = bad_domain,
138 + iaia_e_base = bad_base,
139 + iaia_e_overflow = bad_overflow,
140 +};
141 +#include "clib/iaia.c"
247 142
248 143 bad run(const int argc, const char** argv) {
249 144 # ifndef _POSIX_IO
250 145 /* fuck your buffering, it only ever makes
251 146 * things worse */
252 147 setvbuf(stdout,null,_IONBF);
253 148 # endif
................................................................................
260 155 const char** invalp = in_vals;
261 156 const char* pfxstr;
262 157 forposix(size_t pfxstrlen);
263 158
264 159
265 160 bool raw = false;
266 161 bool prefix = false;
162 + bool lowercase = false;
267 163
268 164 for (const char** arg = argv + 1; *arg != null; ++arg) {
269 165 uint8_t tblval;
270 166 if (*arg[0] == '%') { ++ *arg; goto number; } else
271 167 if (!raw && (tblget(sz(argtbl),argtbl, *arg, &tblval) == ok)) {
272 168 enum argument symbol = (enum argument) tblval;
273 169 switch (symbol) {
................................................................................
339 235 char* ptr = (buf + bufmax) - 1;
340 236 forposix(char* lastptr = ptr);
341 237
342 238 for (const char** s = in_vals; *s != null; ++s) {
343 239 word val;
344 240 bad e = atoi(base[set_in], *s, &val);
345 241 if (e == ok) {
346 - bad e = itoa(base[set_out], val, buf, ptr, &ptr);
242 + bad e = itoa(base[set_out], val, buf, ptr, &ptr, lowercase);
347 243
348 244 if (prefix) {
349 245 if (pfxstr != null) { print(pfxstrlen, pfxstr); }
350 246 else if (base[set_out] < sz(prefixes)) {
351 247 print((size_t)prefixes[base[set_out]][0],
352 248 prefixes[base[set_out]] + 1);
353 249 }