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 + -
显示快捷键?