diff --git a/hmmlib/hmmlib.h b/hmmlib/hmmlib.h index 0841fa3..acf637a 100644 --- a/hmmlib/hmmlib.h +++ b/hmmlib/hmmlib.h @@ -40,7 +40,8 @@ typedef enum { typedef struct { HMML_MarkerType type; - char* text; + char* marker; + char* parameter; int offset; } HMML_Marker; diff --git a/hmmlib/hmmlib.l b/hmmlib/hmmlib.l index 0ab5344..faee716 100644 --- a/hmmlib/hmmlib.l +++ b/hmmlib/hmmlib.l @@ -27,17 +27,27 @@ return 1;\ } while(0) +#define CHECKESCAPE(x) do { if(!strchr("[]:@~\\\"", x)) HMML_ERR("Unknown backslash escape code '%c'", x); } 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;\ + char* c = UNQUOTE(strndup(t, n));\ + sb_last(yyextra->an.markers).marker = c;\ sb_last(yyextra->an.markers).offset = sb_count(yyextra->an.text);\ - memcpy(sb_add(yyextra->an.text, n), c, n);\ + if(yyextra->mnext == TEXT){\ + memcpy(sb_add(yyextra->an.text, n), c, n);\ + }\ } while(0) - + +#define MX_ADD(c) \ + do { \ + sb_push(sb_last(yyextra->an.markers).parameter, c);\ + if(c) sb_push(yyextra->an.text, c);\ + } while(0) + #define NEWANNO() \ do { \ if(!yyextra->first) sb_push(yyextra->annos, yyextra->an); \ @@ -46,7 +56,19 @@ yyextra->first = false;\ } while(0) -#define CHECKESCAPE(x) do { if(!strchr("[]:@~\\", x)) HMML_ERR("Unknown backslash escape code '%c'", x); } while(0) +#define UNQUOTE(_attr) ({ \ + typeof(_attr) attr = (_attr); \ + size_t len = strlen(attr); \ + for(char* c = attr; *c; ++c){\ + if(*c == '\\'){ \ + CHECKESCAPE(c[1]); \ + memmove(c, c+1, len-(c-attr)); \ + --len; \ + } \ + } \ + attr; \ +}) + %} %option reentrant @@ -99,7 +121,7 @@ RB \] {S} { BEGIN(VIDEO); } {ATTR_SIMPLE} { *yyextra->attr = strndup(yytext , yyleng ); BEGIN(VIDEO); } -{ATTR_QUOTED} { *yyextra->attr = strndup(yytext+1, yyleng-2); BEGIN(VIDEO); } +{ATTR_QUOTED} { *yyextra->attr = UNQUOTE(strndup(yytext+1, yyleng-2)); BEGIN(VIDEO); } \] { yyless(0); BEGIN(VIDEO); } {TIMECODE}{LB}@ { NEWANNO(); yyextra->an.time = strndup(yytext+1, yyleng-4); BEGIN(AUTHOR); } @@ -125,16 +147,17 @@ RB \] \] { BEGIN(AFTERTEXT); } {LB}ref { yyextra->ref.offset = sb_count(yyextra->an.text); BEGIN(REF); } {LB} -[ \r\t]{1,2} { sb_push(yyextra->an.text, ' '); } +{S} { sb_push(yyextra->an.text, ' '); } . { sb_push(yyextra->an.text, *yytext); } {ATTR_ALNUM} { M_ADD(yytext , yyleng ); BEGIN(yyextra->mnext); }; {ATTR_QUOTED} { M_ADD(yytext+1, yyleng-2); BEGIN(yyextra->mnext); }; . { HMML_ERR("Cannot parse Marker. Expected quoted or alphanumeric attribute."); } - /* TODO: store the extra text somewhere */ -\] { BEGIN(TEXT); } -. +\\] { MX_ADD(']'); } +\] { MX_ADD('\0'); BEGIN(TEXT); } +[ ] { if(sb_last(yyextra->an.markers).parameter){ MX_ADD(' '); } } +. { MX_ADD(*yytext); } {S} site{S}= { yyextra->attr = R_(site); BEGIN(R_ATTR); } @@ -151,7 +174,7 @@ RB \] {S} {ATTR_SIMPLE} { *yyextra->attr = strndup(yytext , yyleng ); BEGIN(REF); } -{ATTR_QUOTED} { *yyextra->attr = strndup(yytext+1, yyleng-2); BEGIN(REF); } +{ATTR_QUOTED} { *yyextra->attr = UNQUOTE(strndup(yytext+1, yyleng-2)); BEGIN(REF); } \[\/video\] { NEWANNO(); return 0; } @@ -166,8 +189,8 @@ RB \] {S} {S} -:{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); } +:{ATTR_SIMPLE} { HMML_Marker m = { HMML_CATEGORY, strndup(yytext+1, yyleng-1), NULL, -1 }; sb_push(yyextra->an.markers, m); } +:{ATTR_QUOTED} { HMML_Marker m = { HMML_CATEGORY, UNQUOTE(strndup(yytext+2, yyleng-3)), NULL, -1 }; sb_push(yyextra->an.markers, m); } \]{LB} { BEGIN(QUOTES); } \] { BEGIN(ANNOTATION); } . { HMML_ERR("Unexpected character in category tag: '%c'\n", *yytext); } @@ -243,7 +266,8 @@ static void _hmml_free_anno(HMML_Annotation* a){ sb_free(a->references); for(size_t j = 0; j < sb_count(a->markers); ++j){ - free(a->markers[j].text); + free(a->markers[j].marker); + sb_free(a->markers[j].parameter); } sb_free(a->markers); @@ -328,7 +352,7 @@ void hmml_dump(HMML_Output* hmml){ for(size_t j = 0; j < a->marker_count; ++j){ int type = a->markers[j].type; - char* text = a->markers[j].text; + char* text = a->markers[j].marker; size_t len = strlen(text); if(len > max_text_len){