symbian-qemu-0.9.1-12/qemu-symbian-svp/gui_parser.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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