aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo Hörnquist <hugo@lysator.liu.se>2019-02-03 21:35:13 +0100
committerHugo Hörnquist <hugo@lysator.liu.se>2019-02-03 21:35:13 +0100
commit7b22939c20afa4f4a08c13a25d71f2720f0b6a29 (patch)
treecca1ec10d242fcaca03104c0fc86656223d1bdb9
parentUpdate gitignore to contain parse and *.x. (diff)
downloadcalp-7b22939c20afa4f4a08c13a25d71f2720f0b6a29.tar.gz
calp-7b22939c20afa4f4a08c13a25d71f2720f0b6a29.tar.xz
Loads of memmory fixes, among other.
-rw-r--r--Makefile3
-rw-r--r--calendar.c35
-rw-r--r--main.c27
-rw-r--r--parse.c76
-rw-r--r--parse.h13
-rw-r--r--strbuf.c18
-rw-r--r--strbuf.h6
-rw-r--r--trie.inc.h4
-rw-r--r--vcal.c32
-rw-r--r--vcal.h10
10 files changed, 175 insertions, 49 deletions
diff --git a/Makefile b/Makefile
index cea10f18..57e78210 100644
--- a/Makefile
+++ b/Makefile
@@ -49,6 +49,9 @@ CALDIR = cal
%.pdf: %.dot
dot -Tpdf -o $@ $<
+tags: $(C_FILES) $(H_FILES)
+ ctags -R
+
clean:
-rm parse
-rm $(OBJDIR)/*.o
diff --git a/calendar.c b/calendar.c
index abecef89..5ac47f58 100644
--- a/calendar.c
+++ b/calendar.c
@@ -14,6 +14,28 @@
#include "macro.h"
#include "parse.h"
+/*
+ * Returns 0 if file has no extersion
+ */
+int get_extension(const char* filename, char* ext, ssize_t max_len) {
+ int ext_idx = -1;
+ ext[0] = '\0';
+ for (char* c = (char*) filename; *c != '\0'; c++) {
+ if (*c == '.') {
+ ext_idx = 0;
+ continue;
+ }
+ if (ext_idx >= 0) {
+ ext[ext_idx++] = *c;
+ if (ext_idx == max_len) break;
+ }
+ }
+ ext[ext_idx] = '\0';
+ return (ext_idx == -1)
+ ? 0
+ : ext_idx;
+}
+
int read_vcalendar(vcalendar* cal, char* path) {
DIR* dir = opendir(path);
@@ -24,11 +46,11 @@ int read_vcalendar(vcalendar* cal, char* path) {
if (d->d_type != DT_REG) continue;
/* Check that we have an ICS file */
- char *s, *fname;
- s = fname = d->d_name;
- while (*(s++) != '.');
+ char* fname = d->d_name;
- if (strcmp(s, "ics") != 0) continue;
+ char ext[10];
+ int has_ext = get_extension(fname, ext, 9);
+ if (! has_ext || strcmp(ext, "ics") != 0) continue;
/* We now assume that it's a good file, and start parsing it */
@@ -45,10 +67,11 @@ int read_vcalendar(vcalendar* cal, char* path) {
* 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);
- cal->events[cal->n_events - 1]->filename = fname;
+ parse_file(fname, f, cal);
+
fclose(f);
+ ;
}
closedir(dir);
diff --git a/main.c b/main.c
index 27385b55..6783c3e3 100644
--- a/main.c
+++ b/main.c
@@ -29,24 +29,43 @@ int main (int argc, char* argv[argc]) {
}
SNEW(vcalendar, cal);
-
read_vcalendar(&cal, args.argv[0]);
+
arg_shift(&args);
if (args.argc == 0 || strcmp(args.argv[0], "-p") == 0) {
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, get_property(cal.events[i], "SUMMARY")->val.mem);
+ char* filename = cal.events[i]->filename;
+
+ printf("%3lu | %s | %s\n",
+ i + 1,
+ filename,
+ get_property(cal.events[i], "SUMMARY")->val.mem);
}
} else if (strcmp(args.argv[0], "-g") == 0) {
if (arg_shift(&args) == 0) {
- create_graph(cal.events[0], "graph.dot");
+ for (size_t i = 0; i < cal.n_events; i++) {
+ char target[0xFF];
+ target[0] = '\0';
+ strcat(target, "/tmp/dot/");
+ strcat(target, cal.events[i]->filename);
+ strcat(target, ".dot");
+ create_graph(cal.events[i], target);
+ }
+ // create_graph(cal.events[0], "graph.dot");
} else {
create_graph(cal.events[0], args.argv[0]);
}
}
+ free_vcalendar(&cal);
+ for (int i = 0; i < cline_ptr; i++) {
+ if (clines[i] != NULL) {
+ printf("clines[%i] : [%s] := [%s]\n", i, clines[i]->key.mem, clines[i]->val.mem);
+ }
+ }
- free_vcalendar(&cal);
+ free(clines);
}
diff --git a/parse.c b/parse.c
index 6b0f835b..82a60671 100644
--- a/parse.c
+++ b/parse.c
@@ -4,20 +4,27 @@
#include <string.h>
#include "macro.h"
+#include "vcal.h"
-int parse_file(FILE* f, vcalendar* cal) {
+int parse_file(char* fname, FILE* f, vcalendar* cal) {
int segments = 1;
SNEW(strbuf, str, segments * SEGSIZE);
part_context p_ctx = p_key;
- scope_context s_ctx = s_none;
+ SNEW(strbuf, skip, SEGSIZE);
+ parse_ctx ctx = {
+ .scope = s_none,
+ .skip_to = &skip
+ };
+ // scope_context s_ctx = s_none;
int keylen = 100;
int vallen = 100;
int line = 0;
- NEW(vevent, ev);
+ // NEW(vevent, ev, fname);
+ vevent* ev = NULL;
SNEW(content_line, cline, keylen, vallen);
@@ -66,23 +73,27 @@ int parse_file(FILE* f, vcalendar* cal) {
++line;
- handle_kv(cal, ev, &cline, line, &s_ctx);
+ switch (handle_kv(cal, ev, &cline, line, &ctx)) {
+ case s_event:
+ ev = malloc(sizeof(*ev));
+ CONSTRUCT(vevent, ev, fname);
+ break;
+ }
strbuf_soft_reset(&str);
p_ctx = p_key;
continue;
}
+
/*
* TODO context for property_{key,val}.
*/
} else if (p_ctx == p_key && c == ':') {
- /*
- if (str.ptr + 1 > keylen) {
- keylen = str.ptr + 1;
- // TODO this might break everything
- strbuf_realloc(&key, keylen);
+ if (str.ptr + 1 > keylen) {
+ keylen = str.ptr + 1;
+ // TODO this might break everything
+ // strbuf_realloc(&cline.key, keylen);
}
- */
strbuf_copy(&cline.key, &str);
strbuf_cap(&cline.key);
strbuf_soft_reset(&str);
@@ -93,7 +104,6 @@ int parse_file(FILE* f, vcalendar* cal) {
strbuf_append(&str, c);
}
-
if (! feof(f)) {
ERR("Error parsing", errno);
} else {
@@ -101,7 +111,7 @@ int parse_file(FILE* f, vcalendar* cal) {
* 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.
- * TODO this doesn't do anything with its read value
+ * TODO -- this doesn't do anything with its read value
* TODO This might crash if we have the CRLF
*/
if (str.ptr + 1 > vallen) {
@@ -109,10 +119,12 @@ int parse_file(FILE* f, vcalendar* cal) {
strbuf_realloc(&cline.val, vallen);
}
strbuf_copy(&cline.val, &str);
- *strbuf_cur(&cline.val) = 0;
+ strbuf_cap(&cline.val);
+ handle_kv(cal, ev, &cline, line, &ctx);
}
FREE(strbuf)(&str);
FREE(content_line)(&cline);
+ FREE(strbuf)(ctx.skip_to);
return 0;
}
@@ -125,40 +137,58 @@ int handle_kv(
vevent* ev,
content_line* cline,
int line,
- scope_context* s_ctx
+ // scope_context* s_ctx
+ parse_ctx* ctx
) {
- switch (*s_ctx) {
+ switch (ctx->scope) {
+
+ case s_skip:
+ if (strbuf_c(&cline->key, "END") && strbuf_cmp(&cline->val, ctx->skip_to)) {
+ ctx->scope = s_calendar;
+ // FREE(strbuf)(ctx->skip_to);
+ }
+ break;
+
case s_none:
if (! (strbuf_c(&cline->key, "BEGIN") && strbuf_c(&cline->val, "VCALENDAR"))) {
ERR("Invalid start of calendar", line);
- return 1;
+ return -1;
}
- *s_ctx = s_calendar;
+ ctx->scope = s_calendar;
break;
+
case s_calendar:
if (strbuf_c(&cline->key, "BEGIN")) {
if (strbuf_c(&cline->val, "VEVENT")) {
- *s_ctx = s_event;
+ ctx->scope = s_event;
+ return ctx->scope;
break;
} else {
- ERR("Unsupported start", line);
- return 2;
+ // ERR("Unsupported start", line);
+ ctx->scope = s_skip;
+ strbuf_copy(ctx->skip_to, &cline->val);
}
} else if (strbuf_c(&cline->key, "END")) {
if (strbuf_c(&cline->val, "VCALENDAR")) {
- *s_ctx = s_none;
+ ctx->scope = s_none;
break;
}
}
break;
+
case s_event:
+ if (ev == NULL) {
+ ERR("Something has gone terribly wrong", line);
+ return -5;
+ }
if (strbuf_c(&cline->key, "END")) {
if (strbuf_c(&cline->val, "VEVENT")) {
push_event(cal, ev);
- *s_ctx = s_calendar;
+ ctx->scope = s_calendar;
+ return ctx->scope;
} else {
ERR("Trying to end something, expected VEVENT", line);
- return 3;
+ return -3;
}
} else {
NEW(content_line, c);
diff --git a/parse.h b/parse.h
index 76611599..667ccd35 100644
--- a/parse.h
+++ b/parse.h
@@ -25,17 +25,24 @@ typedef enum {
} part_context;
typedef enum {
- s_none, s_calendar, s_event
+ s_none = 1, s_calendar, s_event,
+ s_skip
} scope_context;
+typedef struct {
+ scope_context scope;
+ strbuf* skip_to;
+} parse_ctx;
+
int handle_kv(
vcalendar* cal,
vevent* ev,
content_line* cline,
int line,
- scope_context* s_ctx
+ // scope_context* s_ctx
+ parse_ctx* ctx
);
-int parse_file(FILE* f, vcalendar* cal);
+int parse_file(char* fname, FILE* f, vcalendar* cal);
#endif /* PARSE_H */
diff --git a/strbuf.c b/strbuf.c
index 353b6d84..0dbaa0c7 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -25,9 +25,9 @@ int CONSTRUCTOR_DECL(strbuf, size_t len) {
int strbuf_realloc(strbuf* str, size_t len) {
#ifdef SAFE_STR
- if (str->mem == NULL || str->alloc == 0) {
+ if (str->mem == NULL /*|| str->alloc == -1*/) {
ERR("String memory not initialized");
- return 1;
+ // return 1;
}
#endif
str->mem = realloc(str->mem, len);
@@ -38,14 +38,12 @@ int strbuf_realloc(strbuf* str, size_t len) {
// int strbuf_free(strbuf* str) {
int FREE_DECL(strbuf) {
#ifdef SAFE_STR
- if (this->alloc == 0 || this->mem == NULL) {
- ERR("String not allocated");
- return 1;
- }
+ if (this->mem == NULL) return 1;
#endif
- // fprintf(stderr, "Memmory = %p | %4lu | %s\n", this->mem, this->alloc, this->mem);
free (this->mem);
+ this->mem = NULL;
this->alloc = 0;
+ this->len = 0;
return 0;
}
@@ -103,6 +101,12 @@ int strbuf_reset(strbuf* s)
return 0;
}
+int strbuf_realloc_copy(strbuf* dest, strbuf* src) {
+ strbuf_realloc(dest, src->len);
+ strbuf_copy(dest, src);
+ return 0;
+}
+
int strbuf_init_copy(strbuf* dest, strbuf* src) {
#ifdef SAFE_STR
if (dest->alloc != 0) {
diff --git a/strbuf.h b/strbuf.h
index 678d87ff..b5cd085f 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -72,6 +72,12 @@ int strbuf_soft_reset(strbuf* s);
char* strbuf_end(strbuf* s);
/*
+ * Reallocs dest to be the same size as src, and copies the contents
+ * of src into dest.
+ */
+int strbuf_realloc_copy(strbuf* dest, strbuf* src);
+
+/*
* Copies contents from src to dest, also allocating dest in the
* process. dest should not be initialized before this call.
*/
diff --git a/trie.inc.h b/trie.inc.h
index 316b54b2..b839a7e8 100644
--- a/trie.inc.h
+++ b/trie.inc.h
@@ -107,6 +107,10 @@ int TRIE_NODE_FREE(TYPE) ( TRIE_NODE(TYPE)* node ) {
}
int TRIE_FREE(TYPE) ( TRIE(TYPE)* trie ) {
+ if (trie->root->c != '\0') {
+ // ERR("Invalid trie");
+ return 1;
+ }
return TRIE_NODE_FREE(TYPE)(trie->root);
}
diff --git a/vcal.c b/vcal.c
index 2310c3fb..7464c72b 100644
--- a/vcal.c
+++ b/vcal.c
@@ -7,8 +7,18 @@
#include "trie.inc.h"
#undef TYPE
-int CONSTRUCTOR_DECL(vevent) {
+content_line** clines;
+int cline_ptr;
+
+int CONSTRUCTOR_DECL(vevent, char* filename) {
+
CONSTRUCT(TRIE(content_line), &this->clines);
+
+ this->filename = calloc(sizeof(*filename), strlen(filename) + 1);
+ strcpy(this->filename, filename);
+
+ this->calendar = NULL;
+
return 0;
}
@@ -22,6 +32,7 @@ int add_content_line (vevent* ev, content_line* c) {
}
int CONSTRUCTOR_DECL(content_line) {
+ clines[cline_ptr++] = this;
CONSTRUCT(strbuf, &this->key);
CONSTRUCT(strbuf, &this->val);
// TODO remaining fields
@@ -29,6 +40,7 @@ int CONSTRUCTOR_DECL(content_line) {
}
int CONSTRUCTOR_DECL(content_line, int keylen, int vallen) {
+ clines[cline_ptr++] = this;
CONSTRUCT(strbuf, &this->key, keylen);
CONSTRUCT(strbuf, &this->val, vallen);
// TODO remaining fields
@@ -46,18 +58,30 @@ int content_line_copy (content_line* dest, content_line* src) {
int FREE_DECL(content_line) {
FREE(strbuf)(&this->key);
FREE(strbuf)(&this->val);
+ for (int i = 0; i < cline_ptr; i++) {
+ if (clines[i] == this) {
+ clines[i] = NULL;
+ }
+ }
// TODO remaining fields
return 0;
}
int FREE_DECL(vevent) {
- TRIE_FREE(content_line)(&this->clines);
+ if (this->filename != NULL) free(this->filename);
+ if (TRIE_FREE(content_line)(&this->clines) != 0) {
+ fprintf(stderr, "Error freeing vevent belonging to file \n %s \n",
+ this->filename);
+ }
+
return 0;
}
int push_event(vcalendar* cal, vevent* ev) {
- /* Make sure that cal->events is large enough */
+ ev->calendar = cal;
+
+ /* Make sure that cal->eents is large enough */
if (cal->n_events + 1 > cal->alloc) {
cal->alloc <<= 1;
cal->events = realloc(cal->events, sizeof(*cal->events) * cal->alloc);
@@ -71,6 +95,8 @@ int push_event(vcalendar* cal, vevent* ev) {
}
int CONSTRUCTOR_DECL(vcalendar) {
+ clines = calloc(sizeof(*clines), 10000);
+ cline_ptr = 0;
this->alloc = 1;
this->events = calloc(sizeof(*this->events), this->alloc);
this->n_events = 0;
diff --git a/vcal.h b/vcal.h
index 32564cb2..350871b7 100644
--- a/vcal.h
+++ b/vcal.h
@@ -14,8 +14,8 @@ typedef struct {
typedef struct {
strbuf key;
- strbuf val;
+ strbuf val;
strbuf* aux_values;
int value_count;
@@ -33,10 +33,11 @@ int CONSTRUCTOR_DECL(content_line, int keylen, int vallen);
typedef struct s_vevent {
char* filename;
+ struct s_vcalendar* calendar;
TRIE(content_line) clines;
} vevent;
-int CONSTRUCTOR_DECL(vevent);
+int CONSTRUCTOR_DECL(vevent, char* filename);
int FREE_DECL(content_line);
int content_line_copy (content_line* dest, content_line* src);
@@ -47,7 +48,7 @@ int add_content_line (vevent* ev, content_line* c);
int free_vevent(vevent* ev);
-typedef struct {
+typedef struct s_vcalendar {
size_t n_events;
size_t alloc;
vevent** events;
@@ -62,4 +63,7 @@ int free_vcalendar (vcalendar* cal);
*/
int push_event(vcalendar* cal, vevent* ev);
+extern content_line** clines;
+extern int cline_ptr;
+
#endif /* VCAL_H */