From f0e2fe43a5e5e22342a13139815556ae3b373d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=B6rnquist?= Date: Tue, 1 Oct 2019 23:03:11 +0200 Subject: Start moving to scheme structs. --- src/guile_type_helpers.c | 11 +-- src/parse.c | 225 ++++++++++++++++++++--------------------------- src/parse.h | 6 +- src/strbuf.h | 1 - src/struct.c | 59 +++++++++++++ src/struct.h | 23 +++++ src/vcal.c | 6 +- 7 files changed, 190 insertions(+), 141 deletions(-) create mode 100644 src/struct.c create mode 100644 src/struct.h diff --git a/src/guile_type_helpers.c b/src/guile_type_helpers.c index 0353a88a..f03ac671 100644 --- a/src/guile_type_helpers.c +++ b/src/guile_type_helpers.c @@ -4,12 +4,13 @@ #include "macro.h" SCM scm_from_strbuf(strbuf* s) { - if (s->scm == NULL) { - s->scm = scm_from_utf8_stringn (s->mem, s->len); - scm_gc_protect_object(s->scm); - } + // if (s->scm == NULL) { + SCM ret = scm_from_utf8_stringn (s->mem, s->len); + scm_gc_protect_object(ret); + // } - return s->scm; + // return s->scm; + return ret; } SCM scm_from_strbuf_symbol(strbuf* s) { diff --git a/src/parse.c b/src/parse.c index 565e1d6c..e79231cb 100644 --- a/src/parse.c +++ b/src/parse.c @@ -9,6 +9,10 @@ #include "err.h" +#include +#include "struct.h" +#include "guile_type_helpers.h" + // #define TYPE vcomponent // #include "linked_list.inc.h" // #undef TYPE @@ -20,10 +24,33 @@ #undef T #undef V +/* + +-------------------------------------------------------+ + v | + BEGIN → key -------------------------------→ ':' → value → CRLF -+-→ EOF + | ^ + v | + ';' → param-key → ':' → param-value --+ + ^ | + +------------------------------------+ + + + vcomponent := map> + line := pair + attributes := map> + + + */ + +#define string_eq(a, b) scm_string_eq(a, b, SCM_BOOL_F,SCM_BOOL_F,SCM_BOOL_F,SCM_BOOL_F) + /* * name *(";" param) ":" value CRLF */ int parse_file(char* filename, FILE* f, vcomponent* root) { + scm_c_use_module ("(vcomponent struct)"); + + part_context p_ctx = p_key; SNEW(parse_ctx, ctx, f, filename); @@ -36,9 +63,18 @@ int parse_file(char* filename, FILE* f, vcomponent* root) { * {cline,param}_key is also temporary register used during * parsing. */ - SNEW(content_line, cline); - SNEW(strbuf, cline_key); - SNEW(strbuf, param_key); + // SNEW(content_line, cline); + // SNEW(strbuf, param_key); + // SNEW(strbuf, param_val); + // SNEW(strbuf, attr_key); + // SNEW(strbuf, attr_val); + + SNEW(strbuf, str); + SCM component; /* TODO init to root */ + SCM line = scm_make_vline(); + SCM attr_key; /* string */ + SCM line_key; /* string */ + SCM param_set; /* hashtable */ char c; while ( (c = fgetc(f)) != EOF) { @@ -48,21 +84,48 @@ int parse_file(char* filename, FILE* f, vcomponent* root) { if (fold(&ctx, c) > 0) { /* Actuall end of line, handle value */ - TRANSFER(CLINE_CUR_VAL(&cline), &ctx.str); - handle_kv(&cline_key, &cline, &ctx); + // TRANSFER(CLINE_CUR_VAL(&cline), &ctx.str); + /* + * The key being BEGIN means that we decend into a new component. + */ + if (string_eq(line_key, scm_from_utf8_string("BEGIN"))) { + /* key \in { VCALENDAR, VEVENT, VALARM, VTODO, VTIMEZONE, ... } */ + SCM child = scm_make_vcomponent(scm_from_strbuf(&str)); + scm_add_child_x (component, child); + component = child; + + } else if (string_eq(line_key, scm_from_utf8_string("END"))) { + // TODO make current component be parent of current component? + component = scm_component_parent(component); + + /* + * A regular key, value pair. Push it into to the current + * component. + */ + } else { + scm_set_value_x(line, scm_from_strbuf(&str)); + scm_add_line_x(component, line_key, line); + line = scm_make_vline(); + } + + strbuf_soft_reset (&str); p_ctx = p_key; } /* Else continue on current line */ /* We have an escaped character */ } else if (c == '\\') { - handle_escape (&ctx); + char esc = handle_escape (&ctx); + strbuf_append(&str, esc); /* Border between param {key, value} */ } else if (p_ctx == p_param_name && c == '=') { /* Save the current parameter key */ - TRANSFER (¶m_key, &ctx.str); + // TODO + // TRANSFER (¶m_key, &ctx.str); + attr_key = scm_from_strbuf(&str); p_ctx = p_param_value; + strbuf_soft_reset (&str); /* * One of four cases: @@ -77,15 +140,8 @@ int parse_file(char* filename, FILE* f, vcomponent* root) { * the current parameter set. */ if (p_ctx == p_param_value) { /* save current parameter value. */ - - NEW(strbuf, s); - TRANSFER(s, &ctx.str); - - NEW(param_set, ps); - PUSH(param_set)(ps, s); - - PUSH(TRIE(param_set))(CLINE_CUR_PARAMS(&cline), param_key.mem, ps); - strbuf_soft_reset (¶m_key); + scm_add_attribute_x(line, line_key, scm_from_strbuf(&str)); + strbuf_soft_reset (&str); } /* @@ -96,10 +152,12 @@ int parse_file(char* filename, FILE* f, vcomponent* root) { */ if (p_ctx == p_key) { - TRANSFER(&cline_key, &ctx.str); + // TRANSFER(&cline_key, &ctx.str); - NEW(content_set, p); - PUSH(LLIST(content_set))(&cline, p); + // NEW(content_set, p); + // PUSH(LLIST(content_set))(&cline, p); + attr_key = scm_from_strbuf(&str); + strbuf_soft_reset (&str); } if (c == ':') p_ctx = p_value; @@ -110,7 +168,7 @@ int parse_file(char* filename, FILE* f, vcomponent* root) { * the current string. */ } else { - strbuf_append(&ctx.str, c); + strbuf_append(&str, c); ++ctx.column; ++ctx.pcolumn; @@ -121,21 +179,24 @@ int parse_file(char* filename, FILE* f, vcomponent* root) { ERR("Error parsing"); } /* Check to see if empty line */ - else if (ctx.str.ptr != 0) { + else if (str.ptr != 0) { /* * The standard (3.4, l. 2675) says that each icalobject must * end with CRLF. My files however does not, so we also parse * the end here. */ - TRANSFER(CLINE_CUR_VAL(&cline), &ctx.str); - handle_kv(&cline_key, &cline, &ctx); + // TRANSFER(CLINE_CUR_VAL(&cline), &ctx.str); + // TODO + // handle_kv(&cline_key, &cline, &ctx); } - FREE(content_line)(&cline); - FREE(strbuf)(&cline_key); - FREE(strbuf)(¶m_key); + // FREE(content_line)(&cline); + // FREE(strbuf)(&cline_key); + // FREE(strbuf)(¶m_key); + + FREE(strbuf)(&str); assert(POP(LLIST(vcomponent))(&ctx.comp_stack) == root); assert(EMPTY(LLIST(strbuf))(&ctx.key_stack)); @@ -146,102 +207,6 @@ int parse_file(char* filename, FILE* f, vcomponent* root) { return 0; } -/* - * We have a complete key value pair. - */ -int handle_kv ( - strbuf* key, - content_line* cline, - parse_ctx* ctx - ) { - - /* - * The key being BEGIN means that we decend into a new component. - */ - if (strbuf_c(key, "BEGIN")) { - /* key \in { VCALENDAR, VEVENT, VALARM, VTODO, VTIMEZONE, ... } */ - - /* - * Take a copy of the name of the entered component, and store - * it on the stack of component names. - */ - NEW(strbuf, s); - DEEP_COPY(strbuf)(s, CLINE_CUR_VAL(cline)); - PUSH(LLIST(strbuf))(&ctx->key_stack, s); - - /* Clear the value list in the parse content_line */ - RESET(LLIST(content_set))(cline); - - /* - * Create the new curent component, link it with the current - * component in a parent/child relationship. - * Finally push the new component on to the top of the - * component stack. - */ - NEW(vcomponent, e, - s->mem, - ctx->filename); - vcomponent* parent = PEEK(LLIST(vcomponent))(&ctx->comp_stack); - PUSH(vcomponent)(parent, e); - - PUSH(LLIST(vcomponent))(&ctx->comp_stack, e); - - /* - * The end of a component, go back along the stack to the previous - * component. - */ - } else if (strbuf_c(key, "END")) { - strbuf* expected_key = POP(LLIST(strbuf))(&ctx->key_stack); - - if (strbuf_cmp(expected_key, CLINE_CUR_VAL(cline)) != 0) { - - ERR_P(ctx, "Expected END:%s, got END:%s.\n%s line", - expected_key->mem, - CLINE_CUR_VAL(cline)->mem, - vcomponent_get_val( - PEEK(LLIST(vcomponent))(&ctx->comp_stack), - "X-HNH-FILENAME")); - PUSH(LLIST(strbuf))(&ctx->key_stack, expected_key); - - return -1; - - } else { - FFREE(strbuf, expected_key); - POP(LLIST(vcomponent))(&ctx->comp_stack); - } - - /* - * A regular key, value pair. Push it into to the current - * component. - */ - } else { - - /* - * cline is the value store used during parsing, meaning that - * its values WILL mutate at a later point. Therefore we take - * a copy of it here. - */ - NEW(content_line, c); - DEEP_COPY(content_line)(c, cline); - - /* - * The PUSH(TRIE(T)) method handles collisions by calling - * RESOLVE(T). content_line resolves by merging the new value - * into the old value, and freeing the new value's container. - * - * This means that |c| declared above might be destroyed - * here. - */ - PUSH(TRIE(content_line))( - &PEEK(LLIST(vcomponent))(&ctx->comp_stack)->clines, - key->mem, c); - - RESET(LLIST(content_set))(cline); - } - - return 0; -} - int fold(parse_ctx* ctx, char c) { int retval; @@ -289,7 +254,7 @@ INIT_F(parse_ctx, FILE* f, char* filename) { self->pline = 1; self->pcolumn = 1; - INIT(strbuf, &self->str); + // INIT(strbuf, &self->str); return 0; } @@ -302,12 +267,12 @@ FREE_F(parse_ctx) { self->line = 0; self->column = 0; - FREE(strbuf)(&self->str); + // FREE(strbuf)(&self->str); return 0; } -int handle_escape (parse_ctx* ctx) { +char handle_escape (parse_ctx* ctx) { char esc = fgetc(ctx->f); /* @@ -340,11 +305,13 @@ int handle_escape (parse_ctx* ctx) { ERR_P(ctx, "Non escapable character '%c' (%i)", esc, esc); } - /* save escapade character as a normal character */ - strbuf_append(&ctx->str, esc); - ++ctx->column; ++ctx->pcolumn; - return 0; + return esc; + + /* save escapade character as a normal character */ + // strbuf_append(&ctx->str, esc); + + // return 0; } diff --git a/src/parse.h b/src/parse.h index 53263b4c..a7e97ec8 100644 --- a/src/parse.h +++ b/src/parse.h @@ -47,7 +47,7 @@ typedef struct { FILE* f; - /* + /* * context stacks used since ICS files form a tree. key_stack is * only for sequrity purposes. */ @@ -68,7 +68,7 @@ typedef struct { * String which we write everything read into. * Later copied to appropiate places. */ - strbuf str; + // strbuf str; } parse_ctx; INIT_F(parse_ctx, FILE* f, char* filename); @@ -117,6 +117,6 @@ int handle_kv( */ int fold(parse_ctx* ctx, char c); -int handle_escape (parse_ctx* ctx); +char handle_escape (parse_ctx* ctx); #endif /* PARSE_H */ diff --git a/src/strbuf.h b/src/strbuf.h index 7f936a9e..0c028eb6 100644 --- a/src/strbuf.h +++ b/src/strbuf.h @@ -15,7 +15,6 @@ */ typedef struct { char* mem; - SCM scm; /* TODO add support for negative ptr */ int ptr; unsigned int alloc; diff --git a/src/struct.c b/src/struct.c new file mode 100644 index 00000000..cd3ee412 --- /dev/null +++ b/src/struct.c @@ -0,0 +1,59 @@ +#include "struct.h" + +#include + +SCM_DEFINE(scm_make_vcomponent, "make-vcomponent", 1, 0, 0, + (SCM type), + "") +{ + SCM str = scm_from_utf8_string("pr" "pw" "pw" "pr"); + SCM vcomponent_vtable = scm_make_vtable(str, SCM_BOOL_F); + return scm_c_make_struct (vcomponent_vtable, scm_from_int(0), + type, SCM_EOL, SCM_BOOL_F, + scm_make_hash_table(SCM_BOOL_F), + SCM_UNDEFINED); +} + + +SCM_DEFINE(scm_add_line_x, "add-line!", 3, 0, 0, + (SCM vcomponent, SCM key, SCM line), + "") +{ + scm_hash_set_x (scm_struct_ref(vcomponent, vcomponent_lines), key, line); + return SCM_UNSPECIFIED; +} + + +SCM_DEFINE(scm_add_child_x, "add-child!", 2, 0, 0, + (SCM vcomponent, SCM child), + "") +{ + scm_struct_set_x (child, vcomponent_parent, vcomponent); + scm_struct_set_x (vcomponent, vcomponent_children, + scm_cons (child, scm_struct_ref (vcomponent, vcomponent_children))); + + return SCM_UNSPECIFIED; +} + + +SCM_DEFINE(scm_make_vline, "make-vline", 0, 0, 0, + (), "") +{ + SCM vline_vtable = + scm_make_vtable(scm_from_utf8_string("pw" "pw"), + SCM_BOOL_F); + return scm_c_make_struct (vline_vtable, scm_from_int(0), + SCM_BOOL_F, scm_make_hash_table(SCM_BOOL_F), + SCM_UNDEFINED); +} + + +SCM_DEFINE(scm_add_attribute_x, "add-attribute!", 3, 0, 0, + (SCM vline, SCM key, SCM value), + "") +{ + SCM table = scm_struct_ref (vline, vline_attributes); + scm_hash_set_x (table, key, + scm_cons(value, scm_hash_ref(table, key, SCM_EOL))); + return SCM_UNSPECIFIED; +} diff --git a/src/struct.h b/src/struct.h new file mode 100644 index 00000000..838d8180 --- /dev/null +++ b/src/struct.h @@ -0,0 +1,23 @@ +#ifndef STRUCT_H +#define STRUCT_H + +#include + +#define vcomponent_type scm_from_uint8(0) +#define vcomponent_children scm_from_uint8(1) +#define vcomponent_parent scm_from_uint8(2) +#define vcomponent_lines scm_from_uint8(3) + +inline SCM scm_component_parent(SCM component) { + return scm_struct_ref (component, vcomponent_parent); } + +#define vline_value scm_from_uint8(0) +#define vline_attributes scm_from_uint8(1) + +SCM scm_make_vcomponent(SCM); +SCM scm_add_line_x (SCM, SCM, SCM); +SCM scm_add_child_x (SCM, SCM); +SCM scm_make_vline (); +SCM scm_add_attribute_x (SCM, SCM, SCM); + +#endif /* STRUCT_H */ diff --git a/src/vcal.c b/src/vcal.c index 74af44be..29177bf3 100644 --- a/src/vcal.c +++ b/src/vcal.c @@ -61,11 +61,11 @@ INIT_F(vcomponent, const char* type, const char* filename) { /* * NOTE * RFC-7986 adds additional parameters linked to this one. - * - `SOURCE' :: where a (possibly) updated version of the data can be - * found + * - `SOURCE' :: where a (possibly) updated version of the + * data can be found * - `URL' :: Where the same data can be fonud, but * differently (but not where the original data can be fonud - * agani). + * again). */ vcomponent_push_val (self, "X-HNH-FILENAME", filename); } -- cgit v1.2.3