>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