[git commit] od: get rid of (almost all) statics

Denys Vlasenko vda.linux at googlemail.com
Mon Oct 19 00:51:56 UTC 2015


commit: http://git.busybox.net/busybox/commit/?id=f3d58a29be7cbf5c0bf94f1a12ac747f706b3d99
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
od_main                                             2565    2600     +35
check_and_close                                      113     115      +2
static.prev_pair_equal                                 1       -      -1
static.first                                           1       -      -1
exit_code                                              1       -      -1
string_min                                             4       -      -4
n_specs                                                4       -      -4
in_stream                                              4       -      -4
format_address                                         4       -      -4
file_list                                              4       -      -4
bytes_per_block                                        4       -      -4
get_lcm                                              120     115      -5
pseudo_offset                                          8       -      -8
------------------------------------------------------------------------------
(add/remove: 0/10 grow/shrink: 2/1 up/down: 37/-40)            Total: -3 bytes
   text	   data	    bss	    dec	    hex	filename
 938487	    932	  17392	 956811	  e998b	busybox_old
 938519	    924	  17360	 956803	  e9983	busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 coreutils/od_bloaty.c |  230 ++++++++++++++++++++++++++-----------------------
 1 files changed, 122 insertions(+), 108 deletions(-)

diff --git a/coreutils/od_bloaty.c b/coreutils/od_bloaty.c
index ab7ea99..f47f84b 100644
--- a/coreutils/od_bloaty.c
+++ b/coreutils/od_bloaty.c
@@ -66,7 +66,7 @@ enum {
 	/* -S was -s and also had optional parameter */ \
 	/* but in coreutils 6.3 it was renamed and now has */ \
 	/* _mandatory_ parameter */ \
-	&str_A, &str_N, &str_j, &lst_t, &str_S, &bytes_per_block)
+	&str_A, &str_N, &str_j, &lst_t, &str_S, &G.bytes_per_block)
 
 
 /* Check for 0x7f is a coreutils 6.3 addition */
@@ -174,38 +174,52 @@ struct ERR_width_bytes_has_bad_size {
 	char ERR_width_bytes_has_bad_size[ARRAY_SIZE(width_bytes) == N_SIZE_SPECS ? 1 : -1];
 };
 
-static smallint exit_code;
+struct globals {
+	smallint exit_code;
 
-static unsigned string_min;
+	unsigned string_min;
 
-/* An array of specs describing how to format each input block.  */
-static size_t n_specs;
-static struct tspec *spec;
+	/* An array of specs describing how to format each input block.  */
+	unsigned n_specs;
+	struct tspec *spec;
 
-/* Function that accepts an address and an optional following char,
-   and prints the address and char to stdout.  */
-static void (*format_address)(off_t, char);
-/* The difference between the old-style pseudo starting address and
-   the number of bytes to skip.  */
+	/* Function that accepts an address and an optional following char,
+	   and prints the address and char to stdout.  */
+	void (*format_address)(off_t, char);
+
+	/* The difference between the old-style pseudo starting address and
+	   the number of bytes to skip.  */
 #if ENABLE_LONG_OPTS
-static off_t pseudo_offset;
-#else
-enum { pseudo_offset = 0 };
+	off_t pseudo_offset;
+# define G_pseudo_offset G.pseudo_offset
 #endif
-/* When zero, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all
-   input is formatted.  */
-
-/* The number of input bytes formatted per output line.  It must be
-   a multiple of the least common multiple of the sizes associated with
-   the specified output types.  It should be as large as possible, but
-   no larger than 16 -- unless specified with the -w option.  */
-static unsigned bytes_per_block = 32; /* have to use unsigned, not size_t */
-
-/* A NULL-terminated list of the file-arguments from the command line.  */
-static const char *const *file_list;
+	/* When zero, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all
+	   input is formatted.  */
+
+	/* The number of input bytes formatted per output line.  It must be
+	   a multiple of the least common multiple of the sizes associated with
+	   the specified output types.  It should be as large as possible, but
+	   no larger than 16 -- unless specified with the -w option.  */
+	unsigned bytes_per_block; /* have to use unsigned, not size_t */
+
+	/* A NULL-terminated list of the file-arguments from the command line.  */
+	const char *const *file_list;
+
+	/* The input stream associated with the current file.  */
+	FILE *in_stream;
+
+	bool not_first;
+	bool prev_pair_equal;
+} FIX_ALIASING;
+#if !ENABLE_LONG_OPTS
+enum { G_pseudo_offset = 0 };
+#endif
+#define G (*(struct globals*)&bb_common_bufsiz1)
+#define INIT_G() do { \
+	BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
+	G.bytes_per_block = 32; \
+} while (0)
 
