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