Routino SVN Repository Browser

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

ViewVC logotype

Contents of /trunk/src/xmlparse.l

Parent Directory Parent Directory | Revision Log Revision Log


Revision 377 - (show 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 %{
2 /***************************************
3 $Header: /home/amb/CVS/routino/src/xmlparse.l,v 1.12 2010-04-24 15:49:03 amb Exp $
4
5 A simple generic XML parser where the structure comes from the function parameters.
6 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
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 #include <ctype.h>
31 #include <string.h>
32
33 #include "xmlparse.h"
34
35
36 /* Parser outputs */
37
38 #define LEX_EOF 0
39
40 #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
49 #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 #define LEX_ERROR_ATTR_VAL 109
60 #define LEX_ERROR_ENTITY_REF 110
61 #define LEX_ERROR_CHAR_REF 111
62
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 #define LEX_ERROR_CALLBACK 255
71
72
73 /* 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 static int xmlparse_options;
104
105 %}
106
107 %option 8bit
108 %option pointer
109 %option batch
110 %option yylineno
111
112 %option nodefault
113 %option perf-report
114 %option fast
115 %option nounput
116
117
118 /* Grammar based on http://www.w3.org/TR/2004/REC-xml-20040204/ but for ASCII not Unicode. */
119
120 S [ \t\r\n]
121
122 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 %x COMMENT
134 %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 %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 static int after_attr=0;
147 int newlen;
148 int doctype_depth=0;
149
150 /* Handle top level entities */
151
152 "<!--" { BEGIN(COMMENT); }
153 "<![CDATA[" { BEGIN(CDATA); }
154 "<!DOCTYPE" { BEGIN(DOCTYPE); doctype_depth=0; }
155 "</" { BEGIN(END_TAG1); }
156 "<?" { BEGIN(XML_DECL_START); }
157 "<" { BEGIN(TAG_START); }
158 ">" { return(LEX_ERROR_CLOSE); }
159 [^<>]+ { }
160
161 /* Comments */
162
163 <COMMENT>"--->" { return(LEX_ERROR_COMMENT); }
164 <COMMENT>"-->" { BEGIN(INITIAL); }
165 <COMMENT>"--"[^->]+ { }
166 <COMMENT>[^-]+ { }
167 <COMMENT>"-" { }
168
169 /* CDATA */
170
171 <CDATA>"]]>" { BEGIN(INITIAL); }
172 <CDATA>"]" { }
173 <CDATA>[^]]+ { }
174
175 /* CDATA */
176
177 <DOCTYPE>"<" { doctype_depth++; }
178 <DOCTYPE>">" { if(doctype_depth==0) BEGIN(INITIAL); else doctype_depth--; }
179 <DOCTYPE>[^<>]+ { }
180
181 /* 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 <TAG>"/>" { BEGIN(INITIAL); return(LEX_TAG_FINISH); }
209 <TAG>">" { BEGIN(INITIAL); return(LEX_TAG_PUSH); }
210 <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
214 /* Attributes */
215
216 <ATTR_KEY>= { BEGIN(ATTR_VAL); }
217 <ATTR_KEY>.|\n { return(LEX_ERROR_ATTR); }
218
219 <ATTR_VAL>\" { BEGIN(DQUOTED); reset_string; }
220 <ATTR_VAL>\' { BEGIN(SQUOTED); reset_string; }
221 <ATTR_VAL>.|\n { return(LEX_ERROR_ATTR); }
222
223 /* Quoted strings */
224
225 <DQUOTED>\" { BEGIN(after_attr); yylval=string; return(LEX_ATTR_VAL); }
226 <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 <DQUOTED>[<>&] { yylval=yytext; return(LEX_ERROR_ATTR_VAL); }
231 <DQUOTED>[^<>&\"]+ { append_string(yytext); }
232
233 <SQUOTED>\' { BEGIN(after_attr); yylval=string; return(LEX_ATTR_VAL); }
234 <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 <SQUOTED>[<>&] { yylval=yytext; return(LEX_ERROR_ATTR_VAL); }
239 <SQUOTED>[^<>&\']+ { append_string(yytext); }
240
241 /* End of file */
242
243 <<EOF>> { free(string); string=NULL; stringlen=stringused=0; BEGIN(INITIAL); return(LEX_EOF); }
244
245 %%
246
247
248 /*++++++++++++++++++++++++++++++++++++++
249 A function to call the callback function with the parameters needed.
250
251 int call_callback Returns 1 if the callback returned with an error.
252
253 const char *name The name of the tag.
254
255 int (*callback)() The callback function.
256
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 static inline int call_callback(const char *name,int (*callback)(),int type,int nattributes,char *attributes[XMLPARSE_MAX_ATTRS])
265 {
266 switch(nattributes)
267 {
268 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
286 default:
287 fprintf(stderr,"XML Parser: Error on line %d: too many attributes for tag '%s' source code needs changing.\n",yylineno,name);
288 exit(1);
289 }
290 }
291
292
293 /*++++++++++++++++++++++++++++++++++++++
294 Parse the XML and call the functions for each tag as seen.
295
296 int ParseXML Returns 0 if OK or something else in case of an error.
297
298 FILE *file The file to parse.
299
300 xmltag **tags The array of pointers to tags for the top level.
301
302 int options A list of XML Parser options OR-ed together.
303 ++++++++++++++++++++++++++++++++++++++*/
304
305 int ParseXML(FILE *file,xmltag **tags,int options)
306 {
307 int yychar,i;
308
309 char *attributes[XMLPARSE_MAX_ATTRS]={NULL};
310 int attribute=0;
311
312 int stackdepth=0,stackused=0;
313 xmltag ***tags_stack=NULL;
314 xmltag **tag_stack=NULL;
315 xmltag *tag=NULL;
316
317 /* The actual parser. */
318
319 xmlparse_options=options;
320
321 yyin=file;
322
323 yyrestart(yyin);
324
325 BEGIN(INITIAL);
326
327 do
328 {
329 yychar=yylex();
330
331 switch(yychar)
332 {
333 /* 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 /* 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 for(i=0;i<tag->nattributes;i++)
356 if(attributes[i])
357 {
358 free(attributes[i]);
359 attributes[i]=NULL;
360 }
361
362 break;
363 }
364
365 if(tag==NULL)
366 {
367 fprintf(stderr,"XML Parser: Error on line %d: unexpected tag '%s'.\n",yylineno,yylval);
368 yychar=LEX_ERROR_UNEXP_TAG;
369 }
370
371 break;
372
373 /* The end of the start-tag for an element */
374
375 case LEX_TAG_PUSH:
376
377 if(stackused==stackdepth)
378 {
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
383 tag_stack [stackused]=tag;
384 tags_stack[stackused]=tags;
385 stackused++;
386
387 if(tag->callback)
388 if(call_callback(tag->name,tag->callback,XMLPARSE_TAG_START,tag->nattributes,attributes))
389 yychar=LEX_ERROR_CALLBACK;
390
391 tags=tag->subtags;
392
393 break;
394
395 /* The end of the empty-element-tag for an XML declaration */
396
397 case LEX_XML_DECL_FINISH:
398
399 /* The end of the empty-element-tag for an element */
400
401 case LEX_TAG_FINISH:
402
403 if(tag->callback)
404 if(call_callback(tag->name,tag->callback,XMLPARSE_TAG_START|XMLPARSE_TAG_END,tag->nattributes,attributes))
405 yychar=LEX_ERROR_CALLBACK;
406
407 if(stackused>0)
408 tag=tag_stack[stackused-1];
409 else
410 tag=NULL;
411
412 break;
413
414 /* The end of the end-tag for an element */
415
416 case LEX_TAG_POP:
417
418 stackused--;
419 tags=tags_stack[stackused];
420 tag =tag_stack [stackused];
421
422 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 for(i=0;i<tag->nattributes;i++)
435 if(attributes[i])
436 {
437 free(attributes[i]);
438 attributes[i]=NULL;
439 }
440
441 if(tag->callback)
442 if(call_callback(tag->name,tag->callback,XMLPARSE_TAG_END,tag->nattributes,attributes))
443 yychar=LEX_ERROR_CALLBACK;
444
445 if(stackused>0)
446 tag=tag_stack[stackused-1];
447 else
448 tag=NULL;
449
450 break;
451
452 /* An attribute key */
453
454 case LEX_ATTR_KEY:
455
456 attribute=-1;
457
458 for(i=0;i<tag->nattributes;i++)
459 if(!strcasecmp(yylval,tag->attributes[i]))
460 {
461 attribute=i;
462
463 break;
464 }
465
466 if(attribute==-1)
467 {
468 if((options&XMLPARSE_UNKNOWN_ATTRIBUTES)==XMLPARSE_UNKNOWN_ATTR_ERROR ||
469 ((options&XMLPARSE_UNKNOWN_ATTRIBUTES)==XMLPARSE_UNKNOWN_ATTR_ERRNONAME && !strchr(yylval,':')))
470 {
471 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 }
474 else if((options&XMLPARSE_UNKNOWN_ATTRIBUTES)==XMLPARSE_UNKNOWN_ATTR_WARN)
475 fprintf(stderr,"XML Parser: Warning on line %d: unexpected attribute '%s' for tag '%s'.\n",yylineno,yylval,tag->name);
476 }
477
478 break;
479
480 /* An attribute value */
481
482 case LEX_ATTR_VAL:
483
484 if(tag->callback && attribute!=-1 && yylval)
485 attributes[attribute]=strcpy(malloc(strlen(yylval)+1),yylval);
486
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
533 case LEX_ERROR_ATTR_VAL:
534 fprintf(stderr,"XML Parser: Error on line %d: invalid character '%s' seen in attribute value.\n",yylineno,yylval);
535 break;
536
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 }
545 }
546 while(yychar>LEX_EOF && yychar<LEX_ERROR);
547
548 /* Delete the tagdata */
549
550 for(i=0;i<XMLPARSE_MAX_ATTRS;i++)
551 if(attributes[i])
552 free(attributes[i]);
553
554 if(stackdepth)
555 free(tags_stack);
556
557 return(yychar);
558 }
559
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
572
573 /*++++++++++++++++++++++++++++++++++++++
574 Convert an XML entity reference into an ASCII string.
575
576 char *ParseXML_Decode_Entity_Ref Returns a pointer to the replacement decoded string.
577
578 const char *string The entity reference string.
579 ++++++++++++++++++++++++++++++++++++++*/
580
581 char *ParseXML_Decode_Entity_Ref(const char *string)
582 {
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 char *ParseXML_Decode_Char_Ref Returns a pointer to the replacement decoded string.
596
597 const char *string The character reference string.
598 ++++++++++++++++++++++++++++++++++++++*/
599
600 char *ParseXML_Decode_Char_Ref(const char *string)
601 {
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 char *ParseXML_Encode_Safe_XML Returns a pointer to the replacement encoded string (or the original if no change needed).
621
622 const char *string The string to convert.
623 ++++++++++++++++++++++++++++++++++++++*/
624
625 char *ParseXML_Encode_Safe_XML(const char *string)
626 {
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 return((char*)string);
637
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
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.