forked from len0rd/rockbox
Adding the new WPS parser, code works but need to build the tag table
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26281 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
fd9d7d0ac1
commit
d5b24ddcc5
11 changed files with 1579 additions and 0 deletions
17
utils/themeeditor/main.c
Normal file
17
utils/themeeditor/main.c
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#include "skin_parser.h"
|
||||||
|
#include "skin_debug.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
char* doc = "This is a sample %V(1, 2, 3, 4, 5, six, seven)\n"
|
||||||
|
"WPS document, with ; sublines and a %?T(conditional| or| two)";
|
||||||
|
|
||||||
|
struct skin_element* test = skin_parse(doc);
|
||||||
|
|
||||||
|
skin_debug_tree(test);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
226
utils/themeeditor/skin_debug.c
Normal file
226
utils/themeeditor/skin_debug.c
Normal file
|
|
@ -0,0 +1,226 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* 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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "skin_parser.h"
|
||||||
|
#include "skin_debug.h"
|
||||||
|
|
||||||
|
/* Global variables for debug output */
|
||||||
|
int debug_indent_level = 0;
|
||||||
|
extern int skin_line;
|
||||||
|
|
||||||
|
/* Debugging functions */
|
||||||
|
void skin_error(enum skin_errorcode error)
|
||||||
|
{
|
||||||
|
|
||||||
|
fprintf(stderr, "Error on line %d: ", skin_line);
|
||||||
|
|
||||||
|
switch(error)
|
||||||
|
{
|
||||||
|
case MEMORY_LIMIT_EXCEEDED:
|
||||||
|
fprintf(stderr, "Memory limit exceeded\n");
|
||||||
|
break;
|
||||||
|
case NEWLINE_EXPECTED:
|
||||||
|
fprintf(stderr, "Newline expected\n");
|
||||||
|
break;
|
||||||
|
case ILLEGAL_TAG:
|
||||||
|
fprintf(stderr, "Illegal tag\n");
|
||||||
|
break;
|
||||||
|
case ARGLIST_EXPECTED:
|
||||||
|
fprintf(stderr, "Argument list expected\n");
|
||||||
|
break;
|
||||||
|
case TOO_MANY_ARGS:
|
||||||
|
fprintf(stderr, "Too many arguments given\n");
|
||||||
|
break;
|
||||||
|
case DEFAULT_NOT_ALLOWED:
|
||||||
|
fprintf(stderr, "Argument can not be set to default\n");
|
||||||
|
break;
|
||||||
|
case UNEXPECTED_NEWLINE:
|
||||||
|
fprintf(stderr, "Unexpected newline\n");
|
||||||
|
break;
|
||||||
|
case INSUFFICIENT_ARGS:
|
||||||
|
fprintf(stderr, "Not enough arguments\n");
|
||||||
|
break;
|
||||||
|
case INT_EXPECTED:
|
||||||
|
fprintf(stderr, "Expected integer\n");
|
||||||
|
break;
|
||||||
|
case SEPERATOR_EXPECTED:
|
||||||
|
fprintf(stderr, "Expected argument seperator\n");
|
||||||
|
break;
|
||||||
|
case CLOSE_EXPECTED:
|
||||||
|
fprintf(stderr, "Expected list close\n");
|
||||||
|
break;
|
||||||
|
case MULTILINE_EXPECTED:
|
||||||
|
fprintf(stderr, "Expected subline seperator\n");
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void skin_debug_tree(struct skin_element* root)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
struct skin_element* current = root;
|
||||||
|
|
||||||
|
while(current)
|
||||||
|
{
|
||||||
|
skin_debug_indent();
|
||||||
|
|
||||||
|
switch(current->type)
|
||||||
|
{
|
||||||
|
|
||||||
|
case TEXT:
|
||||||
|
printf("[ Plain text on line %d : %s ]\n", current->line,
|
||||||
|
current->text);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NEWLINE:
|
||||||
|
printf("[ Newline on line %d ]\n", current->line);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case COMMENT:
|
||||||
|
printf("[ Comment on line %d: ", current->line);
|
||||||
|
for(i = 0; i < (int)strlen(current->text); i++)
|
||||||
|
{
|
||||||
|
if(current->text[i] == '\n')
|
||||||
|
printf("\\n");
|
||||||
|
else
|
||||||
|
printf("%c", current->text[i]);
|
||||||
|
}
|
||||||
|
printf(" ]\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TAG:
|
||||||
|
printf("[ %s tag on line %d with %d arguments\n", current->name,
|
||||||
|
current->line, current->params_count);
|
||||||
|
debug_indent_level++;
|
||||||
|
skin_debug_params(current->params_count, current->params);
|
||||||
|
debug_indent_level--;
|
||||||
|
skin_debug_indent();
|
||||||
|
printf("]\n");
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SUBLINES:
|
||||||
|
printf("[ Alternator on line %d with %d sublines \n", current->line,
|
||||||
|
current->children_count);
|
||||||
|
debug_indent_level++;
|
||||||
|
for(i = 0; i < current->children_count; i++)
|
||||||
|
{
|
||||||
|
skin_debug_indent();
|
||||||
|
printf("[ Subline %d\n", i);
|
||||||
|
|
||||||
|
debug_indent_level++;
|
||||||
|
skin_debug_tree(current->children[i]);
|
||||||
|
debug_indent_level--;
|
||||||
|
|
||||||
|
skin_debug_indent();
|
||||||
|
printf("]\n");
|
||||||
|
}
|
||||||
|
debug_indent_level--;
|
||||||
|
skin_debug_indent();
|
||||||
|
printf("]\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CONDITIONAL:
|
||||||
|
printf("[ Conditional tag on line %d with %d enumerations \n",
|
||||||
|
current->line, current->children_count - 1);
|
||||||
|
debug_indent_level++;
|
||||||
|
|
||||||
|
skin_debug_indent();
|
||||||
|
printf("[ Condition tag \n");
|
||||||
|
debug_indent_level++;
|
||||||
|
skin_debug_tree(current->children[0]);
|
||||||
|
debug_indent_level--;
|
||||||
|
skin_debug_indent();
|
||||||
|
printf("]\n");
|
||||||
|
|
||||||
|
for(i = 1; i < current->children_count; i++)
|
||||||
|
{
|
||||||
|
skin_debug_indent();
|
||||||
|
printf("[ Enumeration %d\n", i - 1);
|
||||||
|
debug_indent_level++;
|
||||||
|
skin_debug_tree(current->children[i]);
|
||||||
|
debug_indent_level--;
|
||||||
|
skin_debug_indent();
|
||||||
|
printf("]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_indent_level--;
|
||||||
|
skin_debug_indent();
|
||||||
|
printf("]\n");
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void skin_debug_params(int count, struct skin_tag_parameter params[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
skin_debug_indent();
|
||||||
|
switch(params[i].type)
|
||||||
|
{
|
||||||
|
case DEFAULT:
|
||||||
|
printf("[-]");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STRING:
|
||||||
|
printf("[%s]", params[i].data.text);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NUMERIC:
|
||||||
|
printf("[%d]", params[i].data.numeric);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CODE:
|
||||||
|
printf("[ WPS Code: \n");
|
||||||
|
debug_indent_level++;
|
||||||
|
skin_debug_tree(params[i].data.code);
|
||||||
|
debug_indent_level--;
|
||||||
|
skin_debug_indent();
|
||||||
|
printf("]");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void skin_debug_indent()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < debug_indent_level; i++)
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
37
utils/themeeditor/skin_debug.h
Normal file
37
utils/themeeditor/skin_debug.h
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SKIN_DEBUG_H
|
||||||
|
#define SKIN_DEBUG_H
|
||||||
|
|
||||||
|
#include "skin_parser.h"
|
||||||
|
|
||||||
|
/* Debugging functions */
|
||||||
|
void skin_error(enum skin_errorcode error);
|
||||||
|
void skin_debug_tree(struct skin_element* root);
|
||||||
|
|
||||||
|
/* Auxiliary debug functions */
|
||||||
|
void skin_debug_params(int count, struct skin_tag_parameter params[]);
|
||||||
|
void skin_debug_indent();
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SKIN_DEBUG_H
|
||||||
811
utils/themeeditor/skin_parser.c
Normal file
811
utils/themeeditor/skin_parser.c
Normal file
|
|
@ -0,0 +1,811 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
/* Declaration of parse tree buffer */
|
||||||
|
char skin_parse_tree[SKIN_MAX_MEMORY];
|
||||||
|
int skin_current_block = 0;
|
||||||
|
|
||||||
|
/* Global variables for the parser */
|
||||||
|
int skin_line = 0;
|
||||||
|
|
||||||
|
/* Auxiliary parsing functions (not visible at global scope) */
|
||||||
|
struct skin_element* skin_parse_line(char** document);
|
||||||
|
struct skin_element* skin_parse_line_optional(char** document, int conditional);
|
||||||
|
struct skin_element* skin_parse_sublines(char** document);
|
||||||
|
struct skin_element* skin_parse_sublines_optional(char** document,
|
||||||
|
int conditional);
|
||||||
|
|
||||||
|
int skin_parse_tag(struct skin_element* element, char** document);
|
||||||
|
int skin_parse_text(struct skin_element* element, char** document,
|
||||||
|
int conditional);
|
||||||
|
int skin_parse_conditional(struct skin_element* element, char** document);
|
||||||
|
int skin_parse_newline(struct skin_element* element, char** document);
|
||||||
|
int skin_parse_comment(struct skin_element* element, char** document);
|
||||||
|
struct skin_element* skin_parse_code_as_arg(char** document);
|
||||||
|
|
||||||
|
struct skin_element* skin_parse(char* document)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct skin_element* root = NULL;
|
||||||
|
struct skin_element* last = NULL;
|
||||||
|
|
||||||
|
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 */
|
||||||
|
|
||||||
|
skin_line = 1;
|
||||||
|
|
||||||
|
while(*cursor != '\0')
|
||||||
|
{
|
||||||
|
|
||||||
|
/* First, we check to see if this line will contain sublines */
|
||||||
|
bookmark = cursor;
|
||||||
|
sublines = 0;
|
||||||
|
while(*cursor != '\n' && *cursor != '\0')
|
||||||
|
{
|
||||||
|
if(*cursor == MULTILINESYM)
|
||||||
|
{
|
||||||
|
sublines = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(*cursor == TAGSYM)
|
||||||
|
{
|
||||||
|
/* A ';' directly after a '%' doesn't count */
|
||||||
|
cursor ++;
|
||||||
|
|
||||||
|
if(*cursor == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return root;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Auxiliary Parsing Functions */
|
||||||
|
|
||||||
|
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()
|
||||||
|
*/
|
||||||
|
struct skin_element* skin_parse_line_optional(char** document, int conditional)
|
||||||
|
{
|
||||||
|
char* cursor = *document;
|
||||||
|
|
||||||
|
struct skin_element* root = NULL;
|
||||||
|
struct skin_element* current = NULL;
|
||||||
|
|
||||||
|
while(*cursor != '\n' && *cursor != '\0' && *cursor != MULTILINESYM
|
||||||
|
&& !((*cursor == ARGLISTSEPERATESYM || *cursor == ARGLISTCLOSESYM
|
||||||
|
|| *cursor == ENUMLISTSEPERATESYM) && conditional))
|
||||||
|
{
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*cursor == '\n')
|
||||||
|
{
|
||||||
|
/* Allocating memory if necessary */
|
||||||
|
if(root)
|
||||||
|
{
|
||||||
|
current->next = skin_alloc_element();
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current = skin_alloc_element();
|
||||||
|
root = current;
|
||||||
|
}
|
||||||
|
if(!skin_parse_newline(current, &cursor))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Moving up the calling function's pointer */
|
||||||
|
*document = cursor;
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct skin_element* skin_parse_sublines(char** document)
|
||||||
|
{
|
||||||
|
return skin_parse_sublines_optional(document, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* First we count the sublines */
|
||||||
|
while(*cursor != '\0' && *cursor != '\n'
|
||||||
|
&& !((*cursor == ARGLISTSEPERATESYM || *cursor == ARGLISTCLOSESYM
|
||||||
|
|| *cursor == ENUMLISTSEPERATESYM) && conditional))
|
||||||
|
{
|
||||||
|
if(*cursor == COMMENTSYM)
|
||||||
|
skip_comment(&cursor);
|
||||||
|
|
||||||
|
/* Accounting for escaped subline symbols */
|
||||||
|
if(*cursor == TAGSYM)
|
||||||
|
{
|
||||||
|
cursor++;
|
||||||
|
if(*cursor == '\0' || *cursor == '\n')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*cursor == MULTILINESYM)
|
||||||
|
{
|
||||||
|
sublines++;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
cursor++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*document = cursor;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int skin_parse_tag(struct skin_element* element, char** document)
|
||||||
|
{
|
||||||
|
|
||||||
|
char* cursor = *document + 1;
|
||||||
|
char* bookmark;
|
||||||
|
|
||||||
|
char tag_name[3];
|
||||||
|
char* tag_args;
|
||||||
|
|
||||||
|
int num_args = 1;
|
||||||
|
int i;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
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_args = find_tag(tag_name);
|
||||||
|
|
||||||
|
if(!tag_args)
|
||||||
|
{
|
||||||
|
tag_name[1] = '\0';
|
||||||
|
tag_args = find_tag(tag_name);
|
||||||
|
cursor++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cursor += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!tag_args)
|
||||||
|
{
|
||||||
|
skin_error(ILLEGAL_TAG);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copying basic tag info */
|
||||||
|
element->type = TAG;
|
||||||
|
element->name = skin_alloc_string(strlen(tag_name));
|
||||||
|
strcpy(element->name, tag_name);
|
||||||
|
element->line = skin_line;
|
||||||
|
|
||||||
|
/* If this tag has no arguments, we can bail out now */
|
||||||
|
if(strlen(tag_args) == 0)
|
||||||
|
{
|
||||||
|
*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++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(bookmark = cursor; *cursor != '\n' && *cursor != '\0' &&
|
||||||
|
*cursor != ARGLISTCLOSESYM; cursor++)
|
||||||
|
{
|
||||||
|
/* Skipping over escaped characters */
|
||||||
|
if(*cursor == TAGSYM)
|
||||||
|
{
|
||||||
|
cursor++;
|
||||||
|
if(*cursor == '\0')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skipping comments */
|
||||||
|
if(*cursor == COMMENTSYM)
|
||||||
|
skip_comment(&cursor);
|
||||||
|
|
||||||
|
/* Commas inside of contained lists don't count */
|
||||||
|
if(*cursor == ARGLISTOPENSYM)
|
||||||
|
while(*cursor != ARGLISTCLOSESYM && *cursor != '\0')
|
||||||
|
cursor++;
|
||||||
|
|
||||||
|
if(*cursor == ARGLISTSEPERATESYM)
|
||||||
|
num_args++;
|
||||||
|
|
||||||
|
}
|
||||||
|
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 */
|
||||||
|
i = 0;
|
||||||
|
while(i < num_args)
|
||||||
|
{
|
||||||
|
/* 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;
|
||||||
|
tag_args++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checking for a repeated argument */
|
||||||
|
if(isdigit(*tag_args))
|
||||||
|
{
|
||||||
|
count = scan_int(&tag_args);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scanning the arguments */
|
||||||
|
while(count > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
skip_whitespace(&cursor);
|
||||||
|
|
||||||
|
/* Checking for a premature end */
|
||||||
|
if(num_args - i < count)
|
||||||
|
{
|
||||||
|
if(optional && (num_args - i == 0))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
We error out if there are too few arguments, or if there
|
||||||
|
is an optional argument that was supposed to be grouped
|
||||||
|
with another
|
||||||
|
*/
|
||||||
|
skin_error(INSUFFICIENT_ARGS);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checking for comments */
|
||||||
|
if(*cursor == COMMENTSYM)
|
||||||
|
skip_comment(&cursor);
|
||||||
|
|
||||||
|
/* Checking a nullable argument for null */
|
||||||
|
if(*cursor == DEFAULTSYM)
|
||||||
|
{
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
skin_error(INT_EXPECTED);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
element->params[i].type = NUMERIC;
|
||||||
|
element->params[i].data.numeric = scan_int(&cursor);
|
||||||
|
}
|
||||||
|
else if(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')
|
||||||
|
{
|
||||||
|
element->params[i].type = CODE;
|
||||||
|
element->params[i].data.code = skin_parse_code_as_arg(&cursor);
|
||||||
|
if(!element->params[i].data.code)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
count--;
|
||||||
|
skip_whitespace(&cursor);
|
||||||
|
|
||||||
|
if(*cursor != ARGLISTSEPERATESYM && i < num_args)
|
||||||
|
{
|
||||||
|
skin_error(SEPERATOR_EXPECTED);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if(*cursor != ARGLISTCLOSESYM && i == num_args)
|
||||||
|
{
|
||||||
|
skin_error(CLOSE_EXPECTED);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cursor++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tag_args++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
*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
|
||||||
|
*/
|
||||||
|
int skin_parse_text(struct skin_element* element, char** document,
|
||||||
|
int conditional)
|
||||||
|
{
|
||||||
|
char* cursor = *document;
|
||||||
|
|
||||||
|
int length = 0;
|
||||||
|
|
||||||
|
int dest;
|
||||||
|
|
||||||
|
/* First figure out how much text we're copying */
|
||||||
|
while(*cursor != '\0' && *cursor != '\n' && *cursor != MULTILINESYM
|
||||||
|
&& *cursor != COMMENTSYM
|
||||||
|
&& !((*cursor == ARGLISTSEPERATESYM || *cursor == ARGLISTCLOSESYM
|
||||||
|
|| *cursor == ENUMLISTSEPERATESYM) && 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->text = skin_alloc_string(length);
|
||||||
|
|
||||||
|
for(dest = 0; dest < length; dest++)
|
||||||
|
{
|
||||||
|
/* Advancing cursor if we've encountered an escaped character */
|
||||||
|
if(*cursor == TAGSYM)
|
||||||
|
cursor++;
|
||||||
|
|
||||||
|
element->text[dest] = *cursor;
|
||||||
|
cursor++;
|
||||||
|
}
|
||||||
|
element->text[length] = '\0';
|
||||||
|
|
||||||
|
*document = cursor;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int skin_parse_conditional(struct skin_element* element, char** document)
|
||||||
|
{
|
||||||
|
|
||||||
|
char* cursor = *document + 1; /* Starting past the "%" */
|
||||||
|
char* bookmark;
|
||||||
|
struct skin_element* tag = skin_alloc_element(); /* The tag to evaluate */
|
||||||
|
int children = 1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
element->type = CONDITIONAL;
|
||||||
|
element->line = skin_line;
|
||||||
|
|
||||||
|
/* Parsing the tag first */
|
||||||
|
if(!skin_parse_tag(tag, &cursor))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Counting the children */
|
||||||
|
if(*(cursor++) != ARGLISTOPENSYM)
|
||||||
|
{
|
||||||
|
skin_error(ARGLIST_EXPECTED);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
bookmark = cursor;
|
||||||
|
while(*cursor != ARGLISTCLOSESYM && *cursor != '\n' && *cursor != '\0')
|
||||||
|
{
|
||||||
|
if(*cursor == COMMENTSYM)
|
||||||
|
{
|
||||||
|
skip_comment(&cursor);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*cursor == TAGSYM)
|
||||||
|
{
|
||||||
|
cursor++;
|
||||||
|
if(*cursor == '\0' || *cursor == '\n')
|
||||||
|
break;
|
||||||
|
cursor++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*cursor == ENUMLISTSEPERATESYM)
|
||||||
|
children++;
|
||||||
|
|
||||||
|
cursor++;
|
||||||
|
}
|
||||||
|
cursor = bookmark;
|
||||||
|
|
||||||
|
/* Parsing the children */
|
||||||
|
element->children_count = children + 1; /* Make sure to include the tag */
|
||||||
|
element->children = skin_alloc_children(children + 1);
|
||||||
|
element->children[0] = tag;
|
||||||
|
|
||||||
|
for(i = 1; i < children + 1; i++)
|
||||||
|
{
|
||||||
|
element->children[i] = skin_parse_code_as_arg(&cursor);
|
||||||
|
skip_whitespace(&cursor);
|
||||||
|
|
||||||
|
if(i < children && *cursor != ENUMLISTSEPERATESYM)
|
||||||
|
{
|
||||||
|
skin_error(SEPERATOR_EXPECTED);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if(i == children && *cursor != ARGLISTCLOSESYM)
|
||||||
|
{
|
||||||
|
skin_error(CLOSE_EXPECTED);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cursor++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*document = cursor;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int skin_parse_newline(struct skin_element* element, char** document)
|
||||||
|
{
|
||||||
|
|
||||||
|
char* cursor = *document;
|
||||||
|
if(*cursor != '\n')
|
||||||
|
{
|
||||||
|
skin_error(NEWLINE_EXPECTED);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cursor++;
|
||||||
|
|
||||||
|
/* Assembling a skin_element struct for a newline */
|
||||||
|
element->type = NEWLINE;
|
||||||
|
element->line = skin_line;
|
||||||
|
skin_line++;
|
||||||
|
element->text = skin_alloc_string(1);
|
||||||
|
element->text[0] = '\n';
|
||||||
|
element->text[1] = '\0';
|
||||||
|
element->next = NULL;
|
||||||
|
|
||||||
|
*document = cursor;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int skin_parse_comment(struct skin_element* element, char** document)
|
||||||
|
{
|
||||||
|
char* cursor = *document;
|
||||||
|
|
||||||
|
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;
|
||||||
|
element->text = skin_alloc_string(length);
|
||||||
|
/* We copy from one char past cursor to leave out the # */
|
||||||
|
memcpy((void*)(element->text), (void*)(cursor + 1), sizeof(char) * length);
|
||||||
|
element->text[length] = '\0';
|
||||||
|
|
||||||
|
if(cursor[length] == '\n')
|
||||||
|
skin_line++;
|
||||||
|
|
||||||
|
*document += (length + 1); /* Move cursor up past # and all text */
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct skin_element* skin_parse_code_as_arg(char** document)
|
||||||
|
{
|
||||||
|
|
||||||
|
int sublines = 0;
|
||||||
|
char* cursor = *document;
|
||||||
|
|
||||||
|
/* Checking for sublines */
|
||||||
|
while(*cursor != '\n' && *cursor != '\0')
|
||||||
|
{
|
||||||
|
if(*cursor == MULTILINESYM)
|
||||||
|
{
|
||||||
|
sublines = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(*cursor == TAGSYM)
|
||||||
|
{
|
||||||
|
/* A ';' directly after a '%' doesn't count */
|
||||||
|
cursor ++;
|
||||||
|
|
||||||
|
if(*cursor == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
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 */
|
||||||
|
struct skin_element* skin_alloc_element()
|
||||||
|
{
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
char* retval = &skin_parse_tree[skin_current_block * 4];
|
||||||
|
|
||||||
|
int delta = sizeof(struct skin_element) / (sizeof(char) * 4);
|
||||||
|
|
||||||
|
/* If one block is partially filled, make sure to advance to the
|
||||||
|
* next one for the next allocation
|
||||||
|
*/
|
||||||
|
if(sizeof(struct skin_element) % (sizeof(char) * 4) != 0)
|
||||||
|
delta++;
|
||||||
|
|
||||||
|
skin_current_block += delta;
|
||||||
|
|
||||||
|
return (struct skin_element*)retval;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct skin_element* retval = (struct skin_element*)
|
||||||
|
malloc(sizeof(struct skin_element));
|
||||||
|
retval->next = NULL;
|
||||||
|
retval->params_count = 0;
|
||||||
|
retval->children_count = 0;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct skin_tag_parameter* skin_alloc_params(int count)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
char* retval = &skin_parse_tree[skin_current_block * 4];
|
||||||
|
|
||||||
|
int delta = sizeof(struct skin_tag_parameter) / (sizeof(char) * 4);
|
||||||
|
delta *= count;
|
||||||
|
|
||||||
|
/* Correcting uneven alignment */
|
||||||
|
if(count * sizeof(struct skin_tag_parameter) % (sizeof(char) * 4) != 0)
|
||||||
|
delta++;
|
||||||
|
|
||||||
|
skin_current_block += delta;
|
||||||
|
|
||||||
|
return (struct skin_tag_parameter*) retval;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (struct skin_tag_parameter*)malloc(sizeof(struct skin_tag_parameter)
|
||||||
|
* count);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
char* skin_alloc_string(int length)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
char* retval = &skin_parse_tree[skin_current_block * 4];
|
||||||
|
|
||||||
|
/* Checking alignment */
|
||||||
|
length++; /* Accounting for the null terminator */
|
||||||
|
int delta = length / 4;
|
||||||
|
if(length % 4 != 0)
|
||||||
|
delta++;
|
||||||
|
|
||||||
|
skin_current_block += delta;
|
||||||
|
|
||||||
|
if(skin_current_block >= SKIN_MAX_MEMORY / 4)
|
||||||
|
skin_error(MEMORY_LIMIT_EXCEEDED);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (char*)malloc(sizeof(char) * (length + 1));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct skin_element** skin_alloc_children(int count)
|
||||||
|
{
|
||||||
|
return (struct skin_element**) malloc(sizeof(struct skin_element*) * count);
|
||||||
|
}
|
||||||
124
utils/themeeditor/skin_parser.h
Normal file
124
utils/themeeditor/skin_parser.h
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef GENERIC_PARSER_H
|
||||||
|
#define GENERIC_PARSER_H
|
||||||
|
|
||||||
|
#define SKIN_MAX_MEMORY 1048576
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
****** A global buffer will be used to store the parse tree *******
|
||||||
|
*******************************************************************/
|
||||||
|
extern char skin_parse_tree[];
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
****** Data Structures *********************************************
|
||||||
|
*******************************************************************/
|
||||||
|
|
||||||
|
/* Possible types of element in a WPS file */
|
||||||
|
enum skin_element_type
|
||||||
|
{
|
||||||
|
TEXT,
|
||||||
|
NEWLINE,
|
||||||
|
COMMENT,
|
||||||
|
TAG,
|
||||||
|
CONDITIONAL,
|
||||||
|
SUBLINES
|
||||||
|
};
|
||||||
|
|
||||||
|
enum skin_errorcode
|
||||||
|
{
|
||||||
|
MEMORY_LIMIT_EXCEEDED,
|
||||||
|
NEWLINE_EXPECTED,
|
||||||
|
ILLEGAL_TAG,
|
||||||
|
ARGLIST_EXPECTED,
|
||||||
|
TOO_MANY_ARGS,
|
||||||
|
DEFAULT_NOT_ALLOWED,
|
||||||
|
UNEXPECTED_NEWLINE,
|
||||||
|
INSUFFICIENT_ARGS,
|
||||||
|
INT_EXPECTED,
|
||||||
|
SEPERATOR_EXPECTED,
|
||||||
|
CLOSE_EXPECTED,
|
||||||
|
MULTILINE_EXPECTED
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Holds a tag parameter, either numeric or text */
|
||||||
|
struct skin_tag_parameter
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
NUMERIC,
|
||||||
|
STRING,
|
||||||
|
CODE,
|
||||||
|
DEFAULT
|
||||||
|
} type;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
int numeric;
|
||||||
|
char* text;
|
||||||
|
struct skin_element* code;
|
||||||
|
} data;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Defines an element of a SKIN file */
|
||||||
|
struct skin_element
|
||||||
|
{
|
||||||
|
/* Defines what type of element it is */
|
||||||
|
enum skin_element_type type;
|
||||||
|
|
||||||
|
/* The line on which it's defined in the source file */
|
||||||
|
int line;
|
||||||
|
|
||||||
|
/* Text for comments and plaintext */
|
||||||
|
char* text;
|
||||||
|
|
||||||
|
/* The tag or conditional name */
|
||||||
|
char* name;
|
||||||
|
|
||||||
|
/* Pointer to and size of an array of parameters */
|
||||||
|
int params_count;
|
||||||
|
struct skin_tag_parameter* params;
|
||||||
|
|
||||||
|
/* Pointer to and size of an array of children */
|
||||||
|
int children_count;
|
||||||
|
struct skin_element** children;
|
||||||
|
|
||||||
|
/* Link to the next element */
|
||||||
|
struct skin_element* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
***** Functions *******************************************************
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
/* Parses a WPS document and returns a list of skin_element
|
||||||
|
structures. */
|
||||||
|
struct skin_element* skin_parse(char* document);
|
||||||
|
|
||||||
|
/* Memory management functions */
|
||||||
|
struct skin_element* skin_alloc_element();
|
||||||
|
struct skin_element** skin_alloc_children(int count);
|
||||||
|
struct skin_tag_parameter* skin_alloc_params(int count);
|
||||||
|
char* skin_alloc_string(int length);
|
||||||
|
|
||||||
|
#endif /* GENERIC_PARSER_H */
|
||||||
137
utils/themeeditor/skin_scan.c
Normal file
137
utils/themeeditor/skin_scan.c
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* 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 <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "skin_scan.h"
|
||||||
|
#include "skin_debug.h"
|
||||||
|
#include "symbols.h"
|
||||||
|
#include "skin_parser.h"
|
||||||
|
|
||||||
|
/* Scanning Functions */
|
||||||
|
|
||||||
|
/* Simple function to advance a char* past a comment */
|
||||||
|
void skip_comment(char** document)
|
||||||
|
{
|
||||||
|
for(/*NO INIT*/;**document != '\n' && **document != '\0'; (*document)++);
|
||||||
|
if(**document == '\n')
|
||||||
|
(*document)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void skip_whitespace(char** document)
|
||||||
|
{
|
||||||
|
for(/*NO INIT*/; **document == ' ' || **document == '\t'; (*document)++);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* scan_string(char** document)
|
||||||
|
{
|
||||||
|
|
||||||
|
char* cursor = *document;
|
||||||
|
int length = 0;
|
||||||
|
char* buffer = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
while(*cursor != ARGLISTSEPERATESYM && *cursor != ARGLISTCLOSESYM &&
|
||||||
|
*cursor != '\0')
|
||||||
|
{
|
||||||
|
if(*cursor == COMMENTSYM)
|
||||||
|
{
|
||||||
|
skip_comment(&cursor);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*cursor == '\n')
|
||||||
|
{
|
||||||
|
skin_error(UNEXPECTED_NEWLINE);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
length++;
|
||||||
|
cursor++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copying the string */
|
||||||
|
cursor = *document;
|
||||||
|
buffer = skin_alloc_string(length);
|
||||||
|
for(i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
if(*cursor == COMMENTSYM)
|
||||||
|
{
|
||||||
|
skip_comment(&cursor);
|
||||||
|
i--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[i] = *cursor;
|
||||||
|
cursor++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*document = cursor;
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int scan_int(char** document)
|
||||||
|
{
|
||||||
|
|
||||||
|
char* cursor = *document;
|
||||||
|
int length = 0;
|
||||||
|
char* buffer = NULL;
|
||||||
|
int retval;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
while(isdigit(*cursor) || *cursor == COMMENTSYM)
|
||||||
|
{
|
||||||
|
if(*cursor == COMMENTSYM)
|
||||||
|
{
|
||||||
|
skip_comment(&cursor);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
length++;
|
||||||
|
cursor++;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = skin_alloc_string(length);
|
||||||
|
|
||||||
|
/* Copying to the buffer while avoiding comments */
|
||||||
|
cursor = *document;
|
||||||
|
buffer[length] = '\0';
|
||||||
|
for(i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
if(*cursor == COMMENTSYM)
|
||||||
|
{
|
||||||
|
skip_comment(&cursor);
|
||||||
|
i--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[i] = *cursor;
|
||||||
|
cursor++;
|
||||||
|
|
||||||
|
}
|
||||||
|
retval = atoi(buffer);
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
*document = cursor;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
32
utils/themeeditor/skin_scan.h
Normal file
32
utils/themeeditor/skin_scan.h
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef SCANNING_H
|
||||||
|
#define SCANNING_H
|
||||||
|
|
||||||
|
/* Scanning functions */
|
||||||
|
void skip_comment(char** document);
|
||||||
|
void skip_whitespace(char** document);
|
||||||
|
char* scan_string(char** document);
|
||||||
|
int scan_int(char** document);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SCANNING_H
|
||||||
37
utils/themeeditor/symbols.h
Normal file
37
utils/themeeditor/symbols.h
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef SYMBOLS_H
|
||||||
|
#define SYMBOLS_H
|
||||||
|
|
||||||
|
/* Symbol definitions for WPS parsing */
|
||||||
|
|
||||||
|
#define TAGSYM '%'
|
||||||
|
#define COMMENTSYM '#'
|
||||||
|
#define CONDITIONSYM '?'
|
||||||
|
#define MULTILINESYM ';'
|
||||||
|
#define ARGLISTOPENSYM '('
|
||||||
|
#define ARGLISTCLOSESYM ')'
|
||||||
|
#define ARGLISTSEPERATESYM ','
|
||||||
|
#define ENUMLISTSEPERATESYM '|'
|
||||||
|
#define DEFAULTSYM '-'
|
||||||
|
|
||||||
|
#endif /* SYMBOLS_H */
|
||||||
75
utils/themeeditor/tag_table.c
Normal file
75
utils/themeeditor/tag_table.c
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* 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 "tag_table.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* The tag definition table */
|
||||||
|
struct tag_info legal_tags[] =
|
||||||
|
{
|
||||||
|
{ "V" , "IIiii|2sc" },
|
||||||
|
{ "Vi" , "SIIiii|2s" },
|
||||||
|
{ "Vd" , "S" },
|
||||||
|
{ "T" , "" },
|
||||||
|
{ "" , ""} /* Keep this here to mark the end of the table */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* A table of legal escapable characters */
|
||||||
|
char legal_escape_characters[] = "%(|);#,";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Just does a straight search through the tag table to find one by
|
||||||
|
* the given name
|
||||||
|
*/
|
||||||
|
char* find_tag(char* name)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct tag_info* current = legal_tags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Continue searching so long as we have a non-empty name string
|
||||||
|
* and the name of the current element doesn't match the name
|
||||||
|
* we're searching for
|
||||||
|
*/
|
||||||
|
|
||||||
|
while(strcmp(current->name, name) && current->name[0] != '\0')
|
||||||
|
current++;
|
||||||
|
|
||||||
|
if(current->name[0] == '\0')
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
return current->params;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Searches through the legal escape characters string */
|
||||||
|
int find_escape_character(char lookup)
|
||||||
|
{
|
||||||
|
char* current = legal_escape_characters;
|
||||||
|
while(*current != lookup && *current != '\0')
|
||||||
|
current++;
|
||||||
|
|
||||||
|
if(*current == lookup)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
73
utils/themeeditor/tag_table.h
Normal file
73
utils/themeeditor/tag_table.h
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef TAG_TABLE_H
|
||||||
|
#define TAG_TABLE_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Struct for tag parsing information
|
||||||
|
* name - The name of the tag, i.e. V for %V
|
||||||
|
* params - A string specifying all of the tags parameters, each
|
||||||
|
* character representing a single parameter. Valid
|
||||||
|
* characters for parameters are:
|
||||||
|
* I - Required integer
|
||||||
|
* i - Nullable integer
|
||||||
|
* S - Required string
|
||||||
|
* s - Nullable string
|
||||||
|
* F - Required file name
|
||||||
|
* f - Nullable file name
|
||||||
|
* C - Required WPS code
|
||||||
|
* Any nullable parameter may be replaced in the WPS file
|
||||||
|
* with a '-'. To specify that parameters may be left off
|
||||||
|
* altogether, place a '|' in the parameter string. For
|
||||||
|
* instance, with the parameter string...
|
||||||
|
* Ii|Ss
|
||||||
|
* one integer must be specified, one integer can be
|
||||||
|
* specified or set to default with '-', and the user can
|
||||||
|
* stop providing parameters at any time after that.
|
||||||
|
* To specify multiple instances of the same type, put a
|
||||||
|
* number before the character. For instance, the string...
|
||||||
|
* 2s
|
||||||
|
* will specify two strings.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct tag_info
|
||||||
|
{
|
||||||
|
|
||||||
|
char* name;
|
||||||
|
char* params;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finds a tag by name and returns its parameter list, or an empty
|
||||||
|
* string if the tag is not found in the table
|
||||||
|
*/
|
||||||
|
char* find_tag(char* name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determines whether a character is legal to escape or not. If
|
||||||
|
* lookup is not found in the legal escape characters string, returns
|
||||||
|
* false, otherwise returns true
|
||||||
|
*/
|
||||||
|
int find_escape_character(char lookup);
|
||||||
|
|
||||||
|
#endif /* TAG_TABLE_H */
|
||||||
10
utils/themeeditor/themeeditor.pro
Normal file
10
utils/themeeditor/themeeditor.pro
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
HEADERS += tag_table.h \
|
||||||
|
symbols.h \
|
||||||
|
skin_parser.h \
|
||||||
|
skin_scan.h \
|
||||||
|
skin_debug.h
|
||||||
|
SOURCES += tag_table.c \
|
||||||
|
main.c \
|
||||||
|
skin_parser.c \
|
||||||
|
skin_scan.c \
|
||||||
|
skin_debug.c
|
||||||
Loading…
Add table
Add a link
Reference in a new issue