blob: 52f9127f1f88160f4e4d234a17e802a70b8e9d2f [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;
Robert Bieberd5b24dd2010-05-25 15:19:52 +000034
Robert Bieber0e44ce92010-06-07 20:29:46 +000035/* Global error variables */
36int error_line;
Robert Bieber3c4fb8a2010-07-18 00:59:02 +000037int error_col;
Nils Wallménius8be79a22010-07-31 16:33:34 +000038const char *error_line_start;
Robert Bieber0e44ce92010-06-07 20:29:46 +000039char* error_message;
40
Robert Bieberd5b24dd2010-05-25 15:19:52 +000041/* Debugging functions */
Nils Wallménius804437a2010-07-31 16:30:22 +000042void skin_error(enum skin_errorcode error, const char* cursor)
Robert Bieberd5b24dd2010-05-25 15:19:52 +000043{
44
Robert Bieber3c4fb8a2010-07-18 00:59:02 +000045 error_col = 0;
46
47 while(cursor > skin_start && *cursor != '\n')
48 {
49 cursor--;
50 error_col++;
51 }
Jonathan Gordon2d31d772010-07-29 12:37:48 +000052 error_line_start = cursor+1;
Robert Bieber3c4fb8a2010-07-18 00:59:02 +000053
Robert Bieber0e44ce92010-06-07 20:29:46 +000054 error_line = skin_line;
Robert Bieberd5b24dd2010-05-25 15:19:52 +000055
56 switch(error)
57 {
58 case MEMORY_LIMIT_EXCEEDED:
Jonathan Gordon21e89e82011-01-27 11:27:53 +000059 error_line_start = NULL;
60 printf("Error: Memory limit exceeded at Line %d\n", skin_line);
Robert Bieber0e44ce92010-06-07 20:29:46 +000061 error_message = "Memory limit exceeded";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000062 break;
63 case NEWLINE_EXPECTED:
Robert Bieber0e44ce92010-06-07 20:29:46 +000064 error_message = "Newline expected";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000065 break;
66 case ILLEGAL_TAG:
Robert Bieber0e44ce92010-06-07 20:29:46 +000067 error_message = "Illegal tag";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000068 break;
69 case ARGLIST_EXPECTED:
Robert Bieber0e44ce92010-06-07 20:29:46 +000070 error_message = "Argument list expected";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000071 break;
72 case TOO_MANY_ARGS:
Robert Bieber0e44ce92010-06-07 20:29:46 +000073 error_message = "Too many arguments given";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000074 break;
75 case DEFAULT_NOT_ALLOWED:
Robert Bieber0e44ce92010-06-07 20:29:46 +000076 error_message = "Argument can not be set to default";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000077 break;
78 case UNEXPECTED_NEWLINE:
Robert Bieber0e44ce92010-06-07 20:29:46 +000079 error_message = "Unexpected newline";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000080 break;
81 case INSUFFICIENT_ARGS:
Robert Bieber0e44ce92010-06-07 20:29:46 +000082 error_message = "Not enough arguments";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000083 break;
84 case INT_EXPECTED:
Robert Bieber0e44ce92010-06-07 20:29:46 +000085 error_message = "Expected integer";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000086 break;
Robert Bieber15488a02010-07-15 06:24:11 +000087 case DECIMAL_EXPECTED:
88 error_message = "Expected decimal";
89 break;
Bertrik Sikkenfffbdcc2010-11-05 09:51:19 +000090 case SEPARATOR_EXPECTED:
91 error_message = "Expected argument separator";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000092 break;
93 case CLOSE_EXPECTED:
Robert Bieber0e44ce92010-06-07 20:29:46 +000094 error_message = "Expected list close";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000095 break;
96 case MULTILINE_EXPECTED:
Bertrik Sikkenfffbdcc2010-11-05 09:51:19 +000097 error_message = "Expected subline separator";
Robert Bieberd5b24dd2010-05-25 15:19:52 +000098 break;
99 };
100
101}
102
Robert Bieber0e44ce92010-06-07 20:29:46 +0000103int skin_error_line()
104{
105 return error_line;
106}
107
Robert Bieber3c4fb8a2010-07-18 00:59:02 +0000108int skin_error_col()
109{
110 return error_col;
111}
112
Robert Bieber0e44ce92010-06-07 20:29:46 +0000113char* skin_error_message()
114{
115 return error_message;
116}
117
Robert Bieber594d7342010-06-07 21:09:13 +0000118void skin_clear_errors()
119{
120 error_line = 0;
Robert Bieber3c4fb8a2010-07-18 00:59:02 +0000121 error_col = 0;
Robert Bieber594d7342010-06-07 21:09:13 +0000122 error_message = NULL;
123}
124
Jonathan Gordon1e0a0102010-08-03 12:14:50 +0000125#if !defined(ROCKBOX) || defined(__PCTOOL__)
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000126void skin_debug_tree(struct skin_element* root)
127{
128 int i;
Robert Bieber64321ad2010-06-10 21:02:44 +0000129 char *text;
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000130
131 struct skin_element* current = root;
132
133 while(current)
134 {
135 skin_debug_indent();
136
137 switch(current->type)
138 {
Jonathan Gordon35b09cb2010-06-13 03:13:01 +0000139 case UNKNOWN:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000140 printf("* Unknown element.. error *\n");
Jonathan Gordon35b09cb2010-06-13 03:13:01 +0000141 break;
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000142
Robert Bieberd1659d62010-06-01 07:11:23 +0000143 case VIEWPORT:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000144 printf("{ Viewport \n");
Robert Bieberd1659d62010-06-01 07:11:23 +0000145
146 debug_indent_level++;
147 skin_debug_tree(current->children[0]);
148 debug_indent_level--;
149
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000150 printf("}");
Robert Bieberd1659d62010-06-01 07:11:23 +0000151 break;
152
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000153 case TEXT:
Robert Bieber64321ad2010-06-10 21:02:44 +0000154 text = current->data;
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000155 printf("* Plain text on line %d: \"%s\"\n", current->line, text);
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000156 break;
157
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000158 case COMMENT:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000159 printf("# Comment on line %d\n ", current->line);
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000160 break;
161
162 case TAG:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000163 if (current->params_count)
164 {
165 printf("( %%%s tag on line %d with %d arguments\n",
166 current->tag->name,
167 current->line, current->params_count);
168 debug_indent_level++;
169 skin_debug_params(current->params_count, current->params);
170 debug_indent_level--;
171 skin_debug_indent();
172 printf(")\n");
173 }
174 else
175 {
176 printf("[ %%%s tag on line %d ]\n",
177 current->tag->name, current->line);
178 }
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000179
180 break;
181
Jonathan Gordondc347852010-07-04 02:04:14 +0000182 case LINE_ALTERNATOR:
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000183 printf("[ Alternator on line %d with %d sublines \n", current->line,
184 current->children_count);
185 debug_indent_level++;
186 for(i = 0; i < current->children_count; i++)
187 {
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000188 skin_debug_tree(current->children[i]);
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000189 }
190 debug_indent_level--;
Robert Bieber8ea056d2010-05-27 19:57:15 +0000191
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000192 skin_debug_indent();
193 printf("]\n");
194 break;
195
196 case CONDITIONAL:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000197 printf("< Conditional tag %%?%s on line %d with %d enumerations \n",
198 current->tag->name, current->line, current->children_count);
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000199 debug_indent_level++;
200
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000201 for(i = 0; i < current->children_count; i++)
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000202 {
203 skin_debug_indent();
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000204 printf("[ Enumeration %d\n", i);
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000205 debug_indent_level++;
206 skin_debug_tree(current->children[i]);
207 debug_indent_level--;
208 skin_debug_indent();
209 printf("]\n");
210 }
211
212 debug_indent_level--;
213 skin_debug_indent();
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000214 printf(">\n");
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000215
216
217 break;
218
Robert Bieber8ea056d2010-05-27 19:57:15 +0000219 case LINE:
220 printf("[ Logical line on line %d\n", current->line);
221
222 debug_indent_level++;
Jonathan Gordon1e0a0102010-08-03 12:14:50 +0000223 if (current->children)
224 skin_debug_tree(current->children[0]);
Robert Bieber8ea056d2010-05-27 19:57:15 +0000225 debug_indent_level--;
226
227 skin_debug_indent();
228 printf("]\n");
229 break;
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000230 }
231
232 current = current->next;
233 }
234
235}
236
237void skin_debug_params(int count, struct skin_tag_parameter params[])
238{
239 int i;
240 for(i = 0; i < count; i++)
241 {
242
243 skin_debug_indent();
244 switch(params[i].type)
245 {
246 case DEFAULT:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000247 printf("-");
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000248 break;
249
250 case STRING:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000251 printf("string: \"%s\"", params[i].data.text);
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000252 break;
253
Robert Bieber15488a02010-07-15 06:24:11 +0000254 case INTEGER:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000255 printf("integer: %d", params[i].data.number);
Robert Bieber15488a02010-07-15 06:24:11 +0000256 break;
257
258 case DECIMAL:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000259 printf("decimal: %d.%d", params[i].data.number/10,
Robert Bieber15488a02010-07-15 06:24:11 +0000260 params[i].data.number%10);
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000261 break;
262
263 case CODE:
Jonathan Gordon4d8430f2010-11-11 12:05:34 +0000264 printf("Skin Code: \n");
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000265 debug_indent_level++;
266 skin_debug_tree(params[i].data.code);
267 debug_indent_level--;
268 skin_debug_indent();
Robert Bieberd5b24dd2010-05-25 15:19:52 +0000269 break;
270 }
271
272 printf("\n");
273
274 }
275}
276
277void skin_debug_indent()
278{
279 int i;
280 for(i = 0; i < debug_indent_level; i++)
281 printf(" ");
282}
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000283
Björn Stenbergf1a144a2010-06-17 11:04:32 +0000284#endif
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000285
286#define MIN(a,b) ((a<b)?(a):(b))
287void skin_error_format_message()
288{
289 int i;
290 char text[128];
Jonathan Gordonf74a1aa2010-11-11 09:57:37 +0000291 if (!error_line_start)
292 return;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000293 char* line_end = strchr(error_line_start, '\n');
294 int len = MIN(line_end - error_line_start, 80);
295 if (!line_end)
296 len = strlen(error_line_start);
297 printf("Error on line %d.\n", error_line);
298 error_col--;
299 if (error_col <= 10)
300 {
301 strncpy(text, error_line_start, len);
302 text[len] = '\0';
303 }
304 else
305 {
306 int j;
307 /* make it fit nicely.. "<start few chars>...<10 chars><error>" */
308 strncpy(text, error_line_start, 6);
309 i = 5;
310 text[i++] = '.';
311 text[i++] = '.';
312 text[i++] = '.';
313 for (j=error_col-10; error_line_start[j] && error_line_start[j] != '\n'; j++)
314 text[i++] = error_line_start[j];
315 text[i] = '\0';
316 error_col = 18;
317 }
318 printf("%s\n", text);
319 for (i=0; i<error_col; i++)
320 text[i] = ' ';
321 snprintf(&text[i],64, "^ \'%s\' Here", error_message);
322 printf("%s\n", text);
323}