Mercurial > hg > toybox
changeset 1652:971df24b458b draft
Promote printf.
author | Rob Landley <rob@landley.net> |
---|---|
date | Sun, 11 Jan 2015 10:17:58 -0600 |
parents | 114fb916e04e |
children | 58cb2d7bd461 |
files | toys/pending/printf.c toys/posix/printf.c |
diffstat | 2 files changed, 143 insertions(+), 143 deletions(-) [+] |
line wrap: on
line diff
--- a/toys/pending/printf.c Sun Jan 11 10:16:38 2015 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -/* printf.c - Format and Print the data. - * - * Copyright 2014 Sandeep Sharma <sandeep.jack2756@gmail.com> - * Copyright 2014 Kyungwan Han <asura321@gmail.com> - * - * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html - * - * todo: *m$ ala printf("%1$d:%2$.*3$d:%4$.*3$d\n", hour, min, precision, sec); - -USE_PRINTF(NEWTOY(printf, "<1", TOYFLAG_USR|TOYFLAG_BIN)) - -config PRINTF - bool "printf" - default n - help - usage: printf FORMAT [ARGUMENT...] - - Format and print ARGUMENT(s) according to FORMAT, using C printf syntax - (% escapes for cdeEfgGiosuxX, \ escapes for abefnrtv0 or \OCTAL or \xHEX). -*/ - -#define FOR_printf -#include "toys.h" - -// Detect matching character (return true/valse) and advance pointer if match. -static int eat(char **s, char c) -{ - int x = (**s == c); - - if (x) ++*s; - - return x; -} - -// Parse escape sequences. -static int handle_slash(char **esc_val) -{ - char *ptr = *esc_val; - int len, base = 0; - unsigned result = 0, num; - - if (*ptr == 'c') xexit(); - - // 0x12 hex escapes have 1-2 digits, \123 octal escapes have 1-3 digits. - if (eat(&ptr, 'x')) base = 16; - else if (*ptr >= '0' && *ptr <= '8') base = 8; - len = (char []){0,3,2}[base/8]; - - // Not a hex or octal escape? (This catches trailing \) - if (!len) { - if (!(result = unescape(*ptr))) result = '\\'; - else ++*esc_val; - - return result; - } - - while (len) { - num = tolower(*ptr) - '0'; - if (num >= 'a'-'0') num += '0'-'a'+10; - if (num >= base) { - // Don't parse invalid hex value ala "\xvd", print it verbatim - if (base == 16 && len == 2) { - ptr--; - result = '\\'; - } - break; - } - result = (result*base)+num; - ptr++; - len--; - } - *esc_val = ptr; - - return result; -} - -void printf_main(void) -{ - char **arg = toys.optargs+1; - - // Repeat format until arguments consumed - for (;;) { - int seen = 0; - char *f = *toys.optargs; - - // Loop through characters in format - while (*f) { - if (eat(&f, '\\')) putchar(handle_slash(&f)); - else if (!eat(&f, '%') || *f == '%') putchar(*f++); - - // Handle %escape - else { - char c, *end = 0, *aa, *to = toybuf; - int wp[] = {0,-1}, i; - - // Parse width.precision between % and type indicator. - *to++ = '%'; - while (strchr("-+# '0", *f) && (to-toybuf)<10) *to++ = *f++; - for (i=0; i<2; i++) { - if (eat(&f, '*')) { - if (*arg) wp[i] = atolx(*arg++); - } else while (*f >= '0' && *f <= '9') { - if (wp[i]<0) wp[i] = 0; - wp[i] = (wp[i]*10)+(*f++)-'0'; - } - if (!eat(&f, '.')) break; - } - c = *f++; - seen = sprintf(to, "*.*%c", c);; - errno = 0; - aa = *arg ? *arg++ : ""; - - // Output %esc using parsed format string - if (c == 'b') { - while (*aa) putchar(eat(&aa, '\\') ? handle_slash(&aa) : *aa++); - - continue; - } else if (c == 'c') printf(toybuf, wp[0], wp[1], *aa); - else if (c == 's') printf(toybuf, wp[0], wp[1], aa); - else if (strchr("diouxX", c)) { - long ll; - - if (*aa == '\'' || *aa == '"') ll = aa[1]; - else ll = strtoll(aa, &end, 0); - - sprintf(to, "*.*ll%c", c); - printf(toybuf, wp[0], wp[1], ll); - } else if (strchr("feEgG", c)) { - long double ld = strtold(aa, &end); - - sprintf(to, "*.*L%c", c); - printf(toybuf, wp[0], wp[1], ld); - } else error_exit("bad %%%c@%ld", c, f-*toys.optargs); - - if (end && (errno || *end)) perror_msg("bad %%%c %s", c, aa); - } - } - - // Posix says to keep looping through format until we consume all args. - // This only works if the format actually consumed at least one arg. - if (!seen || !*arg) break; - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toys/posix/printf.c Sun Jan 11 10:17:58 2015 -0600 @@ -0,0 +1,143 @@ +/* printf.c - Format and Print the data. + * + * Copyright 2014 Sandeep Sharma <sandeep.jack2756@gmail.com> + * Copyright 2014 Kyungwan Han <asura321@gmail.com> + * + * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html + * + * todo: *m$ ala printf("%1$d:%2$.*3$d:%4$.*3$d\n", hour, min, precision, sec); + +USE_PRINTF(NEWTOY(printf, "<1", TOYFLAG_USR|TOYFLAG_BIN)) + +config PRINTF + bool "printf" + default y + help + usage: printf FORMAT [ARGUMENT...] + + Format and print ARGUMENT(s) according to FORMAT, using C printf syntax + (% escapes for cdeEfgGiosuxX, \ escapes for abefnrtv0 or \OCTAL or \xHEX). +*/ + +#define FOR_printf +#include "toys.h" + +// Detect matching character (return true/valse) and advance pointer if match. +static int eat(char **s, char c) +{ + int x = (**s == c); + + if (x) ++*s; + + return x; +} + +// Parse escape sequences. +static int handle_slash(char **esc_val) +{ + char *ptr = *esc_val; + int len, base = 0; + unsigned result = 0, num; + + if (*ptr == 'c') xexit(); + + // 0x12 hex escapes have 1-2 digits, \123 octal escapes have 1-3 digits. + if (eat(&ptr, 'x')) base = 16; + else if (*ptr >= '0' && *ptr <= '8') base = 8; + len = (char []){0,3,2}[base/8]; + + // Not a hex or octal escape? (This catches trailing \) + if (!len) { + if (!(result = unescape(*ptr))) result = '\\'; + else ++*esc_val; + + return result; + } + + while (len) { + num = tolower(*ptr) - '0'; + if (num >= 'a'-'0') num += '0'-'a'+10; + if (num >= base) { + // Don't parse invalid hex value ala "\xvd", print it verbatim + if (base == 16 && len == 2) { + ptr--; + result = '\\'; + } + break; + } + result = (result*base)+num; + ptr++; + len--; + } + *esc_val = ptr; + + return result; +} + +void printf_main(void) +{ + char **arg = toys.optargs+1; + + // Repeat format until arguments consumed + for (;;) { + int seen = 0; + char *f = *toys.optargs; + + // Loop through characters in format + while (*f) { + if (eat(&f, '\\')) putchar(handle_slash(&f)); + else if (!eat(&f, '%') || *f == '%') putchar(*f++); + + // Handle %escape + else { + char c, *end = 0, *aa, *to = toybuf; + int wp[] = {0,-1}, i; + + // Parse width.precision between % and type indicator. + *to++ = '%'; + while (strchr("-+# '0", *f) && (to-toybuf)<10) *to++ = *f++; + for (i=0; i<2; i++) { + if (eat(&f, '*')) { + if (*arg) wp[i] = atolx(*arg++); + } else while (*f >= '0' && *f <= '9') { + if (wp[i]<0) wp[i] = 0; + wp[i] = (wp[i]*10)+(*f++)-'0'; + } + if (!eat(&f, '.')) break; + } + c = *f++; + seen = sprintf(to, "*.*%c", c);; + errno = 0; + aa = *arg ? *arg++ : ""; + + // Output %esc using parsed format string + if (c == 'b') { + while (*aa) putchar(eat(&aa, '\\') ? handle_slash(&aa) : *aa++); + + continue; + } else if (c == 'c') printf(toybuf, wp[0], wp[1], *aa); + else if (c == 's') printf(toybuf, wp[0], wp[1], aa); + else if (strchr("diouxX", c)) { + long ll; + + if (*aa == '\'' || *aa == '"') ll = aa[1]; + else ll = strtoll(aa, &end, 0); + + sprintf(to, "*.*ll%c", c); + printf(toybuf, wp[0], wp[1], ll); + } else if (strchr("feEgG", c)) { + long double ld = strtold(aa, &end); + + sprintf(to, "*.*L%c", c); + printf(toybuf, wp[0], wp[1], ld); + } else error_exit("bad %%%c@%ld", c, f-*toys.optargs); + + if (end && (errno || *end)) perror_msg("bad %%%c %s", c, aa); + } + } + + // Posix says to keep looping through format until we consume all args. + // This only works if the format actually consumed at least one arg. + if (!seen || !*arg) break; + } +}