/[zanavi_public1]/navit/navit/xmlconfig.c
ZANavi

Contents of /navit/navit/xmlconfig.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 41 - (hide annotations) (download)
Tue Aug 11 18:50:37 2015 UTC (7 years, 5 months ago) by zoff99
File MIME type: text/plain
File size: 34027 byte(s)
many fixes, and new features
1 zoff99 2 /**
2 zoff99 30 * ZANavi, Zoff Android Navigation system.
3     * Copyright (C) 2011-2012 Zoff <zoff@zoff.cc>
4     *
5     * This program is free software; you can redistribute it and/or
6     * modify it under the terms of the GNU General Public License
7     * version 2 as published by the Free Software Foundation.
8     *
9     * This program is distributed in the hope that it will be useful,
10     * but WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     * GNU General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with this program; if not, write to the
16     * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     * Boston, MA 02110-1301, USA.
18     */
19    
20     /**
21 zoff99 2 * Navit, a modular navigation system.
22     * Copyright (C) 2005-2009 Navit Team
23     *
24     * This program is free software; you can redistribute it and/or
25     * modify it under the terms of the GNU General Public License
26     * version 2 as published by the Free Software Foundation.
27     *
28     * This program is distributed in the hope that it will be useful,
29     * but WITHOUT ANY WARRANTY; without even the implied warranty of
30     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31     * GNU General Public License for more details.
32     *
33     * You should have received a copy of the GNU General Public License
34     * along with this program; if not, write to the
35     * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
36     * Boston, MA 02110-1301, USA.
37     */
38    
39     /* see http://library.gnome.org/devel/glib/stable/glib-Simple-XML-Subset-Parser.html
40     * for details on how the xml file parser works.
41     */
42    
43     #include <stdlib.h>
44     #include <glib.h>
45     #include <glib/gprintf.h>
46     #include <string.h>
47     #include <ctype.h>
48     #include "debug.h"
49     #include "config.h"
50     #include "file.h"
51     #include "coord.h"
52     #include "layout.h"
53     #include "mapset.h"
54     #include "projection.h"
55     #include "map.h"
56     #include "navigation.h"
57     #include "navit.h"
58     #include "plugin.h"
59     #include "route.h"
60     #include "speech.h"
61     #include "track.h"
62     #include "vehicle.h"
63     #include "point.h"
64     #include "graphics.h"
65     #include "gui.h"
66     #include "osd.h"
67     #include "log.h"
68     #include "announcement.h"
69     #include "vehicleprofile.h"
70     #include "roadprofile.h"
71     #include "config_.h"
72     #include "xmlconfig.h"
73    
74     #ifdef HAVE_GLIB
75     #define ATTR_DISTANCE 1
76     const int xml_attr_distance=1;
77     #else
78     #include "ezxml.h"
79 zoff99 27 const int xml_attr_distance = 2;
80 zoff99 2 #define ATTR_DISTANCE 2
81     #define G_MARKUP_ERROR 0
82     #define G_MARKUP_ERROR_INVALID_CONTENT 0
83     #define G_MARKUP_ERROR_PARSE 0
84     #define G_MARKUP_ERROR_UNKNOWN_ELEMENT 0
85     typedef void * GMarkupParseContext;
86     #endif
87    
88 zoff99 27 struct xistate
89     {
90 zoff99 2 struct xistate *parent;
91     struct xistate *child;
92     const gchar *element;
93     const gchar **attribute_names;
94     const gchar **attribute_values;
95     };
96    
97 zoff99 27 struct xmldocument
98     {
99 zoff99 2 const gchar *href;
100     const gchar *xpointer;
101     gpointer user_data;
102     struct xistate *first;
103     struct xistate *last;
104     int active;
105     int level;
106     };
107    
108 zoff99 27 struct xmlstate
109     {
110 zoff99 2 const gchar **attribute_names;
111     const gchar **attribute_values;
112     struct xmlstate *parent;
113     struct attr element_attr;
114     const gchar *element;
115     xmlerror **error;
116     struct element_func *func;
117     struct object_func *object_func;
118     struct xmldocument *document;
119     };
120    
121 zoff99 27 struct attr_fixme
122     {
123 zoff99 2 char *element;
124     char **attr_fixme;
125     };
126    
127     static struct attr ** convert_to_attrs(struct xmlstate *state, struct attr_fixme *fixme)
128     {
129 zoff99 27 const gchar **attribute_name = state->attribute_names;
130     const gchar **attribute_value = state->attribute_values;
131 zoff99 2 const gchar *name;
132 zoff99 27 int count = 0;
133 zoff99 2 struct attr **ret;
134     static int fixme_count;
135    
136 zoff99 27 while (*attribute_name)
137     {
138 zoff99 2 count++;
139     attribute_name++;
140 zoff99 27 }ret=g_new(struct attr *, count+1);
141     attribute_name = state->attribute_names;
142     count = 0;
143     while (*attribute_name)
144     {
145     name = *attribute_name;
146     if (fixme)
147     {
148     char **attr_fixme = fixme->attr_fixme;
149     while (attr_fixme[0])
150     {
151     if (!strcmp(name, attr_fixme[0]))
152     {
153     name = attr_fixme[1];
154 zoff99 2 if (fixme_count++ < 10)
155 zoff99 27 {
156     //dbg(0,"Please change attribute '%s' to '%s' in <%s />\n",attr_fixme[0], attr_fixme[1], fixme->element);
157     }
158 zoff99 2 break;
159     }
160 zoff99 27 attr_fixme += 2;
161 zoff99 2 }
162     }
163 zoff99 27 ret[count] = attr_new_from_text(name, *attribute_value);
164 zoff99 2 if (ret[count])
165 zoff99 27 {
166 zoff99 2 count++;
167 zoff99 27 }
168     else if (strcmp(*attribute_name, "enabled") && strcmp(*attribute_name, "xmlns:xi"))
169     {
170     // dbg(0, "failed to create attribute '%s' with value '%s'\n", *attribute_name, *attribute_value);
171     }
172 zoff99 2 attribute_name++;
173     attribute_value++;
174     }
175 zoff99 27 ret[count] = NULL;
176     //dbg(1, "ret=%p\n", ret);
177 zoff99 2 return ret;
178     }
179    
180 zoff99 41 static const char *find_attribute(struct xmlstate *state, const char *attribute, int required)
181 zoff99 2 {
182 zoff99 27 const gchar **attribute_name = state->attribute_names;
183     const gchar **attribute_value = state->attribute_values;
184     while (*attribute_name)
185     {
186     if (!g_ascii_strcasecmp(attribute, *attribute_name))
187 zoff99 41 {
188 zoff99 2 return *attribute_value;
189 zoff99 41 }
190 zoff99 2 attribute_name++;
191     attribute_value++;
192     }
193 zoff99 41
194 zoff99 2 if (required)
195 zoff99 41 {
196 zoff99 27 g_set_error(state->error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "element '%s' is missing attribute '%s'", state->element, attribute);
197 zoff99 41 }
198    
199 zoff99 2 return NULL;
200     }
201    
202 zoff99 27 static int find_boolean(struct xmlstate *state, const char *attribute, int deflt, int required)
203 zoff99 2 {
204     const char *value;
205    
206 zoff99 27 value = find_attribute(state, attribute, required);
207     if (!value)
208 zoff99 2 return deflt;
209 zoff99 27 if (g_ascii_strcasecmp(value, "no") && g_ascii_strcasecmp(value, "0") && g_ascii_strcasecmp(value, "false"))
210 zoff99 2 return 1;
211     return 0;
212     }
213    
214     /**
215     * * Convert a string number to int
216     * *
217     * * @param val the string value to convert
218     * * @returns int value of converted string
219     * */
220 zoff99 27 static int convert_number(const char *val)
221 zoff99 2 {
222     if (val)
223 zoff99 27 return g_ascii_strtoull(val, NULL, 0);
224 zoff99 2 else
225     return 0;
226     }
227    
228 zoff99 27 static int xmlconfig_announce(struct xmlstate *state)
229 zoff99 2 {
230 zoff99 27 const char *type, *value;
231 zoff99 2 char key[32];
232     int level[3];
233     int i;
234     enum item_type itype;
235 zoff99 41 char *tok, *type_str, *str, *unit;
236 zoff99 2
237 zoff99 27 type = find_attribute(state, "type", 1);
238 zoff99 41
239 zoff99 27 if (!type)
240 zoff99 41 {
241 zoff99 2 return 0;
242 zoff99 41 }
243    
244     unit = find_attribute(state, "unit", 0);
245     if (unit)
246     {
247     // TODO: handle other unit types than "m" , maybe "s" (seconds) in the future
248     }
249    
250 zoff99 27 for (i = 0; i < 3; i++)
251     {
252     sprintf(key, "level%d", i);
253     value = find_attribute(state, key, 0);
254 zoff99 2 if (value)
255 zoff99 41 {
256 zoff99 27 level[i] = convert_number(value);
257 zoff99 41 }
258 zoff99 2 else
259 zoff99 41 {
260 zoff99 27 level[i] = -1;
261 zoff99 41 }
262 zoff99 2 }
263 zoff99 41
264 zoff99 27 type_str = g_strdup(type);
265 zoff99 41
266 zoff99 27 str = type_str;
267     while ((tok = strtok(str, ",")))
268     {
269     itype = item_from_name(tok);
270 zoff99 2 navigation_set_announce(state->parent->element_attr.u.data, itype, level);
271 zoff99 27 str = NULL;
272 zoff99 2 }
273 zoff99 41
274 zoff99 2 g_free(type_str);
275 zoff99 41
276 zoff99 2 return 1;
277     }
278     /**
279     * * Define the elements in our config
280     * *
281     * */
282    
283     #define NEW(x) (void *(*)(struct attr *, struct attr **))(x)
284     #define GET(x) (int (*)(void *, enum attr_type type, struct attr *attr, struct attr_iter *iter))(x)
285     #define ITERN(x) (struct attr_iter * (*)(void *))(x)
286     #define ITERD(x) (void (*)(struct attr_iter *iter))(x)
287     #define SET(x) (int (*)(void *, struct attr *attr))(x)
288     #define ADD(x) (int (*)(void *, struct attr *attr))(x)
289     #define REMOVE(x) (int (*)(void *, struct attr *attr))(x)
290     #define INIT(x) (int (*)(void *))(x)
291     #define DESTROY(x) (void (*)(void *))(x)
292    
293 zoff99 31 static struct object_func
294     object_funcs[] =
295 zoff99 34 { { attr_announcement, NEW(announcement_new), GET(announcement_get_attr), NULL, NULL, SET(announcement_set_attr), ADD(announcement_add_attr) },
296     { attr_arrows, NEW(arrows_new) },
297     { attr_circle, NEW(circle_new), NULL, NULL, NULL, NULL, ADD(element_add_attr) },
298     { attr_config, NEW(config_new), GET(config_get_attr), ITERN(config_attr_iter_new), ITERD(config_attr_iter_destroy), SET(config_set_attr), ADD(config_add_attr), REMOVE(config_remove_attr), NULL, DESTROY(config_destroy) },
299     { attr_coord, NEW(coord_new_from_attrs) },
300     { attr_cursor, NEW(cursor_new), NULL, NULL, NULL, NULL, ADD(cursor_add_attr) },
301     { attr_debug, NEW(debug_new) },
302     { attr_graphics, NEW(graphics_new) },
303     { attr_gui, NEW(gui_new), GET(gui_get_attr), NULL, NULL, SET(gui_set_attr), ADD(gui_add_attr) },
304     { attr_icon, NEW(icon_new), NULL, NULL, NULL, NULL, ADD(element_add_attr) },
305     { attr_image, NEW(image_new) },
306     { attr_itemgra, NEW(itemgra_new), NULL, NULL, NULL, NULL, ADD(itemgra_add_attr) },
307     { attr_layer, NEW(layer_new), NULL, NULL, NULL, NULL, ADD(layer_add_attr) },
308     { attr_layout, NEW(layout_new), NULL, NULL, NULL, NULL, ADD(layout_add_attr) },
309     { attr_log, NEW(log_new) },
310     { attr_map, NEW(map_new) },
311     { attr_mapset, NEW(mapset_new), NULL, NULL, NULL, NULL, ADD(mapset_add_attr_name) },
312     { attr_navigation, NEW(navigation_new), GET(navigation_get_attr) },
313     { attr_navit, NEW(navit_new), GET(navit_get_attr), ITERN(navit_attr_iter_new), ITERD(navit_attr_iter_destroy), SET(navit_set_attr), ADD(navit_add_attr), REMOVE(navit_remove_attr), INIT(navit_init), DESTROY(navit_destroy) },
314     { attr_osd, NEW(osd_new) },
315 zoff99 40 // { attr_plugins, NEW(plugins_new), NULL, NULL, NULL, NULL, NULL, NULL, INIT(plugins_init) },
316     // { attr_plugin, NEW(plugin_new) },
317 zoff99 34 { attr_polygon, NEW(polygon_new), NULL, NULL, NULL, NULL, ADD(element_add_attr) },
318     { attr_polyline, NEW(polyline_new), NULL, NULL, NULL, NULL, ADD(element_add_attr) },
319     { attr_roadprofile, NEW(roadprofile_new), GET(roadprofile_get_attr), NULL, NULL, SET(roadprofile_set_attr), ADD(roadprofile_add_attr) },
320     { attr_route, NEW(route_new), GET(route_get_attr), NULL, NULL, SET(route_set_attr), ADD(route_add_attr), REMOVE(route_remove_attr) },
321     { attr_speech, NEW(speech_new), GET(speech_get_attr), NULL, NULL, SET(speech_set_attr) },
322     { attr_text, NEW(text_new) },
323     { attr_tracking, NEW(tracking_new) },
324     { attr_vehicle, NEW(vehicle_new), GET(vehicle_get_attr), NULL, NULL, SET(vehicle_set_attr), ADD(vehicle_add_attr), REMOVE(vehicle_remove_attr) },
325     { attr_vehicleprofile, NEW(vehicleprofile_new), GET(vehicleprofile_get_attr), NULL, NULL, SET(vehicleprofile_set_attr), ADD(vehicleprofile_add_attr) },
326     { attr_maptile, NEW(maptile_new) },
327     };
328 zoff99 2
329     struct object_func *
330     object_func_lookup(enum attr_type type)
331     {
332     int i;
333 zoff99 27 for (i = 0; i < sizeof(object_funcs) / sizeof(struct object_func); i++)
334     {
335 zoff99 2 if (object_funcs[i].type == type)
336     return &object_funcs[i];
337     }
338     return NULL;
339     }
340    
341 zoff99 27 struct element_func
342     {
343 zoff99 2 char *name;
344     char *parent;
345     int (*func)(struct xmlstate *state);
346     enum attr_type type;
347     };
348     struct element_func *elements;
349    
350 zoff99 31 static char *attr_fixme_itemgra[] = { "type", "item_types", NULL, NULL, };
351 zoff99 2
352 zoff99 31 static char *attr_fixme_text[] = { "label_size", "text_size", NULL, NULL, };
353 zoff99 2
354 zoff99 31 static char *attr_fixme_circle[] = { "label_size", "text_size", NULL, NULL, };
355 zoff99 2
356 zoff99 31 static struct attr_fixme attr_fixmes[] = { { "item", attr_fixme_itemgra }, { "itemgra", attr_fixme_itemgra }, { "text", attr_fixme_text }, { "label", attr_fixme_text }, { "circle", attr_fixme_circle }, { NULL, NULL }, };
357 zoff99 2
358 zoff99 31 static char *element_fixmes[] = { "item", "itemgra", "label", "text", NULL, NULL, };
359 zoff99 2
360 zoff99 27 static void initStatic(void)
361     {
362 zoff99 34 elements=g_new0(struct element_func,41); //40 is a number of elements + ending NULL element
363 zoff99 2
364 zoff99 27 elements[0].name = "config";
365     elements[0].parent = NULL;
366     elements[0].func = NULL;
367     elements[0].type = attr_config;
368 zoff99 2
369 zoff99 27 elements[1].name = "announce";
370     elements[1].parent = "navigation";
371     elements[1].func = xmlconfig_announce;
372 zoff99 2
373 zoff99 27 elements[2].name = "speech";
374     elements[2].parent = "navit";
375     elements[2].func = NULL;
376     elements[2].type = attr_speech;
377 zoff99 2
378 zoff99 27 elements[3].name = "tracking";
379     elements[3].parent = "navit";
380     elements[3].func = NULL;
381     elements[3].type = attr_tracking;
382 zoff99 2
383 zoff99 27 elements[4].name = "route";
384     elements[4].parent = "navit";
385     elements[4].func = NULL;
386     elements[4].type = attr_route;
387 zoff99 2
388 zoff99 27 elements[5].name = "mapset";
389     elements[5].parent = "navit";
390     elements[5].func = NULL;
391     elements[5].type = attr_mapset;
392 zoff99 2
393 zoff99 27 elements[6].name = "map";
394     elements[6].parent = "mapset";
395     elements[6].func = NULL;
396     elements[6].type = attr_map;
397 zoff99 2
398 zoff99 27 elements[7].name = "debug";
399     elements[7].parent = "config";
400     elements[7].func = NULL;
401     elements[7].type = attr_debug;
402 zoff99 2
403 zoff99 27 elements[8].name = "osd";
404     elements[8].parent = "navit";
405     elements[8].func = NULL;
406     elements[8].type = attr_osd;
407 zoff99 2
408 zoff99 27 elements[9].name = "navigation";
409     elements[9].parent = "navit";
410     elements[9].func = NULL;
411     elements[9].type = attr_navigation;
412 zoff99 2
413 zoff99 27 elements[10].name = "navit";
414     elements[10].parent = "config";
415     elements[10].func = NULL;
416     elements[10].type = attr_navit;
417 zoff99 2
418 zoff99 27 elements[11].name = "graphics";
419     elements[11].parent = "navit";
420     elements[11].func = NULL;
421     elements[11].type = attr_graphics;
422 zoff99 2
423 zoff99 27 elements[12].name = "gui";
424     elements[12].parent = "navit";
425     elements[12].func = NULL;
426     elements[12].type = attr_gui;
427 zoff99 2
428 zoff99 27 elements[13].name = "layout";
429     elements[13].parent = "navit";
430     elements[13].func = NULL;
431     elements[13].type = attr_layout;
432 zoff99 2
433 zoff99 27 elements[14].name = "cursor";
434     elements[14].parent = "layout";
435     elements[14].func = NULL;
436     elements[14].type = attr_cursor;
437 zoff99 2
438 zoff99 27 elements[15].name = "layer";
439     elements[15].parent = "layout";
440     elements[15].func = NULL;
441     elements[15].type = attr_layer;
442 zoff99 2
443 zoff99 27 elements[16].name = "itemgra";
444     elements[16].parent = "layer";
445     elements[16].func = NULL;
446     elements[16].type = attr_itemgra;
447 zoff99 2
448 zoff99 27 elements[17].name = "circle";
449     elements[17].parent = "itemgra";
450     elements[17].func = NULL;
451     elements[17].type = attr_circle;
452 zoff99 2
453 zoff99 27 elements[18].name = "coord";
454     elements[18].parent = "circle";
455     elements[18].func = NULL;
456     elements[18].type = attr_coord;
457 zoff99 2
458 zoff99 27 elements[19].name = "icon";
459     elements[19].parent = "itemgra";
460     elements[19].func = NULL;
461     elements[19].type = attr_icon;
462 zoff99 2
463 zoff99 27 elements[20].name = "coord";
464     elements[20].parent = "icon";
465     elements[20].func = NULL;
466     elements[20].type = attr_coord;
467 zoff99 2
468 zoff99 27 elements[21].name = "image";
469     elements[21].parent = "itemgra";
470     elements[21].func = NULL;
471     elements[21].type = attr_image;
472 zoff99 2
473 zoff99 27 elements[22].name = "text";
474     elements[22].parent = "itemgra";
475     elements[22].func = NULL;
476     elements[22].type = attr_text;
477 zoff99 2
478 zoff99 27 elements[23].name = "polygon";
479     elements[23].parent = "itemgra";
480     elements[23].func = NULL;
481     elements[23].type = attr_polygon;
482 zoff99 2
483 zoff99 27 elements[24].name = "coord";
484     elements[24].parent = "polygon";
485     elements[24].func = NULL;
486     elements[24].type = attr_coord;
487 zoff99 2
488 zoff99 27 elements[25].name = "polyline";
489     elements[25].parent = "itemgra";
490     elements[25].func = NULL;
491     elements[25].type = attr_polyline;
492 zoff99 2
493 zoff99 27 elements[26].name = "coord";
494     elements[26].parent = "polyline";
495     elements[26].func = NULL;
496     elements[26].type = attr_coord;
497 zoff99 2
498 zoff99 27 elements[27].name = "arrows";
499     elements[27].parent = "itemgra";
500     elements[27].func = NULL;
501     elements[27].type = attr_arrows;
502 zoff99 2
503 zoff99 27 elements[28].name = "vehicle";
504     elements[28].parent = "navit";
505     elements[28].func = NULL;
506     elements[28].type = attr_vehicle;
507 zoff99 2
508 zoff99 27 elements[29].name = "vehicleprofile";
509     elements[29].parent = "navit";
510     elements[29].func = NULL;
511     elements[29].type = attr_vehicleprofile;
512 zoff99 2
513 zoff99 27 elements[30].name = "roadprofile";
514     elements[30].parent = "vehicleprofile";
515     elements[30].func = NULL;
516     elements[30].type = attr_roadprofile;
517 zoff99 2
518 zoff99 27 elements[31].name = "announcement";
519     elements[31].parent = "roadprofile";
520     elements[31].func = NULL;
521     elements[31].type = attr_announcement;
522 zoff99 2
523 zoff99 27 elements[32].name = "cursor";
524     elements[32].parent = "vehicle";
525     elements[32].func = NULL;
526     elements[32].type = attr_cursor;
527 zoff99 2
528 zoff99 27 elements[33].name = "itemgra";
529     elements[33].parent = "cursor";
530     elements[33].func = NULL;
531     elements[33].type = attr_itemgra;
532 zoff99 2
533 zoff99 27 elements[34].name = "log";
534     elements[34].parent = "vehicle";
535     elements[34].func = NULL;
536     elements[34].type = attr_log;
537 zoff99 2
538 zoff99 27 elements[35].name = "log";
539     elements[35].parent = "navit";
540     elements[35].func = NULL;
541     elements[35].type = attr_log;
542 zoff99 2
543 zoff99 27 elements[36].name = "plugins";
544     elements[36].parent = "config";
545     elements[36].func = NULL;
546     elements[36].type = attr_plugins;
547 zoff99 2
548 zoff99 27 elements[37].name = "plugin";
549     elements[37].parent = "plugins";
550     elements[37].func = NULL;
551     elements[37].type = attr_plugin;
552 zoff99 34
553     elements[38].name = "maptile";
554     elements[38].parent = "itemgra";
555     elements[38].func = NULL;
556     elements[38].type = attr_maptile;
557    
558 zoff99 2 }
559    
560     /**
561     * * Parse the opening tag of a config element
562     * *
563     * * @param context document parse context
564     * * @param element_name the current tag name
565     * * @param attribute_names ptr to return the set of attribute names
566     * * @param attribute_values ptr return the set of attribute values
567     * * @param user_data ptr to xmlstate structure
568     * * @param error ptr return error context
569     * * @returns nothing
570     * */
571    
572 zoff99 27 static void start_element(GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer user_data, xmlerror **error)
573 zoff99 2 {
574 zoff99 27 struct xmlstate *new = NULL, **parent = user_data;
575     struct element_func *e = elements, *func = NULL;
576     struct attr_fixme *attr_fixme = attr_fixmes;
577     char **element_fixme = element_fixmes;
578     int found = 0;
579 zoff99 2 static int fixme_count;
580 zoff99 27 const char *parent_name = NULL;
581     char *s, *sep = "", *possible_parents;
582 zoff99 2 struct attr *parent_attr;
583 zoff99 27 // dbg(2, "name='%s' parent='%s'\n", element_name, *parent ? (*parent)->element : NULL);
584 zoff99 2
585 zoff99 27 if (!strcmp(element_name, "xml"))
586 zoff99 2 return;
587     /* determine if we have to fix any attributes */
588 zoff99 27 while (attr_fixme[0].element)
589     {
590     if (!strcmp(element_name, attr_fixme[0].element))
591 zoff99 2 break;
592     attr_fixme++;
593     }
594     if (!attr_fixme[0].element)
595 zoff99 27 attr_fixme = NULL;
596 zoff99 2
597     /* tell user to fix deprecated element names */
598 zoff99 27 while (element_fixme[0])
599     {
600     if (!strcmp(element_name, element_fixme[0]))
601     {
602     element_name = element_fixme[1];
603 zoff99 2 if (fixme_count++ < 10)
604 zoff99 27 {
605     // dbg(0, "Please change <%s /> to <%s /> in config file\n",element_fixme[0], element_fixme[1]);
606     }
607 zoff99 2 }
608 zoff99 27 element_fixme += 2;
609 zoff99 2 }
610     /* validate that this element is valid
611     * and that the element has a valid parent */
612 zoff99 27 possible_parents = g_strdup("");
613 zoff99 2 if (*parent)
614 zoff99 27 parent_name = (*parent)->element;
615     while (e->name)
616     {
617     if (!g_ascii_strcasecmp(element_name, e->name))
618     {
619     found = 1;
620     s = g_strconcat(possible_parents, sep, e->parent, NULL);
621 zoff99 2 g_free(possible_parents);
622 zoff99 27 possible_parents = s;
623     sep = ",";
624     if ((parent_name && e->parent && !g_ascii_strcasecmp(parent_name, e->parent)) || (!parent_name && !e->parent))
625     func = e;
626 zoff99 2 }
627     e++;
628     }
629 zoff99 27 if (!found)
630     {
631     g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, "Unknown element '%s'", element_name);
632 zoff99 2 g_free(possible_parents);
633     return;
634     }
635 zoff99 27 if (!func)
636     {
637 zoff99 31 g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "Element '%s' within unexpected context '%s'. Expected '%s'%s", element_name, parent_name, possible_parents, !strcmp(possible_parents, "config") ? "\nPlease add <config> </config> tags at the beginning/end of your navit.xml" : "");
638 zoff99 2 g_free(possible_parents);
639     return;
640     }
641     g_free(possible_parents);
642    
643     new=g_new(struct xmlstate, 1);
644 zoff99 27 new->attribute_names = attribute_names;
645     new->attribute_values = attribute_values;
646     new->parent = *parent;
647     new->element_attr.u.data = NULL;
648     new->element = element_name;
649     new->error = error;
650     new->func = func;
651     new->object_func = NULL;
652     *parent = new;
653 zoff99 2 if (!find_boolean(new, "enabled", 1, 0))
654     return;
655     if (new->parent && !new->parent->element_attr.u.data)
656     return;
657 zoff99 27 if (func->func)
658     {
659     if (!func->func(new))
660     {
661 zoff99 2 return;
662     }
663 zoff99 27 }
664     else
665     {
666 zoff99 2 struct attr **attrs;
667    
668 zoff99 27 new->object_func = object_func_lookup(func->type);
669     if (!new->object_func)
670 zoff99 2 return;
671 zoff99 27 attrs = convert_to_attrs(new, attr_fixme);
672     new->element_attr.type = attr_none;
673 zoff99 2 if (!new->parent || new->parent->element_attr.type == attr_none)
674 zoff99 27 parent_attr = NULL;
675 zoff99 2 else
676 zoff99 27 parent_attr = &new->parent->element_attr;
677 zoff99 2 new->element_attr.u.data = new->object_func->create(parent_attr, attrs);
678 zoff99 27 if (!new->element_attr.u.data)
679 zoff99 2 return;
680 zoff99 27 new->element_attr.type = attr_from_name(element_name);
681 zoff99 2 if (new->element_attr.type == attr_none)
682 zoff99 27 {
683     // dbg(0, "failed to create object of type '%s'\n", element_name);
684     }
685 zoff99 2 if (new->parent && new->parent->object_func && new->parent->object_func->add_attr)
686     new->parent->object_func->add_attr(new->parent->element_attr.u.data, &new->element_attr);
687     }
688     return;
689     }
690    
691     /* Called for close tags </foo> */
692 zoff99 27 static void end_element(GMarkupParseContext *context, const gchar *element_name, gpointer user_data, xmlerror **error)
693 zoff99 2 {
694     struct xmlstate *curr, **state = user_data;
695    
696 zoff99 27 if (!strcmp(element_name, "xml"))
697     {
698 zoff99 2 return;
699 zoff99 27 }
700     // dbg(2, "name='%s'\n", element_name);
701     curr = *state;
702 zoff99 2 if (curr->object_func && curr->object_func->init)
703     curr->object_func->init(curr->element_attr.u.data);
704 zoff99 27 *state = curr->parent;
705 zoff99 2 g_free(curr);
706     }
707    
708     static gboolean parse_file(struct xmldocument *document, xmlerror **error);
709    
710 zoff99 27 static void xinclude(GMarkupParseContext *context, const gchar **attribute_names, const gchar **attribute_values, struct xmldocument *doc_old, xmlerror **error)
711 zoff99 2 {
712     struct xmldocument doc_new;
713     struct file_wordexp *we;
714 zoff99 27 int i, count;
715     const char *href = NULL;
716 zoff99 2 char **we_files;
717    
718 zoff99 27 if (doc_old->level >= 16)
719     {
720     g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "xi:include recursion too deep");
721 zoff99 2 return;
722     }
723     memset(&doc_new, 0, sizeof(doc_new));
724 zoff99 27 i = 0;
725     while (attribute_names[i])
726     {
727     if (!g_ascii_strcasecmp("href", attribute_names[i]))
728     {
729 zoff99 2 if (!href)
730 zoff99 27 href = attribute_values[i];
731     else
732     {
733     g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "xi:include has more than one href");
734 zoff99 2 return;
735     }
736 zoff99 27 }
737     else if (!g_ascii_strcasecmp("xpointer", attribute_names[i]))
738     {
739 zoff99 2 if (!doc_new.xpointer)
740 zoff99 27 doc_new.xpointer = attribute_values[i];
741     else
742     {
743     g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "xi:include has more than one xpointer");
744 zoff99 2 return;
745     }
746 zoff99 27 }
747     else
748     {
749     g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "xi:include has invalid attributes");
750 zoff99 2 return;
751     }
752     i++;
753     }
754 zoff99 27 if (!doc_new.xpointer && !href)
755     {
756     g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "xi:include has neither href nor xpointer");
757 zoff99 2 return;
758     }
759 zoff99 27 doc_new.level = doc_old->level + 1;
760     doc_new.user_data = doc_old->user_data;
761     if (!href)
762     {
763     //dbg(1, "no href, using '%s'\n", doc_old->href);
764     doc_new.href = doc_old->href;
765     if (file_exists(doc_new.href))
766     {
767     parse_file(&doc_new, error);
768 zoff99 2 }
769 zoff99 27 else
770     {
771     //dbg(0, "Unable to include %s\n", doc_new.href);
772     }
773     }
774     else
775     {
776     //dbg(1, "expanding '%s'\n", href);
777     we = file_wordexp_new(href);
778     we_files = file_wordexp_get_array(we);
779     count = file_wordexp_get_count(we);
780     //dbg(1, "%d results\n", count);
781     if (file_exists(we_files[0]))
782     {
783     for (i = 0; i < count; i++)
784     {
785     //dbg(1, "result[%d]='%s'\n", i, we_files[i]);
786     doc_new.href = we_files[i];
787 zoff99 2 parse_file(&doc_new, error);
788     }
789     }
790 zoff99 27 else
791     {
792     //dbg(0, "Unable to include %s\n", we_files[0]);
793     }
794 zoff99 2 file_wordexp_destroy(we);
795    
796     }
797    
798     }
799    
800 zoff99 27 static int strncmp_len(const char *s1, int s1len, const char *s2)
801 zoff99 2 {
802     int ret;
803     #if 0
804     char c[s1len+1];
805     strncpy(c, s1, s1len);
806     c[s1len]='\0';
807 zoff99 27 //dbg(0,"'%s' vs '%s'\n", c, s2);
808 zoff99 2 #endif
809    
810 zoff99 27 ret = strncmp(s1, s2, s1len);
811 zoff99 2 if (ret)
812     return ret;
813 zoff99 27 return strlen(s2) - s1len;
814 zoff99 2 }
815    
816 zoff99 27 static int xpointer_value(const char *test, int len, struct xistate *elem, const char **out, int out_len)
817 zoff99 2 {
818 zoff99 27 int i, ret = 0;
819     if (len <= 0 || out_len <= 0)
820     {
821 zoff99 2 return 0;
822     }
823 zoff99 27 if (!(strncmp_len(test, len, "name(.)")))
824     {
825     out[0] = elem->element;
826 zoff99 2 return 1;
827     }
828 zoff99 27 if (test[0] == '@')
829     {
830     i = 0;
831     while (elem->attribute_names[i] && out_len > 0)
832     {
833     if (!strncmp_len(test + 1, len - 1, elem->attribute_names[i]))
834     {
835     out[ret++] = elem->attribute_values[i];
836 zoff99 2 out_len--;
837     }
838     i++;
839     }
840     return ret;
841     }
842     return 0;
843     }
844    
845 zoff99 27 static int xpointer_test(const char *test, int len, struct xistate *elem)
846 zoff99 2 {
847 zoff99 27 int eq, i, count, vlen, cond_req = 1, cond = 0;
848 zoff99 2 char c;
849     const char *tmp[16];
850     #if 0
851     char test2[len+1];
852    
853     strncpy(test2, test, len);
854     test2[len]='\0';
855 zoff99 27 //dbg(0,"%s\n", test2);
856 zoff99 2 #endif
857     if (!len)
858     return 0;
859 zoff99 27 c = test[len - 1];
860 zoff99 2 if (c != '\'' && c != '"')
861     return 0;
862 zoff99 27 eq = strcspn(test, "=");
863     if (eq >= len || test[eq + 1] != c)
864 zoff99 2 return 0;
865 zoff99 27 vlen = eq;
866     if (eq > 0 && test[eq - 1] == '!')
867     {
868     cond_req = 0;
869 zoff99 2 vlen--;
870     }
871 zoff99 27 count = xpointer_value(test, vlen, elem, tmp, 16);
872     for (i = 0; i < count; i++)
873     {
874     if (!strncmp_len(test + eq + 2, len - eq - 3, tmp[i]))
875     cond = 1;
876 zoff99 2 }
877     if (cond == cond_req)
878     return 1;
879     return 0;
880     }
881    
882 zoff99 27 static int xpointer_element_match(const char *xpointer, int len, struct xistate *elem)
883 zoff99 2 {
884 zoff99 27 int start, tlen, tlen2;
885 zoff99 2 #if 0
886     char test2[len+1];
887    
888     strncpy(test2, xpointer, len);
889     test2[len]='\0';
890 zoff99 27 //dbg(0,"%s\n", test2);
891 zoff99 2 #endif
892 zoff99 27 start = strcspn(xpointer, "[");
893 zoff99 2 if (start > len)
894 zoff99 27 start = len;
895 zoff99 2 if (strncmp_len(xpointer, start, elem->element) && (start != 1 || xpointer[0] != '*'))
896     return 0;
897     if (start == len)
898     return 1;
899 zoff99 27 if (xpointer[len - 1] != ']')
900 zoff99 2 return 0;
901 zoff99 27 tlen = len - start - 2;
902     for (;;)
903     {
904 zoff99 2 start++;
905 zoff99 27 tlen2 = strcspn(xpointer + start, "]");
906 zoff99 2 if (start + tlen2 > len)
907     return 1;
908 zoff99 27 if (!xpointer_test(xpointer + start, tlen2, elem))
909 zoff99 2 return 0;
910 zoff99 27 start += tlen2 + 1;
911 zoff99 2 }
912     }
913    
914 zoff99 27 static int xpointer_xpointer_match(const char *xpointer, int len, struct xistate *first)
915 zoff99 2 {
916     const char *c;
917     int s;
918 zoff99 27 //dbg(2, "%s\n", xpointer);
919 zoff99 2 if (xpointer[0] != '/')
920     return 0;
921 zoff99 27 c = xpointer + 1;
922 zoff99 2 len--;
923 zoff99 27 do
924     {
925     s = strcspn(c, "/");
926 zoff99 2 if (s > len)
927 zoff99 27 s = len;
928     if (!xpointer_element_match(c, s, first))
929 zoff99 2 return 0;
930 zoff99 27 first = first->child;
931     c += s + 1;
932     len -= s + 1;
933     }
934     while (len > 0 && first);
935 zoff99 2 if (len > 0)
936     return 0;
937     return 1;
938     }
939    
940 zoff99 27 static int xpointer_match(const char *xpointer, struct xistate *first)
941 zoff99 2 {
942 zoff99 27 char *prefix = "xpointer(";
943 zoff99 2 int len;
944 zoff99 27 if (!xpointer)
945 zoff99 2 return 1;
946 zoff99 27 len = strlen(xpointer);
947     if (strncmp(xpointer, prefix, strlen(prefix)))
948 zoff99 2 return 0;
949 zoff99 27 if (xpointer[len - 1] != ')')
950 zoff99 2 return 0;
951 zoff99 27 return xpointer_xpointer_match(xpointer + strlen(prefix), len - strlen(prefix) - 1, first);
952 zoff99 2
953     }
954    
955 zoff99 27 static void xi_start_element(GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer user_data, xmlerror **error)
956 zoff99 2 {
957 zoff99 27 struct xmldocument *doc = user_data;
958 zoff99 2 struct xistate *xistate;
959 zoff99 27 int i, count = 0;
960     while (attribute_names[count++ * ATTR_DISTANCE])
961     ;xistate=g_new0(struct xistate, 1);
962     xistate->element = element_name;
963 zoff99 2 xistate->attribute_names=g_new0(const char *, count);
964     xistate->attribute_values=g_new0(const char *, count);
965 zoff99 27 for (i = 0; i < count; i++)
966     {
967     if (attribute_names[i * ATTR_DISTANCE] && attribute_values[i * ATTR_DISTANCE])
968     {
969     xistate->attribute_names[i] = g_strdup(attribute_names[i * ATTR_DISTANCE]);
970     xistate->attribute_values[i] = g_strdup(attribute_values[i * ATTR_DISTANCE]);
971 zoff99 2 }
972     }
973 zoff99 27 xistate->parent = doc->last;
974 zoff99 2
975 zoff99 27 if (doc->last)
976     {
977     doc->last->child = xistate;
978     }
979     else
980     doc->first = xistate;
981     doc->last = xistate;
982     if (doc->active > 0 || xpointer_match(doc->xpointer, doc->first))
983     {
984     if (!g_ascii_strcasecmp("xi:include", element_name))
985     {
986 zoff99 2 xinclude(context, xistate->attribute_names, xistate->attribute_values, doc, error);
987     return;
988     }
989     start_element(context, element_name, xistate->attribute_names, xistate->attribute_values, doc->user_data, error);
990     doc->active++;
991     }
992    
993     }
994     /**
995     * * Reached closing tag of a config element
996     * *
997     * * @param context
998     * * @param element name
999     * * @param user_data ptr to xmldocument
1000     * * @param error ptr to struct for error information
1001     * * @returns nothing
1002     * */
1003    
1004 zoff99 27 static void xi_end_element(GMarkupParseContext *context, const gchar *element_name, gpointer user_data, xmlerror **error)
1005 zoff99 2 {
1006 zoff99 27 struct xmldocument *doc = user_data;
1007     struct xistate *xistate = doc->last;
1008     int i = 0;
1009     doc->last = doc->last->parent;
1010     if (!doc->last)
1011     doc->first = NULL;
1012 zoff99 2 else
1013 zoff99 27 doc->last->child = NULL;
1014     if (doc->active > 0)
1015     {
1016     if (!g_ascii_strcasecmp("xi:include", element_name))
1017     {
1018 zoff99 2 return;
1019     }
1020     end_element(context, element_name, doc->user_data, error);
1021     doc->active--;
1022     }
1023 zoff99 27 while (xistate->attribute_names[i])
1024     {
1025     g_free((char *) (xistate->attribute_names[i]));
1026     g_free((char *) (xistate->attribute_values[i]));
1027 zoff99 2 i++;
1028     }
1029     g_free(xistate->attribute_names);
1030     g_free(xistate->attribute_values);
1031     g_free(xistate);
1032     }
1033    
1034     /* Called for character data */
1035     /* text is not nul-terminated */
1036 zoff99 27 static void xi_text(GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, xmlerror **error)
1037 zoff99 2 {
1038 zoff99 27 struct xmldocument *doc = user_data;
1039 zoff99 2 int i;
1040 zoff99 27 if (doc->active)
1041     {
1042     for (i = 0; i < text_len; i++)
1043     {
1044     if (!isspace(text[i]))
1045     {
1046     struct xmldocument *doc = user_data;
1047 zoff99 2 struct xmlstate *curr, **state = doc->user_data;
1048     struct attr attr;
1049 zoff99 27 char *text_dup = malloc(text_len + 1);
1050 zoff99 2
1051 zoff99 27 curr = *state;
1052 zoff99 2 strncpy(text_dup, text, text_len);
1053 zoff99 27 text_dup[text_len] = '\0';
1054     attr.type = attr_xml_text;
1055     attr.u.str = text_dup;
1056 zoff99 2 if (curr->object_func && curr->object_func->add_attr && curr->element_attr.u.data)
1057     curr->object_func->add_attr(curr->element_attr.u.data, &attr);
1058     free(text_dup);
1059     return;
1060     }
1061     }
1062     }
1063     }
1064    
1065     #ifndef HAVE_GLIB
1066 zoff99 27 static void parse_node_text(ezxml_t node, void *data, void(*start)(void *, const char *, const char **, const char **, void *, void *), void(*end)(void *, const char *, void *, void *), void(*text)(void *, const char *, int, void *, void *))
1067 zoff99 2 {
1068 zoff99 27 while (node)
1069     {
1070 zoff99 2 if (start)
1071 zoff99 27 start(NULL, node->name, (const char **) node->attr, (const char **) (node->attr + 1), data, NULL);
1072 zoff99 2 if (text && node->txt)
1073     text(NULL, node->txt, strlen(node->txt), data, NULL);
1074     if (node->child)
1075     parse_node_text(node->child, data, start, end, text);
1076     if (end)
1077     end(NULL, node->name, data, NULL);
1078 zoff99 27 node = node->ordered;
1079 zoff99 2 }
1080     }
1081     #endif
1082    
1083 zoff99 27 void xml_parse_text(const char *document, void *data, void(*start)(void *, const char *, const char **, const char **, void *, void *), void(*end)(void *, const char *, void *, void *), void(*text)(void *, const char *, int, void *, void *))
1084 zoff99 2 {
1085     #ifdef HAVE_GLIB
1086 zoff99 27 GMarkupParser parser =
1087     { start, end, text, NULL, NULL};
1088 zoff99 2 GMarkupParseContext *context;
1089     gboolean result;
1090    
1091     context = g_markup_parse_context_new (&parser, 0, data, NULL);
1092     result = g_markup_parse_context_parse (context, document, strlen(document), NULL);
1093     g_markup_parse_context_free (context);
1094     #else
1095 zoff99 27 char *str = g_strdup(document);
1096 zoff99 2 ezxml_t root = ezxml_parse_str(str, strlen(str));
1097     if (!root)
1098     return;
1099     parse_node_text(root, data, start, end, text);
1100     ezxml_free(root);
1101     g_free(str);
1102     #endif
1103     }
1104    
1105     #ifdef HAVE_GLIB
1106    
1107 zoff99 27 static const GMarkupParser parser =
1108     {
1109 zoff99 2 xi_start_element,
1110     xi_end_element,
1111     xi_text,
1112     NULL,
1113     NULL
1114     };
1115     /**
1116     * * Parse the contents of the configuration file
1117     * *
1118     * * @param document struct holding info about the config file
1119     * * @param error info on any errors detected
1120     * * @returns boolean TRUE or FALSE
1121     * */
1122    
1123     static gboolean
1124     parse_file(struct xmldocument *document, xmlerror **error)
1125     {
1126 zoff99 30 //dbg(0,"EEnter\n");
1127    
1128 zoff99 2 GMarkupParseContext *context;
1129     gchar *contents, *message;
1130     gsize len;
1131     gint line, chr;
1132     gboolean result;
1133     char *xmldir,*newxmldir,*xmlfile,*newxmlfile,*sep;
1134    
1135 zoff99 27 //dbg(1,"enter filename='%s'\n", document->href);
1136 zoff99 2 #if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 12
1137     #define G_MARKUP_TREAT_CDATA_AS_TEXT 0
1138     #endif
1139    
1140 zoff99 30 context = g_markup_parse_context_new(&parser, G_MARKUP_TREAT_CDATA_AS_TEXT, document, NULL);
1141    
1142     if (!g_file_get_contents(document->href, &contents, &len, error))
1143 zoff99 27 {
1144 zoff99 30 g_markup_parse_context_free(context);
1145 zoff99 2 return FALSE;
1146     }
1147     xmldir=getenv("XMLDIR");
1148     xmlfile=getenv("XMLFILE");
1149     newxmlfile=g_strdup(document->href);
1150     newxmldir=g_strdup(document->href);
1151 zoff99 27 if ((sep=strrchr(newxmldir,'/')))
1152     *sep='\0';
1153     else
1154     {
1155 zoff99 2 g_free(newxmldir);
1156     newxmldir=g_strdup(".");
1157     }
1158     setenv("XMLDIR",newxmldir,1);
1159     setenv("XMLFILE",newxmlfile,1);
1160     document->active=document->xpointer ? 0:1;
1161     document->first=NULL;
1162     document->last=NULL;
1163 zoff99 30 result = g_markup_parse_context_parse(context, contents, len, error);
1164 zoff99 27 if (!result && error && *error)
1165     {
1166 zoff99 2 g_markup_parse_context_get_position(context, &line, &chr);
1167     message=g_strdup_printf("%s at line %d, char %d\n", (*error)->message, line, chr);
1168     g_free((*error)->message);
1169     (*error)->message=message;
1170     }
1171 zoff99 30 g_markup_parse_context_free(context);
1172 zoff99 2 g_free (contents);
1173     if (xmldir)
1174 zoff99 27 setenv("XMLDIR",xmldir,1);
1175 zoff99 2 else
1176     #ifndef __MINGW32__
1177 zoff99 27 unsetenv("XMLDIR");
1178 zoff99 2 #else
1179 zoff99 27 putenv("XMLDIR=");
1180 zoff99 2 #endif /* __MINGW32__ */
1181     if (xmlfile)
1182 zoff99 27 setenv("XMLFILE",xmlfile,1);
1183 zoff99 2 else
1184     #ifndef __MINGW32__
1185 zoff99 27 unsetenv("XMLFILE");
1186 zoff99 2 #else
1187 zoff99 27 putenv("XMLFILE=");
1188 zoff99 2 #endif /* __MINGW32__ */
1189     g_free(newxmldir);
1190     g_free(newxmlfile);
1191 zoff99 27 //dbg(1,"return %d\n", result);
1192 zoff99 2
1193     return result;
1194     }
1195     #else
1196 zoff99 30
1197     // this is used on android!!!!
1198     // this is used on android!!!!
1199     // this is used on android!!!!
1200 zoff99 27 static void parse_node(struct xmldocument *document, ezxml_t node)
1201 zoff99 2 {
1202 zoff99 30
1203     //dbg(0,"EEnter\n");
1204    
1205 zoff99 27 while (node)
1206     {
1207 zoff99 30 //dbg(0,"name:%s\n", node->name);
1208    
1209 zoff99 27 xi_start_element(NULL, node->name, node->attr, node->attr + 1, document, NULL);
1210 zoff99 2 if (node->txt)
1211 zoff99 27 {
1212 zoff99 30 //dbg(0," txt:start\n");
1213 zoff99 27 xi_text(NULL, node->txt, strlen(node->txt), document, NULL);
1214 zoff99 30 //dbg(0," txt:end\n");
1215 zoff99 27 }
1216 zoff99 30
1217 zoff99 2 if (node->child)
1218 zoff99 27 {
1219 zoff99 2 parse_node(document, node->child);
1220 zoff99 27 }
1221 zoff99 30
1222 zoff99 27 xi_end_element(NULL, node->name, document, NULL);
1223     node = node->ordered;
1224 zoff99 2 }
1225     }
1226    
1227 zoff99 30 // this is used on android!!!!
1228     // this is used on android!!!!
1229     // this is used on android!!!!
1230     // this is used on android!!!!
1231 zoff99 27 static gboolean parse_file(struct xmldocument *document, xmlerror **error)
1232 zoff99 2 {
1233 zoff99 30 //dbg(0,"EEnter 2\n");
1234    
1235 zoff99 2 FILE *f;
1236     ezxml_t root;
1237    
1238 zoff99 27 f = fopen(document->href, "rb");
1239 zoff99 2 if (!f)
1240     return FALSE;
1241     root = ezxml_parse_fp(f);
1242     fclose(f);
1243     if (!root)
1244     return FALSE;
1245 zoff99 27 document->active = document->xpointer ? 0 : 1;
1246     document->first = NULL;
1247     document->last = NULL;
1248 zoff99 2
1249     parse_node(document, root);
1250    
1251     return TRUE;
1252     }
1253     #endif
1254    
1255     /**
1256     * * Load and parse the master config file
1257     * *
1258     * * @param filename FQFN of the file
1259     * * @param error ptr to error details, if any
1260     * * @returns boolean TRUE or FALSE (if error detected)
1261     * */
1262    
1263     gboolean config_load(const char *filename, xmlerror **error)
1264     {
1265     struct xmldocument document;
1266 zoff99 27 struct xmlstate *curr = NULL;
1267 zoff99 2 gboolean result;
1268    
1269     initStatic();
1270    
1271 zoff99 28 dbg(0, "XML-----XML-----enter filename='%s'\n", filename);
1272 zoff99 2 memset(&document, 0, sizeof(document));
1273 zoff99 27 document.href = filename;
1274     document.user_data = &curr;
1275     result = parse_file(&document, error);
1276 zoff99 31 //dbg(0,"xml 003\n");
1277 zoff99 27 if (result && curr)
1278     {
1279     g_set_error(error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, "element '%s' not closed", curr->element);
1280     result = FALSE;
1281 zoff99 2 }
1282 zoff99 28 dbg(0, "XML-----XML-----return %d\n", result);
1283 zoff99 2 return result;
1284     }
1285    

   
Visit the ZANavi Wiki