Changeset 642 for BAORadio/libindi/libindi/libs/lilxml.c
- Timestamp:
- Feb 24, 2012, 12:37:36 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
BAORadio/libindi/libindi/libs/lilxml.c
r490 r642 15 15 You should have received a copy of the GNU Lesser General Public 16 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 5 1 Franklin Street, Fifth Floor, Boston, MA 02110-1301USA17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 18 19 19 #endif … … 27 27 */ 28 28 29 #include <stdio.h> 29 30 #include <stdlib.h> 30 31 #include <string.h> … … 41 42 #define MINMEM 64 /* starting string length */ 42 43 43 static int oneXMLchar (LilXML *lp, int c, char errmsg[]);44 static int oneXMLchar (LilXML *lp, int c, char ynot[]); 44 45 static void initParser(LilXML *lp); 45 46 static void pushXMLEle(LilXML *lp); … … 111 112 static char entities[] = "&<>'\""; 112 113 113 /* default memory managers, override with indi_xmlMalloc() */114 /* default memory managers, override with lilxmlMalloc() */ 114 115 static void *(*mymalloc)(size_t size) = malloc; 115 116 static void *(*myrealloc)(void *ptr, size_t size) = realloc; … … 120 121 */ 121 122 void 122 indi_xmlMalloc (void *(*newmalloc)(size_t size),123 124 125 { 126 127 128 123 lilxmlMalloc (void *(*newmalloc)(size_t size), 124 void *(*newrealloc)(void *ptr, size_t size), 125 void (*newfree)(void *ptr)) 126 { 127 mymalloc = newmalloc; 128 myrealloc = newrealloc; 129 myfree = newfree; 129 130 } 130 131 … … 133 134 newLilXML () 134 135 { 135 136 137 138 136 LilXML *lp = (LilXML *) moremem (NULL, sizeof(LilXML)); 137 memset (lp, 0, sizeof(LilXML)); 138 initParser(lp); 139 return (lp); 139 140 } 140 141 … … 143 144 delLilXML (LilXML *lp) 144 145 { 145 146 147 146 delXMLEle (lp->ce); 147 freeString (&lp->endtag); 148 (*myfree) (lp); 148 149 } 149 150 … … 152 153 delXMLEle (XMLEle *ep) 153 154 { 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 155 int i; 156 157 /* benign if NULL */ 158 if (!ep) 159 return; 160 161 /* delete all parts of ep */ 162 freeString (&ep->tag); 163 freeString (&ep->pcdata); 164 if (ep->at) { 165 for (i = 0; i < ep->nat; i++) 166 freeAtt (ep->at[i]); 167 (*myfree) (ep->at); 168 } 169 if (ep->el) { 170 for (i = 0; i < ep->nel; i++) { 171 /* forget parent so deleting doesn't modify _this_ el[] */ 172 ep->el[i]->pe = NULL; 173 174 delXMLEle (ep->el[i]); 175 } 176 (*myfree) (ep->el); 177 } 178 179 /* remove from parent's list if known */ 180 if (ep->pe) { 181 XMLEle *pe = ep->pe; 182 for (i = 0; i < pe->nel; i++) { 183 if (pe->el[i] == ep) { 184 memmove (&pe->el[i], &pe->el[i+1], 185 (--pe->nel-i)*sizeof(XMLEle*)); 186 break; 187 } 188 } 189 } 190 191 /* delete ep itself */ 192 (*myfree) (ep); 192 193 } 193 194 194 195 /* process one more character of an XML file. 195 196 * when find closure with outter element return root of complete tree. 196 * when find error return NULL with reason in errmsg[].197 * when need more return NULL with errmsg[0] = '\0'.197 * when find error return NULL with reason in ynot[]. 198 * when need more return NULL with ynot[0] = '\0'. 198 199 * N.B. it is up to the caller to delete any tree returned with delXMLEle(). 199 200 */ 200 201 XMLEle * 201 readXMLEle (LilXML *lp, int newc, char errmsg[]) 202 { 203 XMLEle *root; 204 int s; 205 206 /* start optimistic */ 207 errmsg[0] = '\0'; 208 209 /* EOF? */ 210 if (newc == 0) { 211 sprintf (errmsg, "Line %d: early XML EOF", lp->ln); 212 initParser(lp); 213 return (NULL); 214 } 215 216 /* new line? */ 217 if (newc == '\n') 218 lp->ln++; 219 220 /* skip comments and declarations. requires 1 char history */ 221 if (!lp->skipping && lp->lastc == '<' && (newc == '?' || newc == '!')) { 222 lp->skipping = 1; 223 lp->lastc = newc; 224 return (NULL); 225 } 226 if (lp->skipping) { 227 if (newc == '>') 228 lp->skipping = 0; 229 lp->lastc = newc; 230 return (NULL); 231 } 232 if (newc == '<') { 233 lp->lastc = '<'; 234 return (NULL); 235 } 236 237 /* do a pending '<' first then newc */ 238 if (lp->lastc == '<') { 239 if (oneXMLchar (lp, '<', errmsg) < 0) { 240 initParser(lp); 241 return (NULL); 242 } 243 /* N.B. we assume '<' will never result in closure */ 244 } 245 246 /* process newc (at last!) */ 247 s = oneXMLchar (lp, newc, errmsg); 248 if (s == 0) { 249 lp->lastc = newc; 250 return (NULL); 251 } 252 if (s < 0) { 253 initParser(lp); 254 return (NULL); 255 } 256 257 /* Ok! return ce and we start over. 258 * N.B. up to caller to call delXMLEle with what we return. 259 */ 260 root = lp->ce; 261 lp->ce = NULL; 262 initParser(lp); 263 return (root); 202 readXMLEle (LilXML *lp, int newc, char ynot[]) 203 { 204 XMLEle *root; 205 int s; 206 207 /* start optimistic */ 208 ynot[0] = '\0'; 209 210 /* EOF? */ 211 if (newc == 0) { 212 sprintf (ynot, "Line %d: early XML EOF", lp->ln); 213 initParser(lp); 214 return (NULL); 215 } 216 217 /* new line? */ 218 if (newc == '\n') 219 lp->ln++; 220 221 /* skip comments and declarations. requires 1 char history */ 222 if (!lp->skipping && lp->lastc == '<' && (newc == '?' || newc == '!')) { 223 lp->skipping = 1; 224 lp->lastc = newc; 225 return (NULL); 226 } 227 if (lp->skipping) { 228 if (newc == '>') 229 lp->skipping = 0; 230 lp->lastc = newc; 231 return (NULL); 232 } 233 if (newc == '<') { 234 lp->lastc = '<'; 235 return (NULL); 236 } 237 238 /* do a pending '<' first then newc */ 239 if (lp->lastc == '<') { 240 if (oneXMLchar (lp, '<', ynot) < 0) { 241 initParser(lp); 242 return (NULL); 243 } 244 /* N.B. we assume '<' will never result in closure */ 245 } 246 247 /* process newc (at last!) */ 248 s = oneXMLchar (lp, newc, ynot); 249 if (s == 0) { 250 lp->lastc = newc; 251 return (NULL); 252 } 253 if (s < 0) { 254 initParser(lp); 255 return (NULL); 256 } 257 258 /* Ok! return ce and we start over. 259 * N.B. up to caller to call delXMLEle with what we return. 260 */ 261 root = lp->ce; 262 lp->ce = NULL; 263 initParser(lp); 264 return (root); 265 } 266 267 /* parse the given XML string. 268 * return XMLEle* else NULL with reason why in ynot[] 269 */ 270 XMLEle * 271 parseXML (char buf[], char ynot[]) 272 { 273 LilXML *lp = newLilXML(); 274 XMLEle *root; 275 276 do { 277 root = readXMLEle (lp, *buf++, ynot); 278 } while (!root && !ynot[0]); 279 280 delLilXML (lp); 281 282 return (root); 283 } 284 285 /* return a deep copy of the given XMLEle * 286 */ 287 XMLEle * 288 cloneXMLEle (XMLEle *ep) 289 { 290 char *buf; 291 char ynot[1024]; 292 XMLEle *newep; 293 294 buf = (*mymalloc) (sprlXMLEle (ep, 0) + 1); 295 sprXMLEle (buf, ep, 0); 296 newep = parseXML (buf, ynot); 297 (*myfree) (buf); 298 299 return (newep); 264 300 } 265 301 … … 270 306 findXMLAtt (XMLEle *ep, const char *name) 271 307 { 272 273 274 275 276 277 308 int i; 309 310 for (i = 0; i < ep->nat; i++) 311 if (!strcmp (ep->at[i]->name.s, name)) 312 return (ep->at[i]); 313 return (NULL); 278 314 } 279 315 … … 284 320 findXMLEle (XMLEle *ep, const char *tag) 285 321 { 286 287 288 289 290 291 292 293 294 322 int tl = strlen (tag); 323 int i; 324 325 for (i = 0; i < ep->nel; i++) { 326 String *sp = &ep->el[i]->tag; 327 if (sp->sl == tl && !strcmp (sp->s, tag)) 328 return (ep->el[i]); 329 } 330 return (NULL); 295 331 } 296 332 … … 302 338 nextXMLEle (XMLEle *ep, int init) 303 339 { 304 305 306 307 308 309 310 311 312 340 int eit; 341 342 if (init) 343 ep->eit = 0; 344 345 eit = ep->eit++; 346 if (eit < 0 || eit >= ep->nel) 347 return (NULL); 348 return (ep->el[eit]); 313 349 } 314 350 … … 320 356 nextXMLAtt (XMLEle *ep, int init) 321 357 { 322 323 324 325 326 327 328 329 330 358 int ait; 359 360 if (init) 361 ep->ait = 0; 362 363 ait = ep->ait++; 364 if (ait < 0 || ait >= ep->nat) 365 return (NULL); 366 return (ep->at[ait]); 331 367 } 332 368 … … 335 371 parentXMLEle (XMLEle *ep) 336 372 { 337 373 return (ep->pe); 338 374 } 339 375 … … 342 378 parentXMLAtt (XMLAtt *ap) 343 379 { 344 380 return (ap->ce); 345 381 } 346 382 … … 351 387 tagXMLEle (XMLEle *ep) 352 388 { 353 389 return (ep->tag.s); 354 390 } 355 391 … … 358 394 pcdataXMLEle (XMLEle *ep) 359 395 { 360 396 return (ep->pcdata.s); 361 397 } 362 398 363 399 /* return the number of characters in the pcdata portion of the given element */ 364 int 400 int 365 401 pcdatalenXMLEle (XMLEle *ep) 366 402 { 367 403 return (ep->pcdata.sl); 368 404 } 369 405 … … 372 408 nameXMLAtt (XMLAtt *ap) 373 409 { 374 410 return (ap->name.s); 375 411 } 376 412 … … 379 415 valuXMLAtt (XMLAtt *ap) 380 416 { 381 417 return (ap->valu.s); 382 418 } 383 419 … … 386 422 nXMLEle (XMLEle *ep) 387 423 { 388 424 return (ep->nel); 389 425 } 390 426 … … 393 429 nXMLAtt (XMLEle *ep) 394 430 { 395 431 return (ep->nat); 396 432 } 397 433 … … 403 439 findXMLAttValu (XMLEle *ep, const char *name) 404 440 { 405 406 441 XMLAtt *a = findXMLAtt (ep, name); 442 return (a ? a->valu.s : ""); 407 443 } 408 444 409 445 /* handy wrapper to read one xml file. 410 * return root element else NULL with report in errmsg[]446 * return root element else NULL with report in ynot[] 411 447 */ 412 448 XMLEle * 413 readXMLFile (FILE *fp, LilXML *lp, char errmsg[])414 { 415 416 417 418 XMLEle *root = readXMLEle (lp, c, errmsg);419 if (root || errmsg[0])420 421 422 423 449 readXMLFile (FILE *fp, LilXML *lp, char ynot[]) 450 { 451 int c; 452 453 while ((c = fgetc(fp)) != EOF) { 454 XMLEle *root = readXMLEle (lp, c, ynot); 455 if (root || ynot[0]) 456 return (root); 457 } 458 459 return (NULL); 424 460 } 425 461 … … 430 466 addXMLEle (XMLEle *parent, const char *tag) 431 467 { 432 XMLEle *ep = growEle (parent); 433 appendString (&ep->tag, tag); 434 return (ep); 468 XMLEle *ep = growEle (parent); 469 appendString (&ep->tag, tag); 470 return (ep); 471 } 472 473 /* append an existing element to the given element. 474 * N.B. be mindful of when these are deleted, this is not a deep copy. 475 */ 476 void 477 appXMLEle (XMLEle *ep, XMLEle *newep) 478 { 479 ep->el = (XMLEle **) moremem (ep->el, (ep->nel+1)*sizeof(XMLEle *)); 480 ep->el[ep->nel++] = newep; 435 481 } 436 482 … … 439 485 editXMLEle (XMLEle *ep, const char *pcdata) 440 486 { 441 442 443 487 freeString (&ep->pcdata); 488 appendString (&ep->pcdata, pcdata); 489 ep->pcdata_hasent = (strpbrk (pcdata, entities) != NULL); 444 490 } 445 491 … … 448 494 addXMLAtt (XMLEle *ep, const char *name, const char *valu) 449 495 { 450 451 452 453 496 XMLAtt *ap = growAtt (ep); 497 appendString (&ap->name, name); 498 appendString (&ap->valu, valu); 499 return (ap); 454 500 } 455 501 … … 458 504 rmXMLAtt (XMLEle *ep, const char *name) 459 505 { 460 461 462 463 464 465 466 467 468 506 int i; 507 508 for (i = 0; i < ep->nat; i++) { 509 if (strcmp (ep->at[i]->name.s, name) == 0) { 510 freeAtt (ep->at[i]); 511 memmove (&ep->at[i],&ep->at[i+1],(--ep->nat-i)*sizeof(XMLAtt*)); 512 return; 513 } 514 } 469 515 } 470 516 … … 473 519 editXMLAtt (XMLAtt *ap, const char *str) 474 520 { 475 476 521 freeString (&ap->valu); 522 appendString (&ap->valu, str); 477 523 } 478 524 … … 484 530 prXMLEle (FILE *fp, XMLEle *ep, int level) 485 531 { 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 532 int indent = level*PRINDENT; 533 int i; 534 535 fprintf (fp, "%*s<%s", indent, "", ep->tag.s); 536 for (i = 0; i < ep->nat; i++) 537 fprintf (fp, " %s=\"%s\"", ep->at[i]->name.s, 538 entityXML(ep->at[i]->valu.s)); 539 if (ep->nel > 0) { 540 fprintf (fp, ">\n"); 541 for (i = 0; i < ep->nel; i++) 542 prXMLEle (fp, ep->el[i], level+1); 543 } 544 if (ep->pcdata.sl > 0) { 545 if (ep->nel == 0) 546 fprintf (fp, ">\n"); 547 if (ep->pcdata_hasent) 548 fprintf (fp, "%s", entityXML(ep->pcdata.s)); 549 else 550 fprintf (fp, "%s", ep->pcdata.s); 551 if (ep->pcdata.s[ep->pcdata.sl-1] != '\n') 552 fprintf (fp, "\n"); 553 } 554 if (ep->nel > 0 || ep->pcdata.sl > 0) 555 fprintf (fp, "%*s</%s>\n", indent, "", ep->tag.s); 556 else 557 fprintf (fp, "/>\n"); 512 558 } 513 559 … … 520 566 sprXMLEle (char *s, XMLEle *ep, int level) 521 567 { 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 568 int indent = level*PRINDENT; 569 int sl = 0; 570 int i; 571 572 sl += sprintf (s+sl, "%*s<%s", indent, "", ep->tag.s); 573 for (i = 0; i < ep->nat; i++) 574 sl += sprintf (s+sl, " %s=\"%s\"", ep->at[i]->name.s, 575 entityXML(ep->at[i]->valu.s)); 576 if (ep->nel > 0) { 577 sl += sprintf (s+sl, ">\n"); 578 for (i = 0; i < ep->nel; i++) 579 sl += sprXMLEle (s+sl, ep->el[i], level+1); 580 } 581 if (ep->pcdata.sl > 0) { 582 if (ep->nel == 0) 583 sl += sprintf (s+sl, ">\n"); 584 if (ep->pcdata_hasent) 585 sl += sprintf (s+sl, "%s", entityXML(ep->pcdata.s)); 586 else { 587 strcpy (s+sl, ep->pcdata.s); 588 sl += ep->pcdata.sl; 589 } 590 if (ep->pcdata.s[ep->pcdata.sl-1] != '\n') 591 sl += sprintf (s+sl, "\n"); 592 } 593 if (ep->nel > 0 || ep->pcdata.sl > 0) 594 sl += sprintf (s+sl, "%*s</%s>\n", indent, "", ep->tag.s); 595 else 596 sl += sprintf (s+sl, "/>\n"); 597 598 return (sl); 553 599 } 554 600 … … 560 606 sprlXMLEle (XMLEle *ep, int level) 561 607 { 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 608 int indent = level*PRINDENT; 609 int l = 0; 610 int i; 611 612 l += indent + 1 + ep->tag.sl; 613 for (i = 0; i < ep->nat; i++) 614 l += ep->at[i]->name.sl + 4 + strlen(entityXML(ep->at[i]->valu.s)); 615 616 if (ep->nel > 0) { 617 l += 2; 618 for (i = 0; i < ep->nel; i++) 619 l += sprlXMLEle (ep->el[i], level+1); 620 } 621 if (ep->pcdata.sl > 0) { 622 if (ep->nel == 0) 623 l += 2; 624 if (ep->pcdata_hasent) 625 l += strlen (entityXML(ep->pcdata.s)); 626 else 627 l += ep->pcdata.sl; 628 if (ep->pcdata.s[ep->pcdata.sl-1] != '\n') 629 l += 1; 630 } 631 if (ep->nel > 0 || ep->pcdata.sl > 0) 632 l += indent + 4 + ep->tag.sl; 633 else 634 l += 3; 635 636 return (l); 591 637 } 592 638 … … 598 644 entityXML (char *s) 599 645 { 600 static char *malbuf; 601 int nmalbuf = 0; 602 char *sret; 603 char *ep; 604 605 /* scan for each entity, if any */ 606 for (sret = s; (ep = strpbrk (s, entities)) != NULL; s = ep+1) { 607 608 /* found another entity, copy preceding to malloced buffer */ 609 int nnew = ep - s; /* all but entity itself */ 610 sret = malbuf = moremem (malbuf, nmalbuf + nnew + 10); 611 memcpy (malbuf+nmalbuf, s, nnew); 612 nmalbuf += nnew; 613 614 /* replace with entity encoding */ 615 switch (*ep) { 616 case '&': 617 nmalbuf += sprintf (malbuf+nmalbuf, "&"); 618 break; 619 case '<': 620 nmalbuf += sprintf (malbuf+nmalbuf, "<"); 621 break; 622 case '>': 623 nmalbuf += sprintf (malbuf+nmalbuf, ">"); 624 break; 625 case '\'': 626 nmalbuf += sprintf (malbuf+nmalbuf, "'"); 627 break; 628 case '"': 629 nmalbuf += sprintf (malbuf+nmalbuf, """); 630 break; 631 632 } 633 634 } 635 636 /* return s if no entities, else malloc cleaned-up copy */ 637 if (sret == s) { 638 /* using s, so free any malloced memory from last time */ 639 if (malbuf) { 640 free (malbuf); 641 malbuf = NULL; 642 } 643 } else { 644 /* put remaining part of s into malbuf */ 645 int nleft = strlen (s) + 1; /* include \0 */ 646 sret = malbuf = moremem (malbuf, nmalbuf + nleft); 647 memcpy (malbuf+nmalbuf, s, nleft); 648 } 649 650 return (sret); 651 } 646 static char *malbuf; 647 int nmalbuf = 0; 648 char *sret; 649 char *ep; 650 651 /* scan for each entity, if any */ 652 for (sret = s; (ep = strpbrk (s, entities)) != NULL; s = ep+1) { 653 654 /* found another entity, copy preceding to malloced buffer */ 655 int nnew = ep - s; /* all but entity itself */ 656 sret = malbuf = moremem (malbuf, nmalbuf + nnew + 10); 657 memcpy (malbuf+nmalbuf, s, nnew); 658 nmalbuf += nnew; 659 660 /* replace with entity encoding */ 661 switch (*ep) { 662 case '&': 663 nmalbuf += sprintf (malbuf+nmalbuf, "&"); 664 break; 665 case '<': 666 nmalbuf += sprintf (malbuf+nmalbuf, "<"); 667 break; 668 case '>': 669 nmalbuf += sprintf (malbuf+nmalbuf, ">"); 670 break; 671 case '\'': 672 nmalbuf += sprintf (malbuf+nmalbuf, "'"); 673 break; 674 case '"': 675 nmalbuf += sprintf (malbuf+nmalbuf, """); 676 break; 677 678 } 679 680 } 681 682 /* return s if no entities, else malloc cleaned-up copy */ 683 if (sret == s) { 684 /* using s, so free any malloced memory from last time */ 685 if (malbuf) { 686 free (malbuf); 687 malbuf = NULL; 688 } 689 } else { 690 /* put remaining part of s into malbuf */ 691 int nleft = strlen (s) + 1; /* include \0 */ 692 sret = malbuf = moremem (malbuf, nmalbuf + nleft); 693 memcpy (malbuf+nmalbuf, s, nleft); 694 } 695 696 return (sret); 697 } 698 699 700 652 701 653 702 /* if ent is a recognized xml entity sequence, set *cp to char and return 1 … … 657 706 decodeEntity (char *ent, int *cp) 658 707 { 659 660 constchar *ent;661 662 663 664 665 666 667 668 669 unsignedint i;670 671 672 673 674 675 676 677 678 708 static struct { 709 char *ent; 710 char c; 711 } enttable[] = { 712 {"&", '&'}, 713 {"'", '\''}, 714 {"<", '<'}, 715 {">", '>'}, 716 {""", '"'}, 717 }; 718 int i; 719 720 for (i = 0; i < sizeof(enttable)/sizeof(enttable[0]); i++) { 721 if (strcmp (ent, enttable[i].ent) == 0) { 722 *cp = enttable[i].c; 723 return (1); 724 } 725 } 726 727 return (0); 679 728 } 680 729 … … 682 731 * if find final closure, return 1 and tree is in ce. 683 732 * if need more, return 0. 684 * if real trouble, return -1 and put reason in errmsg.733 * if real trouble, return -1 and put reason in ynot. 685 734 */ 686 735 static int 687 oneXMLchar (LilXML *lp, int c, char errmsg[])688 { 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 sprintf (errmsg, "Line %d: Bogus tag char %c", lp->ln, c);704 705 706 707 708 709 710 711 712 713 714 715 else 716 717 718 719 720 721 722 723 724 725 726 727 728 729 sprintf (errmsg, "Line %d: Bogus leading attr name char: %c",730 731 732 733 734 735 736 737 738 739 740 741 742 sprintf (errmsg, "Line %d: Bogus char %c before >", lp->ln, c);743 744 745 746 747 748 749 750 751 752 753 sprintf (errmsg, "Line %d: Bogus attr name char: %c", lp->ln,c);754 755 756 757 758 759 760 761 762 763 sprintf (errmsg, "Line %d: No value for attribute %s", lp->ln,764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 sprintf (errmsg, "Line %d: Bogus preend tag char %c", lp->ln,c);855 856 857 858 859 860 861 862 863 864 sprintf (errmsg,"Line %d: closing tag %s does not match %s",865 866 867 868 869 870 871 872 873 sprintf (errmsg, "Line %d: Bogus end tag char %c", lp->ln, c);874 875 876 877 878 879 736 oneXMLchar (LilXML *lp, int c, char ynot[]) 737 { 738 switch (lp->cs) { 739 case LOOK4START: /* looking for first element start */ 740 if (c == '<') { 741 pushXMLEle(lp); 742 lp->cs = LOOK4TAG; 743 } 744 /* silently ignore until resync */ 745 break; 746 747 case LOOK4TAG: /* looking for element tag */ 748 if (isTokenChar (1, c)) { 749 growString (&lp->ce->tag, c); 750 lp->cs = INTAG; 751 } else if (!isspace(c)) { 752 sprintf (ynot, "Line %d: Bogus tag char %c", lp->ln, c); 753 return (-1); 754 } 755 break; 756 757 case INTAG: /* reading tag */ 758 if (isTokenChar (0, c)) 759 growString (&lp->ce->tag, c); 760 else if (c == '>') 761 lp->cs = LOOK4CON; 762 else if (c == '/') 763 lp->cs = SAWSLASH; 764 else 765 lp->cs = LOOK4ATTRN; 766 break; 767 768 case LOOK4ATTRN: /* looking for attr name, > or / */ 769 if (c == '>') 770 lp->cs = LOOK4CON; 771 else if (c == '/') 772 lp->cs = SAWSLASH; 773 else if (isTokenChar (1, c)) { 774 XMLAtt *ap = growAtt(lp->ce); 775 growString (&ap->name, c); 776 lp->cs = INATTRN; 777 } else if (!isspace(c)) { 778 sprintf (ynot, "Line %d: Bogus leading attr name char: %c", 779 lp->ln, c); 780 return (-1); 781 } 782 break; 783 784 case SAWSLASH: /* saw / in element opening */ 785 if (c == '>') { 786 if (!lp->ce->pe) 787 return(1); /* root has no content */ 788 popXMLEle(lp); 789 lp->cs = LOOK4CON; 790 } else { 791 sprintf (ynot, "Line %d: Bogus char %c before >", lp->ln, c); 792 return (-1); 793 } 794 break; 795 796 case INATTRN: /* reading attr name */ 797 if (isTokenChar (0, c)) 798 growString (&lp->ce->at[lp->ce->nat-1]->name, c); 799 else if (isspace(c) || c == '=') 800 lp->cs = LOOK4ATTRV; 801 else { 802 sprintf (ynot, "Line %d: Bogus attr name char: %c", lp->ln,c); 803 return (-1); 804 } 805 break; 806 807 case LOOK4ATTRV: /* looking for attr value */ 808 if (c == '\'' || c == '"') { 809 lp->delim = c; 810 lp->cs = INATTRV; 811 } else if (!(isspace(c) || c == '=')) { 812 sprintf (ynot, "Line %d: No value for attribute %s", lp->ln, 813 lp->ce->at[lp->ce->nat-1]->name.s); 814 return (-1); 815 } 816 break; 817 818 case INATTRV: /* in attr value */ 819 if (c == '&') { 820 newString (&lp->entity); 821 growString (&lp->entity, c); 822 lp->cs = ENTINATTRV; 823 } else if (c == lp->delim) 824 lp->cs = LOOK4ATTRN; 825 else if (!iscntrl(c)) 826 growString (&lp->ce->at[lp->ce->nat-1]->valu, c); 827 break; 828 829 case ENTINATTRV: /* working on entity in attr valu */ 830 if (c == ';') { 831 /* if find a recongized esp seq, add equiv char else raw seq */ 832 growString (&lp->entity, c); 833 if (decodeEntity (lp->entity.s, &c)) 834 growString (&lp->ce->at[lp->ce->nat-1]->valu, c); 835 else 836 appendString(&lp->ce->at[lp->ce->nat-1]->valu,lp->entity.s); 837 freeString (&lp->entity); 838 lp->cs = INATTRV; 839 } else 840 growString (&lp->entity, c); 841 break; 842 843 case LOOK4CON: /* skipping leading content whitespace*/ 844 if (c == '<') 845 lp->cs = SAWLTINCON; 846 else if (!isspace(c)) { 847 growString (&lp->ce->pcdata, c); 848 lp->cs = INCON; 849 } 850 break; 851 852 case INCON: /* reading content */ 853 if (c == '&') { 854 newString (&lp->entity); 855 growString (&lp->entity, c); 856 lp->cs = ENTINCON; 857 } else if (c == '<') { 858 /* chomp trailing whitespace */ 859 while (lp->ce->pcdata.sl > 0 && 860 isspace(lp->ce->pcdata.s[lp->ce->pcdata.sl-1])) 861 lp->ce->pcdata.s[--(lp->ce->pcdata.sl)] = '\0'; 862 lp->cs = SAWLTINCON; 863 } else { 864 growString (&lp->ce->pcdata, c); 865 } 866 break; 867 868 case ENTINCON: /* working on entity in content */ 869 if (c == ';') { 870 /* if find a recognized esc seq, add equiv char else raw seq */ 871 growString (&lp->entity, c); 872 if (decodeEntity (lp->entity.s, &c)) 873 growString (&lp->ce->pcdata, c); 874 else { 875 appendString(&lp->ce->pcdata, lp->entity.s); 876 lp->ce->pcdata_hasent = 1; 877 } 878 freeString (&lp->entity); 879 lp->cs = INCON; 880 } else 881 growString (&lp->entity, c); 882 break; 883 884 case SAWLTINCON: /* saw < in content */ 885 if (c == '/') { 886 resetEndTag(lp); 887 lp->cs = LOOK4CLOSETAG; 888 } else { 889 pushXMLEle(lp); 890 if (isTokenChar(1,c)) { 891 growString (&lp->ce->tag, c); 892 lp->cs = INTAG; 893 } else 894 lp->cs = LOOK4TAG; 895 } 896 break; 897 898 case LOOK4CLOSETAG: /* looking for closing tag after < */ 899 if (isTokenChar (1, c)) { 900 growString (&lp->endtag, c); 901 lp->cs = INCLOSETAG; 902 } else if (!isspace(c)) { 903 sprintf (ynot, "Line %d: Bogus preend tag char %c", lp->ln,c); 904 return (-1); 905 } 906 break; 907 908 case INCLOSETAG: /* reading closing tag */ 909 if (isTokenChar(0, c)) 910 growString (&lp->endtag, c); 911 else if (c == '>') { 912 if (strcmp (lp->ce->tag.s, lp->endtag.s)) { 913 sprintf (ynot,"Line %d: closing tag %s does not match %s", 914 lp->ln, lp->endtag.s, lp->ce->tag.s); 915 return (-1); 916 } else if (lp->ce->pe) { 917 popXMLEle(lp); 918 lp->cs = LOOK4CON; /* back to content after nested elem */ 919 } else 920 return (1); /* yes! */ 921 } else if (!isspace(c)) { 922 sprintf (ynot, "Line %d: Bogus end tag char %c", lp->ln, c); 923 return (-1); 924 } 925 break; 926 } 927 928 return (0); 880 929 } 881 930 … … 884 933 initParser(LilXML *lp) 885 934 { 886 887 888 889 890 891 935 delXMLEle (lp->ce); 936 freeString (&lp->endtag); 937 memset (lp, 0, sizeof(*lp)); 938 newString (&lp->endtag); 939 lp->cs = LOOK4START; 940 lp->ln = 1; 892 941 } 893 942 … … 900 949 pushXMLEle(LilXML *lp) 901 950 { 902 903 951 lp->ce = growEle (lp->ce); 952 resetEndTag(lp); 904 953 } 905 954 … … 910 959 popXMLEle(LilXML *lp) 911 960 { 912 913 961 lp->ce = lp->ce->pe; 962 resetEndTag(lp); 914 963 } 915 964 … … 918 967 growEle (XMLEle *pe) 919 968 { 920 921 922 923 924 925 926 927 928 929 930 931 932 969 XMLEle *newe = (XMLEle *) moremem (NULL, sizeof(XMLEle)); 970 971 memset (newe, 0, sizeof(XMLEle)); 972 newString (&newe->tag); 973 newString (&newe->pcdata); 974 newe->pe = pe; 975 976 if (pe) { 977 pe->el = (XMLEle **) moremem (pe->el, (pe->nel+1)*sizeof(XMLEle *)); 978 pe->el[pe->nel++] = newe; 979 } 980 981 return (newe); 933 982 } 934 983 … … 937 986 growAtt(XMLEle *ep) 938 987 { 939 940 941 942 943 944 945 946 947 948 949 988 XMLAtt *newa = (XMLAtt *) moremem (NULL, sizeof(XMLAtt)); 989 990 memset (newa, 0, sizeof(*newa)); 991 newString(&newa->name); 992 newString(&newa->valu); 993 newa->ce = ep; 994 995 ep->at = (XMLAtt **) moremem (ep->at, (ep->nat+1)*sizeof(XMLAtt *)); 996 ep->at[ep->nat++] = newa; 997 998 return (newa); 950 999 } 951 1000 … … 954 1003 freeAtt (XMLAtt *a) 955 1004 { 956 957 958 959 960 1005 if (!a) 1006 return; 1007 freeString (&a->name); 1008 freeString (&a->valu); 1009 (*myfree)(a); 961 1010 } 962 1011 … … 965 1014 resetEndTag(LilXML *lp) 966 1015 { 967 968 1016 freeString (&lp->endtag); 1017 newString (&lp->endtag); 969 1018 } 970 1019 … … 975 1024 isTokenChar (int start, int c) 976 1025 { 977 1026 return (isalpha(c) || c == '_' || (!start && isdigit(c))); 978 1027 } 979 1028 … … 982 1031 growString (String *sp, int c) 983 1032 { 984 985 986 987 988 989 990 991 992 993 994 1033 int l = sp->sl + 2; /* need room for '\0' plus c */ 1034 1035 if (l > sp->sm) { 1036 if (!sp->s) 1037 newString (sp); 1038 else 1039 sp->s = (char *) moremem (sp->s, sp->sm *= 2); 1040 } 1041 sp->s[--l] = '\0'; 1042 sp->s[--l] = (char)c; 1043 sp->sl++; 995 1044 } 996 1045 … … 999 1048 appendString (String *sp, const char *str) 1000 1049 { 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 sp->sl += strl; 1050 int strl = strlen (str); 1051 int l = sp->sl + strl + 1; /* need room for '\0' */ 1052 1053 if (l > sp->sm) { 1054 if (!sp->s) 1055 newString (sp); 1056 if (l > sp->sm) 1057 sp->s = (char *) moremem (sp->s, (sp->sm = l)); 1058 } 1059 strcpy (&sp->s[sp->sl], str); 1060 sp->sl += strl; 1012 1061 } 1013 1062 … … 1016 1065 newString(String *sp) 1017 1066 { 1018 1019 1020 1021 1067 sp->s = (char *)moremem(NULL, MINMEM); 1068 sp->sm = MINMEM; 1069 *sp->s = '\0'; 1070 sp->sl = 0; 1022 1071 } 1023 1072 … … 1026 1075 freeString (String *sp) 1027 1076 { 1028 1029 1030 1031 1032 1077 if (sp->s) 1078 (*myfree) (sp->s); 1079 sp->s = NULL; 1080 sp->sl = 0; 1081 sp->sm = 0; 1033 1082 } 1034 1083 … … 1037 1086 moremem (void *old, int n) 1038 1087 { 1039 1088 return (old ? (*myrealloc)(old, n) : (*mymalloc)(n)); 1040 1089 } 1041 1090 … … 1044 1093 main (int ac, char *av[]) 1045 1094 { 1046 1047 char errmsg[1024];1048 1049 1050 root = readXMLFile (stdin, lp, errmsg);1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 } else if (errmsg[0]) {1072 fprintf (stderr, "Error: %s\n", errmsg);1073 1074 1075 1076 1077 1095 LilXML *lp = newLilXML(); 1096 char ynot[1024]; 1097 XMLEle *root; 1098 1099 root = readXMLFile (stdin, lp, ynot); 1100 if (root) { 1101 char *str; 1102 int l; 1103 1104 if (ac > 1) { 1105 XMLEle *theend = addXMLEle (root, "theend"); 1106 editXMLEle (theend, "Added to test editing"); 1107 addXMLAtt (theend, "hello", "world"); 1108 } 1109 1110 fprintf (stderr, "::::::::::::: %s\n", tagXMLEle(root)); 1111 prXMLEle (stdout, root, 0); 1112 1113 l = sprlXMLEle (root, 0); 1114 str = malloc (l+1); 1115 fprintf (stderr, "::::::::::::: %s : %d : %d", 1116 tagXMLEle(root), l, sprXMLEle (str, root, 0)); 1117 fprintf (stderr, ": %d\n", printf ("%s", str)); 1118 1119 delXMLEle (root); 1120 } else if (ynot[0]) { 1121 fprintf (stderr, "Error: %s\n", ynot); 1122 } 1123 1124 delLilXML (lp); 1125 1126 return (0); 1078 1127 } 1079 1128 #endif 1080
Note: See TracChangeset
for help on using the changeset viewer.