diff options
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/dump.c | 298 |
1 files changed, 160 insertions, 138 deletions
diff --git a/libbb/dump.c b/libbb/dump.c index 29c2c85ee..0d553d4d0 100644 --- a/libbb/dump.c +++ b/libbb/dump.c @@ -14,19 +14,6 @@ #include "libbb.h" #include "dump.h" -FS *bb_dump_fshead; /* head of format strings */ -off_t bb_dump_skip; /* bytes to skip */ -int bb_dump_blocksize; /* data block size */ -int bb_dump_length = -1; /* max bytes to read */ -smallint /*enum _vflag*/ bb_dump_vflag = FIRST; - -static FU *endfu; -static char **_argv; -static off_t savaddress; /* saved address/offset in stream */ -static off_t eaddress; /* end address */ -static off_t address; /* address/offset in stream */ -static int exitval; /* final exit value */ - static const char index_str[] ALIGN1 = ".#-+ 0123456789"; static const char size_conv_str[] ALIGN1 = @@ -34,7 +21,36 @@ static const char size_conv_str[] ALIGN1 = static const char lcc[] ALIGN1 = "diouxX"; -int FAST_FUNC bb_dump_size(FS *fs) + +typedef struct priv_dumper_t { + dumper_t pub; + + char **argv; + FU *endfu; + off_t savaddress; /* saved address/offset in stream */ + off_t eaddress; /* end address */ + off_t address; /* address/offset in stream */ + int blocksize; + smallint exitval; /* final exit value */ + + /* former statics */ + smallint next__done; + smallint get__ateof; // = 1; + unsigned char *get__curp; + unsigned char *get__savp; +} priv_dumper_t; + +dumper_t* FAST_FUNC alloc_dumper(void) +{ + priv_dumper_t *dumper = xzalloc(sizeof(*dumper)); + dumper->pub.dump_length = -1; + dumper->pub.dump_vflag = FIRST; + dumper->get__ateof = 1; + return &dumper->pub; +} + + +static NOINLINE int bb_dump_size(FS *fs) { FU *fu; int bcnt, cur_size; @@ -52,13 +68,14 @@ int FAST_FUNC bb_dump_size(FS *fs) if (*fmt != '%') continue; /* - * bb_dump_skip any special chars -- save precision in + * skip any special chars -- save precision in * case it's a %s format. */ while (strchr(index_str + 1, *++fmt)); if (*fmt == '.' && isdigit(*++fmt)) { prec = atoi(fmt); - while (isdigit(*++fmt)); + while (isdigit(*++fmt)) + continue; } p = strchr(size_conv_str + 12, *fmt); if (!p) { @@ -79,7 +96,7 @@ int FAST_FUNC bb_dump_size(FS *fs) return cur_size; } -static void rewrite(FS *fs) +static void rewrite(priv_dumper_t *dumper, FS *fs) { enum { NOTOKAY, USEBCNT, USEPREC } sokay; PR *pr, **nextpr = NULL; @@ -104,7 +121,7 @@ static void rewrite(FS *fs) * uninitialized 1st time through. */ - /* bb_dump_skip preceding text and up to the next % sign */ + /* skip preceding text and up to the next % sign */ for (p1 = fmtp; *p1 && *p1 != '%'; ++p1) continue; @@ -121,11 +138,11 @@ static void rewrite(FS *fs) */ if (fu->bcnt) { sokay = USEBCNT; - /* bb_dump_skip to conversion character */ + /* skip to conversion character */ for (++p1; strchr(index_str, *p1); ++p1) continue; } else { - /* bb_dump_skip any special chars, field width */ + /* skip any special chars, field width */ while (strchr(index_str + 1, *++p1)) continue; if (*p1 == '.' && isdigit(*++p1)) { @@ -137,7 +154,7 @@ static void rewrite(FS *fs) sokay = NOTOKAY; } - p2 = p1 + 1; /* set end pointer */ + p2 = p1 + 1; /* set end pointer */ /* * figure out the byte count for each conversion; @@ -198,7 +215,7 @@ static void rewrite(FS *fs) ++p2; switch (p1[1]) { case 'A': - endfu = fu; + dumper->endfu = fu; fu->flags |= F_IGNORE; /* FALLTHROUGH */ case 'a': @@ -274,7 +291,7 @@ static void rewrite(FS *fs) } /* * if the format string interprets any data at all, and it's - * not the same as the bb_dump_blocksize, and its last format unit + * not the same as the blocksize, and its last format unit * interprets any data at all, and has no iteration count, * repeat it as necessary. * @@ -282,10 +299,10 @@ static void rewrite(FS *fs) * gets output from the last iteration of the format unit. */ for (fu = fs->nextfu;; fu = fu->nextfu) { - if (!fu->nextfu && fs->bcnt < bb_dump_blocksize + if (!fu->nextfu && fs->bcnt < dumper->blocksize && !(fu->flags & F_SETREP) && fu->bcnt ) { - fu->reps += (bb_dump_blocksize - fs->bcnt) / fu->bcnt; + fu->reps += (dumper->blocksize - fs->bcnt) / fu->bcnt; } if (fu->reps > 1) { for (pr = fu->nextpr;; pr = pr->nextpr) @@ -301,7 +318,7 @@ static void rewrite(FS *fs) } } -static void do_skip(const char *fname, int statok) +static void do_skip(priv_dumper_t *dumper, const char *fname, int statok) { struct stat sbuf; @@ -309,125 +326,122 @@ static void do_skip(const char *fname, int statok) if (fstat(STDIN_FILENO, &sbuf)) { bb_simple_perror_msg_and_die(fname); } - if ((!(S_ISCHR(sbuf.st_mode) || - S_ISBLK(sbuf.st_mode) || - S_ISFIFO(sbuf.st_mode))) && bb_dump_skip >= sbuf.st_size) { - /* If bb_dump_size valid and bb_dump_skip >= size */ - bb_dump_skip -= sbuf.st_size; - address += sbuf.st_size; + if (!(S_ISCHR(sbuf.st_mode) || S_ISBLK(sbuf.st_mode) || S_ISFIFO(sbuf.st_mode)) + && dumper->pub.dump_skip >= sbuf.st_size + ) { + /* If bb_dump_size valid and pub.dump_skip >= size */ + dumper->pub.dump_skip -= sbuf.st_size; + dumper->address += sbuf.st_size; return; } } - if (fseek(stdin, bb_dump_skip, SEEK_SET)) { + if (fseek(stdin, dumper->pub.dump_skip, SEEK_SET)) { bb_simple_perror_msg_and_die(fname); } - savaddress = address += bb_dump_skip; - bb_dump_skip = 0; + dumper->address += dumper->pub.dump_skip; + dumper->savaddress = dumper->address; + dumper->pub.dump_skip = 0; } -static int next(char **argv) +static NOINLINE int next(priv_dumper_t *dumper) { - static smallint done; - int statok; - if (argv) { - _argv = argv; - return 1; - } for (;;) { - if (*_argv) { - if (!(freopen(*_argv, "r", stdin))) { - bb_simple_perror_msg(*_argv); - exitval = 1; - ++_argv; + if (*dumper->argv) { + if (!(freopen(*dumper->argv, "r", stdin))) { + bb_simple_perror_msg(*dumper->argv); + dumper->exitval = 1; + ++dumper->argv; continue; } - done = statok = 1; + dumper->next__done = statok = 1; } else { - if (done) + if (dumper->next__done) return 0; - done = 1; + dumper->next__done = 1; statok = 0; } - if (bb_dump_skip) - do_skip(statok ? *_argv : "stdin", statok); - if (*_argv) - ++_argv; - if (!bb_dump_skip) + if (dumper->pub.dump_skip) + do_skip(dumper, statok ? *dumper->argv : "stdin", statok); + if (*dumper->argv) + ++dumper->argv; + if (!dumper->pub.dump_skip) return 1; } /* NOTREACHED */ } -static unsigned char *get(void) +static unsigned char *get(priv_dumper_t *dumper) { - static smallint ateof = 1; - static unsigned char *curp = NULL, *savp; /*DBU:[dave@cray.com]initialize curp */ - int n; int need, nread; unsigned char *tmpp; + int blocksize = dumper->blocksize; - if (!curp) { - address = (off_t)0; /*DBU:[dave@cray.com] initialize,initialize..*/ - curp = xmalloc(bb_dump_blocksize); - savp = xmalloc(bb_dump_blocksize); + if (!dumper->get__curp) { + dumper->address = (off_t)0; /*DBU:[dave@cray.com] initialize,initialize..*/ + dumper->get__curp = xmalloc(blocksize); + dumper->get__savp = xmalloc(blocksize); } else { - tmpp = curp; - curp = savp; - savp = tmpp; - address = savaddress += bb_dump_blocksize; + tmpp = dumper->get__curp; + dumper->get__curp = dumper->get__savp; + dumper->get__savp = tmpp; + dumper->savaddress += blocksize; + dumper->address = dumper->savaddress; } - for (need = bb_dump_blocksize, nread = 0;;) { + need = blocksize; + nread = 0; + while (1) { /* * if read the right number of bytes, or at EOF for one file, * and no other files are available, zero-pad the rest of the * block and set the end flag. */ - if (!bb_dump_length || (ateof && !next(NULL))) { - if (need == bb_dump_blocksize) { + if (!dumper->pub.dump_length || (dumper->get__ateof && !next(dumper))) { + if (need == blocksize) { return NULL; } - if (bb_dump_vflag != ALL && !memcmp(curp, savp, nread)) { - if (bb_dump_vflag != DUP) { + if (dumper->pub.dump_vflag != ALL && !memcmp(dumper->get__curp, dumper->get__savp, nread)) { + if (dumper->pub.dump_vflag != DUP) { puts("*"); } return NULL; } - memset(curp + nread, 0, need); - eaddress = address + nread; - return curp; + memset(dumper->get__curp + nread, 0, need); + dumper->eaddress = dumper->address + nread; + return dumper->get__curp; } - n = fread(curp + nread, sizeof(unsigned char), - bb_dump_length == -1 ? need : MIN(bb_dump_length, need), stdin); + n = fread(dumper->get__curp + nread, sizeof(unsigned char), + dumper->pub.dump_length == -1 ? need : MIN(dumper->pub.dump_length, need), stdin); if (!n) { if (ferror(stdin)) { - bb_simple_perror_msg(_argv[-1]); + bb_simple_perror_msg(dumper->argv[-1]); } - ateof = 1; + dumper->get__ateof = 1; continue; } - ateof = 0; - if (bb_dump_length != -1) { - bb_dump_length -= n; + dumper->get__ateof = 0; + if (dumper->pub.dump_length != -1) { + dumper->pub.dump_length -= n; } need -= n; if (!need) { - if (bb_dump_vflag == ALL || bb_dump_vflag == FIRST - || memcmp(curp, savp, bb_dump_blocksize) + if (dumper->pub.dump_vflag == ALL || dumper->pub.dump_vflag == FIRST + || memcmp(dumper->get__curp, dumper->get__savp, blocksize) ) { - if (bb_dump_vflag == DUP || bb_dump_vflag == FIRST) { - bb_dump_vflag = WAIT; + if (dumper->pub.dump_vflag == DUP || dumper->pub.dump_vflag == FIRST) { + dumper->pub.dump_vflag = WAIT; } - return curp; + return dumper->get__curp; } - if (bb_dump_vflag == WAIT) { + if (dumper->pub.dump_vflag == WAIT) { puts("*"); } - bb_dump_vflag = DUP; - address = savaddress += bb_dump_blocksize; - need = bb_dump_blocksize; + dumper->pub.dump_vflag = DUP; + dumper->savaddress += blocksize; + dumper->address = dumper->savaddress; + need = blocksize; nread = 0; } else { nread += n; @@ -515,29 +529,31 @@ static void conv_u(PR *pr, unsigned char *p) } } -static void display(void) +static void display(priv_dumper_t* dumper) { -/* extern FU *endfu; */ FS *fs; FU *fu; PR *pr; int cnt; - unsigned char *bp; + unsigned char *bp, *savebp; off_t saveaddress; - unsigned char savech = 0, *savebp; + unsigned char savech = '\0'; - while ((bp = get()) != NULL) { - for (fs = bb_dump_fshead, savebp = bp, saveaddress = address; fs; - fs = fs->nextfs, bp = savebp, address = saveaddress) { + while ((bp = get(dumper)) != NULL) { + fs = dumper->pub.fshead; + savebp = bp; + saveaddress = dumper->address; + for (; fs; fs = fs->nextfs, bp = savebp, dumper->address = saveaddress) { for (fu = fs->nextfu; fu; fu = fu->nextfu) { if (fu->flags & F_IGNORE) { break; } for (cnt = fu->reps; cnt; --cnt) { - for (pr = fu->nextpr; pr; address += pr->bcnt, - bp += pr->bcnt, pr = pr->nextpr) { - if (eaddress && address >= eaddress && - !(pr->flags & (F_TEXT | F_BPAD))) { + for (pr = fu->nextpr; pr; dumper->address += pr->bcnt, + bp += pr->bcnt, pr = pr->nextpr) { + if (dumper->eaddress && dumper->address >= dumper->eaddress + && !(pr->flags & (F_TEXT | F_BPAD)) + ) { bpad(pr); } if (cnt == 1 && pr->nospace) { @@ -547,7 +563,7 @@ static void display(void) /* PRINT; */ switch (pr->flags) { case F_ADDRESS: - printf(pr->fmt, (unsigned) address); + printf(pr->fmt, (unsigned) dumper->address); break; case F_BPAD: printf(pr->fmt, ""); @@ -558,7 +574,7 @@ static void display(void) case F_CHAR: printf(pr->fmt, *bp); break; - case F_DBL:{ + case F_DBL: { double dval; float fval; @@ -574,7 +590,7 @@ static void display(void) } break; } - case F_INT:{ + case F_INT: { int ival; short sval; @@ -605,7 +621,7 @@ static void display(void) case F_U: conv_u(pr, bp); break; - case F_UINT:{ + case F_UINT: { unsigned ival; unsigned short sval; @@ -633,21 +649,21 @@ static void display(void) } } } - if (endfu) { + if (dumper->endfu) { /* - * if eaddress not set, error or file bb_dump_size was multiple of - * bb_dump_blocksize, and no partial block ever found. + * if eaddress not set, error or file size was multiple + * of blocksize, and no partial block ever found. */ - if (!eaddress) { - if (!address) { + if (!dumper->eaddress) { + if (!dumper->address) { return; } - eaddress = address; + dumper->eaddress = dumper->address; } - for (pr = endfu->nextpr; pr; pr = pr->nextpr) { + for (pr = dumper->endfu->nextpr; pr; pr = pr->nextpr) { switch (pr->flags) { case F_ADDRESS: - printf(pr->fmt, (unsigned) eaddress); + printf(pr->fmt, (unsigned) dumper->eaddress); break; case F_TEXT: printf(pr->fmt); @@ -657,52 +673,58 @@ static void display(void) } } -int FAST_FUNC bb_dump_dump(char **argv) +#define dumper ((priv_dumper_t*)pub_dumper) +int FAST_FUNC bb_dump_dump(dumper_t *pub_dumper, char **argv) { FS *tfs; + int blocksize; /* figure out the data block bb_dump_size */ - for (bb_dump_blocksize = 0, tfs = bb_dump_fshead; tfs; tfs = tfs->nextfs) { + blocksize = 0; + tfs = dumper->pub.fshead; + while (tfs) { tfs->bcnt = bb_dump_size(tfs); - if (bb_dump_blocksize < tfs->bcnt) { - bb_dump_blocksize = tfs->bcnt; + if (blocksize < tfs->bcnt) { + blocksize = tfs->bcnt; } + tfs = tfs->nextfs; } + dumper->blocksize = blocksize; + /* rewrite the rules, do syntax checking */ - for (tfs = bb_dump_fshead; tfs; tfs = tfs->nextfs) { - rewrite(tfs); + for (tfs = dumper->pub.fshead; tfs; tfs = tfs->nextfs) { + rewrite(dumper, tfs); } - next(argv); - display(); + dumper->argv = argv; + display(dumper); - return exitval; + return dumper->exitval; } -void FAST_FUNC bb_dump_add(const char *fmt) +void FAST_FUNC bb_dump_add(dumper_t* pub_dumper, const char *fmt) { - static FS **nextfs; - const char *p; char *p1; char *p2; FS *tfs; - FU *tfu, **nextfu; + FU *tfu, **nextfupp; const char *savep; /* start new linked list of format units */ tfs = xzalloc(sizeof(FS)); /*DBU:[dave@cray.com] start out NULL */ - if (!bb_dump_fshead) { - bb_dump_fshead = tfs; + if (!dumper->pub.fshead) { + dumper->pub.fshead = tfs; } else { - *nextfs = tfs; + FS *fslast = dumper->pub.fshead; + while (fslast->nextfs) + fslast = fslast->nextfs; + fslast->nextfs = tfs; } - nextfs = &tfs->nextfs; - nextfu = &tfs->nextfu; + nextfupp = &tfs->nextfu; /* take the format string and break it up into format units */ for (p = fmt;;) { - /* bb_dump_skip leading white space */ p = skip_whitespace(p); if (!*p) { break; @@ -712,8 +734,8 @@ void FAST_FUNC bb_dump_add(const char *fmt) /* NOSTRICT */ /* DBU:[dave@cray.com] zalloc so that forward pointers start out NULL */ tfu = xzalloc(sizeof(FU)); - *nextfu = tfu; - nextfu = &tfu->nextfu; + *nextfupp = tfu; + nextfupp = &tfu->nextfu; tfu->reps = 1; /* if leading digit, repetition count */ @@ -726,11 +748,11 @@ void FAST_FUNC bb_dump_add(const char *fmt) /* may overwrite either white space or slash */ tfu->reps = atoi(savep); tfu->flags = F_SETREP; - /* bb_dump_skip trailing white space */ + /* skip trailing white space */ p = skip_whitespace(++p); } - /* bb_dump_skip slash and trailing white space */ + /* skip slash and trailing white space */ if (*p == '/') { p = skip_whitespace(++p); } @@ -745,7 +767,7 @@ void FAST_FUNC bb_dump_add(const char *fmt) bb_error_msg_and_die("bad format {%s}", fmt); } tfu->bcnt = atoi(savep); - /* bb_dump_skip trailing white space */ + /* skip trailing white space */ p = skip_whitespace(++p); } |