-/* The input stream associated with the current file.  */
-static FILE *in_stream;
 
 #define MAX_INTEGRAL_TYPE_SIZE sizeof(ulonglong_t)
 static const unsigned char integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1] ALIGN1 = {
@@ -476,17 +490,17 @@ static void
 open_next_file(void)
 {
 	while (1) {
-		if (!*file_list)
+		if (!*G.file_list)
 			return;
-		in_stream = fopen_or_warn_stdin(*file_list++);
-		if (in_stream) {
+		G.in_stream = fopen_or_warn_stdin(*G.file_list++);
+		if (G.in_stream) {
 			break;
 		}
-		exit_code = 1;
+		G.exit_code = 1;
 	}
 
 	if ((option_mask32 & (OPT_N|OPT_S)) == OPT_N)
-		setbuf(in_stream, NULL);
+		setbuf(G.in_stream, NULL);
 }
 
 /* Test whether there have been errors on in_stream, and close it if
@@ -499,16 +513,16 @@ open_next_file(void)
 static void
 check_and_close(void)
 {
-	if (in_stream) {
-		if (ferror(in_stream))	{
-			bb_error_msg("%s: read error", (in_stream == stdin)
+	if (G.in_stream) {
+		if (ferror(G.in_stream))	{
+			bb_error_msg("%s: read error", (G.in_stream == stdin)
 					? bb_msg_standard_input
-					: file_list[-1]
+					: G.file_list[-1]
 			);
-			exit_code = 1;
+			G.exit_code = 1;
 		}
-		fclose_if_not_stdin(in_stream);
-		in_stream = NULL;
+		fclose_if_not_stdin(G.in_stream);
+		G.in_stream = NULL;
 	}
 
 	if (ferror(stdout)) {
@@ -744,9 +758,9 @@ decode_format_string(const char *s)
 
 		assert(s != next);
 		s = next;
-		spec = xrealloc_vector(spec, 4, n_specs);
-		memcpy(&spec[n_specs], &tspec, sizeof(spec[0]));
-		n_specs++;
+		G.spec = xrealloc_vector(G.spec, 4, G.n_specs);
+		memcpy(&G.spec[G.n_specs], &tspec, sizeof(G.spec[0]));
+		G.n_specs++;
 	}
 }
 
@@ -763,7 +777,7 @@ skip(off_t n_skip)
 	if (n_skip == 0)
 		return;
 
-	while (in_stream) { /* !EOF */
+	while (G.in_stream) { /* !EOF */
 		struct stat file_stats;
 
 		/* First try seeking.  For large offsets, this extra work is
@@ -781,15 +795,15 @@ skip(off_t n_skip)
 			   If the number of bytes left to skip is at least
 			   as large as the size of the current file, we can
 			   decrement n_skip and go on to the next file.  */
-		if (fstat(fileno(in_stream), &file_stats) == 0
+		if (fstat(fileno(G.in_stream), &file_stats) == 0
 		 && S_ISREG(file_stats.st_mode) && file_stats.st_size > 0
 		) {
 			if (file_stats.st_size < n_skip) {
 				n_skip -= file_stats.st_size;
 				/* take "check & close / open_next" route */
 			} else {
-				if (fseeko(in_stream, n_skip, SEEK_CUR) != 0)
-					exit_code = 1;
+				if (fseeko(G.in_stream, n_skip, SEEK_CUR) != 0)
+					G.exit_code = 1;
 				return;
 			}
 		} else {
@@ -802,7 +816,7 @@ skip(off_t n_skip)
 			while (n_skip > 0) {
 				if (n_skip < n_bytes_to_read)
 					n_bytes_to_read = n_skip;
-				n_bytes_read = fread(buf, 1, n_bytes_to_read, in_stream);
+				n_bytes_read = fread(buf, 1, n_bytes_to_read, G.in_stream);
 				n_skip -= n_bytes_read;
 				if (n_bytes_read != n_bytes_to_read)
 					break; /* EOF on this file or error */
@@ -855,7 +869,7 @@ static void
 format_address_label(off_t address, char c)
 {
 	format_address_std(address, ' ');
-	format_address_paren(address + pseudo_offset, c);
+	format_address_paren(address + G_pseudo_offset, c);
 }
 #endif
 
@@ -886,36 +900,34 @@ static void
 write_block(off_t current_offset, size_t n_bytes,
 		const char *prev_block, const char *curr_block)
 {
-	static char first = 1;
-	static char prev_pair_equal = 0;
-	size_t i;
+	unsigned i;
 
 	if (!(option_mask32 & OPT_v)
-	 && !first
-	 && n_bytes == bytes_per_block
-	 && memcmp(prev_block, curr_block, bytes_per_block) == 0
+	 && G.not_first
+	 && n_bytes == G.bytes_per_block
+	 && memcmp(prev_block, curr_block, G.bytes_per_block) == 0
 	) {
-		if (prev_pair_equal) {
+		if (G.prev_pair_equal) {
 			/* The two preceding blocks were equal, and the current
 			   block is the same as the last one, so print nothing.  */
 		} else {
 			puts("*");
-			prev_pair_equal = 1;
+			G.prev_pair_equal = 1;
 		}
 	} else {
-		first = 0;
-		prev_pair_equal = 0;
-		for (i = 0; i < n_specs; i++) {
+		G.not_first = 1;
+		G.prev_pair_equal = 0;
+		for (i = 0; i < G.n_specs; i++) {
 			if (i == 0)
-				format_address(current_offset, '\0');
+				G.format_address(current_offset, '\0');
 			else
 				printf("%*s", address_pad_len_char - '0', "");
-			(*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string);
-			if (spec[i].hexl_mode_trailer) {
+			(*G.spec[i].print_function) (n_bytes, curr_block, G.spec[i].fmt_string);
+			if (G.spec[i].hexl_mode_trailer) {
 				/* space-pad out to full line width, then dump the trailer */
-				unsigned datum_width = width_bytes[spec[i].size];
-				unsigned blank_fields = (bytes_per_block - n_bytes) / datum_width;
-				unsigned field_width = spec[i].field_width + 1;
+				unsigned datum_width = width_bytes[G.spec[i].size];
+				unsigned blank_fields = (G.bytes_per_block - n_bytes) / datum_width;
+				unsigned field_width = G.spec[i].field_width + 1;
 				printf("%*s", blank_fields * field_width, "");
 				dump_hexl_mode_trailer(n_bytes, curr_block);
 			}
@@ -927,19 +939,19 @@ write_block(off_t current_offset, size_t n_bytes,
 static void
 read_block(size_t n, char *block, size_t *n_bytes_in_buffer)
 {
-	assert(0 < n && n <= bytes_per_block);
+	assert(0 < n && n <= G.bytes_per_block);
 
 	*n_bytes_in_buffer = 0;
 
 	if (n == 0)
 		return;
 
-	while (in_stream != NULL) { /* EOF.  */
+	while (G.in_stream != NULL) { /* EOF.  */
 		size_t n_needed;
 		size_t n_read;
 
 		n_needed = n - *n_bytes_in_buffer;
-		n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, in_stream);
+		n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, G.in_stream);
 		*n_bytes_in_buffer += n_read;
 		if (n_read == n_needed)
 			break;
@@ -958,8 +970,8 @@ get_lcm(void)
 	size_t i;
 	int l_c_m = 1;
 
-	for (i = 0; i < n_specs; i++)
-		l_c_m = lcm(l_c_m, width_bytes[(int) spec[i].size]);
+	for (i = 0; i < G.n_specs; i++)
+		l_c_m = lcm(l_c_m, width_bytes[(int) G.spec[i].size]);
 	return l_c_m;
 }
 
@@ -980,8 +992,8 @@ dump(off_t current_offset, off_t end_offset)
 	int idx;
 	size_t n_bytes_read;
 
-	block[0] = xmalloc(2 * bytes_per_block);
-	block[1] = block[0] + bytes_per_block;
+	block[0] = xmalloc(2 * G.bytes_per_block);
+	block[1] = block[0] + G.bytes_per_block;
 
 	idx = 0;
 	if (option_mask32 & OPT_N) {
@@ -991,21 +1003,21 @@ dump(off_t current_offset, off_t end_offset)
 				n_bytes_read = 0;
 				break;
 			}
-			n_needed = MIN(end_offset - current_offset, (off_t) bytes_per_block);
+			n_needed = MIN(end_offset - current_offset, (off_t) G.bytes_per_block);
 			read_block(n_needed, block[idx], &n_bytes_read);
-			if (n_bytes_read < bytes_per_block)
+			if (n_bytes_read < G.bytes_per_block)
 				break;
-			assert(n_bytes_read == bytes_per_block);
+			assert(n_bytes_read == G.bytes_per_block);
 			write_block(current_offset, n_bytes_read, block[idx ^ 1], block[idx]);
 			current_offset += n_bytes_read;
 			idx ^= 1;
 		}
 	} else {
 		while (1) {
-			read_block(bytes_per_block, block[idx], &n_bytes_read);
-			if (n_bytes_read < bytes_per_block)
+			read_block(G.bytes_per_block, block[idx], &n_bytes_read);
+			if (n_bytes_read < G.bytes_per_block)
 				break;
-			assert(n_bytes_read == bytes_per_block);
+			assert(n_bytes_read == G.bytes_per_block);
 			write_block(current_offset, n_bytes_read, block[idx ^ 1], block[idx]);
 			current_offset += n_bytes_read;
 			idx ^= 1;
@@ -1028,7 +1040,7 @@ dump(off_t current_offset, off_t end_offset)
 		current_offset += n_bytes_read;
 	}
 
-	format_address(current_offset, '\n');
+	G.format_address(current_offset, '\n');
 
 	if ((option_mask32 & OPT_N) && current_offset >= end_offset)
 		check_and_close();
@@ -1059,16 +1071,16 @@ dump(off_t current_offset, off_t end_offset)
 static void
 dump_strings(off_t address, off_t end_offset)
 {
-	unsigned bufsize = MAX(100, string_min);
+	unsigned bufsize = MAX(100, G.string_min);
 	unsigned char *buf = xmalloc(bufsize);
 
 	while (1) {
 		size_t i;
 		int c;
 
-		/* See if the next 'string_min' chars are all printing chars.  */
+		/* See if the next 'G.string_min' chars are all printing chars.  */
  tryline:
-		if ((option_mask32 & OPT_N) && (end_offset - string_min <= address))
+		if ((option_mask32 & OPT_N) && (end_offset - G.string_min <= address))
 			break;
 		i = 0;
 		while (!(option_mask32 & OPT_N) || address < end_offset) {
@@ -1077,8 +1089,8 @@ dump_strings(off_t address, off_t end_offset)
 				buf = xrealloc(buf, bufsize);
 			}
 
-			while (in_stream) { /* !EOF */
-				c = fgetc(in_stream);
+			while (G.in_stream) { /* !EOF */
+				c = fgetc(G.in_stream);
 				if (c != EOF)
 					goto got_char;
 				check_and_close();
@@ -1095,12 +1107,12 @@ dump_strings(off_t address, off_t end_offset)
 			buf[i++] = c;		/* String continues; store it all.  */
 		}
 
-		if (i < string_min)		/* Too short! */
+		if (i < G.string_min)		/* Too short! */
 			goto tryline;
 
 		/* If we get here, the string is all printable and NUL-terminated */
 		buf[i] = 0;
-		format_address(address - i - 1, ' ');
+		G.format_address(address - i - 1, ' ');
 
 		for (i = 0; (c = buf[i]); i++) {
 			switch (c) {
@@ -1118,7 +1130,7 @@ dump_strings(off_t address, off_t end_offset)
 	}
 
 	/* We reach this point only if we search through
-	   (max_bytes_to_format - string_min) bytes before reaching EOF.  */
+	   (max_bytes_to_format - G.string_min) bytes before reaching EOF.  */
 	check_and_close();
  ret:
 	free(buf);
@@ -1190,8 +1202,10 @@ int od_main(int argc UNUSED_PARAM, char **argv)
 	/* The maximum number of bytes that will be formatted.  */
 	off_t max_bytes_to_format = 0;
 
-	spec = NULL;
-	format_address = format_address_std;
+	INIT_G();
+
+	/*G.spec = NULL; - already is */
+	G.format_address = format_address_std;
 	address_base_char = 'o';
 	address_pad_len_char = '7';
 
@@ -1217,7 +1231,7 @@ int od_main(int argc UNUSED_PARAM, char **argv)
 			bb_error_msg_and_die("bad output address radix "
 				"'%c' (must be [doxn])", str_A[0]);
 		pos = p - doxn;
-		if (pos == 3) format_address = format_address_none;
+		if (pos == 3) G.format_address = format_address_none;
 		address_base_char = doxn_address_base_char[pos];
 		address_pad_len_char = doxn_address_pad_len_char[pos];
 	}
@@ -1240,11 +1254,11 @@ int od_main(int argc UNUSED_PARAM, char **argv)
 	if (opt & OPT_x) decode_format_string("x2");
 	if (opt & OPT_s) decode_format_string("d2");
 	if (opt & OPT_S) {
-		string_min = xstrtou_sfx(str_S, 0, bkm_suffixes);
+		G.string_min = xstrtou_sfx(str_S, 0, bkm_suffixes);
 	}
 
 	// Bloat:
-	//if ((option_mask32 & OPT_S) && n_specs > 0)
+	//if ((option_mask32 & OPT_S) && G.n_specs > 0)
 	//	bb_error_msg_and_die("no type may be specified when dumping strings");
 
 	/* If the --traditional option is used, there may be from
@@ -1300,14 +1314,14 @@ int od_main(int argc UNUSED_PARAM, char **argv)
 			}
 
 			if (pseudo_start >= 0) {
-				if (format_address == format_address_none) {
+				if (G.format_address == format_address_none) {
 					address_base_char = 'o';
 					address_pad_len_char = '7';
-					format_address = format_address_paren;
+					G.format_address = format_address_paren;
 				} else {
-					format_address = format_address_label;
+					G.format_address = format_address_label;
 				}
-				pseudo_offset = pseudo_start - n_bytes_to_skip;
+				G_pseudo_offset = pseudo_start - n_bytes_to_skip;
 			}
 		}
 		/* else: od --traditional (without args) */
@@ -1320,45 +1334,45 @@ int od_main(int argc UNUSED_PARAM, char **argv)
 			bb_error_msg_and_die("SKIP + SIZE is too large");
 	}
 
-	if (n_specs == 0) {
+	if (G.n_specs == 0) {
 		decode_format_string("o2");
-		/*n_specs = 1; - done by decode_format_string */
+		/*G.n_specs = 1; - done by decode_format_string */
 	}
 
 	/* If no files were listed on the command line,
 	   set the global pointer FILE_LIST so that it
 	   references the null-terminated list of one name: "-".  */
-	file_list = bb_argv_dash;
+	G.file_list = bb_argv_dash;
 	if (argv[0]) {
 		/* Set the global pointer FILE_LIST so that it
 		   references the first file-argument on the command-line.  */
-		file_list = (char const *const *) argv;
+		G.file_list = (char const *const *) argv;
 	}
 
 	/* Open the first input file */
 	open_next_file();
 	/* Skip over any unwanted header bytes */
 	skip(n_bytes_to_skip);
-	if (!in_stream)
+	if (!G.in_stream)
 		return EXIT_FAILURE;
 
 	/* Compute output block length */
 	l_c_m = get_lcm();
 
 	if (opt & OPT_w) { /* -w: width */
-		if (!bytes_per_block || bytes_per_block % l_c_m != 0) {
+		if (!G.bytes_per_block || G.bytes_per_block % l_c_m != 0) {
 			bb_error_msg("warning: invalid width %u; using %d instead",
-					(unsigned)bytes_per_block, l_c_m);
-			bytes_per_block = l_c_m;
+					(unsigned)G.bytes_per_block, l_c_m);
+			G.bytes_per_block = l_c_m;
 		}
 	} else {
-		bytes_per_block = l_c_m;
+		G.bytes_per_block = l_c_m;
 		if (l_c_m < DEFAULT_BYTES_PER_BLOCK)
-			bytes_per_block *= DEFAULT_BYTES_PER_BLOCK / l_c_m;
+			G.bytes_per_block *= DEFAULT_BYTES_PER_BLOCK / l_c_m;
 	}
 
 #ifdef DEBUG
-	for (i = 0; i < n_specs; i++) {
+	for (i = 0; i < G.n_specs; i++) {
 		printf("%d: fmt=\"%s\" width=%d\n",
 			i, spec[i].fmt_string, width_bytes[spec[i].size]);
 	}
@@ -1372,5 +1386,5 @@ int od_main(int argc UNUSED_PARAM, char **argv)
 	if (fclose(stdin))
 		bb_perror_msg_and_die(bb_msg_standard_input);
 
-	return exit_code;
+	return G.exit_code;
 }


More information about the busybox-cvs mailing list