Add optional parameter to HMML_Markers + fix stuff*

* make sure quoted attrs are unescaped properly
This commit is contained in:
Alex Baines 2017-03-18 17:29:10 +00:00
parent f4217d5057
commit c31b486cfa
2 changed files with 41 additions and 16 deletions

View File

@ -40,7 +40,8 @@ typedef enum {
typedef struct { typedef struct {
HMML_MarkerType type; HMML_MarkerType type;
char* text; char* marker;
char* parameter;
int offset; int offset;
} HMML_Marker; } HMML_Marker;

View File

@ -27,15 +27,25 @@
return 1;\ return 1;\
} while(0) } 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 V_(x) &yyextra->meta.x
#define R_(x) &yyextra->ref.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_(x, state) do { HMML_Marker m = { HMML_ ## x }; sb_push(yyextra->an.markers, m); yyextra->mnext = state; } while(0)
#define M_ADD(t, n) \ #define M_ADD(t, n) \
do { \ do { \
char* c = strndup(t, n);\ char* c = UNQUOTE(strndup(t, n));\
sb_last(yyextra->an.markers).text = c;\ sb_last(yyextra->an.markers).marker = c;\
sb_last(yyextra->an.markers).offset = sb_count(yyextra->an.text);\ 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) } while(0)
#define NEWANNO() \ #define NEWANNO() \
@ -46,7 +56,19 @@
yyextra->first = false;\ yyextra->first = false;\
} while(0) } 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 %option reentrant
@ -99,7 +121,7 @@ RB \]
<V_ATTR>{S} { BEGIN(VIDEO); } <V_ATTR>{S} { BEGIN(VIDEO); }
<V_ATTR>{ATTR_SIMPLE} { *yyextra->attr = strndup(yytext , yyleng ); BEGIN(VIDEO); } <V_ATTR>{ATTR_SIMPLE} { *yyextra->attr = strndup(yytext , yyleng ); BEGIN(VIDEO); }
<V_ATTR>{ATTR_QUOTED} { *yyextra->attr = strndup(yytext+1, yyleng-2); BEGIN(VIDEO); } <V_ATTR>{ATTR_QUOTED} { *yyextra->attr = UNQUOTE(strndup(yytext+1, yyleng-2)); BEGIN(VIDEO); }
<V_ATTR>\] { yyless(0); BEGIN(VIDEO); } <V_ATTR>\] { yyless(0); BEGIN(VIDEO); }
<ANNOTATION>{TIMECODE}{LB}@ { NEWANNO(); yyextra->an.time = strndup(yytext+1, yyleng-4); BEGIN(AUTHOR); } <ANNOTATION>{TIMECODE}{LB}@ { NEWANNO(); yyextra->an.time = strndup(yytext+1, yyleng-4); BEGIN(AUTHOR); }
@ -125,16 +147,17 @@ RB \]
<TEXT>\] { BEGIN(AFTERTEXT); } <TEXT>\] { BEGIN(AFTERTEXT); }
<TEXT>{LB}ref { yyextra->ref.offset = sb_count(yyextra->an.text); BEGIN(REF); } <TEXT>{LB}ref { yyextra->ref.offset = sb_count(yyextra->an.text); BEGIN(REF); }
<TEXT>{LB} <TEXT>{LB}
<TEXT>[ \r\t]{1,2} { sb_push(yyextra->an.text, ' '); } <TEXT>{S} { sb_push(yyextra->an.text, ' '); }
<TEXT>. { sb_push(yyextra->an.text, *yytext); } <TEXT>. { sb_push(yyextra->an.text, *yytext); }
<MARKER>{ATTR_ALNUM} { M_ADD(yytext , yyleng ); BEGIN(yyextra->mnext); }; <MARKER>{ATTR_ALNUM} { M_ADD(yytext , yyleng ); BEGIN(yyextra->mnext); };
<MARKER>{ATTR_QUOTED} { M_ADD(yytext+1, yyleng-2); BEGIN(yyextra->mnext); }; <MARKER>{ATTR_QUOTED} { M_ADD(yytext+1, yyleng-2); BEGIN(yyextra->mnext); };
<MARKER>. { HMML_ERR("Cannot parse Marker. Expected quoted or alphanumeric attribute."); } <MARKER>. { HMML_ERR("Cannot parse Marker. Expected quoted or alphanumeric attribute."); }
/* TODO: store the extra text somewhere */ <MARKER_XTRA>\\] { MX_ADD(']'); }
<MARKER_XTRA>\] { BEGIN(TEXT); } <MARKER_XTRA>\] { MX_ADD('\0'); BEGIN(TEXT); }
<MARKER_XTRA>. <MARKER_XTRA>[ ] { if(sb_last(yyextra->an.markers).parameter){ MX_ADD(' '); } }
<MARKER_XTRA>. { MX_ADD(*yytext); }
<REF>{S} <REF>{S}
<REF>site{S}= { yyextra->attr = R_(site); BEGIN(R_ATTR); } <REF>site{S}= { yyextra->attr = R_(site); BEGIN(R_ATTR); }
@ -151,7 +174,7 @@ RB \]
<R_ATTR>{S} <R_ATTR>{S}
<R_ATTR>{ATTR_SIMPLE} { *yyextra->attr = strndup(yytext , yyleng ); BEGIN(REF); } <R_ATTR>{ATTR_SIMPLE} { *yyextra->attr = strndup(yytext , yyleng ); BEGIN(REF); }
<R_ATTR>{ATTR_QUOTED} { *yyextra->attr = strndup(yytext+1, yyleng-2); BEGIN(REF); } <R_ATTR>{ATTR_QUOTED} { *yyextra->attr = UNQUOTE(strndup(yytext+1, yyleng-2)); BEGIN(REF); }
<AFTERTEXT,ANNOTATION>\[\/video\] { NEWANNO(); return 0; } <AFTERTEXT,ANNOTATION>\[\/video\] { NEWANNO(); return 0; }
@ -166,8 +189,8 @@ RB \]
<AUTHOR>{S} <AUTHOR>{S}
<CATEGORIES>{S} <CATEGORIES>{S}
<CATEGORIES>:{ATTR_SIMPLE} { HMML_Marker m = { HMML_CATEGORY, strndup(yytext+1, yyleng-1), -1 }; sb_push(yyextra->an.markers, m); } <CATEGORIES>:{ATTR_SIMPLE} { HMML_Marker m = { HMML_CATEGORY, strndup(yytext+1, yyleng-1), NULL, -1 }; sb_push(yyextra->an.markers, m); }
<CATEGORIES>:{ATTR_QUOTED} { HMML_Marker m = { HMML_CATEGORY, strndup(yytext+2, yyleng-3), -1 }; sb_push(yyextra->an.markers, m); } <CATEGORIES>:{ATTR_QUOTED} { HMML_Marker m = { HMML_CATEGORY, UNQUOTE(strndup(yytext+2, yyleng-3)), NULL, -1 }; sb_push(yyextra->an.markers, m); }
<CATEGORIES>\]{LB} { BEGIN(QUOTES); } <CATEGORIES>\]{LB} { BEGIN(QUOTES); }
<CATEGORIES>\] { BEGIN(ANNOTATION); } <CATEGORIES>\] { BEGIN(ANNOTATION); }
<CATEGORIES>. { HMML_ERR("Unexpected character in category tag: '%c'\n", *yytext); } <CATEGORIES>. { 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); sb_free(a->references);
for(size_t j = 0; j < sb_count(a->markers); ++j){ 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); sb_free(a->markers);
@ -328,7 +352,7 @@ void hmml_dump(HMML_Output* hmml){
for(size_t j = 0; j < a->marker_count; ++j){ for(size_t j = 0; j < a->marker_count; ++j){
int type = a->markers[j].type; int type = a->markers[j].type;
char* text = a->markers[j].text; char* text = a->markers[j].marker;
size_t len = strlen(text); size_t len = strlen(text);
if(len > max_text_len){ if(len > max_text_len){