3
0

printf.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /* vi: set sw=4 ts=4: */
  2. /* printf - format and print data
  3. Copyright 1999 Dave Cinege
  4. Portions copyright (C) 1990-1996 Free Software Foundation, Inc.
  5. Licensed under GPL v2 or later, see file LICENSE in this tarball for details.
  6. */
  7. /* Usage: printf format [argument...]
  8. A front end to the printf function that lets it be used from the shell.
  9. Backslash escapes:
  10. \" = double quote
  11. \\ = backslash
  12. \a = alert (bell)
  13. \b = backspace
  14. \c = produce no further output
  15. \f = form feed
  16. \n = new line
  17. \r = carriage return
  18. \t = horizontal tab
  19. \v = vertical tab
  20. \0ooo = octal number (ooo is 0 to 3 digits)
  21. \xhhh = hexadecimal number (hhh is 1 to 3 digits)
  22. Additional directive:
  23. %b = print an argument string, interpreting backslash escapes
  24. The 'format' argument is re-used as many times as necessary
  25. to convert all of the given arguments.
  26. David MacKenzie <djm@gnu.ai.mit.edu>
  27. */
  28. // 19990508 Busy Boxed! Dave Cinege
  29. #include "libbb.h"
  30. /* A note on bad input: neither bash 3.2 nor coreutils 6.10 stop on it.
  31. * They report it:
  32. * bash: printf: XXX: invalid number
  33. * printf: XXX: expected a numeric value
  34. * bash: printf: 123XXX: invalid number
  35. * printf: 123XXX: value not completely converted
  36. * but then they use 0 (or partially converted numeric prefix) as a value
  37. * and continue. They exit with 1 in this case.
  38. * Both accept insane field width/precision (e.g. %9999999999.9999999999d).
  39. * Both print error message and assume 0 if %*.*f width/precision is "bad"
  40. * (but negative numbers are not "bad").
  41. * Both accept negative numbers for %u specifier.
  42. *
  43. * We try to be compatible. We are not compatible here:
  44. * - we do not accept -NUM for %u
  45. * - exit code is 0 even if "invalid number" was seen (FIXME)
  46. * See "if (errno)" checks in the code below.
  47. */
  48. typedef void FAST_FUNC (*converter)(const char *arg, void *result);
  49. static int multiconvert(const char *arg, void *result, converter convert)
  50. {
  51. if (*arg == '"' || *arg == '\'') {
  52. arg = utoa((unsigned char)arg[1]);
  53. }
  54. errno = 0;
  55. convert(arg, result);
  56. if (errno) {
  57. bb_error_msg("%s: invalid number", arg);
  58. return 1;
  59. }
  60. return 0;
  61. }
  62. static void FAST_FUNC conv_strtoul(const char *arg, void *result)
  63. {
  64. *(unsigned long*)result = bb_strtoul(arg, NULL, 0);
  65. }
  66. static void FAST_FUNC conv_strtol(const char *arg, void *result)
  67. {
  68. *(long*)result = bb_strtol(arg, NULL, 0);
  69. }
  70. static void FAST_FUNC conv_strtod(const char *arg, void *result)
  71. {
  72. char *end;
  73. /* Well, this one allows leading whitespace... so what? */
  74. /* What I like much less is that "-" accepted too! :( */
  75. *(double*)result = strtod(arg, &end);
  76. if (end[0]) {
  77. errno = ERANGE;
  78. *(double*)result = 0;
  79. }
  80. }
  81. /* Callers should check errno to detect errors */
  82. static unsigned long my_xstrtoul(const char *arg)
  83. {
  84. unsigned long result;
  85. if (multiconvert(arg, &result, conv_strtoul))
  86. result = 0;
  87. return result;
  88. }
  89. static long my_xstrtol(const char *arg)
  90. {
  91. long result;
  92. if (multiconvert(arg, &result, conv_strtol))
  93. result = 0;
  94. return result;
  95. }
  96. static double my_xstrtod(const char *arg)
  97. {
  98. double result;
  99. multiconvert(arg, &result, conv_strtod);
  100. return result;
  101. }
  102. static void print_esc_string(char *str)
  103. {
  104. while (*str) {
  105. if (*str == '\\') {
  106. str++;
  107. bb_putchar(bb_process_escape_sequence((const char **)&str));
  108. } else {
  109. bb_putchar(*str);
  110. str++;
  111. }
  112. }
  113. }
  114. static void print_direc(char *format, unsigned fmt_length,
  115. int field_width, int precision,
  116. const char *argument)
  117. {
  118. long lv;
  119. double dv;
  120. char saved;
  121. char *have_prec, *have_width;
  122. saved = format[fmt_length];
  123. format[fmt_length] = '\0';
  124. have_prec = strstr(format, ".*");
  125. have_width = strchr(format, '*');
  126. if (have_width - 1 == have_prec)
  127. have_width = NULL;
  128. switch (format[fmt_length - 1]) {
  129. case 'c':
  130. printf(format, *argument);
  131. break;
  132. case 'd':
  133. case 'i':
  134. lv = my_xstrtol(argument);
  135. print_long:
  136. /* if (errno) return; - see comment at the top */
  137. if (!have_width) {
  138. if (!have_prec)
  139. printf(format, lv);
  140. else
  141. printf(format, precision, lv);
  142. } else {
  143. if (!have_prec)
  144. printf(format, field_width, lv);
  145. else
  146. printf(format, field_width, precision, lv);
  147. }
  148. break;
  149. case 'o':
  150. case 'u':
  151. case 'x':
  152. case 'X':
  153. lv = my_xstrtoul(argument);
  154. /* cheat: unsigned long and long have same width, so... */
  155. goto print_long;
  156. case 's':
  157. /* Are char* and long the same? (true for most arches) */
  158. if (sizeof(argument) == sizeof(lv)) {
  159. lv = (long)(ptrdiff_t)argument;
  160. goto print_long;
  161. } else { /* Hope compiler will optimize it out */
  162. if (!have_width) {
  163. if (!have_prec)
  164. printf(format, argument);
  165. else
  166. printf(format, precision, argument);
  167. } else {
  168. if (!have_prec)
  169. printf(format, field_width, argument);
  170. else
  171. printf(format, field_width, precision, argument);
  172. }
  173. break;
  174. }
  175. case 'f':
  176. case 'e':
  177. case 'E':
  178. case 'g':
  179. case 'G':
  180. dv = my_xstrtod(argument);
  181. /* if (errno) return; */
  182. if (!have_width) {
  183. if (!have_prec)
  184. printf(format, dv);
  185. else
  186. printf(format, precision, dv);
  187. } else {
  188. if (!have_prec)
  189. printf(format, field_width, dv);
  190. else
  191. printf(format, field_width, precision, dv);
  192. }
  193. break;
  194. } /* switch */
  195. format[fmt_length] = saved;
  196. }
  197. /* Handle params for "%*.*f". Negative numbers are ok (compat). */
  198. static int get_width_prec(const char *str)
  199. {
  200. int v = bb_strtoi(str, NULL, 10);
  201. if (errno) {
  202. bb_error_msg("%s: invalid number", str);
  203. v = 0;
  204. }
  205. return v;
  206. }
  207. /* Print the text in FORMAT, using ARGV for arguments to any '%' directives.
  208. Return advanced ARGV. */
  209. static char **print_formatted(char *f, char **argv)
  210. {
  211. char *direc_start; /* Start of % directive. */
  212. unsigned direc_length; /* Length of % directive. */
  213. int field_width; /* Arg to first '*' */
  214. int precision; /* Arg to second '*' */
  215. char **saved_argv = argv;
  216. for (; *f; ++f) {
  217. switch (*f) {
  218. case '%':
  219. direc_start = f++;
  220. direc_length = 1;
  221. field_width = precision = 0;
  222. if (*f == '%') {
  223. bb_putchar('%');
  224. break;
  225. }
  226. if (*f == 'b') {
  227. if (*argv) {
  228. print_esc_string(*argv);
  229. ++argv;
  230. }
  231. break;
  232. }
  233. if (strchr("-+ #", *f)) {
  234. ++f;
  235. ++direc_length;
  236. }
  237. if (*f == '*') {
  238. ++f;
  239. ++direc_length;
  240. if (*argv)
  241. field_width = get_width_prec(*argv++);
  242. } else {
  243. while (isdigit(*f)) {
  244. ++f;
  245. ++direc_length;
  246. }
  247. }
  248. if (*f == '.') {
  249. ++f;
  250. ++direc_length;
  251. if (*f == '*') {
  252. ++f;
  253. ++direc_length;
  254. if (*argv)
  255. precision = get_width_prec(*argv++);
  256. } else {
  257. while (isdigit(*f)) {
  258. ++f;
  259. ++direc_length;
  260. }
  261. }
  262. }
  263. /* Remove size modifiers - "%Ld" would try to printf
  264. * long long, we pass long, and it spews garbage */
  265. if ((*f | 0x20) == 'l' || *f == 'h' || *f == 'z') {
  266. overlapping_strcpy(f, f + 1);
  267. }
  268. //FIXME: actually, the same happens with bare "%d":
  269. //it printfs an int, but we pass long!
  270. //What saves us is that on most arches stack slot
  271. //is pointer-sized -> long-sized -> ints are promoted to longs
  272. // for variadic functions -> printf("%d", int_v) is in reality
  273. // indistinqushable from printf("%d", long_v) ->
  274. // since printf("%d", int_v) works, printf("%d", long_v) has to work.
  275. //But "clean" solution would be to add "l" to d,i,o,x,X.
  276. //Probably makes sense to go all the way to "ll" then.
  277. //Coreutils support long long-sized arguments.
  278. /* needed - try "printf %" without it */
  279. if (!strchr("diouxXfeEgGcs", *f)) {
  280. bb_error_msg("%s: invalid format", direc_start);
  281. /* causes main() to exit with error */
  282. return saved_argv - 1;
  283. }
  284. ++direc_length;
  285. if (*argv) {
  286. print_direc(direc_start, direc_length, field_width,
  287. precision, *argv);
  288. ++argv;
  289. } else {
  290. print_direc(direc_start, direc_length, field_width,
  291. precision, "");
  292. }
  293. /* if (errno) return saved_argv - 1; */
  294. break;
  295. case '\\':
  296. if (*++f == 'c') {
  297. return saved_argv; /* causes main() to exit */
  298. }
  299. bb_putchar(bb_process_escape_sequence((const char **)&f));
  300. f--;
  301. break;
  302. default:
  303. bb_putchar(*f);
  304. }
  305. }
  306. return argv;
  307. }
  308. int printf_main(int argc UNUSED_PARAM, char **argv)
  309. {
  310. char *format;
  311. char **argv2;
  312. /* We must check that stdout is not closed.
  313. * The reason for this is highly non-obvious.
  314. * printf_main is used from shell.
  315. * Shell must correctly handle 'printf "%s" foo'
  316. * if stdout is closed. With stdio, output gets shoveled into
  317. * stdout buffer, and even fflush cannot clear it out. It seems that
  318. * even if libc receives EBADF on write attempts, it feels determined
  319. * to output data no matter what. So it will try later,
  320. * and possibly will clobber future output. Not good. */
  321. // TODO: check fcntl() & O_ACCMODE == O_WRONLY or O_RDWR?
  322. if (fcntl(1, F_GETFL) == -1)
  323. return 1; /* match coreutils 6.10 (sans error msg to stderr) */
  324. //if (dup2(1, 1) != 1) - old way
  325. // return 1;
  326. /* bash builtin errors out on "printf '-%s-\n' foo",
  327. * coreutils-6.9 works. Both work with "printf -- '-%s-\n' foo".
  328. * We will mimic coreutils. */
  329. if (argv[1] && argv[1][0] == '-' && argv[1][1] == '-' && !argv[1][2])
  330. argv++;
  331. if (!argv[1]) {
  332. if (ENABLE_ASH_BUILTIN_PRINTF
  333. && applet_name[0] != 'p'
  334. ) {
  335. bb_error_msg("usage: printf FORMAT [ARGUMENT...]");
  336. return 2; /* bash compat */
  337. }
  338. bb_show_usage();
  339. }
  340. format = argv[1];
  341. argv2 = argv + 2;
  342. do {
  343. argv = argv2;
  344. argv2 = print_formatted(format, argv);
  345. } while (argv2 > argv && *argv2);
  346. /* coreutils compat (bash doesn't do this):
  347. if (*argv)
  348. fprintf(stderr, "excess args ignored");
  349. */
  350. return (argv2 < argv); /* if true, print_formatted errored out */
  351. }