diff options
Diffstat (limited to 'utils/themeeditor/skin_parser.c')
| -rw-r--r-- | utils/themeeditor/skin_parser.c | 923 |
1 files changed, 0 insertions, 923 deletions
diff --git a/utils/themeeditor/skin_parser.c b/utils/themeeditor/skin_parser.c deleted file mode 100644 index 93a7191..0000000 --- a/utils/themeeditor/skin_parser.c +++ /dev/null @@ -1,923 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2010 Robert Bieber - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> - -#include "skin_parser.h" -#include "skin_debug.h" -#include "tag_table.h" -#include "symbols.h" -#include "skin_scan.h" - -#ifdef ROCKBOX -/* Declaration of parse tree buffer */ -#define SKIN_MAX_MEMORY (30*1024) -static char skin_parse_tree[SKIN_MAX_MEMORY]; -static char *skin_buffer; -#endif - -/* Global variables for the parser */ -int skin_line = 0; - -/* Auxiliary parsing functions (not visible at global scope) */ -static struct skin_element* skin_parse_viewport(char** document); -static struct skin_element* skin_parse_line(char** document); -static struct skin_element* skin_parse_line_optional(char** document, - int conditional); -static struct skin_element* skin_parse_sublines(char** document); -static struct skin_element* skin_parse_sublines_optional(char** document, - int conditional); - -static int skin_parse_tag(struct skin_element* element, char** document); -static int skin_parse_text(struct skin_element* element, char** document, - int conditional); -static int skin_parse_conditional(struct skin_element* element, - char** document); -static int skin_parse_comment(struct skin_element* element, char** document); -static struct skin_element* skin_parse_code_as_arg(char** document); - -struct skin_element* skin_parse(const char* document) -{ - - struct skin_element* root = NULL; - struct skin_element* last = NULL; - - struct skin_element** to_write = 0; - - char* cursor = (char*)document; /*Keeps track of location in the document*/ -#ifdef ROCKBOX - /* FIXME */ - skin_buffer = &skin_parse_tree[0]; -#endif - - skin_line = 1; - - skin_clear_errors(); - - while(*cursor != '\0') - { - - if(!root) - to_write = &root; - else - to_write = &(last->next); - - - *to_write = skin_parse_viewport(&cursor); - last = *to_write; - if(!last) - { - skin_free_tree(root); /* Clearing any memory already used */ - return NULL; - } - - /* Making sure last is at the end */ - while(last->next) - last = last->next; - - } - - return root; - -} - -static struct skin_element* skin_parse_viewport(char** document) -{ - - struct skin_element* root = NULL; - struct skin_element* last = NULL; - struct skin_element* retval = NULL; - - retval = skin_alloc_element(); - retval->type = VIEWPORT; - retval->children_count = 1; - retval->line = skin_line; - - struct skin_element** to_write = 0; - - char* cursor = *document; /* Keeps track of location in the document */ - char* bookmark; /* Used when we need to look ahead */ - - int sublines = 0; /* Flag for parsing sublines */ - - /* Parsing out the viewport tag if there is one */ - if(check_viewport(cursor)) - { - skin_parse_tag(retval, &cursor); - if(*cursor == '\n') - { - cursor++; - skin_line++; - } - } - - retval->children_count = 1; - retval->children = skin_alloc_children(1); - - - do - { - - /* First, we check to see if this line will contain sublines */ - bookmark = cursor; - sublines = 0; - while(*cursor != '\n' && *cursor != '\0' - && !(check_viewport(cursor) && cursor != *document)) - { - if(*cursor == MULTILINESYM) - { - sublines = 1; - break; - } - else if(*cursor == TAGSYM) - { - /* A ';' directly after a '%' doesn't count */ - cursor ++; - - if(*cursor == '\0') - break; - - 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 */ - cursor++; - } - } - cursor = bookmark; - - if(!root) - to_write = &root; - else - to_write = &(last->next); - - if(sublines) - { - *to_write = skin_parse_sublines(&cursor); - last = *to_write; - if(!last) - return NULL; - } - else - { - - *to_write = skin_parse_line(&cursor); - last = *to_write; - if(!last) - return NULL; - - } - - /* Making sure last is at the end */ - while(last->next) - last = last->next; - - if(*cursor == '\n') - { - cursor++; - skin_line++; - } - } - while(*cursor != '\0' && !(check_viewport(cursor) && cursor != *document)); - - *document = cursor; - - retval->children[0] = root; - return retval; - -} - -/* Auxiliary Parsing Functions */ - -static struct skin_element* skin_parse_line(char**document) -{ - - return skin_parse_line_optional(document, 0); - -} - - -/* - * If conditional is set to true, then this will break upon encountering - * SEPERATESYM. This should only be used when parsing a line inside a - * conditional, otherwise just use the wrapper function skin_parse_line() - */ -static struct skin_element* skin_parse_line_optional(char** document, - int conditional) -{ - char* cursor = *document; - - struct skin_element* root = NULL; - struct skin_element* current = NULL; - struct skin_element* retval = NULL; - - /* A wrapper for the line */ - retval = skin_alloc_element(); - retval->type = LINE; - retval->line = skin_line; - if(*cursor != '\0' && *cursor != '\n' - && !(conditional && (*cursor == ARGLISTSEPERATESYM - || *cursor == ARGLISTCLOSESYM - || *cursor == ENUMLISTSEPERATESYM - || *cursor == ENUMLISTCLOSESYM))) - { - retval->children_count = 1; - } - else - { - retval->children_count = 0; - } - - if(retval->children_count > 0) - retval->children = skin_alloc_children(1); - - while(*cursor != '\n' && *cursor != '\0' && *cursor != MULTILINESYM - && !((*cursor == ARGLISTSEPERATESYM - || *cursor == ARGLISTCLOSESYM - || *cursor == ENUMLISTSEPERATESYM - || *cursor == ENUMLISTCLOSESYM) - && conditional) - && !(check_viewport(cursor) && cursor != *document)) - { - /* Allocating memory if necessary */ - if(root) - { - current->next = skin_alloc_element(); - current = current->next; - } - else - { - current = skin_alloc_element(); - root = current; - } - - /* Parsing the current element */ - if(*cursor == TAGSYM && cursor[1] == CONDITIONSYM) - { - if(!skin_parse_conditional(current, &cursor)) - return NULL; - } - else if(*cursor == TAGSYM && !find_escape_character(cursor[1])) - { - if(!skin_parse_tag(current, &cursor)) - return NULL; - } - else if(*cursor == COMMENTSYM) - { - if(!skin_parse_comment(current, &cursor)) - return NULL; - } - else - { - if(!skin_parse_text(current, &cursor, conditional)) - return NULL; - } - } - - /* Moving up the calling function's pointer */ - *document = cursor; - - if(root) - retval->children[0] = root; - return retval; -} - -static struct skin_element* skin_parse_sublines(char** document) -{ - return skin_parse_sublines_optional(document, 0); -} - -static struct skin_element* skin_parse_sublines_optional(char** document, - int conditional) -{ - struct skin_element* retval; - char* cursor = *document; - int sublines = 1; - int i; - - retval = skin_alloc_element(); - retval->type = SUBLINES; - retval->next = NULL; - retval->line = skin_line; - - /* First we count the sublines */ - while(*cursor != '\0' && *cursor != '\n' - && !((*cursor == ARGLISTSEPERATESYM - || *cursor == ARGLISTCLOSESYM - || *cursor == ENUMLISTSEPERATESYM - || *cursor == ENUMLISTCLOSESYM) - && conditional) - && !(check_viewport(cursor) && cursor != *document)) - { - if(*cursor == COMMENTSYM) - { - 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++; - } - else if(*cursor == MULTILINESYM) - { - sublines++; - cursor++; - } - else - { - cursor++; - } - } - - /* ...and then we parse them */ - retval->children_count = sublines; - retval->children = skin_alloc_children(sublines); - - cursor = *document; - for(i = 0; i < sublines; i++) - { - retval->children[i] = skin_parse_line_optional(&cursor, conditional); - skip_whitespace(&cursor); - - if(*cursor != MULTILINESYM && i != sublines - 1) - { - skin_error(MULTILINE_EXPECTED); - return NULL; - } - else if(i != sublines - 1) - { - cursor++; - } - } - - *document = cursor; - - return retval; -} - -static int skin_parse_tag(struct skin_element* element, char** document) -{ - - char* cursor = *document + 1; - char* bookmark; - - char tag_name[3]; - char* tag_args; - struct tag_info *tag; - - int num_args = 1; - int i; - int star = 0; /* Flag for the all-or-none option */ - int req_args; /* To mark when we enter optional arguments */ - - int optional = 0; - - /* Checking the tag name */ - tag_name[0] = cursor[0]; - tag_name[1] = cursor[1]; - tag_name[2] = '\0'; - - /* First we check the two characters after the '%', then a single char */ - tag = find_tag(tag_name); - - if(!tag) - { - tag_name[1] = '\0'; - tag = find_tag(tag_name); - cursor++; - } - else - { - cursor += 2; - } - - if(!tag) - { - skin_error(ILLEGAL_TAG); - return 0; - } - - /* Copying basic tag info */ - if(element->type != CONDITIONAL && element->type != VIEWPORT) - element->type = TAG; - element->tag = tag; - tag_args = tag->params; - element->line = skin_line; - - /* Checking for the * flag */ - if(tag_args[0] == '*') - { - star = 1; - tag_args++; - } - - /* If this tag has no arguments, we can bail out now */ - if(strlen(tag_args) == 0 - || (tag_args[0] == '|' && *cursor != ARGLISTOPENSYM) - || (star && *cursor != ARGLISTOPENSYM)) - { - *document = cursor; - return 1; - } - - /* Checking the number of arguments and allocating args */ - if(*cursor != ARGLISTOPENSYM && tag_args[0] != '|') - { - skin_error(ARGLIST_EXPECTED); - return 0; - } - else - { - cursor++; - } - - bookmark = cursor; - while(*cursor != '\n' && *cursor != '\0' && *cursor != ARGLISTCLOSESYM) - { - /* Skipping over escaped characters */ - if(*cursor == TAGSYM) - { - cursor++; - if(*cursor == '\0') - break; - cursor++; - } - else if(*cursor == COMMENTSYM) - { - skip_comment(&cursor); - } - else if(*cursor == ARGLISTOPENSYM) - { - skip_arglist(&cursor); - } - else if(*cursor == ARGLISTSEPERATESYM) - { - num_args++; - cursor++; - } - else - { - cursor++; - } - } - - cursor = bookmark; /* Restoring the cursor */ - element->params_count = num_args; - element->params = skin_alloc_params(num_args); - - /* Now we have to actually parse each argument */ - for(i = 0; i < num_args; i++) - { - /* Making sure we haven't run out of arguments */ - if(*tag_args == '\0') - { - skin_error(TOO_MANY_ARGS); - return 0; - } - - /* Checking for the optional bar */ - if(*tag_args == '|') - { - optional = 1; - req_args = i; - tag_args++; - } - - /* Scanning the arguments */ - skip_whitespace(&cursor); - - - /* Checking for comments */ - if(*cursor == COMMENTSYM) - skip_comment(&cursor); - - /* Storing the type code */ - element->params[i].type_code = *tag_args; - - /* Checking a nullable argument for null */ - if(*cursor == DEFAULTSYM && !isdigit(cursor[1])) - { - if(islower(*tag_args)) - { - element->params[i].type = DEFAULT; - cursor++; - } - else - { - skin_error(DEFAULT_NOT_ALLOWED); - return 0; - } - } - else if(tolower(*tag_args) == 'i') - { - /* Scanning an int argument */ - if(!isdigit(*cursor) && *cursor != '-') - { - skin_error(INT_EXPECTED); - return 0; - } - - element->params[i].type = NUMERIC; - element->params[i].data.numeric = scan_int(&cursor); - } - else if(tolower(*tag_args) == 'n' || - tolower(*tag_args) == 's' || tolower(*tag_args) == 'f') - { - /* Scanning a string argument */ - element->params[i].type = STRING; - element->params[i].data.text = scan_string(&cursor); - - } - else if(tolower(*tag_args) == 'c') - { - /* Recursively parsing a code argument */ - element->params[i].type = CODE; - element->params[i].data.code = skin_parse_code_as_arg(&cursor); - if(!element->params[i].data.code) - return 0; - } - - skip_whitespace(&cursor); - - if(*cursor != ARGLISTSEPERATESYM && i < num_args - 1) - { - skin_error(SEPERATOR_EXPECTED); - return 0; - } - else if(*cursor != ARGLISTCLOSESYM && i == num_args - 1) - { - skin_error(CLOSE_EXPECTED); - return 0; - } - else - { - cursor++; - } - - if (*tag_args != 'N') - tag_args++; - - /* Checking for the optional bar */ - if(*tag_args == '|') - { - optional = 1; - req_args = i + 1; - tag_args++; - } - - } - - /* Checking for a premature end */ - if(*tag_args != '\0' && !optional) - { - skin_error(INSUFFICIENT_ARGS); - return 0; - } - - *document = cursor; - - return 1; -} - -/* - * If the conditional flag is set true, then parsing text will stop at an - * ARGLISTSEPERATESYM. Only set that flag when parsing within a conditional - */ -static int skin_parse_text(struct skin_element* element, char** document, - int conditional) -{ - char* cursor = *document; - int length = 0; - int dest; - char *text = NULL; - - /* First figure out how much text we're copying */ - while(*cursor != '\0' && *cursor != '\n' && *cursor != MULTILINESYM - && *cursor != COMMENTSYM - && !((*cursor == ARGLISTSEPERATESYM - || *cursor == ARGLISTCLOSESYM - || *cursor == ENUMLISTSEPERATESYM - || *cursor == ENUMLISTCLOSESYM) - && conditional)) - { - /* Dealing with possibility of escaped characters */ - if(*cursor == TAGSYM) - { - if(find_escape_character(cursor[1])) - cursor++; - else - break; - } - - length++; - cursor++; - } - - cursor = *document; - - /* Copying the text into the element struct */ - element->type = TEXT; - element->line = skin_line; - element->next = NULL; - element->data = text = skin_alloc_string(length); - - for(dest = 0; dest < length; dest++) - { - /* Advancing cursor if we've encountered an escaped character */ - if(*cursor == TAGSYM) - cursor++; - - text[dest] = *cursor; - cursor++; - } - text[length] = '\0'; - - *document = cursor; - - return 1; -} - -static int skin_parse_conditional(struct skin_element* element, char** document) -{ - - char* cursor = *document + 1; /* Starting past the "%" */ - char* bookmark; - int children = 1; - int i; - - element->type = CONDITIONAL; - element->line = skin_line; - - /* Parsing the tag first */ - if(!skin_parse_tag(element, &cursor)) - return 0; - - /* Counting the children */ - if(*(cursor++) != ENUMLISTOPENSYM) - { - skin_error(ARGLIST_EXPECTED); - return 0; - } - bookmark = cursor; - while(*cursor != ENUMLISTCLOSESYM && *cursor != '\n' && *cursor != '\0') - { - if(*cursor == COMMENTSYM) - { - skip_comment(&cursor); - } - else if(*cursor == ENUMLISTOPENSYM) - { - skip_enumlist(&cursor); - } - else if(*cursor == TAGSYM) - { - cursor++; - if(*cursor == '\0' || *cursor == '\n') - break; - cursor++; - } - else if(*cursor == ENUMLISTSEPERATESYM) - { - children++; - cursor++; - } - else - { - cursor++; - } - } - cursor = bookmark; - - /* Parsing the children */ - element->children = skin_alloc_children(children); - element->children_count = children; - - for(i = 0; i < children; i++) - { - element->children[i] = skin_parse_code_as_arg(&cursor); - skip_whitespace(&cursor); - - if(i < children - 1 && *cursor != ENUMLISTSEPERATESYM) - { - skin_error(SEPERATOR_EXPECTED); - return 0; - } - else if(i == children - 1 && *cursor != ENUMLISTCLOSESYM) - { - skin_error(CLOSE_EXPECTED); - return 0; - } - else - { - cursor++; - } - } - - *document = cursor; - - return 1; -} - -static int skin_parse_comment(struct skin_element* element, char** document) -{ - char* cursor = *document; - char* text = NULL; - - int length; - /* - * Finding the index of the ending newline or null-terminator - * The length of the string of interest doesn't include the leading #, the - * length we need to reserve is the same as the index of the last character - */ - for(length = 0; cursor[length] != '\n' && cursor[length] != '\0'; length++); - - element->type = COMMENT; - element->line = skin_line; -#ifdef ROCKBOX - element->data = NULL; -#else - element->data = text = skin_alloc_string(length); - /* We copy from one char past cursor to leave out the # */ - memcpy((void*)text, (void*)(cursor + 1), - sizeof(char) * (length-1)); - text[length - 1] = '\0'; -#endif - if(cursor[length] == '\n') - skin_line++; - - *document += (length); /* Move cursor up past # and all text */ - if(**document == '\n') - (*document)++; - - return 1; -} - -static struct skin_element* skin_parse_code_as_arg(char** document) -{ - - int sublines = 0; - char* cursor = *document; - - /* Checking for sublines */ - while(*cursor != '\n' && *cursor != '\0' - && *cursor != ENUMLISTSEPERATESYM && *cursor != ARGLISTSEPERATESYM - && *cursor != ENUMLISTCLOSESYM && *cursor != ARGLISTCLOSESYM) - { - if(*cursor == MULTILINESYM) - { - sublines = 1; - break; - } - 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); - } - else - { - /* Advancing the cursor as normal */ - cursor++; - } - } - - if(sublines) - return skin_parse_sublines_optional(document, 1); - else - return skin_parse_line_optional(document, 1); -} - - -/* Memory management */ -char* skin_alloc(size_t size) -{ -#ifdef ROCKBOX - char *retval = skin_buffer; - skin_buffer = (void *)(((unsigned long)skin_buffer + 3) & ~3); - return retval; -#else - return malloc(size); -#endif -} - -struct skin_element* skin_alloc_element() -{ - struct skin_element* retval = (struct skin_element*) - skin_alloc(sizeof(struct skin_element)); - retval->type = UNKNOWN; - retval->next = NULL; - retval->tag = NULL; - retval->params_count = 0; - retval->children_count = 0; - - return retval; - -} - -struct skin_tag_parameter* skin_alloc_params(int count) -{ - size_t size = sizeof(struct skin_tag_parameter) * count; - return (struct skin_tag_parameter*)skin_alloc(size); - -} - -char* skin_alloc_string(int length) -{ - return (char*)skin_alloc(sizeof(char) * (length + 1)); -} - -struct skin_element** skin_alloc_children(int count) -{ - return (struct skin_element**) - skin_alloc(sizeof(struct skin_element*) * count); -} - -void skin_free_tree(struct skin_element* root) -{ -#ifndef ROCKBOX - int i; - - /* First make the recursive call */ - if(!root) - return; - skin_free_tree(root->next); - - /* Free any text */ - if(root->type == TEXT || root->type == COMMENT) - free(root->data); - - /* Then recursively free any children, before freeing their pointers */ - for(i = 0; i < root->children_count; i++) - skin_free_tree(root->children[i]); - if(root->children_count > 0) - free(root->children); - - /* Free any parameters, making sure to deallocate strings */ - for(i = 0; i < root->params_count; i++) - if(root->params[i].type == STRING) - free(root->params[i].data.text); - if(root->params_count > 0) - free(root->params); - - /* Finally, delete root's memory */ - free(root); -#else - (void)root; -#endif -} |