diff options
Diffstat (limited to 'toys/pending/printf.c')
-rw-r--r-- | toys/pending/printf.c | 269 |
1 files changed, 0 insertions, 269 deletions
diff --git a/toys/pending/printf.c b/toys/pending/printf.c deleted file mode 100644 index 0970c8c..0000000 --- a/toys/pending/printf.c +++ /dev/null @@ -1,269 +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 - -USE_PRINTF(NEWTOY(printf, "<1", TOYFLAG_USR|TOYFLAG_BIN)) - -config PRINTF - bool "printf" - default n - help - usage: printf Format [Arguments..] - - Format and print ARGUMENT(s) according to FORMAT. - Format is 'C' control output as 'C' printf. -*/ -#define FOR_printf -#include "toys.h" - -GLOBALS( - char *hv_w; - char *hv_p; - int encountered; -) - -// Calculate width and precision from format string -static int get_w_p() -{ - char *ptr, *str = *toys.optargs; - - errno = 0; - if (*str == '-') str++; - long value = strtol(str, &ptr, 10); - if (errno || (ptr && (*ptr != '\0' || ptr == str))) - perror_msg("Invalid num %s", *toys.optargs); - if (*--str == '-') return (int)(-1 * value); - return value; -} - -// Add ll and L to Interger and floating point formats respectively. -static char *get_format(char *f) -{ - int len = strlen(f); - char last = f[--len], *post = ""; - - f[len] = '\0'; - if (strchr("diouxX", last)) post = "ll"; // add ll to integer modifier. - else if (strchr("feEgG", last)) post = "L"; // add L to float modifier. - return xmprintf("%s%s%c", f, post, last); -} - -// Print arguments with corresponding conversion and width and precision. -static void print(char *fmt, int w, int p, int l) -{ - char *ptr = (fmt+l-1), *ep = NULL, *format = NULL; - long long val; - long double dval; - - errno = 0; - switch (*ptr) { - case 'd': /*FALL_THROUGH*/ - case 'i': /*FALL_THROUGH*/ - case 'o': /*FALL_THROUGH*/ - case 'u': /*FALL_THROUGH*/ - case 'x': /*FALL_THROUGH*/ - case 'X': - if (!*toys.optargs) val = 0; - else { - if (**toys.optargs == '\'' || **toys.optargs == '"') - val = *((*toys.optargs) + 1); - else { - val = strtoll(*toys.optargs, &ep, 0); - if (errno || (ep && (*ep != '\0' || ep == *toys.optargs))) { - perror_msg("Invalid num %s", *toys.optargs); - val = 0; - } - } - } - format = get_format(fmt); - TT.hv_w ? (TT.hv_p ? printf(format, w, p, val) : printf(format, w, val)) - : (TT.hv_p ? printf(format, p, val) : printf(format, val)); - break; - case 'g': /*FALL_THROUGH*/ - case 'e': /*FALL_THROUGH*/ - case 'E': /*FALL_THROUGH*/ - case 'G': /*FALL_THROUGH*/ - case 'f': - if (*toys.optargs) { - dval = strtold(*toys.optargs, &ep); - if (errno || (ep && (*ep != '\0' || ep == *toys.optargs))) { - perror_msg("Invalid num %s", *toys.optargs); - dval = 0; - } - } else dval = 0; - format = get_format(fmt); - TT.hv_w ? (TT.hv_p ? printf(format, w, p, dval):printf(format, w, dval)) - : (TT.hv_p ? printf(format, p, dval) : printf(format, dval)); - break; - case 's': - { - char *str = (*toys.optargs ? *toys.optargs : ""); - TT.hv_w ? (TT.hv_p ? printf(fmt,w,p,str): printf(fmt, w, str)) - : (TT.hv_p ? printf(fmt, p, str) : printf(fmt, str)); - } - break; - case 'c': - printf(fmt, (*toys.optargs ? **toys.optargs : '\0')); - break; - } - if (format) free(format); -} - -// Handle the escape sequences. -static int handle_slash(char **esc_val) -{ - char *ptr = *esc_val; - int esc_length = 0; - unsigned base = 0, num = 0, result = 0, count = 0; - - /* - * Hex escape sequence have only 1 or 2 digits, xHH. Oct escape sequence - * have 1,2 or 3 digits, xHHH. Leading "0" (\0HHH) we are ignoring. - */ - if (*ptr == 'x') { - ptr++; - esc_length++; - base = 16; - } else if (isdigit(*ptr)) base = 8; - - while (esc_length < 3 && base) { - num = tolower(*ptr) - '0'; - if (num > 10) num += ('0' - 'a' + 10); - if (num >= base) { - if (base == 16) { - esc_length--; - if (!esc_length) {// Invalid hex value eg. /xvd, print as it is /xvd - result = '\\'; - ptr--; - } - } - break; - } - esc_length++; - count = result = (count * base) + num; - ptr++; - } - if (base) { - ptr--; - *esc_val = ptr; - return (char)result; - } else { - switch (*ptr) { - case 'n': result = '\n'; break; - case 't': result = '\t'; break; - case 'e': result = (char)27; break; - case 'b': result = '\b'; break; - case 'a': result = '\a'; break; - case 'f': result = '\f'; break; - case 'v': result = '\v'; break; - case 'r': result = '\r'; break; - case '\\': result = '\\'; break; - default : - result = '\\'; - ptr--; // Let pointer pointing to / we will increment after returning. - break; - } - } - *esc_val = ptr; - return (char)result; -} - -// Handle "%b" option with '\' interpreted. -static void print_esc_str(char *str) -{ - for (; *str; str++) { - if (*str == '\\') { - str++; - xputc(handle_slash(&str)); //print corresponding char - } else xputc(*str); - } -} - -// Prase the format string and print. -static void parse_print(char *f) -{ - char *start, *p, format_specifiers[] = "diouxXfeEgGcs"; - int len = 0, width = 0, prec = 0; - - while (*f) { - switch (*f) { - case '%': - start = f++; - len++; - if (*f == '%') { - xputc('%'); - break; - } - if (*f == 'b') { - if (*toys.optargs) { - print_esc_str(*toys.optargs++); - TT.encountered = 1; - } else print_esc_str(""); - break; - } - if (strchr("-+# ", *f)) f++, len++; - if (*f == '*') { - f++, len++; - if (*toys.optargs) { - width = get_w_p(); - toys.optargs++; - } - } else { - while (isdigit(*f)) f++, len++; - } - if (*f == '.') { - f++, len++; - if (*f == '*') { - f++, len++; - if (*toys.optargs) { - prec = get_w_p(); - toys.optargs++; - } - } else { - while (isdigit(*f)) f++, len++; - } - } - if (!(p = strchr(format_specifiers, *f))) - perror_exit("Missing OR Invalid format specifier"); - else { - len++; - TT.hv_p = strstr(start, ".*"); - TT.hv_w = strchr(start, '*'); - //pitfall: handle diff b/w * and .* - if ((TT.hv_w-1) == TT.hv_p) TT.hv_w = NULL; - memcpy((p = xzalloc(len+1)), start, len); - print(p, width, prec, len); - if (*toys.optargs) toys.optargs++; - free(p); - p = NULL; - } - TT.encountered = 1; - break; - case '\\': - if (f[1]) { - if (*++f == 'c') exit(0); //Got '\c', so no further output - xputc(handle_slash(&f)); - } else xputc(*f); - break; - default: - xputc(*f); - break; - } - f++; - len = 0; - } -} - -void printf_main(void) -{ - char *format = *toys.optargs++; - - TT.encountered = 0; - parse_print(format); //printf acc. to format. - //Re-use FORMAT arg as necessary to convert all given ARGS. - while (*toys.optargs && TT.encountered) parse_print(format); - xflush(); -} |