Index: third_party/libxml/src/rngparser.c |
diff --git a/third_party/libxml/src/rngparser.c b/third_party/libxml/src/rngparser.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e681e0c22cd1dbbf9a5dc2a2576fb26a70036227 |
--- /dev/null |
+++ b/third_party/libxml/src/rngparser.c |
@@ -0,0 +1,1595 @@ |
+/** |
+ * 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 10 |
+ |
+typedef 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 void |
+xmlCRNGErr(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) == ':')) |
+#endif |
+ |
+static int |
+xmlCRNGIsKeyword(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 int |
+xmlCRNGNextToken(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 tokenPtr |
+xmlParseCRNGGetToken(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. |
+ * |
+ * Returns -1 in case of error and 0 otherwise |
+ */ |
+static int |
+xmlParseCRNGDropTokens(xmlCRelaxNGParserCtxtPtr ctxt, int nr) { |
+ if ((nr <= 0) || (nr >= MAX_TOKEN)) return(-1); |
+ while ((ctxt->nbTokens >0) && (nr > 0)) { |
+ ctxt->firstToken++; |
+ nr--; |
+ ctxt->nbTokens--; |
+ ctxt->totalToken++; |
+ if (ctxt->totalToken == 384) |
+ fprintf(stderr, "found\n"); |
+ } |
+ ctxt->firstToken = ctxt->firstToken % MAX_TOKEN; |
+ return(0); |
+} |
+ |
+static void |
+xmlParseCRNGTokenize(xmlCRelaxNGParserCtxtPtr ctxt) { |
+ tokenPtr token; |
+ |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ while (token != NULL) { |
+ switch (token->toktype) { |
+ case CRNG_NONE: printf("none"); break; |
+ case CRNG_OP: printf("op"); break; |
+ case CRNG_KEYWORD: printf("keyword"); break; |
+ case CRNG_IDENTIFIER: printf("identifier"); break; |
+ case CRNG_LITERAL_SEGMENT: printf("literal"); break; |
+ case CRNG_CNAME: printf("cname"); break; |
+ case CRNG_QNAME: printf("qname"); break; |
+ case CRNG_NSNAME: printf("nsname"); break; |
+ case CRNG_DOCUMENTATION: printf("doc"); break; |
+ } |
+ printf(":%s\n", token->token); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ } |
+} |
+ |
+/** |
+ * xmlParseCRNG_attribute: |
+ * @ctxt: a compact RNG parser context |
+ * @name: the attribute name |
+ * @ns: the attribute namespace |
+ * @value: the attribute value |
+ * |
+ * implements attribute of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_attribute(xmlCRelaxNGParserCtxtPtr ctxt, |
+ const xmlChar *name, |
+ xmlNsPtr ns, |
+ const xmlChar *value) |
+{ |
+ xmlAttrPtr attr; |
+ |
+ attr = xmlNewNsPropEatName(NULL, ns, (xmlChar *) name, value); |
+ if (attr == NULL) CRNG_MEM_ERROR0(); |
+ attr->next = ctxt->attrs; |
+ if (ctxt->attrs != NULL) |
+ ctxt->attrs->prev = attr; |
+ ctxt->attrs = attr; |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseCRNG_bindPrefix: |
+ * @ctxt: a compact RNG parser context |
+ * @prefix: the namespace prefix or NULL |
+ * @namespace: the namespace name |
+ * |
+ * implements bindPrefix of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_bindPrefix(xmlCRelaxNGParserCtxtPtr ctxt, |
+ const xmlChar *prefix, |
+ const xmlChar *namespace) |
+{ |
+ int ret; |
+ |
+ if ((prefix != NULL) && (xmlStrEqual(prefix, BAD_CAST "xml")) && |
+ (!xmlStrEqual(namespace, XML_XML_NAMESPACE))) { |
+ ERROR("The \"xml\" prefix must be bound to \"http://www.w3.org/XML/1998/namespace\""); |
+ return(-1); |
+ } else if ((xmlStrEqual(namespace, XML_XML_NAMESPACE)) && |
+ (!xmlStrEqual(prefix, BAD_CAST "xml"))) { |
+ ERROR("The \"http://www.w3.org/XML/1998/namespace\" name must be bound to \"xml\" prefix"); |
+ return(-1); |
+ } |
+ if (ctxt->namespaces == NULL) |
+ ctxt->namespaces = xmlHashCreate(10); |
+ if (ctxt->namespaces == NULL) { |
+ ERROR("Failed to create namespace hash table"); |
+ return(-1); |
+ } |
+ if (prefix == NULL) |
+ ret = xmlHashAddEntry(ctxt->namespaces, xmlCRelaxNGDefault, |
+ (void *) namespace); |
+ else |
+ ret = xmlHashAddEntry(ctxt->namespaces, prefix, |
+ (void *) namespace); |
+ if (ret < 0) { |
+ if (prefix == NULL) { |
+ ERROR("Redefinition of default namespace"); |
+ } else { |
+ ERROR("Redefinition of namespace"); |
+ } |
+ return(-1); |
+ } |
+ |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseCRNG_bindDatatypePrefix: |
+ * @ctxt: a compact RNG parser context |
+ * @prefix: the datatype prefix |
+ * @namespace: the datatype identifier |
+ * |
+ * implements bindDatatypePrefix of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_bindDatatypePrefix(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED, |
+ const xmlChar *prefix, |
+ const xmlChar *namespace) |
+{ |
+ int ret; |
+ |
+ if ((prefix != NULL) && (xmlStrEqual(prefix, BAD_CAST "xsd")) && |
+ (!xmlStrEqual(namespace, |
+ BAD_CAST "http://www.w3.org/2001/XMLSchema-datatypes"))) { |
+ ERROR("The \"xsd\" prefix must be bound to \"http://www.w3.org/2001/XMLSchema-datatypes\""); |
+ return(-1); |
+ } |
+ if (ctxt->datatypes == NULL) |
+ ctxt->datatypes = xmlHashCreate(10); |
+ if (ctxt->datatypes == NULL) { |
+ ERROR("Failed to create namespace hash table"); |
+ return(-1); |
+ } |
+ ret = xmlHashAddEntry(ctxt->datatypes, prefix, |
+ (void *) namespace); |
+ if (ret < 0) { |
+ ERROR("Redefinition of datatype"); |
+ return(-1); |
+ } |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseCRNG_lookupPrefix: |
+ * @ctxt: a compact RNG parser context |
+ * @prefix: the namespace prefix or NULL |
+ * |
+ * implements lookupPrefix of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns the prefix in case of success or NULL in case of error |
+ */ |
+static const xmlChar * |
+xmlParseCRNG_lookupPrefix(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED, |
+ const xmlChar *prefix) |
+{ |
+ const xmlChar *ret; |
+ |
+ if (prefix == NULL) |
+ ret = xmlHashLookup(ctxt->namespaces, xmlCRelaxNGDefault); |
+ else |
+ ret = xmlHashLookup(ctxt->namespaces, prefix); |
+ return(ret); |
+} |
+ |
+/** |
+ * xmlParseCRNG_lookupDatatypePrefix: |
+ * @ctxt: a compact RNG parser context |
+ * @prefix: the namespace prefix or NULL |
+ * |
+ * implements lookupDatatypePrefix of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns the prefix in case of success or NULL in case of error |
+ */ |
+static const xmlChar * |
+xmlParseCRNG_lookupDatatypePrefix(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED, |
+ const xmlChar *prefix) |
+{ |
+ const xmlChar *ret; |
+ ret = xmlHashLookup(ctxt->datatypes, prefix); |
+ return(ret); |
+} |
+ |
+/** |
+ * xmlParseCRNG_datatypeAttributes: |
+ * @ctxt: a compact RNG parser context |
+ * @prefix: the namespace prefix or NULL |
+ * |
+ * implements lookupPrefix of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns the prefix in case of success or NULL in case of error |
+ */ |
+static xmlAttrPtr |
+xmlParseCRNG_datatypeAttributes(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED, |
+ const xmlChar *library, const xmlChar *type) |
+{ |
+ xmlAttrPtr lib, typ; |
+ |
+ lib = xmlNewNsProp(NULL, NULL, BAD_CAST "datatypeLibrary", library); |
+ if (lib == NULL) { |
+ CRNG_MEM_ERROR(); |
+ return(NULL); |
+ } |
+ typ = xmlNewNsProp(NULL, NULL, BAD_CAST "type", type); |
+ if (typ == NULL) { |
+ CRNG_MEM_ERROR(); |
+ return(lib); |
+ } |
+ lib->next = typ; |
+ |
+ return(lib); |
+} |
+ |
+/** |
+ * xmlParseCRNG_XXX: |
+ * @ctxt: a compact RNG parser context |
+ * |
+ * Parse XXX of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_XXX(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED) |
+{ |
+ return(0); |
+} |
+ |
+static int xmlParseCRNG_pattern(xmlCRelaxNGParserCtxtPtr ctxt); |
+static int xmlParseCRNG_nameClass(xmlCRelaxNGParserCtxtPtr ctxt); |
+ |
+/** |
+ * xmlParseCRNG_params: |
+ * @ctxt: a compact RNG parser context |
+ * |
+ * Parse params of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_params(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED) |
+{ |
+ TODO |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseCRNG_exceptNameClass: |
+ * @ctxt: a compact RNG parser context |
+ * |
+ * Parse exceptNameClass of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_exceptNameClass(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED) |
+{ |
+ tokenPtr token; |
+ xmlNodePtr insert = ctxt->insert, cur; |
+ |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if ((token->toktype == CRNG_OP) && |
+ (token->token[0] == '-') && (token->token[1] == 0)) { |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ cur = xmlNewNode(NULL, BAD_CAST "except"); |
+ if (cur == NULL) CRNG_MEM_ERROR0(); |
+ if (ctxt->insert != NULL) |
+ xmlAddChild(ctxt->insert, cur); |
+ ctxt->insert = cur; |
+ xmlParseCRNG_nameClass(ctxt); |
+ } |
+ ctxt->insert = insert; |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseCRNG_innerNameClass: |
+ * @ctxt: a compact RNG parser context |
+ * |
+ * Parse innerNameClass of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_innerNameClass(xmlCRelaxNGParserCtxtPtr ctxt) |
+{ |
+ tokenPtr token; |
+ xmlNodePtr cur; |
+ |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if (token->toktype == CRNG_OP) { |
+ if ((token->token[0] == '(') && (token->token[1] == 0)) { |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ xmlParseCRNG_nameClass(ctxt); |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if ((token->toktype != CRNG_OP) || |
+ (token->token[0] != ')') || (token->token[1] != 0)) { |
+ ERROR("Expecting \")\" here"); |
+ } |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ } else if ((token->token[0] == '*') && (token->token[1] == 0)) { |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ cur = xmlNewNode(NULL, BAD_CAST "anyName"); |
+ if (cur == NULL) CRNG_MEM_ERROR0(); |
+ if (ctxt->insert != NULL) |
+ xmlAddChild(ctxt->insert, cur); |
+ ctxt->insert = cur; |
+ xmlParseCRNG_exceptNameClass(ctxt); |
+ } else { |
+ TODO |
+ } |
+ } else if ((token->toktype == CRNG_IDENTIFIER) || |
+ (token->toktype == CRNG_KEYWORD)) { |
+ cur = xmlNewNode(NULL, BAD_CAST "name"); |
+ if (cur == NULL) CRNG_MEM_ERROR0(); |
+ if (ctxt->isElem) { |
+ xmlSetProp(cur, BAD_CAST "ns", |
+ xmlParseCRNG_lookupPrefix(ctxt, NULL)); |
+ } else { |
+ xmlSetProp(cur, BAD_CAST "ns", BAD_CAST ""); |
+ } |
+ xmlNodeAddContent(cur, token->token); |
+ if (ctxt->insert != NULL) |
+ xmlAddChild(ctxt->insert, cur); |
+ ctxt->insert = cur; |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ } else if (token->toktype == CRNG_CNAME) { |
+ TODO |
+ } else if (token->toktype == CRNG_NSNAME) { |
+ cur = xmlNewNode(NULL, BAD_CAST "nsName"); |
+ if (cur == NULL) CRNG_MEM_ERROR0(); |
+ xmlSetProp(cur, BAD_CAST "ns", |
+ xmlParseCRNG_lookupPrefix(ctxt, token->token)); |
+ if (ctxt->insert != NULL) |
+ xmlAddChild(ctxt->insert, cur); |
+ ctxt->insert = cur; |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ xmlParseCRNG_exceptNameClass(ctxt); |
+ } else { |
+ TODO /* probably an error */ |
+ } |
+ |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseCRNG_nameClass: |
+ * @ctxt: a compact RNG parser context |
+ * |
+ * Parse nameClass of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_nameClass(xmlCRelaxNGParserCtxtPtr ctxt) |
+{ |
+ tokenPtr token; |
+ xmlNodePtr insert = ctxt->insert, last, choice; |
+ |
+ ctxt->insert = NULL; |
+ xmlParseCRNG_innerNameClass(ctxt); |
+ last = ctxt->insert; |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ while ((token->toktype == CRNG_OP) && |
+ (token->token[0] == '|') && (token->token[1] == 0)) { |
+ choice = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_choice); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if (choice == NULL) CRNG_MEM_ERROR0(); |
+ ctxt->insert = NULL; |
+ xmlParseCRNG_innerNameClass(ctxt); |
+ xmlAddChild(choice, last); |
+ xmlAddChild(choice, ctxt->insert); |
+ last = choice; |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ } |
+ xmlAddChild(insert, last); |
+ |
+ ctxt->insert = insert; |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseCRNG_patternBlock: |
+ * @ctxt: a compact RNG parser context |
+ * |
+ * Parse a pattern block of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_patternBlock(xmlCRelaxNGParserCtxtPtr ctxt) |
+{ |
+ tokenPtr token; |
+ |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if ((token->toktype != CRNG_OP) || |
+ (token->token[0] != '{') || (token->token[1] != 0)) { |
+ ERROR("Expecting \"{\" here"); |
+ } |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ xmlParseCRNG_pattern(ctxt); |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if ((token->toktype != CRNG_OP) || |
+ (token->token[0] != '}') || (token->token[1] != 0)) { |
+ ERROR("Expecting \"}\" here"); |
+ } |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseCRNG_datatype: |
+ * @ctxt: a compact RNG parser context |
+ * |
+ * Parse datatype of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_datatype(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED) |
+{ |
+ tokenPtr token; |
+ xmlAttrPtr attrs = NULL; |
+ |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if (token->toktype == CRNG_KEYWORD) { |
+ if (token->token == ctxt->key_string) { |
+ attrs = xmlParseCRNG_datatypeAttributes(ctxt, BAD_CAST "", |
+ token->token); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ } else if (token->token == ctxt->key_token) { |
+ attrs = xmlParseCRNG_datatypeAttributes(ctxt, BAD_CAST "", |
+ token->token); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ } else { |
+ TODO /* probably an error */ |
+ } |
+ } else if (token->toktype == CRNG_LITERAL_SEGMENT) { |
+ ctxt->insert = xmlNewNode(NULL, BAD_CAST "value"); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if (ctxt->insert == NULL) CRNG_MEM_ERROR0(); |
+ xmlNodeAddContent(ctxt->insert, token->token); |
+ } else if (token->toktype == CRNG_QNAME) { |
+ attrs = xmlParseCRNG_datatypeAttributes(ctxt, |
+ xmlParseCRNG_lookupDatatypePrefix(ctxt, token->prefix), |
+ token->token); |
+ } else { |
+ TODO |
+ } |
+ if (attrs != NULL) { |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if (token->toktype == CRNG_LITERAL_SEGMENT) { |
+ ctxt->insert = xmlNewNode(NULL, BAD_CAST "value"); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if (ctxt->insert == NULL) { |
+ xmlFreePropList(attrs); |
+ CRNG_MEM_ERROR0(); |
+ } |
+ ctxt->insert->properties = attrs; |
+ xmlNodeAddContent(ctxt->insert, token->token); |
+ } else if ((token->toktype == CRNG_OP) && |
+ (token->token[0] == '{') && (token->token[0] == 0)) { |
+ ctxt->insert = xmlNewNode(NULL, BAD_CAST "data"); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if (ctxt->insert == NULL) { |
+ xmlFreePropList(attrs); |
+ CRNG_MEM_ERROR0(); |
+ } |
+ ctxt->insert->properties = attrs; |
+ xmlParseCRNG_params(ctxt); |
+ } else { |
+ ctxt->insert = xmlNewNode(NULL, BAD_CAST "data"); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if (ctxt->insert == NULL) { |
+ xmlFreePropList(attrs); |
+ CRNG_MEM_ERROR0(); |
+ } |
+ ctxt->insert->properties = attrs; |
+ xmlNodeAddContent(ctxt->insert, token->token); |
+ } |
+ } |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseCRNG_primary: |
+ * @ctxt: a compact RNG parser context |
+ * |
+ * Parse primary of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_primary(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED) |
+{ |
+ tokenPtr token; |
+ |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if (token == NULL) |
+ return(0); |
+ if (token->toktype == CRNG_KEYWORD) { |
+ if (token->token == ctxt->key_element) { |
+ ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if (ctxt->insert == NULL) CRNG_MEM_ERROR0(); |
+ ctxt->isElem = 1; |
+ xmlParseCRNG_nameClass(ctxt); |
+ xmlParseCRNG_patternBlock(ctxt); |
+ } else if (token->token == ctxt->key_attribute) { |
+ ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if (ctxt->insert == NULL) CRNG_MEM_ERROR0(); |
+ ctxt->isElem = 0; |
+ xmlParseCRNG_nameClass(ctxt); |
+ xmlParseCRNG_patternBlock(ctxt); |
+ } else if (token->token == ctxt->key_mixed) { |
+ ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if (ctxt->insert == NULL) CRNG_MEM_ERROR0(); |
+ xmlParseCRNG_patternBlock(ctxt); |
+ } else if (token->token == ctxt->key_list) { |
+ ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if (ctxt->insert == NULL) CRNG_MEM_ERROR0(); |
+ xmlParseCRNG_patternBlock(ctxt); |
+ } else if (token->token == ctxt->key_empty) { |
+ ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if (ctxt->insert == NULL) CRNG_MEM_ERROR0(); |
+ } else if (token->token == ctxt->key_notAllowed) { |
+ ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if (ctxt->insert == NULL) CRNG_MEM_ERROR0(); |
+ } else if (token->token == ctxt->key_text) { |
+ ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if (ctxt->insert == NULL) CRNG_MEM_ERROR0(); |
+ } else if (token->token == ctxt->key_parent) { |
+ ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if (ctxt->insert == NULL) CRNG_MEM_ERROR0(); |
+ TODO |
+ } else if (token->token == ctxt->key_grammar) { |
+ ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) token->token); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if (ctxt->insert == NULL) CRNG_MEM_ERROR0(); |
+ TODO |
+ } else if (token->token == ctxt->key_external) { |
+ ctxt->insert = xmlNewNode(NULL, BAD_CAST "externalRef"); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if (ctxt->insert == NULL) CRNG_MEM_ERROR0(); |
+ TODO |
+ } else { |
+ TODO |
+ } |
+ } else if (token->toktype == CRNG_IDENTIFIER) { |
+ ctxt->insert = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_ref); |
+ if (ctxt->insert == NULL) CRNG_MEM_ERROR0(); |
+ xmlSetProp(ctxt->insert, BAD_CAST "name", token->token); |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ } else if (token->toktype == CRNG_QNAME) { |
+ xmlParseCRNG_datatype(ctxt); |
+ } else if (token->toktype == CRNG_LITERAL_SEGMENT) { |
+ xmlParseCRNG_datatype(ctxt); |
+ } else if ((token->toktype == CRNG_OP) && |
+ (token->token[0] == '(') && (token->token[1] == 0)) { |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ xmlParseCRNG_pattern(ctxt); |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if ((token->toktype != CRNG_OP) || |
+ (token->token[0] != ')') || (token->token[1] != 0)) { |
+ ERROR("Expecting \")\" here"); |
+ } |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ } |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseCRNG_particle: |
+ * @ctxt: a compact RNG parser context |
+ * |
+ * Parse particle of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_particle(xmlCRelaxNGParserCtxtPtr ctxt) |
+{ |
+ tokenPtr token; |
+ xmlNodePtr insert = ctxt->insert, res, tmp = NULL; |
+ |
+ ctxt->insert = NULL; |
+ xmlParseCRNG_primary(ctxt); |
+ res = ctxt->insert; |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if ((token != NULL) && (token->toktype == CRNG_OP)) { |
+ if ((token->token[0] == '*') && (token->token[1] == 0)) { |
+ tmp = xmlNewNode(NULL, BAD_CAST "zeroOrMore"); |
+ if (tmp == NULL) CRNG_MEM_ERROR0(); |
+ } else if ((token->token[0] == '+') && (token->token[1] == 0)) { |
+ tmp = xmlNewNode(NULL, BAD_CAST "oneOrMore"); |
+ if (tmp == NULL) CRNG_MEM_ERROR0(); |
+ } else if ((token->token[0] == '?') && (token->token[1] == 0)) { |
+ tmp = xmlNewNode(NULL, BAD_CAST "optional"); |
+ if (tmp == NULL) CRNG_MEM_ERROR0(); |
+ } |
+ if (tmp != NULL) { |
+ xmlAddChild(tmp, res); |
+ res = tmp; |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ } |
+ } |
+ if (insert != NULL) { |
+ xmlAddChild(insert, res); |
+ ctxt->insert = insert; |
+ } else |
+ ctxt->insert = res; |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseCRNG_pattern: |
+ * @ctxt: a compact RNG parser context |
+ * |
+ * Parse pattern of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_pattern(xmlCRelaxNGParserCtxtPtr ctxt) |
+{ |
+ tokenPtr token; |
+ xmlNodePtr insert = ctxt->insert, prev, grp; |
+ |
+ ctxt->insert = NULL; |
+ xmlParseCRNG_particle(ctxt); |
+ prev = ctxt->insert; |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ while ((prev != NULL) && (token != NULL) && (token->toktype == CRNG_OP)) { |
+ if (token->token == ctxt->key_or) { |
+ grp = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_choice); |
+ if (grp == NULL) CRNG_MEM_ERROR0(); |
+ } else if (token->token == ctxt->key_and) { |
+ grp = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_interleave); |
+ if (grp == NULL) CRNG_MEM_ERROR0(); |
+ } else if (token->token == ctxt->key_comma) { |
+ grp = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_group); |
+ if (grp == NULL) CRNG_MEM_ERROR0(); |
+ } else |
+ break; |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ ctxt->insert = NULL; |
+ xmlParseCRNG_particle(ctxt); |
+ xmlAddChild(grp, prev); |
+ xmlAddChild(grp, ctxt->insert); |
+ prev = grp; |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ } |
+ if (insert != NULL) { |
+ xmlAddChild(insert, prev); |
+ ctxt->insert = insert; |
+ } else { |
+ ctxt->insert = prev; |
+ } |
+ |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseCRNG_component: |
+ * @ctxt: a compact RNG parser context |
+ * |
+ * Parse component of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_component(xmlCRelaxNGParserCtxtPtr ctxt) |
+{ |
+ tokenPtr token, tok2; |
+ xmlNodePtr insert = ctxt->insert; |
+ |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if (token == NULL) |
+ return(0); |
+ if (token->toktype == CRNG_KEYWORD) { |
+ if (token->token == ctxt->key_start) { |
+ xmlNodePtr start; |
+ |
+ start = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_start); |
+ if (start == NULL) CRNG_MEM_ERROR0(); |
+ if (ctxt->insert != NULL) |
+ xmlAddChild(ctxt->insert, start); |
+ ctxt->insert = start; |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ |
+ if ((token->toktype == CRNG_OP) && |
+ (token->token == ctxt->key_equal)) { |
+ } else if ((token->toktype == CRNG_OP) && |
+ (token->token == ctxt->key_orequal)) { |
+ xmlParseCRNG_attribute(ctxt, ctxt->key_combine, NULL, |
+ BAD_CAST "choice"); |
+ } else if ((token->toktype == CRNG_OP) && |
+ (token->token == ctxt->key_andequal)) { |
+ xmlParseCRNG_attribute(ctxt, ctxt->key_combine, NULL, |
+ BAD_CAST "interleave"); |
+ } else { |
+ ERROR("expecting \"=\" or \"&=\" or \"|=\" here") |
+ return(-1); |
+ } |
+ start->properties = ctxt->attrs; |
+ ctxt->attrs = NULL; |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ xmlParseCRNG_pattern(ctxt); |
+ |
+ } else if (token->token == ctxt->key_include) { |
+ TODO |
+ } else if (token->token == ctxt->key_div) { |
+ TODO |
+ } else { |
+ return(-1); |
+ } |
+ } else if (token->toktype == CRNG_IDENTIFIER) { |
+ xmlNodePtr define; |
+ const xmlChar *identifier; |
+ |
+ identifier = token->token; |
+ tok2 = xmlParseCRNGGetToken(ctxt, 2); |
+ if ((tok2->toktype == CRNG_OP) && |
+ (tok2->token == ctxt->key_equal)) { |
+ } else if ((tok2->toktype == CRNG_OP) && |
+ (tok2->token == ctxt->key_orequal)) { |
+ xmlParseCRNG_attribute(ctxt, ctxt->key_combine, NULL, |
+ BAD_CAST "choice"); |
+ } else if ((tok2->toktype == CRNG_OP) && |
+ (tok2->token == ctxt->key_andequal)) { |
+ xmlParseCRNG_attribute(ctxt, ctxt->key_combine, NULL, |
+ BAD_CAST "interleave"); |
+ } else { |
+ ERROR("expecting \"=\" or \"&=\" or \"|=\" here") |
+ return(-1); |
+ } |
+ xmlParseCRNGDropTokens(ctxt, 2); |
+ |
+ define = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_define); |
+ if (define == NULL) CRNG_MEM_ERROR0(); |
+ define->properties = ctxt->attrs; |
+ ctxt->attrs = NULL; |
+ xmlSetProp(define, BAD_CAST "name", identifier); |
+ if (ctxt->insert != NULL) |
+ xmlAddChild(ctxt->insert, define); |
+ ctxt->insert = define; |
+ xmlParseCRNG_pattern(ctxt); |
+ } else { |
+ return(-1); |
+ } |
+ ctxt->insert = insert; |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseCRNG_grammar: |
+ * @ctxt: a compact RNG parser context |
+ * |
+ * Parse grammar of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_grammar(xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED) |
+{ |
+ tokenPtr token; |
+ int ret; |
+ |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ while (token != NULL) { |
+ ret = xmlParseCRNG_component(ctxt); |
+ if (ret != 0) |
+ break; |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ } |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseCRNG_topLevelBody: |
+ * @ctxt: a compact RNG parser context |
+ * |
+ * Parse topLevelBody of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_topLevelBody(xmlCRelaxNGParserCtxtPtr ctxt) |
+{ |
+ tokenPtr token, tok2; |
+ |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if (token->toktype == CRNG_KEYWORD) { |
+ if ((token->token == ctxt->key_start) || |
+ (token->token == ctxt->key_include) || |
+ (token->token == ctxt->key_div)) { |
+ xmlNodePtr grammar; |
+ |
+ grammar = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_grammar); |
+ if (grammar == NULL) CRNG_MEM_ERROR0(); |
+ xmlDocSetRootElement(ctxt->doc, grammar); |
+ ctxt->insert = grammar; |
+ |
+ xmlParseCRNG_grammar(ctxt); |
+ } else { |
+ xmlParseCRNG_pattern(ctxt); |
+ } |
+ } else { |
+ tok2 = xmlParseCRNGGetToken(ctxt, 2); |
+ if ((tok2->toktype == CRNG_OP) && |
+ ((tok2->token == ctxt->key_equal) || |
+ (tok2->token == ctxt->key_orequal) || |
+ (tok2->token == ctxt->key_andequal))) { |
+ xmlNodePtr grammar; |
+ |
+ grammar = xmlNewNodeEatName(NULL, (xmlChar *) ctxt->key_grammar); |
+ if (grammar == NULL) CRNG_MEM_ERROR0(); |
+ xmlDocSetRootElement(ctxt->doc, grammar); |
+ ctxt->insert = grammar; |
+ |
+ xmlParseCRNG_grammar(ctxt); |
+ } else { |
+ xmlParseCRNG_pattern(ctxt); |
+ } |
+ } |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseCRNG_namespacePrefix: |
+ * @ctxt: a compact RNG parser context |
+ * |
+ * Parse namespacePrefix of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns the prefix or NULL in case of error |
+ */ |
+static const xmlChar * |
+xmlParseCRNG_namespacePrefix(xmlCRelaxNGParserCtxtPtr ctxt) |
+{ |
+ tokenPtr token; |
+ const xmlChar *prefix = NULL; |
+ |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if (token->toktype == CRNG_IDENTIFIER) { |
+ prefix = token->token; |
+ } else if (token->toktype == CRNG_OP) { |
+ if ((token->token[0] == '=') && (token->token[1] == 0)) |
+ return(NULL); |
+ prefix = token->token; |
+ } else { |
+ ERROR("Expecting a namespace prefix"); |
+ return(NULL); |
+ } |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ |
+ if (xmlStrEqual(prefix, BAD_CAST "xmlns")) { |
+ ERROR("Namespace prefix \"xmlns\" is forbidden"); |
+ } |
+ return(prefix); |
+} |
+ |
+/** |
+ * xmlParseCRNG_decl: |
+ * @ctxt: a compact RNG parser context |
+ * |
+ * Parse decl of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_decl(xmlCRelaxNGParserCtxtPtr ctxt) |
+{ |
+ const xmlChar *prefix = NULL; |
+ const xmlChar *namespace = NULL; |
+ tokenPtr token; |
+ |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if (token->toktype != CRNG_KEYWORD) return(-1); |
+ if (token->token == ctxt->key_default) { |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if ((token->toktype != CRNG_KEYWORD) || |
+ (token->token != ctxt->key_namespace)) { |
+ ERROR("Expecting keyword \"namespace\" after \"default\""); |
+ } |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ prefix = xmlParseCRNG_namespacePrefix(ctxt); |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if ((token->toktype != CRNG_OP) || |
+ (token->token[0] != '=') || (token->token[1] != 0)) { |
+ ERROR("Expecting keyword \"=\" here"); |
+ } |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if ((token->toktype == CRNG_KEYWORD) && |
+ (token->token == ctxt->key_inherit)) { |
+ namespace = xmlCRelaxNGInherit; |
+ } else if (token->toktype == CRNG_LITERAL_SEGMENT) { |
+ namespace = token->token; |
+ } else { |
+ ERROR("Expecting an URI or \"inherit\" value"); |
+ } |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if (namespace != NULL) { |
+ if (prefix != NULL) |
+ xmlParseCRNG_bindPrefix(ctxt, prefix, namespace); |
+ xmlParseCRNG_bindPrefix(ctxt, NULL, namespace); |
+ } |
+ } else if (token->token == ctxt->key_namespace) { |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ prefix = xmlParseCRNG_namespacePrefix(ctxt); |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if ((token->toktype != CRNG_OP) || |
+ (token->token[0] != '=') || (token->token[1] != 0)) { |
+ ERROR("Expecting keyword \"=\" here"); |
+ } |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if ((token->toktype == CRNG_KEYWORD) && |
+ (token->token == ctxt->key_inherit)) { |
+ namespace = xmlCRelaxNGInherit; |
+ } else if (token->toktype == CRNG_LITERAL_SEGMENT) { |
+ namespace = token->token; |
+ } else { |
+ ERROR("Expecting an URI or \"inherit\" value"); |
+ } |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if (namespace != NULL) |
+ xmlParseCRNG_bindPrefix(ctxt, prefix, namespace); |
+ } else if (token->token == ctxt->key_datatypes) { |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if ((token->toktype != CRNG_KEYWORD) && |
+ (token->toktype != CRNG_IDENTIFIER)) { |
+ ERROR("Expecting a datatype prefix identifier here"); |
+ } else |
+ prefix = token->token; |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if ((token->toktype != CRNG_OP) || |
+ (token->token[0] != '=') || (token->token[1] != 0)) { |
+ ERROR("Expecting keyword \"=\" here"); |
+ } |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ if (token->toktype == CRNG_LITERAL_SEGMENT) { |
+ namespace = token->token; |
+ } else { |
+ ERROR("Expecting a literal value for the datatype identifier"); |
+ } |
+ xmlParseCRNGDropTokens(ctxt, 1); |
+ if ((namespace != NULL) && (prefix != NULL)) |
+ xmlParseCRNG_bindDatatypePrefix(ctxt, prefix, namespace); |
+ } |
+ |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseCRNG_preamble: |
+ * @ctxt: a compact RNG parser context |
+ * |
+ * Parse preamble of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_preamble(xmlCRelaxNGParserCtxtPtr ctxt) |
+{ |
+ tokenPtr token; |
+ |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ while (token != NULL) { |
+ if (token == NULL) return(-1); |
+ if ((token->toktype == CRNG_KEYWORD) && |
+ ((token->token == ctxt->key_default) || |
+ (token->token == ctxt->key_namespace) || |
+ (token->token == ctxt->key_datatypes))) { |
+ xmlParseCRNG_decl(ctxt); |
+ } else |
+ break; |
+ token = xmlParseCRNGGetToken(ctxt, 1); |
+ } |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseCRNG_topLevel: |
+ * @ctxt: a compact RNG parser context |
+ * |
+ * Parse topLevel of the RELAX NG Compact Syntax Appendix A |
+ * |
+ * Returns 0 in case of success and -1 in case of error |
+ */ |
+static int |
+xmlParseCRNG_topLevel(xmlCRelaxNGParserCtxtPtr ctxt) |
+{ |
+ xmlParseCRNG_preamble(ctxt); |
+ xmlParseCRNG_topLevelBody(ctxt); |
+ return(0); |
+} |
+ |
+/** |
+ * xmlConvertCRNG: |
+ * @schemas: pointer to the text of the compact schemas |
+ * @len: length of the schemas in bytes (or 0) |
+ * @encoding: encoding indicated by the context or NULL |
+ * |
+ * Compiles the schemas into the equivalent Relax-NG XML structure |
+ * |
+ * Returns the xmlDocPtr resulting from the compilation or |
+ * NULL in case of error |
+ */ |
+xmlDocPtr |
+xmlConvertCRNG(const char *schemas, int len, const char *encoding) { |
+ struct _xmlCRelaxNGParserCtxt ctxt; |
+ xmlDocPtr ret = NULL; |
+ |
+ if (schemas == NULL) return(NULL); |
+ if (len <= 5) len = xmlStrlen((const unsigned char *) schemas); |
+ if (len <= 0) return(NULL); |
+ |
+ memset(&ctxt, 0, sizeof(ctxt)); |
+ ctxt.compact = (const unsigned char *) schemas; |
+ ctxt.cur = (const unsigned char *) schemas; |
+ ctxt.end = (const unsigned char *) &schemas[len]; |
+ ctxt.dict = xmlDictCreate(); |
+ if (ctxt.dict == NULL) |
+ return(NULL); |
+ ctxt.doc = xmlNewDoc(NULL); |
+ if (ctxt.doc == NULL) { |
+ xmlDictFree(ctxt.dict); |
+ return(NULL); |
+ } |
+ ctxt.doc->dict = ctxt.dict; |
+ xmlDictReference(ctxt.dict); |
+ |
+ ctxt.nbTokens = 0; |
+ ctxt.firstToken = 0; |
+ ctxt.key_attribute = xmlDictLookup(ctxt.dict, BAD_CAST "attribute", -1); |
+ ctxt.key_default = xmlDictLookup(ctxt.dict, BAD_CAST "default", -1); |
+ ctxt.key_datatypes = xmlDictLookup(ctxt.dict, BAD_CAST "datatypes", -1); |
+ ctxt.key_div = xmlDictLookup(ctxt.dict, BAD_CAST "div", -1); |
+ ctxt.key_element = xmlDictLookup(ctxt.dict, BAD_CAST "element", -1); |
+ ctxt.key_empty = xmlDictLookup(ctxt.dict, BAD_CAST "empty", -1); |
+ ctxt.key_external = xmlDictLookup(ctxt.dict, BAD_CAST "external", -1); |
+ ctxt.key_grammar = xmlDictLookup(ctxt.dict, BAD_CAST "grammar", -1); |
+ ctxt.key_include = xmlDictLookup(ctxt.dict, BAD_CAST "include", -1); |
+ ctxt.key_inherit = xmlDictLookup(ctxt.dict, BAD_CAST "inherit", -1); |
+ ctxt.key_list = xmlDictLookup(ctxt.dict, BAD_CAST "list", -1); |
+ ctxt.key_mixed = xmlDictLookup(ctxt.dict, BAD_CAST "mixed", -1); |
+ ctxt.key_namespace = xmlDictLookup(ctxt.dict, BAD_CAST "namespace", -1); |
+ ctxt.key_notAllowed = xmlDictLookup(ctxt.dict, BAD_CAST "notAllowed", -1); |
+ ctxt.key_parent = xmlDictLookup(ctxt.dict, BAD_CAST "parent", -1); |
+ ctxt.key_start = xmlDictLookup(ctxt.dict, BAD_CAST "start", -1); |
+ ctxt.key_string = xmlDictLookup(ctxt.dict, BAD_CAST "string", -1); |
+ ctxt.key_text = xmlDictLookup(ctxt.dict, BAD_CAST "text", -1); |
+ ctxt.key_token = xmlDictLookup(ctxt.dict, BAD_CAST "token", -1); |
+ ctxt.key_equal = xmlDictLookup(ctxt.dict, BAD_CAST "=", 1); |
+ ctxt.key_orequal = xmlDictLookup(ctxt.dict, BAD_CAST "|=", 2); |
+ ctxt.key_andequal = xmlDictLookup(ctxt.dict, BAD_CAST "&=", 2); |
+ ctxt.key_combine = xmlDictLookup(ctxt.dict, BAD_CAST "&=", 2); |
+ ctxt.key_or = xmlDictLookup(ctxt.dict, BAD_CAST "|", 1); |
+ ctxt.key_comma = xmlDictLookup(ctxt.dict, BAD_CAST ",", 1); |
+ ctxt.key_and = xmlDictLookup(ctxt.dict, BAD_CAST "&", 1); |
+ ctxt.key_choice = xmlDictLookup(ctxt.dict, BAD_CAST "choice", -1); |
+ ctxt.key_group = xmlDictLookup(ctxt.dict, BAD_CAST "group", -1); |
+ ctxt.key_interleave = xmlDictLookup(ctxt.dict, BAD_CAST "interleave", -1); |
+ ctxt.key_ref = xmlDictLookup(ctxt.dict, BAD_CAST "ref", 3); |
+ ctxt.key_define = xmlDictLookup(ctxt.dict, BAD_CAST "define", 6); |
+ |
+ /* xmlConvertCRNGTokenize(&ctxt); */ |
+ xmlConvertCRNG_topLevel(&ctxt); |
+ |
+ xmlDictFree(ctxt.dict); |
+ |
+ ret = ctxt.doc; |
+ return(ret); |
+} |
+ |
+/** |
+ * xmlConvertCRNGFile: |
+ * @URL: URL or filename for the resource |
+ * @encoding: encoding indicated by the context or NULL |
+ * |
+ * Compiles the schemas into the equivalent Relax-NG XML structure |
+ * |
+ * Returns the xmlDocPtr resulting from the compilation or |
+ * NULL in case of error |
+ */ |
+xmlDocPtr |
+xmlConvertCRNGFile(const char *URL, const char *encoding) { |
+} |
+ |
+#ifdef STANDALONE |
+const xmlChar *schemas = |
+"# RELAX NG XML syntax specified in compact syntax.\n\ |
+\n\ |
+default namespace rng = \"http://relaxng.org/ns/structure/1.0\"\n\ |
+namespace local = \"\"\n\ |
+datatypes xsd = \"http://www.w3.org/2001/XMLSchema-datatypes\"\n\ |
+\n\ |
+start = pattern\n\ |
+\n\ |
+pattern =\n\ |
+ element element { (nameQName | nameClass), (common & pattern+) }\n\ |
+ | element attribute { (nameQName | nameClass), (common & pattern?) }\n\ |
+ | element group|interleave|choice|optional\n\ |
+ |zeroOrMore|oneOrMore|list|mixed { common & pattern+ }\n\ |
+ | element ref|parentRef { nameNCName, common }\n\ |
+ | element empty|notAllowed|text { common }\n\ |
+ | element data { type, param*, (common & exceptPattern?) }\n\ |
+ | element value { commonAttributes, type?, xsd:string }\n\ |
+ | element externalRef { href, common }\n\ |
+ | element grammar { common & grammarContent* }\n\ |
+\n\ |
+param = element param { commonAttributes, nameNCName, xsd:string }\n\ |
+\n\ |
+exceptPattern = element except { common & pattern+ }\n\ |
+\n\ |
+grammarContent =\n\ |
+ definition\n\ |
+ | element div { common & grammarContent* }\n\ |
+ | element include { href, (common & includeContent*) }\n\ |
+\n\ |
+includeContent =\n\ |
+ definition\n\ |
+ | element div { common & includeContent* }\n\ |
+\n\ |
+definition =\n\ |
+ element start { combine?, (common & pattern+) }\n\ |
+ | element define { nameNCName, combine?, (common & pattern+) }\n\ |
+\n\ |
+combine = attribute combine { \"choice\" | \"interleave\" }\n\ |
+\n\ |
+nameClass =\n\ |
+ element name { commonAttributes, xsd:QName }\n\ |
+ | element anyName { common & exceptNameClass? }\n\ |
+ | element nsName { common & exceptNameClass? }\n\ |
+ | element choice { common & nameClass+ }\n\ |
+\n\ |
+exceptNameClass = element except { common & nameClass+ }\n\ |
+\n\ |
+nameQName = attribute name { xsd:QName }\n\ |
+nameNCName = attribute name { xsd:NCName }\n\ |
+href = attribute href { xsd:anyURI }\n\ |
+type = attribute type { xsd:NCName }\n\ |
+\n\ |
+common = commonAttributes, foreignElement*\n\ |
+\n\ |
+commonAttributes =\n\ |
+ attribute ns { xsd:string }?,\n\ |
+ attribute datatypeLibrary { xsd:anyURI }?,\n\ |
+ foreignAttribute*\n\ |
+\n\ |
+foreignElement = element * - rng:* { (anyAttribute | text | anyElement)* }\n\ |
+foreignAttribute = attribute * - (rng:*|local:*) { text }\n\ |
+anyElement = element * { (anyAttribute | text | anyElement)* }\n\ |
+anyAttribute = attribute * { text }\n\ |
+"; |
+ |
+int main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { |
+ xmlDocPtr res; |
+ |
+ res = xmlConvertCRNG(schemas, -1); |
+ if (res != NULL) { |
+ xmlDocFormatDump(stdout, res, 1); |
+ xmlFreeDoc(res); |
+ } |
+ return(0); |
+} |
+#endif |
+#define bottom_rngparser |
+#include "elfgcchack.h" |