rngparser.c
来自「图片显示,电脑光于望技术湖连望键往,网络」· C语言 代码 · 共 1,594 行 · 第 1/4 页
C
1,594 行
/** * rngparser.c: parser for the Relax-NG compact syntax. * * Based on: * RELAX NG Compact Syntax * Committee Specification 21 November 2002 * http://www.oasis-open.org/committees/relax-ng/compact-20021121.html * * See Copyright for the status of this software. * * Daniel Veillard <veillard@redhat.com> */#include <string.h>#include <libxml/parser.h>#include <libxml/parserInternals.h>#include <libxml/relaxng.h>#include <libxml/dict.h>#define TODO \ xmlGenericError(xmlGenericErrorContext, \ "Unimplemented block at %s:%d\n", \ __FILE__, __LINE__);#define MAX_TOKEN 10typedef enum { CRNG_NONE = 0, CRNG_OP = 1, CRNG_KEYWORD, CRNG_IDENTIFIER, CRNG_LITERAL_SEGMENT, CRNG_CNAME, CRNG_QNAME, CRNG_NSNAME, CRNG_DOCUMENTATION} xmlCRNGTokType;typedef enum { CRNG_OKAY = 0, CRNG_MEMORY_ERROR, CRNG_INVALID_CHAR_ERROR, CRNG_END_ERROR, CRNG_ENCODING_ERROR} xmlCRNGError;typedef enum { XML_CRNG_ERROR = -1, XML_CRNG_OK = 0, XML_CRNG_EOF = 1} xmlCRelaxNGParserState;typedef struct _token _token;typedef _token *tokenPtr;struct _token { xmlCRNGTokType toktype; int toklen; const xmlChar *token; const xmlChar *prefix;};typedef struct _xmlCRelaxNGParserCtxt xmlCRelaxNGParserCtxt;typedef xmlCRelaxNGParserCtxt *xmlCRelaxNGParserCtxtPtr;struct _xmlCRelaxNGParserCtxt { void *userData; /* user specific data block */ xmlRelaxNGValidityErrorFunc error; /* the callback in case of errors */ xmlRelaxNGValidityWarningFunc warning;/* the callback in case of warning */ xmlRelaxNGValidErr err; const xmlChar *compact; const xmlChar *end; const xmlChar *cur; int isElem; int lineno; const xmlChar *linestart; const char *filename; int nbTokens; int firstToken; _token tokens[MAX_TOKEN]; int totalToken; xmlCRelaxNGParserState state; int nbErrors; xmlDocPtr res; /* the result */ xmlNodePtr ins; /* the current insertion node */ xmlNsPtr nsDef; tokenPtr token; xmlHashTablePtr namespaces; xmlHashTablePtr datatypes; /* * dictionnary and keywords */ xmlDictPtr dict; const xmlChar *key_attribute; const xmlChar *key_default; const xmlChar *key_datatypes; const xmlChar *key_div; const xmlChar *key_element; const xmlChar *key_empty; const xmlChar *key_external; const xmlChar *key_grammar; const xmlChar *key_include; const xmlChar *key_inherit; const xmlChar *key_list; const xmlChar *key_mixed; const xmlChar *key_namespace; const xmlChar *key_notAllowed; const xmlChar *key_parent; const xmlChar *key_start; const xmlChar *key_string; const xmlChar *key_text; const xmlChar *key_token; const xmlChar *key_equal; const xmlChar *key_orequal; const xmlChar *key_andequal; const xmlChar *key_combine; const xmlChar *key_or; const xmlChar *key_comma; const xmlChar *key_and; const xmlChar *key_choice; const xmlChar *key_group; const xmlChar *key_interleave; const xmlChar *key_ref; const xmlChar *key_define; /* results */ xmlDocPtr doc; /* the resulting doc */ xmlNodePtr insert; /* the insertion point */ xmlAttrPtr attrs; /* pending attributes */};static const xmlChar *xmlCRelaxNGInherit = BAD_CAST "Inherit string";static const xmlChar *xmlCRelaxNGDefault = BAD_CAST "Default string";#define CUR_CHAR(l) xmlXPathCurrentChar(ctxt, &l)/** * IS_BLANK: * @c: an UNICODE value (int) * * Macro to check the following production in the XML spec: * * [3] S ::= (#x20 | #x9 | #xD | #xA)+ */#ifndef IS_BLANK#define IS_BLANK(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) || \ ((c) == 0x0D))#endif#define IS_SEPARATOR(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) || \ ((c) == 0x0D) || (c == '#'))#define CRNG_ERROR0(X) \ { xmlCRNGErr(ctxt, X, NULL); return(0); }#define CRNG_ERROR(X) \ { xmlCRNGErr(ctxt, X, NULL); }#define CRNG_MEM_ERROR0() \ { xmlCRNGErr(ctxt, CRNG_MEMORY_ERROR, NULL); return(0); }#define CRNG_MEM_ERROR() \ { xmlCRNGErr(ctxt, CRNG_MEMORY_ERROR, NULL); }#define ERROR(str) xmlCRNGErr(ctxt, 0, str);static voidxmlCRNGErr(xmlCRelaxNGParserCtxtPtr ctxt, int err_no, const char *err_msg) { const xmlChar *cur; xmlChar buffer[150]; int i, l; if (ctxt != NULL) { if (ctxt->filename != NULL) fprintf(stderr, "%s:%d ", ctxt->filename, ctxt->lineno); } if (err_msg != NULL) { fprintf(stderr, "error: %s\n", err_msg); } else if (err_no != 0) fprintf(stderr, "error %d\n", err_no); cur = ctxt->cur; while ((*cur != '\n') && (*cur != '\r') && (ctxt->cur - cur < 80)) cur--; l = ctxt->cur - cur; cur++; for (i = 0; i < 100;i++) { if ((*cur == '\n') || (*cur == '\r')) break; buffer[i] = *cur++; } buffer[i] = 0; fprintf(stderr, "%s\n", buffer); for (i = 0; i < l;i++) buffer[i] = ' '; buffer[i++] = '^'; buffer[i++] = 0; fprintf(stderr, "%s\n", buffer);}/** * IS_OP * @c: an UNICODE value (int) * * Macro to check for operator value */#ifndef IS_OP#define IS_OP(c) (((c) == ',') || ((c) == '&') || ((c) == '|') || \ ((c) == '?') || ((c) == '-') || ((c) == '*') || \ ((c) == '{') || ((c) == '}') || ((c) == '(') || \ ((c) == ')') || ((c) == '+') || ((c) == '=') || \ ((c) == ':'))#endifstatic intxmlCRNGIsKeyword(xmlCRelaxNGParserCtxtPtr ctxt, const xmlChar *str) { if ((str == ctxt->key_attribute) || (str == ctxt->key_default) || (str == ctxt->key_datatypes) || (str == ctxt->key_div) || (str == ctxt->key_element) || (str == ctxt->key_empty) || (str == ctxt->key_external) || (str == ctxt->key_grammar) || (str == ctxt->key_include) || (str == ctxt->key_inherit) || (str == ctxt->key_list) || (str == ctxt->key_mixed) || (str == ctxt->key_namespace) || (str == ctxt->key_notAllowed) || (str == ctxt->key_parent) || (str == ctxt->key_start) || (str == ctxt->key_string) || (str == ctxt->key_text) || (str == ctxt->key_token)) return(1); return(0);}/* * xmlCRNGNextToken: * ctxt: a compact RNG parser context * * Scan the schema to get the next token * * Return 0 if success and -1 in case of error */static intxmlCRNGNextToken(xmlCRelaxNGParserCtxtPtr ctxt) { const xmlChar *cur; tokenPtr token; if (ctxt == NULL) return(-1); if (ctxt->nbTokens >= MAX_TOKEN) return(-1); token = &(ctxt->tokens[(ctxt->firstToken + ctxt->nbTokens) % MAX_TOKEN]); token->toktype = CRNG_NONE; if (ctxt->cur == NULL) { ctxt->cur = ctxt->compact; }retry: if (ctxt->cur >= ctxt->end) { ctxt->state = XML_CRNG_EOF; return(-1); } while ((ctxt->cur < ctxt->end) && (IS_BLANK(*ctxt->cur))) ctxt->cur++; if (ctxt->cur >= ctxt->end) { ctxt->state = XML_CRNG_EOF; return(-1); } if (*ctxt->cur == '#') { cur = ctxt->cur; cur++; while ((cur < ctxt->end) && (*cur != '\n') && (*cur != '\r')) cur++; ctxt->cur = cur; goto retry; } else if (*ctxt->cur == '"') { /* string, check for '"""' */ ctxt->cur++; if (ctxt->cur >= ctxt->end) goto eof; cur = ctxt->cur; if ((ctxt->end - ctxt->end > 2) && (*cur == '"') && (cur[1] == '"')) { TODO } else { while ((cur < ctxt->end) && (*cur != '"')) cur++; if (cur >= ctxt->end) goto eof; token->toklen = cur - ctxt->cur; token->token = xmlDictLookup(ctxt->dict, ctxt->cur, token->toklen); token->toktype = CRNG_LITERAL_SEGMENT; token->prefix = NULL; cur++; ctxt->cur = cur; } } else if (*ctxt->cur == '\'') { /* string, check for "'''" */ TODO } else if ((IS_OP(*ctxt->cur)) || (*ctxt->cur == ':')) { cur = ctxt->cur; cur++; if ((cur < ctxt->end) && (((*cur == '=') && ((*ctxt->cur == '|') || (*ctxt->cur == '&'))) || ((*cur == '*') && (*ctxt->cur == ':')))) { token->toklen = 2; } else { token->toklen = 1; } token->token = xmlDictLookup(ctxt->dict, ctxt->cur, token->toklen); token->toktype = CRNG_OP; token->prefix = NULL; ctxt->cur += token->toklen; } else { int escape = 0; cur = ctxt->cur; if (*cur == '\\') { escape = 1; cur++; ctxt->cur++; } while ((cur < ctxt->end) && (!(IS_SEPARATOR(*cur))) && (!(IS_OP(*cur)))) cur++; token->toklen = cur - ctxt->cur; token->token = xmlDictLookup(ctxt->dict, ctxt->cur, token->toklen); token->prefix = NULL; ctxt->cur = cur; if ((escape == 0) && (xmlCRNGIsKeyword(ctxt, token->token))) token->toktype = CRNG_KEYWORD; else { token->toktype = CRNG_IDENTIFIER; } if (*ctxt->cur == ':') { ctxt->cur++; if (*ctxt->cur == '*') { ctxt->cur++; token->toktype = CRNG_NSNAME; } else { cur = ctxt->cur; while ((cur < ctxt->end) && (!(IS_SEPARATOR(*cur))) && (!(IS_OP(*cur)))) cur++; token->prefix = token->token; token->toklen = cur - ctxt->cur; token->token = xmlDictLookup(ctxt->dict, ctxt->cur, token->toklen); ctxt->cur = cur; if (xmlValidateNCName(token->token, 0) == 0) token->toktype = CRNG_QNAME; else { TODO /* sounds like an error ! */ token->toktype = CRNG_IDENTIFIER; } } } } ctxt->nbTokens++; return(0);eof: ctxt->state = XML_CRNG_EOF; CRNG_ERROR(CRNG_END_ERROR); return(-1);}/** * xmlParseCRNGGetToken: * @ctxt: a compact RNG parser context * @no: the number of the token from 1 for the first one * and 2, 3 ... for read-ahead * * Token reading interface * * returns a pointer to the new token, or NULL in case of error or EOF */static tokenPtrxmlParseCRNGGetToken(xmlCRelaxNGParserCtxtPtr ctxt, int no) { tokenPtr ret; int res; if ((no <= 0) || (no >= MAX_TOKEN)) return(NULL); no--; while (ctxt->nbTokens <= no) { res = xmlCRNGNextToken(ctxt); if (res < 0) return(NULL); } ret = &(ctxt->tokens[(ctxt->firstToken + no) % MAX_TOKEN]); return(ret);}/** * xmlParseCRNGDropTokens: * @ctxt: a compact RNG parser context * @nr: the number of token marked as read * * mark a number of token as read and consumed.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?