summaryrefslogtreecommitdiff
path: root/lib/skin_parser/skin_parser.c
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/skin_parser/skin_parser.c
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/skin_parser/skin_parser.c')
-rw-r--r--lib/skin_parser/skin_parser.c178
1 files changed, 98 insertions, 80 deletions
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