reading lines into a buffe - ploot - simple plotting tools
 (HTM) git clone git://bitreich.org/ploot git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ploot
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Tags
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit b22b1b174646f828a28144c010961a9c57f54dbd
 (DIR) parent 522bbe841ea86e232baf35ba638fe490cc763325
 (HTM) Author: Josuah Demangeon <mail@josuah.net>
       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(-)
       ---
 (DIR) 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 } }
       +};
 (DIR) 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);
                }
        }
        
 (DIR) 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,
 (DIR) 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 *);
       +
 (DIR) 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;
       +}