ploot

plot images or real-time plain text from a .csv file
Log | Files | Refs | README

commit b22b1b174646f828a28144c010961a9c57f54dbd
parent 522bbe841ea86e232baf35ba638fe490cc763325
Author: Josuah Demangeon <mail@josuah.net>
Date:   Wed,  2 May 2018 01:12:56 +0200

reading lines into a buffe

Diffstat:
Aconfig.h | 8++++++++
Mffplot.c | 2+-
Mmain.c | 132+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Mploot.h | 11++++++++++-
Autil.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", argv0); - 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, double, double, 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; +}