tadd option parsing and format string options to all programs - numtools - perf… | |
git clone git://src.adamsgaard.dk/numtools | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 8b5e9b0cf97126537c548e49329ead6bad47c105 | |
parent 5c71d867b926ca74ab063744b0359086be572e88 | |
Author: Anders Damsgaard <[email protected]> | |
Date: Mon, 9 May 2022 16:52:46 +0200 | |
add option parsing and format string options to all programs | |
Diffstat: | |
M max.1 | 17 ++++++++++++++++- | |
M max.c | 32 ++++++++++++++++++++++++++++-… | |
M mean.1 | 16 ++++++++++++++++ | |
M mean.c | 32 ++++++++++++++++++++++++++++-… | |
M min.1 | 16 ++++++++++++++++ | |
M min.c | 32 ++++++++++++++++++++++++++++-… | |
M stddev.1 | 9 +++++++++ | |
M stddev.c | 24 ++++++++++++++++-------- | |
M stdvar.1 | 9 +++++++++ | |
M stdvar.c | 12 ++++++++++-- | |
M sum.1 | 16 ++++++++++++++++ | |
M sum.c | 32 ++++++++++++++++++++++++++++-… | |
M util.c | 13 +++++++++++++ | |
M util.h | 1 + | |
14 files changed, 238 insertions(+), 23 deletions(-) | |
--- | |
diff --git a/max.1 b/max.1 | |
t@@ -6,13 +6,28 @@ | |
.Nd returns the maximum value for each column | |
.Sh SYNOPSIS | |
.Nm | |
-.Op Ar file | |
+.Op Fl f Ar fmtstr | |
+.Op Fl h | |
.Sh DESCRIPTION | |
.Nm | |
returns the maximum numerical value for each column in standard | |
input. | |
Input fields must be tab-separated and each line must contain | |
the same number of fields. | |
+.Pp | |
+The options are as follows: | |
+.Bl -tag -width Ds | |
+.It Fl f Ar fmtstr | |
+Formatting string to use as documented in | |
+.Xr printf 3 . | |
+When including a format specifier (%..), only use forms that are | |
+compatible with | |
+.Vt double | |
+types. | |
+The default format string is '%.17g'. | |
+.It Fl h | |
+Show usage information and exit. | |
+.El | |
.Sh EXAMPLES | |
.Dl $ printf '1\et2\et3\en4\et5\et6\en' | max | |
.Dl 4 5 6 | |
diff --git a/max.c b/max.c | |
t@@ -2,19 +2,45 @@ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
+#include <limits.h> | |
+#include "arg.h" | |
#include "util.h" | |
+char *argv0; | |
+ | |
+static void | |
+usage(void) | |
+{ | |
+ errx(1, "usage: %s [-f fmtstr] [-h] ", argv0); | |
+} | |
+ | |
int | |
-main(void) | |
+main(int argc, char *argv[]) | |
{ | |
+ int ret; | |
size_t i = 0, nf = 0, nr = 0, linesize = 0; | |
- char *line = NULL, *data = NULL; | |
+ char *line = NULL, *data = NULL, fmtstr[PATH_MAX] = "%.17g"; | |
double val, *vals = NULL; | |
if (pledge("stdio", NULL) == -1) | |
err(2, "pledge"); | |
+ ARGBEGIN { | |
+ case 'f': | |
+ ret = snprintf(fmtstr, sizeof(fmtstr), "%s", EARGF(usage())); | |
+ if (ret < 0 || (size_t)ret >= sizeof(fmtstr)) | |
+ errx(1, "%s: could not write fmtstr", __func__); | |
+ break; | |
+ case 'h': | |
+ usage(); | |
+ break; | |
+ default: | |
+ usage(); | |
+ } ARGEND; | |
+ if (argc > 0) | |
+ usage(); | |
+ | |
while (getline(&line, &linesize, stdin) > 0) { | |
if (nr == 0) | |
if ((nf = allocarr(&vals, line, linesize)) == 0) | |
t@@ -28,7 +54,7 @@ main(void) | |
} | |
nr++; | |
} | |
- printarr(vals, nf); | |
+ printfarr(fmtstr, vals, nf); | |
free(line); | |
free(vals); | |
diff --git a/mean.1 b/mean.1 | |
t@@ -6,11 +6,27 @@ | |
.Nd returns the average value for each column | |
.Sh SYNOPSIS | |
.Nm | |
+.Op Fl f Ar fmtstr | |
+.Op Fl h | |
.Sh DESCRIPTION | |
.Nm | |
returns the mean numerical value for each column in standard input. | |
Input fields must be tab-separated and each line must contain the same | |
number of fields. | |
+.Pp | |
+The options are as follows: | |
+.Bl -tag -width Ds | |
+.It Fl f Ar fmtstr | |
+Formatting string to use as documented in | |
+.Xr printf 3 . | |
+When including a format specifier (%..), only use forms that are | |
+compatible with | |
+.Vt double | |
+types. | |
+The default format string is '%.17g'. | |
+.It Fl h | |
+Show usage information and exit. | |
+.El | |
.Sh EXAMPLES | |
.Dl $ printf '1\et2\et3\en4\et5\et6\en' | mean | |
.Dl 2.5 3.5 4.5 | |
diff --git a/mean.c b/mean.c | |
t@@ -2,19 +2,45 @@ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
+#include <limits.h> | |
+#include "arg.h" | |
#include "util.h" | |
+char *argv0; | |
+ | |
+static void | |
+usage(void) | |
+{ | |
+ errx(1, "usage: %s [-f fmtstr] [-h] ", argv0); | |
+} | |
+ | |
int | |
-main(void) | |
+main(int argc, char *argv[]) | |
{ | |
+ int ret; | |
size_t i = 0, nf = 0, nr = 0, linesize = 0; | |
- char *line = NULL, *data = NULL; | |
+ char *line = NULL, *data = NULL, fmtstr[PATH_MAX] = "%.17g"; | |
double val, *vals = NULL; | |
if (pledge("stdio", NULL) == -1) | |
err(2, "pledge"); | |
+ ARGBEGIN { | |
+ case 'f': | |
+ ret = snprintf(fmtstr, sizeof(fmtstr), "%s", EARGF(usage())); | |
+ if (ret < 0 || (size_t)ret >= sizeof(fmtstr)) | |
+ errx(1, "%s: could not write fmtstr", __func__); | |
+ break; | |
+ case 'h': | |
+ usage(); | |
+ break; | |
+ default: | |
+ usage(); | |
+ } ARGEND; | |
+ if (argc > 0) | |
+ usage(); | |
+ | |
while (getline(&line, &linesize, stdin) > 0) { | |
if (nr == 0) | |
if ((nf = allocarr(&vals, line, linesize)) == 0) | |
t@@ -31,7 +57,7 @@ main(void) | |
} | |
for (i = 0; i < nf; i++) | |
vals[i] /= (double)nr; | |
- printarr(vals, nf); | |
+ printfarr(fmtstr, vals, nf); | |
free(line); | |
free(vals); | |
diff --git a/min.1 b/min.1 | |
t@@ -6,12 +6,28 @@ | |
.Nd returns the minimum value for each column | |
.Sh SYNOPSIS | |
.Nm | |
+.Op Fl f Ar fmtstr | |
+.Op Fl h | |
.Sh DESCRIPTION | |
.Nm | |
returns the minimum numerical value for each column in standard | |
input. | |
Input fields must be tab-separated and each line must contain the same | |
number of fields. | |
+.Pp | |
+The options are as follows: | |
+.Bl -tag -width Ds | |
+.It Fl f Ar fmtstr | |
+Formatting string to use as documented in | |
+.Xr printf 3 . | |
+When including a format specifier (%..), only use forms that are | |
+compatible with | |
+.Vt double | |
+types. | |
+The default format string is '%.17g'. | |
+.It Fl h | |
+Show usage information and exit. | |
+.El | |
.Sh EXAMPLES | |
.Dl $ printf '1\et2\et3\en4\et5\et6\en' | min | |
.Dl 1 2 3 | |
diff --git a/min.c b/min.c | |
t@@ -2,19 +2,45 @@ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
+#include <limits.h> | |
+#include "arg.h" | |
#include "util.h" | |
+char *argv0; | |
+ | |
+static void | |
+usage(void) | |
+{ | |
+ errx(1, "usage: %s [-f fmtstr] [-h] ", argv0); | |
+} | |
+ | |
int | |
-main(void) | |
+main(int argc, char *argv[]) | |
{ | |
+ int ret; | |
size_t i = 0, nf = 0, nr = 0, linesize = 0; | |
- char *line = NULL, *data = NULL; | |
+ char *line = NULL, *data = NULL, fmtstr[PATH_MAX] = "%.17g"; | |
double val, *vals = NULL; | |
if (pledge("stdio", NULL) == -1) | |
err(2, "pledge"); | |
+ ARGBEGIN { | |
+ case 'f': | |
+ ret = snprintf(fmtstr, sizeof(fmtstr), "%s", EARGF(usage())); | |
+ if (ret < 0 || (size_t)ret >= sizeof(fmtstr)) | |
+ errx(1, "%s: could not write fmtstr", __func__); | |
+ break; | |
+ case 'h': | |
+ usage(); | |
+ break; | |
+ default: | |
+ usage(); | |
+ } ARGEND; | |
+ if (argc > 0) | |
+ usage(); | |
+ | |
while (getline(&line, &linesize, stdin) > 0) { | |
if (nr == 0) | |
if ((nf = allocarr(&vals, line, linesize)) == 0) | |
t@@ -28,7 +54,7 @@ main(void) | |
} | |
nr++; | |
} | |
- printarr(vals, nf); | |
+ printfarr(fmtstr, vals, nf); | |
free(line); | |
free(vals); | |
diff --git a/stddev.1 b/stddev.1 | |
t@@ -6,6 +6,7 @@ | |
.Nd returns the standard deviation for each column | |
.Sh SYNOPSIS | |
.Nm | |
+.Op Fl f Ar fmtstr | |
.Op Fl h | |
.Op Fl u | |
.Sh DESCRIPTION | |
t@@ -18,6 +19,14 @@ The output is always in full double precision. | |
.Pp | |
The options are as follows: | |
.Bl -tag -width Ds | |
+.It Fl f Ar fmtstr | |
+Formatting string to use as documented in | |
+.Xr printf 3 . | |
+When including a format specifier (%..), only use forms that are | |
+compatible with | |
+.Vt double | |
+types. | |
+The default format string is '%.17g'. | |
.It Fl h | |
Show usage information and exit. | |
.It Fl u | |
diff --git a/stddev.c b/stddev.c | |
t@@ -3,6 +3,7 @@ | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <math.h> | |
+#include <limits.h> | |
#include "arg.h" | |
#include "util.h" | |
t@@ -12,19 +13,26 @@ char *argv0; | |
static void | |
usage(void) | |
{ | |
- errx(1, "usage: %s [-h] [-u]\n", argv0); | |
+ errx(1, "usage: %s [-f fmtstr] [-h] [-u]\n", argv0); | |
} | |
int | |
main(int argc, char *argv[]) | |
{ | |
+ int ret; | |
size_t i, j, nf = 0, nr = 0, correction = 1; | |
- double *means = NULL, *stdvars = NULL, **vals = NULL; | |
+ double *means = NULL, *stdvals = NULL, **vals = NULL; | |
+ char fmtstr[PATH_MAX] = "%.17g"; | |
if (pledge("stdio", NULL) == -1) | |
err(2, "pledge"); | |
ARGBEGIN { | |
+ case 'f': | |
+ ret = snprintf(fmtstr, sizeof(fmtstr), "%s", EARGF(usage())); | |
+ if (ret < 0 || (size_t)ret >= sizeof(fmtstr)) | |
+ errx(1, "%s: could not write fmtstr", __func__); | |
+ break; | |
case 'h': | |
usage(); | |
break; | |
t@@ -38,7 +46,7 @@ main(int argc, char *argv[]) | |
nr = fscanmatrix(stdin, &vals, &nf); | |
if (!(means = calloc(nf, sizeof(double))) || | |
- !(stdvars = calloc(nf, sizeof(double)))) | |
+ !(stdvals = calloc(nf, sizeof(double)))) | |
err(1, "calloc"); | |
for (i = 0; i < nf; i++) { | |
t@@ -49,16 +57,16 @@ main(int argc, char *argv[]) | |
} | |
for (i = 0; i < nf; i++) { | |
- stdvars[i] = 0.0; | |
+ stdvals[i] = 0.0; | |
for (j = 0; j < nr; j++) | |
- stdvars[i] += pow(vals[j][i] - means[i], 2.0); | |
- stdvars[i] = sqrt(stdvars[i] / ((double)(nr - correction))); | |
+ stdvals[i] += pow(vals[j][i] - means[i], 2.0); | |
+ stdvals[i] = sqrt(stdvals[i] / ((double)(nr - correction))); | |
} | |
- printarr(stdvars, nf); | |
+ printfarr(fmtstr, stdvals, nf); | |
free(means); | |
- free(stdvars); | |
+ free(stdvals); | |
for (i = 0; i < nr; i++) | |
free(vals[i]); | |
free(vals); | |
diff --git a/stdvar.1 b/stdvar.1 | |
t@@ -6,6 +6,7 @@ | |
.Nd returns the standard variance for each column | |
.Sh SYNOPSIS | |
.Nm | |
+.Op Fl f Ar fmtstr | |
.Op Fl h | |
.Op Fl u | |
.Sh DESCRIPTION | |
t@@ -18,6 +19,14 @@ The output is always in full double precision. | |
.Pp | |
The options are as follows: | |
.Bl -tag -width Ds | |
+.It Fl f Ar fmtstr | |
+Formatting string to use as documented in | |
+.Xr printf 3 . | |
+When including a format specifier (%..), only use forms that are | |
+compatible with | |
+.Vt double | |
+types. | |
+The default format string is '%.17g'. | |
.It Fl h | |
Show usage information and exit. | |
.It Fl u | |
diff --git a/stdvar.c b/stdvar.c | |
t@@ -3,6 +3,7 @@ | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <math.h> | |
+#include <limits.h> | |
#include "arg.h" | |
#include "util.h" | |
t@@ -12,19 +13,26 @@ char *argv0; | |
static void | |
usage(void) | |
{ | |
- errx(1, "usage: %s [-h] [-u]\n", argv0); | |
+ errx(1, "usage: %s [-f fmtstr] [-h] [-u]\n", argv0); | |
} | |
int | |
main(int argc, char *argv[]) | |
{ | |
+ int ret; | |
size_t i, j, nf = 0, nr = 0, correction = 1; | |
double *means = NULL, *stdvars = NULL, **vals = NULL; | |
+ char fmtstr[PATH_MAX] = "%.17g"; | |
if (pledge("stdio", NULL) == -1) | |
err(2, "pledge"); | |
ARGBEGIN { | |
+ case 'f': | |
+ ret = snprintf(fmtstr, sizeof(fmtstr), "%s", EARGF(usage())); | |
+ if (ret < 0 || (size_t)ret >= sizeof(fmtstr)) | |
+ errx(1, "%s: could not write fmtstr", __func__); | |
+ break; | |
case 'h': | |
usage(); | |
break; | |
t@@ -55,7 +63,7 @@ main(int argc, char *argv[]) | |
stdvars[i] /= (double)(nr - correction); | |
} | |
- printarr(stdvars, nf); | |
+ printfarr(fmtstr, stdvars, nf); | |
free(means); | |
free(stdvars); | |
diff --git a/sum.1 b/sum.1 | |
t@@ -6,11 +6,27 @@ | |
.Nd returns the sum for each column | |
.Sh SYNOPSIS | |
.Nm | |
+.Op Fl f Ar fmtstr | |
+.Op Fl h | |
.Sh DESCRIPTION | |
.Nm | |
returns the numerical sum for each column in standard input. | |
Input fields must be tab-separated and each line must contain the | |
same number of fields. | |
+.Pp | |
+The options are as follows: | |
+.Bl -tag -width Ds | |
+.It Fl f Ar fmtstr | |
+Formatting string to use as documented in | |
+.Xr printf 3 . | |
+When including a format specifier (%..), only use forms that are | |
+compatible with | |
+.Vt double | |
+types. | |
+The default format string is '%.17g'. | |
+.It Fl h | |
+Show usage information and exit. | |
+.El | |
.Sh EXAMPLES | |
.Dl $ printf '1\et2\et3\en4\et5\et6\en' | sum | |
.Dl 5 7 9 | |
diff --git a/sum.c b/sum.c | |
t@@ -2,19 +2,45 @@ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
+#include <limits.h> | |
+#include "arg.h" | |
#include "util.h" | |
+char *argv0; | |
+ | |
+static void | |
+usage(void) | |
+{ | |
+ errx(1, "usage: %s [-f fmtstr] [-h] ", argv0); | |
+} | |
+ | |
int | |
-main(void) | |
+main(int argc, char *argv[]) | |
{ | |
+ int ret; | |
size_t i = 0, nf = 0, nr = 0, linesize = 0; | |
- char *line = NULL, *data = NULL; | |
+ char *line = NULL, *data = NULL, fmtstr[PATH_MAX] = "%.17g"; | |
double val, *vals = NULL; | |
if (pledge("stdio", NULL) == -1) | |
err(2, "pledge"); | |
+ ARGBEGIN { | |
+ case 'f': | |
+ ret = snprintf(fmtstr, sizeof(fmtstr), "%s", EARGF(usage())); | |
+ if (ret < 0 || (size_t)ret >= sizeof(fmtstr)) | |
+ errx(1, "%s: could not write fmtstr", __func__); | |
+ break; | |
+ case 'h': | |
+ usage(); | |
+ break; | |
+ default: | |
+ usage(); | |
+ } ARGEND; | |
+ if (argc > 0) | |
+ usage(); | |
+ | |
while (getline(&line, &linesize, stdin) > 0) { | |
if (nr == 0) | |
if ((nf = allocarr(&vals, line, linesize)) == 0) | |
t@@ -29,7 +55,7 @@ main(void) | |
} | |
nr++; | |
} | |
- printarr(vals, nf); | |
+ printfarr(fmtstr, vals, nf); | |
free(line); | |
free(vals); | |
diff --git a/util.c b/util.c | |
t@@ -44,6 +44,19 @@ printarr(double *arr, size_t len) | |
puts(""); | |
} | |
+void | |
+printfarr(char *fmtstr, double *arr, size_t len) | |
+{ | |
+ size_t i; | |
+ | |
+ for (i = 0; i < len; i++) { | |
+ printf(fmtstr, arr[i]); | |
+ if (i < len) | |
+ printf(DELIMSTR); | |
+ } | |
+ puts(""); | |
+} | |
+ | |
size_t | |
fscanmatrix(FILE *stream, double ***arr, size_t *nf) | |
{ | |
diff --git a/util.h b/util.h | |
t@@ -22,6 +22,7 @@ void * xreallocarray(void *m, size_t n, size_t s); | |
size_t allocarr(double **arr, const char *str, size_t maxlen); | |
int scannextval(char **str, double *val); | |
void printarr(double *arr, size_t len); | |
+void printfarr(char *fmtstr, double *arr, size_t len); | |
size_t fscanmatrix(FILE *stream, double ***arr, size_t *nf); | |
#endif |