URI: 
       add initial parsing functions - ics2txt - convert icalendar .ics file to plain text
  HTML git clone git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ics2txt
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
       ---
   DIR commit 8248ba97aa609be30e0ecf481d93e59a9876afcd
   DIR parent a7b4ceeaf4a57476c0952e0da2def5f92bdfdb9f
  HTML Author: Josuah Demangeon <me@josuah.net>
       Date:   Sun, 28 Jun 2020 14:33:48 +0200
       
       add initial parsing functions
       
       Diffstat:
         M ics2tsv.c                           |       7 ++++---
         M src/ical.c                          |      93 +++++++++++++++++++++++++++----
         M src/ical.h                          |      40 ++++++++++++++++++++++++++++----
         M src/map.c                           |       3 ---
       
       4 files changed, 122 insertions(+), 21 deletions(-)
       ---
   DIR diff --git a/ics2tsv.c b/ics2tsv.c
       @@ -1,5 +1,6 @@
        #include <stdio.h>
        #include <stdlib.h>
       +#include <string.h>
        
        #include "ical.h"
        #include "log.h"
       @@ -8,16 +9,16 @@
        int
        print_ical_to_tsv(FILE *fp)
        {
       -        struct ical_contentline contentline;
       +        struct ical_contentline cl;
                char *line = NULL, *ln = NULL;
                size_t sz = 0;
                ssize_t r;
        
       -        ical_init_contentline(&contentline);
       +        memset(&cl, 0, sizeof cl);
        
                while ((r = ical_read_line(&line, &ln, &sz, fp)) > 0) {
                        debug("readling line \"%s\"", line);
       -                if (ical_parse_contentline(&contentline, line) < 0)
       +                if (ical_parse_contentline(&cl, line) < 0)
                                die("parsing line \"%s\"", line);
                }
                free(line);
   DIR diff --git a/src/ical.c b/src/ical.c
       @@ -1,9 +1,11 @@
        #include "ical.h"
        
       +#include <assert.h>
        #include <errno.h>
        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
       +#include <strings.h> /* strcase* */
        
        #include "util.h"
        
       @@ -29,19 +31,21 @@ ical_read_line(char **line, char **ln, size_t *sz, FILE *fp)
                } while (c == ' ');
        
                ungetc(c, fp);
       +        assert(!ferror(fp));
                return 1;
        }
        
        int
       -ical_parse_contentline(struct ical_contentline *contentline, char *line)
       +ical_parse_contentline(struct ical_contentline *cl, char *line)
        {
                char *column, *equal, *param, *cp;
                size_t sz;
       +        int e = errno;
        
                if ((column = strchr(line, ':')) == NULL)
                        return -1;
                *column = '\0';
       -        if ((contentline->value = strdup(column + 1)) == NULL)
       +        if ((cl->value = strdup(column + 1)) == NULL)
                        return -1;
        
                if ((cp = strchr(line, ';')) != NULL)
       @@ -50,27 +54,94 @@ ical_parse_contentline(struct ical_contentline *contentline, char *line)
                        if ((equal = strchr(param, '=')) == NULL)
                                return -1;
                        *equal = '\0';
       -                if (map_set(&contentline->param, param, equal + 1) < 0)
       +                if (map_set(&cl->param, param, equal + 1) < 0)
                                return -1;
                }
        
       -        sz = sizeof(contentline->name);
       -        if (strlcpy(contentline->name, line, sz) >= sz)
       +        sz = sizeof cl->name;
       +        if (strlcpy(cl->name, line, sz) >= sz)
                        return errno=EMSGSIZE, -1;
        
       +        assert(errno == e);
                return 0;
        }
        
       -void
       -ical_init_contentline(struct ical_contentline *contentline)
       +int
       +ical_parse_tzid(struct ical_value *value, struct ical_contentline *cl)
       +{
       +        return 0;
       +}
       +
       +int
       +ical_parse_date(struct ical_value *value, struct ical_contentline *cl)
       +{
       +        return 0;
       +}
       +
       +int
       +ical_parse_attribute(struct ical_value *value, struct ical_contentline *cl)
       +{
       +        return 0;
       +}
       +
       +int
       +ical_begin_vnode(struct ical_vcalendar *vcal, char const *name)
        {
       -        memset(contentline, 0, sizeof(*contentline));
       +        if (strcasecmp(name, "VCALENDAR"))
       +                return 0;
       +        return -1;
        }
        
       +int
       +ical_end_vnode(struct ical_vcalendar *vcal, char const *name)
       +{
       +        if (strcasecmp(name, "VCALENDAR"))
       +                return 0;
       +        return -1;
       +}
       +
       +int
       +ical_add_contentline(struct ical_vcalendar *vcal, struct ical_contentline *cl)
       +{
       +        struct ical_value value_buf, *value = &value_buf;
       +        int i;
       +        struct {
       +                char *name;
       +                enum ical_value_type type;
       +                int (*fn)(struct ical_value *, struct ical_contentline *);
       +        } map[] = {
       +                { "DTSTART", ICAL_VALUE_TIME,      ical_parse_date },
       +                { "DTEND",   ICAL_VALUE_TIME,      ical_parse_date },
       +                { "TZID",    ICAL_VALUE_TIME,      ical_parse_tzid },
       +                { NULL,      ICAL_VALUE_ATTRIBUTE, ical_parse_attribute },
       +        };
       +
       +        if (strcasecmp(cl->name, "BEGIN") == 0)
       +                return ical_begin_vnode(vcal, cl->value);
       +
       +        if (strcasecmp(cl->name, "END") == 0)
       +                return ical_end_vnode(vcal, cl->value);
       +
       +        memset(value, 0, sizeof *value);
       +
       +        for (i = 0; map[i].name == NULL; i++)
       +                if (strcasecmp(cl->name, map[i].name) == 0)
       +                        break;
       +        value->type = map[i].type;
       +        if (map[i].fn(value, cl) < 0)
       +                return -1;
       +        return 0;
       +}
       +
       +void
       +ical_free_value(struct ical_value *value)
       +{
       +        ;
       +}
        
        void
       -ical_free_contentline(struct ical_contentline *contentline)
       +ical_free_contentline(struct ical_contentline *cl)
        {
       -        map_free(&contentline->param);
       -        free(contentline->value);
       +        map_free(&cl->param);
       +        free(cl->value);
        }
   DIR diff --git a/src/ical.h b/src/ical.h
       @@ -6,16 +6,48 @@
        
        #include "map.h"
        
       -struct ical_vevent {
       -        time_t beg, end;
       -        struct map map;
       -};
       +#define ICAL_NEST_MAX 4
       +
       +/*  */
        
        struct ical_contentline {
                char name[32], *value;
                struct map param;
        };
        
       +/* single value for an iCalendar element attribute */
       +
       +enum ical_value_type {
       +        ICAL_VALUE_TIME, ICAL_VALUE_ATTRIBUTE,
       +} type;
       +
       +union ical_value_union {
       +        time_t *time;
       +        char *str;
       +};
       +
       +struct ical_value {
       +        enum ical_value_type type;
       +        union ical_value_union value;
       +};
       +
       +/* global propoerties for an iCalendar document as well as parsing state */
       +
       +struct ical_vcalendar {
       +        time_t tzid;
       +        char *stack[ICAL_NEST_MAX + 1];
       +        struct ical_vnode *current;
       +};
       +
       +/* element part of an iCalendar document with eventual nested childs */
       +
       +struct ical_vnode {
       +        char name[32];
       +        time_t beg, end;
       +        struct map properties; /* struct ical_value */
       +        struct ical_vnode *child, *next;
       +};
       +
        /** src/ical.c **/
        int ical_read_line(char **line, char **ln, size_t *sz, FILE *fp);
        int ical_parse_contentline(struct ical_contentline *contentline, char *line);
   DIR diff --git a/src/map.c b/src/map.c
       @@ -32,11 +32,8 @@ map_set(struct map *map, char *key, void *value)
                size_t i, sz;
                void *v;
        
       -        debug("%s: key=%s len=%zd", __func__, key, map->len);
       -
                for (i = 0; i < map->len; i++) {
                        int cmp = strcmp(key, map->entry[i].key);
       -                debug("cmp(%s,%s)=%d", key, map->entry[i].key, cmp);
        
                        if (cmp == 0) {
                                map->entry[i].value = value;