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/xmlparse.l

Parent Directory Parent Directory | Revision Log Revision Log


Revision 377 - (hide annotations) (download)
Sat Apr 24 15:49:03 2010 UTC (14 years, 10 months ago) by amb
File size: 23580 byte(s)
Changed functions from const.

1 amb 334 %{
2     /***************************************
3 amb 377 $Header: /home/amb/CVS/routino/src/xmlparse.l,v 1.12 2010-04-24 15:49:03 amb Exp $
4 amb 334
5     A simple generic XML parser where the structure comes from the function parameters.
6 amb 348 Not intended to be fully conforming to XML staandard or a validating parser but
7     sufficient to parse OSM XML and simple program configuration files.
8 amb 334
9     Part of the Routino routing software.
10     ******************/ /******************
11     This file Copyright 2010 Andrew M. Bishop
12    
13     This program is free software: you can redistribute it and/or modify
14     it under the terms of the GNU Affero General Public License as published by
15     the Free Software Foundation, either version 3 of the License, or
16     (at your option) any later version.
17    
18     This program is distributed in the hope that it will be useful,
19     but WITHOUT ANY WARRANTY; without even the implied warranty of
20     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21     GNU Affero General Public License for more details.
22    
23     You should have received a copy of the GNU Affero General Public License
24     along with this program. If not, see <http://www.gnu.org/licenses/>.
25     ***************************************/
26    
27    
28     #include <stdio.h>
29     #include <stdlib.h>
30 amb 363 #include <ctype.h>
31 amb 334 #include <string.h>
32    
33 amb 356 #include "xmlparse.h"
34    
35    
36 amb 334 /* Parser outputs */
37    
38 amb 348 #define LEX_EOF 0
39 amb 334
40 amb 348 #define LEX_TAG_BEGIN 1
41     #define LEX_XML_DECL_BEGIN 2
42     #define LEX_TAG_POP 3
43     #define LEX_TAG_PUSH 4
44     #define LEX_XML_DECL_FINISH 6
45     #define LEX_TAG_FINISH 7
46     #define LEX_ATTR_KEY 8
47     #define LEX_ATTR_VAL 9
48 amb 334
49 amb 348 #define LEX_ERROR 100
50    
51     #define LEX_ERROR_TAG_START 101
52     #define LEX_ERROR_XML_DECL_START 102
53     #define LEX_ERROR_TAG 103
54     #define LEX_ERROR_XML_DECL 104
55     #define LEX_ERROR_ATTR 105
56     #define LEX_ERROR_END_TAG 106
57     #define LEX_ERROR_COMMENT 107
58     #define LEX_ERROR_CLOSE 108
59 amb 351 #define LEX_ERROR_ATTR_VAL 109
60 amb 356 #define LEX_ERROR_ENTITY_REF 110
61     #define LEX_ERROR_CHAR_REF 111
62 amb 348
63     #define LEX_ERROR_UNEXP_TAG 201
64     #define LEX_ERROR_UNBALANCED 202
65     #define LEX_ERROR_NO_START 203
66     #define LEX_ERROR_UNEXP_ATT 204
67     #define LEX_ERROR_UNEXP_EOF 205
68     #define LEX_ERROR_XML_NOT_FIRST 206
69    
70 amb 363 #define LEX_ERROR_CALLBACK 255
71 amb 348
72 amb 363
73 amb 334 /* Lexer definitions */
74    
75     #define YY_SKIP_YYWRAP 1 /* Remove error with prototype of ..._yywrap */
76     #ifndef yywrap
77     /*+ Needed in lex but does nothing. +*/
78     #define yywrap() 1
79     #endif
80    
81     /*+ Reset the current string. +*/
82     #define reset_string \
83     if(string) *string=0; \
84     stringused=0;
85    
86     /*+ append information to the current string. +*/
87     #define append_string(xx) \
88     newlen=strlen(xx); \
89     if((stringused+newlen)>=stringlen) \
90     string=(char*)realloc((void*)string,stringlen=(stringused+newlen+16)); \
91     strcpy(string+stringused,xx); \
92     stringused+=newlen;
93    
94     #define YY_NO_INPUT
95    
96    
97     /* Lexer functions and variables */
98    
99     extern int yylex(void);
100    
101     static char *yylval=NULL;
102    
103 amb 374 static int xmlparse_options;
104    
105 amb 334 %}
106    
107 amb 344 %option 8bit
108 amb 348 %option pointer
109 amb 344 %option batch
110     %option yylineno
111 amb 348
112 amb 344 %option nodefault
113     %option perf-report
114     %option fast
115 amb 348 %option nounput
116 amb 344
117 amb 334
118 amb 348 /* Grammar based on http://www.w3.org/TR/2004/REC-xml-20040204/ but for ASCII not Unicode. */
119 amb 334
120 amb 348 S [ \t\r\n]
121 amb 334
122 amb 348 letter [a-zA-Z]
123     digit [0-9]
124     xdigit [a-fA-F0-9]
125    
126     namechar ({letter}|{digit}|[-._:])
127     name ({letter}|[_:]){namechar}*
128    
129     entityref &{name};
130     charref &#({digit}+|x{xdigit}+);
131    
132    
133 amb 334 %x COMMENT
134 amb 348 %x CDATA
135     %x DOCTYPE
136     %x XML_DECL_START XML_DECL
137     %x TAG_START TAG
138     %x ATTR_KEY ATTR_VAL
139     %x END_TAG1 END_TAG2
140 amb 334 %x DQUOTED SQUOTED
141    
142     %%
143     /* Must use static variables since the parser returns often. */
144     static char *string=NULL;
145     static int stringlen=0,stringused=0;
146 amb 348 static int after_attr=0;
147 amb 334 int newlen;
148 amb 348 int doctype_depth=0;
149 amb 334
150 amb 348 /* Handle top level entities */
151 amb 334
152     "<!--" { BEGIN(COMMENT); }
153 amb 348 "<![CDATA[" { BEGIN(CDATA); }
154     "<!DOCTYPE" { BEGIN(DOCTYPE); doctype_depth=0; }
155     "</" { BEGIN(END_TAG1); }
156     "<?" { BEGIN(XML_DECL_START); }
157 amb 334 "<" { BEGIN(TAG_START); }
158 amb 348 ">" { return(LEX_ERROR_CLOSE); }
159     [^<>]+ { }
160 amb 334
161 amb 348 /* Comments */
162 amb 334
163 amb 348 <COMMENT>"--->" { return(LEX_ERROR_COMMENT); }
164     <COMMENT>"-->" { BEGIN(INITIAL); }
165     <COMMENT>"--"[^->]+ { }
166     <COMMENT>[^-]+ { }
167 amb 334 <COMMENT>"-" { }
168    
169 amb 348 /* CDATA */
170 amb 334
171 amb 348 <CDATA>"]]>" { BEGIN(INITIAL); }
172     <CDATA>"]" { }
173     <CDATA>[^]]+ { }
174 amb 334
175 amb 348 /* CDATA */
176 amb 334
177 amb 348 <DOCTYPE>"<" { doctype_depth++; }
178     <DOCTYPE>">" { if(doctype_depth==0) BEGIN(INITIAL); else doctype_depth--; }
179     <DOCTYPE>[^<>]+ { }
180 amb 334
181 amb 348 /* XML Declaration start */
182    
183     <XML_DECL_START>{name} { BEGIN(XML_DECL); yylval=yytext; return(LEX_XML_DECL_BEGIN); }
184     <XML_DECL_START>.|\n { return(LEX_ERROR_XML_DECL_START); }
185    
186     /* Tag middle */
187    
188     <XML_DECL>"?>" { BEGIN(INITIAL); return(LEX_XML_DECL_FINISH); }
189     <XML_DECL>{S}+ { }
190     <XML_DECL>{name} { after_attr=XML_DECL; BEGIN(ATTR_KEY); yylval=yytext; return(LEX_ATTR_KEY); }
191     <XML_DECL>.|\n { return(LEX_ERROR_XML_DECL); }
192    
193     /* Any tag start */
194    
195     <TAG_START>{name} { BEGIN(TAG); yylval=yytext; return(LEX_TAG_BEGIN); }
196     <TAG_START>.|\n { return(LEX_ERROR_TAG_START); }
197    
198     /* End-tag start */
199    
200     <END_TAG1>{name} { BEGIN(END_TAG2); yylval=yytext; return(LEX_TAG_POP); }
201     <END_TAG1>.|\n { return(LEX_ERROR_END_TAG); }
202    
203     <END_TAG2>">" { BEGIN(INITIAL); }
204     <END_TAG2>.|\n { return(LEX_ERROR_END_TAG); }
205    
206     /* Any tag middle */
207    
208 amb 334 <TAG>"/>" { BEGIN(INITIAL); return(LEX_TAG_FINISH); }
209     <TAG>">" { BEGIN(INITIAL); return(LEX_TAG_PUSH); }
210 amb 348 <TAG>{S}+ { }
211     <TAG>{name} { after_attr=TAG; BEGIN(ATTR_KEY); yylval=yytext; return(LEX_ATTR_KEY); }
212     <TAG>.|\n { return(LEX_ERROR_TAG); }
213 amb 334
214 amb 348 /* Attributes */
215 amb 334
216 amb 348 <ATTR_KEY>= { BEGIN(ATTR_VAL); }
217     <ATTR_KEY>.|\n { return(LEX_ERROR_ATTR); }
218 amb 334
219 amb 348 <ATTR_VAL>\" { BEGIN(DQUOTED); reset_string; }
220     <ATTR_VAL>\' { BEGIN(SQUOTED); reset_string; }
221     <ATTR_VAL>.|\n { return(LEX_ERROR_ATTR); }
222    
223 amb 334 /* Quoted strings */
224    
225 amb 348 <DQUOTED>\" { BEGIN(after_attr); yylval=string; return(LEX_ATTR_VAL); }
226 amb 374 <DQUOTED>{entityref} { if(xmlparse_options&XMLPARSE_RETURN_ATTR_ENCODED) {append_string(yytext);}
227     else { const char *str=ParseXML_Decode_Entity_Ref(yytext); if(str) {append_string(str);} else {yylval=yytext; return(LEX_ERROR_ENTITY_REF);} } }
228     <DQUOTED>{charref} { if(xmlparse_options&XMLPARSE_RETURN_ATTR_ENCODED) {append_string(yytext);}
229     else { const char *str=ParseXML_Decode_Char_Ref(yytext); if(str) {append_string(str);} else {yylval=yytext; return(LEX_ERROR_CHAR_REF);} } }
230 amb 356 <DQUOTED>[<>&] { yylval=yytext; return(LEX_ERROR_ATTR_VAL); }
231 amb 348 <DQUOTED>[^<>&\"]+ { append_string(yytext); }
232 amb 334
233 amb 348 <SQUOTED>\' { BEGIN(after_attr); yylval=string; return(LEX_ATTR_VAL); }
234 amb 374 <SQUOTED>{entityref} { if(xmlparse_options&XMLPARSE_RETURN_ATTR_ENCODED) {append_string(yytext);}
235     else { const char *str=ParseXML_Decode_Entity_Ref(yytext); if(str) {append_string(str);} else {yylval=yytext; return(LEX_ERROR_ENTITY_REF);} } }
236     <SQUOTED>{charref} { if(xmlparse_options&XMLPARSE_RETURN_ATTR_ENCODED) {append_string(yytext);}
237     else { const char *str=ParseXML_Decode_Char_Ref(yytext); if(str) {append_string(str);} else {yylval=yytext; return(LEX_ERROR_CHAR_REF);} } }
238 amb 356 <SQUOTED>[<>&] { yylval=yytext; return(LEX_ERROR_ATTR_VAL); }
239 amb 348 <SQUOTED>[^<>&\']+ { append_string(yytext); }
240 amb 334
241     /* End of file */
242    
243 amb 368 <<EOF>> { free(string); string=NULL; stringlen=stringused=0; BEGIN(INITIAL); return(LEX_EOF); }
244 amb 334
245     %%
246    
247    
248 amb 348 /*++++++++++++++++++++++++++++++++++++++
249     A function to call the callback function with the parameters needed.
250    
251 amb 363 int call_callback Returns 1 if the callback returned with an error.
252    
253 amb 356 const char *name The name of the tag.
254 amb 348
255 amb 363 int (*callback)() The callback function.
256 amb 348
257     int type The type of tag (start and/or end).
258    
259     int nattributes The number of attributes collected.
260    
261     char *attributes[XMLPARSE_MAX_ATTRS] The list of attributes.
262     ++++++++++++++++++++++++++++++++++++++*/
263    
264 amb 363 static inline int call_callback(const char *name,int (*callback)(),int type,int nattributes,char *attributes[XMLPARSE_MAX_ATTRS])
265 amb 344 {
266     switch(nattributes)
267     {
268 amb 373 case 0: return (*callback)(name,type);
269     case 1: return (*callback)(name,type,attributes[0]);
270     case 2: return (*callback)(name,type,attributes[0],attributes[1]);
271     case 3: return (*callback)(name,type,attributes[0],attributes[1],attributes[2]);
272     case 4: return (*callback)(name,type,attributes[0],attributes[1],attributes[2],attributes[3]);
273     case 5: return (*callback)(name,type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4]);
274     case 6: return (*callback)(name,type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5]);
275     case 7: return (*callback)(name,type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6]);
276     case 8: return (*callback)(name,type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7]);
277     case 9: return (*callback)(name,type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7],attributes[8]);
278     case 10: return (*callback)(name,type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7],attributes[8],attributes[9]);
279     case 11: return (*callback)(name,type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7],attributes[8],attributes[9],attributes[10]);
280     case 12: return (*callback)(name,type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7],attributes[8],attributes[9],attributes[10],attributes[11]);
281     case 13: return (*callback)(name,type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7],attributes[8],attributes[9],attributes[10],attributes[11],attributes[12]);
282     case 14: return (*callback)(name,type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7],attributes[8],attributes[9],attributes[10],attributes[11],attributes[12],attributes[13]);
283     case 15: return (*callback)(name,type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7],attributes[8],attributes[9],attributes[10],attributes[11],attributes[12],attributes[13],attributes[14]);
284     case 16: return (*callback)(name,type,attributes[0],attributes[1],attributes[2],attributes[3],attributes[4],attributes[5],attributes[6],attributes[7],attributes[8],attributes[9],attributes[10],attributes[11],attributes[12],attributes[13],attributes[14],attributes[15]);
285 amb 334
286 amb 344 default:
287 amb 363 fprintf(stderr,"XML Parser: Error on line %d: too many attributes for tag '%s' source code needs changing.\n",yylineno,name);
288 amb 344 exit(1);
289     }
290     }
291    
292    
293 amb 334 /*++++++++++++++++++++++++++++++++++++++
294     Parse the XML and call the functions for each tag as seen.
295    
296 amb 348 int ParseXML Returns 0 if OK or something else in case of an error.
297    
298 amb 334 FILE *file The file to parse.
299    
300     xmltag **tags The array of pointers to tags for the top level.
301 amb 337
302 amb 366 int options A list of XML Parser options OR-ed together.
303 amb 334 ++++++++++++++++++++++++++++++++++++++*/
304    
305 amb 366 int ParseXML(FILE *file,xmltag **tags,int options)
306 amb 334 {
307     int yychar,i;
308    
309 amb 351 char *attributes[XMLPARSE_MAX_ATTRS]={NULL};
310 amb 334 int attribute=0;
311    
312     int stackdepth=0,stackused=0;
313 amb 344 xmltag ***tags_stack=NULL;
314     xmltag **tag_stack=NULL;
315 amb 334 xmltag *tag=NULL;
316    
317 amb 368 /* The actual parser. */
318 amb 334
319 amb 374 xmlparse_options=options;
320    
321 amb 334 yyin=file;
322    
323 amb 368 yyrestart(yyin);
324 amb 334
325 amb 368 BEGIN(INITIAL);
326 amb 334
327 amb 348 do
328     {
329     yychar=yylex();
330    
331 amb 334 switch(yychar)
332     {
333 amb 348 /* The start of a tag for an XML declaration */
334    
335     case LEX_XML_DECL_BEGIN:
336    
337     if(tag_stack)
338     {
339     fprintf(stderr,"XML Parser: Error on line %d: XML declaration not before all other tags.\n",yylineno);
340     yychar=LEX_ERROR_XML_NOT_FIRST;
341     break;
342     }
343    
344 amb 334 /* The start of a tag for an element */
345    
346     case LEX_TAG_BEGIN:
347    
348     tag=NULL;
349    
350     for(i=0;tags[i];i++)
351     if(!strcasecmp(yylval,tags[i]->name))
352     {
353     tag=tags[i];
354    
355 amb 356 for(i=0;i<tag->nattributes;i++)
356 amb 351 if(attributes[i])
357     {
358     free(attributes[i]);
359     attributes[i]=NULL;
360     }
361 amb 334
362     break;
363     }
364    
365     if(tag==NULL)
366     {
367 amb 348 fprintf(stderr,"XML Parser: Error on line %d: unexpected tag '%s'.\n",yylineno,yylval);
368     yychar=LEX_ERROR_UNEXP_TAG;
369 amb 334 }
370 amb 348
371 amb 334 break;
372    
373     /* The end of the start-tag for an element */
374    
375     case LEX_TAG_PUSH:
376    
377     if(stackused==stackdepth)
378 amb 344 {
379     tag_stack =(xmltag**) realloc((void*)tag_stack ,(stackdepth+=8)*sizeof(xmltag*));
380     tags_stack=(xmltag***)realloc((void*)tags_stack,(stackdepth+=8)*sizeof(xmltag**));
381     }
382 amb 334
383 amb 344 tag_stack [stackused]=tag;
384     tags_stack[stackused]=tags;
385     stackused++;
386    
387     if(tag->callback)
388 amb 363 if(call_callback(tag->name,tag->callback,XMLPARSE_TAG_START,tag->nattributes,attributes))
389     yychar=LEX_ERROR_CALLBACK;
390 amb 344
391 amb 334 tags=tag->subtags;
392    
393 amb 344 break;
394    
395 amb 348 /* The end of the empty-element-tag for an XML declaration */
396    
397     case LEX_XML_DECL_FINISH:
398    
399 amb 334 /* The end of the empty-element-tag for an element */
400    
401     case LEX_TAG_FINISH:
402    
403     if(tag->callback)
404 amb 363 if(call_callback(tag->name,tag->callback,XMLPARSE_TAG_START|XMLPARSE_TAG_END,tag->nattributes,attributes))
405     yychar=LEX_ERROR_CALLBACK;
406 amb 334
407 amb 344 if(stackused>0)
408     tag=tag_stack[stackused-1];
409     else
410     tag=NULL;
411 amb 334
412     break;
413    
414     /* The end of the end-tag for an element */
415    
416     case LEX_TAG_POP:
417    
418 amb 344 stackused--;
419     tags=tags_stack[stackused];
420     tag =tag_stack [stackused];
421 amb 334
422 amb 348 if(strcmp(tag->name,yylval))
423     {
424     fprintf(stderr,"XML Parser: Error on line %d: end tag '</%s>' doesn't match start tag '<%s ...>'.\n",yylineno,yylval,tag->name);
425     yychar=LEX_ERROR_UNBALANCED;
426     }
427    
428     if(stackused<0)
429     {
430     fprintf(stderr,"XML Parser: Error on line %d: end tag '</%s>' seen but there was no start tag '<%s ...>'.\n",yylineno,yylval,yylval);
431     yychar=LEX_ERROR_NO_START;
432     }
433    
434 amb 356 for(i=0;i<tag->nattributes;i++)
435 amb 351 if(attributes[i])
436     {
437     free(attributes[i]);
438     attributes[i]=NULL;
439     }
440    
441 amb 344 if(tag->callback)
442 amb 363 if(call_callback(tag->name,tag->callback,XMLPARSE_TAG_END,tag->nattributes,attributes))
443     yychar=LEX_ERROR_CALLBACK;
444 amb 344
445 amb 348 if(stackused>0)
446     tag=tag_stack[stackused-1];
447     else
448     tag=NULL;
449 amb 344
450 amb 334 break;
451    
452     /* An attribute key */
453    
454     case LEX_ATTR_KEY:
455    
456     attribute=-1;
457    
458 amb 356 for(i=0;i<tag->nattributes;i++)
459 amb 334 if(!strcasecmp(yylval,tag->attributes[i]))
460     {
461     attribute=i;
462    
463     break;
464     }
465    
466     if(attribute==-1)
467     {
468 amb 366 if((options&XMLPARSE_UNKNOWN_ATTRIBUTES)==XMLPARSE_UNKNOWN_ATTR_ERROR ||
469     ((options&XMLPARSE_UNKNOWN_ATTRIBUTES)==XMLPARSE_UNKNOWN_ATTR_ERRNONAME && !strchr(yylval,':')))
470 amb 337 {
471 amb 348 fprintf(stderr,"XML Parser: Error on line %d: unexpected attribute '%s' for tag '%s'.\n",yylineno,yylval,tag->name);
472     yychar=LEX_ERROR_UNEXP_ATT;
473 amb 337 }
474 amb 366 else if((options&XMLPARSE_UNKNOWN_ATTRIBUTES)==XMLPARSE_UNKNOWN_ATTR_WARN)
475 amb 348 fprintf(stderr,"XML Parser: Warning on line %d: unexpected attribute '%s' for tag '%s'.\n",yylineno,yylval,tag->name);
476 amb 334 }
477 amb 348
478 amb 334 break;
479    
480     /* An attribute value */
481    
482     case LEX_ATTR_VAL:
483    
484 amb 363 if(tag->callback && attribute!=-1 && yylval)
485 amb 334 attributes[attribute]=strcpy(malloc(strlen(yylval)+1),yylval);
486 amb 348
487     break;
488    
489     /* End of file */
490    
491     case LEX_EOF:
492    
493     if(tag)
494     {
495     fprintf(stderr,"XML Parser: Error on line %d: end of file seen without end tag '</%s>'.\n",yylineno,tag->name);
496     yychar=LEX_ERROR_UNEXP_EOF;
497     }
498    
499     break;
500    
501     case LEX_ERROR_TAG_START:
502     fprintf(stderr,"XML Parser: Error on line %d: character '<' seen not at start of tag.\n",yylineno);
503     break;
504    
505     case LEX_ERROR_XML_DECL_START:
506     fprintf(stderr,"XML Parser: Error on line %d: characters '<?' seen not at start of XML declaration.\n",yylineno);
507     break;
508    
509     case LEX_ERROR_TAG:
510     fprintf(stderr,"XML Parser: Error on line %d: invalid character seen inside tag '<%s...>'.\n",yylineno,tag->name);
511     break;
512    
513     case LEX_ERROR_XML_DECL:
514     fprintf(stderr,"XML Parser: Error on line %d: invalid character seen inside XML declaration '<?%s...>'.\n",yylineno,tag->name);
515     break;
516    
517     case LEX_ERROR_ATTR:
518     fprintf(stderr,"XML Parser: Error on line %d: invalid attribute definition seen in tag.\n",yylineno);
519     break;
520    
521     case LEX_ERROR_END_TAG:
522     fprintf(stderr,"XML Parser: Error on line %d: invalid character seen in end-tag.\n",yylineno);
523     break;
524    
525     case LEX_ERROR_COMMENT:
526     fprintf(stderr,"XML Parser: Error on line %d: invalid comment seen.\n",yylineno);
527     break;
528    
529     case LEX_ERROR_CLOSE:
530     fprintf(stderr,"XML Parser: Error on line %d: character '>' seen not at end of tag.\n",yylineno);
531     break;
532 amb 351
533     case LEX_ERROR_ATTR_VAL:
534 amb 356 fprintf(stderr,"XML Parser: Error on line %d: invalid character '%s' seen in attribute value.\n",yylineno,yylval);
535 amb 351 break;
536 amb 356
537     case LEX_ERROR_ENTITY_REF:
538     fprintf(stderr,"XML Parser: Error on line %d: invalid entity reference '%s' seen in attribute value.\n",yylineno,yylval);
539     break;
540    
541     case LEX_ERROR_CHAR_REF:
542     fprintf(stderr,"XML Parser: Error on line %d: invalid character reference '%s' seen in attribute value.\n",yylineno,yylval);
543     break;
544 amb 334 }
545 amb 348 }
546     while(yychar>LEX_EOF && yychar<LEX_ERROR);
547 amb 334
548     /* Delete the tagdata */
549    
550 amb 356 for(i=0;i<XMLPARSE_MAX_ATTRS;i++)
551 amb 334 if(attributes[i])
552     free(attributes[i]);
553    
554     if(stackdepth)
555 amb 344 free(tags_stack);
556 amb 348
557     return(yychar);
558 amb 334 }
559 amb 348
560    
561     /*++++++++++++++++++++++++++++++++++++++
562     Return the current parser line number.
563    
564     int ParseXML_LineNumber Returns the line number.
565     ++++++++++++++++++++++++++++++++++++++*/
566    
567     int ParseXML_LineNumber(void)
568     {
569     return(yylineno);
570     }
571 amb 356
572    
573     /*++++++++++++++++++++++++++++++++++++++
574     Convert an XML entity reference into an ASCII string.
575    
576 amb 377 char *ParseXML_Decode_Entity_Ref Returns a pointer to the replacement decoded string.
577 amb 356
578     const char *string The entity reference string.
579     ++++++++++++++++++++++++++++++++++++++*/
580    
581 amb 377 char *ParseXML_Decode_Entity_Ref(const char *string)
582 amb 356 {
583     if(!strcmp(string,"&amp;")) return("&");
584     if(!strcmp(string,"&lt;")) return("<");
585     if(!strcmp(string,"&gt;")) return(">");
586     if(!strcmp(string,"&apos;")) return("'");
587     if(!strcmp(string,"&quot;")) return("\"");
588     return(NULL);
589     }
590    
591    
592     /*++++++++++++++++++++++++++++++++++++++
593     Convert an XML character reference into an ASCII string.
594    
595 amb 377 char *ParseXML_Decode_Char_Ref Returns a pointer to the replacement decoded string.
596 amb 356
597     const char *string The character reference string.
598     ++++++++++++++++++++++++++++++++++++++*/
599    
600 amb 377 char *ParseXML_Decode_Char_Ref(const char *string)
601 amb 356 {
602     static char result[2]=" ";
603     long int val;
604    
605     if(string[2]=='x') val=strtol(string+3,NULL,16);
606     else val=strtol(string+2,NULL,10);
607    
608     if(val<0 || val>255)
609     return(NULL);
610    
611     result[0]=val&0xff;
612    
613     return(result);
614     }
615    
616    
617     /*++++++++++++++++++++++++++++++++++++++
618     Convert a string into something that is safe to output in an XML file.
619    
620 amb 377 char *ParseXML_Encode_Safe_XML Returns a pointer to the replacement encoded string (or the original if no change needed).
621 amb 356
622     const char *string The string to convert.
623     ++++++++++++++++++++++++++++++++++++++*/
624    
625 amb 377 char *ParseXML_Encode_Safe_XML(const char *string)
626 amb 356 {
627     static const char hexstring[17]="0123456789ABCDEF";
628     int i=0,j=0,len;
629     char *result;
630    
631     for(i=0;string[i];i++)
632     if(string[i]=='<' || string[i]=='>' || string[i]=='&' || string[i]=='\'' || string[i]=='"' || string[i]<32 || string[i]>126)
633     break;
634    
635     if(!string[i])
636 amb 377 return((char*)string);
637 amb 356
638     len=i+256-6;
639    
640     result=(char*)malloc(len+7);
641     strncpy(result,string,i);
642    
643     do
644     {
645     for(;j<len && string[i];i++)
646     if(string[i]=='<')
647     {
648     result[j++]='&';
649     result[j++]='l';
650     result[j++]='t';
651     result[j++]=';';
652     }
653     else if(string[i]=='>')
654     {
655     result[j++]='&';
656     result[j++]='g';
657     result[j++]='t';
658     result[j++]=';';
659     }
660     else if(string[i]=='&')
661     {
662     result[j++]='&';
663     result[j++]='a';
664     result[j++]='m';
665     result[j++]='p';
666     result[j++]=';';
667     }
668     else if(string[i]=='\'')
669     {
670     result[j++]='&';
671     result[j++]='a';
672     result[j++]='p';
673     result[j++]='o';
674     result[j++]='s';
675     result[j++]=';';
676     }
677     else if(string[i]=='"')
678     {
679     result[j++]='&';
680     result[j++]='q';
681     result[j++]='u';
682     result[j++]='o';
683     result[j++]='t';
684     result[j++]=';';
685     }
686     else if(string[i]<32 || string[i]>126)
687     {
688     result[j++]='&';
689     result[j++]='#';
690     result[j++]='x';
691     result[j++]=hexstring[(string[i]&0xf0)>>4];
692     result[j++]=hexstring[ string[i]&0x0f ];
693     result[j++]=';';
694     }
695     else
696     result[j++]=string[i];
697    
698     if(string[i]) /* Not finished */
699     {
700     len+=256;
701     result=(char*)realloc((void*)result,len+7);
702     }
703     }
704     while(string[i]);
705    
706     result[j]=0;
707    
708     return(result);
709     }
710 amb 363
711    
712     /*++++++++++++++++++++++++++++++++++++++
713     Convert a string to a integer (checking that it really is a integer).
714    
715     int ParseXML_GetInteger Returns 1 if a integer could be found or 0 otherwise.
716    
717     const char *string The string to be parsed.
718    
719     int *number Returns the number.
720     ++++++++++++++++++++++++++++++++++++++*/
721    
722     int ParseXML_GetInteger(const char *string,int *number)
723     {
724     const char *p=string;
725    
726     if(*p=='-' || *p=='+')
727     p++;
728    
729     while(isdigit(*p))
730     p++;
731    
732     if(*p)
733     return(0);
734    
735     *number=atoi(string);
736    
737     return(1);
738     }
739    
740    
741     /*++++++++++++++++++++++++++++++++++++++
742     Convert a string to a floating point number (checking that it really is a number).
743    
744     int ParseXML_GetFloating Returns 1 if a number could be found or 0 otherwise.
745    
746     const char *string The string to be parsed.
747    
748     int *number Returns the number.
749     ++++++++++++++++++++++++++++++++++++++*/
750    
751     int ParseXML_GetFloating(const char *string,double *number)
752     {
753     const char *p=string;
754    
755     if(*p=='-' || *p=='+')
756     p++;
757    
758     while(isdigit(*p) || *p=='.')
759     p++;
760    
761     if(*p)
762     return(0);
763    
764     *number=atof(string);
765    
766     return(1);
767     }

Properties

Name Value
cvs:description A simple generic XML parser.