diff options
| author | Jonathan Gordon <rockbox@jdgordon.info> | 2012-04-21 23:34:42 +1000 |
|---|---|---|
| committer | Jonathan Gordon <rockbox@jdgordon.info> | 2012-04-22 00:24:16 +1000 |
| commit | 2d3c43dffeb048297313cd9333731d47d66010a0 (patch) | |
| tree | c5f305939f17cd1014c02991790290be7987a146 /lib | |
| parent | 2315a23c04ec03bbe4496dd079bb68a450658cf7 (diff) | |
| download | rockbox-2d3c43dffeb048297313cd9333731d47d66010a0.zip rockbox-2d3c43dffeb048297313cd9333731d47d66010a0.tar.gz rockbox-2d3c43dffeb048297313cd9333731d47d66010a0.tar.bz2 rockbox-2d3c43dffeb048297313cd9333731d47d66010a0.tar.xz | |
skin_engine: rework the parser to be closer to the langauge grammar.
The parser was unconditionally scanning things which it thought
were conditional/enum lists (or tag arg lists) when they couldn't
possibly be (i.e < inside a param which should be valid).
This change fixes it (i.e %?and(%if(%pv, <, -50), %if(%mp, >i, 1))
is perfectly valid now.
This *may* break your exsiting skins if you were using %if with < or >
Change-Id: Ia24dbdf0b11fc7d8a735c1111d648c3bebd68ac6
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/skin_parser/skin_parser.c | 65 | ||||
| -rw-r--r-- | lib/skin_parser/skin_scan.c | 71 | ||||
| -rw-r--r-- | lib/skin_parser/skin_scan.h | 1 |
3 files changed, 57 insertions, 80 deletions
diff --git a/lib/skin_parser/skin_parser.c b/lib/skin_parser/skin_parser.c index a81bcde..44a1c03 100644 --- a/lib/skin_parser/skin_parser.c +++ b/lib/skin_parser/skin_parser.c @@ -182,26 +182,12 @@ static struct skin_element* skin_parse_viewport(const char** document) } else if(*cursor == TAGSYM) { - /* A ';' directly after a '%' doesn't count */ - cursor ++; - - if(*cursor == '\0') - break; - - cursor++; + skip_tag(&cursor); } else if(*cursor == COMMENTSYM) { skip_comment(&cursor); } - else if(*cursor == ARGLISTOPENSYM) - { - skip_arglist(&cursor); - } - else if(*cursor == ENUMLISTOPENSYM) - { - skip_enumlist(&cursor); - } else { /* Advancing the cursor as normal */ @@ -445,20 +431,9 @@ static struct skin_element* skin_parse_sublines_optional(const char** document, { skip_comment(&cursor); } - else if(*cursor == ENUMLISTOPENSYM) - { - skip_enumlist(&cursor); - } - else if(*cursor == ARGLISTOPENSYM) - { - skip_arglist(&cursor); - } else if(*cursor == TAGSYM) { - cursor++; - if(*cursor == '\0' || *cursor == '\n') - break; - cursor++; + skip_tag(&cursor); } else if(*cursor == MULTILINESYM) { @@ -595,19 +570,12 @@ static int skin_parse_tag(struct skin_element* element, const char** document) /* Skipping over escaped characters */ if(*cursor == TAGSYM) { - cursor++; - if(*cursor == '\0') - break; - cursor++; + skip_tag(&cursor); } else if(*cursor == COMMENTSYM) { skip_comment(&cursor); } - else if(*cursor == ARGLISTOPENSYM) - { - skip_arglist(&cursor); - } else if(*cursor == ARGLISTSEPARATESYM) { num_args++; @@ -974,18 +942,9 @@ static int skin_parse_conditional(struct skin_element* element, const char** doc { skip_comment(&cursor); } - else if(*cursor == ENUMLISTOPENSYM) - { - if (*cursor == '\n') - cursor++; - skip_enumlist(&cursor); - } else if(*cursor == TAGSYM) { - cursor++; - if(*cursor == '\0' || *cursor == '\n') - break; - cursor++; + skip_tag(&cursor); } else if(*cursor == ENUMLISTSEPARATESYM) { @@ -1139,21 +1098,7 @@ static struct skin_element* skin_parse_code_as_arg(const char** document) } else if(*cursor == TAGSYM) { - /* A ';' directly after a '%' doesn't count */ - cursor ++; - - if(*cursor == '\0') - break; - - cursor++; - } - else if(*cursor == ARGLISTOPENSYM) - { - skip_arglist(&cursor); - } - else if(*cursor == ENUMLISTOPENSYM) - { - skip_enumlist(&cursor); + skip_tag(&cursor); } else { diff --git a/lib/skin_parser/skin_scan.c b/lib/skin_parser/skin_scan.c index 50d58bc..f93606d 100644 --- a/lib/skin_parser/skin_scan.c +++ b/lib/skin_parser/skin_scan.c @@ -28,6 +28,7 @@ #include "skin_debug.h" #include "symbols.h" #include "skin_parser.h" +#include "tag_table.h" /* Scanning Functions */ @@ -40,6 +41,54 @@ void skip_comment(const char** document) (*document)++; } +void skip_tag(const char** document) +{ + char tag_name[MAX_TAG_LENGTH]; + int i; + bool qmark; + const struct tag_info *tag; + const char *cursor; + + if(**document == TAGSYM) + (*document)++; + qmark = (**document == CONDITIONSYM); + if (qmark) + (*document)++; + + if (!qmark && find_escape_character(**document)) + { + (*document)++; + } + else + { + cursor = *document; + + /* Checking the tag name */ + for (i=0; cursor[i] && i<MAX_TAG_LENGTH; i++) + tag_name[i] = cursor[i]; + + /* First we check the two characters after the '%', then a single char */ + tag = NULL; + i = MAX_TAG_LENGTH; + while (!tag && i > 1) + { + tag_name[i-1] = '\0'; + tag = find_tag(tag_name); + i--; + } + + if (tag) + { + *document += strlen(tag->name); + } + } + if (**document == ARGLISTOPENSYM) + skip_arglist(document); + + if (**document == ENUMLISTOPENSYM) + skip_enumlist(document); +} + void skip_arglist(const char** document) { if(**document == ARGLISTOPENSYM) @@ -47,16 +96,7 @@ void skip_arglist(const char** document) while(**document && **document != ARGLISTCLOSESYM) { if(**document == TAGSYM) - { - (*document)++; - if(**document == '\0') - break; - (*document)++; - } - else if(**document == ARGLISTOPENSYM) - skip_arglist(document); - else if(**document == ENUMLISTOPENSYM) - skip_enumlist(document); + skip_tag(document); else if(**document == COMMENTSYM) skip_comment(document); else @@ -73,16 +113,7 @@ void skip_enumlist(const char** document) while(**document && **document != ENUMLISTCLOSESYM) { if(**document == TAGSYM) - { - (*document)++; - if(**document == '\0') - break; - (*document)++; - } - else if(**document == ARGLISTOPENSYM) - skip_arglist(document); - else if(**document == ENUMLISTOPENSYM) - skip_enumlist(document); + skip_tag(document); else if(**document == COMMENTSYM) skip_comment(document); else diff --git a/lib/skin_parser/skin_scan.h b/lib/skin_parser/skin_scan.h index 47d8289..6281582 100644 --- a/lib/skin_parser/skin_scan.h +++ b/lib/skin_parser/skin_scan.h @@ -29,6 +29,7 @@ extern "C" /* Scanning functions */ +void skip_tag(const char** document); void skip_comment(const char** document); void skip_arglist(const char** document); void skip_enumlist(const char** document); |