>From bb5162a7521aee6b95c902acc65c1d3800ba4f30 Mon Sep 17 00:00:00 2001
From: Assaf Gordon
Date: Tue, 4 Dec 2012 15:32:05 -0500
Subject: [PATCH] numfmt: stub code for new program
---
build-aux/gen-lists-of-programs.sh | 1 +
src/.gitignore | 1 +
src/numfmt.c | 298 ++++++++++++++++++++++++++++++++++++
3 files changed, 300 insertions(+), 0 deletions(-)
create mode 100644 src/numfmt.c
diff --git a/build-aux/gen-lists-of-programs.sh b/build-aux/gen-lists-of-programs.sh
index 212ce02..bf63ee3 100755
--- a/build-aux/gen-lists-of-programs.sh
+++ b/build-aux/gen-lists-of-programs.sh
@@ -85,6 +85,7 @@ normal_progs='
nl
nproc
nohup
+ numfmt
od
paste
pathchk
diff --git a/src/.gitignore b/src/.gitignore
index 18cccc1..25573df 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -59,6 +59,7 @@ nice
nl
nohup
nproc
+numfmt
od
paste
pathchk
diff --git a/src/numfmt.c b/src/numfmt.c
new file mode 100644
index 0000000..e513194
--- /dev/null
+++ b/src/numfmt.c
@@ -0,0 +1,298 @@
+/* Reformat numbers like 11505426432 to the more human-readable 11G
+ Copyright (C) 2012 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see . */
+
+#include
+#include
+#include
+#include
+
+#include "argmatch.h"
+#include "error.h"
+#include "system.h"
+#include "xstrtol.h"
+
+/* The official name of this program (e.g., no 'g' prefix). */
+#define PROGRAM_NAME "numfmt"
+
+#define AUTHORS proper_name ("XXXX")
+
+#define BUFFER_SIZE (16 * 1024)
+
+enum
+{
+ FROM_OPTION = CHAR_MAX + 1,
+ FROM_UNIT_OPTION,
+ TO_OPTION,
+ TO_UNIT_OPTION,
+ ROUND_OPTION,
+ SUFFIX_OPTION
+};
+
+enum scale_type
+{
+scale_none, /* the default: no scaling */
+scale_auto, /* --from only */
+scale_SI,
+scale_IEC,
+scale_custom /* --to only, custom scale */
+};
+
+static char const *const scale_from_args[] =
+{
+"auto", "SI", "IEC", NULL
+};
+static enum scale_type const scale_from_types[] =
+{
+scale_auto, scale_SI, scale_IEC
+};
+
+static char const *const scale_to_args[] =
+{
+"SI", "IEC", NULL
+};
+static enum scale_type const scale_to_types[] =
+{
+scale_SI, scale_IEC
+};
+
+
+enum round_type
+{
+round_ceiling,
+round_floor,
+round_nearest
+};
+
+static char const *const round_args[] =
+{
+"ceiling","floor","nearest", NULL
+};
+
+static enum round_type const round_types[] =
+{
+round_ceiling,round_floor,round_nearest
+};
+
+static struct option const longopts[] =
+{
+ {"from", required_argument, NULL, FROM_OPTION},
+ {"from-unit", required_argument, NULL, FROM_UNIT_OPTION},
+ {"to", required_argument, NULL, TO_OPTION},
+ {"to-unit", required_argument, NULL, TO_UNIT_OPTION},
+ {"round", required_argument, NULL, ROUND_OPTION},
+ {"format", required_argument, NULL, 'f'},
+ {"suffix", required_argument, NULL, SUFFIX_OPTION},
+ {GETOPT_HELP_OPTION_DECL},
+ {GETOPT_VERSION_OPTION_DECL},
+ {NULL, 0, NULL, 0}
+};
+
+
+enum scale_type scale_from=scale_none;
+enum scale_type scale_to=scale_none;
+enum round_type _round=round_ceiling;
+char const *format_str = NULL;
+const char *suffix = NULL;
+uintmax_t from_unit_size=1;
+uintmax_t to_unit_size=1;
+
+/* Convert a string of decimal digits, N_STRING, with an optional suffinx
+ to an integral value. Upon successful conversion,
+ return that value. If it cannot be converted, give a diagnostic and exit.
+*/
+static uintmax_t
+string_to_integer (const char *n_string)
+{
+ strtol_error s_err;
+ uintmax_t n;
+
+ s_err = xstrtoumax (n_string, NULL, 10, &n, "bkKmMGTPEZY0");
+
+ if (s_err == LONGINT_OVERFLOW)
+ {
+ error (EXIT_FAILURE, 0,
+ _("%s: unit size is so large that it is not representable"),
+ n_string);
+ }
+
+ if (s_err != LONGINT_OK)
+ {
+ error (EXIT_FAILURE, 0, _("%s: invalid unit size"), n_string);
+ }
+ return n;
+}
+
+
+
+void
+usage (int status)
+{
+ if (status != EXIT_SUCCESS)
+ emit_try_help ();
+ else
+ {
+ printf (_("\
+Usage: %s [OPTIONS] [NUMBER]\n\
+"),
+ program_name);
+ fputs (_("\
+Reformats NUMBER(s) to/from human-readable values.\n\
+Numbers can be processed either from stdin or command arguments.\n\
+\n\
+"), stdout);
+ fputs (_("\
+ --from=UNIT Auto-scale input numbers (auto, SI, IEC)\n\
+ If not specified, input suffixed are ignored.\n\
+ --from-unit=N Specifiy the input unit size (instead of the default 1).\n\
+ --to=UNIT Auto-scale output numbres (SI,IEC,).\n\
+ If not specified, XXXX\n\
+ --to-unit=N Specifiy the output unit size (instead of the default 1).\n\
+ --rount=METHOD Round input numbers. METHOD can be:\n\
+ ceiling (the default), floor, nearest\n\
+ -f, --format=FORMAT use printf style output FORMAT.\n\
+ Default output format is %d .\n\
+ --suffix=SUFFIX XXXX\n\
+ \n\
+"), stdout);
+ fputs (HELP_OPTION_DESCRIPTION, stdout);
+ fputs (VERSION_OPTION_DESCRIPTION, stdout);
+
+ fputs (_("\
+\n\
+UNIT options:\n\
+ auto ('--from' only):\n\
+ 1K = 1000\n\
+ 1Ki = 1024\n\
+ 1G = 1000000\n\
+ 1Gi = 1048576\n\
+ SI:\n\
+ 1K* = 1000\n\
+ (additional suffixes after K/G/T do not alter the scale)\n\
+ IEC:\n\
+ 1K* = 1024\n\
+ (additional suffixes after K/G/T do not alter the scale)\n\
+ ('--to' only):\n\
+ Use number N as the scale.\n\
+\n\
+"), stdout);
+
+ printf (_("\
+\n\
+Examples:\n\
+ %s --to=SI 1000 -> \"1K\"\n\
+ echo 1K | %s --from=SI -> \"1000\"\n\
+ echo 1K | %s --from=IEC -> \"1024\"\n\
+"),
+ program_name, program_name, program_name);
+ emit_ancillary_info ();
+ }
+ exit (status);
+}
+
+static void format_number(const char* str)
+{
+ printf("Reformatting: %s\n", str);
+}
+
+int
+main (int argc, char **argv)
+{
+ initialize_main (&argc, &argv);
+ set_program_name (argv[0]);
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+
+ atexit (close_stdout);
+
+ while (true)
+ {
+ int c = getopt_long (argc, argv, "f:", longopts, NULL);
+
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case FROM_OPTION:
+ scale_from = XARGMATCH ("--from", optarg, scale_from_args, scale_from_types);
+ break;
+
+ case FROM_UNIT_OPTION:
+ from_unit_size = string_to_integer(optarg);
+ break;
+
+ case TO_OPTION:
+ //TODO: add custom handling for numeric/custom scale values
+ scale_to = XARGMATCH ("--to", optarg, scale_to_args, scale_to_types);
+ break;
+
+ case TO_UNIT_OPTION:
+ to_unit_size = string_to_integer(optarg);
+ break;
+
+ case ROUND_OPTION:
+ _round = XARGMATCH ("--round", optarg, round_args, round_types);
+ break;
+
+ case 'f':
+ format_str = optarg;
+ break;
+
+ case SUFFIX_OPTION:
+ suffix = optarg;
+ break;
+
+ case_GETOPT_HELP_CHAR;
+ case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
+
+ default:
+ usage (EXIT_FAILURE);
+ }
+ }
+
+#if 0
+ printf("scale_from = %d\n", scale_from);
+ printf("scale_to = %d\n", scale_to);
+ printf("from_unit_size = %zu\n", from_unit_size);
+ printf("to_unit_size = %zu\n", to_unit_size);
+ printf("round = %d\n", _round);
+ printf("format = '%s'\n", format_str);
+ printf("suffix = '%s'\n", suffix);
+#endif
+
+ if (argc > optind)
+ {
+ for (; optind < argc; optind++)
+ format_number(argv[optind]);
+ }
+ else
+ {
+ char buf[BUFFER_SIZE + 1];
+
+ //TODO: allow multiple values on each line?
+ //TODO: support '--field=NUM' feature
+ while ( fgets(buf,BUFFER_SIZE,stdin) != NULL )
+ format_number(buf);
+
+ if (ferror(stdin))
+ {
+ error(0,errno,_("error reading input"));
+ }
+ }
+
+ exit (EXIT_SUCCESS);
+}
--
1.7.7.4