reading lines into a buffe - ploot - simple plotting tools | |
git clone git://bitreich.org/ploot git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
LICENSE | |
--- | |
commit b22b1b174646f828a28144c010961a9c57f54dbd | |
parent 522bbe841ea86e232baf35ba638fe490cc763325 | |
Author: Josuah Demangeon <[email protected]> | |
Date: Wed, 2 May 2018 01:12:56 +0200 | |
reading lines into a buffe | |
Diffstat: | |
A config.h | 8 ++++++++ | |
M ffplot.c | 2 +- | |
M main.c | 132 ++++++++++++++++++++++++++++-… | |
M ploot.h | 11 ++++++++++- | |
A util.c | 21 +++++++++++++++++++++ | |
5 files changed, 162 insertions(+), 12 deletions(-) | |
--- | |
diff --git a/config.h b/config.h | |
@@ -0,0 +1,8 @@ | |
+ColorList colorlist[] = { | |
+ { "red", { 0xffff, 0x4444, 0x4444, 0xffff } }, | |
+ { "orange", { 0xffff, 0x9999, 0x4444, 0xffff } }, | |
+ { "yellow", { 0xffff, 0xffff, 0x4444, 0xffff } }, | |
+ { "green", { 0x1111, 0xffff, 0x5555, 0xffff } }, | |
+ { "cyan", { 0x0000, 0xffff, 0xdddd, 0xffff } }, | |
+ { NULL, { 0, 0, 0, 0 } } | |
+}; | |
diff --git a/ffplot.c b/ffplot.c | |
@@ -193,7 +193,7 @@ legend(Canvas *can, Color *label_fg, Vlist *v, int n) | |
ffdraw_str_left(can, &v->col, "\1", font, x, y); | |
y += FONT_W * 2; | |
- ffdraw_str_left(can, label_fg, v->name, font, x, y); | |
+ ffdraw_str_left(can, label_fg, v->label, font, x, y); | |
} | |
} | |
diff --git a/main.c b/main.c | |
@@ -2,9 +2,13 @@ | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <fcntl.h> | |
+#include <limits.h> | |
+#include <string.h> | |
+#include <ctype.h> | |
#include "arg.h" | |
#include "ploot.h" | |
+#include "config.h" /* after ploot.h for type definitions */ | |
#define LEN(x) (sizeof(x) / sizeof(*x)) | |
@@ -12,25 +16,132 @@ char *argv0; | |
char *tflag = ""; | |
char *uflag = ""; | |
+static int | |
+color(Color *col, char *name) | |
+{ | |
+ ColorList *c; | |
+ | |
+ for (c = colorlist; c->name != NULL; c++) { | |
+ if (strcmp(name, c->name) == 0) { | |
+ memcpy(col, &c->col, sizeof(*col)); | |
+ return 0; | |
+ } | |
+ } | |
+ | |
+ return -1; | |
+} | |
+ | |
+void | |
+estriplf(char *line) | |
+{ | |
+ char *lf; | |
+ | |
+ if ((lf = strchr(line, '\n')) == NULL || lf[1] != '\0') | |
+ fputs("invalid input\n", stderr), exit(1); | |
+ *lf = '\0'; | |
+} | |
+ | |
static void | |
-usage(void) | |
+read_labels(Vlist *v, char **argv, char *buf) | |
{ | |
- fprintf(stderr, "usage: %s [-t title] [-u unit] label:color...\n", arg… | |
- exit(1); | |
+ if (fgets(buf, LINE_MAX, stdin) == NULL) { | |
+ if (ferror(stdin)) | |
+ perror("fread from stdin"); | |
+ else | |
+ fputs("missing label line\n", stderr); | |
+ exit(1); | |
+ } | |
+ estriplf(buf); | |
+ | |
+ if (strcmp(strsep(&buf, ","), "epoch") != 0) | |
+ fputs("first label must be \"epoch\"\n", stderr), exit(1); | |
+ | |
+ for (; *argv != NULL; v++, argv++) | |
+ if ((v->label = strsep(&buf, ",")) == NULL) | |
+ fputs("more arguments than columns\n", stderr), exit(1… | |
+ else if (color(&v->col, *argv) == -1) | |
+ fprintf(stderr, "unknown color: %s\n", *argv), exit(1); | |
+ | |
+ if (strsep(&buf, ",") != NULL) | |
+ fputs("more columns than arguments\n", stderr), exit(1); | |
+} | |
+ | |
+long | |
+eatol(char *str) | |
+{ | |
+ char *s; | |
+ | |
+ for (s = str; *s != '\0'; s++) | |
+ if (!isdigit(*s)) | |
+ fputs("invalid number format", stderr), exit(0); | |
+ return atol(str); | |
} | |
void | |
-read_labels(Vlist *v, int n) | |
+add_value(double **v, int *bufsiz, int nval, char *field) | |
{ | |
- (void)v; | |
- (void)n; | |
+ if (nval >= *bufsiz) { | |
+ *bufsiz *= 2; | |
+ if ((*v = realloc(*v, *bufsiz)) == NULL) | |
+ perror("reallocating values buffer"), exit(1); | |
+ } | |
+ (*v)[nval] = eatol(field); | |
+} | |
+ | |
+/* | |
+ * Add to each column the value on the current row. | |
+ */ | |
+void | |
+add_each_value(Vlist *v, int *bufsiz, int ncol, int nval, char *line) | |
+{ | |
+ time_t epoch; | |
+ int n; | |
+ char *field; | |
+ | |
+ if ((field = strsep(&line, ",")) == NULL) | |
+ fprintf(stderr, "%d: missing epoch\n", nval), exit(0); | |
+ | |
+ epoch = eatol(field); | |
+ | |
+ for (n = 0; (field = strsep(&line, ",")) != NULL; n++, v++) { | |
+ if (n > ncol) | |
+ fprintf(stderr, "%d: too many fields\n", nval), exit(0… | |
+ add_value(&v->v, bufsiz, nval, field); | |
+ } | |
+ if (n < ncol) | |
+ fprintf(stderr, "%d: too few fields\n", nval), exit(0); | |
} | |
+/* | |
+ * < ncol > | |
+ * epoch,a1,b1,c1 ^ | |
+ * epoch,a2,b2,c2 nval | |
+ * epoch,a3,b3,c3 v | |
+ */ | |
void | |
-read_values(Vlist *v, int n) | |
+read_values(Vlist *v, int ncol) | |
{ | |
- (void)v; | |
- (void)n; | |
+ int n, nval, bufsiz; | |
+ char line[LINE_MAX]; | |
+ | |
+ for (nval = 0; fgets(line, sizeof(line), stdin); nval++) { | |
+ estriplf(line); | |
+ add_each_value(v, &bufsiz, ncol, nval, line); | |
+ } | |
+ for (n = 0; n < ncol; n++, v++) | |
+ v->n = nval; | |
+} | |
+ | |
+static void | |
+usage(void) | |
+{ | |
+ ColorList *c; | |
+ | |
+ fprintf(stderr, "usage: %s [-t title] [-u unit] color...\n" | |
+ "available colors as defined by \"config.h\":\n", argv0); | |
+ for (c = colorlist; c->name != NULL; c++) | |
+ fprintf(stderr, "- %s\n", c->name); | |
+ exit(1); | |
} | |
int | |
@@ -39,6 +150,7 @@ main(int argc, char **argv) | |
Vlist *v; | |
double vmin, vmax, vstep; | |
time_t tmin, tmax, tstep; | |
+ char labels[LINE_MAX]; | |
ARGBEGIN { | |
case 't': | |
@@ -55,7 +167,7 @@ main(int argc, char **argv) | |
vmin = -30; vmax = 700; vstep = 120; | |
tmin = 0; tmax = 2000; tstep = 300; | |
- read_labels(v, argc); | |
+ read_labels(v, argv, labels); | |
read_values(v, argc); | |
ffdraw(tflag, uflag, v, argc, | |
diff --git a/ploot.h b/ploot.h | |
@@ -25,9 +25,14 @@ typedef struct { | |
time_t *t; /* array of timestamps */ | |
double *v; /* array of values */ | |
int n; /* number of values */ | |
- char *name; /* for the legend */ | |
+ char *label; /* for the legend */ | |
} Vlist; | |
+typedef struct { | |
+ char *name; | |
+ Color col; | |
+} ColorList; | |
+ | |
/* ffdraw.c */ | |
void ffdraw_pixel (Canvas *, Color *, int, int); | |
void ffdraw_rectangle(Canvas *, Color *, int, int, int, int); | |
@@ -42,3 +47,7 @@ void ffdraw_print (Canvas *); | |
/* ffplot.c */ | |
void ffdraw (char *, char *, Vlist *, int, doub… | |
double, time_t, time_t, time_t); | |
+ | |
+/* util.c */ | |
+char *strsep (char **, const char *); | |
+ | |
diff --git a/util.c b/util.c | |
@@ -0,0 +1,21 @@ | |
+#include <string.h> | |
+ | |
+#include "ploot.h" | |
+ | |
+char * | |
+strsep(char **strp, const char *sep) | |
+{ | |
+ char *s, *prev; | |
+ | |
+ if (*strp == NULL) | |
+ return NULL; | |
+ for (s = prev = *strp; strchr(sep, *s) == NULL; s++); | |
+ if (*s == '\0') { | |
+ *strp = NULL; | |
+ return prev; | |
+ } | |
+ *s = '\0'; | |
+ *strp = s + 1; | |
+ | |
+ return prev; | |
+} |