aboutsummaryrefslogtreecommitdiff
path: root/parse.c
diff options
context:
space:
mode:
authorHugo Hörnquist <hugo@hornquist.se>2019-01-19 19:06:09 +0100
committerHugo Hörnquist <hugo@hornquist.se>2019-01-19 19:06:14 +0100
commitc42c2834d8c7b5d81465b9d9d127d8384151b9cb (patch)
tree53b1a8eb0368d5f91525604eea2c3173083c1955 /parse.c
parentCan now parse entire directory in one go. (diff)
downloadcalp-c42c2834d8c7b5d81465b9d9d127d8384151b9cb.tar.gz
calp-c42c2834d8c7b5d81465b9d9d127d8384151b9cb.tar.xz
[BROKEN] Work on adding hash tables.
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c197
1 files changed, 59 insertions, 138 deletions
diff --git a/parse.c b/parse.c
index af5a5471..cce311a6 100644
--- a/parse.c
+++ b/parse.c
@@ -1,4 +1,7 @@
-#define SAFE_STR
+#include "parse.h"
+
+#include "macro.h"
+
/*
* TODO currently not all pointers inside strings are reset correctly,
@@ -8,44 +11,8 @@
* along with the introduction of a MSG macro.
*/
-#include <stdio.h>
-#include <stdlib.h>
#include <errno.h>
#include <string.h>
-#include <dirent.h>
-
-/*
- * These three are only for some FD hacks.
- */
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "strbuf.h"
-#include "vcal.h"
-
-/*
- * Max length of a line.
- * TODO update this to allow longer lines, in case someone doesn't
- * follow the standard.
- */
-#define SEGSIZE 75
-
-#define ERR(x, line) do { \
- fprintf(stderr, "ERR %i: %s (cal %i)\n", __LINE__, (x), (line)); \
-} while(0)
-
-#define LINE(nr, key, value) fprintf(stderr, "%i: [%s] := [%s]\n", nr, key, value);
-
-typedef enum {
- p_key, p_value
-} part_context;
-
-typedef enum {
- s_none, s_calendar, s_event
-} scope_context;
-
-int handle_kv(vcalendar* cal, vevent* ev, string* key, string* val, int line, scope_context* s_ctx);
int parse_file(FILE* f, vcalendar* cal) {
int segments = 1;
@@ -58,18 +25,17 @@ int parse_file(FILE* f, vcalendar* cal) {
int keylen = 100;
int vallen = 100;
- string key, val;
-
- init_string(&key, keylen);
- init_string(&val, vallen);
-
int line = 0;
- vevent ev;
+ // TODO this can apparently segfault...
+ NEW(vevent, ev, /**/ 100);
+
+ content_line cline;
+ init_content_line (&cline, keylen, vallen);
char c;
- // TODO this segfaults...
while ( (c = fgetc(f)) != EOF) {
+ // D E S (-48 '\320')
/*
* A carrige return means that the current line is at an
* end. The following character should always be \n.
@@ -84,35 +50,47 @@ int parse_file(FILE* f, vcalendar* cal) {
if (s[0] != '\n') { ERR("expected newline after CR", line); }
else if (s[1] == ' ' || s[1] == '\t') {
+ /*
+ * Folded line, increase size of key and continue.
+ */
+
// TODO check return value
// TODO segments is always incremented here, meaning
// that segment grows larger for every multi line
// encountered.
-#if 1
if (realloc_string(&str, ++segments * SEGSIZE) != 0) { /* TODO signal error */
ERR("Failed to realloc string", line);
exit (1);
}
-#endif
continue;
} else {
+ /*
+ * Actuall end of line, handle values.
+ */
if (ungetc(s[1], f) != s[1]) { /* TODO signal error */
exit (2);
}
/* At TRUE end of line */
+ /*
if (str.ptr + 1 > vallen) {
vallen = str.ptr + 1;
- realloc_string(&val, vallen);
+ // TODO this fails
+ realloc_string(&cline.val, vallen);
}
- copy_strbuf(&val, &str);
- strbuf_cap(&val);
+ */
+ copy_strbuf(&cline.val, &str);
+ strbuf_cap(&cline.val);
++line;
/* We just got a value */
// LINE(line, key.mem, val.mem);
- handle_kv(cal, &ev, &key, &val, line, &s_ctx);
+ if (strbuf_c(&cline.key, "LOCATION")) {
+ if (strbuf_c(&cline.val, "")) return 1;
+ LINE(line, cline.key.mem, cline.val.mem);
+ }
+ handle_kv(cal, ev, &cline, line, &s_ctx);
strbuf_soft_reset(&str);
p_ctx = p_key;
@@ -120,14 +98,14 @@ int parse_file(FILE* f, vcalendar* cal) {
}
} else if (p_ctx == p_key && c == ':') {
/*
- if (str.ptr + 1 > keylen) {
- keylen = str.ptr + 1;
- // TODO this might break everything
- realloc_string(&key, keylen);
+ if (str.ptr + 1 > keylen) {
+ keylen = str.ptr + 1;
+ // TODO this might break everything
+ realloc_string(&key, keylen);
}
*/
- copy_strbuf(&key, &str);
- *strbuf_end(&key) = 0;
+ copy_strbuf(&cline.key, &str);
+ strbuf_cap(&cline.key);
strbuf_soft_reset(&str);
p_ctx = p_value;
continue;
@@ -135,7 +113,9 @@ int parse_file(FILE* f, vcalendar* cal) {
strbuf_append(&str, c);
}
- if (errno != 0) {
+
+
+ if (! feof(f)) {
ERR("Error parsing", errno);
} else {
/*
@@ -145,122 +125,63 @@ int parse_file(FILE* f, vcalendar* cal) {
*/
if (str.ptr + 1 > vallen) {
vallen = str.ptr + 1;
- realloc_string(&val, vallen);
+ realloc_string(&cline.val, vallen);
}
- copy_strbuf(&val, &str);
- *strbuf_cur(&val) = 0;
+ copy_strbuf(&cline.val, &str);
+ *strbuf_cur(&cline.val) = 0;
}
- free_vevent(&ev);
free_string(&str);
- free_string(&key);
- free_string(&val);
+ content_line_free(&cline);
return 0;
}
-int main (int argc, char* argv[argc]) {
- if (argc < 2) {
- //puts("Please give a ics file as first argument");
- puts("Please give vdir as first argument");
- exit (1);
- }
- vcalendar cal;
- init_vcalendar(&cal);
-
- char* dname = argv[1];
- DIR* dir = opendir(dname);
- struct dirent* d;
- int fcount = 0;
- while ((d = readdir(dir)) != NULL) {
-
-
- /* Check that it's a regular file */
- if (d->d_type != DT_REG) continue;
-
- /* Check that we have an ICS file */
- char *s, *fname;
- s = fname = d->d_name;
- while (*(s++) != '.');
- if (strcmp(s, "ics") != 0) continue;
-
- /* We now assume that it's a good file, and start parsing it */
-
- int fd = openat(dirfd(dir), fname, O_RDONLY);
-
- FILE* f = fdopen(fd, "r");
- if (f == NULL) {
- fprintf(stderr, "Error opening file [%s], errno = %i\n",
- fname, errno);
- exit (1);
- }
-
- printf("%3i | %s\n", fcount++, fname);
- /* TODO currently the hedaers cal is overwritten each
- * iteration (not really, since I don't save any headers).
- * Preferably, a special case is made for vdir structures
- * which can assume that all headers are equal. */
- parse_file(f, &cal);
- fclose(f);
-
- }
-
- printf("\nParsed calendar file containing [%lu] events\n",
- cal.n_events);
- for (size_t i = 0; i < cal.n_events; i++) {
- printf("%3lu. %s\n", i + 1, cal.events[i].summary.mem);
- }
-
- free_vcalendar(&cal);
-}
-
-int handle_kv(vcalendar* cal, vevent* ev, string* key, string* val, int line, scope_context* s_ctx) {
+int handle_kv(
+ vcalendar* cal,
+ vevent* ev,
+ content_line* cline,
+ int line,
+ scope_context* s_ctx
+ ) {
switch (*s_ctx) {
case s_none:
- /* Both key and val is null here */
- if (! (strbuf_c(key, "BEGIN") && strbuf_c(val, "VCALENDAR"))) {
+ if (! (strbuf_c(&cline->key, "BEGIN") && strbuf_c(&cline->val, "VCALENDAR"))) {
ERR("Invalid start of calendar", line);
return 1;
}
*s_ctx = s_calendar;
break;
case s_calendar:
- if (strbuf_c(key, "BEGIN")) {
- if (strbuf_c(val, "VEVENT")) {
+ if (strbuf_c(&cline->key, "BEGIN")) {
+ if (strbuf_c(&cline->val, "VEVENT")) {
*s_ctx = s_event;
break;
} else {
ERR("Unsupported start", line);
return 2;
}
- } else if (strbuf_c(key, "END")) {
- if (strbuf_c(val, "VCALENDAR")) {
+ } else if (strbuf_c(&cline->key, "END")) {
+ if (strbuf_c(&cline->val, "VCALENDAR")) {
*s_ctx = s_none;
- /* GOTO cleanup */
break;
}
}
break;
case s_event:
- /* */ if (strbuf_c(key, "DTSTART")) {
- strbuf_init_copy(&ev->dtstart, val);
- } else if (strbuf_c(key, "DTEND")) {
- strbuf_init_copy(&ev->dtend, val);
- } else if (strbuf_c(key, "SUMMARY")) {
- strbuf_init_copy(&ev->summary, val);
- } else if (strbuf_c(key, "DESCRIPTION")) {
- strbuf_init_copy(&ev->description, val);
- } else if (strbuf_c(key, "END")) {
- if (strbuf_c(val, "VEVENT")) {
+ if (strbuf_c(&cline->key, "END")) {
+ if (strbuf_c(&cline->val, "VEVENT")) {
push_event(cal, ev);
*s_ctx = s_calendar;
} else {
ERR("Trying to end something, expected VEVENT", line);
return 3;
}
+ } else {
+ content_line* c = malloc(sizeof(*c));
+ content_line_copy(c, cline);
+ add_content_line (ev, c);
}
-
break;
}
-
return 0;
}