libbb: get rid of statics in dump.c; code shrinks a lot too

function                                             old     new   delta
alloc_dumper                                           -      26     +26
hexdump_main                                         600     601      +1
static.done                                            1       -      -1
static.ateof                                           1       -      -1
bb_dump_vflag                                          1       -      -1
static.savp                                            4       -      -4
static.nextfs                                          4       -      -4
static.curp                                            4       -      -4
exitval                                                4       -      -4
endfu                                                  4       -      -4
bb_dump_length                                         4       -      -4
bb_dump_fshead                                         4       -      -4
bb_dump_blocksize                                      4       -      -4
_argv                                                  4       -      -4
bb_dump_add                                          365     358      -7
savaddress                                             8       -      -8
eaddress                                               8       -      -8
bb_dump_skip                                           8       -      -8
address                                                8       -      -8
bb_dump_dump                                        2748    2672     -76
next                                                 538     445     -93
------------------------------------------------------------------------------
(add/remove: 1/16 grow/shrink: 1/3 up/down: 27/-247)         Total: -220 bytes
   text	   data	    bss	    dec	    hex	filename
 789458	    607	   6764	 796829	  c289d	busybox_old
 789309	    601	   6696	 796606	  c27be	busybox_unstripped

diff --git a/libbb/dump.c b/libbb/dump.c
index 29c2c85..0d553d4 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 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 @@
 			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 @@
 	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 @@
 			 * 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 @@
 			 */
 			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 @@
 					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 @@
 				++p2;
 				switch (p1[1]) {
 				case 'A':
-					endfu = fu;
+					dumper->endfu = fu;
 					fu->flags |= F_IGNORE;
 					/* FALLTHROUGH */
 				case 'a':
@@ -274,7 +291,7 @@
 	}
 	/*
 	 * 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 @@
 	 * 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 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 @@
 		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 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 @@
 /*                      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 @@
 						case F_CHAR:
 							printf(pr->fmt, *bp);
 							break;
-						case F_DBL:{
+						case F_DBL: {
 							double dval;
 							float fval;
 
@@ -574,7 +590,7 @@
 							}
 							break;
 						}
-						case F_INT:{
+						case F_INT: {
 							int ival;
 							short sval;
 
@@ -605,7 +621,7 @@
 						case F_U:
 							conv_u(pr, bp);
 							break;
-						case F_UINT:{
+						case F_UINT: {
 							unsigned ival;
 							unsigned short sval;
 
@@ -633,21 +649,21 @@
 			}
 		}
 	}
-	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 @@
 	}
 }
 
-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 @@
 		/* 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 @@
 			/* 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 @@
 				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);
 		}