123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817 |
- #include "sys-defines.h"
- #include "libcommon.h"
- #include "getopt.h"
- typedef enum
- {
- T_ASCII, T_SINGLE, T_DOUBLE, T_INTEGER
- }
- data_type;
- data_type input_type = T_ASCII;
- data_type output_type = T_ASCII;
- const char *progname = "double";
- const char *written = "Written by Robert S. Maier and Rich Murphey.";
- const char *copyright = "Copyright (C) 2009 Free Software Foundation, Inc.";
- const char *usage_appendage = " [FILE]...\n\
- With no FILE, or when FILE is -, read standard input.\n";
- int precision = 8;
- #define ARG_NONE 0
- #define ARG_REQUIRED 1
- #define ARG_OPTIONAL 2
- struct option long_options[] =
- {
-
- {"input-type", ARG_REQUIRED, NULL, 'I'},
- {"output-type", ARG_REQUIRED, NULL, 'O'},
- {"precision", ARG_REQUIRED, NULL, 'q'},
-
- {"times-file", ARG_REQUIRED, NULL, 'T'},
- {"plus-file", ARG_REQUIRED, NULL, 'P'},
- {"pre-join-file", ARG_REQUIRED, NULL, 'j'},
- {"post-join-file", ARG_REQUIRED, NULL, 'J'},
-
- {"times", ARG_REQUIRED, NULL, 't'},
- {"plus", ARG_REQUIRED, NULL, 'p'},
-
- {"record-length", ARG_REQUIRED, NULL, 'R'},
- {"fields", ARG_OPTIONAL, NULL, 'f'},
- {"dataset-limits", ARG_OPTIONAL, NULL, 'd'},
-
- {"version", ARG_NONE, NULL, 'V' << 8},
- {"help", ARG_NONE, NULL, 'h' << 8},
- {NULL, 0, 0, 0}
- };
- int hidden_options[] = { 0 };
- bool mung_dataset (FILE *input, int record_length, int *field_array, int field_array_len, double scale, double baseline, FILE *add_fp, FILE *mult_fp, FILE *pre_join_fp, FILE *post_join_fp, int precision, bool suppress);
- bool read_float (FILE *input, double *dptr);
- bool skip_whitespace (FILE *stream);
- bool write_float (double data, int precision);
- int get_record (FILE *input, double *record, int record_length);
- void maybe_emit_oob_warning (void);
- void open_file (char *name, FILE **fpp);
- void output_dataset_separator (void);
- void set_format_type (char *s, data_type *typep);
- int
- main (int argc, char **argv)
- {
- int option;
- int opt_index;
- int errcnt = 0;
- int i;
- bool show_version = false;
- bool show_usage = false;
- char *add_file = NULL, *mult_file = NULL;
- char *pre_join_file = NULL, *post_join_file = NULL;
- FILE *add_fp = NULL, *mult_fp = NULL;
- FILE *pre_join_fp = NULL, *post_join_fp = NULL;
- double scale = 1.0, baseline = 0.0;
- int record_length = 1;
- int dataset_min = 0, dataset_max = INT_MAX, dataset_spacing = 1;
- int local_dataset_min, local_dataset_max, local_dataset_spacing;
- int *field_array = NULL;
- int field_array_len = 0;
- int dataset_index = 0;
- bool more_points, dataset_printed = false;
- for ( ; ; )
- {
- option = getopt_long (argc, argv, "I:O:q:T:P:j:J:t:p:R:f::d::", long_options, &opt_index);
- if (option == 0)
- option = long_options[opt_index].val;
- switch (option)
- {
-
- case 'V' << 8:
- show_version = true;
- break;
- case 'h' << 8:
- show_usage = true;
- break;
-
- case 'I':
- set_format_type (optarg, &input_type);
- break;
- case 'O':
- set_format_type (optarg, &output_type);
- break;
- case 'T':
- mult_file = xstrdup (optarg);
- break;
- case 'P':
- add_file = xstrdup (optarg);
- break;
- case 'j':
- pre_join_file = xstrdup (optarg);
- break;
- case 'J':
- post_join_file = xstrdup (optarg);
- break;
- case 't':
- if (sscanf (optarg, "%lf", &scale) <= 0)
- {
- fprintf (stderr,
- "%s: error: the multiplicative constant `%s' is bad\n",
- progname, optarg);
- return EXIT_FAILURE;
- }
- break;
- case 'p':
- if (sscanf (optarg, "%lf", &baseline) <= 0)
- {
- fprintf (stderr,
- "%s: error: the additive constant `%s' is bad\n",
- progname, optarg);
- return EXIT_FAILURE;
- }
- break;
- case 'q':
- if ((sscanf (optarg, "%d", &precision) <= 0)
- || (precision < 1))
- {
- fprintf (stderr,
- "%s: error: the precision `%s' is bad (it should be an integer greater than or equal to 1)\n",
- progname, optarg);
- return EXIT_FAILURE;
- }
- break;
- case 'R':
- if ((sscanf (optarg, "%d", &record_length) <= 0)
- || (record_length < 1))
- {
- fprintf (stderr,
- "%s: error: the record length `%s' is bad (it should be an integer greater than or equal to 1)\n",
- progname, optarg);
- return EXIT_FAILURE;
- }
- break;
-
- case 'd':
- if (optind >= argc)
- break;
- if (sscanf (argv[optind], "%d", &local_dataset_min) <= 0)
- break;
- dataset_min = local_dataset_min;
- optind++;
- if (optind >= argc)
- break;
- if (sscanf (argv [optind], "%d", &local_dataset_max) <= 0)
- break;
- dataset_max = local_dataset_max;
- optind++;
- if (optind >= argc)
- break;
- if (sscanf (argv [optind], "%d", &local_dataset_spacing) <= 0)
- break;
- dataset_spacing = local_dataset_spacing;
- optind++;
- break;
- case 'f':
- for ( ; ; )
- {
- int field_index;
- if (optind >= argc)
- break;
- if (sscanf (argv[optind], "%d", &field_index) <= 0)
- break;
- if (field_index < 0)
- {
- fprintf (stderr, "%s: error: the field index `%d' is bad (it should be greater than or equal to 0)\n",
- progname, field_index);
- return EXIT_FAILURE;
- }
- if (field_array_len == 0)
- field_array =
- (int *)xmalloc ((++field_array_len) * sizeof(int));
- else
- field_array =
- (int *)xrealloc (field_array,
- (++field_array_len) * sizeof(int));
- field_array[field_array_len - 1] = field_index;
- optind++;
- }
- break;
-
- default:
- errcnt++;
- break;
- }
- if ((option == EOF))
- {
- errcnt--;
- break;
- }
- }
-
- if (errcnt > 0)
- {
- fprintf (stderr, "Try `%s --help' for more information\n", progname);
- return EXIT_FAILURE;
- }
- if (show_version)
- {
- display_version (progname, written, copyright);
- return EXIT_SUCCESS;
- }
- if (show_usage)
- {
- display_usage (progname, hidden_options, usage_appendage, 0);
- return EXIT_SUCCESS;
- }
-
- if (dataset_spacing < 1)
- {
- fprintf (stderr, "%s: error: the dataset spacing `%d' is bad (it should be positive)\n",
- progname, dataset_spacing);
- return EXIT_FAILURE;
- }
- for (i = 0; i < field_array_len; i++)
- if (field_array[i] >= record_length)
- {
- fprintf (stderr,
- "%s: error: at least one field index is out of bounds\n", progname);
- return EXIT_FAILURE;
- }
-
- if (field_array_len == 0)
- {
- field_array =
- (int *)xmalloc ((record_length) * sizeof(int));
- field_array_len = record_length;
- for (i = 0; i < field_array_len; i++)
- field_array[i] = i;
- }
-
- if (add_file)
- open_file (add_file, &add_fp);
- if (mult_file)
- open_file (mult_file, &mult_fp);
- if (pre_join_file)
- open_file (pre_join_file, &pre_join_fp);
- if (post_join_file)
- open_file (post_join_file, &post_join_fp);
-
- if (optind < argc)
- {
-
- for (; optind < argc; optind++)
- {
- FILE *data_fp;
-
-
- if (strcmp (argv[optind], "-") == 0)
- data_fp = stdin;
- else
- open_file (argv[optind], &data_fp);
-
- do
- {
- bool dataset_ok;
-
- dataset_ok = ((dataset_index >= dataset_min)
- && (dataset_index <= dataset_max)
- && ((dataset_index - dataset_min)
- % dataset_spacing == 0)) ? true : false;
-
- if (dataset_printed && dataset_ok)
- output_dataset_separator();
- more_points = mung_dataset (data_fp,
- record_length,
- field_array, field_array_len,
- scale, baseline,
- add_fp, mult_fp,
- pre_join_fp, post_join_fp,
- precision, dataset_ok ? false : true);
- if (dataset_ok)
- dataset_printed = true;
-
- dataset_index++;
- }
- while (more_points);
-
-
- if (data_fp != stdin && fclose (data_fp) < 0)
- {
- fprintf (stderr, "%s: error: the input file could not be closed\n",
- progname);
- return EXIT_FAILURE;
- }
- }
- }
- else
-
- do
- {
- bool dataset_ok;
-
- dataset_ok = ((dataset_index >= dataset_min)
- && (dataset_index <= dataset_max)
- && ((dataset_index - dataset_min)
- % dataset_spacing == 0)) ? true : false;
-
- if (dataset_printed && dataset_ok)
- output_dataset_separator();
- more_points = mung_dataset (stdin,
- record_length,
- field_array, field_array_len,
- scale, baseline,
- add_fp, mult_fp,
- pre_join_fp, post_join_fp,
- precision, dataset_ok ? false : true);
- if (dataset_ok)
- dataset_printed = true;
- dataset_index++;
- }
- while (more_points);
- return EXIT_SUCCESS;
- }
- bool
- read_float (FILE *input, double *dptr)
- {
- int num_read;
- double dval;
- float fval;
- int ival;
- switch (input_type)
- {
- case T_ASCII:
- default:
- num_read = fscanf (input, "%lf", &dval);
- break;
- case T_SINGLE:
- num_read = fread ((void *) &fval, sizeof (fval), 1, input);
- dval = fval;
- break;
- case T_DOUBLE:
- num_read = fread ((void *) &dval, sizeof (dval), 1, input);
- break;
- case T_INTEGER:
- num_read = fread ((void *) &ival, sizeof (ival), 1, input);
- dval = ival;
- break;
- }
- if (num_read <= 0)
- return false;
- if (dval != dval)
- {
- fprintf (stderr, "%s: a NaN (not-a-number) was encountered in a binary-format input file\n",
- progname);
- return false;
- }
- else
- {
- *dptr = dval;
- return true;
- }
- }
- int
- get_record (FILE *input, double *record, int record_length)
- {
- bool success;
- int i, items_read, lookahead;
- head:
- if (input_type == T_ASCII)
- {
- bool two_newlines;
-
- two_newlines = skip_whitespace (input);
- if (two_newlines)
-
- return 2;
- }
- if (feof (input))
- return 1;
- if (input_type == T_ASCII)
- {
- lookahead = getc (input);
- ungetc (lookahead, input);
- if (lookahead == (int)'#')
- {
- char c;
-
- do
- {
- items_read = fread (&c, sizeof (c), 1, input);
- if (items_read <= 0)
- return 1;
- }
- while (c != '\n');
- ungetc ((int)'\n', input);
- goto head;
- }
- }
- for (i = 0; i < record_length; i++)
- {
- double val;
- success = read_float (input, &val);
- if (i == 0 &&
- ((input_type == T_DOUBLE && val == DBL_MAX)
- || (input_type == T_SINGLE && val == (double)FLT_MAX)
- || (input_type == T_INTEGER && val == (double)INT_MAX)))
-
- return 2;
- if (!success)
- {
- if (i > 0)
- fprintf (stderr, "%s: the input file terminated prematurely\n",
- progname);
- return 1;
- }
- record[i] = val;
- }
-
- return 0;
- }
- bool
- write_float (double x, int precision)
- {
- int num_written = 0;
- float fx;
- int ix;
- switch (output_type)
- {
- case T_ASCII:
- default:
- num_written = printf ("%.*g ", precision, x);
- break;
- case T_SINGLE:
- fx = FROUND(x);
- if (fx == FLT_MAX || fx == -(FLT_MAX))
- {
- maybe_emit_oob_warning();
- if (fx == FLT_MAX)
- fx *= 0.99999;
- }
- num_written = fwrite ((void *) &fx, sizeof (fx), 1, stdout);
- break;
- case T_DOUBLE:
- num_written = fwrite ((void *) &x, sizeof (x), 1, stdout);
- break;
- case T_INTEGER:
- ix = IROUND(x);
- if (ix == INT_MAX || ix == -(INT_MAX))
- {
- maybe_emit_oob_warning();
- if (ix == INT_MAX)
- ix--;
- }
- num_written = fwrite ((void *) &ix, sizeof (ix), 1, stdout);
- break;
- }
- if (num_written < 0)
- return false;
- else
- return true;
- }
- void
- open_file (char *name, FILE **fpp)
- {
- FILE *fp;
- fp = fopen (name, "r");
- if (fp == NULL)
- {
- fprintf (stderr, "%s: %s: %s\n", progname, name, strerror(errno));
- exit (EXIT_FAILURE);
- }
- *fpp = fp;
- }
- void
- set_format_type (char *s, data_type *typep)
- {
- switch (s[0])
- {
- case 'a':
- case 'A':
-
- *typep = T_ASCII;
- break;
- case 'f':
- case 'F':
-
- *typep = T_SINGLE;
- break;
- case 'd':
- case 'D':
-
- *typep = T_DOUBLE;
- break;
- case 'i':
- case 'I':
-
- *typep = T_INTEGER;
- break;
- default:
- {
- fprintf (stderr, "%s: error: the data format type `%s' is invalid\n",
- progname, s);
- exit (EXIT_FAILURE);
- }
- break;
- }
- }
- bool
- mung_dataset (FILE *input, int record_length,
- int *field_array, int field_array_len,
- double scale, double baseline, FILE *add_fp, FILE *mult_fp,
- FILE *pre_join_fp, FILE *post_join_fp, int precision,
- bool suppress)
- {
- double *record = (double *)xmalloc (record_length * sizeof(double));
- bool in_trouble = suppress;
-
- if (!in_trouble)
- {
-
- if (add_fp)
- fseek(add_fp, 0L, 0);
- if (mult_fp)
- fseek(mult_fp, 0L, 0);
- if (pre_join_fp)
- fseek(pre_join_fp, 0L, 0);
- if (post_join_fp)
- fseek(post_join_fp, 0L, 0);
- }
- for ( ; ; )
- {
- int i;
- int success;
- double add_data, mult_data, pre_join_data, post_join_data;
- if (!in_trouble && add_fp && read_float (add_fp, &add_data) == false)
- in_trouble = true;
- if (!in_trouble && mult_fp && read_float (mult_fp, &mult_data) == false)
- in_trouble = true;
- if (!in_trouble && pre_join_fp
- && read_float (pre_join_fp, &pre_join_data) == false)
- in_trouble = true;
- if (!in_trouble && post_join_fp
- && read_float (post_join_fp, &post_join_data) == false)
- in_trouble = true;
-
- success = get_record (input, record, record_length);
- switch (success)
- {
- case 0:
- if (in_trouble)
- continue;
- if (pre_join_fp)
- write_float (pre_join_data, precision);
- for (i = 0; i < field_array_len; i++)
- {
- double datum;
-
- datum = record[field_array[i]];
- if (mult_fp)
- datum *= mult_data;
- if (add_fp)
- datum += add_data;
- datum *= scale;
- datum += baseline;
-
-
- write_float (datum, precision);
- }
-
- if (post_join_fp)
- write_float (post_join_data, precision);
- if (output_type == T_ASCII)
- printf ("\n");
- break;
- case 1:
- return false;
- case 2:
- return true;
- }
- }
- }
- bool
- skip_whitespace (FILE *stream)
- {
- int lookahead;
- int nlcount = 0;
-
- do
- {
- lookahead = getc (stream);
- if (lookahead == (int)'\n')
- nlcount++;
- }
- while (lookahead != EOF
- && isspace((unsigned char)lookahead)
- && nlcount < 2);
- if (lookahead == EOF)
- return false;
-
- ungetc (lookahead, stream);
- return (nlcount == 2 ? true : false);
- }
- void
- output_dataset_separator(void)
- {
- double ddummy;
- float fdummy;
- int idummy;
- switch (output_type)
- {
- case T_ASCII:
- default:
- printf ("\n");
- break;
- case T_DOUBLE:
- ddummy = DBL_MAX;
- fwrite ((void *) &ddummy, sizeof(ddummy), 1, stdout);
- break;
- case T_SINGLE:
- fdummy = FLT_MAX;
- fwrite ((void *) &fdummy, sizeof(fdummy), 1, stdout);
- break;
- case T_INTEGER:
- idummy = INT_MAX;
- fwrite ((void *) &idummy, sizeof(idummy), 1, stdout);
- break;
- }
- }
- void
- maybe_emit_oob_warning (void)
- {
- static bool warning_written = false;
- if (!warning_written)
- {
- fprintf (stderr, "%s: one or more out-of-bounds output values are approximated\n", progname);
- warning_written = true;
- }
- }
|