2004-01-06 02:11:54 +03:00
/**
* rngparser . c : parser for the Relax - NG compact syntax .
*
2004-01-25 22:54:59 +03:00
* Based on :
* RELAX NG Compact Syntax
* Committee Specification 21 November 2002
* http : //www.oasis-open.org/committees/relax-ng/compact-20021121.html
*
2004-01-06 02:11:54 +03:00
* 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 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 ;
/*
2016-04-13 17:56:07 +03:00
* dictionary and keywords
2004-01-06 02:11:54 +03:00
*/
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 ;
2012-09-11 09:26:36 +04:00
if ( ( ctxt - > end - ctxt - > end > 2 ) & &
2004-01-06 02:11:54 +03:00
( * cur = = ' " ' ) & & ( cur [ 1 ] = = ' " ' ) ) {
2023-12-18 23:12:29 +03:00
/* TODO */
2004-01-06 02:11:54 +03:00
} 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 "'''" */
2023-12-18 23:12:29 +03:00
/* TODO */
2004-01-06 02:11:54 +03:00
} 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 {
2023-12-18 23:12:29 +03:00
/* TODO: sounds like an error ! */
2004-01-06 02:11:54 +03:00
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
2012-09-11 09:26:36 +04:00
*
2004-01-06 02:11:54 +03:00
* 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 + + ;
2012-09-11 09:26:36 +04:00
if ( ctxt - > totalToken = = 384 )
2004-01-06 02:11:54 +03:00
fprintf ( stderr , " found \n " ) ;
}
ctxt - > firstToken = ctxt - > firstToken % MAX_TOKEN ;
return ( 0 ) ;
}
static void
xmlParseCRNGTokenize ( xmlCRelaxNGParserCtxtPtr ctxt ) {
tokenPtr token ;
2012-09-11 09:26:36 +04:00
2004-01-06 02:11:54 +03:00
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
2012-09-11 09:26:36 +04:00
xmlParseCRNG_attribute ( xmlCRelaxNGParserCtxtPtr ctxt ,
2004-01-06 02:11:54 +03:00
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
2012-09-11 09:26:36 +04:00
xmlParseCRNG_bindPrefix ( xmlCRelaxNGParserCtxtPtr ctxt ,
2004-01-06 02:11:54 +03:00
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
2012-09-11 09:26:36 +04:00
ret = xmlHashAddEntry ( ctxt - > namespaces , prefix ,
2004-01-06 02:11:54 +03:00
( 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
2012-09-11 09:26:36 +04:00
xmlParseCRNG_bindDatatypePrefix ( xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED ,
2004-01-06 02:11:54 +03:00
const xmlChar * prefix ,
const xmlChar * namespace )
{
int ret ;
if ( ( prefix ! = NULL ) & & ( xmlStrEqual ( prefix , BAD_CAST " xsd " ) ) & &
2012-09-11 09:26:36 +04:00
( ! xmlStrEqual ( namespace ,
2004-01-06 02:11:54 +03:00
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 ) ;
}
2012-09-11 09:26:36 +04:00
ret = xmlHashAddEntry ( ctxt - > datatypes , prefix ,
2004-01-06 02:11:54 +03:00
( 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 *
2012-09-11 09:26:36 +04:00
xmlParseCRNG_lookupPrefix ( xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED ,
2004-01-06 02:11:54 +03:00
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 *
2012-09-11 09:26:36 +04:00
xmlParseCRNG_lookupDatatypePrefix ( xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED ,
2004-01-06 02:11:54 +03:00
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
2012-09-11 09:26:36 +04:00
xmlParseCRNG_datatypeAttributes ( xmlCRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED ,
2004-01-06 02:11:54 +03:00
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 )
{
2023-12-18 23:12:29 +03:00
/* TODO */
2004-01-06 02:11:54 +03:00
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 {
2023-12-18 23:12:29 +03:00
/* TODO */
2004-01-06 02:11:54 +03:00
}
} 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 " ,
2012-09-11 09:26:36 +04:00
xmlParseCRNG_lookupPrefix ( ctxt , NULL ) ) ;
2004-01-06 02:11:54 +03:00
} else {
2012-09-11 09:26:36 +04:00
xmlSetProp ( cur , BAD_CAST " ns " , BAD_CAST " " ) ;
2004-01-06 02:11:54 +03:00
}
xmlNodeAddContent ( cur , token - > token ) ;
if ( ctxt - > insert ! = NULL )
xmlAddChild ( ctxt - > insert , cur ) ;
ctxt - > insert = cur ;
xmlParseCRNGDropTokens ( ctxt , 1 ) ;
} else if ( token - > toktype = = CRNG_CNAME ) {
2023-12-18 23:12:29 +03:00
/* TODO */
2004-01-06 02:11:54 +03:00
} else if ( token - > toktype = = CRNG_NSNAME ) {
cur = xmlNewNode ( NULL , BAD_CAST " nsName " ) ;
if ( cur = = NULL ) CRNG_MEM_ERROR0 ( ) ;
xmlSetProp ( cur , BAD_CAST " ns " ,
2012-09-11 09:26:36 +04:00
xmlParseCRNG_lookupPrefix ( ctxt , token - > token ) ) ;
2004-01-06 02:11:54 +03:00
if ( ctxt - > insert ! = NULL )
xmlAddChild ( ctxt - > insert , cur ) ;
ctxt - > insert = cur ;
xmlParseCRNGDropTokens ( ctxt , 1 ) ;
xmlParseCRNG_exceptNameClass ( ctxt ) ;
} else {
2023-12-18 23:12:29 +03:00
/* TODO: probably an error */
2004-01-06 02:11:54 +03:00
}
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 ) {
2012-09-11 09:26:36 +04:00
attrs = xmlParseCRNG_datatypeAttributes ( ctxt , BAD_CAST " " ,
2004-01-06 02:11:54 +03:00
token - > token ) ;
xmlParseCRNGDropTokens ( ctxt , 1 ) ;
} else if ( token - > token = = ctxt - > key_token ) {
2012-09-11 09:26:36 +04:00
attrs = xmlParseCRNG_datatypeAttributes ( ctxt , BAD_CAST " " ,
2004-01-06 02:11:54 +03:00
token - > token ) ;
xmlParseCRNGDropTokens ( ctxt , 1 ) ;
} else {
2023-12-18 23:12:29 +03:00
/* TODO: probably an error */
2004-01-06 02:11:54 +03:00
}
} 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 ) {
2012-09-11 09:26:36 +04:00
attrs = xmlParseCRNG_datatypeAttributes ( ctxt ,
2004-01-06 02:11:54 +03:00
xmlParseCRNG_lookupDatatypePrefix ( ctxt , token - > prefix ) ,
token - > token ) ;
} else {
2023-12-18 23:12:29 +03:00
/* TODO */
2004-01-06 02:11:54 +03:00
}
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 ( ) ;
2023-12-18 23:12:29 +03:00
/* TODO */
2004-01-06 02:11:54 +03:00
} else if ( token - > token = = ctxt - > key_grammar ) {
ctxt - > insert = xmlNewNodeEatName ( NULL , ( xmlChar * ) token - > token ) ;
xmlParseCRNGDropTokens ( ctxt , 1 ) ;
if ( ctxt - > insert = = NULL ) CRNG_MEM_ERROR0 ( ) ;
2023-12-18 23:12:29 +03:00
/* TODO */
2004-01-06 02:11:54 +03:00
} else if ( token - > token = = ctxt - > key_external ) {
ctxt - > insert = xmlNewNode ( NULL , BAD_CAST " externalRef " ) ;
xmlParseCRNGDropTokens ( ctxt , 1 ) ;
if ( ctxt - > insert = = NULL ) CRNG_MEM_ERROR0 ( ) ;
2023-12-18 23:12:29 +03:00
/* TODO */
2004-01-06 02:11:54 +03:00
} else {
2023-12-18 23:12:29 +03:00
/* TODO */
2004-01-06 02:11:54 +03:00
}
} 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 ;
}
2012-09-11 09:26:36 +04:00
2004-01-06 02:11:54 +03:00
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 ;
2012-09-11 09:26:36 +04:00
2004-01-06 02:11:54 +03:00
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 ) {
2023-12-18 23:12:29 +03:00
/* TODO */
2004-01-06 02:11:54 +03:00
} else if ( token - > token = = ctxt - > key_div ) {
2023-12-18 23:12:29 +03:00
/* TODO */
2004-01-06 02:11:54 +03:00
} 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 ;
2012-09-11 09:26:36 +04:00
2004-01-06 02:11:54 +03:00
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 ;
2012-09-11 09:26:36 +04:00
2004-01-06 02:11:54 +03:00
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 ;
2012-09-11 09:26:36 +04:00
2004-01-06 02:11:54 +03:00
xmlParseCRNG_grammar ( ctxt ) ;
} else {
xmlParseCRNG_pattern ( ctxt ) ;
}
} else {
tok2 = xmlParseCRNGGetToken ( ctxt , 2 ) ;
2012-09-11 09:26:36 +04:00
if ( ( tok2 - > toktype = = CRNG_OP ) & &
2004-01-06 02:11:54 +03:00
( ( 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 ;
2012-09-11 09:26:36 +04:00
2004-01-06 02:11:54 +03:00
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 ;
2012-09-11 09:26:36 +04:00
2004-01-06 02:11:54 +03:00
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 ) ;
2012-09-11 09:26:36 +04:00
2004-01-06 02:11:54 +03:00
token = xmlParseCRNGGetToken ( ctxt , 1 ) ;
if ( ( token - > toktype ! = CRNG_KEYWORD ) & &
( token - > toktype ! = CRNG_IDENTIFIER ) ) {
ERROR ( " Expecting a datatype prefix identifier here " ) ;
2012-09-11 09:26:36 +04:00
} else
2004-01-06 02:11:54 +03:00
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 ;
2012-09-11 09:26:36 +04:00
2004-01-06 02:11:54 +03:00
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 ) ;
}
/**
2004-01-25 22:54:59 +03:00
* xmlConvertCRNG :
2004-01-06 02:11:54 +03:00
* @ schemas : pointer to the text of the compact schemas
* @ len : length of the schemas in bytes ( or 0 )
2004-01-25 22:54:59 +03:00
* @ encoding : encoding indicated by the context or NULL
2004-01-06 02:11:54 +03:00
*
* Compiles the schemas into the equivalent Relax - NG XML structure
*
* Returns the xmlDocPtr resulting from the compilation or
* NULL in case of error
*/
2004-01-25 22:54:59 +03:00
xmlDocPtr
xmlConvertCRNG ( const char * schemas , int len , const char * encoding ) {
2004-01-06 02:11:54 +03:00
struct _xmlCRelaxNGParserCtxt ctxt ;
xmlDocPtr ret = NULL ;
if ( schemas = = NULL ) return ( NULL ) ;
2004-02-11 16:25:26 +03:00
if ( len < = 5 ) len = xmlStrlen ( ( const unsigned char * ) schemas ) ;
2004-01-06 02:11:54 +03:00
if ( len < = 0 ) return ( NULL ) ;
memset ( & ctxt , 0 , sizeof ( ctxt ) ) ;
2004-02-11 16:25:26 +03:00
ctxt . compact = ( const unsigned char * ) schemas ;
ctxt . cur = ( const unsigned char * ) schemas ;
ctxt . end = ( const unsigned char * ) & schemas [ len ] ;
2004-01-06 02:11:54 +03:00
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 ) ;
2004-01-25 22:54:59 +03:00
/* xmlConvertCRNGTokenize(&ctxt); */
xmlConvertCRNG_topLevel ( & ctxt ) ;
2004-01-06 02:11:54 +03:00
xmlDictFree ( ctxt . dict ) ;
ret = ctxt . doc ;
return ( ret ) ;
}
2004-01-25 22:54:59 +03:00
/**
* 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
2004-04-22 11:15:40 +04:00
xmlConvertCRNGFile ( const char * URL , const char * encoding ) {
2004-01-25 22:54:59 +03:00
}
# ifdef STANDALONE
2012-09-11 09:26:36 +04:00
const xmlChar * schemas =
2004-01-06 02:11:54 +03:00
" # 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 ;
2004-01-25 22:54:59 +03:00
res = xmlConvertCRNG ( schemas , - 1 ) ;
2004-01-06 02:11:54 +03:00
if ( res ! = NULL ) {
xmlDocFormatDump ( stdout , res , 1 ) ;
xmlFreeDoc ( res ) ;
}
return ( 0 ) ;
}
2004-01-25 22:54:59 +03:00
# endif