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 /libbb | |
| 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>
Diffstat (limited to 'libbb')
| -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); |
