Mercurial > hg > toybox
annotate toys/posix/printf.c @ 1667:aa6487c2c5f8 draft
fix typo in printf
author | Elliott Hughes <enh@google.com> |
---|---|
date | Tue, 20 Jan 2015 15:52:41 -0600 |
parents | 971df24b458b |
children | 848969327d77 |
rev | line source |
---|---|
1256
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
1 /* printf.c - Format and Print the data. |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
2 * |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
3 * Copyright 2014 Sandeep Sharma <sandeep.jack2756@gmail.com> |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
4 * Copyright 2014 Kyungwan Han <asura321@gmail.com> |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
5 * |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
6 * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html |
1651
114fb916e04e
One more bugfix for printf.c, with test suite entry. (Make %-3d etc work.)
Rob Landley <rob@landley.net>
parents:
1650
diff
changeset
|
7 * |
114fb916e04e
One more bugfix for printf.c, with test suite entry. (Make %-3d etc work.)
Rob Landley <rob@landley.net>
parents:
1650
diff
changeset
|
8 * todo: *m$ ala printf("%1$d:%2$.*3$d:%4$.*3$d\n", hour, min, precision, sec); |
1256
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
9 |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
10 USE_PRINTF(NEWTOY(printf, "<1", TOYFLAG_USR|TOYFLAG_BIN)) |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
11 |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
12 config PRINTF |
1643 | 13 bool "printf" |
1652 | 14 default y |
1643 | 15 help |
16 usage: printf FORMAT [ARGUMENT...] | |
1256
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
17 |
1643 | 18 Format and print ARGUMENT(s) according to FORMAT, using C printf syntax |
1647
35c035b7e3e0
More printf cleanup, and test suite entries.
Rob Landley <rob@landley.net>
parents:
1645
diff
changeset
|
19 (% escapes for cdeEfgGiosuxX, \ escapes for abefnrtv0 or \OCTAL or \xHEX). |
1256
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
20 */ |
1643 | 21 |
1256
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
22 #define FOR_printf |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
23 #include "toys.h" |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
24 |
1667 | 25 // Detect matching character (return true/false) and advance pointer if match. |
1645
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
26 static int eat(char **s, char c) |
1256
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
27 { |
1645
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
28 int x = (**s == c); |
1643 | 29 |
1645
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
30 if (x) ++*s; |
1643 | 31 |
1645
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
32 return x; |
1256
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
33 } |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
34 |
1645
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
35 // Parse escape sequences. |
1256
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
36 static int handle_slash(char **esc_val) |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
37 { |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
38 char *ptr = *esc_val; |
1649
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
39 int len, base = 0; |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
40 unsigned result = 0, num; |
1645
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
41 |
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
42 if (*ptr == 'c') xexit(); |
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
43 |
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
44 // 0x12 hex escapes have 1-2 digits, \123 octal escapes have 1-3 digits. |
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
45 if (eat(&ptr, 'x')) base = 16; |
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
46 else if (*ptr >= '0' && *ptr <= '8') base = 8; |
1649
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
47 len = (char []){0,3,2}[base/8]; |
1643 | 48 |
1645
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
49 // Not a hex or octal escape? (This catches trailing \) |
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
50 if (!len) { |
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
51 if (!(result = unescape(*ptr))) result = '\\'; |
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
52 else ++*esc_val; |
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
53 |
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
54 return result; |
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
55 } |
1256
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
56 |
1645
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
57 while (len) { |
1649
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
58 num = tolower(*ptr) - '0'; |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
59 if (num >= 'a'-'0') num += '0'-'a'+10; |
1256
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
60 if (num >= base) { |
1645
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
61 // Don't parse invalid hex value ala "\xvd", print it verbatim |
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
62 if (base == 16 && len == 2) { |
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
63 ptr--; |
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
64 result = '\\'; |
1256
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
65 } |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
66 break; |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
67 } |
1645
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
68 result = (result*base)+num; |
1256
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
69 ptr++; |
1645
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
70 len--; |
1256
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
71 } |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
72 *esc_val = ptr; |
1645
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
73 |
1649
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
74 return result; |
1256
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
75 } |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
76 |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
77 void printf_main(void) |
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
78 { |
1649
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
79 char **arg = toys.optargs+1; |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
80 |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
81 // Repeat format until arguments consumed |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
82 for (;;) { |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
83 int seen = 0; |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
84 char *f = *toys.optargs; |
1645
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
85 |
1649
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
86 // Loop through characters in format |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
87 while (*f) { |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
88 if (eat(&f, '\\')) putchar(handle_slash(&f)); |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
89 else if (!eat(&f, '%') || *f == '%') putchar(*f++); |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
90 |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
91 // Handle %escape |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
92 else { |
1650 | 93 char c, *end = 0, *aa, *to = toybuf; |
94 int wp[] = {0,-1}, i; | |
1256
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
95 |
1649
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
96 // Parse width.precision between % and type indicator. |
1650 | 97 *to++ = '%'; |
1651
114fb916e04e
One more bugfix for printf.c, with test suite entry. (Make %-3d etc work.)
Rob Landley <rob@landley.net>
parents:
1650
diff
changeset
|
98 while (strchr("-+# '0", *f) && (to-toybuf)<10) *to++ = *f++; |
1649
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
99 for (i=0; i<2; i++) { |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
100 if (eat(&f, '*')) { |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
101 if (*arg) wp[i] = atolx(*arg++); |
1650 | 102 } else while (*f >= '0' && *f <= '9') { |
103 if (wp[i]<0) wp[i] = 0; | |
104 wp[i] = (wp[i]*10)+(*f++)-'0'; | |
105 } | |
1649
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
106 if (!eat(&f, '.')) break; |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
107 } |
1650 | 108 c = *f++; |
109 seen = sprintf(to, "*.*%c", c);; | |
1649
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
110 errno = 0; |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
111 aa = *arg ? *arg++ : ""; |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
112 |
1650 | 113 // Output %esc using parsed format string |
1649
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
114 if (c == 'b') { |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
115 while (*aa) putchar(eat(&aa, '\\') ? handle_slash(&aa) : *aa++); |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
116 |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
117 continue; |
1650 | 118 } else if (c == 'c') printf(toybuf, wp[0], wp[1], *aa); |
119 else if (c == 's') printf(toybuf, wp[0], wp[1], aa); | |
1649
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
120 else if (strchr("diouxX", c)) { |
1650 | 121 long ll; |
122 | |
123 if (*aa == '\'' || *aa == '"') ll = aa[1]; | |
124 else ll = strtoll(aa, &end, 0); | |
125 | |
1651
114fb916e04e
One more bugfix for printf.c, with test suite entry. (Make %-3d etc work.)
Rob Landley <rob@landley.net>
parents:
1650
diff
changeset
|
126 sprintf(to, "*.*ll%c", c); |
1650 | 127 printf(toybuf, wp[0], wp[1], ll); |
128 } else if (strchr("feEgG", c)) { | |
129 long double ld = strtold(aa, &end); | |
130 | |
131 sprintf(to, "*.*L%c", c); | |
132 printf(toybuf, wp[0], wp[1], ld); | |
133 } else error_exit("bad %%%c@%ld", c, f-*toys.optargs); | |
1649
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
134 |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
135 if (end && (errno || *end)) perror_msg("bad %%%c %s", c, aa); |
1645
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
136 } |
1649
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
137 } |
1645
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
138 |
1649
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
139 // Posix says to keep looping through format until we consume all args. |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
140 // This only works if the format actually consumed at least one arg. |
66bb2847993d
More half-finished cleanup of printf.c, and more test suite entries.
Rob Landley <rob@landley.net>
parents:
1647
diff
changeset
|
141 if (!seen || !*arg) break; |
1645
2ffee259f519
Another cleanup pass on printf.
Rob Landley <rob@landley.net>
parents:
1643
diff
changeset
|
142 } |
1256
2fe64bc16a61
An implementation of __printf__ is attached.
Ashwini Sharma <ak.ashwini1981@gmail.com>
parents:
diff
changeset
|
143 } |