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, > 1))
is perfectly valid now.

This *may* break your exsiting skins if you were using %if with < or >

Change-Id: Ibcb42bc6bb78908f79de024b61276b91b1ce02a0
Reviewed-on: http://gerrit.rockbox.org/214
Reviewed-by: Thomas Martitz <kugel@rockbox.org>
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 @@
             }
             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 @@
         {
             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 @@
         /* 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 @@
         {
             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 @@
         }
         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..f6424ab 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 @@
         (*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 @@
     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 @@
     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 @@
 
 
 /* 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);