summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJonathan Gordon <rockbox@jdgordon.info>2012-04-21 23:34:42 +1000
committerJonathan Gordon <rockbox@jdgordon.info>2012-04-22 00:24:16 +1000
commit2d3c43dffeb048297313cd9333731d47d66010a0 (patch)
treec5f305939f17cd1014c02991790290be7987a146 /lib
parent2315a23c04ec03bbe4496dd079bb68a450658cf7 (diff)
downloadrockbox-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.c65
-rw-r--r--lib/skin_parser/skin_scan.c71
-rw-r--r--lib/skin_parser/skin_scan.h1
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);