/*************************************************************************** * __________ __ ___. * 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 #include #include #include "skin_parser.h" #include "skin_debug.h" #include "tag_table.h" /* Global variables for debug output */ int debug_indent_level = 0; extern int skin_line; extern char* skin_start; extern char* skin_buffer; /* Global error variables */ static int error_line; static int error_col; static const char *error_line_start; static char* error_message; static inline struct skin_element* get_child(OFFSETTYPE(struct skin_element**) children, int child) { struct skin_element **kids = SKINOFFSETTOPTR(skin_buffer, children); return kids[child]; } /* Debugging functions */ void skin_error(enum skin_errorcode error, const char* cursor) { error_col = 0; while(cursor > skin_start && *cursor != '\n') { cursor--; error_col++; } error_line_start = cursor+1; error_line = skin_line; switch(error) { case MEMORY_LIMIT_EXCEEDED: error_line_start = NULL; printf("Error: Memory limit exceeded at Line %d\n", skin_line); error_message = "Memory limit exceeded"; break; case NEWLINE_EXPECTED: error_message = "Newline expected"; break; case ILLEGAL_TAG: error_message = "Illegal tag"; break; case ARGLIST_EXPECTED: error_message = "Argument list expected"; break; case TOO_MANY_ARGS: error_message = "Too many arguments given"; break; case DEFAULT_NOT_ALLOWED: error_message = "Argument can not be set to default"; break; case UNEXPECTED_NEWLINE: error_message = "Unexpected newline"; break; case INSUFFICIENT_ARGS: error_message = "Not enough arguments"; break; case INT_EXPECTED: error_message = "Expected integer"; break; case DECIMAL_EXPECTED: error_message = "Expected decimal"; break; case SEPARATOR_EXPECTED: error_message = "Expected argument separator"; break; case CLOSE_EXPECTED: error_message = "Expected list close"; break; case MULTILINE_EXPECTED: error_message = "Expected subline separator"; break; case GOT_CALLBACK_ERROR: error_message = "Parser callback returned error"; break; }; } int skin_error_line() { return error_line; } int skin_error_col() { return error_col; } char* skin_error_message() { return error_message; } void skin_clear_errors() { error_line = 0; error_col = 0; error_message = NULL; } #if !defined(ROCKBOX) || defined(__PCTOOL__) void skin_debug_tree(struct skin_element* root) { int i; char *text; struct skin_element* current = root; while(current) { skin_debug_indent(); switch(current->type) { case UNKNOWN: printf("* Unknown element.. error *\n"); break; case VIEWPORT: printf("{ Viewport \n"); debug_indent_level++; skin_debug_tree(get_child(current->children, 0)); debug_indent_level--; printf("}"); break; case TEXT: text = SKINOFFSETTOPTR(skin_buffer, current->data); printf("* Plain text on line %d: \"%s\"\n", current->line, text); break; case COMMENT: printf("# Comment on line %d\n ", current->line); break; case TAG: if (current->params_count) { printf("( %%%s tag on line %d with %d arguments\n", current->tag->name, current->line, current->params_count); debug_indent_level++; skin_debug_params(current->params_count, SKINOFFSETTOPTR(skin_buffer, current->params)); debug_indent_level--; skin_debug_indent(); printf(")\n"); } else { printf("[ %%%s tag on line %d ]\n", current->tag->name, current->line); } break; case LINE_ALTERNATOR: 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_tree(get_child(current->children, i)); } debug_indent_level--; skin_debug_indent(); printf("]\n"); break; case CONDITIONAL: printf("< Conditional tag %%?%s on line %d with %d enumerations \n", current->tag->name, current->line, current->children_count); debug_indent_level++; for(i = 0; i < current->children_count; i++) { skin_debug_indent(); printf("[ Enumeration %d\n", i); debug_indent_level++; skin_debug_tree(get_child(current->children, i)); debug_indent_level--; skin_debug_indent(); printf("]\n"); } debug_indent_level--; skin_debug_indent(); printf(">\n"); break; case LINE: printf("[ Logical line on line %d\n", current->line); debug_indent_level++; if (current->children) skin_debug_tree(get_child(current->children, 0)); debug_indent_level--; skin_debug_indent(); printf("]\n"); break; } current = SKINOFFSETTOPTR(skin_buffer, 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("string: \"%s\"", SKINOFFSETTOPTR(skin_buffer, params[i].data.text)); break; case INTEGER: printf("integer: %d", params[i].data.number); break; case DECIMAL: printf("decimal: %d.%d", params[i].data.number/10, params[i].data.number%10); break; case CODE: printf("Skin Code: \n"); debug_indent_level++; skin_debug_tree(SKINOFFSETTOPTR(skin_buffer, params[i].data.code)); debug_indent_level--; skin_debug_indent(); break; } printf("\n"); } } void skin_debug_indent(void) { int i; for(i = 0; i < debug_indent_level; i++) printf(" "); } #endif #define MIN(a,b) ((a...<10 chars>" */ strncpy(text, error_line_start, 6); i = 5; text[i++] = '.'; text[i++] = '.'; text[i++] = '.'; for (j=error_col-10; error_line_start[j] && error_line_start[j] != '\n'; j++) text[i++] = error_line_start[j]; text[i] = '\0'; error_col = 18; } printf("%s\n", text); for (i=0; i