Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Annotation of /trunk/src/xml/xsd-to-xmlparser.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1980 - (hide annotations) (download) (as text)
Sun Apr 7 15:55:17 2019 UTC (5 years, 11 months ago) by amb
File MIME type: text/x-csrc
File size: 16621 byte(s)
Free some memory to avoid leaks - found by running with gcc's runtime
sanitizer enabled (make SANITIZE=1 test).

1 amb 334 /***************************************
2 amb 373 $Header: /home/amb/CVS/routino/src/xml/xsd-to-xmlparser.c,v 1.10 2010-04-23 18:41:20 amb Exp $
3 amb 334
4     An XML parser for simplified XML Schema Definitions to create XML parser skeletons.
5    
6     Part of the Routino routing software.
7     ******************/ /******************
8 amb 1980 This file Copyright 2010-2015, 2019 Andrew M. Bishop
9 amb 334
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 amb 1680 #if !defined(_MSC_VER)
27 amb 1192 #include <unistd.h>
28 amb 1680 #endif
29 amb 334 #include <ctype.h>
30     #include <stdlib.h>
31     #include <string.h>
32    
33     #include "xmlparse.h"
34    
35    
36 amb 367 /*+ 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 amb 334 /* The local variables and functions */
55    
56 amb 367 int ntagsx=0;
57     xmltagx **tagsx=NULL;
58 amb 334 char *currenttype=NULL;
59    
60     static char *safe(const char *name);
61    
62    
63     /* The XML tag processing function prototypes */
64    
65 amb 373 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 amb 1204 static int elementType_function(const char *_tag_,int _type_,const char *name,const char *type,const char *minOccurs,const char *maxOccurs);
68 amb 373 static int complexType_function(const char *_tag_,int _type_,const char *name);
69 amb 1204 static int sequenceType_function(const char *_tag_,int _type_);
70 amb 373 static int attributeType_function(const char *_tag_,int _type_,const char *name,const char *type);
71 amb 334
72    
73 amb 1204 /* The XML tag definitions (forward declarations) */
74 amb 334
75 amb 1719 static const xmltag xmlDeclaration_tag;
76     static const xmltag schemaType_tag;
77     static const xmltag elementType_tag;
78     static const xmltag complexType_tag;
79     static const xmltag sequenceType_tag;
80     static const xmltag attributeType_tag;
81 amb 1204
82    
83     /* The XML tag definition values */
84    
85     /*+ The complete set of tags at the top level. +*/
86 amb 1719 static const xmltag * const xml_toplevel_tags[]={&xmlDeclaration_tag,&schemaType_tag,NULL};
87 amb 1204
88     /*+ The xmlDeclaration type tag. +*/
89 amb 1719 static const xmltag xmlDeclaration_tag=
90 amb 1204 {"xml",
91     2, {"version","encoding"},
92     xmlDeclaration_function,
93     {NULL}};
94    
95     /*+ The schemaType type tag. +*/
96 amb 1719 static const xmltag schemaType_tag=
97 amb 1204 {"xsd:schema",
98     2, {"elementFormDefault","xmlns:xsd"},
99     schemaType_function,
100     {&elementType_tag,&complexType_tag,NULL}};
101    
102 amb 334 /*+ The elementType type tag. +*/
103 amb 1719 static const xmltag elementType_tag=
104 amb 339 {"xsd:element",
105 amb 355 4, {"name","type","minOccurs","maxOccurs"},
106 amb 367 elementType_function,
107 amb 339 {NULL}};
108 amb 334
109 amb 1204 /*+ The complexType type tag. +*/
110 amb 1719 static const xmltag complexType_tag=
111 amb 1204 {"xsd:complexType",
112     1, {"name"},
113     complexType_function,
114     {&sequenceType_tag,&attributeType_tag,NULL}};
115    
116 amb 334 /*+ The sequenceType type tag. +*/
117 amb 1719 static const xmltag sequenceType_tag=
118 amb 339 {"xsd:sequence",
119 amb 355 0, {NULL},
120 amb 367 sequenceType_function,
121     {&elementType_tag,NULL}};
122 amb 334
123     /*+ The attributeType type tag. +*/
124 amb 1719 static const xmltag attributeType_tag=
125 amb 339 {"xsd:attribute",
126 amb 355 2, {"name","type"},
127 amb 367 attributeType_function,
128 amb 339 {NULL}};
129 amb 334
130 amb 339
131 amb 1204 /* The XML tag processing functions */
132 amb 339
133 amb 334
134 amb 1204 /*++++++++++++++++++++++++++++++++++++++
135     The function that is called when the XML declaration is seen
136 amb 334
137 amb 1204 int xmlDeclaration_function Returns 0 if no error occured or something else otherwise.
138 amb 334
139 amb 1204 const char *_tag_ Set to the name of the element tag that triggered this function call.
140 amb 334
141 amb 1204 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 amb 334
143 amb 1204 const char *version The contents of the 'version' attribute (or NULL if not defined).
144 amb 334
145 amb 1204 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 amb 1980
159     if(currenttype)
160     free(currenttype);
161 amb 1204 currenttype=NULL;
162    
163     return(0);
164     }
165    
166    
167 amb 334 /*++++++++++++++++++++++++++++++++++++++
168 amb 1204 The function that is called when the schemaType XSD type is seen
169    
170     int schemaType_function Returns 0 if no error occured or something else otherwise.
171    
172     const char *_tag_ Set to the name of the element tag that triggered this function call.
173    
174     int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
175    
176     const char *elementFormDefault The contents of the 'elementFormDefault' attribute (or NULL if not defined).
177    
178     const char *xmlns_xsd The contents of the 'xmlns:xsd' attribute (or NULL if not defined).
179     ++++++++++++++++++++++++++++++++++++++*/
180    
181     static int schemaType_function(const char *_tag_,int _type_,const char *elementFormDefault,const char *xmlns_xsd)
182     {
183     return(0);
184     }
185    
186    
187     /*++++++++++++++++++++++++++++++++++++++
188 amb 344 The function that is called when the elementType XSD type is seen
189 amb 334
190 amb 367 int elementType_function Returns 0 if no error occured or something else otherwise.
191 amb 363
192 amb 373 const char *_tag_ Set to the name of the element tag that triggered this function call.
193    
194 amb 344 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
195    
196 amb 355 const char *name The contents of the 'name' attribute (or NULL if not defined).
197 amb 334
198 amb 355 const char *type The contents of the 'type' attribute (or NULL if not defined).
199 amb 334
200 amb 355 const char *minOccurs The contents of the 'minOccurs' attribute (or NULL if not defined).
201 amb 334
202 amb 355 const char *maxOccurs The contents of the 'maxOccurs' attribute (or NULL if not defined).
203 amb 334 ++++++++++++++++++++++++++++++++++++++*/
204    
205 amb 373 static int elementType_function(const char *_tag_,int _type_,const char *name,const char *type,const char *minOccurs,const char *maxOccurs)
206 amb 334 {
207 amb 367 xmltagx *tagx=NULL;
208     int i;
209 amb 334
210 amb 344 if(_type_==XMLPARSE_TAG_END)
211 amb 363 return(0);
212 amb 344
213 amb 367 for(i=0;i<ntagsx;i++)
214     if(!strcmp(type,tagsx[i]->type) && !strcmp(name,tagsx[i]->name))
215     tagx=tagsx[i];
216 amb 334
217 amb 367 if(!tagx)
218 amb 334 {
219 amb 367 ntagsx++;
220     tagsx=(xmltagx**)realloc((void*)tagsx,ntagsx*sizeof(xmltagx*));
221 amb 334
222 amb 367 tagsx[ntagsx-1]=(xmltagx*)calloc(1,sizeof(xmltagx));
223     tagsx[ntagsx-1]->name=strcpy(malloc(strlen(name)+1),name);
224     tagsx[ntagsx-1]->type=strcpy(malloc(strlen(type)+1),type);
225 amb 334
226 amb 367 tagx=tagsx[ntagsx-1];
227 amb 334 }
228    
229     if(!currenttype)
230 amb 363 return(0);
231 amb 334
232 amb 367 for(i=0;i<ntagsx;i++)
233     if(!strcmp(tagsx[i]->type,currenttype))
234 amb 339 {
235 amb 367 tagsx[i]->subtagsx[tagsx[i]->nsubtagsx]=tagx;
236     tagsx[i]->nsubtagsx++;
237 amb 339
238 amb 367 if(tagsx[i]->nsubtagsx==XMLPARSE_MAX_SUBTAGS)
239 amb 339 {fprintf(stderr,"Too many subtags seen for type '%s'.\n",currenttype); exit(1);}
240     }
241 amb 363
242     return(0);
243 amb 334 }
244    
245    
246     /*++++++++++++++++++++++++++++++++++++++
247 amb 1204 The function that is called when the complexType XSD type is seen
248    
249     int complexType_function Returns 0 if no error occured or something else otherwise.
250    
251     const char *_tag_ Set to the name of the element tag that triggered this function call.
252    
253     int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
254    
255     const char *name The contents of the 'name' attribute (or NULL if not defined).
256     ++++++++++++++++++++++++++++++++++++++*/
257    
258     static int complexType_function(const char *_tag_,int _type_,const char *name)
259     {
260     if(_type_==XMLPARSE_TAG_END)
261     return(0);
262    
263     currenttype=strcpy(realloc(currenttype,strlen(name)+1),name);
264    
265     return(0);
266     }
267    
268    
269     /*++++++++++++++++++++++++++++++++++++++
270 amb 344 The function that is called when the sequenceType XSD type is seen
271    
272 amb 367 int sequenceType_function Returns 0 if no error occured or something else otherwise.
273 amb 363
274 amb 373 const char *_tag_ Set to the name of the element tag that triggered this function call.
275    
276 amb 344 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
277 amb 334 ++++++++++++++++++++++++++++++++++++++*/
278    
279 amb 373 static int sequenceType_function(const char *_tag_,int _type_)
280 amb 334 {
281 amb 363 return(0);
282 amb 334 }
283    
284    
285     /*++++++++++++++++++++++++++++++++++++++
286 amb 344 The function that is called when the attributeType XSD type is seen
287 amb 334
288 amb 367 int attributeType_function Returns 0 if no error occured or something else otherwise.
289 amb 363
290 amb 373 const char *_tag_ Set to the name of the element tag that triggered this function call.
291    
292 amb 344 int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag.
293    
294 amb 355 const char *name The contents of the 'name' attribute (or NULL if not defined).
295 amb 334
296 amb 355 const char *type The contents of the 'type' attribute (or NULL if not defined).
297 amb 334 ++++++++++++++++++++++++++++++++++++++*/
298    
299 amb 373 static int attributeType_function(const char *_tag_,int _type_,const char *name,const char *type)
300 amb 334 {
301 amb 367 int i;
302 amb 334
303 amb 344 if(_type_==XMLPARSE_TAG_END)
304 amb 363 return(0);
305 amb 344
306 amb 367 for(i=0;i<ntagsx;i++)
307     if(!strcmp(tagsx[i]->type,currenttype))
308 amb 339 {
309 amb 367 tagsx[i]->attributes[tagsx[i]->nattributes]=strcpy(malloc(strlen(name)+1),name);
310     tagsx[i]->nattributes++;
311 amb 339
312 amb 367 if(tagsx[i]->nattributes==XMLPARSE_MAX_ATTRS)
313 amb 339 {fprintf(stderr,"Too many attributes seen for type '%s'.\n",currenttype); exit(1);}
314     }
315 amb 363
316     return(0);
317 amb 334 }
318    
319    
320     /*++++++++++++++++++++++++++++++++++++++
321     The XML Schema Definition XML parser and C program generator.
322     ++++++++++++++++++++++++++++++++++++++*/
323    
324     int main(int argc,char **argv)
325     {
326 amb 1204 int i,j;
327 amb 334
328 amb 1204 /* Parse the XSD file */
329    
330 amb 1192 if(ParseXML(STDIN_FILENO,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_IGNORE))
331 amb 349 {
332     fprintf(stderr,"Cannot parse XML file - exiting.\n");
333     exit(1);
334     }
335 amb 334
336     /* Print the header */
337    
338     printf("/***************************************\n");
339     printf(" An automatically generated skeleton XML parser.\n");
340     printf("\n");
341     printf(" Automatically generated by xsd-to-xmlparser.\n");
342     printf(" ***************************************/\n");
343     printf("\n");
344     printf("\n");
345     printf("#include <stdio.h>\n");
346 amb 1680 printf("#if !defined(_MSC_VER)\n");
347 amb 1192 printf("#include <unistd.h>\n");
348 amb 1680 printf("#endif\n");
349 amb 334 printf("\n");
350     printf("#include \"xmlparse.h\"\n");
351    
352     /* Print the function prototypes */
353    
354     printf("\n");
355     printf("\n");
356     printf("/* The XML tag processing function prototypes */\n");
357     printf("\n");
358    
359 amb 1204 for(i=0;i<ntagsx;i++)
360 amb 334 {
361 amb 373 printf("static int %s_function(const char *_tag_,int _type_",safe(tagsx[i]->type));
362 amb 334
363 amb 367 for(j=0;j<tagsx[i]->nattributes;j++)
364     printf(",const char *%s",safe(tagsx[i]->attributes[j]));
365 amb 334
366     printf(");\n");
367     }
368    
369     /* Print the xmltag variables */
370    
371     printf("\n");
372     printf("\n");
373 amb 1204 printf("/* The XML tag definitions (forward declarations) */\n");
374 amb 334
375 amb 1204 printf("\n");
376    
377 amb 367 for(i=0;i<ntagsx;i++)
378 amb 1719 printf("static const xmltag %s_tag;\n",safe(tagsx[i]->type));
379 amb 1204
380     printf("\n");
381     printf("\n");
382     printf("/* The XML tag definition values */\n");
383    
384     printf("\n");
385     printf("/*+ The complete set of tags at the top level. +*/\n");
386 amb 1719 printf("static const xmltag * const xml_toplevel_tags[]={");
387 amb 1204 printf("&%s_tag,",safe(tagsx[0]->type));
388     printf("&%s_tag,",safe(tagsx[1]->type));
389     printf("NULL};\n");
390    
391     for(i=0;i<ntagsx;i++)
392 amb 334 {
393     printf("\n");
394 amb 367 printf("/*+ The %s type tag. +*/\n",tagsx[i]->type);
395 amb 1719 printf("static const xmltag %s_tag=\n",safe(tagsx[i]->type));
396 amb 367 printf(" {\"%s\",\n",tagsx[i]->name);
397 amb 334
398 amb 367 printf(" %d, {",tagsx[i]->nattributes);
399     for(j=0;j<tagsx[i]->nattributes;j++)
400     printf("%s\"%s\"",(j?",":""),tagsx[i]->attributes[j]);
401     printf("%s},\n",(tagsx[i]->nattributes?"":"NULL"));
402 amb 334
403 amb 367 printf(" %s_function,\n",safe(tagsx[i]->type));
404 amb 334
405 amb 339 printf(" {");
406 amb 367 for(j=0;j<tagsx[i]->nsubtagsx;j++)
407     printf("&%s_tag,",safe(tagsx[i]->subtagsx[j]->type));
408 amb 334 printf("NULL}};\n");
409     }
410    
411     /* Print the functions */
412    
413     printf("\n");
414     printf("\n");
415     printf("/* The XML tag processing functions */\n");
416    
417 amb 367 for(i=0;i<ntagsx;i++)
418 amb 334 {
419     printf("\n");
420     printf("\n");
421     printf("/*++++++++++++++++++++++++++++++++++++++\n");
422 amb 1204 if(i==0) /* XML tag */
423 amb 367 printf(" The function that is called when the XML declaration is seen\n");
424     else
425     printf(" The function that is called when the %s XSD type is seen\n",tagsx[i]->type);
426 amb 344 printf("\n");
427 amb 367 printf(" int %s_function Returns 0 if no error occured or something else otherwise.\n",safe(tagsx[i]->type));
428 amb 363 printf("\n");
429 amb 373 printf(" const char *_tag_ Set to the name of the element tag that triggered this function call.\n");
430     printf("\n");
431 amb 344 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");
432 amb 367 for(j=0;j<tagsx[i]->nattributes;j++)
433 amb 355 {
434     printf("\n");
435 amb 367 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]);
436 amb 355 }
437 amb 334 printf(" ++++++++++++++++++++++++++++++++++++++*/\n");
438     printf("\n");
439    
440 amb 373 printf("static int %s_function(const char *_tag_,int _type_",safe(tagsx[i]->type));
441 amb 334
442 amb 367 for(j=0;j<tagsx[i]->nattributes;j++)
443     printf(",const char *%s",safe(tagsx[i]->attributes[j]));
444 amb 334
445     printf(")\n");
446    
447     printf("{\n");
448    
449 amb 367 if(i==(ntagsx-1)) /* XML tag */
450 amb 349 {
451 amb 373 printf(" printf(\"<?%%s\",_tag_);\n");
452 amb 367 for(j=0;j<tagsx[i]->nattributes;j++)
453 amb 355 {
454 amb 367 char *safename=safe(tagsx[i]->attributes[j]);
455     printf(" if(%s) printf(\" %s=\\\"%%s\\\"\",ParseXML_Encode_Safe_XML(%s));\n",safename,tagsx[i]->attributes[j],safename);
456 amb 355 }
457 amb 352 printf(" printf(\" ?>\\n\");\n");
458 amb 349 }
459     else
460     {
461 amb 373 printf(" printf(\"<%%s%%s\",(_type_==XMLPARSE_TAG_END)?\"/\":\"\",_tag_);\n");
462 amb 367 for(j=0;j<tagsx[i]->nattributes;j++)
463 amb 355 {
464 amb 367 char *safename=safe(tagsx[i]->attributes[j]);
465     printf(" if(%s) printf(\" %s=\\\"%%s\\\"\",ParseXML_Encode_Safe_XML(%s));\n",safename,tagsx[i]->attributes[j],safename);
466 amb 355 }
467 amb 352 printf(" printf(\"%%s>\\n\",(_type_==(XMLPARSE_TAG_START|XMLPARSE_TAG_END))?\" /\":\"\");\n");
468 amb 349 }
469 amb 334
470 amb 363 printf(" return(0);\n");
471 amb 334 printf("}\n");
472     }
473    
474     /* Print the main function */
475    
476     printf("\n");
477     printf("\n");
478     printf("/*++++++++++++++++++++++++++++++++++++++\n");
479     printf(" A skeleton XML parser.\n");
480     printf(" ++++++++++++++++++++++++++++++++++++++*/\n");
481     printf("\n");
482     printf("int main(int argc,char **argv)\n");
483     printf("{\n");
484 amb 1192 printf(" if(ParseXML(STDIN_FILENO,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_WARN))\n");
485 amb 349 printf(" return(1);\n");
486     printf(" else\n");
487     printf(" return(0);\n");
488 amb 334 printf("}\n");
489    
490     return(0);
491     }
492    
493    
494     /*++++++++++++++++++++++++++++++++++++++
495     A function to return a safe C identifier from an XML tag or attribute name.
496    
497     char *safe Returns the safe name in a private string (only use once).
498    
499     const char *name The name to convert.
500     ++++++++++++++++++++++++++++++++++++++*/
501    
502     static char *safe(const char *name)
503     {
504 amb 1784 static char *safe=NULL; /* static allocation of return value */
505 amb 334 int i;
506    
507     safe=realloc(safe,strlen(name)+1);
508    
509     for(i=0;name[i];i++)
510     if(isalnum(name[i]))
511     safe[i]=name[i];
512     else
513     safe[i]='_';
514    
515     safe[i]=0;
516    
517     return(safe);
518     }

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.