#include "common.h"#include "dystring.h"#include "errabort.h"#include "hash.h"#include "xp.h"#include "xmlEscape.h"Include dependency graph for xp.c:

Go to the source code of this file.
Defines | |
| #define | xpGetChar(xp) (xp->in < xp->inBufEnd ? *xp->in++ : xpNextBuf(xp)) |
| #define | xpUngetChar(xp) (--xp->in) |
Functions | |
| char | xpNextBuf (struct xp *xp) |
| xp * | xpNew (void *userData, void(*atStartTag)(void *userData, char *name, char **atts), void(*atEndTag)(void *userData, char *name, char *text), int(*read)(void *userData, char *buf, int bufSize), char *fileName) |
| int | xpReadFromFile (void *userData, char *buf, int bufSize) |
| void | xpFree (struct xp **pXp) |
| int | xpLineIx (struct xp *xp) |
| char * | xpFileName (struct xp *xp) |
| void | xpError (struct xp *xp, char *format,...) |
| static void | xpUnexpectedEof (struct xp *xp) |
| static void | xpEatComment (struct xp *xp, char commentC) |
| static void | xpLookup (struct xp *xp, struct dyString *temp, struct dyString *text) |
| void | xpForceMatch (struct xp *xp, char *matchString) |
| void | xpTextUntil (struct xp *xp, char *endPattern) |
| void | xpParseStartTag (struct xp *xp, int maxAttCount, struct dyString *retName, int *retAttCount, struct dyString **retAttributes, boolean *retClosed) |
| void | xpParseEndTag (struct xp *xp, char *tagName) |
| boolean | xpParseNext (struct xp *xp, char *tag) |
| void | xpParse (struct xp *xp) |
Variables | |
| static char const | rcsid [] = "$Id: xp.c,v 1.15 2005/12/19 17:51:14 kent Exp $" |
Definition at line 30 of file xp.c.
Referenced by xpEatComment(), xpForceMatch(), xpLookup(), xpParseEndTag(), xpParseNext(), xpParseStartTag(), and xpTextUntil().
| static void xpEatComment | ( | struct xp * | xp, | |
| char | commentC | |||
| ) | [static] |
Definition at line 129 of file xp.c.
References xp::lineIx, xpError(), and xpGetChar.
Referenced by xpParseNext().
00131 { 00132 int startLine = xp->lineIx; 00133 char lastC = 0; 00134 char c; 00135 for (;;) 00136 { 00137 if ((c = xpGetChar(xp)) == 0) 00138 xpError(xp, "End of file in comment that started line %d", startLine); 00139 if (c == '\n') 00140 ++xp->lineIx; 00141 if (c == '>') 00142 { 00143 if (lastC == commentC || commentC == '!') 00144 break; 00145 } 00146 lastC = c; 00147 } 00148 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void xpError | ( | struct xp * | xp, | |
| char * | format, | |||
| ... | ||||
| ) |
Definition at line 113 of file xp.c.
References errAbort(), vaWarn(), xpFileName(), and xpLineIx().
Referenced by xpEatComment(), xpForceMatch(), xpLookup(), xpParseEndTag(), xpParseNext(), xpParseStartTag(), and xpUnexpectedEof().
00115 { 00116 va_list args; 00117 va_start(args, format); 00118 vaWarn(format, args); 00119 errAbort("line %d of %s", xpLineIx(xp), xpFileName(xp)); 00120 va_end(args); 00121 }
Here is the call graph for this function:

Here is the caller graph for this function:

| char* xpFileName | ( | struct xp * | xp | ) |
Definition at line 107 of file xp.c.
References xp::fileName.
Referenced by xpError().
00109 { 00110 return xp->fileName; 00111 }
Here is the caller graph for this function:

| void xpForceMatch | ( | struct xp * | xp, | |
| char * | matchString | |||
| ) |
| void xpFree | ( | struct xp ** | pXp | ) |
Definition at line 73 of file xp.c.
References ArraySize, xp::attDyBuf, xp::endTag, xp::fileName, freeDyString(), freeMem(), freez(), hashFree, xp::stackBuf, xp::stackBufEnd, xp::symHash, xpStack::tag, and xpStack::text.
Referenced by xapFree().
00075 { 00076 int i; 00077 struct xp *xp = *pXp; 00078 if (xp != NULL) 00079 { 00080 struct xpStack *stack; 00081 for (stack = xp->stackBufEnd; --stack >= xp->stackBuf; ) 00082 { 00083 if (stack->tag == NULL) 00084 break; 00085 freeDyString(&stack->tag); 00086 freeDyString(&stack->text); 00087 } 00088 for (i=0; i<ArraySize(xp->attDyBuf); ++i) 00089 { 00090 if (xp->attDyBuf[i] == NULL) 00091 break; 00092 freeDyString(&xp->attDyBuf[i]); 00093 } 00094 freeDyString(&xp->endTag); 00095 freeMem(xp->fileName); 00096 hashFree(&xp->symHash); 00097 freez(pXp); 00098 } 00099 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int xpLineIx | ( | struct xp * | xp | ) |
Definition at line 101 of file xp.c.
References xp::lineIx.
Referenced by xapError(), and xpError().
00103 { 00104 return xp->lineIx; 00105 }
Here is the caller graph for this function:

Definition at line 150 of file xp.c.
References dyStringAppend(), dyStringAppendC(), dyStringClear, hashFindVal(), dyString::string, xp::symHash, xpStack::text, xpError(), and xpGetChar.
Referenced by xpParseNext(), and xpParseStartTag().
00152 { 00153 char c; 00154 char *s; 00155 dyStringClear(temp); 00156 for (;;) 00157 { 00158 if ((c = xpGetChar(xp)) == 0) 00159 xpError(xp, "End of file in after & and before ;"); 00160 if (isspace(c)) 00161 xpError(xp, "& without ;"); 00162 if (c == ';') 00163 break; 00164 dyStringAppendC(temp, c); 00165 } 00166 s = temp->string; 00167 if (s[0] == '#') 00168 { 00169 c = atoi(s+1); 00170 dyStringAppendC(text, c); 00171 } 00172 else if ((s = hashFindVal(xp->symHash, s)) == NULL) 00173 { 00174 dyStringAppendC(text, '&'); 00175 dyStringAppend(text, temp->string); 00176 dyStringAppendC(text, ';'); 00177 } 00178 else 00179 { 00180 dyStringAppend(text, s); 00181 } 00182 }
Here is the call graph for this function:

Here is the caller graph for this function:

| struct xp* xpNew | ( | void * | userData, | |
| void(*)(void *userData, char *name, char **atts) | atStartTag, | |||
| void(*)(void *userData, char *name, char *text) | atEndTag, | |||
| int(*)(void *userData, char *buf, int bufSize) | read, | |||
| char * | fileName | |||
| ) | [read] |
Definition at line 38 of file xp.c.
References AllocVar, ArraySize, xp::atEndTag, xp::atStartTag, cloneString(), xp::endTag, xp::fileName, xp::in, xp::inBuf, xp::inBufEnd, xp::lineIx, newDyString(), xp::read, xp::stack, xp::stackBuf, xp::stackBufEnd, xp::symHash, xp::userData, and xmlEscapeSymHash().
Referenced by xapNew().
00045 { 00046 struct xp *xp; 00047 AllocVar(xp); 00048 xp->stack = xp->stackBufEnd = xp->stackBuf + ArraySize(xp->stackBuf); 00049 xp->userData = userData; 00050 xp->atStartTag = atStartTag; 00051 xp->atEndTag = atEndTag; 00052 xp->read = read; 00053 xp->lineIx = 1; 00054 xp->endTag = newDyString(64); 00055 if (fileName) 00056 xp->fileName = cloneString(fileName); 00057 else 00058 xp->fileName = cloneString("XML"); 00059 xp->inBufEnd = xp->in = xp->inBuf; 00060 xp->symHash = xmlEscapeSymHash(); 00061 return xp; 00062 }
Here is the call graph for this function:

Here is the caller graph for this function:

| char xpNextBuf | ( | struct xp * | xp | ) |
Definition at line 19 of file xp.c.
References xp::in, xp::inBuf, xp::inBufEnd, xp::read, hash::size, and xp::userData.
00021 { 00022 int size = xp->read(xp->userData, xp->inBuf, sizeof(xp->inBuf)); 00023 if (size <= 0) 00024 return 0; 00025 xp->inBufEnd = xp->inBuf + size; 00026 xp->in = xp->inBuf+1; 00027 return xp->inBuf[0]; 00028 }
| void xpParse | ( | struct xp * | xp | ) |
Definition at line 549 of file xp.c.
References xpParseNext().
Referenced by xapParseFile().
00551 { 00552 xpParseNext(xp, NULL); 00553 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void xpParseEndTag | ( | struct xp * | xp, | |
| char * | tagName | |||
| ) |
Definition at line 391 of file xp.c.
References dyStringAppendC(), dyStringClear, xp::endTag, xp::lineIx, sameString, dyString::string, xpError(), xpGetChar, and xpUnexpectedEof().
Referenced by xpParseNext().
00394 { 00395 struct dyString *dy = xp->endTag; 00396 char c; 00397 00398 dyStringClear(dy); 00399 00400 /* Skip leading space. */ 00401 for (;;) 00402 { 00403 if ((c = xpGetChar(xp)) == 0) 00404 xpUnexpectedEof(xp); 00405 if (isspace(c)) 00406 { 00407 if (c == '\n') 00408 ++xp->lineIx; 00409 } 00410 else 00411 break; 00412 } 00413 00414 /* Read end tag. */ 00415 for (;;) 00416 { 00417 dyStringAppendC(dy, c); 00418 if ((c = xpGetChar(xp)) == 0) 00419 xpUnexpectedEof(xp); 00420 if (isspace(c)) 00421 { 00422 if (c == '\n') 00423 ++xp->lineIx; 00424 break; 00425 } 00426 if (c == '>') 00427 break; 00428 } 00429 00430 /* Skip until '>' */ 00431 while (c != '>') 00432 { 00433 dyStringAppendC(dy, c); 00434 if ((c = xpGetChar(xp)) == 0) 00435 xpUnexpectedEof(xp); 00436 if (isspace(c)) 00437 { 00438 if (c == '\n') 00439 ++xp->lineIx; 00440 } 00441 else if (c != '>') 00442 xpError(xp, "Unexpected characters past first word in /%s tag", dy->string); 00443 } 00444 00445 if (!sameString(dy->string, tagName)) 00446 xpError(xp, "Mismatch between start tag %s and end tag %s", tagName, dy->string); 00447 }
Here is the call graph for this function:

Here is the caller graph for this function:

| boolean xpParseNext | ( | struct xp * | xp, | |
| char * | tag | |||
| ) |
Definition at line 449 of file xp.c.
References ArraySize, xp::atEndTag, dyStringAppendC(), dyStringClear, xp::endTag, FALSE, xp::lineIx, newDyString(), sameString, xp::stack, xp::stackBufEnd, dyString::string, xpStack::tag, xpStack::text, TRUE, xp::userData, xpEatComment(), xpError(), xpGetChar, xpLookup(), xpParseEndTag(), xpParseStartTag(), and xpUngetChar.
Referenced by xapNext(), and xpParse().
00455 { 00456 char c; 00457 int i, attCount = 0; 00458 struct dyString *text = NULL; 00459 boolean isClosed; 00460 boolean inside = (tag == NULL); 00461 struct xpStack *initialStack = xp->stack; 00462 00463 for (;;) 00464 { 00465 /* Load up text until next tag. */ 00466 for (;;) 00467 { 00468 if ((c = xpGetChar(xp)) == 0) 00469 return FALSE; 00470 if (c == '<') 00471 break; 00472 if (c == '&') 00473 xpLookup(xp, xp->endTag, text); 00474 else 00475 { 00476 if (c == '\n') 00477 ++xp->lineIx; 00478 if (text != NULL) 00479 dyStringAppendC(text, c); 00480 } 00481 } 00482 00483 /* Get next character to figure out what type of tag. */ 00484 c = xpGetChar(xp); 00485 if (c == 0) 00486 xpError(xp, "End of file inside tag"); 00487 else if (c == '?' || c == '!') 00488 xpEatComment(xp, c); 00489 else if (c == '/') /* Closing tag. */ 00490 { 00491 struct xpStack *stack = xp->stack; 00492 if (stack >= xp->stackBufEnd) 00493 xpError(xp, "Extra end tag"); 00494 xpParseEndTag(xp, stack->tag->string); 00495 if (inside) 00496 xp->atEndTag(xp->userData, stack->tag->string, stack->text->string); 00497 xp->stack += 1; 00498 if (xp->stack == initialStack) 00499 return TRUE; 00500 } 00501 else /* Start tag. */ 00502 { 00503 /* Push new frame on stack and check for overflow and unallocated strings. */ 00504 struct xpStack *stack = --xp->stack; 00505 if (stack < xp->stackBuf) 00506 xpError(xp, "Stack overflow"); 00507 if (stack->tag == NULL) 00508 stack->tag = newDyString(32); 00509 else 00510 dyStringClear(stack->tag); 00511 if (stack->text == NULL) 00512 stack->text = newDyString(256); 00513 else 00514 dyStringClear(stack->text); 00515 text = stack->text; 00516 00517 /* Parse the start tag. */ 00518 xpUngetChar(xp); 00519 xpParseStartTag(xp, ArraySize(xp->attDyBuf), stack->tag, 00520 &attCount, xp->attDyBuf, &isClosed); 00521 00522 if (!inside && sameString(stack->tag->string, tag)) 00523 { 00524 inside = TRUE; 00525 initialStack = xp->stack + 1; 00526 } 00527 00528 /* Call user start function, and if closed tag, end function too. */ 00529 if (inside) 00530 { 00531 /* Unpack attributes into simple array of strings. */ 00532 for (i=0; i<attCount; ++i) 00533 xp->attBuf[i] = xp->attDyBuf[i]->string; 00534 xp->attBuf[attCount] = NULL; 00535 xp->atStartTag(xp->userData, stack->tag->string, xp->attBuf); 00536 } 00537 if (isClosed) 00538 { 00539 if (inside) 00540 xp->atEndTag(xp->userData, stack->tag->string, stack->text->string); 00541 xp->stack += 1; 00542 if (xp->stack == initialStack) 00543 return TRUE; 00544 } 00545 } 00546 } 00547 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void xpParseStartTag | ( | struct xp * | xp, | |
| int | maxAttCount, | |||
| struct dyString * | retName, | |||
| int * | retAttCount, | |||
| struct dyString ** | retAttributes, | |||
| boolean * | retClosed | |||
| ) |
Definition at line 223 of file xp.c.
References dyStringAppendC(), dyStringClear, xp::endTag, xp::lineIx, newDyString(), xpError(), xpGetChar, xpLookup(), and xpUnexpectedEof().
Referenced by xpParseNext().
00231 { 00232 char c, quotC; 00233 int attCount = 0; 00234 struct dyString *dy; 00235 int lineStart; 00236 00237 dyStringClear(retName); 00238 00239 /* Skip white space after '<' and before tag name. */ 00240 for (;;) 00241 { 00242 if ((c = xpGetChar(xp)) == 0) 00243 xpUnexpectedEof(xp); 00244 if (isspace(c)) 00245 { 00246 if (c == '\n') 00247 ++xp->lineIx; 00248 } 00249 else 00250 break; 00251 } 00252 00253 /* Read in tag name. */ 00254 for (;;) 00255 { 00256 dyStringAppendC(retName, c); 00257 if ((c = xpGetChar(xp)) == 0) 00258 xpUnexpectedEof(xp); 00259 if (c == '>' || c == '/' || isspace(c)) 00260 break; 00261 } 00262 if (c == '\n') 00263 ++xp->lineIx; 00264 00265 /* Parse attributes. */ 00266 if (c != '>' && c != '/') 00267 { 00268 for (;;) 00269 { 00270 /* Skip leading white space. */ 00271 for (;;) 00272 { 00273 if ((c = xpGetChar(xp)) == 0) 00274 xpUnexpectedEof(xp); 00275 if (isspace(c)) 00276 { 00277 if (c == '\n') 00278 ++xp->lineIx; 00279 } 00280 else 00281 break; 00282 } 00283 if (c == '>' || c == '/') 00284 break; 00285 00286 /* Allocate space in attribute table. */ 00287 if (attCount >= maxAttCount - 2) 00288 xpError(xp, "Attribute stack overflow"); 00289 dy = retAttributes[attCount]; 00290 if (dy == NULL) 00291 dy = retAttributes[attCount] = newDyString(64); 00292 else 00293 dyStringClear(dy); 00294 ++attCount; 00295 00296 /* Read until not a label character. */ 00297 for (;;) 00298 { 00299 dyStringAppendC(dy, c); 00300 if ((c = xpGetChar(xp)) == 0) 00301 xpUnexpectedEof(xp); 00302 if (isspace(c)) 00303 { 00304 if (c == '\n') 00305 ++xp->lineIx; 00306 break; 00307 } 00308 if (c == '=') 00309 break; 00310 if (c == '/' || c == '>') 00311 xpError(xp, "Expecting '=' after attribute name"); 00312 } 00313 00314 /* Skip white space until '=' */ 00315 if (c != '=') 00316 { 00317 for (;;) 00318 { 00319 if ((c = xpGetChar(xp)) == 0) 00320 xpUnexpectedEof(xp); 00321 if (isspace(c)) 00322 { 00323 if (c == '\n') 00324 ++xp->lineIx; 00325 } 00326 else 00327 break; 00328 } 00329 if (c != '=') 00330 xpError(xp, "Expecting '=' after attribute name"); 00331 } 00332 00333 /* Skip space until quote. */ 00334 for (;;) 00335 { 00336 if ((c = xpGetChar(xp)) == 0) 00337 xpUnexpectedEof(xp); 00338 else if (isspace(c)) 00339 { 00340 if (c == '\n') 00341 ++xp->lineIx; 00342 } 00343 else 00344 break; 00345 } 00346 if (c != '\'' && c != '"') 00347 xpError(xp, "Expecting quoted string after ="); 00348 00349 /* Allocate space in attribute table. */ 00350 if (attCount >= maxAttCount - 2) 00351 xpError(xp, "Attribute stack overflow"); 00352 dy = retAttributes[attCount]; 00353 if (dy == NULL) 00354 dy = retAttributes[attCount] = newDyString(64); 00355 else 00356 dyStringClear(dy); 00357 ++attCount; 00358 00359 /* Read until next quote. */ 00360 quotC = c; 00361 lineStart = xp->lineIx; 00362 for (;;) 00363 { 00364 if ((c = xpGetChar(xp)) == 0) 00365 xpError(xp, "End of file inside literal string that started at line %d", lineStart); 00366 if (c == quotC) 00367 break; 00368 if (c == '&') 00369 xpLookup(xp, xp->endTag, dy); 00370 else 00371 { 00372 if (c == '\n') 00373 ++xp->lineIx; 00374 dyStringAppendC(dy, c); 00375 } 00376 } 00377 } 00378 } 00379 if (c == '/') 00380 { 00381 *retClosed = TRUE; 00382 c = xpGetChar(xp); 00383 if (c != '>') 00384 xpError(xp, "Expecting '>' after '/'"); 00385 } 00386 else 00387 *retClosed = FALSE; 00388 *retAttCount = attCount; 00389 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int xpReadFromFile | ( | void * | userData, | |
| char * | buf, | |||
| int | bufSize | |||
| ) |
| void xpTextUntil | ( | struct xp * | xp, | |
| char * | endPattern | |||
| ) |
Definition at line 195 of file xp.c.
References dyStringAppendC(), dyStringAppendN(), xp::stack, xpStack::text, xpGetChar, and xpUnexpectedEof().
00197 { 00198 int endSize = strlen(endPattern); 00199 int endPos = 0; 00200 char c; 00201 struct dyString *dy = xp->stack->text; 00202 for (;;) 00203 { 00204 if ((c = xpGetChar(xp)) == 0) 00205 xpUnexpectedEof(xp); 00206 if (c == endPattern[endPos]) 00207 { 00208 endPos += 1; 00209 if (endPos == endSize) 00210 return; 00211 } 00212 else 00213 { 00214 if (endPos > 0) 00215 dyStringAppendN(dy, endPattern, endPos); 00216 dyStringAppendC(dy, c); 00217 endPos = 0; 00218 } 00219 } 00220 }
Here is the call graph for this function:

| static void xpUnexpectedEof | ( | struct xp * | xp | ) | [static] |
Definition at line 123 of file xp.c.
References xpError().
Referenced by xpParseEndTag(), xpParseStartTag(), and xpTextUntil().
00125 { 00126 xpError(xp, "Unexpected end of file."); 00127 }
Here is the call graph for this function:

Here is the caller graph for this function:

char const rcsid[] = "$Id: xp.c,v 1.15 2005/12/19 17:51:14 kent Exp $" [static] |
1.5.2