util  Diff

Differences From Artifact [1556b70bdd]:

To Artifact [4cd517ba89]:


    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   				}