diff options
| -rw-r--r-- | ChangeLog | 1 | ||||
| -rw-r--r-- | doc/numconvert.1.in | 8 | ||||
| -rw-r--r-- | src/numconvert.c | 78 |
3 files changed, 79 insertions, 8 deletions
| @@ -5,6 +5,7 @@ Copyright (C) 2008, 2009, 2010, 2021 David M. Syzdek <david@syzdek.net> | |||
| 5 | 1.6 | 5 | 1.6 |
| 6 | - numconvert: fixing output for char (syzdek) | 6 | - numconvert: fixing output for char (syzdek) |
| 7 | - numconvert: fixing padding in output (syzdek) | 7 | - numconvert: fixing padding in output (syzdek) |
| 8 | - numconvert: adding support for strings (syzdek) | ||
| 8 | 9 | ||
| 9 | 1.5 2021/10/11 (syzdek) | 10 | 1.5 2021/10/11 (syzdek) |
| 10 | - autotools: adding flags to enable/disable individual tools (syzdek) | 11 | - autotools: adding flags to enable/disable individual tools (syzdek) |
diff --git a/doc/numconvert.1.in b/doc/numconvert.1.in index 03a4135..1791166 100644 --- a/doc/numconvert.1.in +++ b/doc/numconvert.1.in | |||
| @@ -37,7 +37,7 @@ | |||
| 37 | .SH NAME | 37 | .SH NAME |
| 38 | numconvert \- displays values using multiple numeral systems | 38 | numconvert \- displays values using multiple numeral systems |
| 39 | .SH SYNOPSIS | 39 | .SH SYNOPSIS |
| 40 | \fBnumconvert\fR [\fB-a\fR | \fB-b\fR | \fB-d\fR \fB | \fB-o\fR | \fB-x\fR] [\fB-ABDlOqRrsX\fR] [\fB-f\fR \fIorder\fR] \fInumber1\fR [\fInumber2\fR [\fInumberN\fR]] | 40 | \fBnumconvert\fR [\fB-a\fR | \fB-b\fR | \fB-d\fR \fB | \fB-o\fR | \fB-x\fR] [\fB-ABDlOqRrSswX\fR] [\fB-f\fR \fIorder\fR] \fInumber1\fR [\fInumber2\fR [\fInumberN\fR]] |
| 41 | .sp | 41 | .sp |
| 42 | \fBnumconvert\fR [\fB--help\fR | \fB-h\fR] | 42 | \fBnumconvert\fR [\fB--help\fR | \fB-h\fR] |
| 43 | .sp | 43 | .sp |
| @@ -100,7 +100,13 @@ Display binary numerals in little endian byte order. | |||
| 100 | \fB-r\fR | 100 | \fB-r\fR |
| 101 | Display binary numerals in little endian byte order and little endian bit order | 101 | Display binary numerals in little endian byte order and little endian bit order |
| 102 | .TP | 102 | .TP |
| 103 | \fB-S\fR | ||
| 104 | Display the values as a string. | ||
| 105 | .TP | ||
| 103 | \fB-s\fR | 106 | \fB-s\fR |
| 107 | Process input strings as a ASCII string. | ||
| 108 | .TP | ||
| 109 | \fB-w\fR | ||
| 104 | Do not print spaces when displaying numerals. | 110 | Do not print spaces when displaying numerals. |
| 105 | .TP | 111 | .TP |
| 106 | \fB\-V\fR, \fB--version\fR | 112 | \fB\-V\fR, \fB--version\fR |
diff --git a/src/numconvert.c b/src/numconvert.c index 3f52a53..5db075c 100644 --- a/src/numconvert.c +++ b/src/numconvert.c | |||
| @@ -101,6 +101,7 @@ | |||
| 101 | #define MY_OPT_ASCII 0x0100 | 101 | #define MY_OPT_ASCII 0x0100 |
| 102 | #define MY_OPT_HEADER 0x0200 | 102 | #define MY_OPT_HEADER 0x0200 |
| 103 | #define MY_OPT_QUIET 0x0400 | 103 | #define MY_OPT_QUIET 0x0400 |
| 104 | #define MY_OPT_STR 0x0800 | ||
| 104 | 105 | ||
| 105 | #define MY_TOGGLE(value, bit) ( (value&bit) ? (value&(~bit)) : (value|bit)) | 106 | #define MY_TOGGLE(value, bit) ( (value&bit) ? (value&(~bit)) : (value|bit)) |
| 106 | 107 | ||
| @@ -142,13 +143,13 @@ int main(int argc, char * argv[]) | |||
| 142 | int bases; | 143 | int bases; |
| 143 | int32_t opt; | 144 | int32_t opt; |
| 144 | intmax_t x; | 145 | intmax_t x; |
| 145 | intmax_t y; | 146 | size_t y; |
| 146 | uintmax_t num; | 147 | uintmax_t num; |
| 147 | char * endptr; | 148 | char * endptr; |
| 148 | const char * order; | 149 | const char * order; |
| 149 | 150 | ||
| 150 | // getopt options | 151 | // getopt options |
| 151 | static char short_opt[] = "AaBbDdf:hlOoqRrwVXx"; | 152 | static char short_opt[] = "AaBbDdf:hlOoqRrSswVXx"; |
| 152 | static struct option long_opt[] = | 153 | static struct option long_opt[] = |
| 153 | { | 154 | { |
| 154 | {"help", no_argument, 0, 'h'}, | 155 | {"help", no_argument, 0, 'h'}, |
| @@ -230,6 +231,15 @@ int main(int argc, char * argv[]) | |||
| 230 | opt |= MY_OPT_LEBIT; | 231 | opt |= MY_OPT_LEBIT; |
| 231 | break; | 232 | break; |
| 232 | 233 | ||
| 234 | case 'S': | ||
| 235 | opt |= MY_OPT_STR; | ||
| 236 | bases++; | ||
| 237 | break; | ||
| 238 | |||
| 239 | case 's': | ||
| 240 | base = 128; | ||
| 241 | break; | ||
| 242 | |||
| 233 | case 'w': | 243 | case 'w': |
| 234 | opt = MY_TOGGLE(opt, MY_OPT_SPACE); | 244 | opt = MY_TOGGLE(opt, MY_OPT_SPACE); |
| 235 | break; | 245 | break; |
| @@ -295,6 +305,12 @@ int main(int argc, char * argv[]) | |||
| 295 | bases++; | 305 | bases++; |
| 296 | break; | 306 | break; |
| 297 | 307 | ||
| 308 | case 'S': | ||
| 309 | case 's': | ||
| 310 | opt |= MY_OPT_STR; | ||
| 311 | bases++; | ||
| 312 | break; | ||
| 313 | |||
| 298 | default: | 314 | default: |
| 299 | fprintf(stderr, "%s: unknown order option -- %c\n", PROGRAM_NAME, order[x]); | 315 | fprintf(stderr, "%s: unknown order option -- %c\n", PROGRAM_NAME, order[x]); |
| 300 | fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME); | 316 | fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME); |
| @@ -303,7 +319,7 @@ int main(int argc, char * argv[]) | |||
| 303 | }; | 319 | }; |
| 304 | }; | 320 | }; |
| 305 | if (!(order)) | 321 | if (!(order)) |
| 306 | order = "abxod"; | 322 | order = ((opt & MY_OPT_STR)) ? (((opt & MY_OPT_ASCII)) ? "sabxod" : "sbxod") : "abxod"; |
| 307 | 323 | ||
| 308 | if (!(opt & (MY_OPT_BIN|MY_OPT_DEC|MY_OPT_HEX|MY_OPT_OCT|MY_OPT_ASCII))) | 324 | if (!(opt & (MY_OPT_BIN|MY_OPT_DEC|MY_OPT_HEX|MY_OPT_OCT|MY_OPT_ASCII))) |
| 309 | { | 325 | { |
| @@ -344,7 +360,7 @@ int main(int argc, char * argv[]) | |||
| 344 | optbase = 10; | 360 | optbase = 10; |
| 345 | for(y = 0; ( ((uint32_t)y) < strlen(argv[x]) && (optbase == 10) ); y++) | 361 | for(y = 0; ( ((uint32_t)y) < strlen(argv[x]) && (optbase == 10) ); y++) |
| 346 | if ((argv[x][y] < '0') || (argv[x][y] > '9')) | 362 | if ((argv[x][y] < '0') || (argv[x][y] > '9')) |
| 347 | optbase = -1; | 363 | optbase = 128; |
| 348 | }; | 364 | }; |
| 349 | }; | 365 | }; |
| 350 | 366 | ||
| @@ -352,10 +368,25 @@ int main(int argc, char * argv[]) | |||
| 352 | switch(optbase) | 368 | switch(optbase) |
| 353 | { | 369 | { |
| 354 | case -1: | 370 | case -1: |
| 355 | for(y = 0; (y < (int)strlen(argv[x])); y++) | 371 | for(y = 0; (y < strlen(argv[x])); y++) |
| 356 | my_print(opt, (intmax_t)argv[x][y], order); | 372 | my_print(opt, (intmax_t)argv[x][y], order); |
| 357 | break; | 373 | break; |
| 358 | 374 | ||
| 375 | case 128: | ||
| 376 | for(y = 0; (y < strlen(argv[x])); y++) | ||
| 377 | { | ||
| 378 | if ((y % sizeof(uintmax_t)) == 0) | ||
| 379 | { | ||
| 380 | if (y != 0) | ||
| 381 | my_print(opt, num, order); | ||
| 382 | num = 0; | ||
| 383 | }; | ||
| 384 | num <<= 8; | ||
| 385 | num |= argv[x][y]; | ||
| 386 | }; | ||
| 387 | my_print(opt, num, order); | ||
| 388 | break; | ||
| 389 | |||
| 359 | default: | 390 | default: |
| 360 | num = strtoumax(argv[x], &endptr, optbase); | 391 | num = strtoumax(argv[x], &endptr, optbase); |
| 361 | if (endptr[0] != '\0') | 392 | if (endptr[0] != '\0') |
| @@ -382,11 +413,13 @@ void my_print(int32_t opt, uintmax_t num, const char * order) | |||
| 382 | { | 413 | { |
| 383 | char buff[56]; | 414 | char buff[56]; |
| 384 | unsigned pos; | 415 | unsigned pos; |
| 385 | intmax_t y; | 416 | char c; |
| 386 | intmax_t z; | 417 | uintmax_t y; |
| 418 | uintmax_t z; | ||
| 387 | uintmax_t len; | 419 | uintmax_t len; |
| 388 | uintmax_t max; | 420 | uintmax_t max; |
| 389 | uintmax_t byte; | 421 | uintmax_t byte; |
| 422 | uintmax_t mask; | ||
| 390 | 423 | ||
| 391 | len = 0; | 424 | len = 0; |
| 392 | 425 | ||
| @@ -414,6 +447,35 @@ void my_print(int32_t opt, uintmax_t num, const char * order) | |||
| 414 | len = printf("'%c'", (((num >= 32) && (num <= 126)) ? (char)num : '.')); | 447 | len = printf("'%c'", (((num >= 32) && (num <= 126)) ? (char)num : '.')); |
| 415 | break; | 448 | break; |
| 416 | 449 | ||
| 450 | // print ASCII string value | ||
| 451 | case 'S': | ||
| 452 | case 's': | ||
| 453 | if (!(opt & MY_OPT_STR)) | ||
| 454 | break; | ||
| 455 | if (len) | ||
| 456 | printf((opt & MY_OPT_SPACE) ? ", " : ","); | ||
| 457 | if ((opt & MY_OPT_HEADER)) | ||
| 458 | { | ||
| 459 | len = printf("%*s", (int)((!(opt & MY_OPT_SPACE)) ? 0 : (max+2)), "String"); | ||
| 460 | break; | ||
| 461 | }; | ||
| 462 | mask = ~((uintmax_t)0); | ||
| 463 | for(y = 2; ((mask > 0) && ((mask & num))); y++) | ||
| 464 | mask <<= 8; | ||
| 465 | y = (y < (max+2)) ? (max+2) : y; | ||
| 466 | byte = num; | ||
| 467 | buff[y] = '\0'; | ||
| 468 | buff[0] = '"'; | ||
| 469 | buff[y-1] = '"'; | ||
| 470 | for(z = y-1; (z > 1); z--) | ||
| 471 | { | ||
| 472 | c = byte & 0xff; | ||
| 473 | buff[z-1] = ((c >= 32) && (c <= 126)) ? c : '.'; | ||
| 474 | byte >>= 8; | ||
| 475 | }; | ||
| 476 | len = printf("%*s", (int)(max+2), buff); | ||
| 477 | break; | ||
| 478 | |||
| 417 | // print binary value | 479 | // print binary value |
| 418 | case 'B': | 480 | case 'B': |
| 419 | case 'b': | 481 | case 'b': |
| @@ -521,6 +583,8 @@ void my_usage() | |||
| 521 | printf(" -q suppress column names\n"); | 583 | printf(" -q suppress column names\n"); |
| 522 | printf(" -R display binary in little endian byte order\n"); | 584 | printf(" -R display binary in little endian byte order\n"); |
| 523 | printf(" -r display binary in little endian bit nad byte order\n"); | 585 | printf(" -r display binary in little endian bit nad byte order\n"); |
| 586 | printf(" -S enable ASCII string output\n"); | ||
| 587 | printf(" -s assume ASCII string notation for input\n"); | ||
| 524 | printf(" -w display output without spacing\n"); | 588 | printf(" -w display output without spacing\n"); |
| 525 | printf(" -X enable hexadecimal output\n"); | 589 | printf(" -X enable hexadecimal output\n"); |
| 526 | printf(" -x assume hexadecimal notation for input\n"); | 590 | printf(" -x assume hexadecimal notation for input\n"); |
