|
1 /* |
|
2 * GUI XML parser |
|
3 * |
|
4 * Copyright (c) 2009 CodeSourcery |
|
5 * |
|
6 * Permission is hereby granted, free of charge, to any person obtaining a copy |
|
7 * of this software and associated documentation files (the "Software"), to deal |
|
8 * in the Software without restriction, including without limitation the rights |
|
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
10 * copies of the Software, and to permit persons to whom the Software is |
|
11 * furnished to do so, subject to the following conditions: |
|
12 * |
|
13 * The above copyright notice and this permission notice shall be included in |
|
14 * all copies or substantial portions of the Software. |
|
15 * |
|
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
22 * THE SOFTWARE. |
|
23 */ |
|
24 |
|
25 #include "stdio.h" |
|
26 #include "string.h" |
|
27 #include "stddef.h" |
|
28 #include "qemu-common.h" |
|
29 #include "gui_common.h" |
|
30 #include "gui_parser.h" |
|
31 #include "expat.h" |
|
32 |
|
33 typedef enum { |
|
34 WAITING_GUI_START, |
|
35 WAITING_VT_START, |
|
36 WAITING_VT_CONTENT, |
|
37 WAITING_BUTTON_END, |
|
38 WAITING_PAREA_END, /* Pointer Area */ |
|
39 WAITING_DAREA_END, /* Display Area */ |
|
40 /* leave this at the end */ |
|
41 N_PARSER_STATES |
|
42 } parser_state_t; |
|
43 |
|
44 typedef struct |
|
45 { |
|
46 XML_Parser parser; |
|
47 parse_result_t result; |
|
48 parser_state_t state; |
|
49 gui_xml_tree_t *gui_xml_tree; |
|
50 |
|
51 vt_node_t *last_vt_node; |
|
52 /* the following data points to the last vt node */ |
|
53 image_node_t *last_image_node; |
|
54 displayarea_node_t *last_displayarea_node; |
|
55 pointerarea_node_t *last_pointerarea_node; |
|
56 button_node_t *last_button_node; |
|
57 |
|
58 } parser_data_t; |
|
59 |
|
60 typedef struct |
|
61 { |
|
62 void (*start)(parser_data_t *pdata, const char *element, const char **attr); |
|
63 void (*end)(parser_data_t *pdata, const char *element); |
|
64 } parser_state_handler_t; |
|
65 |
|
66 typedef struct |
|
67 { |
|
68 gui_area_t area; |
|
69 int height; |
|
70 int width; |
|
71 } tmp_area_t; |
|
72 |
|
73 #define HANDLER_NAME_START(state) parser_##state##_start_handler |
|
74 #define HANDLER_START_SIGNATURE (parser_data_t *pdata, const char *element, const char **attr) |
|
75 #define START_HANDLER_DECL(state) static void HANDLER_NAME_START(state) HANDLER_START_SIGNATURE |
|
76 |
|
77 #define HANDLER_NAME_END(state) parser_##state##_end_handler |
|
78 #define HANDLER_END_SIGNATURE (parser_data_t *pdata, const char *element) |
|
79 #define END_HANDLER_DECL(state) static void HANDLER_NAME_END(state) HANDLER_END_SIGNATURE |
|
80 |
|
81 #define FORWARD_DECL_STATE(state) \ |
|
82 START_HANDLER_DECL(state); \ |
|
83 END_HANDLER_DECL(state) |
|
84 |
|
85 #define HANDLER_PAIR(state) &HANDLER_NAME_START(state), &HANDLER_NAME_END(state) |
|
86 |
|
87 FORWARD_DECL_STATE(waiting_gui_start); |
|
88 FORWARD_DECL_STATE(waiting_vt_start); |
|
89 FORWARD_DECL_STATE(waiting_vt_content); |
|
90 FORWARD_DECL_STATE(waiting_button_end); |
|
91 FORWARD_DECL_STATE(waiting_parea_end); |
|
92 FORWARD_DECL_STATE(waiting_darea_end); |
|
93 |
|
94 static const parser_state_handler_t state_handler[N_PARSER_STATES] = { |
|
95 { HANDLER_PAIR(waiting_gui_start) }, |
|
96 { HANDLER_PAIR(waiting_vt_start) }, |
|
97 { HANDLER_PAIR(waiting_vt_content) }, |
|
98 { HANDLER_PAIR(waiting_button_end) }, |
|
99 { HANDLER_PAIR(waiting_parea_end) }, |
|
100 { HANDLER_PAIR(waiting_darea_end) } |
|
101 }; |
|
102 |
|
103 /**************************/ |
|
104 |
|
105 const char* parsing_location_error(void) |
|
106 { |
|
107 return ""; |
|
108 } |
|
109 |
|
110 static inline int attribute_is(const char *attr, const char *name) |
|
111 { |
|
112 return (strcmp(attr, name) == 0); |
|
113 } |
|
114 |
|
115 static void clear_tarea(tmp_area_t *tarea) |
|
116 { |
|
117 memset(tarea, 0, sizeof(tmp_area_t)); |
|
118 } |
|
119 |
|
120 static int assign_bool_value(const char *value, int* res) |
|
121 { |
|
122 int is_bool_value = 1; |
|
123 |
|
124 if (strcmp(value, "1") == 0 || strcmp(value, "yes") == 0 || strcmp(value, "YES") == 0) |
|
125 *res = 1; |
|
126 else if (strcmp(value, "0") == 0 || strcmp(value, "no") == 0 || strcmp(value, "NO") == 0) |
|
127 *res = 0; |
|
128 else { |
|
129 is_bool_value = 0; |
|
130 fprintf(stderr, "Warning: unrecognized bool value '%s'\n", value); |
|
131 } |
|
132 |
|
133 return is_bool_value; |
|
134 } |
|
135 |
|
136 static int assign_tarea_attribute(const char *full_attribute, const char *value, tmp_area_t *tarea, const char *attribute_prefix) |
|
137 { |
|
138 int is_area_attribute = 1; |
|
139 const char *attribute; |
|
140 int int_value = atol(value); |
|
141 int was_negative = 0; |
|
142 |
|
143 if (int_value < 0) { |
|
144 was_negative = 1; |
|
145 int_value = 0; |
|
146 } |
|
147 |
|
148 if (attribute_prefix != NULL) { |
|
149 const int prefix_len = strlen(attribute_prefix); |
|
150 if (strncmp(attribute_prefix, full_attribute, prefix_len) == 0) |
|
151 attribute = full_attribute + prefix_len; |
|
152 else |
|
153 return 0; |
|
154 } else |
|
155 attribute = full_attribute; |
|
156 |
|
157 |
|
158 if (attribute_is(attribute, "x0") || attribute_is(attribute, "x")) |
|
159 tarea->area.x0 = int_value; |
|
160 else if (attribute_is(attribute, "x1")) |
|
161 tarea->area.x1 = int_value; |
|
162 else if (attribute_is(attribute, "y0") || attribute_is(attribute, "y")) |
|
163 tarea->area.y0 = int_value; |
|
164 else if (attribute_is(attribute, "y1")) |
|
165 tarea->area.y1 = int_value; |
|
166 else if (attribute_is(attribute, "width")) |
|
167 tarea->width = int_value; |
|
168 else if (attribute_is(attribute, "height")) |
|
169 tarea->height = int_value; |
|
170 else |
|
171 is_area_attribute = 0; |
|
172 |
|
173 if (was_negative && is_area_attribute) { |
|
174 fprintf(stderr, "Warning: attribute '%s' has a negative value. Made it 0.\n", attribute); |
|
175 } |
|
176 |
|
177 return is_area_attribute; |
|
178 } |
|
179 |
|
180 static void assign_tarea_to_area(const tmp_area_t *tarea, gui_area_t *area) |
|
181 { |
|
182 *area = tarea->area; |
|
183 if (tarea->height != 0) { |
|
184 if (area->y1 == 0) |
|
185 area->y1 = area->y0 + tarea->height; |
|
186 else |
|
187 fprintf(stderr, "Warning: both y1 and height specified. 'height' ignored.\n"); |
|
188 } |
|
189 if (tarea->width != 0) { |
|
190 if (area->x1 == 0) |
|
191 area->x1 = area->x0 + tarea->width; |
|
192 else |
|
193 fprintf(stderr, "Warning: both x1 and width specified. 'width' ignored.\n"); |
|
194 } |
|
195 } |
|
196 |
|
197 /* this is not for the first image, since it is the background */ |
|
198 static int allocate_image_node(parser_data_t *pdata) |
|
199 { |
|
200 const int ret = pdata->last_vt_node->n_images; |
|
201 |
|
202 image_node_t* const node = (image_node_t*)qemu_mallocz(sizeof(image_node_t)); |
|
203 |
|
204 pdata->last_image_node->next = node; |
|
205 pdata->last_image_node = node; |
|
206 |
|
207 pdata->last_vt_node->n_images++; |
|
208 |
|
209 return ret; |
|
210 } |
|
211 |
|
212 static void add_new_vt(parser_data_t *pdata, const char *element, const char **attr) |
|
213 { |
|
214 vt_node_t *new_node; |
|
215 int attr_number = 0; |
|
216 image_node_t background_img; |
|
217 const char *value; |
|
218 |
|
219 new_node = (vt_node_t*)qemu_mallocz(sizeof(vt_node_t)); |
|
220 |
|
221 if (new_node == NULL) { |
|
222 fprintf(stderr, "Out of memory.\n"); |
|
223 pdata->result = OUT_OF_MEMORY; |
|
224 return; |
|
225 } |
|
226 |
|
227 if (pdata->gui_xml_tree->first_vt_node == NULL) |
|
228 pdata->gui_xml_tree->first_vt_node = new_node; |
|
229 else |
|
230 pdata->last_vt_node->next = new_node; |
|
231 |
|
232 pdata->last_vt_node = new_node; |
|
233 pdata->gui_xml_tree->n_vts++; |
|
234 |
|
235 memset(&background_img, 0, sizeof(image_node_t)); |
|
236 |
|
237 /* process attributes */ |
|
238 while (attr[attr_number] != NULL) { |
|
239 value = attr[attr_number + 1]; |
|
240 |
|
241 if (attribute_is(attr[attr_number], "background")) { |
|
242 strncpy(background_img.filename, value, sizeof(background_img.filename)-1); |
|
243 background_img.filename[sizeof(background_img.filename)-1] = 0; |
|
244 } else if (attribute_is(attr[attr_number], "width")) { |
|
245 SET_GUI_AREA_WIDTH(&background_img.area, atol(value)); |
|
246 } else if (attribute_is(attr[attr_number], "height")) { |
|
247 SET_GUI_AREA_HEIGHT(&background_img.area, atol(value)); |
|
248 } else { |
|
249 fprintf(stderr, "Unrecognized vt attribute '%s'.\n", attr[attr_number]); |
|
250 } |
|
251 |
|
252 attr_number += 2; |
|
253 } |
|
254 |
|
255 if (background_img.filename[0] != 0) { |
|
256 new_node->first_image_node = (image_node_t*)qemu_malloc(sizeof(image_node_t)); |
|
257 *(new_node->first_image_node) = background_img; |
|
258 new_node->n_images = 1; |
|
259 pdata->last_image_node = new_node->first_image_node; |
|
260 } else { |
|
261 fprintf(stderr, "Error: background image missing for vt.\n"); |
|
262 pdata->result = UNEXPECTED_EOF; |
|
263 } |
|
264 } |
|
265 |
|
266 static void add_new_button(parser_data_t *pdata, const char *element, const char **attr) |
|
267 { |
|
268 button_node_t *new_node = (button_node_t*)qemu_mallocz(sizeof(button_node_t)); |
|
269 tmp_area_t tarea; |
|
270 tmp_area_t tarea_pressed; |
|
271 image_node_t *pressed_img = NULL; |
|
272 const char *attribute, *value; |
|
273 int attr_number = 0; |
|
274 |
|
275 if (new_node == NULL) { |
|
276 fprintf(stderr, "Out of memory.\n"); |
|
277 pdata->result = OUT_OF_MEMORY; |
|
278 return; |
|
279 } |
|
280 |
|
281 if (pdata->last_vt_node->first_button_node == NULL) |
|
282 pdata->last_vt_node->first_button_node = new_node; |
|
283 else |
|
284 pdata->last_button_node->next = new_node; |
|
285 |
|
286 pdata->last_button_node = new_node; |
|
287 pdata->last_vt_node->n_buttons++; |
|
288 |
|
289 #define NOT_ASSIGNED -1 |
|
290 |
|
291 clear_tarea(&tarea); |
|
292 clear_tarea(&tarea_pressed); |
|
293 tarea_pressed.area.x0 = tarea_pressed.area.y0 = NOT_ASSIGNED; |
|
294 |
|
295 /* process attributes */ |
|
296 while (attr[attr_number] != NULL) { |
|
297 attribute = attr[attr_number]; |
|
298 value = attr[attr_number + 1]; |
|
299 |
|
300 if (attribute_is(attribute, "pressedimg")) { |
|
301 if (pressed_img == NULL) { |
|
302 new_node->pressed_img_id = allocate_image_node(pdata); |
|
303 pressed_img = pdata->last_image_node; |
|
304 } |
|
305 strncpy(pressed_img->filename, value, sizeof(pressed_img->filename)); |
|
306 pressed_img->filename[sizeof(pressed_img->filename)-1] = 0; |
|
307 } else if (attribute_is(attribute, "action")) { |
|
308 strncpy(new_node->action, value, 15); |
|
309 new_node->action[15] = 0; |
|
310 } else if (attribute_is(attribute, "parameter")) { |
|
311 strncpy(new_node->parameter, value, 31); |
|
312 new_node->parameter[31] = 0; |
|
313 } else if (assign_tarea_attribute(attribute, value, &tarea_pressed, "pressedimg_")) { |
|
314 if (pressed_img == NULL) { |
|
315 new_node->pressed_img_id = allocate_image_node(pdata); |
|
316 pressed_img = pdata->last_image_node; |
|
317 } |
|
318 } else if (!assign_tarea_attribute(attribute, value, &tarea, NULL)) { |
|
319 fprintf(stderr, "Warning: unrecognized button attribute '%s'\n", attribute); |
|
320 } |
|
321 |
|
322 attr_number += 2; |
|
323 } |
|
324 |
|
325 assign_tarea_to_area(&tarea, &new_node->area); |
|
326 |
|
327 if (pressed_img != NULL) { |
|
328 if (tarea_pressed.area.x0 == NOT_ASSIGNED) |
|
329 tarea_pressed.area.x0 = tarea.area.x0; |
|
330 |
|
331 if (tarea_pressed.area.y0 == NOT_ASSIGNED) |
|
332 tarea_pressed.area.y0 = tarea.area.y0; |
|
333 |
|
334 assign_tarea_to_area(&tarea_pressed, &pressed_img->area); |
|
335 } |
|
336 |
|
337 #undef NOT_ASSIGNED |
|
338 } |
|
339 |
|
340 static void add_new_parea(parser_data_t *pdata, const char *element, const char **attr) |
|
341 { |
|
342 pointerarea_node_t *new_node = (pointerarea_node_t*)qemu_mallocz(sizeof(pointerarea_node_t)); |
|
343 tmp_area_t tarea; |
|
344 const char *attribute, *value; |
|
345 int attr_number = 0; |
|
346 |
|
347 if (new_node == NULL) { |
|
348 fprintf(stderr, "Out of memory.\n"); |
|
349 pdata->result = OUT_OF_MEMORY; |
|
350 return; |
|
351 } |
|
352 |
|
353 if (pdata->last_vt_node->first_pointerarea_node == NULL) |
|
354 pdata->last_vt_node->first_pointerarea_node = new_node; |
|
355 else |
|
356 pdata->last_pointerarea_node->next = new_node; |
|
357 |
|
358 pdata->last_pointerarea_node = new_node; |
|
359 pdata->last_vt_node->n_pointerareas++; |
|
360 |
|
361 clear_tarea(&tarea); |
|
362 |
|
363 /* process attributes */ |
|
364 while (attr[attr_number] != NULL) { |
|
365 attribute = attr[attr_number]; |
|
366 value = attr[attr_number + 1]; |
|
367 |
|
368 if (attribute_is(attribute, "devid")) { |
|
369 strncpy(new_node->devid, value, sizeof(devid_t)-1); |
|
370 new_node->devid[sizeof(devid_t)-1] = 0; |
|
371 } else if (attribute_is(attribute, "grabonclick")) { |
|
372 assign_bool_value(value, &new_node->grab_on_click); |
|
373 } else if (attribute_is(attribute, "absolute")) { |
|
374 assign_bool_value(value, &new_node->absolute); |
|
375 } else if (attribute_is(attribute, "grabbingcursor")) { |
|
376 assign_bool_value(value, &new_node->show_cursor_while_grabbing); |
|
377 } else if (!assign_tarea_attribute(attribute, value, &tarea, NULL)) { |
|
378 fprintf(stderr, "Warning: unrecognized displayarea attribute '%s'\n", attribute); |
|
379 } |
|
380 |
|
381 attr_number += 2; |
|
382 } |
|
383 |
|
384 assign_tarea_to_area(&tarea, &new_node->area); |
|
385 } |
|
386 |
|
387 static void add_new_darea(parser_data_t *pdata, const char *element, const char **attr) |
|
388 { |
|
389 displayarea_node_t *new_node = (displayarea_node_t*)qemu_mallocz(sizeof(displayarea_node_t)); |
|
390 tmp_area_t tarea; |
|
391 const char *attribute, *value; |
|
392 int attr_number = 0; |
|
393 |
|
394 if (new_node == NULL) { |
|
395 fprintf(stderr, "Out of memory.\n"); |
|
396 pdata->result = OUT_OF_MEMORY; |
|
397 return; |
|
398 } |
|
399 |
|
400 if (pdata->last_vt_node->first_displayarea_node == NULL) |
|
401 pdata->last_vt_node->first_displayarea_node = new_node; |
|
402 else |
|
403 pdata->last_displayarea_node->next = new_node; |
|
404 |
|
405 pdata->last_displayarea_node = new_node; |
|
406 pdata->last_vt_node->n_displayareas++; |
|
407 |
|
408 clear_tarea(&tarea); |
|
409 |
|
410 /* process attributes */ |
|
411 while (attr[attr_number] != NULL) { |
|
412 attribute = attr[attr_number]; |
|
413 value = attr[attr_number + 1]; |
|
414 |
|
415 if (attribute_is(attribute, "devid")) { |
|
416 strncpy(new_node->devid, value, sizeof(devid_t)-1); |
|
417 new_node->devid[sizeof(devid_t)-1] = 0; |
|
418 } else if (!assign_tarea_attribute(attribute, value, &tarea, NULL)) { |
|
419 fprintf(stderr, "Warning: unrecognized displayarea attribute '%s'\n", attribute); |
|
420 } |
|
421 |
|
422 attr_number += 2; |
|
423 } |
|
424 |
|
425 assign_tarea_to_area(&tarea, &new_node->area); |
|
426 |
|
427 } |
|
428 |
|
429 START_HANDLER_DECL(waiting_gui_start) |
|
430 { |
|
431 if (strcmp(element, "gui") == 0) { |
|
432 pdata->state = WAITING_VT_START; |
|
433 } else { |
|
434 fprintf(stderr, "Unexpected element '%s' in line %ld; expected <gui>\n", |
|
435 element, |
|
436 XML_GetCurrentLineNumber(pdata->parser)); |
|
437 } |
|
438 } |
|
439 |
|
440 END_HANDLER_DECL(waiting_gui_start) |
|
441 { |
|
442 fprintf(stderr, "Unexpected closing element '%s' in line %ld\n", |
|
443 element, |
|
444 XML_GetCurrentLineNumber(pdata->parser)); |
|
445 } |
|
446 |
|
447 START_HANDLER_DECL(waiting_vt_start) |
|
448 { |
|
449 if (strcmp(element, "vt") == 0) { |
|
450 pdata->state = WAITING_VT_CONTENT; |
|
451 add_new_vt(pdata, element, attr); |
|
452 } else { |
|
453 fprintf(stderr, "Unexpected element '%s' in line %ld; expected <vt>\n", |
|
454 element, |
|
455 XML_GetCurrentLineNumber(pdata->parser)); |
|
456 } |
|
457 } |
|
458 |
|
459 END_HANDLER_DECL(waiting_vt_start) |
|
460 { |
|
461 if (strcmp(element, "gui") == 0) { |
|
462 /* OK! */ |
|
463 } else { |
|
464 fprintf(stderr, "Unexpected closing element '%s' in line %ld; expected </gui>\n", |
|
465 element, |
|
466 XML_GetCurrentLineNumber(pdata->parser)); |
|
467 } |
|
468 } |
|
469 |
|
470 START_HANDLER_DECL(waiting_vt_content) |
|
471 { |
|
472 if (strcmp(element, "button") == 0) { |
|
473 pdata->state = WAITING_BUTTON_END; |
|
474 add_new_button(pdata, element, attr); |
|
475 } else if (strcmp(element, "displayarea") == 0) { |
|
476 pdata->state = WAITING_DAREA_END; |
|
477 add_new_darea(pdata, element, attr); |
|
478 } else if (strcmp(element, "pointerarea") == 0) { |
|
479 pdata->state = WAITING_PAREA_END; |
|
480 add_new_parea(pdata, element, attr); |
|
481 } else { |
|
482 fprintf(stderr, "Unexpected element '%s' in line %ld; expected <button>, <displayarea>, or <pointerarea>\n", |
|
483 element, |
|
484 XML_GetCurrentLineNumber(pdata->parser)); |
|
485 } |
|
486 } |
|
487 |
|
488 END_HANDLER_DECL(waiting_vt_content) |
|
489 { |
|
490 if (strcmp(element, "vt") == 0) { |
|
491 pdata->state = WAITING_VT_START; |
|
492 } else { |
|
493 fprintf(stderr, "Unexpected closing element '%s' in line %ld; expected </vt>\n", |
|
494 element, |
|
495 XML_GetCurrentLineNumber(pdata->parser)); |
|
496 } |
|
497 } |
|
498 |
|
499 START_HANDLER_DECL(waiting_button_end) |
|
500 { |
|
501 fprintf(stderr, "Unexpected element '%s' in line %ld; expected closing </button>\n", |
|
502 element, |
|
503 XML_GetCurrentLineNumber(pdata->parser)); |
|
504 } |
|
505 |
|
506 END_HANDLER_DECL(waiting_button_end) |
|
507 { |
|
508 if (strcmp(element, "button") == 0) { |
|
509 pdata->state = WAITING_VT_CONTENT; |
|
510 } else { |
|
511 fprintf(stderr, "Unexpected closing element '%s' in line %ld; expected </button>\n", |
|
512 element, |
|
513 XML_GetCurrentLineNumber(pdata->parser)); |
|
514 } |
|
515 } |
|
516 |
|
517 START_HANDLER_DECL(waiting_parea_end) |
|
518 { |
|
519 fprintf(stderr, "Unexpected element '%s' in line %ld; expected closing </pointerarea>\n", |
|
520 element, |
|
521 XML_GetCurrentLineNumber(pdata->parser)); |
|
522 } |
|
523 |
|
524 END_HANDLER_DECL(waiting_parea_end) |
|
525 { |
|
526 if (strcmp(element, "pointerarea") == 0) { |
|
527 pdata->state = WAITING_VT_CONTENT; |
|
528 } else { |
|
529 fprintf(stderr, "Unexpected closing element '%s' in line %ld; expected </pointerarea>\n", |
|
530 element, |
|
531 XML_GetCurrentLineNumber(pdata->parser)); |
|
532 } |
|
533 } |
|
534 |
|
535 START_HANDLER_DECL(waiting_darea_end) |
|
536 { |
|
537 fprintf(stderr, "Unexpected element '%s' in line %ld; expected closing </displayarea>\n", |
|
538 element, |
|
539 XML_GetCurrentLineNumber(pdata->parser)); |
|
540 } |
|
541 |
|
542 END_HANDLER_DECL(waiting_darea_end) |
|
543 { |
|
544 if (strcmp(element, "displayarea") == 0) { |
|
545 pdata->state = WAITING_VT_CONTENT; |
|
546 } else { |
|
547 fprintf(stderr, "Unexpected closing element '%s' in line %ld; expected </displayarea>\n", |
|
548 element, |
|
549 XML_GetCurrentLineNumber(pdata->parser)); |
|
550 } |
|
551 } |
|
552 |
|
553 /**************************/ |
|
554 |
|
555 static void parser_start_hndl(void *data, const char *element, const char **attr) |
|
556 { |
|
557 parser_data_t *pdata = (parser_data_t*)data; |
|
558 |
|
559 state_handler[pdata->state].start(pdata, element, attr); |
|
560 } |
|
561 |
|
562 |
|
563 static void parser_end_hndl(void *data, const char *element) |
|
564 { |
|
565 parser_data_t *pdata = (parser_data_t*)data; |
|
566 |
|
567 state_handler[pdata->state].end(pdata, element); |
|
568 } |
|
569 |
|
570 static void test_start_hndl(void *data, const char *element, const char **attr) |
|
571 { |
|
572 fprintf(stderr, "start '%s'\n", element); |
|
573 } |
|
574 |
|
575 |
|
576 static void test_end_hndl(void *data, const char *element) |
|
577 { |
|
578 fprintf(stderr, "end '%s'\n", element); |
|
579 } |
|
580 |
|
581 parse_result_t parse_gui_xml(const char *xml_file, gui_xml_tree_t *gui_xml_tree) |
|
582 { |
|
583 parser_data_t parser_data; |
|
584 FILE *xml; |
|
585 int done = 0; |
|
586 char buffer[128]; |
|
587 |
|
588 parser_data.parser = XML_ParserCreate(NULL); |
|
589 parser_data.result = PARSE_OK; |
|
590 parser_data.state = WAITING_GUI_START; |
|
591 parser_data.gui_xml_tree = gui_xml_tree; |
|
592 |
|
593 memset(gui_xml_tree, 0, sizeof(gui_xml_tree_t)); |
|
594 |
|
595 if (parser_data.parser == NULL) { |
|
596 fprintf(stderr, "Couldn't allocate memory for parser\n"); |
|
597 return OUT_OF_MEMORY; |
|
598 } |
|
599 |
|
600 xml = fopen(xml_file, "r"); |
|
601 if (xml == NULL) { |
|
602 fprintf(stderr, "XML file not found\n"); |
|
603 XML_ParserFree(parser_data.parser); |
|
604 return FILE_NOT_FOUND; |
|
605 } |
|
606 |
|
607 XML_SetUserData(parser_data.parser, &parser_data); |
|
608 XML_SetElementHandler(parser_data.parser, parser_start_hndl, parser_end_hndl); |
|
609 |
|
610 do { |
|
611 if (fgets(buffer, sizeof(buffer), xml) == NULL) |
|
612 done = 1; |
|
613 else { |
|
614 done = feof(xml); |
|
615 if (! XML_Parse(parser_data.parser, buffer, strlen(buffer), done)) { |
|
616 fprintf(stderr, "Parse error at line %ld:\n%s\n", |
|
617 XML_GetCurrentLineNumber(parser_data.parser), |
|
618 XML_ErrorString(XML_GetErrorCode(parser_data.parser))); |
|
619 parser_data.result = UNEXPECTED_EOF; |
|
620 } |
|
621 } |
|
622 }while(!done && parser_data.result == PARSE_OK); |
|
623 |
|
624 if (done && !feof(xml)) { |
|
625 parser_data.result = UNEXPECTED_EOF; |
|
626 } |
|
627 |
|
628 fclose(xml); |
|
629 XML_ParserFree(parser_data.parser); |
|
630 |
|
631 return parser_data.result; |
|
632 } |
|
633 |