rdmsr: fix formatting options, reorganize for readability

Unbreak the formatting options (which were broken by the --all patch),
move them all to a common structure, and reorganize the various static
functions into a more logical order.  Remove dependencies on global
variables.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
diff --git a/rdmsr.c b/rdmsr.c
index 7062e37..3f5e2b3 100644
--- a/rdmsr.c
+++ b/rdmsr.c
@@ -53,7 +53,7 @@
 
 /* Number of decimal digits for a certain number of bits */
 /* (int) ceil(log(2^n)/log(10)) */
-int decdigits[] = {
+static const int decdigits[] = {
 	1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5,
 	5, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10,
 	10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15,
@@ -73,7 +73,7 @@
 
 const char *program;
 
-void usage(void)
+static void usage(void)
 {
 	fprintf(stderr,
 		"Usage: %s [options] regno\n"
@@ -92,132 +92,20 @@
 		"  --bitfield h:l -f  Output bits [h:l] only\n", program);
 }
 
-void rdmsr_on_cpu(uint32_t reg, int cpu);
+struct format {
+	unsigned int mode;
+	unsigned int highbit;
+	unsigned int lowbit;
+};
 
-void rdmsr_on_all_cpus(uint32_t reg)
-{
-	FILE *fp;
-	int retval;
-
-	fp = fopen(proc_stat, "r");
-	if (fp == NULL) {
-		perror(proc_stat);
-		exit(-1);
-	}
-
-	retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
-	if (retval != 0) {
-		perror("/proc/stat format");
-		exit(-1);
-	}
-
-	for (;;) {
-		int cpu;
-
-		retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d"
-			" %*d\n", &cpu);
-		if (retval != 1)
-			return;
-
-		rdmsr_on_cpu(reg, cpu);
-	}
-	fclose(fp);
-}
-
-unsigned int highbit = 63, lowbit = 0, bits;
-int mode = mo_hex;
-
-int main(int argc, char *argv[])
-{
-	uint32_t reg;
-	int c;
-	int cpu = 0;
-	unsigned long arg;
-	char *endarg;
-
-	program = argv[0];
-
-	while ((c =
-		getopt_long(argc, argv, short_options, long_options,
-			    NULL)) != -1) {
-		switch (c) {
-		case 'h':
-			usage();
-			exit(0);
-		case 'V':
-			fprintf(stderr, "%s: version %s\n", program,
-				VERSION_STRING);
-			exit(0);
-		case 'x':
-			mode = (mode & ~mo_mask) | mo_hex;
-			break;
-		case 'X':
-			mode = (mode & ~mo_mask) | mo_chx;
-			break;
-		case 'o':
-			mode = (mode & ~mo_mask) | mo_oct;
-			break;
-		case 'd':
-			mode = (mode & ~mo_mask) | mo_dec;
-			break;
-		case 'r':
-			mode = (mode & ~mo_mask) | mo_raw;
-			break;
-		case 'u':
-			mode = (mode & ~mo_mask) | mo_uns;
-			break;
-		case 'c':
-			mode |= mo_c;
-			break;
-		case '0':
-			mode |= mo_fill;
-			break;
-		case 'a':
-			cpu = -1;
-			break;
-		case 'p':
-			arg = strtoul(optarg, &endarg, 0);
-			if (*endarg || arg > 255) {
-				usage();
-				exit(127);
-			}
-			cpu = (int)arg;
-			break;
-		case 'f':
-			if (sscanf(optarg, "%u:%u", &highbit, &lowbit) != 2 ||
-			    highbit > 63 || lowbit > highbit) {
-				usage();
-				exit(127);
-			}
-			break;
-		default:
-			usage();
-			exit(127);
-		}
-	}
-
-	if (optind != argc - 1) {
-		/* Should have exactly one argument */
-		usage();
-		exit(127);
-	}
-
-	reg = strtoul(argv[optind], NULL, 0);
-
-	if (cpu == -1)
-		rdmsr_on_all_cpus(reg);
-	else
-		rdmsr_on_cpu(reg, cpu);
-	exit(0);
-}
-void rdmsr_on_cpu(uint32_t reg, int cpu)
+static void rdmsr_on_cpu(const struct format *fmt, uint32_t reg, int cpu)
 {
 	uint64_t data;
 	int fd;
-	int mode = mo_hex;
 	char *pat;
 	int width;
 	char msr_file_name[64];
+	unsigned int bits;
 
 	sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu);
 	fd = open(msr_file_name, O_RDONLY);
@@ -249,17 +137,17 @@
 
 	close(fd);
 
-	bits = highbit - lowbit + 1;
+	bits = fmt->highbit - fmt->lowbit + 1;
 	if (bits < 64) {
 		/* Show only part of register */
-		data >>= lowbit;
+		data >>= fmt->lowbit;
 		data &= (1ULL << bits) - 1;
 	}
 
 	pat = NULL;
 
 	width = 1;		/* Default */
-	switch (mode) {
+	switch (fmt->mode) {
 	case mo_hex:
 		pat = "%*llx\n";
 		break;
@@ -361,3 +249,123 @@
 		printf(pat, width, data);
 	return;
 }
+
+static void rdmsr_on_all_cpus(const struct format *fmt, uint32_t reg)
+{
+	FILE *fp;
+	int retval;
+
+	fp = fopen(proc_stat, "r");
+	if (fp == NULL) {
+		perror(proc_stat);
+		exit(-1);
+	}
+
+	retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
+	if (retval != 0) {
+		perror("/proc/stat format");
+		exit(-1);
+	}
+
+	for (;;) {
+		int cpu;
+
+		retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d"
+			" %*d\n", &cpu);
+		if (retval != 1)
+			return;
+
+		rdmsr_on_cpu(fmt, reg, cpu);
+	}
+	fclose(fp);
+}
+
+int main(int argc, char *argv[])
+{
+	uint32_t reg;
+	int c;
+	int cpu = 0;
+	unsigned long arg;
+	char *endarg;
+	struct format fmt;
+
+	fmt.mode    = mo_hex;
+	fmt.highbit = 63;
+	fmt.lowbit  = 0;
+
+	program = argv[0];
+
+	while ((c = getopt_long(argc, argv, short_options,
+				long_options, NULL)) != -1) {
+		switch (c) {
+		case 'h':
+			usage();
+			exit(0);
+		case 'V':
+			fprintf(stderr, "%s: version %s\n", program,
+				VERSION_STRING);
+			exit(0);
+		case 'x':
+			fmt.mode = (fmt.mode & ~mo_mask) | mo_hex;
+			break;
+		case 'X':
+			fmt.mode = (fmt.mode & ~mo_mask) | mo_chx;
+			break;
+		case 'o':
+			fmt.mode = (fmt.mode & ~mo_mask) | mo_oct;
+			break;
+		case 'd':
+			fmt.mode = (fmt.mode & ~mo_mask) | mo_dec;
+			break;
+		case 'r':
+			fmt.mode = (fmt.mode & ~mo_mask) | mo_raw;
+			break;
+		case 'u':
+			fmt.mode = (fmt.mode & ~mo_mask) | mo_uns;
+			break;
+		case 'c':
+			fmt.mode |= mo_c;
+			break;
+		case '0':
+			fmt.mode |= mo_fill;
+			break;
+		case 'a':
+			cpu = -1;
+			break;
+		case 'p':
+			arg = strtoul(optarg, &endarg, 0);
+			if (*endarg || arg > 255) {
+				usage();
+				exit(127);
+			}
+			cpu = (int)arg;
+			break;
+		case 'f':
+			if (sscanf(optarg, "%u:%u", &fmt.highbit, &fmt.lowbit)
+			    != 2 ||
+			    fmt.highbit > 63 ||
+			    fmt.lowbit > fmt.highbit) {
+				usage();
+				exit(127);
+			}
+			break;
+		default:
+			usage();
+			exit(127);
+		}
+	}
+
+	if (optind != argc - 1) {
+		/* Should have exactly one argument */
+		usage();
+		exit(127);
+	}
+
+	reg = strtoul(argv[optind], NULL, 0);
+
+	if (cpu == -1)
+		rdmsr_on_all_cpus(&fmt, reg);
+	else
+		rdmsr_on_cpu(&fmt, reg, cpu);
+	exit(0);
+}