aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-01-25 16:21:00 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2017-01-25 16:21:00 +0100
commitcb8e84e65a254dcba4939e237b93d03c46ae56aa (patch)
treeba39f4322201f5e3b4ae131ddacbee78da7d0b32
parentb13b6183354e6c9d031951fa4f11bcb9b38ae251 (diff)
downloadbusybox-w32-cb8e84e65a254dcba4939e237b93d03c46ae56aa.tar.gz
busybox-w32-cb8e84e65a254dcba4939e237b93d03c46ae56aa.tar.bz2
busybox-w32-cb8e84e65a254dcba4939e237b93d03c46ae56aa.zip
libbb: shrink sump.c
function old new delta dot_flags_width_chars - 16 +16 int_convs - 7 +7 lcc 7 - -7 index_str 16 - -16 rewrite 1013 937 -76 ------------------------------------------------------------------------------ (add/remove: 2/2 grow/shrink: 0/1 up/down: 23/-99) Total: -76 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--libbb/dump.c159
1 files changed, 80 insertions, 79 deletions
diff --git a/libbb/dump.c b/libbb/dump.c
index e9ac0c673..87c1dce13 100644
--- a/libbb/dump.c
+++ b/libbb/dump.c
@@ -14,12 +14,12 @@
14#include "libbb.h" 14#include "libbb.h"
15#include "dump.h" 15#include "dump.h"
16 16
17static const char index_str[] ALIGN1 = ".#-+ 0123456789"; 17static const char dot_flags_width_chars[] ALIGN1 = ".#-+ 0123456789";
18 18
19static const char size_conv_str[] ALIGN1 = 19static const char size_conv_str[] ALIGN1 =
20"\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG"; 20"\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG";
21 21
22static const char lcc[] ALIGN1 = "diouxX"; 22static const char int_convs[] ALIGN1 = "diouxX";
23 23
24 24
25typedef struct priv_dumper_t { 25typedef struct priv_dumper_t {
@@ -71,7 +71,7 @@ static NOINLINE int bb_dump_size(FS *fs)
71 * skip any special chars -- save precision in 71 * skip any special chars -- save precision in
72 * case it's a %s format. 72 * case it's a %s format.
73 */ 73 */
74 while (strchr(index_str + 1, *++fmt)) 74 while (strchr(dot_flags_width_chars + 1, *++fmt))
75 continue; 75 continue;
76 if (*fmt == '.' && isdigit(*++fmt)) { 76 if (*fmt == '.' && isdigit(*++fmt)) {
77 prec = atoi(fmt); 77 prec = atoi(fmt);
@@ -82,14 +82,15 @@ static NOINLINE int bb_dump_size(FS *fs)
82 if (!p) { 82 if (!p) {
83 if (*fmt == 's') { 83 if (*fmt == 's') {
84 bcnt += prec; 84 bcnt += prec;
85 } else if (*fmt == '_') { 85 }
86 if (*fmt == '_') {
86 ++fmt; 87 ++fmt;
87 if ((*fmt == 'c') || (*fmt == 'p') || (*fmt == 'u')) { 88 if ((*fmt == 'c') || (*fmt == 'p') || (*fmt == 'u')) {
88 bcnt += 1; 89 bcnt += 1;
89 } 90 }
90 } 91 }
91 } else { 92 } else {
92 bcnt += size_conv_str[p - (size_conv_str + 12)]; 93 bcnt += p[-12];
93 } 94 }
94 } 95 }
95 cur_size += bcnt * fu->reps; 96 cur_size += bcnt * fu->reps;
@@ -99,32 +100,30 @@ static NOINLINE int bb_dump_size(FS *fs)
99 100
100static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) 101static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
101{ 102{
102 enum { NOTOKAY, USEBCNT, USEPREC } sokay;
103 FU *fu; 103 FU *fu;
104 PR *pr;
105 char *p1, *p2, *p3;
106 char savech, *fmtp;
107 const char *byte_count_str;
108 int nconv, prec = 0;
109 104
110 for (fu = fs->nextfu; fu; fu = fu->nextfu) { 105 for (fu = fs->nextfu; fu; fu = fu->nextfu) {
106 PR *pr;
107 char *p1, *p2, *p3;
108 char *fmtp;
109 int nconv = 0;
111 /* 110 /*
112 * break each format unit into print units; each 111 * break each format unit into print units; each
113 * conversion character gets its own. 112 * conversion character gets its own.
114 */ 113 */
115 for (nconv = 0, fmtp = fu->fmt; *fmtp; ) { 114 for (fmtp = fu->fmt; *fmtp; ) {
116 /* NOSTRICT */ 115 unsigned len;
117 /* DBU:[dvae@cray.com] zalloc so that forward ptrs start out NULL*/ 116 const char *prec;
118 pr = xzalloc(sizeof(PR)); 117 const char *byte_count_str;
118
119 /* DBU:[dvae@cray.com] zalloc so that forward ptrs start out NULL */
120 pr = xzalloc(sizeof(*pr));
119 if (!fu->nextpr) 121 if (!fu->nextpr)
120 fu->nextpr = pr; 122 fu->nextpr = pr;
121 123
122 /* skip preceding text and up to the next % sign */ 124 /* skip preceding text and up to the next % sign */
123 for (p1 = fmtp; *p1 && *p1 != '%'; ++p1) 125 p1 = strchr(fmtp, '%');
124 continue; 126 if (!p1) { /* only text in the string */
125
126 /* only text in the string */
127 if (!*p1) {
128 pr->fmt = fmtp; 127 pr->fmt = fmtp;
129 pr->flags = F_TEXT; 128 pr->flags = F_TEXT;
130 break; 129 break;
@@ -134,22 +133,20 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
134 * get precision for %s -- if have a byte count, don't 133 * get precision for %s -- if have a byte count, don't
135 * need it. 134 * need it.
136 */ 135 */
136 prec = NULL;
137 if (fu->bcnt) { 137 if (fu->bcnt) {
138 sokay = USEBCNT;
139 /* skip to conversion character */ 138 /* skip to conversion character */
140 for (++p1; strchr(index_str, *p1); ++p1) 139 while (strchr(dot_flags_width_chars, *++p1))
141 continue; 140 continue;
142 } else { 141 } else {
143 /* skip any special chars, field width */ 142 /* skip any special chars, field width */
144 while (strchr(index_str + 1, *++p1)) 143 while (strchr(dot_flags_width_chars + 1, *++p1))
145 continue; 144 continue;
146 if (*p1 == '.' && isdigit(*++p1)) { 145 if (*p1 == '.' && isdigit(*++p1)) {
147 sokay = USEPREC; 146 prec = p1;
148 prec = atoi(p1);
149 while (isdigit(*++p1)) 147 while (isdigit(*++p1))
150 continue; 148 continue;
151 } else 149 }
152 sokay = NOTOKAY;
153 } 150 }
154 151
155 p2 = p1 + 1; /* set end pointer */ 152 p2 = p1 + 1; /* set end pointer */
@@ -174,63 +171,63 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
174 } 171 }
175 /* Unlike the original, output the remainder of the format string. */ 172 /* Unlike the original, output the remainder of the format string. */
176 pr->bcnt = *byte_count_str; 173 pr->bcnt = *byte_count_str;
177 } else if (*p1 == 'l') { 174 } else
175 if (*p1 == 'l') { /* %ld etc */
176 const char *e;
177
178 ++p2; 178 ++p2;
179 ++p1; 179 ++p1;
180 DO_INT_CONV: 180 DO_INT_CONV:
181 { 181 e = strchr(int_convs, *p1); /* "diouxX"? */
182 const char *e; 182 if (!e)
183 e = strchr(lcc, *p1); 183 goto DO_BAD_CONV_CHAR;
184 if (!e) { 184 pr->flags = F_INT;
185 goto DO_BAD_CONV_CHAR; 185 if (e > int_convs + 1) /* not d or i? */
186 } 186 pr->flags = F_UINT;
187 pr->flags = F_INT; 187 byte_count_str = "\004\002\001";
188 if (e > lcc + 1) { 188 goto DO_BYTE_COUNT;
189 pr->flags = F_UINT; 189 } else
190 } 190 if (strchr(int_convs, *p1)) { /* %d etc */
191 byte_count_str = "\004\002\001";
192 goto DO_BYTE_COUNT;
193 }
194 /* NOTREACHED */
195 } else if (strchr(lcc, *p1)) {
196 goto DO_INT_CONV; 191 goto DO_INT_CONV;
197 } else if (strchr("eEfgG", *p1)) { 192 } else
193 if (strchr("eEfgG", *p1)) { /* floating point */
198 pr->flags = F_DBL; 194 pr->flags = F_DBL;
199 byte_count_str = "\010\004"; 195 byte_count_str = "\010\004";
200 goto DO_BYTE_COUNT; 196 goto DO_BYTE_COUNT;
201 } else if (*p1 == 's') { 197 } else
198 if (*p1 == 's') {
202 pr->flags = F_STR; 199 pr->flags = F_STR;
203 if (sokay == USEBCNT) { 200 pr->bcnt = fu->bcnt;
204 pr->bcnt = fu->bcnt; 201 if (fu->bcnt == 0) {
205 } else if (sokay == USEPREC) { 202 if (!prec)
206 pr->bcnt = prec; 203 bb_error_msg_and_die("%%s needs precision or byte count");
207 } else { /* NOTOKAY */ 204 pr->bcnt = atoi(prec);
208 bb_error_msg_and_die("%%s requires a precision or a byte count");
209 } 205 }
210 } else if (*p1 == '_') { 206 } else
211 ++p2; 207 if (*p1 == '_') {
208 p2++; /* move past a in "%_a" */
212 switch (p1[1]) { 209 switch (p1[1]) {
213 case 'A': 210 case 'A': /* %_A[dox]: print address and the end */
214 dumper->endfu = fu; 211 dumper->endfu = fu;
215 fu->flags |= F_IGNORE; 212 fu->flags |= F_IGNORE;
216 /* FALLTHROUGH */ 213 /* FALLTHROUGH */
217 case 'a': 214 case 'a': /* %_a[dox]: current address */
218 pr->flags = F_ADDRESS; 215 pr->flags = F_ADDRESS;
219 ++p2; 216 p2++; /* move past x in "%_ax" */
220 if ((p1[2] != 'd') && (p1[2] != 'o') && (p1[2] != 'x')) { 217 if ((p1[2] != 'd') && (p1[2] != 'o') && (p1[2] != 'x')) {
221 goto DO_BAD_CONV_CHAR; 218 goto DO_BAD_CONV_CHAR;
222 } 219 }
223 *p1 = p1[2]; 220 *p1 = p1[2];
224 break; 221 break;
225 case 'c': 222 case 'c': /* %_c: chars, \ooo, \n \r \t etc */
226 pr->flags = F_C; 223 pr->flags = F_C;
227 /* *p1 = 'c'; set in conv_c */ 224 /* *p1 = 'c'; set in conv_c */
228 goto DO_BYTE_COUNT_1; 225 goto DO_BYTE_COUNT_1;
229 case 'p': 226 case 'p': /* %_p: chars, dots for nonprintable */
230 pr->flags = F_P; 227 pr->flags = F_P;
231 *p1 = 'c'; 228 *p1 = 'c';
232 goto DO_BYTE_COUNT_1; 229 goto DO_BYTE_COUNT_1;
233 case 'u': 230 case 'u': /* %_p: chars, 'nul', 'esc' etc for nonprintable */
234 pr->flags = F_U; 231 pr->flags = F_U;
235 /* *p1 = 'c'; set in conv_u */ 232 /* *p1 = 'c'; set in conv_u */
236 goto DO_BYTE_COUNT_1; 233 goto DO_BYTE_COUNT_1;
@@ -246,13 +243,8 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
246 * copy to PR format string, set conversion character 243 * copy to PR format string, set conversion character
247 * pointer, update original. 244 * pointer, update original.
248 */ 245 */
249 savech = *p2; 246 len = (p1 - fmtp) + 1;
250 p1[1] = '\0'; 247 pr->fmt = xstrndup(fmtp, len);
251 pr->fmt = xstrdup(fmtp);
252 *p2 = savech;
253 //Too early! xrealloc can move pr->fmt!
254 //pr->cchar = pr->fmt + (p1 - fmtp);
255
256 /* DBU:[dave@cray.com] w/o this, trailing fmt text, space is lost. 248 /* DBU:[dave@cray.com] w/o this, trailing fmt text, space is lost.
257 * Skip subsequent text and up to the next % sign and tack the 249 * Skip subsequent text and up to the next % sign and tack the
258 * additional text onto fmt: eg. if fmt is "%x is a HEX number", 250 * additional text onto fmt: eg. if fmt is "%x is a HEX number",
@@ -260,16 +252,17 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
260 */ 252 */
261 for (p3 = p2; *p3 && *p3 != '%'; p3++) 253 for (p3 = p2; *p3 && *p3 != '%'; p3++)
262 continue; 254 continue;
263 if (p3 > p2) { 255 if ((p3 - p2) != 0) {
264 savech = *p3; 256 char *d;
265 *p3 = '\0'; 257 pr->fmt = d = xrealloc(pr->fmt, len + (p3 - p2) + 1);
266 pr->fmt = xrealloc(pr->fmt, strlen(pr->fmt) + (p3-p2) + 1); 258 d += len;
267 strcat(pr->fmt, p2); 259 do {
268 *p3 = savech; 260 *d++ = *p2++;
269 p2 = p3; 261 } while (p2 != p3);
262 *d = '\0';
263 /* now p2 = p3 */
270 } 264 }
271 265 pr->cchar = pr->fmt + len - 1; /* must be after realloc! */
272 pr->cchar = pr->fmt + (p1 - fmtp);
273 fmtp = p2; 266 fmtp = p2;
274 267
275 /* only one conversion character if byte count */ 268 /* only one conversion character if byte count */
@@ -281,7 +274,7 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
281 * if format unit byte count not specified, figure it out 274 * if format unit byte count not specified, figure it out
282 * so can adjust rep count later. 275 * so can adjust rep count later.
283 */ 276 */
284 if (!fu->bcnt) 277 if (fu->bcnt == 0)
285 for (pr = fu->nextpr; pr; pr = pr->nextpr) 278 for (pr = fu->nextpr; pr; pr = pr->nextpr)
286 fu->bcnt += pr->bcnt; 279 fu->bcnt += pr->bcnt;
287 } 280 }
@@ -303,16 +296,18 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
303 fu->reps += (dumper->blocksize - fs->bcnt) / fu->bcnt; 296 fu->reps += (dumper->blocksize - fs->bcnt) / fu->bcnt;
304 } 297 }
305 if (fu->reps > 1 && fu->nextpr) { 298 if (fu->reps > 1 && fu->nextpr) {
299 PR *pr;
300 char *p1, *p2;
301
306 for (pr = fu->nextpr;; pr = pr->nextpr) 302 for (pr = fu->nextpr;; pr = pr->nextpr)
307 if (!pr->nextpr) 303 if (!pr->nextpr)
308 break; 304 break;
309 for (p1 = pr->fmt, p2 = NULL; *p1; ++p1) 305 p2 = NULL;
306 for (p1 = pr->fmt; *p1; ++p1)
310 p2 = isspace(*p1) ? p1 : NULL; 307 p2 = isspace(*p1) ? p1 : NULL;
311 if (p2) 308 if (p2)
312 pr->nospace = p2; 309 pr->nospace = p2;
313 } 310 }
314 if (!fu->nextfu)
315 break;
316 } 311 }
317} 312}
318 313
@@ -356,6 +351,7 @@ static NOINLINE int next(priv_dumper_t *dumper)
356 if (dumper->next__done) 351 if (dumper->next__done)
357 return 0; /* no next file */ 352 return 0; /* no next file */
358 dumper->next__done = 1; 353 dumper->next__done = 1;
354//why stat of stdin is specially prohibited?
359 statok = 0; 355 statok = 0;
360 } 356 }
361 if (dumper->pub.dump_skip) 357 if (dumper->pub.dump_skip)
@@ -760,6 +756,11 @@ void FAST_FUNC bb_dump_add(dumper_t* pub_dumper, const char *fmt)
760 if (!isspace(*p)) { 756 if (!isspace(*p)) {
761 bb_error_msg_and_die("bad format {%s}", fmt); 757 bb_error_msg_and_die("bad format {%s}", fmt);
762 } 758 }
759// Above check prohibits formats such as '/1"%02x"' - it requires space after 1.
760// Other than this, formats can be pretty much jammed together:
761// "%07_ax:"8/2 "%04x|""\n"
762// but this space is required. The check *can* be removed, but
763// keeping it to stay compat with util-linux hexdump.
763 tfu->bcnt = atoi(savep); 764 tfu->bcnt = atoi(savep);
764 /* skip trailing white space */ 765 /* skip trailing white space */
765 p = skip_whitespace(p + 1); 766 p = skip_whitespace(p + 1);