URI: 
       convert some fields to time_t - 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 54ba66bb7b1b7eed7e3aaf60ef00c9ccc9cc65d6
   DIR parent 58d91e5e80aea1ab98f675ccc4530f26a9659162
  HTML Author: Josuah Demangeon <me@josuah.net>
       Date:   Thu, 17 Jun 2021 01:35:05 +0200
       
       convert some fields to time_t
       
       Diffstat:
         M ical.c                              |      24 ++++++++++++------------
         M ical.h                              |       6 +++---
         M ics2tree.c                          |       8 ++++----
         M ics2tsv.c                           |      69 ++++++++++++++++---------------
       
       4 files changed, 55 insertions(+), 52 deletions(-)
       ---
   DIR diff --git a/ical.c b/ical.c
       @@ -93,7 +93,7 @@ ical_get_time(IcalParser *p, char *s, time_t *t)
         * permit to only have parsing code left to parsing functions */
        
        static int
       -hook_entry_name(IcalParser *p, char *name)
       +hook_field_name(IcalParser *p, char *name)
        {
                (void)p; (void)name;
                return 0;
       @@ -119,7 +119,7 @@ hook_param_value(IcalParser *p, char *name, char *value)
        }
        
        static int
       -hook_entry_value(IcalParser *p, char *name, char *value)
       +hook_field_value(IcalParser *p, char *name, char *value)
        {
                if (strcasecmp(name, "TZID") == 0)
                        if (strlcpy(p->current->tzid, value, sizeof p->current->tzid) >=
       @@ -144,9 +144,9 @@ hook_block_begin(IcalParser *p, char *name)
        
                for (int i = 0; ical_block_name[i] != NULL; i++) {
                        if (strcasecmp(ical_block_name[i], name) == 0) {
       -                        if (p->block != ICAL_BLOCK_OTHER)
       +                        if (p->blocktype != ICAL_BLOCK_OTHER)
                                        return ical_err(p, "BEGIN:V* in BEGIN:V*");
       -                        p->block = i;
       +                        p->blocktype = i;
                        }
                }
        
       @@ -164,9 +164,9 @@ hook_block_end(IcalParser *p, char *name)
                if (p->current < p->stack)
                        return ical_err(p, "more END: than BEGIN:");
        
       -        if (ical_block_name[p->block] != NULL &&
       -            strcasecmp(ical_block_name[p->block], name) == 0)
       -                p->block = ICAL_BLOCK_OTHER;
       +        if (ical_block_name[p->blocktype] != NULL &&
       +            strcasecmp(ical_block_name[p->blocktype], name) == 0)
       +                p->blocktype = ICAL_BLOCK_OTHER;
                return 0;
        }
        
       @@ -241,8 +241,8 @@ ical_parse_contentline(IcalParser *p, char *s)
                        return ical_err(p, "invalid property name");
                c = *s, *s = '\0';
                if (strcasecmp(name, "BEGIN") != 0 && strcasecmp(name, "END") != 0)
       -                if ((err = hook_entry_name(p, name)) != 0 ||
       -                    (err = CALL(p, fn_entry_name, name)) != 0)
       +                if ((err = hook_field_name(p, name)) != 0 ||
       +                    (err = CALL(p, fn_field_name, name)) != 0)
                                return err;
                *s = c;
                sep = s;
       @@ -268,8 +268,8 @@ ical_parse_contentline(IcalParser *p, char *s)
                            (err = CALL(p, fn_block_end, s)) != 0)
                                return err;
                } else {
       -                if ((err = hook_entry_value(p, name, s)) != 0 ||
       -                    (err = CALL(p, fn_entry_value, name, s)) != 0)
       +                if ((err = hook_field_value(p, name, s)) != 0 ||
       +                    (err = CALL(p, fn_field_value, name, s)) != 0)
                                return err;
                }
                return 0;
       @@ -312,7 +312,7 @@ ical_parse(IcalParser *p, FILE *fp)
        
                p->current = p->stack;
                p->linenum = 0;
       -        p->block = ICAL_BLOCK_OTHER;
       +        p->blocktype = ICAL_BLOCK_OTHER;
        
                do {
                        if ((l = ical_getline(&contentline, &line, &sz, fp)) < 0) {
   DIR diff --git a/ical.h b/ical.h
       @@ -25,10 +25,10 @@ struct IcalStack {
        
        struct IcalParser {
                /* function called while parsing in this order */
       -        int (*fn_entry_name)(IcalParser *, char *);
       +        int (*fn_field_name)(IcalParser *, char *);
                int (*fn_param_name)(IcalParser *, char *);
                int (*fn_param_value)(IcalParser *, char *, char *);
       -        int (*fn_entry_value)(IcalParser *, char *, char *);
       +        int (*fn_field_value)(IcalParser *, char *, char *);
                int (*fn_block_begin)(IcalParser *, char *);
                int (*fn_block_end)(IcalParser *, char *);
                /* if returning non-zero then halt the parser */
       @@ -37,7 +37,7 @@ struct IcalParser {
                char        *errmsg;
                size_t         linenum;
                char        *tzid;
       -        IcalBlock block;
       +        IcalBlock blocktype;
                IcalStack stack[ICAL_STACK_SIZE], *current;
        };
        
   DIR diff --git a/ics2tree.c b/ics2tree.c
       @@ -14,7 +14,7 @@ print_ruler(int level)
        }
        
        static int
       -fn_entry_name(IcalParser *p, char *name)
       +fn_field_name(IcalParser *p, char *name)
        {
                print_ruler(ical_get_level(p));
                printf("name %s\n", name);
       @@ -41,7 +41,7 @@ fn_param_value(IcalParser *p, char *name, char *value)
        }
        
        static int
       -fn_entry_value(IcalParser *p, char *name, char *value)
       +fn_field_value(IcalParser *p, char *name, char *value)
        {
                size_t len;
                (void)name;
       @@ -69,10 +69,10 @@ main(int argc, char **argv)
                IcalParser p = {0};
                arg0 = *argv++;
        
       -        p.fn_entry_name = fn_entry_name;
       +        p.fn_field_name = fn_field_name;
                p.fn_block_begin = fn_block_begin;
                p.fn_param_value = fn_param_value;
       -        p.fn_entry_value = fn_entry_value;
       +        p.fn_field_value = fn_field_value;
        
                if (*argv == NULL) {
                        if (ical_parse(&p, stdin) < 0)
   DIR diff --git a/ics2tsv.c b/ics2tsv.c
       @@ -1,3 +1,4 @@
       +#include <errno.h>
        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
       @@ -8,25 +9,18 @@
        
        #define FIELDS_MAX 64
        
       -typedef struct Event Event;
       +typedef struct Field Field;
       +typedef struct Block Block;
        
       -struct Event {
       +struct Block {
                time_t beg, end;
                char *fields[FIELDS_MAX];
        };
        
       -static char *fields_time[] = {
       -        "DTSTART", "DTEND", "DTSTAMP", "DUE", "EXDATE", "RDATE"
       -};
       -
       -static char *fields_default[] = {
       -        "ATTENDEE", "CATEGORY", "DESCRIPTION", "LOCATION", "SUMMARY", "URL"
       -};
       -
       -static char **fields = fields_default;
       +Block block;
        
        static int
       -fn_entry_name(IcalParser *p, char *name)
       +fn_field_name(IcalParser *p, char *name)
        {
                printf("name %s\n", name);
                return 0;
       @@ -35,7 +29,14 @@ fn_entry_name(IcalParser *p, char *name)
        static int
        fn_block_begin(IcalParser *p, char *name)
        {
       -        printf("begin %s\n", name);
       +        debug("begin %s\n", name);
       +        return 0;
       +}
       +
       +static int
       +fn_block_end(IcalParser *p, char *name)
       +{
       +        debug("end %s\n", name);
                return 0;
        }
        
       @@ -47,25 +48,26 @@ fn_param_value(IcalParser *p, char *name, char *value)
        }
        
        static int
       -fn_entry_value(IcalParser *p, char *name, char *value)
       +fn_field_value(IcalParser *p, char *name, char *value)
        {
       -        size_t len;
       -        (void)name;
       -
       -        if (ical_get_value(p, value, &len) < 0)
       -                return -1;
       -
       -        if (strcasecmp(name, "DTSTART") == 0 ||
       -            strcasecmp(name, "DTSTAMP") == 0 ||
       -            strcasecmp(name, "DTEND") == 0) {
       -                time_t t = 0;
       -                if (ical_get_time(p, value, &t) != 0)
       -                        warn("%s: %s", p->errmsg, value);
       -                printf("epoch %lld\n", t);
       -        } else {        
       -                printf("value %s\n", value);
       -        }
       -
       +        static char *fieldmap[][2] = {
       +                [ICAL_BLOCK_VEVENT]        = { "DTSTART",        "DTEND" },
       +                [ICAL_BLOCK_VTODO]        = { NULL,        "DUE" },
       +                [ICAL_BLOCK_VJOURNAL]        = { "DTSTAMP",        NULL },
       +                [ICAL_BLOCK_VFREEBUSY]        = { "DTSTART",        "DTEND" },
       +                [ICAL_BLOCK_VALARM]        = { "DTSTART",        NULL },
       +                [ICAL_BLOCK_OTHER]        = { NULL,        NULL },
       +        };
       +        char *beg, *end;
       +
       +        beg = fieldmap[p->blocktype][0];
       +        if (beg != NULL && strcasecmp(name, beg) == 0)
       +                if (ical_get_time(p, value, &block.beg) != 0)
       +                        return -1;
       +        end = fieldmap[p->blocktype][1];
       +        if (end != NULL && strcasecmp(name, end) == 0)
       +                if (ical_get_time(p, value, &block.end) != 0)
       +                        return -1;
                return 0;
        }
        
       @@ -75,10 +77,11 @@ main(int argc, char **argv)
                IcalParser p = {0};
                arg0 = *argv++;
        
       -        p.fn_entry_name = fn_entry_name;
       +        p.fn_field_name = fn_field_name;
                p.fn_block_begin = fn_block_begin;
       +        p.fn_block_end = fn_block_end;
                p.fn_param_value = fn_param_value;
       -        p.fn_entry_value = fn_entry_value;
       +        p.fn_field_value = fn_field_value;
        
                if (*argv == NULL) {
                        if (ical_parse(&p, stdin) < 0)