blob: 9537182341cdb400ec17c1f2f1f9c4c0419b9410 [file] [log] [blame]
Robert Bieberd5b24dd2010-05-25 15:19:52 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 Robert Bieber
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26#include "skin_parser.h"
27#include "skin_debug.h"
Robert Bieber0a054b22010-06-01 16:44:52 +000028#include "tag_table.h"
Robert Bieberd5b24dd2010-05-25 15:19:52 +000029
30/* Global variables for debug output */
31int debug_indent_level = 0;
32extern int skin_line;
Robert Bieber3c4fb8a2010-07-18 00:59:02 +000033extern char* skin_start;
Jonathan Gordon9e07ef22011-11-15 14:11:08 +000034extern char* skin_buffer;
Robert Bieberd5b24dd2010-05-25 15:19:52 +000035
Robert Bieber0e44ce92010-06-07 20:29:46 +000036/* Global error variables */
37int error_line;
Robert Bieber3c4fb8a2010-07-18 00:59:02 +000038int error_col;
Nils Wallménius8be79a22010-07-31 16:33:34 +000039const char *error_line_start;
Robert Bieber0e44ce92010-06-07 20:29:46 +000040char* error_message;
41
Jonathan Gordon9e07ef22011-11-15 14:11:08 +000042
43static inline struct skin_element*
44get_child(OFFSETTYPE(struct skin_element**) children, int child)
45{
46 struct skin_element **kids = SKINOFFSETTOPTR(skin_buffer, children);
47 return kids[child];
48}
49
Robert Bieberd5b24dd2010-05-25 15:19:52 +000050/* Debugging functions */
Nils Wallménius804437a2010-07-31 16:30:22 +000051void skin_error(enum skin_errorcode error, const char* cursor)
Robert Bieberd5b24dd2010-05-25 15:19:52 +000052{
53
Robert Bieber3c4fb8a2010-07-18 00:59:02 +000054 error_col = 0;
55
56 while(cursor > skin_start && *cursor != '\n')
57 {
58 cursor--;
59 error_col++;
60 }
Jonathan Gordon2d31d772010-07-29 12:37:48 +000061 error_line_start = cursor+1;
Robert Bieber3c4fb8a2010-07-18 00:59:02 +000062
Robert Bieber0e44ce92010-06-07 20:29:46 +000063 error_line = skin_line;
Robert Bieberd5b24dd2010-05-25 15:19:52 +000064
65 switch(error)
66 {
67 case MEMORY_LIMIT_EXCEEDED:
Jonathan Gordon21e89e82011-01-27 11:27:53 +000068 error_line_start = NULL;
69 printf("Error: Memory limit exceeded at Line %d\n", skin_line);
Robert Bieber0e44ce92010-06-07 20:29:46 +000070 error_message = "Memory limit exceeded";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000071 break;
72 case NEWLINE_EXPECTED:
Robert Bieber0e44ce92010-06-07 20:29:46 +000073 error_message = "Newline expected";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000074 break;
75 case ILLEGAL_TAG:
Robert Bieber0e44ce92010-06-07 20:29:46 +000076 error_message = "Illegal tag";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000077 break;
78 case ARGLIST_EXPECTED:
Robert Bieber0e44ce92010-06-07 20:29:46 +000079 error_message = "Argument list expected";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000080 break;
81 case TOO_MANY_ARGS:
Robert Bieber0e44ce92010-06-07 20:29:46 +000082 error_message = "Too many arguments given";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000083 break;
84 case DEFAULT_NOT_ALLOWED:
Robert Bieber0e44ce92010-06-07 20:29:46 +000085 error_message = "Argument can not be set to default";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000086 break;
87 case UNEXPECTED_NEWLINE:
Robert Bieber0e44ce92010-06-07 20:29:46 +000088 error_message = "Unexpected newline";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000089 break;
90 case INSUFFICIENT_ARGS:
Robert Bieber0e44ce92010-06-07 20:29:46 +000091 error_message = "Not enough arguments";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000092 break;
93 case INT_EXPECTED:
Robert Bieber0e44ce92010-06-07 20:29:46 +000094 error_message = "Expected integer";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000095 break;
Robert Bieber15488a02010-07-15 06:24:11 +000096 case DECIMAL_EXPECTED:
97 error_message = "Expected decimal";
98 break;
Bertrik Sikkenfffbdcc2010-11-05 09:51:19 +000099 case SEPARATOR_EXPECTED:
100 error_message = "Expected argument separator";
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000101 break;
102 case CLOSE_EXPECTED:
Robert Bieber0e44ce92010-06-07 20:29:46 +0000103 error_message = "Expected list close";
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000104 break;
105 case MULTILINE_EXPECTED:
Bertrik Sikkenfffbdcc2010-11-05 09:51:19 +0000106 error_message = "Expected subline separator";
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000107 break;
108 };
109
110}
111
Robert Bieber0e44ce92010-06-07 20:29:46 +0000112int skin_error_line()
113{
114 return error_line;
115}
116
Robert Bieber3c4fb8a2010-07-18 00:59:02 +0000117int skin_error_col()
118{
119 return error_col;
120}
121
Robert Bieber0e44ce92010-06-07 20:29:46 +0000122char* skin_error_message()
123{
124 return error_message;
125}
126
Robert Bieber594d7342010-06-07 21:09:13 +0000127void skin_clear_errors()
128{
129 error_line = 0;
Robert Bieber3c4fb8a2010-07-18 00:59:02 +0000130 error_col = 0;
Robert Bieber594d7342010-06-07 21:09:13 +0000131 error_message = NULL;
132}
133
Jonathan Gordon1e0a0102010-08-03 12:14:50 +0000134#if !defined(ROCKBOX) || defined(__PCTOOL__)
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000135void skin_debug_tree(struct skin_element* root)
136{
137 int i;
Robert Bieber64321ad2010-06-10 21:02:44 +0000138 char *text;
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000139
140 struct skin_element* current = root;
141
142 while(current)
143 {
144 skin_debug_indent();
145
146 switch(current->type)
147 {
Jonathan Gordon35b09cb2010-06-13 03:13:01 +0000148 case UNKNOWN:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000149 printf("* Unknown element.. error *\n");
Jonathan Gordon35b09cb2010-06-13 03:13:01 +0000150 break;
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000151
Robert Bieberd1659d62010-06-01 07:11:23 +0000152 case VIEWPORT:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000153 printf("{ Viewport \n");
Robert Bieberd1659d62010-06-01 07:11:23 +0000154
155 debug_indent_level++;
Jonathan Gordon9e07ef22011-11-15 14:11:08 +0000156 skin_debug_tree(get_child(current->children, 0));
Robert Bieberd1659d62010-06-01 07:11:23 +0000157 debug_indent_level--;
158
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000159 printf("}");
Robert Bieberd1659d62010-06-01 07:11:23 +0000160 break;
161
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000162 case TEXT:
Jonathan Gordon9e07ef22011-11-15 14:11:08 +0000163 text = SKINOFFSETTOPTR(skin_buffer, current->data);
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000164 printf("* Plain text on line %d: \"%s\"\n", current->line, text);
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000165 break;
166
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000167 case COMMENT:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000168 printf("# Comment on line %d\n ", current->line);
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000169 break;
170
171 case TAG:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000172 if (current->params_count)
173 {
174 printf("( %%%s tag on line %d with %d arguments\n",
175 current->tag->name,
176 current->line, current->params_count);
177 debug_indent_level++;
Jonathan Gordon9e07ef22011-11-15 14:11:08 +0000178 skin_debug_params(current->params_count, SKINOFFSETTOPTR(skin_buffer, current->params));
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000179 debug_indent_level--;
180 skin_debug_indent();
181 printf(")\n");
182 }
183 else
184 {
185 printf("[ %%%s tag on line %d ]\n",
186 current->tag->name, current->line);
187 }
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000188
189 break;
190
Jonathan Gordondc347852010-07-04 02:04:14 +0000191 case LINE_ALTERNATOR:
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000192 printf("[ Alternator on line %d with %d sublines \n", current->line,
193 current->children_count);
194 debug_indent_level++;
195 for(i = 0; i < current->children_count; i++)
196 {
Jonathan Gordon9e07ef22011-11-15 14:11:08 +0000197 skin_debug_tree(get_child(current->children, i));
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000198 }
199 debug_indent_level--;
Robert Bieber8ea056d2010-05-27 19:57:15 +0000200
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000201 skin_debug_indent();
202 printf("]\n");
203 break;
204
205 case CONDITIONAL:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000206 printf("< Conditional tag %%?%s on line %d with %d enumerations \n",
207 current->tag->name, current->line, current->children_count);
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000208 debug_indent_level++;
209
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000210 for(i = 0; i < current->children_count; i++)
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000211 {
212 skin_debug_indent();
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000213 printf("[ Enumeration %d\n", i);
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000214 debug_indent_level++;
Jonathan Gordon9e07ef22011-11-15 14:11:08 +0000215 skin_debug_tree(get_child(current->children, i));
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000216 debug_indent_level--;
217 skin_debug_indent();
218 printf("]\n");
219 }
220
221 debug_indent_level--;
222 skin_debug_indent();
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000223 printf(">\n");
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000224
225
226 break;
227
Robert Bieber8ea056d2010-05-27 19:57:15 +0000228 case LINE:
229 printf("[ Logical line on line %d\n", current->line);
230
231 debug_indent_level++;
Jonathan Gordon1e0a0102010-08-03 12:14:50 +0000232 if (current->children)
Jonathan Gordon9e07ef22011-11-15 14:11:08 +0000233 skin_debug_tree(get_child(current->children, 0));
Robert Bieber8ea056d2010-05-27 19:57:15 +0000234 debug_indent_level--;
235
236 skin_debug_indent();
237 printf("]\n");
238 break;
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000239 }
240
Jonathan Gordon9e07ef22011-11-15 14:11:08 +0000241 current = SKINOFFSETTOPTR(skin_buffer, current->next);
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000242 }
243
244}
245
246void skin_debug_params(int count, struct skin_tag_parameter params[])
247{
248 int i;
249 for(i = 0; i < count; i++)
250 {
251
252 skin_debug_indent();
253 switch(params[i].type)
254 {
255 case DEFAULT:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000256 printf("-");
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000257 break;
258
259 case STRING:
Jonathan Gordon9e07ef22011-11-15 14:11:08 +0000260 printf("string: \"%s\"", SKINOFFSETTOPTR(skin_buffer, params[i].data.text));
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000261 break;
262
Robert Bieber15488a02010-07-15 06:24:11 +0000263 case INTEGER:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000264 printf("integer: %d", params[i].data.number);
Robert Bieber15488a02010-07-15 06:24:11 +0000265 break;
266
267 case DECIMAL:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000268 printf("decimal: %d.%d", params[i].data.number/10,
Robert Bieber15488a02010-07-15 06:24:11 +0000269 params[i].data.number%10);
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000270 break;
271
272 case CODE:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000273 printf("Skin Code: \n");
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000274 debug_indent_level++;
Jonathan Gordon9e07ef22011-11-15 14:11:08 +0000275 skin_debug_tree(SKINOFFSETTOPTR(skin_buffer, params[i].data.code));
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000276 debug_indent_level--;
277 skin_debug_indent();
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000278 break;
279 }
280
281 printf("\n");
282
283 }
284}
285
Jonathan Gordon5edae542012-03-15 23:26:07 +1100286void skin_debug_indent(void)
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000287{
288 int i;
289 for(i = 0; i < debug_indent_level; i++)
290 printf(" ");
291}
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000292
Björn Stenbergf1a144a2010-06-17 11:04:32 +0000293#endif
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000294
295#define MIN(a,b) ((a<b)?(a):(b))
Jonathan Gordon5edae542012-03-15 23:26:07 +1100296void skin_error_format_message(void)
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000297{
298 int i;
299 char text[128];
Jonathan Gordonf74a1aa2010-11-11 09:57:37 +0000300 if (!error_line_start)
301 return;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000302 char* line_end = strchr(error_line_start, '\n');
303 int len = MIN(line_end - error_line_start, 80);
304 if (!line_end)
305 len = strlen(error_line_start);
306 printf("Error on line %d.\n", error_line);
307 error_col--;
308 if (error_col <= 10)
309 {
310 strncpy(text, error_line_start, len);
311 text[len] = '\0';
312 }
313 else
314 {
315 int j;
316 /* make it fit nicely.. "<start few chars>...<10 chars><error>" */
317 strncpy(text, error_line_start, 6);
318 i = 5;
319 text[i++] = '.';
320 text[i++] = '.';
321 text[i++] = '.';
322 for (j=error_col-10; error_line_start[j] && error_line_start[j] != '\n'; j++)
323 text[i++] = error_line_start[j];
324 text[i] = '\0';
325 error_col = 18;
326 }
327 printf("%s\n", text);
328 for (i=0; i<error_col; i++)
329 text[i] = ' ';
330 snprintf(&text[i],64, "^ \'%s\' Here", error_message);
331 printf("%s\n", text);
332}