diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-25 16:21:00 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-01-25 16:21:00 +0100 |
commit | cb8e84e65a254dcba4939e237b93d03c46ae56aa (patch) | |
tree | ba39f4322201f5e3b4ae131ddacbee78da7d0b32 | |
parent | b13b6183354e6c9d031951fa4f11bcb9b38ae251 (diff) | |
download | busybox-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.c | 159 |
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 | ||
17 | static const char index_str[] ALIGN1 = ".#-+ 0123456789"; | 17 | static const char dot_flags_width_chars[] ALIGN1 = ".#-+ 0123456789"; |
18 | 18 | ||
19 | static const char size_conv_str[] ALIGN1 = | 19 | static 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 | ||
22 | static const char lcc[] ALIGN1 = "diouxX"; | 22 | static const char int_convs[] ALIGN1 = "diouxX"; |
23 | 23 | ||
24 | 24 | ||
25 | typedef struct priv_dumper_t { | 25 | typedef 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 | ||
100 | static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) | 101 | static 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); |