Overview
Comment: | add mkpw |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
42ea2c7296fcf7fbdfb520435719ffec |
User & Date: | lexi on 2019-07-19 11:34:42 |
Other Links: | manifest | tags |
Context
2019-07-19
| ||
11:47 | switch from syscall to getrandom check-in: 6b3b3fa87f user: lexi tags: trunk | |
11:34 | add mkpw check-in: 42ea2c7296 user: lexi tags: trunk | |
06:37 | fix dumb bugs check-in: e3d4aa2fb2 user: lexi tags: trunk | |
Changes
Added clib/iaia.c version [b9f828e90b].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
/* [ʞ] iaia.c * ~ lexi hale <lexi@hale.su> * # include "iaia.c" * # define _IAIA_FN_{ATOI,ITOA,ASCTOI,ITOASC} * : typedef iaia_word_type, * iaia_error_type * : enum iaia_e_domain, * iaia_e_base, * iaia_e_overflow * ? arbitrary-base integer conversion functions */ #ifndef _IAIA_FN_ATOI # define _IAIA_FN_ATOI atoi #endif #ifndef _IAIA_FN_ITOA # define _IAIA_FN_ITOA itoa #endif #ifndef _IAIA_FN_ASCTOI # define _IAIA_FN_ASCTOI asctoi #endif #ifndef _IAIA_FN_ITOASC # define _IAIA_FN_ITOASC itoasc #endif enum /* constants */ { /* ascii address space */ numspace = (0x39 - 0x30) + 1, /* 10 */ alphaspace = (0x5a - 0x41) + 1, /* 26 */ smallalphaspace = (0x7a - 0x61) + 1, /* 26 */ /* base representations */ imaxbase = numspace + alphaspace, /* 36 */ maxbase = imaxbase + smallalphaspace /* 62 */ }; /* -- string to integer converters -- */ iaia_error_type _IAIA_FN_ASCTOI(const char* s, iaia_word_type* ret) { iaia_word_type val = 0; enum { base = 128 }; for (;*s!=null;++s) { uint8_t v = *s; if (v > base) return iaia_e_domain; val *= base; val += v; } *ret = val; return ok; } iaia_error_type _IAIA_FN_ATOI(iaia_word_type base, const char* s, iaia_word_type* ret) { /* s must be a null-terminated ASCII numeral string */ if (base > maxbase) return iaia_e_base; /* override the default base if it's a basèd literal */ if (s[0] == '@' || base == 0) return _IAIA_FN_ASCTOI(s + (s[0]=='@'),ret); else if (s[0] == '0' && s[1] == 'x') base = 16, s += 2; else if (s[0] == '0' && s[1] == 'd') base = 10, s += 2; else if (s[0] == '0' && s[1] == 'b') base = 2, s += 2; else if (s[0] == '0' && s[1] == 't') base = 3, s += 2; else if (s[0] == '0') base = 8, s += 1; bool insens = (base <= imaxbase); iaia_word_type val = 0; for (;*s!=null;++s) { uint8_t v = *s; if(v >= 0x30 && v <= 0x39) v -= 0x30; else { if(v >= 0x61 && v <= 0x7a) { if (insens) v -= 0x20; else { v = numspace + alphaspace + (v - 0x61); goto checkval; } } if(v >= 0x41 && v <= 0x5a) v = numspace + (v - 0x41); else return iaia_e_domain; } checkval: if (v >= base) return iaia_e_domain; val *= base; val += v; } *ret = val; return iaia_e_ok; } /* -- integer to string converters -- */ /* needed for efficiency's sake, but really sucky - * this table needs to be kept in sync with the * itoa algorithm by hand. unfortunately, given C's * abject lack of metaprogramming, we have to do this * by hand. */ const char iaia_ref_table[] = /* numerals[10] */ "0123456789" /* bigalpha[26] */ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* smallalpha[26] */ "abcdefghijklmnopqrstuvwxyz"; _Static_assert (sizeof iaia_ref_table - 1 == maxbase); iaia_error_type _IAIA_FN_ITOASC(iaia_word_type val, const char* buf_start, char* buf_end, char** newbuf) { char* ptr = buf_end; *ptr-- = 0; while(val > 0) { if (ptr < buf_start) return iaia_e_overflow; iaia_word_type rem = val % 128; val /= 128; *ptr-- = (char)rem; } if (newbuf != null) *newbuf = ptr + 1; return ok; } iaia_error_type _IAIA_FN_ITOA(iaia_word_type base, iaia_word_type val, const char* buf_start, char* buf_end, char** newbuf, bool lowercase) { char* ptr = buf_end; if (base > maxbase) return iaia_e_base; if (base == 0) return _IAIA_FN_ITOASC(val, buf_start, buf_end, newbuf); *ptr-- = 0; if (val == 0) *ptr-- = '0'; else while(val > 0) { if (ptr < buf_start) return iaia_e_overflow; iaia_word_type rem = val % base; val /= base; char out = iaia_ref_table[rem]; if (lowercase && base <= imaxbase) if (out >= 'A' && out <= 'Z') out += ('a' - 'A'); *ptr-- = out; } if (newbuf != null) *newbuf = ptr + 1; return iaia_e_ok; } |
Added clib/tbl.c version [92768be859].
> > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/* [ʞ] tbl.c * ~ lexi hale <lexi@hale.su> * ? simple table-scanning function to make * parsing easier */ struct tblrow { tbl_word_type val; const char* str; }; tbl_error_type tblget(size_t stacksz, const struct tblrow* haystack, const char* needle, tbl_word_type* val) { for (size_t i = 0; i<stacksz; ++i) { if (strcmp(haystack[i].str, needle) == ok) { *val = haystack[i].val; return tbl_ok; } } return tbl_error; } |
Added mkpw.c version [a0f03f1e22].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
/* [ʞ] mkpw.c - make password * ~ lexi hale <lexi@hale.su> * © AGPLv3 * $ cc -O4 mkpw.c -omkpw [-D_CLIPBOARD] * - D_CLIPBOARD enables mkpw to automatically * copy new passwords to the clipboard. it * does this by attempting to execute a sequence * of binaries, and then writing the password * to STDIN of the binary that succeeds. * ? generates passwords * → mkpw is unlikely to be portable to non-POSIX * systems, but should run fine on Linux as well * as BSDs with getrandom() support. */ #include <unistd.h> #include <sys/random.h> #include <stddef.h> #include <stdint.h> #include <string.h> #define sz(a) ( sizeof (a) / sizeof (a) [0] ) #define say(x) (write(2, (x), sizeof (x))) #ifdef _CLIPBOARD # include <sys/types.h> # include <pwd.h> # include <stdlib.h> # define _cl_opt o('n',nocopy,copy = false) #else # define _cl_opt #endif #define options \ o('l',lower,mode = lower) \ o('m',mix,mode = mix) \ o('u',upper,mode = upper)\ _cl_opt enum /* constants */ { null = 0, true = 1, false = 0 }; typedef enum bad { ok = 0, fail = 1, bad_user, bad_option, bad_syntax, bad_usage = 64, /* fleabsd idiom */ } bad; typedef _Bool bool; typedef unsigned long long iaia_word_type; typedef bad iaia_error_type; enum /* iaia errors */ { iaia_e_ok = ok, iaia_e_base = fail, iaia_e_domain = fail, iaia_e_overflow = fail, }; #define _IAIA_FN_ATOI katoi #include "clib/iaia.c" typedef enum { tbl_ok = ok, tbl_error = fail } tbl_error_type; typedef unsigned char tbl_word_type; #include "clib/tbl.c" enum args { #define o(short, long, code) arg_##long, options #undef o }; struct tblrow argtbl[] = { #define o(short, long, code) {arg_##long, #long}, options #undef o }; #define str_ucase "ABCDEFGHIJKLMNOPQRSTUVWXYZ" #define str_lcase "abcdefghijklmnopqrstuvwxyz" #define str_num "0123456789" const char* reftbl = str_num str_ucase str_lcase; const char* reftbl_lcase = str_num str_lcase; #ifdef _CLIPBOARD char* const* cbd_cmds[] = { /* NOTE: these commands must be specified in order of * most- to least-specific. more than one utility may * be present on a given system, so we need to make sure * the right one is called. */ (char* const[]){"termux-clipboard-set", null}, (char* const[]){"xsel", "-bi", null}, /* TODO: allow command to be specified by env var */ null }; #endif int main(int argc, const char** argv) { if (argc == 0) return -1; if (argc == 1) { size_t namelen = strlen(argv[0]); say("\x1b[1musage:\x1b[m "); write(2, argv[0], namelen); say(" [-lmu" # ifdef _CLIPBOARD "n" # endif "] [--lower] [--mix] [--upper]" # ifdef _CLIPBOARD " [--nocopy]" # endif " <length> [<quantity>]"); return bad_usage; } enum { upper, mix, lower } mode = lower; unsigned long long len, q = 1; bool gotlen = false; bool gotq = false; # ifdef _CLIPBOARD bool copy = true; # endif for (const char** arg = argv; *arg != null; ++arg) { if ((*arg)[0] == '-') { if ((*arg)[1] == '-') { /* long opt */ unsigned char a; if (tblget(sz(argtbl), argtbl, *arg + 2, &a) == ok) switch (a) { # define o(short, long, code) case arg_##long:code;break; options # undef o } else { return bad_option; } } else { /* short opt */ for(const char* ptr = (*arg) + 1; *ptr != 0; ++ptr) { switch(*ptr) { # define o(short, long, code) case short:code;break; options # undef o default: return bad_option; } } } } else { if (gotq) return bad_syntax; else if (gotlen) { if (katoi(10, *arg, &q) == ok) { gotq = true; } } else if(katoi(10, *arg, &len) == ok) { gotlen = true; } } } if (!gotlen) return bad_syntax; # ifdef _CLIPBOARD if (geteuid() == 0 && copy) { /* on a sane system, what we'd do is hike up the process * tree til we found a non-root user. alas, this is UNIX. */ const char* realuser = getenv("SUDO_USER"); if (realuser == null) realuser = "nobody"; say("\x1b[1;33mwarning:\x1b[m you are running \x1b[4m"); size_t namelen = strlen(argv[0]); write(2,argv[0],namelen); say("\x1b[24m as \x1b[1mroot\x1b[m! dropping to \x1b[1m"); write(2,realuser,strlen(realuser)); setenv("USER", realuser, true); say("\x1b[m to prevent malicious behavior\n"); struct passwd* nobody = getpwnam(realuser); if (nobody == null) { say("\x1b[1;31mfatal:\x1b[m could not get UID to drop privileges; bailing"); return bad_user; } else { setenv("HOME", nobody -> pw_dir, true); setenv("SHELL", "/dev/null", true); setuid(nobody -> pw_uid); } } # endif const unsigned char chars = (sizeof str_num - 1) + ((mode == upper) ? (sizeof str_ucase - 1) : ((mode == lower) ? (sizeof str_lcase - 1) : ((sizeof str_ucase - 1) + (sizeof str_lcase - 1)))); const char* tbl = (mode == upper) ? reftbl : ((mode == lower) ? reftbl_lcase : reftbl); char buf[len+1]; /* *buf = 0; */ unsigned char noise[len]; for (size_t i = 0; i<q; ++i) { unsigned char* cur = noise; getrandom(noise, len, 0); for(char* ptr = buf; ptr < buf + len; ++ptr, ++cur) { *ptr = tbl[*cur % chars]; /* such a waste of entropy… :( */ } buf[len] = '\n'; write(1, buf, len + 1); } # ifdef _CLIPBOARD if (copy) { char* const clipboard_env = getenv("mkpw_clipboard_setter"); char* const clipboard_env_arg = getenv("mkpw_clipboard_setter_arg"); // FIXME: allow multiple args int fds[2]; if (pipe(fds) != 0) return 63; if (!fork()) { close(fds[1]); dup2(fds[0], 0); if (clipboard_env != null) { execvp(clipboard_env, (char* const[]){ clipboard_env, clipboard_env_arg, null}); return -1; } else for(char* const** cmd = cbd_cmds; *cmd != null; ++cmd) { execvp((*cmd)[0], *cmd); } return -1; /* exec failed */ } else { close(fds[0]); write(fds[1], buf, len); write(fds[1], "\n", 1); close(fds[1]); } } # endif return ok; } |
Modified ord.c from [1556b70bdd] to [4cd517ba89].
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 .. 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 ... 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 ... 260 261 262 263 264 265 266 267 268 269 270 271 272 273 ... 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
# define forlibc(x) x #endif #include <stddef.h> #include <stdint.h> #include <string.h> #include <limits.h> #define sz(x) ( sizeof (x) / sizeof (x) [0] ) enum /* constants */ { null = 0, /* ascii address space */ numspace = (0x39 - 0x30) + 1, /* 10 */ alphaspace = (0x5a - 0x41) + 1, /* 26 */ smallalphaspace = (0x7a - 0x61) + 1, /* 26 */ /* base representations */ imaxbase = numspace + alphaspace, /* 36 */ maxbase = imaxbase + smallalphaspace /* 62 */ }; typedef unsigned long long word; typedef _Bool bool; enum { false = 0, true = 1 }; typedef struct pair { uint8_t val; const char* str; } pair; #define error_list \ e(domain, "bad argument passed for domain") \ e(find, "could not find key in table") \ e(syntax, "invalid syntax") \ e(base, "that base is out of range") \ e(overflow, "a memory overflow has occurred") \ ................................................................................ typedef enum bad { ok = 0, fail = 1, # define e(name, desc) bad_##name, error_list # undef e } bad; bad tblget(size_t stacksz, const pair* haystack, const char* needle, uint8_t* val) { for (size_t i = 0; i<stacksz; ++i) { if (strcmp(haystack[i].str, needle) == ok) { *val = haystack[i].val; return ok; } } return bad_find; } enum argument { arg_to, arg_set, arg_base, arg_asc, arg_bin, arg_trn, arg_oct, arg_dec, ................................................................................ {switch_prefix, "-p"}, {switch_prefix, "--prefix"}, {switch_lowercase, "-l"}, {switch_lowercase, "--lowercase"}, {param_prefix, "-m"}, {param_prefix, "--manual-prefix"}, {arg_ebcdic, "ebcdic"}, }; bad asctoi(const char* s, word* ret) { word val = 0; enum { base = 128 }; for (;*s!=null;++s) { uint8_t v = *s; if (v > base) return bad_domain; val *= base; val += v; } *ret = val; return ok; } bad atoi(word base, const char* s, word* ret) { /* s must be a null-terminated ASCII numeral string */ if (base > maxbase) return bad_base; /* override the default base if it's a basèd literal */ if (s[0] == '@' || base == 0) return asctoi(s + (s[0]=='@'),ret); else if (s[0] == '0' && s[1] == 'x') base = 16, s += 2; else if (s[0] == '0' && s[1] == 'd') base = 10, s += 2; else if (s[0] == '0' && s[1] == 'b') base = 2, s += 2; else if (s[0] == '0' && s[1] == 't') base = 3, s += 2; else if (s[0] == '0') base = 8, s += 1; bool insens = (base <= imaxbase); word val = 0; for (;*s!=null;++s) { uint8_t v = *s; if(v >= 0x30 && v <= 0x39) v -= 0x30; else { if(v >= 0x61 && v <= 0x7a) { if (insens) v -= 0x20; else { v = numspace + alphaspace + (v - 0x61); goto checkval; } } if(v >= 0x41 && v <= 0x5a) v = numspace + (v - 0x41); else return bad_domain; } checkval: if (v >= base) return bad_domain; val *= base; val += v; } *ret = val; return ok; } /* needed for efficiency's sake, but really sucky - * this table needs to be kept in sync with the * itoa algorithm by hand. unfortunately, given C's * abject lack of metaprogramming, we have to do this * by hand. */ const char baseref[] = /* numerals[10] */ "0123456789" /* bigalpha[26] */ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* smallalpha[26] */ "abcdefghijklmnopqrstuvwxyz"; _Static_assert (sizeof baseref - 1 == maxbase); bad itoasc(word val, const char* buf_start, char* buf_end, char** newbuf) { char* ptr = buf_end; *ptr-- = 0; while(val > 0) { if (ptr < buf_start) return bad_overflow; word rem = val % 128; val /= 128; *ptr-- = (char)rem; } if (newbuf != null) *newbuf = ptr + 1; return ok; } bool lowercase = false; bad itoa(word base, word val, const char* buf_start, char* buf_end, char** newbuf) { char* ptr = buf_end; if (base > maxbase) return bad_base; if (base == 0) return itoasc(val, buf_start, buf_end, newbuf); *ptr-- = 0; if (val == 0) *ptr-- = '0'; else while(val > 0) { if (ptr < buf_start) return bad_overflow; word rem = val % base; val /= base; char out = baseref[rem]; if (lowercase && base <= imaxbase) if (out >= 'A' && out <= 'Z') out += ('a' - 'A'); *ptr-- = out; } if (newbuf != null) *newbuf = ptr + 1; return ok; } bad run(const int argc, const char** argv) { # ifndef _POSIX_IO /* fuck your buffering, it only ever makes * things worse */ setvbuf(stdout,null,_IONBF); # endif ................................................................................ const char** invalp = in_vals; const char* pfxstr; forposix(size_t pfxstrlen); bool raw = false; bool prefix = false; for (const char** arg = argv + 1; *arg != null; ++arg) { uint8_t tblval; if (*arg[0] == '%') { ++ *arg; goto number; } else if (!raw && (tblget(sz(argtbl),argtbl, *arg, &tblval) == ok)) { enum argument symbol = (enum argument) tblval; switch (symbol) { ................................................................................ char* ptr = (buf + bufmax) - 1; forposix(char* lastptr = ptr); for (const char** s = in_vals; *s != null; ++s) { word val; bad e = atoi(base[set_in], *s, &val); if (e == ok) { bad e = itoa(base[set_out], val, buf, ptr, &ptr); if (prefix) { if (pfxstr != null) { print(pfxstrlen, pfxstr); } else if (base[set_out] < sz(prefixes)) { print((size_t)prefixes[base[set_out]][0], prefixes[base[set_out]] + 1); } |
> < < < < < < < < < < | | | | | | < < < | | | < > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | > > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > | |
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 .. 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 ... 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 ... 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 ... 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
# define forlibc(x) x #endif #include <stddef.h> #include <stdint.h> #include <string.h> #include <limits.h> #define sz(x) ( sizeof (x) / sizeof (x) [0] ) enum /* constants */ { null = 0, }; typedef unsigned long long word; typedef _Bool bool; enum { false = 0, true = 1 }; #define error_list \ e(domain, "bad argument passed for domain") \ e(find, "could not find key in table") \ e(syntax, "invalid syntax") \ e(base, "that base is out of range") \ e(overflow, "a memory overflow has occurred") \ ................................................................................ typedef enum bad { ok = 0, fail = 1, # define e(name, desc) bad_##name, error_list # undef e } bad; typedef enum { tbl_ok = ok, tbl_error = bad_find } tbl_error_type; typedef unsigned char tbl_word_type; #include "clib/tbl.c" typedef struct tblrow pair; enum argument { arg_to, arg_set, arg_base, arg_asc, arg_bin, arg_trn, arg_oct, arg_dec, ................................................................................ {switch_prefix, "-p"}, {switch_prefix, "--prefix"}, {switch_lowercase, "-l"}, {switch_lowercase, "--lowercase"}, {param_prefix, "-m"}, {param_prefix, "--manual-prefix"}, {arg_ebcdic, "ebcdic"}, }; /* import the conversion utilities */ typedef bad iaia_error_type; typedef word iaia_word_type; enum /* iaia synonyms */ { iaia_e_ok = ok, iaia_e_domain = bad_domain, iaia_e_base = bad_base, iaia_e_overflow = bad_overflow, }; #include "clib/iaia.c" bad run(const int argc, const char** argv) { # ifndef _POSIX_IO /* fuck your buffering, it only ever makes * things worse */ setvbuf(stdout,null,_IONBF); # endif ................................................................................ const char** invalp = in_vals; const char* pfxstr; forposix(size_t pfxstrlen); bool raw = false; bool prefix = false; bool lowercase = false; for (const char** arg = argv + 1; *arg != null; ++arg) { uint8_t tblval; if (*arg[0] == '%') { ++ *arg; goto number; } else if (!raw && (tblget(sz(argtbl),argtbl, *arg, &tblval) == ok)) { enum argument symbol = (enum argument) tblval; switch (symbol) { ................................................................................ char* ptr = (buf + bufmax) - 1; forposix(char* lastptr = ptr); for (const char** s = in_vals; *s != null; ++s) { word val; bad e = atoi(base[set_in], *s, &val); if (e == ok) { bad e = itoa(base[set_out], val, buf, ptr, &ptr, lowercase); if (prefix) { if (pfxstr != null) { print(pfxstrlen, pfxstr); } else if (base[set_out] < sz(prefixes)) { print((size_t)prefixes[base[set_out]][0], prefixes[base[set_out]] + 1); } |