aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo Hörnquist <hugo@hornquist.se>2019-10-01 23:03:11 +0200
committerHugo Hörnquist <hugo@hornquist.se>2019-10-01 23:03:11 +0200
commitf0e2fe43a5e5e22342a13139815556ae3b373d6c (patch)
tree19acf9638371241e76c70451b33cb717a1247ae8
parentAdd missing '$' sign in main. (diff)
downloadcalp-f0e2fe43a5e5e22342a13139815556ae3b373d6c.tar.gz
calp-f0e2fe43a5e5e22342a13139815556ae3b373d6c.tar.xz
Start moving to scheme structs.
-rw-r--r--src/guile_type_helpers.c11
-rw-r--r--src/parse.c225
-rw-r--r--src/parse.h6
-rw-r--r--src/strbuf.h1
-rw-r--r--src/struct.c59
-rw-r--r--src/struct.h23
-rw-r--r--src/vcal.c6
7 files changed, 190 insertions, 141 deletions
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 <libguile.h>
+#include "struct.h"
+#include "guile_type_helpers.h"
+
// #define TYPE vcomponent
// #include "linked_list.inc.h"
// #undef TYPE
@@ -21,9 +25,32 @@
#undef V
/*
+ +-------------------------------------------------------+
+ v |
+ BEGIN → key -------------------------------→ ':' → value → CRLF -+-→ EOF
+ | ^
+ v |
+ ';' → param-key → ':' → param-value --+
+ ^ |
+ +------------------------------------+
+
+
+ vcomponent := map<string, list<line>>
+ line := pair<value, attributes>
+ attributes := map<string, list<value>>
+
+
+ */
+
+#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 (&param_key, &ctx.str);
+ // TODO
+ // TRANSFER (&param_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 (&param_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)(&param_key);
+ // FREE(content_line)(&cline);
+ // FREE(strbuf)(&cline_key);
+ // FREE(strbuf)(&param_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 <libguile.h>
+
+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 <libguile.h>
+
+#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);
}