lib/xp.c File Reference

#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)
xpxpNew (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 $"


Define Documentation

#define xpGetChar ( xp   )     (xp->in < xp->inBufEnd ? *xp->in++ : xpNextBuf(xp))

Definition at line 30 of file xp.c.

Referenced by xpEatComment(), xpForceMatch(), xpLookup(), xpParseEndTag(), xpParseNext(), xpParseStartTag(), and xpTextUntil().

#define xpUngetChar ( xp   )     (--xp->in)

Definition at line 34 of file xp.c.

Referenced by xpParseNext().


Function Documentation

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 
)

Definition at line 184 of file xp.c.

References xpError(), and xpGetChar.

00186 {
00187 char *match = matchString, m;
00188 while ((m = *match++) != 0)
00189     {
00190     if (m != xpGetChar(xp))
00191         xpError(xp, "Expecting %s", matchString);
00192     }
00193 }

Here is the call graph for this function:

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:

static void xpLookup ( struct xp xp,
struct dyString temp,
struct dyString text 
) [static]

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 
)

Definition at line 64 of file xp.c.

00066 {
00067 FILE *f = userData;
00068 return fread(buf, 1, bufSize, f);
00069 }

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:


Variable Documentation

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

Definition at line 16 of file xp.c.


Generated on Tue Dec 25 20:23:52 2007 for blat by  doxygen 1.5.2