diff --git a/hmmlib/.gitignore b/hmmlib/.gitignore new file mode 100644 index 0000000..7bf1de1 --- /dev/null +++ b/hmmlib/.gitignore @@ -0,0 +1,4 @@ +example +hmml.a +hmmlib.o +hmmlib.c diff --git a/hmmlib/hmmlib.h b/hmmlib/hmmlib.h index c55ae60..0841fa3 100644 --- a/hmmlib/hmmlib.h +++ b/hmmlib/hmmlib.h @@ -27,6 +27,7 @@ typedef struct { char* editor; char* publisher; char* isbn; + int offset; } HMML_Reference; typedef enum { @@ -40,6 +41,7 @@ typedef enum { typedef struct { HMML_MarkerType type; char* text; + int offset; } HMML_Marker; typedef struct { @@ -61,7 +63,6 @@ typedef struct { HMML_Quote quote; bool is_quote; - } HMML_Annotation; typedef struct { diff --git a/hmmlib/hmmlib.l b/hmmlib/hmmlib.l index 19f5cec..0d5b8ee 100644 --- a/hmmlib/hmmlib.l +++ b/hmmlib/hmmlib.l @@ -13,7 +13,7 @@ HMML_Annotation an; HMML_Reference ref; - HMML_Error* error; + HMML_Error error; char** attr; int mnext; @@ -22,15 +22,21 @@ #define HMML_ERR(fmt, ...) \ do { \ - asprintf(&yyextra->error->message, fmt, ##__VA_ARGS__);\ - yyextra->error->line = yyextra->line;\ + asprintf(&yyextra->error.message, fmt, ##__VA_ARGS__);\ + yyextra->error.line = yyextra->line;\ return 1;\ } while(0) #define V_(x) &yyextra->meta.x #define R_(x) &yyextra->ref.x #define M_(x, state) do { HMML_Marker m = { HMML_ ## x }; sb_push(yyextra->an.markers, m); yyextra->mnext = state; } while(0) -#define M_ADD(t, n) do { char* c = strndup(t, n); sb_last(yyextra->an.markers).text = c; memcpy(sb_add(yyextra->an.text, n), c, n); } while(0) +#define M_ADD(t, n) \ + do { \ + char* c = strndup(t, n);\ + sb_last(yyextra->an.markers).text = c;\ + sb_last(yyextra->an.markers).offset = sb_count(yyextra->an.text);\ + memcpy(sb_add(yyextra->an.text, n), c, n);\ + } while(0) #define NEWANNO() \ do { \ @@ -116,7 +122,7 @@ RB \] {LB}@ { M_(MEMBER , MARKER_XTRA); BEGIN(MARKER); } {LB}~ { M_(PROJECT , MARKER_XTRA); BEGIN(MARKER); } \] { BEGIN(AFTERTEXT); } -{LB}ref { memset(&yyextra->ref, 0, sizeof(yyextra->ref)); BEGIN(REF); } +{LB}ref { yyextra->ref.offset = sb_count(yyextra->an.text); BEGIN(REF); } {LB} {S}{S} { sb_push(yyextra->an.text, ' '); } . { sb_push(yyextra->an.text, *yytext); } @@ -139,7 +145,7 @@ RB \] editor{S}= { yyextra->attr = R_(editor); BEGIN(R_ATTR); } publisher{S}= { yyextra->attr = R_(publisher); BEGIN(R_ATTR); } isbn{S}= { yyextra->attr = R_(isbn); BEGIN(R_ATTR); } -\] { sb_push(yyextra->an.references, yyextra->ref); BEGIN(TEXT); } +\] { sb_push(yyextra->an.references, yyextra->ref); memset(&yyextra->ref, 0, sizeof(yyextra->ref)); BEGIN(TEXT); } . { HMML_ERR("Unexpected item in ref: %s", yytext); } {S} @@ -159,8 +165,8 @@ RB \] {S} {S} -:{ATTR_SIMPLE} { HMML_Marker m = { HMML_CATEGORY, strndup(yytext+1, yyleng-1) }; sb_push(yyextra->an.markers, m); } -:{ATTR_QUOTED} { HMML_Marker m = { HMML_CATEGORY, strndup(yytext+2, yyleng-3) }; sb_push(yyextra->an.markers, m); } +:{ATTR_SIMPLE} { HMML_Marker m = { HMML_CATEGORY, strndup(yytext+1, yyleng-1), -1 }; sb_push(yyextra->an.markers, m); } +:{ATTR_QUOTED} { HMML_Marker m = { HMML_CATEGORY, strndup(yytext+2, yyleng-3), -1 }; sb_push(yyextra->an.markers, m); } \]{LB} { BEGIN(QUOTES); } \] { BEGIN(ANNOTATION); } . { HMML_ERR("Unexpected character in category tag: '%c'\n", *yytext); } @@ -172,11 +178,15 @@ RB \] %% +#define HMML_REF_ITEMS 9 + +static void _hmml_free_ref(HMML_Reference*); +static void _hmml_free_anno(HMML_Annotation*); + HMML_Output hmml_parse_file(FILE* f){ HMML_Output output = {}; HMML_ParseState state = {}; - state.error = &output.error; state.first = true; state.line = 1; @@ -186,29 +196,59 @@ HMML_Output hmml_parse_file(FILE* f){ output.well_formed = yylex(scan) == 0; - if(output.well_formed){ - memcpy(&output.metadata, &state.meta, sizeof(HMML_VideoMetaData)); + memcpy(&output.metadata, &state.meta, sizeof(HMML_VideoMetaData)); - output.annotations = state.annos; - output.annotation_count = sb_count(state.annos); + output.annotations = state.annos; + output.annotation_count = sb_count(state.annos); - for(size_t i = 0; i < output.annotation_count; ++i){ - HMML_Annotation* a = output.annotations + i; - sb_push(a->text, 0); - a->marker_count = sb_count(a->markers); - a->reference_count = sb_count(a->references); + for(size_t i = 0; i < output.annotation_count; ++i){ + HMML_Annotation* a = output.annotations + i; + sb_push(a->text, 0); + a->marker_count = sb_count(a->markers); + a->reference_count = sb_count(a->references); - if(a->is_quote && a->quote.author){ - sb_push(a->quote.author, 0); - } + if(a->is_quote && a->quote.author){ + sb_push(a->quote.author, 0); } } + if(!output.well_formed){ + hmml_free(&output); + memcpy(&output.error, &state.error, sizeof(HMML_Error)); + } + + _hmml_free_anno(&state.an); + _hmml_free_ref(&state.ref); + yylex_destroy(scan); return output; } +static void _hmml_free_ref(HMML_Reference* r){ + for(size_t k = 0; k < HMML_REF_ITEMS; ++k){ + free(((char**)r)[k]); + } +} + +static void _hmml_free_anno(HMML_Annotation* a){ + free(a->time); + free(a->author); + sb_free(a->text); + + for(size_t j = 0; j < a->reference_count; ++j){ + _hmml_free_ref(a->references + j); + } + sb_free(a->references); + + for(size_t j = 0; j < a->marker_count; ++j){ + free(a->markers[j].text); + } + sb_free(a->markers); + + sb_free(a->quote.author); +} + void hmml_free(HMML_Output* hmml){ if(!hmml) return; @@ -217,23 +257,7 @@ void hmml_free(HMML_Output* hmml){ } for(size_t i = 0; i < hmml->annotation_count; ++i){ - HMML_Annotation* a = hmml->annotations + i; - free(a->time); - free(a->author); - sb_free(a->text); - - for(size_t j = 0; j < a->reference_count; ++j){ - for(size_t k = 0; k < sizeof(HMML_Reference)/sizeof(char*); ++k){ - free(((char**)a->references + j)[k]); - } - } - sb_free(a->references); - - for(size_t j = 0; j < a->marker_count; ++j){ - free(a->markers[j].text); - } - sb_free(a->markers); - sb_free(a->quote.author); + _hmml_free_anno(hmml->annotations + i); } sb_free(hmml->annotations); @@ -353,7 +377,7 @@ void hmml_dump(HMML_Output* hmml){ for(size_t j = 0; j < a->reference_count; ++j){ printf("\t%3d ", a->line); HMML_Reference* r = a->references + j; - for(size_t k = 0; k < 9; ++k){ + for(size_t k = 0; k < HMML_REF_ITEMS; ++k){ char* item = ((char**)r)[k]; if(item){ printf("[%s = %s] ", r_tags[k], item); diff --git a/hmmlib/readme.txt b/hmmlib/readme.txt index f92879e..1fea7cc 100644 --- a/hmmlib/readme.txt +++ b/hmmlib/readme.txt @@ -1,5 +1,5 @@ This is a C hmml parser library thing made with flex. -It has just 3 functions, look at hmml.h for the API. +It has just 3 functions, look at hmmlib.h for the API. To build it, run make, and it'll spit out hmml.a that you just need to include on the command line when you build stuff. e.g.: