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 356 - (show annotations) (download)
Thu Apr 8 17:21:45 2010 UTC (14 years, 11 months ago) by amb
File size: 21569 byte(s)
Make the strings const and add the number of attributes to the xmltag structure.
Add functions to convert character entities and character references.

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

Properties

Name Value
cvs:description A simple generic XML parser.