Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Contents of /branches/libroutino/src/xml/xsd-to-xmlparser.c
Parent Directory
|
Revision Log
Revision 1710 -
(show annotations)
(download)
(as text)
Sun Jun 14 09:07:05 2015 UTC (9 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 16464 byte(s)
Sun Jun 14 09:07:05 2015 UTC (9 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 16464 byte(s)
Audit the use of function static variables to make sure that there are no implicit assumptions about initialisation conditions that would be wrong for library usage. Fix problems and add comments for clarity.
1 | /*************************************** |
2 | $Header: /home/amb/CVS/routino/src/xml/xsd-to-xmlparser.c,v 1.10 2010-04-23 18:41:20 amb Exp $ |
3 | |
4 | An XML parser for simplified XML Schema Definitions to create XML parser skeletons. |
5 | |
6 | Part of the Routino routing software. |
7 | ******************/ /****************** |
8 | This file Copyright 2010-2015 Andrew M. Bishop |
9 | |
10 | This program is free software: you can redistribute it and/or modify |
11 | it under the terms of the GNU Affero General Public License as published by |
12 | the Free Software Foundation, either version 3 of the License, or |
13 | (at your option) any later version. |
14 | |
15 | This program is distributed in the hope that it will be useful, |
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | GNU Affero General Public License for more details. |
19 | |
20 | You should have received a copy of the GNU Affero General Public License |
21 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
22 | ***************************************/ |
23 | |
24 | |
25 | #include <stdio.h> |
26 | #if !defined(_MSC_VER) |
27 | #include <unistd.h> |
28 | #endif |
29 | #include <ctype.h> |
30 | #include <stdlib.h> |
31 | #include <string.h> |
32 | |
33 | #include "xmlparse.h" |
34 | |
35 | |
36 | /*+ A forward definition of the xmltagx +*/ |
37 | typedef struct _xmltagx xmltagx; |
38 | |
39 | |
40 | /*+ A structure to hold the extended definition of a tag. +*/ |
41 | struct _xmltagx |
42 | { |
43 | char *name; /*+ The name of the tag. +*/ |
44 | char *type; /*+ The type of the tag. +*/ |
45 | |
46 | int nattributes; /*+ The number of valid attributes for the tag. +*/ |
47 | char *attributes[XMLPARSE_MAX_ATTRS]; /*+ The valid attributes for the tag. +*/ |
48 | |
49 | int nsubtagsx; /*+ The number of valid attributes for the tag. +*/ |
50 | xmltagx *subtagsx[XMLPARSE_MAX_SUBTAGS]; /*+ The list of types for the subtags contained within this one. +*/ |
51 | }; |
52 | |
53 | |
54 | /* The local variables and functions */ |
55 | |
56 | int ntagsx=0; |
57 | xmltagx **tagsx=NULL; |
58 | char *currenttype=NULL; |
59 | |
60 | static char *safe(const char *name); |
61 | |
62 | |
63 | /* The XML tag processing function prototypes */ |
64 | |
65 | static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding); |
66 | static int schemaType_function(const char *_tag_,int _type_,const char *elementFormDefault,const char *xmlns_xsd); |
67 | static int elementType_function(const char *_tag_,int _type_,const char *name,const char *type,const char *minOccurs,const char *maxOccurs); |
68 | static int complexType_function(const char *_tag_,int _type_,const char *name); |
69 | static int sequenceType_function(const char *_tag_,int _type_); |
70 | static int attributeType_function(const char *_tag_,int _type_,const char *name,const char *type); |
71 | |
72 | |
73 | /* The XML tag definitions (forward declarations) */ |
74 | |
75 | static xmltag xmlDeclaration_tag; |
76 | static xmltag schemaType_tag; |
77 | static xmltag elementType_tag; |
78 | static xmltag complexType_tag; |
79 | static xmltag sequenceType_tag; |
80 | static xmltag attributeType_tag; |
81 | |
82 | |
83 | /* The XML tag definition values */ |
84 | |
85 | /*+ The complete set of tags at the top level. +*/ |
86 | static xmltag *xml_toplevel_tags[]={&xmlDeclaration_tag,&schemaType_tag,NULL}; |
87 | |
88 | /*+ The xmlDeclaration type tag. +*/ |
89 | static xmltag xmlDeclaration_tag= |
90 | {"xml", |
91 | 2, {"version","encoding"}, |
92 | xmlDeclaration_function, |
93 | {NULL}}; |
94 | |
95 | /*+ The schemaType type tag. +*/ |
96 | static xmltag schemaType_tag= |
97 | {"xsd:schema", |
98 | 2, {"elementFormDefault","xmlns:xsd"}, |
99 | schemaType_function, |
100 | {&elementType_tag,&complexType_tag,NULL}}; |
101 | |
102 | /*+ The elementType type tag. +*/ |
103 | static xmltag elementType_tag= |
104 | {"xsd:element", |
105 | 4, {"name","type","minOccurs","maxOccurs"}, |
106 | elementType_function, |
107 | {NULL}}; |
108 | |
109 | /*+ The complexType type tag. +*/ |
110 | static xmltag complexType_tag= |
111 | {"xsd:complexType", |
112 | 1, {"name"}, |
113 | complexType_function, |
114 | {&sequenceType_tag,&attributeType_tag,NULL}}; |
115 | |
116 | /*+ The sequenceType type tag. +*/ |
117 | static xmltag sequenceType_tag= |
118 | {"xsd:sequence", |
119 | 0, {NULL}, |
120 | sequenceType_function, |
121 | {&elementType_tag,NULL}}; |
122 | |
123 | /*+ The attributeType type tag. +*/ |
124 | static xmltag attributeType_tag= |
125 | {"xsd:attribute", |
126 | 2, {"name","type"}, |
127 | attributeType_function, |
128 | {NULL}}; |
129 | |
130 | |
131 | /* The XML tag processing functions */ |
132 | |
133 | |
134 | /*++++++++++++++++++++++++++++++++++++++ |
135 | The function that is called when the XML declaration is seen |
136 | |
137 | int xmlDeclaration_function Returns 0 if no error occured or something else otherwise. |
138 | |
139 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
140 | |
141 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
142 | |
143 | const char *version The contents of the 'version' attribute (or NULL if not defined). |
144 | |
145 | const char *encoding The contents of the 'encoding' attribute (or NULL if not defined). |
146 | ++++++++++++++++++++++++++++++++++++++*/ |
147 | |
148 | static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding) |
149 | { |
150 | /* Add the XML declaration as a tag. */ |
151 | |
152 | currenttype=NULL; |
153 | elementType_function("xsd:element",XMLPARSE_TAG_START|XMLPARSE_TAG_END,"xml","xmlDeclaration",NULL,NULL); |
154 | complexType_function("xsd:complexType",XMLPARSE_TAG_START,"xmlDeclaration"); |
155 | attributeType_function("xsd:attribute",XMLPARSE_TAG_START|XMLPARSE_TAG_END,"version",NULL); |
156 | attributeType_function("xsd:attribute",XMLPARSE_TAG_START|XMLPARSE_TAG_END,"encoding",NULL); |
157 | complexType_function("xsd:complexType",XMLPARSE_TAG_END,NULL); |
158 | currenttype=NULL; |
159 | |
160 | return(0); |
161 | } |
162 | |
163 | |
164 | /*++++++++++++++++++++++++++++++++++++++ |
165 | The function that is called when the schemaType XSD type is seen |
166 | |
167 | int schemaType_function Returns 0 if no error occured or something else otherwise. |
168 | |
169 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
170 | |
171 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
172 | |
173 | const char *elementFormDefault The contents of the 'elementFormDefault' attribute (or NULL if not defined). |
174 | |
175 | const char *xmlns_xsd The contents of the 'xmlns:xsd' attribute (or NULL if not defined). |
176 | ++++++++++++++++++++++++++++++++++++++*/ |
177 | |
178 | static int schemaType_function(const char *_tag_,int _type_,const char *elementFormDefault,const char *xmlns_xsd) |
179 | { |
180 | return(0); |
181 | } |
182 | |
183 | |
184 | /*++++++++++++++++++++++++++++++++++++++ |
185 | The function that is called when the elementType XSD type is seen |
186 | |
187 | int elementType_function Returns 0 if no error occured or something else otherwise. |
188 | |
189 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
190 | |
191 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
192 | |
193 | const char *name The contents of the 'name' attribute (or NULL if not defined). |
194 | |
195 | const char *type The contents of the 'type' attribute (or NULL if not defined). |
196 | |
197 | const char *minOccurs The contents of the 'minOccurs' attribute (or NULL if not defined). |
198 | |
199 | const char *maxOccurs The contents of the 'maxOccurs' attribute (or NULL if not defined). |
200 | ++++++++++++++++++++++++++++++++++++++*/ |
201 | |
202 | static int elementType_function(const char *_tag_,int _type_,const char *name,const char *type,const char *minOccurs,const char *maxOccurs) |
203 | { |
204 | xmltagx *tagx=NULL; |
205 | int i; |
206 | |
207 | if(_type_==XMLPARSE_TAG_END) |
208 | return(0); |
209 | |
210 | for(i=0;i<ntagsx;i++) |
211 | if(!strcmp(type,tagsx[i]->type) && !strcmp(name,tagsx[i]->name)) |
212 | tagx=tagsx[i]; |
213 | |
214 | if(!tagx) |
215 | { |
216 | ntagsx++; |
217 | tagsx=(xmltagx**)realloc((void*)tagsx,ntagsx*sizeof(xmltagx*)); |
218 | |
219 | tagsx[ntagsx-1]=(xmltagx*)calloc(1,sizeof(xmltagx)); |
220 | tagsx[ntagsx-1]->name=strcpy(malloc(strlen(name)+1),name); |
221 | tagsx[ntagsx-1]->type=strcpy(malloc(strlen(type)+1),type); |
222 | |
223 | tagx=tagsx[ntagsx-1]; |
224 | } |
225 | |
226 | if(!currenttype) |
227 | return(0); |
228 | |
229 | for(i=0;i<ntagsx;i++) |
230 | if(!strcmp(tagsx[i]->type,currenttype)) |
231 | { |
232 | tagsx[i]->subtagsx[tagsx[i]->nsubtagsx]=tagx; |
233 | tagsx[i]->nsubtagsx++; |
234 | |
235 | if(tagsx[i]->nsubtagsx==XMLPARSE_MAX_SUBTAGS) |
236 | {fprintf(stderr,"Too many subtags seen for type '%s'.\n",currenttype); exit(1);} |
237 | } |
238 | |
239 | return(0); |
240 | } |
241 | |
242 | |
243 | /*++++++++++++++++++++++++++++++++++++++ |
244 | The function that is called when the complexType XSD type is seen |
245 | |
246 | int complexType_function Returns 0 if no error occured or something else otherwise. |
247 | |
248 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
249 | |
250 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
251 | |
252 | const char *name The contents of the 'name' attribute (or NULL if not defined). |
253 | ++++++++++++++++++++++++++++++++++++++*/ |
254 | |
255 | static int complexType_function(const char *_tag_,int _type_,const char *name) |
256 | { |
257 | if(_type_==XMLPARSE_TAG_END) |
258 | return(0); |
259 | |
260 | currenttype=strcpy(realloc(currenttype,strlen(name)+1),name); |
261 | |
262 | return(0); |
263 | } |
264 | |
265 | |
266 | /*++++++++++++++++++++++++++++++++++++++ |
267 | The function that is called when the sequenceType XSD type is seen |
268 | |
269 | int sequenceType_function Returns 0 if no error occured or something else otherwise. |
270 | |
271 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
272 | |
273 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
274 | ++++++++++++++++++++++++++++++++++++++*/ |
275 | |
276 | static int sequenceType_function(const char *_tag_,int _type_) |
277 | { |
278 | return(0); |
279 | } |
280 | |
281 | |
282 | /*++++++++++++++++++++++++++++++++++++++ |
283 | The function that is called when the attributeType XSD type is seen |
284 | |
285 | int attributeType_function Returns 0 if no error occured or something else otherwise. |
286 | |
287 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
288 | |
289 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
290 | |
291 | const char *name The contents of the 'name' attribute (or NULL if not defined). |
292 | |
293 | const char *type The contents of the 'type' attribute (or NULL if not defined). |
294 | ++++++++++++++++++++++++++++++++++++++*/ |
295 | |
296 | static int attributeType_function(const char *_tag_,int _type_,const char *name,const char *type) |
297 | { |
298 | int i; |
299 | |
300 | if(_type_==XMLPARSE_TAG_END) |
301 | return(0); |
302 | |
303 | for(i=0;i<ntagsx;i++) |
304 | if(!strcmp(tagsx[i]->type,currenttype)) |
305 | { |
306 | tagsx[i]->attributes[tagsx[i]->nattributes]=strcpy(malloc(strlen(name)+1),name); |
307 | tagsx[i]->nattributes++; |
308 | |
309 | if(tagsx[i]->nattributes==XMLPARSE_MAX_ATTRS) |
310 | {fprintf(stderr,"Too many attributes seen for type '%s'.\n",currenttype); exit(1);} |
311 | } |
312 | |
313 | return(0); |
314 | } |
315 | |
316 | |
317 | /*++++++++++++++++++++++++++++++++++++++ |
318 | The XML Schema Definition XML parser and C program generator. |
319 | ++++++++++++++++++++++++++++++++++++++*/ |
320 | |
321 | int main(int argc,char **argv) |
322 | { |
323 | int i,j; |
324 | |
325 | /* Parse the XSD file */ |
326 | |
327 | if(ParseXML(STDIN_FILENO,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE)) |
328 | { |
329 | fprintf(stderr,"Cannot parse XML file - exiting.\n"); |
330 | exit(1); |
331 | } |
332 | |
333 | /* Print the header */ |
334 | |
335 | printf("/***************************************\n"); |
336 | printf(" An automatically generated skeleton XML parser.\n"); |
337 | printf("\n"); |
338 | printf(" Automatically generated by xsd-to-xmlparser.\n"); |
339 | printf(" ***************************************/\n"); |
340 | printf("\n"); |
341 | printf("\n"); |
342 | printf("#include <stdio.h>\n"); |
343 | printf("#if !defined(_MSC_VER)\n"); |
344 | printf("#include <unistd.h>\n"); |
345 | printf("#endif\n"); |
346 | printf("\n"); |
347 | printf("#include \"xmlparse.h\"\n"); |
348 | |
349 | /* Print the function prototypes */ |
350 | |
351 | printf("\n"); |
352 | printf("\n"); |
353 | printf("/* The XML tag processing function prototypes */\n"); |
354 | printf("\n"); |
355 | |
356 | for(i=0;i<ntagsx;i++) |
357 | { |
358 | printf("static int %s_function(const char *_tag_,int _type_",safe(tagsx[i]->type)); |
359 | |
360 | for(j=0;j<tagsx[i]->nattributes;j++) |
361 | printf(",const char *%s",safe(tagsx[i]->attributes[j])); |
362 | |
363 | printf(");\n"); |
364 | } |
365 | |
366 | /* Print the xmltag variables */ |
367 | |
368 | printf("\n"); |
369 | printf("\n"); |
370 | printf("/* The XML tag definitions (forward declarations) */\n"); |
371 | |
372 | printf("\n"); |
373 | |
374 | for(i=0;i<ntagsx;i++) |
375 | printf("static xmltag %s_tag;\n",safe(tagsx[i]->type)); |
376 | |
377 | printf("\n"); |
378 | printf("\n"); |
379 | printf("/* The XML tag definition values */\n"); |
380 | |
381 | printf("\n"); |
382 | printf("/*+ The complete set of tags at the top level. +*/\n"); |
383 | printf("static xmltag *xml_toplevel_tags[]={"); |
384 | printf("&%s_tag,",safe(tagsx[0]->type)); |
385 | printf("&%s_tag,",safe(tagsx[1]->type)); |
386 | printf("NULL};\n"); |
387 | |
388 | for(i=0;i<ntagsx;i++) |
389 | { |
390 | printf("\n"); |
391 | printf("/*+ The %s type tag. +*/\n",tagsx[i]->type); |
392 | printf("static xmltag %s_tag=\n",safe(tagsx[i]->type)); |
393 | printf(" {\"%s\",\n",tagsx[i]->name); |
394 | |
395 | printf(" %d, {",tagsx[i]->nattributes); |
396 | for(j=0;j<tagsx[i]->nattributes;j++) |
397 | printf("%s\"%s\"",(j?",":""),tagsx[i]->attributes[j]); |
398 | printf("%s},\n",(tagsx[i]->nattributes?"":"NULL")); |
399 | |
400 | printf(" %s_function,\n",safe(tagsx[i]->type)); |
401 | |
402 | printf(" {"); |
403 | for(j=0;j<tagsx[i]->nsubtagsx;j++) |
404 | printf("&%s_tag,",safe(tagsx[i]->subtagsx[j]->type)); |
405 | printf("NULL}};\n"); |
406 | } |
407 | |
408 | /* Print the functions */ |
409 | |
410 | printf("\n"); |
411 | printf("\n"); |
412 | printf("/* The XML tag processing functions */\n"); |
413 | |
414 | for(i=0;i<ntagsx;i++) |
415 | { |
416 | printf("\n"); |
417 | printf("\n"); |
418 | printf("/*++++++++++++++++++++++++++++++++++++++\n"); |
419 | if(i==0) /* XML tag */ |
420 | printf(" The function that is called when the XML declaration is seen\n"); |
421 | else |
422 | printf(" The function that is called when the %s XSD type is seen\n",tagsx[i]->type); |
423 | printf("\n"); |
424 | printf(" int %s_function Returns 0 if no error occured or something else otherwise.\n",safe(tagsx[i]->type)); |
425 | printf("\n"); |
426 | printf(" const char *_tag_ Set to the name of the element tag that triggered this function call.\n"); |
427 | printf("\n"); |
428 | printf(" int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.\n"); |
429 | for(j=0;j<tagsx[i]->nattributes;j++) |
430 | { |
431 | printf("\n"); |
432 | printf(" const char *%s The contents of the '%s' attribute (or NULL if not defined).\n",safe(tagsx[i]->attributes[j]),tagsx[i]->attributes[j]); |
433 | } |
434 | printf(" ++++++++++++++++++++++++++++++++++++++*/\n"); |
435 | printf("\n"); |
436 | |
437 | printf("static int %s_function(const char *_tag_,int _type_",safe(tagsx[i]->type)); |
438 | |
439 | for(j=0;j<tagsx[i]->nattributes;j++) |
440 | printf(",const char *%s",safe(tagsx[i]->attributes[j])); |
441 | |
442 | printf(")\n"); |
443 | |
444 | printf("{\n"); |
445 | |
446 | if(i==(ntagsx-1)) /* XML tag */ |
447 | { |
448 | printf(" printf(\"<?%%s\",_tag_);\n"); |
449 | for(j=0;j<tagsx[i]->nattributes;j++) |
450 | { |
451 | char *safename=safe(tagsx[i]->attributes[j]); |
452 | printf(" if(%s) printf(\" %s=\\\"%%s\\\"\",ParseXML_Encode_Safe_XML(%s));\n",safename,tagsx[i]->attributes[j],safename); |
453 | } |
454 | printf(" printf(\" ?>\\n\");\n"); |
455 | } |
456 | else |
457 | { |
458 | printf(" printf(\"<%%s%%s\",(_type_==XMLPARSE_TAG_END)?\"/\":\"\",_tag_);\n"); |
459 | for(j=0;j<tagsx[i]->nattributes;j++) |
460 | { |
461 | char *safename=safe(tagsx[i]->attributes[j]); |
462 | printf(" if(%s) printf(\" %s=\\\"%%s\\\"\",ParseXML_Encode_Safe_XML(%s));\n",safename,tagsx[i]->attributes[j],safename); |
463 | } |
464 | printf(" printf(\"%%s>\\n\",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?\" /\":\"\");\n"); |
465 | } |
466 | |
467 | printf(" return(0);\n"); |
468 | printf("}\n"); |
469 | } |
470 | |
471 | /* Print the main function */ |
472 | |
473 | printf("\n"); |
474 | printf("\n"); |
475 | printf("/*++++++++++++++++++++++++++++++++++++++\n"); |
476 | printf(" A skeleton XML parser.\n"); |
477 | printf(" ++++++++++++++++++++++++++++++++++++++*/\n"); |
478 | printf("\n"); |
479 | printf("int main(int argc,char **argv)\n"); |
480 | printf("{\n"); |
481 | printf(" if(ParseXML(STDIN_FILENO,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_WARN))\n"); |
482 | printf(" return(1);\n"); |
483 | printf(" else\n"); |
484 | printf(" return(0);\n"); |
485 | printf("}\n"); |
486 | |
487 | return(0); |
488 | } |
489 | |
490 | |
491 | /*++++++++++++++++++++++++++++++++++++++ |
492 | A function to return a safe C identifier from an XML tag or attribute name. |
493 | |
494 | char *safe Returns the safe name in a private string (only use once). |
495 | |
496 | const char *name The name to convert. |
497 | ++++++++++++++++++++++++++++++++++++++*/ |
498 | |
499 | static char *safe(const char *name) |
500 | { |
501 | static char *safe=NULL; /* static allocation of return value */ |
502 | int i; |
503 | |
504 | safe=realloc(safe,strlen(name)+1); |
505 | |
506 | for(i=0;name[i];i++) |
507 | if(isalnum(name[i])) |
508 | safe[i]=name[i]; |
509 | else |
510 | safe[i]='_'; |
511 | |
512 | safe[i]=0; |
513 | |
514 | return(safe); |
515 | } |
Properties
Name | Value |
---|---|
cvs:description | An XML parser that can convert XML Scheme description XML files into a skeleton source code file that works with the generic XML parser. |