1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#define FOR_printf
23#include "toys.h"
24
25
26static int eat(char **s, char c)
27{
28 int x = (**s == c);
29
30 if (x) ++*s;
31
32 return x;
33}
34
35
36static int handle_slash(char **esc_val, int posix)
37{
38 char *ptr = *esc_val;
39 int len, base = 0;
40 unsigned result = 0, num;
41
42 if (*ptr == 'c') xexit();
43
44
45 if (eat(&ptr, 'x')) base = 16;
46 else {
47 if (posix && *ptr=='0') ptr++;
48 if (*ptr >= '0' && *ptr <= '7') base = 8;
49 }
50 len = (char []){0,3,2}[base/8];
51
52
53 if (!len) {
54 if (!(result = unescape(*ptr))) result = '\\';
55 else ++*esc_val;
56
57 return result;
58 }
59
60 while (len) {
61 num = tolower(*ptr) - '0';
62 if (num >= 'a'-'0') num += '0'-'a'+10;
63 if (num >= base) {
64
65 if (base == 16 && len == 2) {
66 ptr--;
67 result = '\\';
68 }
69 break;
70 }
71 result = (result*base)+num;
72 ptr++;
73 len--;
74 }
75 *esc_val = ptr;
76
77 return result;
78}
79
80void printf_main(void)
81{
82 char **arg = toys.optargs+1;
83
84
85 for (;;) {
86 int seen = 0;
87 char *f = *toys.optargs;
88
89
90 while (*f) {
91 if (eat(&f, '\\')) putchar(handle_slash(&f, 0));
92 else if (!eat(&f, '%') || *f == '%') putchar(*f++);
93
94
95 else {
96 char c, *end = 0, *aa, *to = toybuf;
97 int wp[] = {0,-1}, i = 0;
98
99
100 *to++ = '%';
101 while (strchr("-+# '0", *f) && (to-toybuf)<10) *to++ = *f++;
102 for (;;) {
103 if (eat(&f, '*')) {
104 if (*arg) wp[i] = atolx(*arg++);
105 } else while (*f >= '0' && *f <= '9') wp[i] = (wp[i]*10)+(*f++)-'0';
106 if (i++ || !eat(&f, '.')) break;
107 wp[1] = 0;
108 }
109 c = *f++;
110 seen = sprintf(to, "*.*%c", c);;
111 errno = 0;
112 aa = *arg ? *arg++ : "";
113
114
115 if (c == 'b') {
116 while (*aa) putchar(eat(&aa, '\\') ? handle_slash(&aa, 1) : *aa++);
117
118 continue;
119 } else if (c == 'c') printf(toybuf, wp[0], wp[1], *aa);
120 else if (c == 's') printf(toybuf, wp[0], wp[1], aa);
121 else if (strchr("diouxX", c)) {
122 long long ll;
123
124 if (*aa == '\'' || *aa == '"') ll = aa[1];
125 else ll = strtoll(aa, &end, 0);
126
127 sprintf(to, "*.*ll%c", c);
128 printf(toybuf, wp[0], wp[1], ll);
129 } else if (strchr("feEgG", c)) {
130 long double ld = strtold(aa, &end);
131
132 sprintf(to, "*.*L%c", c);
133 printf(toybuf, wp[0], wp[1], ld);
134 } else error_exit("bad %%%c@%ld", c, (long)(f-*toys.optargs));
135
136 if (end && (errno || *end)) perror_msg("bad %%%c %s", c, aa);
137 }
138 }
139
140
141
142 if (!seen || !*arg) break;
143 }
144}
145