summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJonathan Gordon <rockbox@jdgordon.info>2011-11-15 14:11:08 +0000
committerJonathan Gordon <rockbox@jdgordon.info>2011-11-15 14:11:08 +0000
commit9e07ef2b0adb8fca7e5a9e516397e533653f8836 (patch)
tree0a283550421917e52ee04068b84a464976f0c4f2 /lib
parent101693fd3047fb64e766580e80635a424fa25c4d (diff)
downloadrockbox-9e07ef2b0adb8fca7e5a9e516397e533653f8836.tar.gz
rockbox-9e07ef2b0adb8fca7e5a9e516397e533653f8836.zip
Use buflib for all skin engine allocations.
Massive thanks to Michael Chicoine and other testers for finding the early bugs. This removes all skin memory limitations git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30991 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'lib')
-rw-r--r--lib/skin_parser/skin_buffer.c73
-rw-r--r--lib/skin_parser/skin_buffer.h15
-rw-r--r--lib/skin_parser/skin_debug.c27
-rw-r--r--lib/skin_parser/skin_parser.c178
-rw-r--r--lib/skin_parser/skin_parser.h35
5 files changed, 165 insertions, 163 deletions
diff --git a/lib/skin_parser/skin_buffer.c b/lib/skin_parser/skin_buffer.c
index 5a9d4464b8..d18122ef20 100644
--- a/lib/skin_parser/skin_buffer.c
+++ b/lib/skin_parser/skin_buffer.c
@@ -47,54 +47,26 @@
47#ifdef ROCKBOX 47#ifdef ROCKBOX
48#include "config.h" 48#include "config.h"
49#include "skin_debug.h" 49#include "skin_debug.h"
50
51#ifdef APPLICATION
52# define USE_HOST_MALLOC
53#else
54# define USE_ROCKBOX_ALLOC
55#endif
56
57#endif
58
59#ifdef USE_ROCKBOX_ALLOC
60static size_t buf_size; 50static size_t buf_size;
61static unsigned char *buffer_start = NULL; 51static unsigned char *buffer_start = NULL;
62static unsigned char *buffer_front = NULL; 52static unsigned char *buffer_front = NULL;
63#endif
64
65#ifdef USE_HOST_MALLOC
66
67struct malloc_object {
68 struct malloc_object *next;
69 char buf[0];
70};
71static struct malloc_object *malloced_head = NULL, *malloced_tail = NULL;
72 53
73static void skin_free_malloced(void) 54#ifndef __PCTOOL__
55long skin_buffer_to_offset(void *pointer)
74{ 56{
75 struct malloc_object *obj = malloced_head; 57 return pointer == NULL ? -1 : (void*)pointer - (void*)buffer_start;
76 struct malloc_object *this;
77 while (obj)
78 {
79 this = obj;
80 obj = this->next;
81 free(this);
82 }
83 malloced_head = NULL;
84 malloced_tail = NULL;
85} 58}
86 59
60void* skin_buffer_from_offset(long offset)
61{
62 return offset < 0 ? NULL : buffer_start + offset;
63}
87#endif 64#endif
88 65
89void skin_buffer_init(char* buffer, size_t size) 66void skin_buffer_init(char* buffer, size_t size)
90{ 67{
91#ifdef USE_ROCKBOX_ALLOC
92 buffer_start = buffer_front = buffer; 68 buffer_start = buffer_front = buffer;
93 buf_size = size; 69 buf_size = size;
94#elif defined(USE_HOST_MALLOC)
95 (void)buffer; (void)size;
96 skin_free_malloced();
97#endif
98} 70}
99 71
100/* Allocate size bytes from the buffer */ 72/* Allocate size bytes from the buffer */
@@ -108,8 +80,6 @@ void* skin_buffer_alloc(size_t size)
108{ 80{
109 void *retval = NULL; 81 void *retval = NULL;
110#endif 82#endif
111
112#ifdef USE_ROCKBOX_ALLOC
113 /* 32-bit aligned */ 83 /* 32-bit aligned */
114 size = (size + 3) & ~3; 84 size = (size + 3) & ~3;
115 if (size > skin_buffer_freespace()) 85 if (size > skin_buffer_freespace())
@@ -119,25 +89,9 @@ void* skin_buffer_alloc(size_t size)
119 } 89 }
120 retval = buffer_front; 90 retval = buffer_front;
121 buffer_front += size; 91 buffer_front += size;
122#elif defined(USE_HOST_MALLOC)
123 size_t malloc_size = sizeof(struct malloc_object) + size;
124 struct malloc_object *obj = malloc(malloc_size);
125 retval = &obj->buf;
126 obj->next = NULL;
127 if (malloced_tail == NULL)
128 malloced_head = malloced_tail = obj;
129 else
130 malloced_tail->next = obj;
131 malloced_tail = obj;
132
133#else
134 retval = malloc(size);
135#endif
136 return retval; 92 return retval;
137} 93}
138 94
139
140#ifdef USE_ROCKBOX_ALLOC
141/* get the number of bytes currently being used */ 95/* get the number of bytes currently being used */
142size_t skin_buffer_usage(void) 96size_t skin_buffer_usage(void)
143{ 97{
@@ -147,16 +101,9 @@ size_t skin_buffer_freespace(void)
147{ 101{
148 return buf_size - skin_buffer_usage(); 102 return buf_size - skin_buffer_usage();
149} 103}
150 104#else
151static unsigned char *saved_buffer_pos = NULL; 105void* skin_buffer_alloc(size_t size)
152void skin_buffer_save_position(void)
153{
154 saved_buffer_pos = buffer_front;
155}
156
157void skin_buffer_restore_position(void)
158{ 106{
159 if (saved_buffer_pos) 107 return malloc(size);
160 buffer_front = saved_buffer_pos;
161} 108}
162#endif 109#endif
diff --git a/lib/skin_parser/skin_buffer.h b/lib/skin_parser/skin_buffer.h
index b2ed34e09f..7c9bb0b9c0 100644
--- a/lib/skin_parser/skin_buffer.h
+++ b/lib/skin_parser/skin_buffer.h
@@ -28,6 +28,18 @@
28void skin_buffer_init(char* buffer, size_t size); 28void skin_buffer_init(char* buffer, size_t size);
29/* Allocate size bytes from the buffer */ 29/* Allocate size bytes from the buffer */
30 30
31#ifndef __PCTOOL__
32#define INVALID_OFFSET (-1)
33#define IS_VALID_OFFSET(o) ((o) >= 0)
34long skin_buffer_to_offset(void *pointer);
35void* skin_buffer_from_offset(long offset);
36#else
37#define INVALID_OFFSET (NULL)
38#define IS_VALID_OFFSET(o) ((o) != NULL)
39#define skin_buffer_to_offset(p) p
40#define skin_buffer_from_offset(o) o
41#endif
42
31/* #define DEBUG_SKIN_ALLOCATIONS */ 43/* #define DEBUG_SKIN_ALLOCATIONS */
32 44
33#ifdef DEBUG_SKIN_ALLOCATIONS 45#ifdef DEBUG_SKIN_ALLOCATIONS
@@ -44,7 +56,4 @@ void* skin_buffer_alloc(size_t size);
44size_t skin_buffer_usage(void); 56size_t skin_buffer_usage(void);
45size_t skin_buffer_freespace(void); 57size_t skin_buffer_freespace(void);
46 58
47/* save and restore a buffer position incase a skin fails to load */
48void skin_buffer_save_position(void);
49void skin_buffer_restore_position(void);
50#endif 59#endif
diff --git a/lib/skin_parser/skin_debug.c b/lib/skin_parser/skin_debug.c
index 52f9127f1f..ecf238f1b1 100644
--- a/lib/skin_parser/skin_debug.c
+++ b/lib/skin_parser/skin_debug.c
@@ -31,6 +31,7 @@
31int debug_indent_level = 0; 31int debug_indent_level = 0;
32extern int skin_line; 32extern int skin_line;
33extern char* skin_start; 33extern char* skin_start;
34extern char* skin_buffer;
34 35
35/* Global error variables */ 36/* Global error variables */
36int error_line; 37int error_line;
@@ -38,6 +39,14 @@ int error_col;
38const char *error_line_start; 39const char *error_line_start;
39char* error_message; 40char* error_message;
40 41
42
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
41/* Debugging functions */ 50/* Debugging functions */
42void skin_error(enum skin_errorcode error, const char* cursor) 51void skin_error(enum skin_errorcode error, const char* cursor)
43{ 52{
@@ -144,14 +153,14 @@ void skin_debug_tree(struct skin_element* root)
144 printf("{ Viewport \n"); 153 printf("{ Viewport \n");
145 154
146 debug_indent_level++; 155 debug_indent_level++;
147 skin_debug_tree(current->children[0]); 156 skin_debug_tree(get_child(current->children, 0));
148 debug_indent_level--; 157 debug_indent_level--;
149 158
150 printf("}"); 159 printf("}");
151 break; 160 break;
152 161
153 case TEXT: 162 case TEXT:
154 text = current->data; 163 text = SKINOFFSETTOPTR(skin_buffer, current->data);
155 printf("* Plain text on line %d: \"%s\"\n", current->line, text); 164 printf("* Plain text on line %d: \"%s\"\n", current->line, text);
156 break; 165 break;
157 166
@@ -166,7 +175,7 @@ void skin_debug_tree(struct skin_element* root)
166 current->tag->name, 175 current->tag->name,
167 current->line, current->params_count); 176 current->line, current->params_count);
168 debug_indent_level++; 177 debug_indent_level++;
169 skin_debug_params(current->params_count, current->params); 178 skin_debug_params(current->params_count, SKINOFFSETTOPTR(skin_buffer, current->params));
170 debug_indent_level--; 179 debug_indent_level--;
171 skin_debug_indent(); 180 skin_debug_indent();
172 printf(")\n"); 181 printf(")\n");
@@ -185,7 +194,7 @@ void skin_debug_tree(struct skin_element* root)
185 debug_indent_level++; 194 debug_indent_level++;
186 for(i = 0; i < current->children_count; i++) 195 for(i = 0; i < current->children_count; i++)
187 { 196 {
188 skin_debug_tree(current->children[i]); 197 skin_debug_tree(get_child(current->children, i));
189 } 198 }
190 debug_indent_level--; 199 debug_indent_level--;
191 200
@@ -203,7 +212,7 @@ void skin_debug_tree(struct skin_element* root)
203 skin_debug_indent(); 212 skin_debug_indent();
204 printf("[ Enumeration %d\n", i); 213 printf("[ Enumeration %d\n", i);
205 debug_indent_level++; 214 debug_indent_level++;
206 skin_debug_tree(current->children[i]); 215 skin_debug_tree(get_child(current->children, i));
207 debug_indent_level--; 216 debug_indent_level--;
208 skin_debug_indent(); 217 skin_debug_indent();
209 printf("]\n"); 218 printf("]\n");
@@ -221,7 +230,7 @@ void skin_debug_tree(struct skin_element* root)
221 230
222 debug_indent_level++; 231 debug_indent_level++;
223 if (current->children) 232 if (current->children)
224 skin_debug_tree(current->children[0]); 233 skin_debug_tree(get_child(current->children, 0));
225 debug_indent_level--; 234 debug_indent_level--;
226 235
227 skin_debug_indent(); 236 skin_debug_indent();
@@ -229,7 +238,7 @@ void skin_debug_tree(struct skin_element* root)
229 break; 238 break;
230 } 239 }
231 240
232 current = current->next; 241 current = SKINOFFSETTOPTR(skin_buffer, current->next);
233 } 242 }
234 243
235} 244}
@@ -248,7 +257,7 @@ void skin_debug_params(int count, struct skin_tag_parameter params[])
248 break; 257 break;
249 258
250 case STRING: 259 case STRING:
251 printf("string: \"%s\"", params[i].data.text); 260 printf("string: \"%s\"", SKINOFFSETTOPTR(skin_buffer, params[i].data.text));
252 break; 261 break;
253 262
254 case INTEGER: 263 case INTEGER:
@@ -263,7 +272,7 @@ void skin_debug_params(int count, struct skin_tag_parameter params[])
263 case CODE: 272 case CODE:
264 printf("Skin Code: \n"); 273 printf("Skin Code: \n");
265 debug_indent_level++; 274 debug_indent_level++;
266 skin_debug_tree(params[i].data.code); 275 skin_debug_tree(SKINOFFSETTOPTR(skin_buffer, params[i].data.code));
267 debug_indent_level--; 276 debug_indent_level--;
268 skin_debug_indent(); 277 skin_debug_indent();
269 break; 278 break;
diff --git a/lib/skin_parser/skin_parser.c b/lib/skin_parser/skin_parser.c
index 2612cc8906..c49ac12a59 100644
--- a/lib/skin_parser/skin_parser.c
+++ b/lib/skin_parser/skin_parser.c
@@ -37,8 +37,6 @@ int skin_line = 0;
37char* skin_start = 0; 37char* skin_start = 0;
38int viewport_line = 0; 38int viewport_line = 0;
39 39
40static int tag_recursion_level = 0;
41
42#ifdef ROCKBOX 40#ifdef ROCKBOX
43static skin_callback callback = NULL; 41static skin_callback callback = NULL;
44static void* callback_data; 42static void* callback_data;
@@ -81,8 +79,6 @@ struct skin_element* skin_parse(const char* document)
81 struct skin_element* root = NULL; 79 struct skin_element* root = NULL;
82 struct skin_element* last = NULL; 80 struct skin_element* last = NULL;
83 81
84 struct skin_element** to_write = 0;
85
86 const char* cursor = document; /*Keeps track of location in the document*/ 82 const char* cursor = document; /*Keeps track of location in the document*/
87 83
88 skin_line = 1; 84 skin_line = 1;
@@ -93,14 +89,18 @@ struct skin_element* skin_parse(const char* document)
93 89
94 while(*cursor != '\0') 90 while(*cursor != '\0')
95 { 91 {
92 struct skin_element* tree = skin_parse_viewport(&cursor);
96 if(!root) 93 if(!root)
97 to_write = &root; 94 {
95 root = tree;
96 last = root;
97 }
98 else 98 else
99 to_write = &(last->next); 99 {
100 100 last->next = skin_buffer_to_offset(tree);
101 last = tree;
102 }
101 103
102 *to_write = skin_parse_viewport(&cursor);
103 last = *to_write;
104 if(!last) 104 if(!last)
105 { 105 {
106 skin_free_tree(root); /* Clearing any memory already used */ 106 skin_free_tree(root); /* Clearing any memory already used */
@@ -108,8 +108,8 @@ struct skin_element* skin_parse(const char* document)
108 } 108 }
109 109
110 /* Making sure last is at the end */ 110 /* Making sure last is at the end */
111 while(last->next) 111 while(IS_VALID_OFFSET(last->next))
112 last = last->next; 112 last = skin_buffer_from_offset(last->next);
113 113
114 } 114 }
115 return root; 115 return root;
@@ -121,8 +121,6 @@ static struct skin_element* skin_parse_viewport(const char** document)
121 struct skin_element* root = NULL; 121 struct skin_element* root = NULL;
122 struct skin_element* last = NULL; 122 struct skin_element* last = NULL;
123 struct skin_element* retval = NULL; 123 struct skin_element* retval = NULL;
124
125 tag_recursion_level = 0;
126 124
127 retval = skin_alloc_element(); 125 retval = skin_alloc_element();
128 if (!retval) 126 if (!retval)
@@ -132,7 +130,7 @@ static struct skin_element* skin_parse_viewport(const char** document)
132 retval->line = skin_line; 130 retval->line = skin_line;
133 viewport_line = skin_line; 131 viewport_line = skin_line;
134 132
135 struct skin_element** to_write = 0; 133 OFFSETTYPE(struct skin_element*)* children;
136 134
137 const char* cursor = *document; /* Keeps track of location in the document */ 135 const char* cursor = *document; /* Keeps track of location in the document */
138 const char* bookmark; /* Used when we need to look ahead */ 136 const char* bookmark; /* Used when we need to look ahead */
@@ -165,8 +163,8 @@ static struct skin_element* skin_parse_viewport(const char** document)
165 return retval; 163 return retval;
166 } 164 }
167 retval->children_count = 1; 165 retval->children_count = 1;
168 retval->children = skin_alloc_children(1); 166 children = skin_alloc_children(1);
169 if (!retval->children) 167 if (!children)
170 return NULL; 168 return NULL;
171 do 169 do
172 { 170 {
@@ -212,15 +210,19 @@ static struct skin_element* skin_parse_viewport(const char** document)
212 } 210 }
213 cursor = bookmark; 211 cursor = bookmark;
214 212
215 if(!root)
216 to_write = &root;
217 else
218 to_write = &(last->next);
219
220 if(sublines) 213 if(sublines)
221 { 214 {
222 *to_write = skin_parse_sublines(&cursor); 215 struct skin_element* out = skin_parse_sublines(&cursor);
223 last = *to_write; 216 if (!root)
217 {
218 root = out;
219 last = root;
220 }
221 else
222 {
223 last->next = skin_buffer_to_offset(out);
224 last = out;
225 }
224 if(!last) 226 if(!last)
225 return NULL; 227 return NULL;
226 } 228 }
@@ -237,15 +239,25 @@ static struct skin_element* skin_parse_viewport(const char** document)
237 if (check_viewport(cursor)) 239 if (check_viewport(cursor))
238 break; 240 break;
239#endif 241#endif
240 *to_write = skin_parse_line(&cursor); 242
241 last = *to_write; 243 struct skin_element* out = skin_parse_line(&cursor);
244 if (!root)
245 {
246 root = out;
247 last = root;
248 }
249 else
250 {
251 last->next = skin_buffer_to_offset(out);
252 last = out;
253 }
242 if(!last) 254 if(!last)
243 return NULL; 255 return NULL;
244 256
245 } 257 }
246 /* Making sure last is at the end */ 258 /* Making sure last is at the end */
247 while(last->next) 259 while(IS_VALID_OFFSET(last->next))
248 last = last->next; 260 last = skin_buffer_from_offset(last->next);
249 261
250 if(*cursor == '\n') 262 if(*cursor == '\n')
251 { 263 {
@@ -269,7 +281,8 @@ static struct skin_element* skin_parse_viewport(const char** document)
269 281
270 *document = cursor; 282 *document = cursor;
271 283
272 retval->children[0] = root; 284 children[0] = skin_buffer_to_offset(root);
285 retval->children = skin_buffer_to_offset(children);
273 return retval; 286 return retval;
274} 287}
275 288
@@ -293,6 +306,7 @@ static struct skin_element* skin_parse_line_optional(const char** document,
293 struct skin_element* root = NULL; 306 struct skin_element* root = NULL;
294 struct skin_element* current = NULL; 307 struct skin_element* current = NULL;
295 struct skin_element* retval = NULL; 308 struct skin_element* retval = NULL;
309 OFFSETTYPE(struct skin_element*)* children = NULL;
296 310
297 /* A wrapper for the line */ 311 /* A wrapper for the line */
298 retval = skin_alloc_element(); 312 retval = skin_alloc_element();
@@ -315,8 +329,8 @@ static struct skin_element* skin_parse_line_optional(const char** document,
315 329
316 if(retval->children_count > 0) 330 if(retval->children_count > 0)
317 { 331 {
318 retval->children = skin_alloc_children(1); 332 children = skin_alloc_children(1);
319 if (!retval->children) 333 if (!children)
320 return NULL; 334 return NULL;
321 } 335 }
322 336
@@ -344,10 +358,11 @@ static struct skin_element* skin_parse_line_optional(const char** document,
344 /* Allocating memory if necessary */ 358 /* Allocating memory if necessary */
345 if(root) 359 if(root)
346 { 360 {
347 current->next = skin_alloc_element(); 361 struct skin_element *next = skin_alloc_element();
348 if (!current->next) 362 if (!next)
349 return NULL; 363 return NULL;
350 current = current->next; 364 current->next = skin_buffer_to_offset(next);
365 current = next;
351 } 366 }
352 else 367 else
353 { 368 {
@@ -384,7 +399,10 @@ static struct skin_element* skin_parse_line_optional(const char** document,
384 *document = cursor; 399 *document = cursor;
385 400
386 if(root) 401 if(root)
387 retval->children[0] = root; 402 {
403 children[0] = skin_buffer_to_offset(root);
404 retval->children = skin_buffer_to_offset(children);
405 }
388 return retval; 406 return retval;
389} 407}
390 408
@@ -397,6 +415,7 @@ static struct skin_element* skin_parse_sublines_optional(const char** document,
397 int conditional) 415 int conditional)
398{ 416{
399 struct skin_element* retval; 417 struct skin_element* retval;
418 OFFSETTYPE(struct skin_element*)* children;
400 const char* cursor = *document; 419 const char* cursor = *document;
401 int sublines = 1; 420 int sublines = 1;
402 int i; 421 int i;
@@ -405,7 +424,7 @@ static struct skin_element* skin_parse_sublines_optional(const char** document,
405 if (!retval) 424 if (!retval)
406 return NULL; 425 return NULL;
407 retval->type = LINE_ALTERNATOR; 426 retval->type = LINE_ALTERNATOR;
408 retval->next = NULL; 427 retval->next = skin_buffer_to_offset(NULL);
409 retval->line = skin_line; 428 retval->line = skin_line;
410 429
411 /* First we count the sublines */ 430 /* First we count the sublines */
@@ -449,14 +468,16 @@ static struct skin_element* skin_parse_sublines_optional(const char** document,
449 468
450 /* ...and then we parse them */ 469 /* ...and then we parse them */
451 retval->children_count = sublines; 470 retval->children_count = sublines;
452 retval->children = skin_alloc_children(sublines); 471 children = skin_alloc_children(sublines);
453 if (!retval->children) 472 if (!children)
454 return NULL; 473 return NULL;
455 474
456 cursor = *document; 475 cursor = *document;
457 for(i = 0; i < sublines; i++) 476 for(i = 0; i < sublines; i++)
458 { 477 {
459 retval->children[i] = skin_parse_line_optional(&cursor, conditional); 478 children[i] = skin_buffer_to_offset(skin_parse_line_optional(&cursor, conditional));
479 if (children[i] < 0)
480 return NULL;
460 skip_whitespace(&cursor); 481 skip_whitespace(&cursor);
461 482
462 if(*cursor != MULTILINESYM && i != sublines - 1) 483 if(*cursor != MULTILINESYM && i != sublines - 1)
@@ -478,6 +499,7 @@ static struct skin_element* skin_parse_sublines_optional(const char** document,
478 } 499 }
479#endif 500#endif
480 *document = cursor; 501 *document = cursor;
502 retval->children = skin_buffer_to_offset(children);
481 503
482 return retval; 504 return retval;
483} 505}
@@ -490,13 +512,13 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
490 char tag_name[3]; 512 char tag_name[3];
491 char* tag_args; 513 char* tag_args;
492 const struct tag_info *tag; 514 const struct tag_info *tag;
515 struct skin_tag_parameter* params = NULL;
493 516
494 int num_args = 1; 517 int num_args = 1;
495 int i; 518 int i;
496 int star = 0; /* Flag for the all-or-none option */ 519 int star = 0; /* Flag for the all-or-none option */
497 520
498 int optional = 0; 521 int optional = 0;
499 tag_recursion_level++;
500 522
501 /* Checking the tag name */ 523 /* Checking the tag name */
502 tag_name[0] = cursor[0]; 524 tag_name[0] = cursor[0];
@@ -597,8 +619,8 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
597 619
598 cursor = bookmark; /* Restoring the cursor */ 620 cursor = bookmark; /* Restoring the cursor */
599 element->params_count = num_args; 621 element->params_count = num_args;
600 element->params = skin_alloc_params(num_args, tag_recursion_level<=1); 622 params = skin_alloc_params(num_args);
601 if (!element->params) 623 if (!params)
602 return 0; 624 return 0;
603 625
604 /* Now we have to actually parse each argument */ 626 /* Now we have to actually parse each argument */
@@ -686,14 +708,14 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
686 else 708 else
687 type_code = *tag_args; 709 type_code = *tag_args;
688 /* Storing the type code */ 710 /* Storing the type code */
689 element->params[i].type_code = type_code; 711 params[i].type_code = type_code;
690 712
691 /* Checking a nullable argument for null. */ 713 /* Checking a nullable argument for null. */
692 if(*cursor == DEFAULTSYM && !isdigit(cursor[1])) 714 if(*cursor == DEFAULTSYM && !isdigit(cursor[1]))
693 { 715 {
694 if(islower(type_code)) 716 if(islower(type_code))
695 { 717 {
696 element->params[i].type = DEFAULT; 718 params[i].type = DEFAULT;
697 cursor++; 719 cursor++;
698 } 720 }
699 else 721 else
@@ -711,8 +733,8 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
711 return 0; 733 return 0;
712 } 734 }
713 735
714 element->params[i].type = INTEGER; 736 params[i].type = INTEGER;
715 element->params[i].data.number = scan_int(&cursor); 737 params[i].data.number = scan_int(&cursor);
716 } 738 }
717 else if(tolower(type_code) == 'd') 739 else if(tolower(type_code) == 'd')
718 { 740 {
@@ -738,23 +760,23 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
738 } 760 }
739 if (have_tenth == false) 761 if (have_tenth == false)
740 val *= 10; 762 val *= 10;
741 element->params[i].type = DECIMAL; 763 params[i].type = DECIMAL;
742 element->params[i].data.number = val; 764 params[i].data.number = val;
743 } 765 }
744 else if(tolower(type_code) == 'n' || 766 else if(tolower(type_code) == 'n' ||
745 tolower(type_code) == 's' || tolower(type_code) == 'f') 767 tolower(type_code) == 's' || tolower(type_code) == 'f')
746 { 768 {
747 /* Scanning a string argument */ 769 /* Scanning a string argument */
748 element->params[i].type = STRING; 770 params[i].type = STRING;
749 element->params[i].data.text = scan_string(&cursor); 771 params[i].data.text = skin_buffer_to_offset(scan_string(&cursor));
750 772
751 } 773 }
752 else if(tolower(type_code) == 'c') 774 else if(tolower(type_code) == 'c')
753 { 775 {
754 /* Recursively parsing a code argument */ 776 /* Recursively parsing a code argument */
755 element->params[i].type = CODE; 777 params[i].type = CODE;
756 element->params[i].data.code = skin_parse_code_as_arg(&cursor); 778 params[i].data.code = skin_buffer_to_offset(skin_parse_code_as_arg(&cursor));
757 if(!element->params[i].data.code) 779 if(params[i].data.code < 0)
758 return 0; 780 return 0;
759 } 781 }
760 else if (tolower(type_code) == 't') 782 else if (tolower(type_code) == 't')
@@ -763,9 +785,9 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
763 child->type = TAG; 785 child->type = TAG;
764 if (!skin_parse_tag(child, &cursor)) 786 if (!skin_parse_tag(child, &cursor))
765 return 0; 787 return 0;
766 child->next = NULL; 788 child->next = skin_buffer_to_offset(NULL);
767 element->params[i].type = CODE; 789 params[i].type = CODE;
768 element->params[i].data.code = child; 790 params[i].data.code = skin_buffer_to_offset(child);
769 } 791 }
770 792
771 793
@@ -796,6 +818,7 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
796 tag_args++; 818 tag_args++;
797 } 819 }
798 } 820 }
821 element->params = skin_buffer_to_offset(params);
799 822
800 /* Checking for a premature end */ 823 /* Checking for a premature end */
801 if(*tag_args != '\0' && !optional) 824 if(*tag_args != '\0' && !optional)
@@ -811,7 +834,6 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
811 } 834 }
812#endif 835#endif
813 *document = cursor; 836 *document = cursor;
814 tag_recursion_level--;
815 837
816 return 1; 838 return 1;
817} 839}
@@ -855,9 +877,10 @@ static int skin_parse_text(struct skin_element* element, const char** document,
855 /* Copying the text into the element struct */ 877 /* Copying the text into the element struct */
856 element->type = TEXT; 878 element->type = TEXT;
857 element->line = skin_line; 879 element->line = skin_line;
858 element->next = NULL; 880 element->next = skin_buffer_to_offset(NULL);
859 element->data = text = skin_alloc_string(length); 881 text = skin_alloc_string(length);
860 if (!element->data) 882 element->data = skin_buffer_to_offset(text);
883 if (element->data < 0)
861 return 0; 884 return 0;
862 885
863 for(dest = 0; dest < length; dest++) 886 for(dest = 0; dest < length; dest++)
@@ -896,6 +919,7 @@ static int skin_parse_conditional(struct skin_element* element, const char** doc
896 const char *false_branch = NULL; 919 const char *false_branch = NULL;
897 const char *conditional_end = NULL; 920 const char *conditional_end = NULL;
898#endif 921#endif
922 OFFSETTYPE(struct skin_element*)* children_array = NULL;
899 923
900 /* Some conditional tags allow for target feature checking, 924 /* Some conditional tags allow for target feature checking,
901 * so to handle that call the callback as usual with type == TAG 925 * so to handle that call the callback as usual with type == TAG
@@ -994,23 +1018,23 @@ static int skin_parse_conditional(struct skin_element* element, const char** doc
994 { 1018 {
995 const char* emptyline= ""; 1019 const char* emptyline= "";
996 children = 1; 1020 children = 1;
997 element->children = skin_alloc_children(children); 1021 children_array = skin_alloc_children(children);
998 if (!element->children) 1022 if (!children_array)
999 return 0; 1023 return 0;
1000 element->children_count = children; 1024 element->children_count = children;
1001 element->children[0] = skin_parse_code_as_arg(&emptyline); 1025 children_array[0] = skin_buffer_to_offset(skin_parse_code_as_arg(&emptyline));
1002 } 1026 }
1003 else 1027 else
1004 { 1028 {
1005 element->children = skin_alloc_children(children); 1029 children_array = skin_alloc_children(children);
1006 if (!element->children) 1030 if (!children_array)
1007 return 0; 1031 return 0;
1008 element->children_count = children; 1032 element->children_count = children;
1009 1033
1010 for(i = 0; i < children; i++) 1034 for(i = 0; i < children; i++)
1011 { 1035 {
1012 element->children[i] = skin_parse_code_as_arg(&cursor); 1036 children_array[i] = skin_buffer_to_offset(skin_parse_code_as_arg(&cursor));
1013 if (element->children[i] == NULL) 1037 if (children_array[i] < 0)
1014 return 0; 1038 return 0;
1015 skip_whitespace(&cursor); 1039 skip_whitespace(&cursor);
1016#ifdef ROCKBOX 1040#ifdef ROCKBOX
@@ -1035,6 +1059,7 @@ static int skin_parse_conditional(struct skin_element* element, const char** doc
1035 } 1059 }
1036 } 1060 }
1037 *document = cursor; 1061 *document = cursor;
1062 element->children = skin_buffer_to_offset(children_array);
1038 1063
1039 return 1; 1064 return 1;
1040} 1065}
@@ -1056,7 +1081,7 @@ static int skin_parse_comment(struct skin_element* element, const char** documen
1056 element->type = COMMENT; 1081 element->type = COMMENT;
1057 element->line = skin_line; 1082 element->line = skin_line;
1058#ifdef ROCKBOX 1083#ifdef ROCKBOX
1059 element->data = NULL; 1084 element->data = INVALID_OFFSET;
1060#else 1085#else
1061 element->data = text = skin_alloc_string(length); 1086 element->data = text = skin_alloc_string(length);
1062 if (!element->data) 1087 if (!element->data)
@@ -1122,7 +1147,6 @@ static struct skin_element* skin_parse_code_as_arg(const char** document)
1122 return skin_parse_line_optional(document, 1); 1147 return skin_parse_line_optional(document, 1);
1123} 1148}
1124 1149
1125
1126/* Memory management */ 1150/* Memory management */
1127struct skin_element* skin_alloc_element() 1151struct skin_element* skin_alloc_element()
1128{ 1152{
@@ -1131,10 +1155,12 @@ struct skin_element* skin_alloc_element()
1131 if (!retval) 1155 if (!retval)
1132 return NULL; 1156 return NULL;
1133 retval->type = UNKNOWN; 1157 retval->type = UNKNOWN;
1134 retval->next = NULL; 1158 retval->next = skin_buffer_to_offset(NULL);
1159 retval->params = skin_buffer_to_offset(NULL);
1135 retval->tag = NULL; 1160 retval->tag = NULL;
1136 retval->params_count = 0; 1161 retval->params_count = 0;
1137 retval->children_count = 0; 1162 retval->children_count = 0;
1163 retval->data = INVALID_OFFSET;
1138 1164
1139 return retval; 1165 return retval;
1140 1166
@@ -1144,16 +1170,8 @@ struct skin_element* skin_alloc_element()
1144 * enough for any tag. params should be used straight away by the callback 1170 * enough for any tag. params should be used straight away by the callback
1145 * so this is safe. 1171 * so this is safe.
1146 */ 1172 */
1147struct skin_tag_parameter* skin_alloc_params(int count, bool use_shared_params) 1173struct skin_tag_parameter* skin_alloc_params(int count)
1148{ 1174{
1149#ifdef ROCKBOX
1150 static struct skin_tag_parameter params[MAX_TAG_PARAMS];
1151 if (use_shared_params && count <= MAX_TAG_PARAMS)
1152 {
1153 memset(params, 0, sizeof(params));
1154 return params;
1155 }
1156#endif
1157 size_t size = sizeof(struct skin_tag_parameter) * count; 1175 size_t size = sizeof(struct skin_tag_parameter) * count;
1158 return (struct skin_tag_parameter*)skin_buffer_alloc(size); 1176 return (struct skin_tag_parameter*)skin_buffer_alloc(size);
1159 1177
@@ -1164,9 +1182,9 @@ char* skin_alloc_string(int length)
1164 return (char*)skin_buffer_alloc(sizeof(char) * (length + 1)); 1182 return (char*)skin_buffer_alloc(sizeof(char) * (length + 1));
1165} 1183}
1166 1184
1167struct skin_element** skin_alloc_children(int count) 1185OFFSETTYPE(struct skin_element*)* skin_alloc_children(int count)
1168{ 1186{
1169 return (struct skin_element**) 1187 return (OFFSETTYPE(struct skin_element*)*)
1170 skin_buffer_alloc(sizeof(struct skin_element*) * count); 1188 skin_buffer_alloc(sizeof(struct skin_element*) * count);
1171} 1189}
1172 1190
diff --git a/lib/skin_parser/skin_parser.h b/lib/skin_parser/skin_parser.h
index 3e0634976c..120112d995 100644
--- a/lib/skin_parser/skin_parser.h
+++ b/lib/skin_parser/skin_parser.h
@@ -29,6 +29,25 @@ extern "C"
29#include <stdlib.h> 29#include <stdlib.h>
30#include <stdbool.h> 30#include <stdbool.h>
31 31
32#if defined(ROCKBOX) && !defined(__PCTOOL__)
33/* Use this type and macro to convert a pointer from the
34 * skin buffer to a useable pointer */
35typedef long skinoffset_t;
36#define SKINOFFSETTOPTR(base, offset) ((offset) < 0 ? NULL : ((void*)&base[offset]))
37#define PTRTOSKINOFFSET(base, pointer) ((pointer) ? ((void*)pointer-(void*)base) : -1)
38/* Use this macro when declaring a variable to self-document the code.
39 * type is the actual type being pointed to (i.e OFFSETTYPE(char*) foo )
40 *
41 * WARNING: Don't use the PTRTOSKINOFFSET() around a function call as it wont
42 * do what you expect.
43 */
44#define OFFSETTYPE(type) skinoffset_t
45#else
46#define SKINOFFSETTOPTR(base, offset) offset
47#define PTRTOSKINOFFSET(base, pointer) pointer
48#define OFFSETTYPE(type) type
49#endif
50
32/******************************************************************** 51/********************************************************************
33 ****** Data Structures ********************************************* 52 ****** Data Structures *********************************************
34 *******************************************************************/ 53 *******************************************************************/
@@ -78,8 +97,8 @@ struct skin_tag_parameter
78 union 97 union
79 { 98 {
80 int number; 99 int number;
81 char* text; 100 OFFSETTYPE(char*) text;
82 struct skin_element* code; 101 OFFSETTYPE(struct skin_element*) code;
83 } data; 102 } data;
84 103
85 char type_code; 104 char type_code;
@@ -92,20 +111,20 @@ struct skin_tag_parameter
92struct skin_element 111struct skin_element
93{ 112{
94 /* Link to the next element */ 113 /* Link to the next element */
95 struct skin_element* next; 114 OFFSETTYPE(struct skin_element*) next;
96 /* Pointer to an array of children */ 115 /* Pointer to an array of children */
97 struct skin_element** children; 116 OFFSETTYPE(struct skin_element**) children;
98 /* Placeholder for element data 117 /* Placeholder for element data
99 * TEXT and COMMENT uses it for the text string 118 * TEXT and COMMENT uses it for the text string
100 * TAG, VIEWPORT, LINE, etc may use it for post parse extra storage 119 * TAG, VIEWPORT, LINE, etc may use it for post parse extra storage
101 */ 120 */
102 void* data; 121 OFFSETTYPE(void*) data;
103 122
104 /* The tag or conditional name */ 123 /* The tag or conditional name */
105 const struct tag_info *tag; 124 const struct tag_info *tag;
106 125
107 /* Pointer to an array of parameters */ 126 /* Pointer to an array of parameters */
108 struct skin_tag_parameter* params; 127 OFFSETTYPE(struct skin_tag_parameter*) params;
109 128
110 /* Number of elements in the children array */ 129 /* Number of elements in the children array */
111 short children_count; 130 short children_count;
@@ -140,8 +159,8 @@ struct skin_element* skin_parse(const char* document);
140#endif 159#endif
141/* Memory management functions */ 160/* Memory management functions */
142struct skin_element* skin_alloc_element(void); 161struct skin_element* skin_alloc_element(void);
143struct skin_element** skin_alloc_children(int count); 162OFFSETTYPE(struct skin_element*)* skin_alloc_children(int count);
144struct skin_tag_parameter* skin_alloc_params(int count, bool use_shared_params); 163struct skin_tag_parameter* skin_alloc_params(int count);
145char* skin_alloc_string(int length); 164char* skin_alloc_string(int length);
146 165
147void skin_free_tree(struct skin_element* root); 166void skin_free_tree(struct skin_element* root);