📄 parser.c
字号:
else ctxt->name = NULL; ret = ctxt->nameTab[ctxt->nameNr]; ctxt->nameTab[ctxt->nameNr] = NULL; return (ret);}#endif /* LIBXML_PUSH_ENABLED *//** * namePush: * @ctxt: an XML parser context * @value: the element name * * Pushes a new element name on top of the name stack * * Returns -1 in case of error, the index in the stack otherwise */intnamePush(xmlParserCtxtPtr ctxt, const xmlChar * value){ if (ctxt == NULL) return (-1); if (ctxt->nameNr >= ctxt->nameMax) { const xmlChar * *tmp; ctxt->nameMax *= 2; tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab, ctxt->nameMax * sizeof(ctxt->nameTab[0])); if (tmp == NULL) { ctxt->nameMax /= 2; goto mem_error; } ctxt->nameTab = tmp; } ctxt->nameTab[ctxt->nameNr] = value; ctxt->name = value; return (ctxt->nameNr++);mem_error: xmlErrMemory(ctxt, NULL); return (-1);}/** * namePop: * @ctxt: an XML parser context * * Pops the top element name from the name stack * * Returns the name just removed */const xmlChar *namePop(xmlParserCtxtPtr ctxt){ const xmlChar *ret; if ((ctxt == NULL) || (ctxt->nameNr <= 0)) return (NULL); ctxt->nameNr--; if (ctxt->nameNr > 0) ctxt->name = ctxt->nameTab[ctxt->nameNr - 1]; else ctxt->name = NULL; ret = ctxt->nameTab[ctxt->nameNr]; ctxt->nameTab[ctxt->nameNr] = NULL; return (ret);}static int spacePush(xmlParserCtxtPtr ctxt, int val) { if (ctxt->spaceNr >= ctxt->spaceMax) { ctxt->spaceMax *= 2; ctxt->spaceTab = (int *) xmlRealloc(ctxt->spaceTab, ctxt->spaceMax * sizeof(ctxt->spaceTab[0])); if (ctxt->spaceTab == NULL) { xmlErrMemory(ctxt, NULL); return(0); } } ctxt->spaceTab[ctxt->spaceNr] = val; ctxt->space = &ctxt->spaceTab[ctxt->spaceNr]; return(ctxt->spaceNr++);}static int spacePop(xmlParserCtxtPtr ctxt) { int ret; if (ctxt->spaceNr <= 0) return(0); ctxt->spaceNr--; if (ctxt->spaceNr > 0) ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1]; else ctxt->space = &ctxt->spaceTab[0]; ret = ctxt->spaceTab[ctxt->spaceNr]; ctxt->spaceTab[ctxt->spaceNr] = -1; return(ret);}/* * Macros for accessing the content. Those should be used only by the parser, * and not exported. * * Dirty macros, i.e. one often need to make assumption on the context to * use them * * CUR_PTR return the current pointer to the xmlChar to be parsed. * To be used with extreme caution since operations consuming * characters may move the input buffer to a different location ! * CUR returns the current xmlChar value, i.e. a 8 bit value if compiled * This should be used internally by the parser * only to compare to ASCII values otherwise it would break when * running with UTF-8 encoding. * RAW same as CUR but in the input buffer, bypass any token * extraction that may have been done * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only * to compare on ASCII based substring. * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined * strings without newlines within the parser. * NEXT1(l) Skip 1 xmlChar, and must also be used only to skip 1 non-newline ASCII * defined char within the parser. * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding * * NEXT Skip to the next character, this does the proper decoding * in UTF-8 mode. It also pop-up unfinished entities on the fly. * NEXTL(l) Skip the current unicode character of l xmlChars long. * CUR_CHAR(l) returns the current unicode character (int), set l * to the number of xmlChars used for the encoding [0-5]. * CUR_SCHAR same but operate on a string instead of the context * COPY_BUF copy the current unicode char to the target buffer, increment * the index * GROW, SHRINK handling of input buffers */#define RAW (*ctxt->input->cur)#define CUR (*ctxt->input->cur)#define NXT(val) ctxt->input->cur[(val)]#define CUR_PTR ctxt->input->cur#define CMP4( s, c1, c2, c3, c4 ) \ ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \ ((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 )#define CMP5( s, c1, c2, c3, c4, c5 ) \ ( CMP4( s, c1, c2, c3, c4 ) && ((unsigned char *) s)[ 4 ] == c5 )#define CMP6( s, c1, c2, c3, c4, c5, c6 ) \ ( CMP5( s, c1, c2, c3, c4, c5 ) && ((unsigned char *) s)[ 5 ] == c6 )#define CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) \ ( CMP6( s, c1, c2, c3, c4, c5, c6 ) && ((unsigned char *) s)[ 6 ] == c7 )#define CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) \ ( CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) && ((unsigned char *) s)[ 7 ] == c8 )#define CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) \ ( CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) && \ ((unsigned char *) s)[ 8 ] == c9 )#define CMP10( s, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 ) \ ( CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) && \ ((unsigned char *) s)[ 9 ] == c10 )#define SKIP(val) do { \ ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val); \ if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \ if ((*ctxt->input->cur == 0) && \ (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \ xmlPopInput(ctxt); \ } while (0)#define SKIPL(val) do { \ int skipl; \ for(skipl=0; skipl<val; skipl++) { \ if (*(ctxt->input->cur) == '\n') { \ ctxt->input->line++; ctxt->input->col = 1; \ } else ctxt->input->col++; \ ctxt->nbChars++; \ ctxt->input->cur++; \ } \ if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \ if ((*ctxt->input->cur == 0) && \ (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \ xmlPopInput(ctxt); \ } while (0)#define SHRINK if ((ctxt->progressive == 0) && \ (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \ (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \ xmlSHRINK (ctxt);static void xmlSHRINK (xmlParserCtxtPtr ctxt) { xmlParserInputShrink(ctxt->input); if ((*ctxt->input->cur == 0) && (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) xmlPopInput(ctxt); }#define GROW if ((ctxt->progressive == 0) && \ (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK)) \ xmlGROW (ctxt);static void xmlGROW (xmlParserCtxtPtr ctxt) { xmlParserInputGrow(ctxt->input, INPUT_CHUNK); if ((*ctxt->input->cur == 0) && (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) xmlPopInput(ctxt);}#define SKIP_BLANKS xmlSkipBlankChars(ctxt)#define NEXT xmlNextChar(ctxt)#define NEXT1 { \ ctxt->input->col++; \ ctxt->input->cur++; \ ctxt->nbChars++; \ if (*ctxt->input->cur == 0) \ xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \ }#define NEXTL(l) do { \ if (*(ctxt->input->cur) == '\n') { \ ctxt->input->line++; ctxt->input->col = 1; \ } else ctxt->input->col++; \ ctxt->input->cur += l; \ if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \ } while (0)#define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)#define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)#define COPY_BUF(l,b,i,v) \ if (l == 1) b[i++] = (xmlChar) v; \ else i += xmlCopyCharMultiByte(&b[i],v)/** * xmlSkipBlankChars: * @ctxt: the XML parser context * * skip all blanks character found at that point in the input streams. * It pops up finished entities in the process if allowable at that point. * * Returns the number of space chars skipped */intxmlSkipBlankChars(xmlParserCtxtPtr ctxt) { int res = 0; /* * It's Okay to use CUR/NEXT here since all the blanks are on * the ASCII range. */ if ((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) { const xmlChar *cur; /* * if we are in the document content, go really fast */ cur = ctxt->input->cur; while (IS_BLANK_CH(*cur)) { if (*cur == '\n') { ctxt->input->line++; ctxt->input->col = 1; } cur++; res++; if (*cur == 0) { ctxt->input->cur = cur; xmlParserInputGrow(ctxt->input, INPUT_CHUNK); cur = ctxt->input->cur; } } ctxt->input->cur = cur; } else { int cur; do { cur = CUR; while (IS_BLANK_CH(cur)) { /* CHECKED tstblanks.xml */ NEXT; cur = CUR; res++; } while ((cur == 0) && (ctxt->inputNr > 1) && (ctxt->instate != XML_PARSER_COMMENT)) { xmlPopInput(ctxt); cur = CUR; } /* * Need to handle support of entities branching here */ if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); } while (IS_BLANK(cur)); /* CHECKED tstblanks.xml */ } return(res);}/************************************************************************ * * * Commodity functions to handle entities * * * ************************************************************************//** * xmlPopInput: * @ctxt: an XML parser context * * xmlPopInput: the current input pointed by ctxt->input came to an end * pop it and return the next char. * * Returns the current xmlChar in the parser context */xmlCharxmlPopInput(xmlParserCtxtPtr ctxt) { if ((ctxt == NULL) || (ctxt->inputNr <= 1)) return(0); if (xmlParserDebugEntities) xmlGenericError(xmlGenericErrorContext, "Popping input %d\n", ctxt->inputNr); xmlFreeInputStream(inputPop(ctxt)); if ((*ctxt->input->cur == 0) && (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) return(xmlPopInput(ctxt)); return(CUR);}/** * xmlPushInput: * @ctxt: an XML parser context * @input: an XML parser input fragment (entity, XML fragment ...). * * xmlPushInput: switch to a new input stream which is stacked on top * of the previous one(s). */voidxmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) { if (input == NULL) return; if (xmlParserDebugEntities) { if ((ctxt->input != NULL) && (ctxt->input->filename)) xmlGenericError(xmlGenericErrorContext, "%s(%d): ", ctxt->input->filename, ctxt->input->line); xmlGenericError(xmlGenericErrorContext, "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur); } inputPush(ctxt, input); GROW;}/** * xmlParseCharRef: * @ctxt: an XML parser context * * parse Reference declarations * * [66] CharRef ::= '&#' [0-9]+ ';' | * '&#x' [0-9a-fA-F]+ ';' * * [ WFC: Legal Character ] * Characters referred to using character references must match the * production for Char. * * Returns the value parsed (as an int), 0 in case of error */intxmlParseCharRef(xmlParserCtxtPtr ctxt) { unsigned int val = 0; int count = 0; unsigned int outofrange = 0; /* * Using RAW/CUR/NEXT is okay since we are working on ASCII range here */ if ((RAW == '&') && (NXT(1) == '#') && (NXT(2) == 'x')) { SKIP(3); GROW; while (RAW != ';') { /* loop blocked by count */ if (count++ > 20) { count = 0; GROW; } if ((RAW >= '0') && (RAW <= '9')) val = val * 16 + (CUR - '0'); else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20)) val = val * 16 + (CUR - 'a') + 10; else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20)) val = val * 16 + (CUR - 'A') + 10; else { xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL); val = 0; break; } if (val > 0x10FFFF) outofrange = val; NEXT; count++; } if (RAW == ';') { /* on purpose to avoid reentrancy problems with NEXT and SKIP */ ctxt->input->col++; ctxt->nbChars ++; ctxt->input->cur++; } } else if ((RAW == '&') && (NXT(1) == '#')) { SKIP(2); GROW; while (RAW != ';') { /* loop blocked by count */ if (count++ > 20) { count = 0; GROW; } if ((RAW >= '0') && (RAW <= '9')) val = val * 10 + (CUR - '0'); else { xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL); val = 0; break; } if (val > 0x10FFFF) outofrange = val; NEXT; count++; } if (RAW == ';') { /* on purpose to avoid reentrancy problems with NEXT and SKIP */ ctxt->input->col++; ctxt->nbChars ++; ctxt->input->cur++; } } else { xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL); } /* * [ WFC: Legal Character ] * Characters referred to using character references must match the * production for Char. */ if ((IS_CHAR(val) && (outofrange == 0))) { return(val); } else { xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR, "xmlParseCharRef: invalid xmlChar value %d\n", val); } return(0);}/** * xmlParseStringCharRef: * @ctxt: an XML parser context * @str: a pointer to an index in the string * * parse Reference declarations, variant parsing from a string rather * than an an input flow. * * [66] CharRef ::= '&#' [0-9]+ ';' | * '&#x' [0-9a-fA-F]+ ';' * * [ WFC: Legal Character ] * Characters referred to using character references must match the * production for Char. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -