Home | History | Annotate | Download | only in libxml2
      1 /*
      2  * schemastypes.c : implementation of the XML Schema Datatypes
      3  *             definition and validity checking
      4  *
      5  * See Copyright for the status of this software.
      6  *
      7  * Daniel Veillard <veillard (at) redhat.com>
      8  */
      9 
     10 #define IN_LIBXML
     11 #include "libxml.h"
     12 
     13 #ifdef LIBXML_SCHEMAS_ENABLED
     14 
     15 #include <string.h>
     16 #include <libxml/xmlmemory.h>
     17 #include <libxml/parser.h>
     18 #include <libxml/parserInternals.h>
     19 #include <libxml/hash.h>
     20 #include <libxml/valid.h>
     21 #include <libxml/xpath.h>
     22 #include <libxml/uri.h>
     23 
     24 #include <libxml/xmlschemas.h>
     25 #include <libxml/schemasInternals.h>
     26 #include <libxml/xmlschemastypes.h>
     27 
     28 #ifdef HAVE_MATH_H
     29 #include <math.h>
     30 #endif
     31 #ifdef HAVE_FLOAT_H
     32 #include <float.h>
     33 #endif
     34 
     35 #define DEBUG
     36 
     37 #ifndef LIBXML_XPATH_ENABLED
     38 extern double xmlXPathNAN;
     39 extern double xmlXPathPINF;
     40 extern double xmlXPathNINF;
     41 #endif
     42 
     43 #define TODO								\
     44     xmlGenericError(xmlGenericErrorContext,				\
     45 	    "Unimplemented block at %s:%d\n",				\
     46             __FILE__, __LINE__);
     47 
     48 #define XML_SCHEMAS_NAMESPACE_NAME \
     49     (const xmlChar *)"http://www.w3.org/2001/XMLSchema"
     50 
     51 #define IS_WSP_REPLACE_CH(c)	((((c) == 0x9) || ((c) == 0xa)) || \
     52 				 ((c) == 0xd))
     53 
     54 #define IS_WSP_SPACE_CH(c)	((c) == 0x20)
     55 
     56 #define IS_WSP_BLANK_CH(c) IS_BLANK_CH(c)
     57 
     58 /* Date value */
     59 typedef struct _xmlSchemaValDate xmlSchemaValDate;
     60 typedef xmlSchemaValDate *xmlSchemaValDatePtr;
     61 struct _xmlSchemaValDate {
     62     long		year;
     63     unsigned int	mon	:4;	/* 1 <=  mon    <= 12   */
     64     unsigned int	day	:5;	/* 1 <=  day    <= 31   */
     65     unsigned int	hour	:5;	/* 0 <=  hour   <= 24   */
     66     unsigned int	min	:6;	/* 0 <=  min    <= 59	*/
     67     double		sec;
     68     unsigned int	tz_flag	:1;	/* is tzo explicitely set? */
     69     signed int		tzo	:12;	/* -1440 <= tzo <= 1440;
     70 					   currently only -840 to +840 are needed */
     71 };
     72 
     73 /* Duration value */
     74 typedef struct _xmlSchemaValDuration xmlSchemaValDuration;
     75 typedef xmlSchemaValDuration *xmlSchemaValDurationPtr;
     76 struct _xmlSchemaValDuration {
     77     long	        mon;		/* mon stores years also */
     78     long	day;
     79     double		sec;            /* sec stores min and hour also */
     80 };
     81 
     82 typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal;
     83 typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr;
     84 struct _xmlSchemaValDecimal {
     85     /* would use long long but not portable */
     86     unsigned long lo;
     87     unsigned long mi;
     88     unsigned long hi;
     89     unsigned int extra;
     90     unsigned int sign:1;
     91     unsigned int frac:7;
     92     unsigned int total:8;
     93 };
     94 
     95 typedef struct _xmlSchemaValQName xmlSchemaValQName;
     96 typedef xmlSchemaValQName *xmlSchemaValQNamePtr;
     97 struct _xmlSchemaValQName {
     98     xmlChar *name;
     99     xmlChar *uri;
    100 };
    101 
    102 typedef struct _xmlSchemaValHex xmlSchemaValHex;
    103 typedef xmlSchemaValHex *xmlSchemaValHexPtr;
    104 struct _xmlSchemaValHex {
    105     xmlChar     *str;
    106     unsigned int total;
    107 };
    108 
    109 typedef struct _xmlSchemaValBase64 xmlSchemaValBase64;
    110 typedef xmlSchemaValBase64 *xmlSchemaValBase64Ptr;
    111 struct _xmlSchemaValBase64 {
    112     xmlChar     *str;
    113     unsigned int total;
    114 };
    115 
    116 struct _xmlSchemaVal {
    117     xmlSchemaValType type;
    118     struct _xmlSchemaVal *next;
    119     union {
    120 	xmlSchemaValDecimal     decimal;
    121         xmlSchemaValDate        date;
    122         xmlSchemaValDuration    dur;
    123 	xmlSchemaValQName	qname;
    124 	xmlSchemaValHex		hex;
    125 	xmlSchemaValBase64	base64;
    126 	float			f;
    127 	double			d;
    128 	int			b;
    129 	xmlChar                *str;
    130     } value;
    131 };
    132 
    133 static int xmlSchemaTypesInitialized = 0;
    134 static xmlHashTablePtr xmlSchemaTypesBank = NULL;
    135 
    136 /*
    137  * Basic types
    138  */
    139 static xmlSchemaTypePtr xmlSchemaTypeStringDef = NULL;
    140 static xmlSchemaTypePtr xmlSchemaTypeAnyTypeDef = NULL;
    141 static xmlSchemaTypePtr xmlSchemaTypeAnySimpleTypeDef = NULL;
    142 static xmlSchemaTypePtr xmlSchemaTypeDecimalDef = NULL;
    143 static xmlSchemaTypePtr xmlSchemaTypeDatetimeDef = NULL;
    144 static xmlSchemaTypePtr xmlSchemaTypeDateDef = NULL;
    145 static xmlSchemaTypePtr xmlSchemaTypeTimeDef = NULL;
    146 static xmlSchemaTypePtr xmlSchemaTypeGYearDef = NULL;
    147 static xmlSchemaTypePtr xmlSchemaTypeGYearMonthDef = NULL;
    148 static xmlSchemaTypePtr xmlSchemaTypeGDayDef = NULL;
    149 static xmlSchemaTypePtr xmlSchemaTypeGMonthDayDef = NULL;
    150 static xmlSchemaTypePtr xmlSchemaTypeGMonthDef = NULL;
    151 static xmlSchemaTypePtr xmlSchemaTypeDurationDef = NULL;
    152 static xmlSchemaTypePtr xmlSchemaTypeFloatDef = NULL;
    153 static xmlSchemaTypePtr xmlSchemaTypeBooleanDef = NULL;
    154 static xmlSchemaTypePtr xmlSchemaTypeDoubleDef = NULL;
    155 static xmlSchemaTypePtr xmlSchemaTypeHexBinaryDef = NULL;
    156 static xmlSchemaTypePtr xmlSchemaTypeBase64BinaryDef = NULL;
    157 static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef = NULL;
    158 
    159 /*
    160  * Derived types
    161  */
    162 static xmlSchemaTypePtr xmlSchemaTypePositiveIntegerDef = NULL;
    163 static xmlSchemaTypePtr xmlSchemaTypeNonPositiveIntegerDef = NULL;
    164 static xmlSchemaTypePtr xmlSchemaTypeNegativeIntegerDef = NULL;
    165 static xmlSchemaTypePtr xmlSchemaTypeNonNegativeIntegerDef = NULL;
    166 static xmlSchemaTypePtr xmlSchemaTypeIntegerDef = NULL;
    167 static xmlSchemaTypePtr xmlSchemaTypeLongDef = NULL;
    168 static xmlSchemaTypePtr xmlSchemaTypeIntDef = NULL;
    169 static xmlSchemaTypePtr xmlSchemaTypeShortDef = NULL;
    170 static xmlSchemaTypePtr xmlSchemaTypeByteDef = NULL;
    171 static xmlSchemaTypePtr xmlSchemaTypeUnsignedLongDef = NULL;
    172 static xmlSchemaTypePtr xmlSchemaTypeUnsignedIntDef = NULL;
    173 static xmlSchemaTypePtr xmlSchemaTypeUnsignedShortDef = NULL;
    174 static xmlSchemaTypePtr xmlSchemaTypeUnsignedByteDef = NULL;
    175 static xmlSchemaTypePtr xmlSchemaTypeNormStringDef = NULL;
    176 static xmlSchemaTypePtr xmlSchemaTypeTokenDef = NULL;
    177 static xmlSchemaTypePtr xmlSchemaTypeLanguageDef = NULL;
    178 static xmlSchemaTypePtr xmlSchemaTypeNameDef = NULL;
    179 static xmlSchemaTypePtr xmlSchemaTypeQNameDef = NULL;
    180 static xmlSchemaTypePtr xmlSchemaTypeNCNameDef = NULL;
    181 static xmlSchemaTypePtr xmlSchemaTypeIdDef = NULL;
    182 static xmlSchemaTypePtr xmlSchemaTypeIdrefDef = NULL;
    183 static xmlSchemaTypePtr xmlSchemaTypeIdrefsDef = NULL;
    184 static xmlSchemaTypePtr xmlSchemaTypeEntityDef = NULL;
    185 static xmlSchemaTypePtr xmlSchemaTypeEntitiesDef = NULL;
    186 static xmlSchemaTypePtr xmlSchemaTypeNotationDef = NULL;
    187 static xmlSchemaTypePtr xmlSchemaTypeNmtokenDef = NULL;
    188 static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef = NULL;
    189 
    190 /************************************************************************
    191  *									*
    192  *			Datatype error handlers				*
    193  *									*
    194  ************************************************************************/
    195 /**
    196  * xmlSchemaTypeErrMemory:
    197  * @extra:  extra informations
    198  *
    199  * Handle an out of memory condition
    200  */
    201 static void
    202 xmlSchemaTypeErrMemory(xmlNodePtr node, const char *extra)
    203 {
    204     __xmlSimpleError(XML_FROM_DATATYPE, XML_ERR_NO_MEMORY, node, NULL, extra);
    205 }
    206 
    207 /************************************************************************
    208  *									*
    209  *			Base types support				*
    210  *									*
    211  ************************************************************************/
    212 
    213 /**
    214  * xmlSchemaNewValue:
    215  * @type:  the value type
    216  *
    217  * Allocate a new simple type value
    218  *
    219  * Returns a pointer to the new value or NULL in case of error
    220  */
    221 static xmlSchemaValPtr
    222 xmlSchemaNewValue(xmlSchemaValType type) {
    223     xmlSchemaValPtr value;
    224 
    225     value = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
    226     if (value == NULL) {
    227 	return(NULL);
    228     }
    229     memset(value, 0, sizeof(xmlSchemaVal));
    230     value->type = type;
    231     return(value);
    232 }
    233 
    234 static xmlSchemaFacetPtr
    235 xmlSchemaNewMinLengthFacet(int value)
    236 {
    237     xmlSchemaFacetPtr ret;
    238 
    239     ret = xmlSchemaNewFacet();
    240     if (ret == NULL) {
    241         return(NULL);
    242     }
    243     ret->type = XML_SCHEMA_FACET_MINLENGTH;
    244     ret->val = xmlSchemaNewValue(XML_SCHEMAS_NNINTEGER);
    245     if (ret->val == NULL) {
    246         xmlFree(ret);
    247 	return(NULL);
    248     }
    249     ret->val->value.decimal.lo = value;
    250     return (ret);
    251 }
    252 
    253 /*
    254  * xmlSchemaInitBasicType:
    255  * @name:  the type name
    256  * @type:  the value type associated
    257  *
    258  * Initialize one primitive built-in type
    259  */
    260 static xmlSchemaTypePtr
    261 xmlSchemaInitBasicType(const char *name, xmlSchemaValType type,
    262 		       xmlSchemaTypePtr baseType) {
    263     xmlSchemaTypePtr ret;
    264 
    265     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
    266     if (ret == NULL) {
    267         xmlSchemaTypeErrMemory(NULL, "could not initialize basic types");
    268 	return(NULL);
    269     }
    270     memset(ret, 0, sizeof(xmlSchemaType));
    271     ret->name = (const xmlChar *)name;
    272     ret->targetNamespace = XML_SCHEMAS_NAMESPACE_NAME;
    273     ret->type = XML_SCHEMA_TYPE_BASIC;
    274     ret->baseType = baseType;
    275     ret->contentType = XML_SCHEMA_CONTENT_BASIC;
    276     /*
    277     * Primitive types.
    278     */
    279     switch (type) {
    280 	case XML_SCHEMAS_STRING:
    281 	case XML_SCHEMAS_DECIMAL:
    282 	case XML_SCHEMAS_DATE:
    283 	case XML_SCHEMAS_DATETIME:
    284 	case XML_SCHEMAS_TIME:
    285 	case XML_SCHEMAS_GYEAR:
    286 	case XML_SCHEMAS_GYEARMONTH:
    287 	case XML_SCHEMAS_GMONTH:
    288 	case XML_SCHEMAS_GMONTHDAY:
    289 	case XML_SCHEMAS_GDAY:
    290 	case XML_SCHEMAS_DURATION:
    291 	case XML_SCHEMAS_FLOAT:
    292 	case XML_SCHEMAS_DOUBLE:
    293 	case XML_SCHEMAS_BOOLEAN:
    294 	case XML_SCHEMAS_ANYURI:
    295 	case XML_SCHEMAS_HEXBINARY:
    296 	case XML_SCHEMAS_BASE64BINARY:
    297 	case XML_SCHEMAS_QNAME:
    298 	case XML_SCHEMAS_NOTATION:
    299 	    ret->flags |= XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE;
    300 	    break;
    301 	default:
    302 	    break;
    303     }
    304     /*
    305     * Set variety.
    306     */
    307     switch (type) {
    308 	case XML_SCHEMAS_ANYTYPE:
    309 	case XML_SCHEMAS_ANYSIMPLETYPE:
    310 	    break;
    311 	case XML_SCHEMAS_IDREFS:
    312 	case XML_SCHEMAS_NMTOKENS:
    313 	case XML_SCHEMAS_ENTITIES:
    314 	    ret->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
    315 	    ret->facets = xmlSchemaNewMinLengthFacet(1);
    316 	    ret->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
    317 	    break;
    318 	default:
    319 	    ret->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
    320 	    break;
    321     }
    322     xmlHashAddEntry2(xmlSchemaTypesBank, ret->name,
    323 	             XML_SCHEMAS_NAMESPACE_NAME, ret);
    324     ret->builtInType = type;
    325     return(ret);
    326 }
    327 
    328 /*
    329 * WARNING: Those type reside normally in xmlschemas.c but are
    330 * redefined here locally in oder of being able to use them for xs:anyType-
    331 * TODO: Remove those definition if we move the types to a header file.
    332 * TODO: Always keep those structs up-to-date with the originals.
    333 */
    334 #define UNBOUNDED (1 << 30)
    335 
    336 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
    337 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
    338 struct _xmlSchemaTreeItem {
    339     xmlSchemaTypeType type;
    340     xmlSchemaAnnotPtr annot;
    341     xmlSchemaTreeItemPtr next;
    342     xmlSchemaTreeItemPtr children;
    343 };
    344 
    345 typedef struct _xmlSchemaParticle xmlSchemaParticle;
    346 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
    347 struct _xmlSchemaParticle {
    348     xmlSchemaTypeType type;
    349     xmlSchemaAnnotPtr annot;
    350     xmlSchemaTreeItemPtr next;
    351     xmlSchemaTreeItemPtr children;
    352     int minOccurs;
    353     int maxOccurs;
    354     xmlNodePtr node;
    355 };
    356 
    357 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
    358 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
    359 struct _xmlSchemaModelGroup {
    360     xmlSchemaTypeType type;
    361     xmlSchemaAnnotPtr annot;
    362     xmlSchemaTreeItemPtr next;
    363     xmlSchemaTreeItemPtr children;
    364     xmlNodePtr node;
    365 };
    366 
    367 static xmlSchemaParticlePtr
    368 xmlSchemaAddParticle(void)
    369 {
    370     xmlSchemaParticlePtr ret = NULL;
    371 
    372     ret = (xmlSchemaParticlePtr)
    373 	xmlMalloc(sizeof(xmlSchemaParticle));
    374     if (ret == NULL) {
    375 	xmlSchemaTypeErrMemory(NULL, "allocating particle component");
    376 	return (NULL);
    377     }
    378     memset(ret, 0, sizeof(xmlSchemaParticle));
    379     ret->type = XML_SCHEMA_TYPE_PARTICLE;
    380     ret->minOccurs = 1;
    381     ret->maxOccurs = 1;
    382     return (ret);
    383 }
    384 
    385 /*
    386  * xmlSchemaInitTypes:
    387  *
    388  * Initialize the default XML Schemas type library
    389  */
    390 void
    391 xmlSchemaInitTypes(void)
    392 {
    393     if (xmlSchemaTypesInitialized != 0)
    394         return;
    395     xmlSchemaTypesBank = xmlHashCreate(40);
    396 
    397 
    398     /*
    399     * 3.4.7 Built-in Complex Type Definition
    400     */
    401     xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType",
    402                                                      XML_SCHEMAS_ANYTYPE,
    403 						     NULL);
    404     xmlSchemaTypeAnyTypeDef->baseType = xmlSchemaTypeAnyTypeDef;
    405     xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED;
    406     /*
    407     * Init the content type.
    408     */
    409     xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED;
    410     {
    411 	xmlSchemaParticlePtr particle;
    412 	xmlSchemaModelGroupPtr sequence;
    413 	xmlSchemaWildcardPtr wild;
    414 	/* First particle. */
    415 	particle = xmlSchemaAddParticle();
    416 	if (particle == NULL)
    417 	    return;
    418 	xmlSchemaTypeAnyTypeDef->subtypes = (xmlSchemaTypePtr) particle;
    419 	/* Sequence model group. */
    420 	sequence = (xmlSchemaModelGroupPtr)
    421 	    xmlMalloc(sizeof(xmlSchemaModelGroup));
    422 	if (sequence == NULL) {
    423 	    xmlSchemaTypeErrMemory(NULL, "allocating model group component");
    424 	    return;
    425 	}
    426 	memset(sequence, 0, sizeof(xmlSchemaModelGroup));
    427 	sequence->type = XML_SCHEMA_TYPE_SEQUENCE;
    428 	particle->children = (xmlSchemaTreeItemPtr) sequence;
    429 	/* Second particle. */
    430 	particle = xmlSchemaAddParticle();
    431 	if (particle == NULL)
    432 	    return;
    433 	particle->minOccurs = 0;
    434 	particle->maxOccurs = UNBOUNDED;
    435 	sequence->children = (xmlSchemaTreeItemPtr) particle;
    436 	/* The wildcard */
    437 	wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
    438 	if (wild == NULL) {
    439 	    xmlSchemaTypeErrMemory(NULL, "allocating wildcard component");
    440 	    return;
    441 	}
    442 	memset(wild, 0, sizeof(xmlSchemaWildcard));
    443 	wild->type = XML_SCHEMA_TYPE_ANY;
    444 	wild->any = 1;
    445 	wild->processContents = XML_SCHEMAS_ANY_LAX;
    446 	particle->children = (xmlSchemaTreeItemPtr) wild;
    447 	/*
    448 	* Create the attribute wildcard.
    449 	*/
    450 	wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
    451 	if (wild == NULL) {
    452 	    xmlSchemaTypeErrMemory(NULL, "could not create an attribute "
    453 		"wildcard on anyType");
    454 	    return;
    455 	}
    456 	memset(wild, 0, sizeof(xmlSchemaWildcard));
    457 	wild->any = 1;
    458 	wild->processContents = XML_SCHEMAS_ANY_LAX;
    459 	xmlSchemaTypeAnyTypeDef->attributeWildcard = wild;
    460     }
    461     xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType",
    462                                                            XML_SCHEMAS_ANYSIMPLETYPE,
    463 							   xmlSchemaTypeAnyTypeDef);
    464     /*
    465     * primitive datatypes
    466     */
    467     xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string",
    468                                                     XML_SCHEMAS_STRING,
    469 						    xmlSchemaTypeAnySimpleTypeDef);
    470     xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal",
    471                                                      XML_SCHEMAS_DECIMAL,
    472 						     xmlSchemaTypeAnySimpleTypeDef);
    473     xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date",
    474                                                   XML_SCHEMAS_DATE,
    475 						  xmlSchemaTypeAnySimpleTypeDef);
    476     xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime",
    477                                                       XML_SCHEMAS_DATETIME,
    478 						      xmlSchemaTypeAnySimpleTypeDef);
    479     xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time",
    480                                                   XML_SCHEMAS_TIME,
    481 						  xmlSchemaTypeAnySimpleTypeDef);
    482     xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear",
    483                                                    XML_SCHEMAS_GYEAR,
    484 						   xmlSchemaTypeAnySimpleTypeDef);
    485     xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth",
    486                                                         XML_SCHEMAS_GYEARMONTH,
    487 							xmlSchemaTypeAnySimpleTypeDef);
    488     xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth",
    489                                                     XML_SCHEMAS_GMONTH,
    490 						    xmlSchemaTypeAnySimpleTypeDef);
    491     xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay",
    492                                                        XML_SCHEMAS_GMONTHDAY,
    493 						       xmlSchemaTypeAnySimpleTypeDef);
    494     xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay",
    495                                                   XML_SCHEMAS_GDAY,
    496 						  xmlSchemaTypeAnySimpleTypeDef);
    497     xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration",
    498                                                       XML_SCHEMAS_DURATION,
    499 						      xmlSchemaTypeAnySimpleTypeDef);
    500     xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float",
    501                                                    XML_SCHEMAS_FLOAT,
    502 						   xmlSchemaTypeAnySimpleTypeDef);
    503     xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double",
    504                                                     XML_SCHEMAS_DOUBLE,
    505 						    xmlSchemaTypeAnySimpleTypeDef);
    506     xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType("boolean",
    507                                                      XML_SCHEMAS_BOOLEAN,
    508 						     xmlSchemaTypeAnySimpleTypeDef);
    509     xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType("anyURI",
    510                                                     XML_SCHEMAS_ANYURI,
    511 						    xmlSchemaTypeAnySimpleTypeDef);
    512     xmlSchemaTypeHexBinaryDef = xmlSchemaInitBasicType("hexBinary",
    513                                                      XML_SCHEMAS_HEXBINARY,
    514 						     xmlSchemaTypeAnySimpleTypeDef);
    515     xmlSchemaTypeBase64BinaryDef
    516         = xmlSchemaInitBasicType("base64Binary", XML_SCHEMAS_BASE64BINARY,
    517 	xmlSchemaTypeAnySimpleTypeDef);
    518     xmlSchemaTypeNotationDef = xmlSchemaInitBasicType("NOTATION",
    519                                                     XML_SCHEMAS_NOTATION,
    520 						    xmlSchemaTypeAnySimpleTypeDef);
    521     xmlSchemaTypeQNameDef = xmlSchemaInitBasicType("QName",
    522                                                    XML_SCHEMAS_QNAME,
    523 						   xmlSchemaTypeAnySimpleTypeDef);
    524 
    525     /*
    526      * derived datatypes
    527      */
    528     xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType("integer",
    529                                                      XML_SCHEMAS_INTEGER,
    530 						     xmlSchemaTypeDecimalDef);
    531     xmlSchemaTypeNonPositiveIntegerDef =
    532         xmlSchemaInitBasicType("nonPositiveInteger",
    533                                XML_SCHEMAS_NPINTEGER,
    534 			       xmlSchemaTypeIntegerDef);
    535     xmlSchemaTypeNegativeIntegerDef =
    536         xmlSchemaInitBasicType("negativeInteger", XML_SCHEMAS_NINTEGER,
    537 	xmlSchemaTypeNonPositiveIntegerDef);
    538     xmlSchemaTypeLongDef =
    539         xmlSchemaInitBasicType("long", XML_SCHEMAS_LONG,
    540 	xmlSchemaTypeIntegerDef);
    541     xmlSchemaTypeIntDef = xmlSchemaInitBasicType("int", XML_SCHEMAS_INT,
    542 	xmlSchemaTypeLongDef);
    543     xmlSchemaTypeShortDef = xmlSchemaInitBasicType("short",
    544                                                    XML_SCHEMAS_SHORT,
    545 						   xmlSchemaTypeIntDef);
    546     xmlSchemaTypeByteDef = xmlSchemaInitBasicType("byte",
    547                                                   XML_SCHEMAS_BYTE,
    548 						  xmlSchemaTypeShortDef);
    549     xmlSchemaTypeNonNegativeIntegerDef =
    550         xmlSchemaInitBasicType("nonNegativeInteger",
    551                                XML_SCHEMAS_NNINTEGER,
    552 			       xmlSchemaTypeIntegerDef);
    553     xmlSchemaTypeUnsignedLongDef =
    554         xmlSchemaInitBasicType("unsignedLong", XML_SCHEMAS_ULONG,
    555 	xmlSchemaTypeNonNegativeIntegerDef);
    556     xmlSchemaTypeUnsignedIntDef =
    557         xmlSchemaInitBasicType("unsignedInt", XML_SCHEMAS_UINT,
    558 	xmlSchemaTypeUnsignedLongDef);
    559     xmlSchemaTypeUnsignedShortDef =
    560         xmlSchemaInitBasicType("unsignedShort", XML_SCHEMAS_USHORT,
    561 	xmlSchemaTypeUnsignedIntDef);
    562     xmlSchemaTypeUnsignedByteDef =
    563         xmlSchemaInitBasicType("unsignedByte", XML_SCHEMAS_UBYTE,
    564 	xmlSchemaTypeUnsignedShortDef);
    565     xmlSchemaTypePositiveIntegerDef =
    566         xmlSchemaInitBasicType("positiveInteger", XML_SCHEMAS_PINTEGER,
    567 	xmlSchemaTypeNonNegativeIntegerDef);
    568     xmlSchemaTypeNormStringDef = xmlSchemaInitBasicType("normalizedString",
    569                                                         XML_SCHEMAS_NORMSTRING,
    570 							xmlSchemaTypeStringDef);
    571     xmlSchemaTypeTokenDef = xmlSchemaInitBasicType("token",
    572                                                    XML_SCHEMAS_TOKEN,
    573 						   xmlSchemaTypeNormStringDef);
    574     xmlSchemaTypeLanguageDef = xmlSchemaInitBasicType("language",
    575                                                       XML_SCHEMAS_LANGUAGE,
    576 						      xmlSchemaTypeTokenDef);
    577     xmlSchemaTypeNameDef = xmlSchemaInitBasicType("Name",
    578                                                   XML_SCHEMAS_NAME,
    579 						  xmlSchemaTypeTokenDef);
    580     xmlSchemaTypeNmtokenDef = xmlSchemaInitBasicType("NMTOKEN",
    581                                                      XML_SCHEMAS_NMTOKEN,
    582 						     xmlSchemaTypeTokenDef);
    583     xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType("NCName",
    584                                                     XML_SCHEMAS_NCNAME,
    585 						    xmlSchemaTypeNameDef);
    586     xmlSchemaTypeIdDef = xmlSchemaInitBasicType("ID", XML_SCHEMAS_ID,
    587 						    xmlSchemaTypeNCNameDef);
    588     xmlSchemaTypeIdrefDef = xmlSchemaInitBasicType("IDREF",
    589                                                    XML_SCHEMAS_IDREF,
    590 						   xmlSchemaTypeNCNameDef);
    591     xmlSchemaTypeEntityDef = xmlSchemaInitBasicType("ENTITY",
    592                                                     XML_SCHEMAS_ENTITY,
    593 						    xmlSchemaTypeNCNameDef);
    594     /*
    595     * Derived list types.
    596     */
    597     /* ENTITIES */
    598     xmlSchemaTypeEntitiesDef = xmlSchemaInitBasicType("ENTITIES",
    599                                                       XML_SCHEMAS_ENTITIES,
    600 						      xmlSchemaTypeAnySimpleTypeDef);
    601     xmlSchemaTypeEntitiesDef->subtypes = xmlSchemaTypeEntityDef;
    602     /* IDREFS */
    603     xmlSchemaTypeIdrefsDef = xmlSchemaInitBasicType("IDREFS",
    604                                                     XML_SCHEMAS_IDREFS,
    605 						    xmlSchemaTypeAnySimpleTypeDef);
    606     xmlSchemaTypeIdrefsDef->subtypes = xmlSchemaTypeIdrefDef;
    607 
    608     /* NMTOKENS */
    609     xmlSchemaTypeNmtokensDef = xmlSchemaInitBasicType("NMTOKENS",
    610                                                       XML_SCHEMAS_NMTOKENS,
    611 						      xmlSchemaTypeAnySimpleTypeDef);
    612     xmlSchemaTypeNmtokensDef->subtypes = xmlSchemaTypeNmtokenDef;
    613 
    614     xmlSchemaTypesInitialized = 1;
    615 }
    616 
    617 /**
    618  * xmlSchemaCleanupTypes:
    619  *
    620  * Cleanup the default XML Schemas type library
    621  */
    622 void
    623 xmlSchemaCleanupTypes(void) {
    624     if (xmlSchemaTypesInitialized == 0)
    625 	return;
    626     /*
    627     * Free xs:anyType.
    628     */
    629     {
    630 	xmlSchemaParticlePtr particle;
    631 	/* Attribute wildcard. */
    632 	xmlSchemaFreeWildcard(xmlSchemaTypeAnyTypeDef->attributeWildcard);
    633 	/* Content type. */
    634 	particle = (xmlSchemaParticlePtr) xmlSchemaTypeAnyTypeDef->subtypes;
    635 	/* Wildcard. */
    636 	xmlSchemaFreeWildcard((xmlSchemaWildcardPtr)
    637 	    particle->children->children->children);
    638 	xmlFree((xmlSchemaParticlePtr) particle->children->children);
    639 	/* Sequence model group. */
    640 	xmlFree((xmlSchemaModelGroupPtr) particle->children);
    641 	xmlFree((xmlSchemaParticlePtr) particle);
    642 	xmlSchemaTypeAnyTypeDef->subtypes = NULL;
    643     }
    644     xmlHashFree(xmlSchemaTypesBank, (xmlHashDeallocator) xmlSchemaFreeType);
    645     xmlSchemaTypesInitialized = 0;
    646 }
    647 
    648 /**
    649  * xmlSchemaIsBuiltInTypeFacet:
    650  * @type: the built-in type
    651  * @facetType:  the facet type
    652  *
    653  * Evaluates if a specific facet can be
    654  * used in conjunction with a type.
    655  *
    656  * Returns 1 if the facet can be used with the given built-in type,
    657  * 0 otherwise and -1 in case the type is not a built-in type.
    658  */
    659 int
    660 xmlSchemaIsBuiltInTypeFacet(xmlSchemaTypePtr type, int facetType)
    661 {
    662     if (type == NULL)
    663 	return (-1);
    664     if (type->type != XML_SCHEMA_TYPE_BASIC)
    665 	return (-1);
    666     switch (type->builtInType) {
    667 	case XML_SCHEMAS_BOOLEAN:
    668 	    if ((facetType == XML_SCHEMA_FACET_PATTERN) ||
    669 		(facetType == XML_SCHEMA_FACET_WHITESPACE))
    670 		return (1);
    671 	    else
    672 		return (0);
    673 	case XML_SCHEMAS_STRING:
    674 	case XML_SCHEMAS_NOTATION:
    675 	case XML_SCHEMAS_QNAME:
    676 	case XML_SCHEMAS_ANYURI:
    677 	case XML_SCHEMAS_BASE64BINARY:
    678 	case XML_SCHEMAS_HEXBINARY:
    679 	    if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
    680 		(facetType == XML_SCHEMA_FACET_MINLENGTH) ||
    681 		(facetType == XML_SCHEMA_FACET_MAXLENGTH) ||
    682 		(facetType == XML_SCHEMA_FACET_PATTERN) ||
    683 		(facetType == XML_SCHEMA_FACET_ENUMERATION) ||
    684 		(facetType == XML_SCHEMA_FACET_WHITESPACE))
    685 		return (1);
    686 	    else
    687 		return (0);
    688 	case XML_SCHEMAS_DECIMAL:
    689 	    if ((facetType == XML_SCHEMA_FACET_TOTALDIGITS) ||
    690 		(facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) ||
    691 		(facetType == XML_SCHEMA_FACET_PATTERN) ||
    692 		(facetType == XML_SCHEMA_FACET_WHITESPACE) ||
    693 		(facetType == XML_SCHEMA_FACET_ENUMERATION) ||
    694 		(facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) ||
    695 		(facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) ||
    696 		(facetType == XML_SCHEMA_FACET_MININCLUSIVE) ||
    697 		(facetType == XML_SCHEMA_FACET_MINEXCLUSIVE))
    698 		return (1);
    699 	    else
    700 		return (0);
    701 	case XML_SCHEMAS_TIME:
    702 	case XML_SCHEMAS_GDAY:
    703 	case XML_SCHEMAS_GMONTH:
    704 	case XML_SCHEMAS_GMONTHDAY:
    705 	case XML_SCHEMAS_GYEAR:
    706 	case XML_SCHEMAS_GYEARMONTH:
    707 	case XML_SCHEMAS_DATE:
    708 	case XML_SCHEMAS_DATETIME:
    709 	case XML_SCHEMAS_DURATION:
    710 	case XML_SCHEMAS_FLOAT:
    711 	case XML_SCHEMAS_DOUBLE:
    712 	    if ((facetType == XML_SCHEMA_FACET_PATTERN) ||
    713 		(facetType == XML_SCHEMA_FACET_ENUMERATION) ||
    714 		(facetType == XML_SCHEMA_FACET_WHITESPACE) ||
    715 		(facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) ||
    716 		(facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) ||
    717 		(facetType == XML_SCHEMA_FACET_MININCLUSIVE) ||
    718 		(facetType == XML_SCHEMA_FACET_MINEXCLUSIVE))
    719 		return (1);
    720 	    else
    721 		return (0);
    722 	default:
    723 	    break;
    724     }
    725     return (0);
    726 }
    727 
    728 /**
    729  * xmlSchemaGetBuiltInType:
    730  * @type:  the type of the built in type
    731  *
    732  * Gives you the type struct for a built-in
    733  * type by its type id.
    734  *
    735  * Returns the type if found, NULL otherwise.
    736  */
    737 xmlSchemaTypePtr
    738 xmlSchemaGetBuiltInType(xmlSchemaValType type)
    739 {
    740     if (xmlSchemaTypesInitialized == 0)
    741 	xmlSchemaInitTypes();
    742     switch (type) {
    743 
    744 	case XML_SCHEMAS_ANYSIMPLETYPE:
    745 	    return (xmlSchemaTypeAnySimpleTypeDef);
    746 	case XML_SCHEMAS_STRING:
    747 	    return (xmlSchemaTypeStringDef);
    748 	case XML_SCHEMAS_NORMSTRING:
    749 	    return (xmlSchemaTypeNormStringDef);
    750 	case XML_SCHEMAS_DECIMAL:
    751 	    return (xmlSchemaTypeDecimalDef);
    752 	case XML_SCHEMAS_TIME:
    753 	    return (xmlSchemaTypeTimeDef);
    754 	case XML_SCHEMAS_GDAY:
    755 	    return (xmlSchemaTypeGDayDef);
    756 	case XML_SCHEMAS_GMONTH:
    757 	    return (xmlSchemaTypeGMonthDef);
    758 	case XML_SCHEMAS_GMONTHDAY:
    759 	    return (xmlSchemaTypeGMonthDayDef);
    760 	case XML_SCHEMAS_GYEAR:
    761 	    return (xmlSchemaTypeGYearDef);
    762 	case XML_SCHEMAS_GYEARMONTH:
    763 	    return (xmlSchemaTypeGYearMonthDef);
    764 	case XML_SCHEMAS_DATE:
    765 	    return (xmlSchemaTypeDateDef);
    766 	case XML_SCHEMAS_DATETIME:
    767 	    return (xmlSchemaTypeDatetimeDef);
    768 	case XML_SCHEMAS_DURATION:
    769 	    return (xmlSchemaTypeDurationDef);
    770 	case XML_SCHEMAS_FLOAT:
    771 	    return (xmlSchemaTypeFloatDef);
    772 	case XML_SCHEMAS_DOUBLE:
    773 	    return (xmlSchemaTypeDoubleDef);
    774 	case XML_SCHEMAS_BOOLEAN:
    775 	    return (xmlSchemaTypeBooleanDef);
    776 	case XML_SCHEMAS_TOKEN:
    777 	    return (xmlSchemaTypeTokenDef);
    778 	case XML_SCHEMAS_LANGUAGE:
    779 	    return (xmlSchemaTypeLanguageDef);
    780 	case XML_SCHEMAS_NMTOKEN:
    781 	    return (xmlSchemaTypeNmtokenDef);
    782 	case XML_SCHEMAS_NMTOKENS:
    783 	    return (xmlSchemaTypeNmtokensDef);
    784 	case XML_SCHEMAS_NAME:
    785 	    return (xmlSchemaTypeNameDef);
    786 	case XML_SCHEMAS_QNAME:
    787 	    return (xmlSchemaTypeQNameDef);
    788 	case XML_SCHEMAS_NCNAME:
    789 	    return (xmlSchemaTypeNCNameDef);
    790 	case XML_SCHEMAS_ID:
    791 	    return (xmlSchemaTypeIdDef);
    792 	case XML_SCHEMAS_IDREF:
    793 	    return (xmlSchemaTypeIdrefDef);
    794 	case XML_SCHEMAS_IDREFS:
    795 	    return (xmlSchemaTypeIdrefsDef);
    796 	case XML_SCHEMAS_ENTITY:
    797 	    return (xmlSchemaTypeEntityDef);
    798 	case XML_SCHEMAS_ENTITIES:
    799 	    return (xmlSchemaTypeEntitiesDef);
    800 	case XML_SCHEMAS_NOTATION:
    801 	    return (xmlSchemaTypeNotationDef);
    802 	case XML_SCHEMAS_ANYURI:
    803 	    return (xmlSchemaTypeAnyURIDef);
    804 	case XML_SCHEMAS_INTEGER:
    805 	    return (xmlSchemaTypeIntegerDef);
    806 	case XML_SCHEMAS_NPINTEGER:
    807 	    return (xmlSchemaTypeNonPositiveIntegerDef);
    808 	case XML_SCHEMAS_NINTEGER:
    809 	    return (xmlSchemaTypeNegativeIntegerDef);
    810 	case XML_SCHEMAS_NNINTEGER:
    811 	    return (xmlSchemaTypeNonNegativeIntegerDef);
    812 	case XML_SCHEMAS_PINTEGER:
    813 	    return (xmlSchemaTypePositiveIntegerDef);
    814 	case XML_SCHEMAS_INT:
    815 	    return (xmlSchemaTypeIntDef);
    816 	case XML_SCHEMAS_UINT:
    817 	    return (xmlSchemaTypeUnsignedIntDef);
    818 	case XML_SCHEMAS_LONG:
    819 	    return (xmlSchemaTypeLongDef);
    820 	case XML_SCHEMAS_ULONG:
    821 	    return (xmlSchemaTypeUnsignedLongDef);
    822 	case XML_SCHEMAS_SHORT:
    823 	    return (xmlSchemaTypeShortDef);
    824 	case XML_SCHEMAS_USHORT:
    825 	    return (xmlSchemaTypeUnsignedShortDef);
    826 	case XML_SCHEMAS_BYTE:
    827 	    return (xmlSchemaTypeByteDef);
    828 	case XML_SCHEMAS_UBYTE:
    829 	    return (xmlSchemaTypeUnsignedByteDef);
    830 	case XML_SCHEMAS_HEXBINARY:
    831 	    return (xmlSchemaTypeHexBinaryDef);
    832 	case XML_SCHEMAS_BASE64BINARY:
    833 	    return (xmlSchemaTypeBase64BinaryDef);
    834 	case XML_SCHEMAS_ANYTYPE:
    835 	    return (xmlSchemaTypeAnyTypeDef);
    836 	default:
    837 	    return (NULL);
    838     }
    839 }
    840 
    841 /**
    842  * xmlSchemaValueAppend:
    843  * @prev: the value
    844  * @cur: the value to be appended
    845  *
    846  * Appends a next sibling to a list of computed values.
    847  *
    848  * Returns 0 if succeeded and -1 on API errors.
    849  */
    850 int
    851 xmlSchemaValueAppend(xmlSchemaValPtr prev, xmlSchemaValPtr cur) {
    852 
    853     if ((prev == NULL) || (cur == NULL))
    854 	return (-1);
    855     prev->next = cur;
    856     return (0);
    857 }
    858 
    859 /**
    860  * xmlSchemaValueGetNext:
    861  * @cur: the value
    862  *
    863  * Accessor for the next sibling of a list of computed values.
    864  *
    865  * Returns the next value or NULL if there was none, or on
    866  *         API errors.
    867  */
    868 xmlSchemaValPtr
    869 xmlSchemaValueGetNext(xmlSchemaValPtr cur) {
    870 
    871     if (cur == NULL)
    872 	return (NULL);
    873     return (cur->next);
    874 }
    875 
    876 /**
    877  * xmlSchemaValueGetAsString:
    878  * @val: the value
    879  *
    880  * Accessor for the string value of a computed value.
    881  *
    882  * Returns the string value or NULL if there was none, or on
    883  *         API errors.
    884  */
    885 const xmlChar *
    886 xmlSchemaValueGetAsString(xmlSchemaValPtr val)
    887 {
    888     if (val == NULL)
    889 	return (NULL);
    890     switch (val->type) {
    891 	case XML_SCHEMAS_STRING:
    892 	case XML_SCHEMAS_NORMSTRING:
    893 	case XML_SCHEMAS_ANYSIMPLETYPE:
    894 	case XML_SCHEMAS_TOKEN:
    895         case XML_SCHEMAS_LANGUAGE:
    896         case XML_SCHEMAS_NMTOKEN:
    897         case XML_SCHEMAS_NAME:
    898         case XML_SCHEMAS_NCNAME:
    899         case XML_SCHEMAS_ID:
    900         case XML_SCHEMAS_IDREF:
    901         case XML_SCHEMAS_ENTITY:
    902         case XML_SCHEMAS_ANYURI:
    903 	    return (BAD_CAST val->value.str);
    904 	default:
    905 	    break;
    906     }
    907     return (NULL);
    908 }
    909 
    910 /**
    911  * xmlSchemaValueGetAsBoolean:
    912  * @val: the value
    913  *
    914  * Accessor for the boolean value of a computed value.
    915  *
    916  * Returns 1 if true and 0 if false, or in case of an error. Hmm.
    917  */
    918 int
    919 xmlSchemaValueGetAsBoolean(xmlSchemaValPtr val)
    920 {
    921     if ((val == NULL) || (val->type != XML_SCHEMAS_BOOLEAN))
    922 	return (0);
    923     return (val->value.b);
    924 }
    925 
    926 /**
    927  * xmlSchemaNewStringValue:
    928  * @type:  the value type
    929  * @value:  the value
    930  *
    931  * Allocate a new simple type value. The type can be
    932  * of XML_SCHEMAS_STRING.
    933  * WARNING: This one is intended to be expanded for other
    934  * string based types. We need this for anySimpleType as well.
    935  * The given value is consumed and freed with the struct.
    936  *
    937  * Returns a pointer to the new value or NULL in case of error
    938  */
    939 xmlSchemaValPtr
    940 xmlSchemaNewStringValue(xmlSchemaValType type,
    941 			const xmlChar *value)
    942 {
    943     xmlSchemaValPtr val;
    944 
    945     if (type != XML_SCHEMAS_STRING)
    946 	return(NULL);
    947     val = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
    948     if (val == NULL) {
    949 	return(NULL);
    950     }
    951     memset(val, 0, sizeof(xmlSchemaVal));
    952     val->type = type;
    953     val->value.str = (xmlChar *) value;
    954     return(val);
    955 }
    956 
    957 /**
    958  * xmlSchemaNewNOTATIONValue:
    959  * @name:  the notation name
    960  * @ns: the notation namespace name or NULL
    961  *
    962  * Allocate a new NOTATION value.
    963  * The given values are consumed and freed with the struct.
    964  *
    965  * Returns a pointer to the new value or NULL in case of error
    966  */
    967 xmlSchemaValPtr
    968 xmlSchemaNewNOTATIONValue(const xmlChar *name,
    969 			  const xmlChar *ns)
    970 {
    971     xmlSchemaValPtr val;
    972 
    973     val = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
    974     if (val == NULL)
    975 	return (NULL);
    976 
    977     val->value.qname.name = (xmlChar *)name;
    978     if (ns != NULL)
    979 	val->value.qname.uri = (xmlChar *)ns;
    980     return(val);
    981 }
    982 
    983 /**
    984  * xmlSchemaNewQNameValue:
    985  * @namespaceName: the namespace name
    986  * @localName: the local name
    987  *
    988  * Allocate a new QName value.
    989  * The given values are consumed and freed with the struct.
    990  *
    991  * Returns a pointer to the new value or NULL in case of an error.
    992  */
    993 xmlSchemaValPtr
    994 xmlSchemaNewQNameValue(const xmlChar *namespaceName,
    995 		       const xmlChar *localName)
    996 {
    997     xmlSchemaValPtr val;
    998 
    999     val = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
   1000     if (val == NULL)
   1001 	return (NULL);
   1002 
   1003     val->value.qname.name = (xmlChar *) localName;
   1004     val->value.qname.uri = (xmlChar *) namespaceName;
   1005     return(val);
   1006 }
   1007 
   1008 /**
   1009  * xmlSchemaFreeValue:
   1010  * @value:  the value to free
   1011  *
   1012  * Cleanup the default XML Schemas type library
   1013  */
   1014 void
   1015 xmlSchemaFreeValue(xmlSchemaValPtr value) {
   1016     xmlSchemaValPtr prev;
   1017 
   1018     while (value != NULL) {
   1019 	switch (value->type) {
   1020 	    case XML_SCHEMAS_STRING:
   1021 	    case XML_SCHEMAS_NORMSTRING:
   1022 	    case XML_SCHEMAS_TOKEN:
   1023 	    case XML_SCHEMAS_LANGUAGE:
   1024 	    case XML_SCHEMAS_NMTOKEN:
   1025 	    case XML_SCHEMAS_NMTOKENS:
   1026 	    case XML_SCHEMAS_NAME:
   1027 	    case XML_SCHEMAS_NCNAME:
   1028 	    case XML_SCHEMAS_ID:
   1029 	    case XML_SCHEMAS_IDREF:
   1030 	    case XML_SCHEMAS_IDREFS:
   1031 	    case XML_SCHEMAS_ENTITY:
   1032 	    case XML_SCHEMAS_ENTITIES:
   1033 	    case XML_SCHEMAS_ANYURI:
   1034 	    case XML_SCHEMAS_ANYSIMPLETYPE:
   1035 		if (value->value.str != NULL)
   1036 		    xmlFree(value->value.str);
   1037 		break;
   1038 	    case XML_SCHEMAS_NOTATION:
   1039 	    case XML_SCHEMAS_QNAME:
   1040 		if (value->value.qname.uri != NULL)
   1041 		    xmlFree(value->value.qname.uri);
   1042 		if (value->value.qname.name != NULL)
   1043 		    xmlFree(value->value.qname.name);
   1044 		break;
   1045 	    case XML_SCHEMAS_HEXBINARY:
   1046 		if (value->value.hex.str != NULL)
   1047 		    xmlFree(value->value.hex.str);
   1048 		break;
   1049 	    case XML_SCHEMAS_BASE64BINARY:
   1050 		if (value->value.base64.str != NULL)
   1051 		    xmlFree(value->value.base64.str);
   1052 		break;
   1053 	    default:
   1054 		break;
   1055 	}
   1056 	prev = value;
   1057 	value = value->next;
   1058 	xmlFree(prev);
   1059     }
   1060 }
   1061 
   1062 /**
   1063  * xmlSchemaGetPredefinedType:
   1064  * @name: the type name
   1065  * @ns:  the URI of the namespace usually "http://www.w3.org/2001/XMLSchema"
   1066  *
   1067  * Lookup a type in the default XML Schemas type library
   1068  *
   1069  * Returns the type if found, NULL otherwise
   1070  */
   1071 xmlSchemaTypePtr
   1072 xmlSchemaGetPredefinedType(const xmlChar *name, const xmlChar *ns) {
   1073     if (xmlSchemaTypesInitialized == 0)
   1074 	xmlSchemaInitTypes();
   1075     if (name == NULL)
   1076 	return(NULL);
   1077     return((xmlSchemaTypePtr) xmlHashLookup2(xmlSchemaTypesBank, name, ns));
   1078 }
   1079 
   1080 /**
   1081  * xmlSchemaGetBuiltInListSimpleTypeItemType:
   1082  * @type: the built-in simple type.
   1083  *
   1084  * Lookup function
   1085  *
   1086  * Returns the item type of @type as defined by the built-in datatype
   1087  * hierarchy of XML Schema Part 2: Datatypes, or NULL in case of an error.
   1088  */
   1089 xmlSchemaTypePtr
   1090 xmlSchemaGetBuiltInListSimpleTypeItemType(xmlSchemaTypePtr type)
   1091 {
   1092     if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_BASIC))
   1093 	return (NULL);
   1094     switch (type->builtInType) {
   1095 	case XML_SCHEMAS_NMTOKENS:
   1096 	    return (xmlSchemaTypeNmtokenDef );
   1097 	case XML_SCHEMAS_IDREFS:
   1098 	    return (xmlSchemaTypeIdrefDef);
   1099 	case XML_SCHEMAS_ENTITIES:
   1100 	    return (xmlSchemaTypeEntityDef);
   1101 	default:
   1102 	    return (NULL);
   1103     }
   1104 }
   1105 
   1106 /****************************************************************
   1107  *								*
   1108  *		Convenience macros and functions		*
   1109  *								*
   1110  ****************************************************************/
   1111 
   1112 #define IS_TZO_CHAR(c)						\
   1113 	((c == 0) || (c == 'Z') || (c == '+') || (c == '-'))
   1114 
   1115 #define VALID_YEAR(yr)          (yr != 0)
   1116 #define VALID_MONTH(mon)        ((mon >= 1) && (mon <= 12))
   1117 /* VALID_DAY should only be used when month is unknown */
   1118 #define VALID_DAY(day)          ((day >= 1) && (day <= 31))
   1119 #define VALID_HOUR(hr)          ((hr >= 0) && (hr <= 23))
   1120 #define VALID_MIN(min)          ((min >= 0) && (min <= 59))
   1121 #define VALID_SEC(sec)          ((sec >= 0) && (sec < 60))
   1122 #define VALID_TZO(tzo)          ((tzo > -840) && (tzo < 840))
   1123 #define IS_LEAP(y)						\
   1124 	(((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
   1125 
   1126 static const unsigned int daysInMonth[12] =
   1127 	{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
   1128 static const unsigned int daysInMonthLeap[12] =
   1129 	{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
   1130 
   1131 #define MAX_DAYINMONTH(yr,mon)                                  \
   1132         (IS_LEAP(yr) ? daysInMonthLeap[mon - 1] : daysInMonth[mon - 1])
   1133 
   1134 #define VALID_MDAY(dt)						\
   1135 	(IS_LEAP(dt->year) ?				        \
   1136 	    (dt->day <= daysInMonthLeap[dt->mon - 1]) :	        \
   1137 	    (dt->day <= daysInMonth[dt->mon - 1]))
   1138 
   1139 #define VALID_DATE(dt)						\
   1140 	(VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt))
   1141 
   1142 #define VALID_END_OF_DAY(dt)					\
   1143 	((dt)->hour == 24 && (dt)->min == 0 && (dt)->sec == 0)
   1144 
   1145 #define VALID_TIME(dt)						\
   1146 	(((VALID_HOUR(dt->hour) && VALID_MIN(dt->min) &&	\
   1147 	  VALID_SEC(dt->sec)) || VALID_END_OF_DAY(dt)) &&	\
   1148 	 VALID_TZO(dt->tzo))
   1149 
   1150 #define VALID_DATETIME(dt)					\
   1151 	(VALID_DATE(dt) && VALID_TIME(dt))
   1152 
   1153 #define SECS_PER_MIN            (60)
   1154 #define SECS_PER_HOUR           (60 * SECS_PER_MIN)
   1155 #define SECS_PER_DAY            (24 * SECS_PER_HOUR)
   1156 
   1157 static const long dayInYearByMonth[12] =
   1158 	{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
   1159 static const long dayInLeapYearByMonth[12] =
   1160 	{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
   1161 
   1162 #define DAY_IN_YEAR(day, month, year)				\
   1163         ((IS_LEAP(year) ?					\
   1164                 dayInLeapYearByMonth[month - 1] :		\
   1165                 dayInYearByMonth[month - 1]) + day)
   1166 
   1167 #ifdef DEBUG
   1168 #define DEBUG_DATE(dt)                                                  \
   1169     xmlGenericError(xmlGenericErrorContext,                             \
   1170         "type=%o %04ld-%02u-%02uT%02u:%02u:%03f",                       \
   1171         dt->type,dt->value.date.year,dt->value.date.mon,                \
   1172         dt->value.date.day,dt->value.date.hour,dt->value.date.min,      \
   1173         dt->value.date.sec);                                            \
   1174     if (dt->value.date.tz_flag)                                         \
   1175         if (dt->value.date.tzo != 0)                                    \
   1176             xmlGenericError(xmlGenericErrorContext,                     \
   1177                 "%+05d\n",dt->value.date.tzo);                          \
   1178         else                                                            \
   1179             xmlGenericError(xmlGenericErrorContext, "Z\n");             \
   1180     else                                                                \
   1181         xmlGenericError(xmlGenericErrorContext,"\n")
   1182 #else
   1183 #define DEBUG_DATE(dt)
   1184 #endif
   1185 
   1186 /**
   1187  * _xmlSchemaParseGYear:
   1188  * @dt:  pointer to a date structure
   1189  * @str: pointer to the string to analyze
   1190  *
   1191  * Parses a xs:gYear without time zone and fills in the appropriate
   1192  * field of the @dt structure. @str is updated to point just after the
   1193  * xs:gYear. It is supposed that @dt->year is big enough to contain
   1194  * the year.
   1195  *
   1196  * Returns 0 or the error code
   1197  */
   1198 static int
   1199 _xmlSchemaParseGYear (xmlSchemaValDatePtr dt, const xmlChar **str) {
   1200     const xmlChar *cur = *str, *firstChar;
   1201     int isneg = 0, digcnt = 0;
   1202 
   1203     if (((*cur < '0') || (*cur > '9')) &&
   1204 	(*cur != '-') && (*cur != '+'))
   1205 	return -1;
   1206 
   1207     if (*cur == '-') {
   1208 	isneg = 1;
   1209 	cur++;
   1210     }
   1211 
   1212     firstChar = cur;
   1213 
   1214     while ((*cur >= '0') && (*cur <= '9')) {
   1215 	dt->year = dt->year * 10 + (*cur - '0');
   1216 	cur++;
   1217 	digcnt++;
   1218     }
   1219 
   1220     /* year must be at least 4 digits (CCYY); over 4
   1221      * digits cannot have a leading zero. */
   1222     if ((digcnt < 4) || ((digcnt > 4) && (*firstChar == '0')))
   1223 	return 1;
   1224 
   1225     if (isneg)
   1226 	dt->year = - dt->year;
   1227 
   1228     if (!VALID_YEAR(dt->year))
   1229 	return 2;
   1230 
   1231     *str = cur;
   1232     return 0;
   1233 }
   1234 
   1235 /**
   1236  * PARSE_2_DIGITS:
   1237  * @num:  the integer to fill in
   1238  * @cur:  an #xmlChar *
   1239  * @invalid: an integer
   1240  *
   1241  * Parses a 2-digits integer and updates @num with the value. @cur is
   1242  * updated to point just after the integer.
   1243  * In case of error, @invalid is set to %TRUE, values of @num and
   1244  * @cur are undefined.
   1245  */
   1246 #define PARSE_2_DIGITS(num, cur, invalid)			\
   1247 	if ((cur[0] < '0') || (cur[0] > '9') ||			\
   1248 	    (cur[1] < '0') || (cur[1] > '9'))			\
   1249 	    invalid = 1;					\
   1250 	else							\
   1251 	    num = (cur[0] - '0') * 10 + (cur[1] - '0');		\
   1252 	cur += 2;
   1253 
   1254 /**
   1255  * PARSE_FLOAT:
   1256  * @num:  the double to fill in
   1257  * @cur:  an #xmlChar *
   1258  * @invalid: an integer
   1259  *
   1260  * Parses a float and updates @num with the value. @cur is
   1261  * updated to point just after the float. The float must have a
   1262  * 2-digits integer part and may or may not have a decimal part.
   1263  * In case of error, @invalid is set to %TRUE, values of @num and
   1264  * @cur are undefined.
   1265  */
   1266 #define PARSE_FLOAT(num, cur, invalid)				\
   1267 	PARSE_2_DIGITS(num, cur, invalid);			\
   1268 	if (!invalid && (*cur == '.')) {			\
   1269 	    double mult = 1;				        \
   1270 	    cur++;						\
   1271 	    if ((*cur < '0') || (*cur > '9'))			\
   1272 		invalid = 1;					\
   1273 	    while ((*cur >= '0') && (*cur <= '9')) {		\
   1274 		mult /= 10;					\
   1275 		num += (*cur - '0') * mult;			\
   1276 		cur++;						\
   1277 	    }							\
   1278 	}
   1279 
   1280 /**
   1281  * _xmlSchemaParseGMonth:
   1282  * @dt:  pointer to a date structure
   1283  * @str: pointer to the string to analyze
   1284  *
   1285  * Parses a xs:gMonth without time zone and fills in the appropriate
   1286  * field of the @dt structure. @str is updated to point just after the
   1287  * xs:gMonth.
   1288  *
   1289  * Returns 0 or the error code
   1290  */
   1291 static int
   1292 _xmlSchemaParseGMonth (xmlSchemaValDatePtr dt, const xmlChar **str) {
   1293     const xmlChar *cur = *str;
   1294     int ret = 0;
   1295     unsigned int value = 0;
   1296 
   1297     PARSE_2_DIGITS(value, cur, ret);
   1298     if (ret != 0)
   1299 	return ret;
   1300 
   1301     if (!VALID_MONTH(value))
   1302 	return 2;
   1303 
   1304     dt->mon = value;
   1305 
   1306     *str = cur;
   1307     return 0;
   1308 }
   1309 
   1310 /**
   1311  * _xmlSchemaParseGDay:
   1312  * @dt:  pointer to a date structure
   1313  * @str: pointer to the string to analyze
   1314  *
   1315  * Parses a xs:gDay without time zone and fills in the appropriate
   1316  * field of the @dt structure. @str is updated to point just after the
   1317  * xs:gDay.
   1318  *
   1319  * Returns 0 or the error code
   1320  */
   1321 static int
   1322 _xmlSchemaParseGDay (xmlSchemaValDatePtr dt, const xmlChar **str) {
   1323     const xmlChar *cur = *str;
   1324     int ret = 0;
   1325     unsigned int value = 0;
   1326 
   1327     PARSE_2_DIGITS(value, cur, ret);
   1328     if (ret != 0)
   1329 	return ret;
   1330 
   1331     if (!VALID_DAY(value))
   1332 	return 2;
   1333 
   1334     dt->day = value;
   1335     *str = cur;
   1336     return 0;
   1337 }
   1338 
   1339 /**
   1340  * _xmlSchemaParseTime:
   1341  * @dt:  pointer to a date structure
   1342  * @str: pointer to the string to analyze
   1343  *
   1344  * Parses a xs:time without time zone and fills in the appropriate
   1345  * fields of the @dt structure. @str is updated to point just after the
   1346  * xs:time.
   1347  * In case of error, values of @dt fields are undefined.
   1348  *
   1349  * Returns 0 or the error code
   1350  */
   1351 static int
   1352 _xmlSchemaParseTime (xmlSchemaValDatePtr dt, const xmlChar **str) {
   1353     const xmlChar *cur = *str;
   1354     int ret = 0;
   1355     int value = 0;
   1356 
   1357     PARSE_2_DIGITS(value, cur, ret);
   1358     if (ret != 0)
   1359 	return ret;
   1360     if (*cur != ':')
   1361 	return 1;
   1362     if (!VALID_HOUR(value) && value != 24 /* Allow end-of-day hour */)
   1363 	return 2;
   1364     cur++;
   1365 
   1366     /* the ':' insures this string is xs:time */
   1367     dt->hour = value;
   1368 
   1369     PARSE_2_DIGITS(value, cur, ret);
   1370     if (ret != 0)
   1371 	return ret;
   1372     if (!VALID_MIN(value))
   1373 	return 2;
   1374     dt->min = value;
   1375 
   1376     if (*cur != ':')
   1377 	return 1;
   1378     cur++;
   1379 
   1380     PARSE_FLOAT(dt->sec, cur, ret);
   1381     if (ret != 0)
   1382 	return ret;
   1383 
   1384     if (!VALID_TIME(dt))
   1385 	return 2;
   1386 
   1387     *str = cur;
   1388     return 0;
   1389 }
   1390 
   1391 /**
   1392  * _xmlSchemaParseTimeZone:
   1393  * @dt:  pointer to a date structure
   1394  * @str: pointer to the string to analyze
   1395  *
   1396  * Parses a time zone without time zone and fills in the appropriate
   1397  * field of the @dt structure. @str is updated to point just after the
   1398  * time zone.
   1399  *
   1400  * Returns 0 or the error code
   1401  */
   1402 static int
   1403 _xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt, const xmlChar **str) {
   1404     const xmlChar *cur;
   1405     int ret = 0;
   1406 
   1407     if (str == NULL)
   1408 	return -1;
   1409     cur = *str;
   1410 
   1411     switch (*cur) {
   1412     case 0:
   1413 	dt->tz_flag = 0;
   1414 	dt->tzo = 0;
   1415 	break;
   1416 
   1417     case 'Z':
   1418 	dt->tz_flag = 1;
   1419 	dt->tzo = 0;
   1420 	cur++;
   1421 	break;
   1422 
   1423     case '+':
   1424     case '-': {
   1425 	int isneg = 0, tmp = 0;
   1426 	isneg = (*cur == '-');
   1427 
   1428 	cur++;
   1429 
   1430 	PARSE_2_DIGITS(tmp, cur, ret);
   1431 	if (ret != 0)
   1432 	    return ret;
   1433 	if (!VALID_HOUR(tmp))
   1434 	    return 2;
   1435 
   1436 	if (*cur != ':')
   1437 	    return 1;
   1438 	cur++;
   1439 
   1440 	dt->tzo = tmp * 60;
   1441 
   1442 	PARSE_2_DIGITS(tmp, cur, ret);
   1443 	if (ret != 0)
   1444 	    return ret;
   1445 	if (!VALID_MIN(tmp))
   1446 	    return 2;
   1447 
   1448 	dt->tzo += tmp;
   1449 	if (isneg)
   1450 	    dt->tzo = - dt->tzo;
   1451 
   1452 	if (!VALID_TZO(dt->tzo))
   1453 	    return 2;
   1454 
   1455 	dt->tz_flag = 1;
   1456 	break;
   1457       }
   1458     default:
   1459 	return 1;
   1460     }
   1461 
   1462     *str = cur;
   1463     return 0;
   1464 }
   1465 
   1466 /**
   1467  * _xmlSchemaBase64Decode:
   1468  * @ch: a character
   1469  *
   1470  * Converts a base64 encoded character to its base 64 value.
   1471  *
   1472  * Returns 0-63 (value), 64 (pad), or -1 (not recognized)
   1473  */
   1474 static int
   1475 _xmlSchemaBase64Decode (const xmlChar ch) {
   1476     if (('A' <= ch) && (ch <= 'Z')) return ch - 'A';
   1477     if (('a' <= ch) && (ch <= 'z')) return ch - 'a' + 26;
   1478     if (('0' <= ch) && (ch <= '9')) return ch - '0' + 52;
   1479     if ('+' == ch) return 62;
   1480     if ('/' == ch) return 63;
   1481     if ('=' == ch) return 64;
   1482     return -1;
   1483 }
   1484 
   1485 /****************************************************************
   1486  *								*
   1487  *	XML Schema Dates/Times Datatypes Handling		*
   1488  *								*
   1489  ****************************************************************/
   1490 
   1491 /**
   1492  * PARSE_DIGITS:
   1493  * @num:  the integer to fill in
   1494  * @cur:  an #xmlChar *
   1495  * @num_type: an integer flag
   1496  *
   1497  * Parses a digits integer and updates @num with the value. @cur is
   1498  * updated to point just after the integer.
   1499  * In case of error, @num_type is set to -1, values of @num and
   1500  * @cur are undefined.
   1501  */
   1502 #define PARSE_DIGITS(num, cur, num_type)	                \
   1503 	if ((*cur < '0') || (*cur > '9'))			\
   1504 	    num_type = -1;					\
   1505         else                                                    \
   1506 	    while ((*cur >= '0') && (*cur <= '9')) {		\
   1507 	        num = num * 10 + (*cur - '0');		        \
   1508 	        cur++;                                          \
   1509             }
   1510 
   1511 /**
   1512  * PARSE_NUM:
   1513  * @num:  the double to fill in
   1514  * @cur:  an #xmlChar *
   1515  * @num_type: an integer flag
   1516  *
   1517  * Parses a float or integer and updates @num with the value. @cur is
   1518  * updated to point just after the number. If the number is a float,
   1519  * then it must have an integer part and a decimal part; @num_type will
   1520  * be set to 1. If there is no decimal part, @num_type is set to zero.
   1521  * In case of error, @num_type is set to -1, values of @num and
   1522  * @cur are undefined.
   1523  */
   1524 #define PARSE_NUM(num, cur, num_type)				\
   1525         num = 0;                                                \
   1526 	PARSE_DIGITS(num, cur, num_type);	                \
   1527 	if (!num_type && (*cur == '.')) {			\
   1528 	    double mult = 1;				        \
   1529 	    cur++;						\
   1530 	    if ((*cur < '0') || (*cur > '9'))			\
   1531 		num_type = -1;					\
   1532             else                                                \
   1533                 num_type = 1;                                   \
   1534 	    while ((*cur >= '0') && (*cur <= '9')) {		\
   1535 		mult /= 10;					\
   1536 		num += (*cur - '0') * mult;			\
   1537 		cur++;						\
   1538 	    }							\
   1539 	}
   1540 
   1541 /**
   1542  * xmlSchemaValidateDates:
   1543  * @type: the expected type or XML_SCHEMAS_UNKNOWN
   1544  * @dateTime:  string to analyze
   1545  * @val:  the return computed value
   1546  *
   1547  * Check that @dateTime conforms to the lexical space of one of the date types.
   1548  * if true a value is computed and returned in @val.
   1549  *
   1550  * Returns 0 if this validates, a positive error code number otherwise
   1551  *         and -1 in case of internal or API error.
   1552  */
   1553 static int
   1554 xmlSchemaValidateDates (xmlSchemaValType type,
   1555 	                const xmlChar *dateTime, xmlSchemaValPtr *val,
   1556 			int collapse) {
   1557     xmlSchemaValPtr dt;
   1558     int ret;
   1559     const xmlChar *cur = dateTime;
   1560 
   1561 #define RETURN_TYPE_IF_VALID(t)					\
   1562     if (IS_TZO_CHAR(*cur)) {					\
   1563 	ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur);	\
   1564 	if (ret == 0) {						\
   1565 	    if (*cur != 0)					\
   1566 		goto error;					\
   1567 	    dt->type = t;					\
   1568 	    goto done;						\
   1569 	}							\
   1570     }
   1571 
   1572     if (dateTime == NULL)
   1573 	return -1;
   1574 
   1575     if (collapse)
   1576 	while IS_WSP_BLANK_CH(*cur) cur++;
   1577 
   1578     if ((*cur != '-') && (*cur < '0') && (*cur > '9'))
   1579 	return 1;
   1580 
   1581     dt = xmlSchemaNewValue(XML_SCHEMAS_UNKNOWN);
   1582     if (dt == NULL)
   1583 	return -1;
   1584 
   1585     if ((cur[0] == '-') && (cur[1] == '-')) {
   1586 	/*
   1587 	 * It's an incomplete date (xs:gMonthDay, xs:gMonth or
   1588 	 * xs:gDay)
   1589 	 */
   1590 	cur += 2;
   1591 
   1592 	/* is it an xs:gDay? */
   1593 	if (*cur == '-') {
   1594 	    if (type == XML_SCHEMAS_GMONTH)
   1595 		goto error;
   1596 	  ++cur;
   1597 	    ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
   1598 	    if (ret != 0)
   1599 		goto error;
   1600 
   1601 	    RETURN_TYPE_IF_VALID(XML_SCHEMAS_GDAY);
   1602 
   1603 	    goto error;
   1604 	}
   1605 
   1606 	/*
   1607 	 * it should be an xs:gMonthDay or xs:gMonth
   1608 	 */
   1609 	ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
   1610 	if (ret != 0)
   1611 	    goto error;
   1612 
   1613         /*
   1614          * a '-' char could indicate this type is xs:gMonthDay or
   1615          * a negative time zone offset. Check for xs:gMonthDay first.
   1616          * Also the first three char's of a negative tzo (-MM:SS) can
   1617          * appear to be a valid day; so even if the day portion
   1618          * of the xs:gMonthDay verifies, we must insure it was not
   1619          * a tzo.
   1620          */
   1621         if (*cur == '-') {
   1622             const xmlChar *rewnd = cur;
   1623             cur++;
   1624 
   1625 	    ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
   1626             if ((ret == 0) && ((*cur == 0) || (*cur != ':'))) {
   1627 
   1628                 /*
   1629                  * we can use the VALID_MDAY macro to validate the month
   1630                  * and day because the leap year test will flag year zero
   1631                  * as a leap year (even though zero is an invalid year).
   1632 		 * FUTURE TODO: Zero will become valid in XML Schema 1.1
   1633 		 * probably.
   1634                  */
   1635                 if (VALID_MDAY((&(dt->value.date)))) {
   1636 
   1637 	            RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY);
   1638 
   1639                     goto error;
   1640                 }
   1641             }
   1642 
   1643             /*
   1644              * not xs:gMonthDay so rewind and check if just xs:gMonth
   1645              * with an optional time zone.
   1646              */
   1647             cur = rewnd;
   1648         }
   1649 
   1650 	RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH);
   1651 
   1652 	goto error;
   1653     }
   1654 
   1655     /*
   1656      * It's a right-truncated date or an xs:time.
   1657      * Try to parse an xs:time then fallback on right-truncated dates.
   1658      */
   1659     if ((*cur >= '0') && (*cur <= '9')) {
   1660 	ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
   1661 	if (ret == 0) {
   1662 	    /* it's an xs:time */
   1663 	    RETURN_TYPE_IF_VALID(XML_SCHEMAS_TIME);
   1664 	}
   1665     }
   1666 
   1667     /* fallback on date parsing */
   1668     cur = dateTime;
   1669 
   1670     ret = _xmlSchemaParseGYear(&(dt->value.date), &cur);
   1671     if (ret != 0)
   1672 	goto error;
   1673 
   1674     /* is it an xs:gYear? */
   1675     RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEAR);
   1676 
   1677     if (*cur != '-')
   1678 	goto error;
   1679     cur++;
   1680 
   1681     ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
   1682     if (ret != 0)
   1683 	goto error;
   1684 
   1685     /* is it an xs:gYearMonth? */
   1686     RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEARMONTH);
   1687 
   1688     if (*cur != '-')
   1689 	goto error;
   1690     cur++;
   1691 
   1692     ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
   1693     if ((ret != 0) || !VALID_DATE((&(dt->value.date))))
   1694 	goto error;
   1695 
   1696     /* is it an xs:date? */
   1697     RETURN_TYPE_IF_VALID(XML_SCHEMAS_DATE);
   1698 
   1699     if (*cur != 'T')
   1700 	goto error;
   1701     cur++;
   1702 
   1703     /* it should be an xs:dateTime */
   1704     ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
   1705     if (ret != 0)
   1706 	goto error;
   1707 
   1708     ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur);
   1709     if (collapse)
   1710 	while IS_WSP_BLANK_CH(*cur) cur++;
   1711     if ((ret != 0) || (*cur != 0) || (!(VALID_DATETIME((&(dt->value.date))))))
   1712 	goto error;
   1713 
   1714 
   1715     dt->type = XML_SCHEMAS_DATETIME;
   1716 
   1717 done:
   1718 #if 1
   1719     if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type))
   1720         goto error;
   1721 #else
   1722     /*
   1723      * insure the parsed type is equal to or less significant (right
   1724      * truncated) than the desired type.
   1725      */
   1726     if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) {
   1727 
   1728         /* time only matches time */
   1729         if ((type == XML_SCHEMAS_TIME) && (dt->type == XML_SCHEMAS_TIME))
   1730             goto error;
   1731 
   1732         if ((type == XML_SCHEMAS_DATETIME) &&
   1733             ((dt->type != XML_SCHEMAS_DATE) ||
   1734              (dt->type != XML_SCHEMAS_GYEARMONTH) ||
   1735              (dt->type != XML_SCHEMAS_GYEAR)))
   1736             goto error;
   1737 
   1738         if ((type == XML_SCHEMAS_DATE) &&
   1739             ((dt->type != XML_SCHEMAS_GYEAR) ||
   1740              (dt->type != XML_SCHEMAS_GYEARMONTH)))
   1741             goto error;
   1742 
   1743         if ((type == XML_SCHEMAS_GYEARMONTH) && (dt->type != XML_SCHEMAS_GYEAR))
   1744             goto error;
   1745 
   1746         if ((type == XML_SCHEMAS_GMONTHDAY) && (dt->type != XML_SCHEMAS_GMONTH))
   1747             goto error;
   1748     }
   1749 #endif
   1750 
   1751     if (val != NULL)
   1752         *val = dt;
   1753     else
   1754 	xmlSchemaFreeValue(dt);
   1755 
   1756     return 0;
   1757 
   1758 error:
   1759     if (dt != NULL)
   1760 	xmlSchemaFreeValue(dt);
   1761     return 1;
   1762 }
   1763 
   1764 /**
   1765  * xmlSchemaValidateDuration:
   1766  * @type: the predefined type
   1767  * @duration:  string to analyze
   1768  * @val:  the return computed value
   1769  *
   1770  * Check that @duration conforms to the lexical space of the duration type.
   1771  * if true a value is computed and returned in @val.
   1772  *
   1773  * Returns 0 if this validates, a positive error code number otherwise
   1774  *         and -1 in case of internal or API error.
   1775  */
   1776 static int
   1777 xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
   1778 	                   const xmlChar *duration, xmlSchemaValPtr *val,
   1779 			   int collapse) {
   1780     const xmlChar  *cur = duration;
   1781     xmlSchemaValPtr dur;
   1782     int isneg = 0;
   1783     unsigned int seq = 0;
   1784     double         num;
   1785     int            num_type = 0;  /* -1 = invalid, 0 = int, 1 = floating */
   1786     const xmlChar  desig[]  = {'Y', 'M', 'D', 'H', 'M', 'S'};
   1787     const double   multi[]  = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0};
   1788 
   1789     if (duration == NULL)
   1790 	return -1;
   1791 
   1792     if (collapse)
   1793 	while IS_WSP_BLANK_CH(*cur) cur++;
   1794 
   1795     if (*cur == '-') {
   1796         isneg = 1;
   1797         cur++;
   1798     }
   1799 
   1800     /* duration must start with 'P' (after sign) */
   1801     if (*cur++ != 'P')
   1802 	return 1;
   1803 
   1804     if (*cur == 0)
   1805 	return 1;
   1806 
   1807     dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
   1808     if (dur == NULL)
   1809 	return -1;
   1810 
   1811     while (*cur != 0) {
   1812 
   1813         /* input string should be empty or invalid date/time item */
   1814         if (seq >= sizeof(desig))
   1815             goto error;
   1816 
   1817         /* T designator must be present for time items */
   1818         if (*cur == 'T') {
   1819             if (seq <= 3) {
   1820                 seq = 3;
   1821                 cur++;
   1822             } else
   1823                 return 1;
   1824         } else if (seq == 3)
   1825             goto error;
   1826 
   1827         /* parse the number portion of the item */
   1828         PARSE_NUM(num, cur, num_type);
   1829 
   1830         if ((num_type == -1) || (*cur == 0))
   1831             goto error;
   1832 
   1833         /* update duration based on item type */
   1834         while (seq < sizeof(desig)) {
   1835             if (*cur == desig[seq]) {
   1836 
   1837                 /* verify numeric type; only seconds can be float */
   1838                 if ((num_type != 0) && (seq < (sizeof(desig)-1)))
   1839                     goto error;
   1840 
   1841                 switch (seq) {
   1842                     case 0:
   1843                         dur->value.dur.mon = (long)num * 12;
   1844                         break;
   1845                     case 1:
   1846                         dur->value.dur.mon += (long)num;
   1847                         break;
   1848                     default:
   1849                         /* convert to seconds using multiplier */
   1850                         dur->value.dur.sec += num * multi[seq];
   1851                         seq++;
   1852                         break;
   1853                 }
   1854 
   1855                 break;          /* exit loop */
   1856             }
   1857             /* no date designators found? */
   1858             if ((++seq == 3) || (seq == 6))
   1859                 goto error;
   1860         }
   1861 	cur++;
   1862 	if (collapse)
   1863 	    while IS_WSP_BLANK_CH(*cur) cur++;
   1864     }
   1865 
   1866     if (isneg) {
   1867         dur->value.dur.mon = -dur->value.dur.mon;
   1868         dur->value.dur.day = -dur->value.dur.day;
   1869         dur->value.dur.sec = -dur->value.dur.sec;
   1870     }
   1871 
   1872     if (val != NULL)
   1873         *val = dur;
   1874     else
   1875 	xmlSchemaFreeValue(dur);
   1876 
   1877     return 0;
   1878 
   1879 error:
   1880     if (dur != NULL)
   1881 	xmlSchemaFreeValue(dur);
   1882     return 1;
   1883 }
   1884 
   1885 /**
   1886  * xmlSchemaStrip:
   1887  * @value: a value
   1888  *
   1889  * Removes the leading and ending spaces of a string
   1890  *
   1891  * Returns the new string or NULL if no change was required.
   1892  */
   1893 static xmlChar *
   1894 xmlSchemaStrip(const xmlChar *value) {
   1895     const xmlChar *start = value, *end, *f;
   1896 
   1897     if (value == NULL) return(NULL);
   1898     while ((*start != 0) && (IS_BLANK_CH(*start))) start++;
   1899     end = start;
   1900     while (*end != 0) end++;
   1901     f = end;
   1902     end--;
   1903     while ((end > start) && (IS_BLANK_CH(*end))) end--;
   1904     end++;
   1905     if ((start == value) && (f == end)) return(NULL);
   1906     return(xmlStrndup(start, end - start));
   1907 }
   1908 
   1909 /**
   1910  * xmlSchemaWhiteSpaceReplace:
   1911  * @value: a value
   1912  *
   1913  * Replaces 0xd, 0x9 and 0xa with a space.
   1914  *
   1915  * Returns the new string or NULL if no change was required.
   1916  */
   1917 xmlChar *
   1918 xmlSchemaWhiteSpaceReplace(const xmlChar *value) {
   1919     const xmlChar *cur = value;
   1920     xmlChar *ret = NULL, *mcur;
   1921 
   1922     if (value == NULL)
   1923 	return(NULL);
   1924 
   1925     while ((*cur != 0) &&
   1926 	(((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) {
   1927 	cur++;
   1928     }
   1929     if (*cur == 0)
   1930 	return (NULL);
   1931     ret = xmlStrdup(value);
   1932     /* TODO FIXME: I guess gcc will bark at this. */
   1933     mcur = (xmlChar *)  (ret + (cur - value));
   1934     do {
   1935 	if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) )
   1936 	    *mcur = ' ';
   1937 	mcur++;
   1938     } while (*mcur != 0);
   1939     return(ret);
   1940 }
   1941 
   1942 /**
   1943  * xmlSchemaCollapseString:
   1944  * @value: a value
   1945  *
   1946  * Removes and normalize white spaces in the string
   1947  *
   1948  * Returns the new string or NULL if no change was required.
   1949  */
   1950 xmlChar *
   1951 xmlSchemaCollapseString(const xmlChar *value) {
   1952     const xmlChar *start = value, *end, *f;
   1953     xmlChar *g;
   1954     int col = 0;
   1955 
   1956     if (value == NULL) return(NULL);
   1957     while ((*start != 0) && (IS_BLANK_CH(*start))) start++;
   1958     end = start;
   1959     while (*end != 0) {
   1960 	if ((*end == ' ') && (IS_BLANK_CH(end[1]))) {
   1961 	    col = end - start;
   1962 	    break;
   1963 	} else if ((*end == 0xa) || (*end == 0x9) || (*end == 0xd)) {
   1964 	    col = end - start;
   1965 	    break;
   1966 	}
   1967 	end++;
   1968     }
   1969     if (col == 0) {
   1970 	f = end;
   1971 	end--;
   1972 	while ((end > start) && (IS_BLANK_CH(*end))) end--;
   1973 	end++;
   1974 	if ((start == value) && (f == end)) return(NULL);
   1975 	return(xmlStrndup(start, end - start));
   1976     }
   1977     start = xmlStrdup(start);
   1978     if (start == NULL) return(NULL);
   1979     g = (xmlChar *) (start + col);
   1980     end = g;
   1981     while (*end != 0) {
   1982 	if (IS_BLANK_CH(*end)) {
   1983 	    end++;
   1984 	    while (IS_BLANK_CH(*end)) end++;
   1985 	    if (*end != 0)
   1986 		*g++ = ' ';
   1987 	} else
   1988 	    *g++ = *end++;
   1989     }
   1990     *g = 0;
   1991     return((xmlChar *) start);
   1992 }
   1993 
   1994 /**
   1995  * xmlSchemaValAtomicListNode:
   1996  * @type: the predefined atomic type for a token in the list
   1997  * @value: the list value to check
   1998  * @ret:  the return computed value
   1999  * @node:  the node containing the value
   2000  *
   2001  * Check that a value conforms to the lexical space of the predefined
   2002  * list type. if true a value is computed and returned in @ret.
   2003  *
   2004  * Returns the number of items if this validates, a negative error code
   2005  *         number otherwise
   2006  */
   2007 static int
   2008 xmlSchemaValAtomicListNode(xmlSchemaTypePtr type, const xmlChar *value,
   2009 	                   xmlSchemaValPtr *ret, xmlNodePtr node) {
   2010     xmlChar *val, *cur, *endval;
   2011     int nb_values = 0;
   2012     int tmp = 0;
   2013 
   2014     if (value == NULL) {
   2015 	return(-1);
   2016     }
   2017     val = xmlStrdup(value);
   2018     if (val == NULL) {
   2019 	return(-1);
   2020     }
   2021     if (ret != NULL) {
   2022         *ret = NULL;
   2023     }
   2024     cur = val;
   2025     /*
   2026      * Split the list
   2027      */
   2028     while (IS_BLANK_CH(*cur)) *cur++ = 0;
   2029     while (*cur != 0) {
   2030 	if (IS_BLANK_CH(*cur)) {
   2031 	    *cur = 0;
   2032 	    cur++;
   2033 	    while (IS_BLANK_CH(*cur)) *cur++ = 0;
   2034 	} else {
   2035 	    nb_values++;
   2036 	    cur++;
   2037 	    while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
   2038 	}
   2039     }
   2040     if (nb_values == 0) {
   2041 	xmlFree(val);
   2042 	return(nb_values);
   2043     }
   2044     endval = cur;
   2045     cur = val;
   2046     while ((*cur == 0) && (cur != endval)) cur++;
   2047     while (cur != endval) {
   2048 	tmp = xmlSchemaValPredefTypeNode(type, cur, NULL, node);
   2049 	if (tmp != 0)
   2050 	    break;
   2051 	while (*cur != 0) cur++;
   2052 	while ((*cur == 0) && (cur != endval)) cur++;
   2053     }
   2054     /* TODO what return value ? c.f. bug #158628
   2055     if (ret != NULL) {
   2056 	TODO
   2057     } */
   2058     xmlFree(val);
   2059     if (tmp == 0)
   2060 	return(nb_values);
   2061     return(-1);
   2062 }
   2063 
   2064 /**
   2065  * xmlSchemaParseUInt:
   2066  * @str: pointer to the string R/W
   2067  * @llo: pointer to the low result
   2068  * @lmi: pointer to the mid result
   2069  * @lhi: pointer to the high result
   2070  *
   2071  * Parse an unsigned long into 3 fields.
   2072  *
   2073  * Returns the number of significant digits in the number or
   2074  * -1 if overflow of the capacity and -2 if it's not a number.
   2075  */
   2076 static int
   2077 xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo,
   2078                    unsigned long *lmi, unsigned long *lhi) {
   2079     unsigned long lo = 0, mi = 0, hi = 0;
   2080     const xmlChar *tmp, *cur = *str;
   2081     int ret = 0, i = 0;
   2082 
   2083     if (!((*cur >= '0') && (*cur <= '9')))
   2084         return(-2);
   2085 
   2086     while (*cur == '0') {        /* ignore leading zeroes */
   2087         cur++;
   2088     }
   2089     tmp = cur;
   2090     while ((*tmp != 0) && (*tmp >= '0') && (*tmp <= '9')) {
   2091         i++;tmp++;ret++;
   2092     }
   2093     if (i > 24) {
   2094         *str = tmp;
   2095         return(-1);
   2096     }
   2097     while (i > 16) {
   2098         hi = hi * 10 + (*cur++ - '0');
   2099         i--;
   2100     }
   2101     while (i > 8) {
   2102         mi = mi * 10 + (*cur++ - '0');
   2103         i--;
   2104     }
   2105     while (i > 0) {
   2106         lo = lo * 10 + (*cur++ - '0');
   2107         i--;
   2108     }
   2109 
   2110     *str = cur;
   2111     *llo = lo;
   2112     *lmi = mi;
   2113     *lhi = hi;
   2114     return(ret);
   2115 }
   2116 
   2117 /**
   2118  * xmlSchemaValAtomicType:
   2119  * @type: the predefined type
   2120  * @value: the value to check
   2121  * @val:  the return computed value
   2122  * @node:  the node containing the value
   2123  * flags:  flags to control the vlidation
   2124  *
   2125  * Check that a value conforms to the lexical space of the atomic type.
   2126  * if true a value is computed and returned in @val.
   2127  * This checks the value space for list types as well (IDREFS, NMTOKENS).
   2128  *
   2129  * Returns 0 if this validates, a positive error code number otherwise
   2130  *         and -1 in case of internal or API error.
   2131  */
   2132 static int
   2133 xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
   2134                        xmlSchemaValPtr * val, xmlNodePtr node, int flags,
   2135 		       xmlSchemaWhitespaceValueType ws,
   2136 		       int normOnTheFly, int applyNorm, int createStringValue)
   2137 {
   2138     xmlSchemaValPtr v;
   2139     xmlChar *norm = NULL;
   2140     int ret = 0;
   2141 
   2142     if (xmlSchemaTypesInitialized == 0)
   2143         xmlSchemaInitTypes();
   2144     if (type == NULL)
   2145         return (-1);
   2146 
   2147     /*
   2148      * validating a non existant text node is similar to validating
   2149      * an empty one.
   2150      */
   2151     if (value == NULL)
   2152         value = BAD_CAST "";
   2153 
   2154     if (val != NULL)
   2155         *val = NULL;
   2156     if ((flags == 0) && (value != NULL)) {
   2157 
   2158         if ((type->builtInType != XML_SCHEMAS_STRING) &&
   2159 	  (type->builtInType != XML_SCHEMAS_ANYTYPE) &&
   2160 	  (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE)) {
   2161 	    if (type->builtInType == XML_SCHEMAS_NORMSTRING)
   2162 		norm = xmlSchemaWhiteSpaceReplace(value);
   2163             else
   2164 		norm = xmlSchemaCollapseString(value);
   2165             if (norm != NULL)
   2166                 value = norm;
   2167         }
   2168     }
   2169 
   2170     switch (type->builtInType) {
   2171         case XML_SCHEMAS_UNKNOWN:
   2172             goto error;
   2173 	case XML_SCHEMAS_ANYTYPE:
   2174 	case XML_SCHEMAS_ANYSIMPLETYPE:
   2175 	    if ((createStringValue) && (val != NULL)) {
   2176 		v = xmlSchemaNewValue(XML_SCHEMAS_ANYSIMPLETYPE);
   2177 		if (v != NULL) {
   2178 		    v->value.str = xmlStrdup(value);
   2179 		    *val = v;
   2180 		} else {
   2181 		    goto error;
   2182 		}
   2183 	    }
   2184 	    goto return0;
   2185         case XML_SCHEMAS_STRING:
   2186 	    if (! normOnTheFly) {
   2187 		const xmlChar *cur = value;
   2188 
   2189 		if (ws == XML_SCHEMA_WHITESPACE_REPLACE) {
   2190 		    while (*cur != 0) {
   2191 			if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
   2192 			    goto return1;
   2193 			} else {
   2194 			    cur++;
   2195 			}
   2196 		    }
   2197 		} else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) {
   2198 		    while (*cur != 0) {
   2199 			if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
   2200 			    goto return1;
   2201 			} else if IS_WSP_SPACE_CH(*cur) {
   2202 			    cur++;
   2203 			    if IS_WSP_SPACE_CH(*cur)
   2204 				goto return1;
   2205 			} else {
   2206 			    cur++;
   2207 			}
   2208 		    }
   2209 		}
   2210 	    }
   2211 	    if (createStringValue && (val != NULL)) {
   2212 		if (applyNorm) {
   2213 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
   2214 			norm = xmlSchemaCollapseString(value);
   2215 		    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
   2216 			norm = xmlSchemaWhiteSpaceReplace(value);
   2217 		    if (norm != NULL)
   2218 			value = norm;
   2219 		}
   2220 		v = xmlSchemaNewValue(XML_SCHEMAS_STRING);
   2221 		if (v != NULL) {
   2222 		    v->value.str = xmlStrdup(value);
   2223 		    *val = v;
   2224 		} else {
   2225 		    goto error;
   2226 		}
   2227 	    }
   2228             goto return0;
   2229         case XML_SCHEMAS_NORMSTRING:{
   2230 		if (normOnTheFly) {
   2231 		    if (applyNorm) {
   2232 			if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
   2233 			    norm = xmlSchemaCollapseString(value);
   2234 			else
   2235 			    norm = xmlSchemaWhiteSpaceReplace(value);
   2236 			if (norm != NULL)
   2237 			    value = norm;
   2238 		    }
   2239 		} else {
   2240 		    const xmlChar *cur = value;
   2241 		    while (*cur != 0) {
   2242 			if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
   2243 			    goto return1;
   2244 			} else {
   2245 			    cur++;
   2246 			}
   2247 		    }
   2248 		}
   2249                 if (val != NULL) {
   2250                     v = xmlSchemaNewValue(XML_SCHEMAS_NORMSTRING);
   2251                     if (v != NULL) {
   2252                         v->value.str = xmlStrdup(value);
   2253                         *val = v;
   2254                     } else {
   2255                         goto error;
   2256                     }
   2257                 }
   2258                 goto return0;
   2259             }
   2260         case XML_SCHEMAS_DECIMAL:{
   2261                 const xmlChar *cur = value;
   2262                 unsigned int len, neg, integ, hasLeadingZeroes;
   2263 		xmlChar cval[25];
   2264 		xmlChar *cptr = cval;
   2265 
   2266                 if ((cur == NULL) || (*cur == 0))
   2267                     goto return1;
   2268 
   2269 		/*
   2270 		* xs:decimal has a whitespace-facet value of 'collapse'.
   2271 		*/
   2272 		if (normOnTheFly)
   2273 		    while IS_WSP_BLANK_CH(*cur) cur++;
   2274 
   2275 		/*
   2276 		* First we handle an optional sign.
   2277 		*/
   2278 		neg = 0;
   2279                 if (*cur == '-') {
   2280 		    neg = 1;
   2281                     cur++;
   2282 		} else if (*cur == '+')
   2283                     cur++;
   2284 		/*
   2285 		* Disallow: "", "-", "- "
   2286 		*/
   2287 		if (*cur == 0)
   2288 		    goto return1;
   2289 		/*
   2290 		 * Next we "pre-parse" the number, in preparation for calling
   2291 		 * the common routine xmlSchemaParseUInt.  We get rid of any
   2292 		 * leading zeroes (because we have reserved only 25 chars),
   2293 		 * and note the position of a decimal point.
   2294 		 */
   2295 		len = 0;
   2296 		integ = ~0u;
   2297 		hasLeadingZeroes = 0;
   2298 		/*
   2299 		* Skip leading zeroes.
   2300 		*/
   2301 		while (*cur == '0') {
   2302 		    cur++;
   2303 		    hasLeadingZeroes = 1;
   2304 		}
   2305 		if (*cur != 0) {
   2306 		    do {
   2307 			if ((*cur >= '0') && (*cur <= '9')) {
   2308 			    *cptr++ = *cur++;
   2309 			    len++;
   2310 			} else if (*cur == '.') {
   2311 			    cur++;
   2312 			    integ = len;
   2313 			    do {
   2314 				if ((*cur >= '0') && (*cur <= '9')) {
   2315 				    *cptr++ = *cur++;
   2316 				    len++;
   2317 				} else
   2318 				    break;
   2319 			    } while (len < 24);
   2320 			    /*
   2321 			    * Disallow "." but allow "00."
   2322 			    */
   2323 			    if ((len == 0) && (!hasLeadingZeroes))
   2324 				goto return1;
   2325 			    break;
   2326 			} else
   2327 			    break;
   2328 		    } while (len < 24);
   2329 		}
   2330 		if (normOnTheFly)
   2331 		    while IS_WSP_BLANK_CH(*cur) cur++;
   2332 		if (*cur != 0)
   2333 		    goto return1; /* error if any extraneous chars */
   2334                 if (val != NULL) {
   2335                     v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
   2336                     if (v != NULL) {
   2337 			/*
   2338 			* Now evaluate the significant digits of the number
   2339 			*/
   2340 			if (len != 0) {
   2341 
   2342 			    if (integ != ~0u) {
   2343 				/*
   2344 				* Get rid of trailing zeroes in the
   2345 				* fractional part.
   2346 				*/
   2347 				while ((len != integ) && (*(cptr-1) == '0')) {
   2348 				    cptr--;
   2349 				    len--;
   2350 				}
   2351 			    }
   2352 			    /*
   2353 			    * Terminate the (preparsed) string.
   2354 			    */
   2355 			    if (len != 0) {
   2356 				*cptr = 0;
   2357 				cptr = cval;
   2358 
   2359 				xmlSchemaParseUInt((const xmlChar **)&cptr,
   2360 				    &v->value.decimal.lo,
   2361 				    &v->value.decimal.mi,
   2362 				    &v->value.decimal.hi);
   2363 			    }
   2364 			}
   2365 			/*
   2366 			* Set the total digits to 1 if a zero value.
   2367 			*/
   2368                         v->value.decimal.sign = neg;
   2369 			if (len == 0) {
   2370 			    /* Speedup for zero values. */
   2371 			    v->value.decimal.total = 1;
   2372 			} else {
   2373 			    v->value.decimal.total = len;
   2374 			    if (integ == ~0u)
   2375 				v->value.decimal.frac = 0;
   2376 			    else
   2377 				v->value.decimal.frac = len - integ;
   2378 			}
   2379                         *val = v;
   2380                     }
   2381                 }
   2382                 goto return0;
   2383             }
   2384         case XML_SCHEMAS_TIME:
   2385         case XML_SCHEMAS_GDAY:
   2386         case XML_SCHEMAS_GMONTH:
   2387         case XML_SCHEMAS_GMONTHDAY:
   2388         case XML_SCHEMAS_GYEAR:
   2389         case XML_SCHEMAS_GYEARMONTH:
   2390         case XML_SCHEMAS_DATE:
   2391         case XML_SCHEMAS_DATETIME:
   2392             ret = xmlSchemaValidateDates(type->builtInType, value, val,
   2393 		normOnTheFly);
   2394             break;
   2395         case XML_SCHEMAS_DURATION:
   2396             ret = xmlSchemaValidateDuration(type, value, val,
   2397 		normOnTheFly);
   2398             break;
   2399         case XML_SCHEMAS_FLOAT:
   2400         case XML_SCHEMAS_DOUBLE: {
   2401                 const xmlChar *cur = value;
   2402                 int neg = 0;
   2403                 int digits_before = 0;
   2404                 int digits_after = 0;
   2405 
   2406 		if (normOnTheFly)
   2407 		    while IS_WSP_BLANK_CH(*cur) cur++;
   2408 
   2409                 if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) {
   2410                     cur += 3;
   2411                     if (*cur != 0)
   2412                         goto return1;
   2413                     if (val != NULL) {
   2414                         if (type == xmlSchemaTypeFloatDef) {
   2415                             v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
   2416                             if (v != NULL) {
   2417                                 v->value.f = (float) xmlXPathNAN;
   2418                             } else {
   2419                                 xmlSchemaFreeValue(v);
   2420                                 goto error;
   2421                             }
   2422                         } else {
   2423                             v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
   2424                             if (v != NULL) {
   2425                                 v->value.d = xmlXPathNAN;
   2426                             } else {
   2427                                 xmlSchemaFreeValue(v);
   2428                                 goto error;
   2429                             }
   2430                         }
   2431                         *val = v;
   2432                     }
   2433                     goto return0;
   2434                 }
   2435                 if (*cur == '-') {
   2436                     neg = 1;
   2437                     cur++;
   2438                 }
   2439                 if ((cur[0] == 'I') && (cur[1] == 'N') && (cur[2] == 'F')) {
   2440                     cur += 3;
   2441                     if (*cur != 0)
   2442                         goto return1;
   2443                     if (val != NULL) {
   2444                         if (type == xmlSchemaTypeFloatDef) {
   2445                             v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
   2446                             if (v != NULL) {
   2447                                 if (neg)
   2448                                     v->value.f = (float) xmlXPathNINF;
   2449                                 else
   2450                                     v->value.f = (float) xmlXPathPINF;
   2451                             } else {
   2452                                 xmlSchemaFreeValue(v);
   2453                                 goto error;
   2454                             }
   2455                         } else {
   2456                             v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
   2457                             if (v != NULL) {
   2458                                 if (neg)
   2459                                     v->value.d = xmlXPathNINF;
   2460                                 else
   2461                                     v->value.d = xmlXPathPINF;
   2462                             } else {
   2463                                 xmlSchemaFreeValue(v);
   2464                                 goto error;
   2465                             }
   2466                         }
   2467                         *val = v;
   2468                     }
   2469                     goto return0;
   2470                 }
   2471                 if ((neg == 0) && (*cur == '+'))
   2472                     cur++;
   2473                 if ((cur[0] == 0) || (cur[0] == '+') || (cur[0] == '-'))
   2474                     goto return1;
   2475                 while ((*cur >= '0') && (*cur <= '9')) {
   2476                     cur++;
   2477                     digits_before++;
   2478                 }
   2479                 if (*cur == '.') {
   2480                     cur++;
   2481                     while ((*cur >= '0') && (*cur <= '9')) {
   2482                         cur++;
   2483                         digits_after++;
   2484                     }
   2485                 }
   2486                 if ((digits_before == 0) && (digits_after == 0))
   2487                     goto return1;
   2488                 if ((*cur == 'e') || (*cur == 'E')) {
   2489                     cur++;
   2490                     if ((*cur == '-') || (*cur == '+'))
   2491                         cur++;
   2492                     while ((*cur >= '0') && (*cur <= '9'))
   2493                         cur++;
   2494                 }
   2495 		if (normOnTheFly)
   2496 		    while IS_WSP_BLANK_CH(*cur) cur++;
   2497 
   2498                 if (*cur != 0)
   2499                     goto return1;
   2500                 if (val != NULL) {
   2501                     if (type == xmlSchemaTypeFloatDef) {
   2502                         v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
   2503                         if (v != NULL) {
   2504 			    /*
   2505 			    * TODO: sscanf seems not to give the correct
   2506 			    * value for extremely high/low values.
   2507 			    * E.g. "1E-149" results in zero.
   2508 			    */
   2509                             if (sscanf((const char *) value, "%f",
   2510                                  &(v->value.f)) == 1) {
   2511                                 *val = v;
   2512                             } else {
   2513                                 xmlSchemaFreeValue(v);
   2514                                 goto return1;
   2515                             }
   2516                         } else {
   2517                             goto error;
   2518                         }
   2519                     } else {
   2520                         v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
   2521                         if (v != NULL) {
   2522 			    /*
   2523 			    * TODO: sscanf seems not to give the correct
   2524 			    * value for extremely high/low values.
   2525 			    */
   2526                             if (sscanf((const char *) value, "%lf",
   2527                                  &(v->value.d)) == 1) {
   2528                                 *val = v;
   2529                             } else {
   2530                                 xmlSchemaFreeValue(v);
   2531                                 goto return1;
   2532                             }
   2533                         } else {
   2534                             goto error;
   2535                         }
   2536                     }
   2537                 }
   2538                 goto return0;
   2539             }
   2540         case XML_SCHEMAS_BOOLEAN:{
   2541                 const xmlChar *cur = value;
   2542 
   2543 		if (normOnTheFly) {
   2544 		    while IS_WSP_BLANK_CH(*cur) cur++;
   2545 		    if (*cur == '0') {
   2546 			ret = 0;
   2547 			cur++;
   2548 		    } else if (*cur == '1') {
   2549 			ret = 1;
   2550 			cur++;
   2551 		    } else if (*cur == 't') {
   2552 			cur++;
   2553 			if ((*cur++ == 'r') && (*cur++ == 'u') &&
   2554 			    (*cur++ == 'e')) {
   2555 			    ret = 1;
   2556 			} else
   2557 			    goto return1;
   2558 		    } else if (*cur == 'f') {
   2559 			cur++;
   2560 			if ((*cur++ == 'a') && (*cur++ == 'l') &&
   2561 			    (*cur++ == 's') && (*cur++ == 'e')) {
   2562 			    ret = 0;
   2563 			} else
   2564 			    goto return1;
   2565 		    } else
   2566 			goto return1;
   2567 		    if (*cur != 0) {
   2568 			while IS_WSP_BLANK_CH(*cur) cur++;
   2569 			if (*cur != 0)
   2570 			    goto return1;
   2571 		    }
   2572 		} else {
   2573 		    if ((cur[0] == '0') && (cur[1] == 0))
   2574 			ret = 0;
   2575 		    else if ((cur[0] == '1') && (cur[1] == 0))
   2576 			ret = 1;
   2577 		    else if ((cur[0] == 't') && (cur[1] == 'r')
   2578 			&& (cur[2] == 'u') && (cur[3] == 'e')
   2579 			&& (cur[4] == 0))
   2580 			ret = 1;
   2581 		    else if ((cur[0] == 'f') && (cur[1] == 'a')
   2582 			&& (cur[2] == 'l') && (cur[3] == 's')
   2583 			&& (cur[4] == 'e') && (cur[5] == 0))
   2584 			ret = 0;
   2585 		    else
   2586 			goto return1;
   2587 		}
   2588                 if (val != NULL) {
   2589                     v = xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN);
   2590                     if (v != NULL) {
   2591                         v->value.b = ret;
   2592                         *val = v;
   2593                     } else {
   2594                         goto error;
   2595                     }
   2596                 }
   2597                 goto return0;
   2598             }
   2599         case XML_SCHEMAS_TOKEN:{
   2600                 const xmlChar *cur = value;
   2601 
   2602 		if (! normOnTheFly) {
   2603 		    while (*cur != 0) {
   2604 			if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
   2605 			    goto return1;
   2606 			} else if (*cur == ' ') {
   2607 			    cur++;
   2608 			    if (*cur == 0)
   2609 				goto return1;
   2610 			    if (*cur == ' ')
   2611 				goto return1;
   2612 			} else {
   2613 			    cur++;
   2614 			}
   2615 		    }
   2616 		}
   2617                 if (val != NULL) {
   2618                     v = xmlSchemaNewValue(XML_SCHEMAS_TOKEN);
   2619                     if (v != NULL) {
   2620                         v->value.str = xmlStrdup(value);
   2621                         *val = v;
   2622                     } else {
   2623                         goto error;
   2624                     }
   2625                 }
   2626                 goto return0;
   2627             }
   2628         case XML_SCHEMAS_LANGUAGE:
   2629 	    if (normOnTheFly) {
   2630 		norm = xmlSchemaCollapseString(value);
   2631 		if (norm != NULL)
   2632 		    value = norm;
   2633 	    }
   2634             if (xmlCheckLanguageID(value) == 1) {
   2635                 if (val != NULL) {
   2636                     v = xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE);
   2637                     if (v != NULL) {
   2638                         v->value.str = xmlStrdup(value);
   2639                         *val = v;
   2640                     } else {
   2641                         goto error;
   2642                     }
   2643                 }
   2644                 goto return0;
   2645             }
   2646             goto return1;
   2647         case XML_SCHEMAS_NMTOKEN:
   2648             if (xmlValidateNMToken(value, 1) == 0) {
   2649                 if (val != NULL) {
   2650                     v = xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN);
   2651                     if (v != NULL) {
   2652                         v->value.str = xmlStrdup(value);
   2653                         *val = v;
   2654                     } else {
   2655                         goto error;
   2656                     }
   2657                 }
   2658                 goto return0;
   2659             }
   2660             goto return1;
   2661         case XML_SCHEMAS_NMTOKENS:
   2662             ret = xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef,
   2663                                              value, val, node);
   2664             if (ret > 0)
   2665                 ret = 0;
   2666             else
   2667                 ret = 1;
   2668             goto done;
   2669         case XML_SCHEMAS_NAME:
   2670             ret = xmlValidateName(value, 1);
   2671             if ((ret == 0) && (val != NULL) && (value != NULL)) {
   2672 		v = xmlSchemaNewValue(XML_SCHEMAS_NAME);
   2673 		if (v != NULL) {
   2674 		     const xmlChar *start = value, *end;
   2675 		     while (IS_BLANK_CH(*start)) start++;
   2676 		     end = start;
   2677 		     while ((*end != 0) && (!IS_BLANK_CH(*end))) end++;
   2678 		     v->value.str = xmlStrndup(start, end - start);
   2679 		    *val = v;
   2680 		} else {
   2681 		    goto error;
   2682 		}
   2683             }
   2684             goto done;
   2685         case XML_SCHEMAS_QNAME:{
   2686                 const xmlChar *uri = NULL;
   2687                 xmlChar *local = NULL;
   2688 
   2689                 ret = xmlValidateQName(value, 1);
   2690 		if (ret != 0)
   2691 		    goto done;
   2692                 if (node != NULL) {
   2693                     xmlChar *prefix;
   2694 		    xmlNsPtr ns;
   2695 
   2696                     local = xmlSplitQName2(value, &prefix);
   2697 		    ns = xmlSearchNs(node->doc, node, prefix);
   2698 		    if ((ns == NULL) && (prefix != NULL)) {
   2699 			xmlFree(prefix);
   2700 			if (local != NULL)
   2701 			    xmlFree(local);
   2702 			goto return1;
   2703 		    }
   2704 		    if (ns != NULL)
   2705 			uri = ns->href;
   2706                     if (prefix != NULL)
   2707                         xmlFree(prefix);
   2708                 }
   2709                 if (val != NULL) {
   2710                     v = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
   2711                     if (v == NULL) {
   2712 			if (local != NULL)
   2713 			    xmlFree(local);
   2714 			goto error;
   2715 		    }
   2716 		    if (local != NULL)
   2717 			v->value.qname.name = local;
   2718 		    else
   2719 			v->value.qname.name = xmlStrdup(value);
   2720 		    if (uri != NULL)
   2721 			v->value.qname.uri = xmlStrdup(uri);
   2722 		    *val = v;
   2723                 } else
   2724 		    if (local != NULL)
   2725 			xmlFree(local);
   2726                 goto done;
   2727             }
   2728         case XML_SCHEMAS_NCNAME:
   2729             ret = xmlValidateNCName(value, 1);
   2730             if ((ret == 0) && (val != NULL)) {
   2731                 v = xmlSchemaNewValue(XML_SCHEMAS_NCNAME);
   2732                 if (v != NULL) {
   2733                     v->value.str = xmlStrdup(value);
   2734                     *val = v;
   2735                 } else {
   2736                     goto error;
   2737                 }
   2738             }
   2739             goto done;
   2740         case XML_SCHEMAS_ID:
   2741             ret = xmlValidateNCName(value, 1);
   2742             if ((ret == 0) && (val != NULL)) {
   2743                 v = xmlSchemaNewValue(XML_SCHEMAS_ID);
   2744                 if (v != NULL) {
   2745                     v->value.str = xmlStrdup(value);
   2746                     *val = v;
   2747                 } else {
   2748                     goto error;
   2749                 }
   2750             }
   2751             if ((ret == 0) && (node != NULL) &&
   2752                 (node->type == XML_ATTRIBUTE_NODE)) {
   2753                 xmlAttrPtr attr = (xmlAttrPtr) node;
   2754 
   2755                 /*
   2756                  * NOTE: the IDness might have already be declared in the DTD
   2757                  */
   2758                 if (attr->atype != XML_ATTRIBUTE_ID) {
   2759                     xmlIDPtr res;
   2760                     xmlChar *strip;
   2761 
   2762                     strip = xmlSchemaStrip(value);
   2763                     if (strip != NULL) {
   2764                         res = xmlAddID(NULL, node->doc, strip, attr);
   2765                         xmlFree(strip);
   2766                     } else
   2767                         res = xmlAddID(NULL, node->doc, value, attr);
   2768                     if (res == NULL) {
   2769                         ret = 2;
   2770                     } else {
   2771                         attr->atype = XML_ATTRIBUTE_ID;
   2772                     }
   2773                 }
   2774             }
   2775             goto done;
   2776         case XML_SCHEMAS_IDREF:
   2777             ret = xmlValidateNCName(value, 1);
   2778             if ((ret == 0) && (val != NULL)) {
   2779 		v = xmlSchemaNewValue(XML_SCHEMAS_IDREF);
   2780 		if (v == NULL)
   2781 		    goto error;
   2782 		v->value.str = xmlStrdup(value);
   2783 		*val = v;
   2784             }
   2785             if ((ret == 0) && (node != NULL) &&
   2786                 (node->type == XML_ATTRIBUTE_NODE)) {
   2787                 xmlAttrPtr attr = (xmlAttrPtr) node;
   2788                 xmlChar *strip;
   2789 
   2790                 strip = xmlSchemaStrip(value);
   2791                 if (strip != NULL) {
   2792                     xmlAddRef(NULL, node->doc, strip, attr);
   2793                     xmlFree(strip);
   2794                 } else
   2795                     xmlAddRef(NULL, node->doc, value, attr);
   2796                 attr->atype = XML_ATTRIBUTE_IDREF;
   2797             }
   2798             goto done;
   2799         case XML_SCHEMAS_IDREFS:
   2800             ret = xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef,
   2801                                              value, val, node);
   2802             if (ret < 0)
   2803                 ret = 2;
   2804             else
   2805                 ret = 0;
   2806             if ((ret == 0) && (node != NULL) &&
   2807                 (node->type == XML_ATTRIBUTE_NODE)) {
   2808                 xmlAttrPtr attr = (xmlAttrPtr) node;
   2809 
   2810                 attr->atype = XML_ATTRIBUTE_IDREFS;
   2811             }
   2812             goto done;
   2813         case XML_SCHEMAS_ENTITY:{
   2814                 xmlChar *strip;
   2815 
   2816                 ret = xmlValidateNCName(value, 1);
   2817                 if ((node == NULL) || (node->doc == NULL))
   2818                     ret = 3;
   2819                 if (ret == 0) {
   2820                     xmlEntityPtr ent;
   2821 
   2822                     strip = xmlSchemaStrip(value);
   2823                     if (strip != NULL) {
   2824                         ent = xmlGetDocEntity(node->doc, strip);
   2825                         xmlFree(strip);
   2826                     } else {
   2827                         ent = xmlGetDocEntity(node->doc, value);
   2828                     }
   2829                     if ((ent == NULL) ||
   2830                         (ent->etype !=
   2831                          XML_EXTERNAL_GENERAL_UNPARSED_ENTITY))
   2832                         ret = 4;
   2833                 }
   2834                 if ((ret == 0) && (val != NULL)) {
   2835                     TODO;
   2836                 }
   2837                 if ((ret == 0) && (node != NULL) &&
   2838                     (node->type == XML_ATTRIBUTE_NODE)) {
   2839                     xmlAttrPtr attr = (xmlAttrPtr) node;
   2840 
   2841                     attr->atype = XML_ATTRIBUTE_ENTITY;
   2842                 }
   2843                 goto done;
   2844             }
   2845         case XML_SCHEMAS_ENTITIES:
   2846             if ((node == NULL) || (node->doc == NULL))
   2847                 goto return3;
   2848             ret = xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef,
   2849                                              value, val, node);
   2850             if (ret <= 0)
   2851                 ret = 1;
   2852             else
   2853                 ret = 0;
   2854             if ((ret == 0) && (node != NULL) &&
   2855                 (node->type == XML_ATTRIBUTE_NODE)) {
   2856                 xmlAttrPtr attr = (xmlAttrPtr) node;
   2857 
   2858                 attr->atype = XML_ATTRIBUTE_ENTITIES;
   2859             }
   2860             goto done;
   2861         case XML_SCHEMAS_NOTATION:{
   2862                 xmlChar *uri = NULL;
   2863                 xmlChar *local = NULL;
   2864 
   2865                 ret = xmlValidateQName(value, 1);
   2866                 if ((ret == 0) && (node != NULL)) {
   2867                     xmlChar *prefix;
   2868 
   2869                     local = xmlSplitQName2(value, &prefix);
   2870                     if (prefix != NULL) {
   2871                         xmlNsPtr ns;
   2872 
   2873                         ns = xmlSearchNs(node->doc, node, prefix);
   2874                         if (ns == NULL)
   2875                             ret = 1;
   2876                         else if (val != NULL)
   2877                             uri = xmlStrdup(ns->href);
   2878                     }
   2879                     if ((local != NULL) && ((val == NULL) || (ret != 0)))
   2880                         xmlFree(local);
   2881                     if (prefix != NULL)
   2882                         xmlFree(prefix);
   2883                 }
   2884                 if ((node == NULL) || (node->doc == NULL))
   2885                     ret = 3;
   2886                 if (ret == 0) {
   2887                     ret = xmlValidateNotationUse(NULL, node->doc, value);
   2888                     if (ret == 1)
   2889                         ret = 0;
   2890                     else
   2891                         ret = 1;
   2892                 }
   2893                 if ((ret == 0) && (val != NULL)) {
   2894                     v = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
   2895                     if (v != NULL) {
   2896                         if (local != NULL)
   2897                             v->value.qname.name = local;
   2898                         else
   2899                             v->value.qname.name = xmlStrdup(value);
   2900                         if (uri != NULL)
   2901                             v->value.qname.uri = uri;
   2902 
   2903                         *val = v;
   2904                     } else {
   2905                         if (local != NULL)
   2906                             xmlFree(local);
   2907                         if (uri != NULL)
   2908                             xmlFree(uri);
   2909                         goto error;
   2910                     }
   2911                 }
   2912                 goto done;
   2913             }
   2914         case XML_SCHEMAS_ANYURI:{
   2915                 if (*value != 0) {
   2916 		    xmlURIPtr uri;
   2917 		    xmlChar *tmpval, *cur;
   2918 		    if (normOnTheFly) {
   2919 			norm = xmlSchemaCollapseString(value);
   2920 			if (norm != NULL)
   2921 			    value = norm;
   2922 		    }
   2923 		    tmpval = xmlStrdup(value);
   2924 		    for (cur = tmpval; *cur; ++cur) {
   2925 			if (*cur < 32 || *cur >= 127 || *cur == ' ' ||
   2926 			    *cur == '<' || *cur == '>' || *cur == '"' ||
   2927 			    *cur == '{' || *cur == '}' || *cur == '|' ||
   2928 			    *cur == '\\' || *cur == '^' || *cur == '`' ||
   2929 			    *cur == '\'')
   2930 			    *cur = '_';
   2931 		    }
   2932                     uri = xmlParseURI((const char *) tmpval);
   2933 		    xmlFree(tmpval);
   2934                     if (uri == NULL)
   2935                         goto return1;
   2936                     xmlFreeURI(uri);
   2937                 }
   2938 
   2939                 if (val != NULL) {
   2940                     v = xmlSchemaNewValue(XML_SCHEMAS_ANYURI);
   2941                     if (v == NULL)
   2942                         goto error;
   2943                     v->value.str = xmlStrdup(value);
   2944                     *val = v;
   2945                 }
   2946                 goto return0;
   2947             }
   2948         case XML_SCHEMAS_HEXBINARY:{
   2949                 const xmlChar *cur = value, *start;
   2950                 xmlChar *base;
   2951                 int total, i = 0;
   2952 
   2953                 if (cur == NULL)
   2954                     goto return1;
   2955 
   2956 		if (normOnTheFly)
   2957 		    while IS_WSP_BLANK_CH(*cur) cur++;
   2958 
   2959 		start = cur;
   2960                 while (((*cur >= '0') && (*cur <= '9')) ||
   2961                        ((*cur >= 'A') && (*cur <= 'F')) ||
   2962                        ((*cur >= 'a') && (*cur <= 'f'))) {
   2963                     i++;
   2964                     cur++;
   2965                 }
   2966 		if (normOnTheFly)
   2967 		    while IS_WSP_BLANK_CH(*cur) cur++;
   2968 
   2969                 if (*cur != 0)
   2970                     goto return1;
   2971                 if ((i % 2) != 0)
   2972                     goto return1;
   2973 
   2974                 if (val != NULL) {
   2975 
   2976                     v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY);
   2977                     if (v == NULL)
   2978                         goto error;
   2979 		    /*
   2980 		    * Copy only the normalized piece.
   2981 		    * CRITICAL TODO: Check this.
   2982 		    */
   2983                     cur = xmlStrndup(start, i);
   2984                     if (cur == NULL) {
   2985 		        xmlSchemaTypeErrMemory(node, "allocating hexbin data");
   2986                         xmlFree(v);
   2987                         goto return1;
   2988                     }
   2989 
   2990                     total = i / 2;      /* number of octets */
   2991 
   2992                     base = (xmlChar *) cur;
   2993                     while (i-- > 0) {
   2994                         if (*base >= 'a')
   2995                             *base = *base - ('a' - 'A');
   2996                         base++;
   2997                     }
   2998 
   2999                     v->value.hex.str = (xmlChar *) cur;
   3000                     v->value.hex.total = total;
   3001                     *val = v;
   3002                 }
   3003                 goto return0;
   3004             }
   3005         case XML_SCHEMAS_BASE64BINARY:{
   3006                 /* ISSUE:
   3007                  *
   3008                  * Ignore all stray characters? (yes, currently)
   3009                  * Worry about long lines? (no, currently)
   3010                  *
   3011                  * rfc2045.txt:
   3012                  *
   3013                  * "The encoded output stream must be represented in lines of
   3014                  * no more than 76 characters each.  All line breaks or other
   3015                  * characters not found in Table 1 must be ignored by decoding
   3016                  * software.  In base64 data, characters other than those in
   3017                  * Table 1, line breaks, and other white space probably
   3018                  * indicate a transmission error, about which a warning
   3019                  * message or even a message rejection might be appropriate
   3020                  * under some circumstances." */
   3021                 const xmlChar *cur = value;
   3022                 xmlChar *base;
   3023                 int total, i = 0, pad = 0;
   3024 
   3025                 if (cur == NULL)
   3026                     goto return1;
   3027 
   3028                 for (; *cur; ++cur) {
   3029                     int decc;
   3030 
   3031                     decc = _xmlSchemaBase64Decode(*cur);
   3032                     if (decc < 0) ;
   3033                     else if (decc < 64)
   3034                         i++;
   3035                     else
   3036                         break;
   3037                 }
   3038                 for (; *cur; ++cur) {
   3039                     int decc;
   3040 
   3041                     decc = _xmlSchemaBase64Decode(*cur);
   3042                     if (decc < 0) ;
   3043                     else if (decc < 64)
   3044                         goto return1;
   3045                     if (decc == 64)
   3046                         pad++;
   3047                 }
   3048 
   3049                 /* rfc2045.txt: "Special processing is performed if fewer than
   3050                  * 24 bits are available at the end of the data being encoded.
   3051                  * A full encoding quantum is always completed at the end of a
   3052                  * body.  When fewer than 24 input bits are available in an
   3053                  * input group, zero bits are added (on the right) to form an
   3054                  * integral number of 6-bit groups.  Padding at the end of the
   3055                  * data is performed using the "=" character.  Since all
   3056                  * base64 input is an integral number of octets, only the
   3057                  * following cases can arise: (1) the final quantum of
   3058                  * encoding input is an integral multiple of 24 bits; here,
   3059                  * the final unit of encoded output will be an integral
   3060                  * multiple ofindent: Standard input:701: Warning:old style
   3061 		 * assignment ambiguity in "=*".  Assuming "= *" 4 characters
   3062 		 * with no "=" padding, (2) the final
   3063                  * quantum of encoding input is exactly 8 bits; here, the
   3064                  * final unit of encoded output will be two characters
   3065                  * followed by two "=" padding characters, or (3) the final
   3066                  * quantum of encoding input is exactly 16 bits; here, the
   3067                  * final unit of encoded output will be three characters
   3068                  * followed by one "=" padding character." */
   3069 
   3070                 total = 3 * (i / 4);
   3071                 if (pad == 0) {
   3072                     if (i % 4 != 0)
   3073                         goto return1;
   3074                 } else if (pad == 1) {
   3075                     int decc;
   3076 
   3077                     if (i % 4 != 3)
   3078                         goto return1;
   3079                     for (decc = _xmlSchemaBase64Decode(*cur);
   3080                          (decc < 0) || (decc > 63);
   3081                          decc = _xmlSchemaBase64Decode(*cur))
   3082                         --cur;
   3083                     /* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00*/
   3084                     /* 00111100 -> 0x3c */
   3085                     if (decc & ~0x3c)
   3086                         goto return1;
   3087                     total += 2;
   3088                 } else if (pad == 2) {
   3089                     int decc;
   3090 
   3091                     if (i % 4 != 2)
   3092                         goto return1;
   3093                     for (decc = _xmlSchemaBase64Decode(*cur);
   3094                          (decc < 0) || (decc > 63);
   3095                          decc = _xmlSchemaBase64Decode(*cur))
   3096                         --cur;
   3097                     /* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */
   3098                     /* 00110000 -> 0x30 */
   3099                     if (decc & ~0x30)
   3100                         goto return1;
   3101                     total += 1;
   3102                 } else
   3103                     goto return1;
   3104 
   3105                 if (val != NULL) {
   3106                     v = xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY);
   3107                     if (v == NULL)
   3108                         goto error;
   3109                     base =
   3110                         (xmlChar *) xmlMallocAtomic((i + pad + 1) *
   3111                                                     sizeof(xmlChar));
   3112                     if (base == NULL) {
   3113 		        xmlSchemaTypeErrMemory(node, "allocating base64 data");
   3114                         xmlFree(v);
   3115                         goto return1;
   3116                     }
   3117                     v->value.base64.str = base;
   3118                     for (cur = value; *cur; ++cur)
   3119                         if (_xmlSchemaBase64Decode(*cur) >= 0) {
   3120                             *base = *cur;
   3121                             ++base;
   3122                         }
   3123                     *base = 0;
   3124                     v->value.base64.total = total;
   3125                     *val = v;
   3126                 }
   3127                 goto return0;
   3128             }
   3129         case XML_SCHEMAS_INTEGER:
   3130         case XML_SCHEMAS_PINTEGER:
   3131         case XML_SCHEMAS_NPINTEGER:
   3132         case XML_SCHEMAS_NINTEGER:
   3133         case XML_SCHEMAS_NNINTEGER:{
   3134                 const xmlChar *cur = value;
   3135                 unsigned long lo, mi, hi;
   3136                 int sign = 0;
   3137 
   3138                 if (cur == NULL)
   3139                     goto return1;
   3140 		if (normOnTheFly)
   3141 		    while IS_WSP_BLANK_CH(*cur) cur++;
   3142                 if (*cur == '-') {
   3143                     sign = 1;
   3144                     cur++;
   3145                 } else if (*cur == '+')
   3146                     cur++;
   3147                 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
   3148                 if (ret < 0)
   3149                     goto return1;
   3150 		if (normOnTheFly)
   3151 		    while IS_WSP_BLANK_CH(*cur) cur++;
   3152                 if (*cur != 0)
   3153                     goto return1;
   3154                 if (type->builtInType == XML_SCHEMAS_NPINTEGER) {
   3155                     if ((sign == 0) &&
   3156                         ((hi != 0) || (mi != 0) || (lo != 0)))
   3157                         goto return1;
   3158                 } else if (type->builtInType == XML_SCHEMAS_PINTEGER) {
   3159                     if (sign == 1)
   3160                         goto return1;
   3161                     if ((hi == 0) && (mi == 0) && (lo == 0))
   3162                         goto return1;
   3163                 } else if (type->builtInType == XML_SCHEMAS_NINTEGER) {
   3164                     if (sign == 0)
   3165                         goto return1;
   3166                     if ((hi == 0) && (mi == 0) && (lo == 0))
   3167                         goto return1;
   3168                 } else if (type->builtInType == XML_SCHEMAS_NNINTEGER) {
   3169                     if ((sign == 1) &&
   3170                         ((hi != 0) || (mi != 0) || (lo != 0)))
   3171                         goto return1;
   3172                 }
   3173                 if (val != NULL) {
   3174                     v = xmlSchemaNewValue(type->builtInType);
   3175                     if (v != NULL) {
   3176 			if (ret == 0)
   3177 			    ret++;
   3178                         v->value.decimal.lo = lo;
   3179                         v->value.decimal.mi = mi;
   3180                         v->value.decimal.hi = hi;
   3181                         v->value.decimal.sign = sign;
   3182                         v->value.decimal.frac = 0;
   3183                         v->value.decimal.total = ret;
   3184                         *val = v;
   3185                     }
   3186                 }
   3187                 goto return0;
   3188             }
   3189         case XML_SCHEMAS_LONG:
   3190         case XML_SCHEMAS_BYTE:
   3191         case XML_SCHEMAS_SHORT:
   3192         case XML_SCHEMAS_INT:{
   3193                 const xmlChar *cur = value;
   3194                 unsigned long lo, mi, hi;
   3195                 int sign = 0;
   3196 
   3197                 if (cur == NULL)
   3198                     goto return1;
   3199                 if (*cur == '-') {
   3200                     sign = 1;
   3201                     cur++;
   3202                 } else if (*cur == '+')
   3203                     cur++;
   3204                 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
   3205                 if (ret < 0)
   3206                     goto return1;
   3207                 if (*cur != 0)
   3208                     goto return1;
   3209                 if (type->builtInType == XML_SCHEMAS_LONG) {
   3210                     if (hi >= 922) {
   3211                         if (hi > 922)
   3212                             goto return1;
   3213                         if (mi >= 33720368) {
   3214                             if (mi > 33720368)
   3215                                 goto return1;
   3216                             if ((sign == 0) && (lo > 54775807))
   3217                                 goto return1;
   3218                             if ((sign == 1) && (lo > 54775808))
   3219                                 goto return1;
   3220                         }
   3221                     }
   3222                 } else if (type->builtInType == XML_SCHEMAS_INT) {
   3223                     if (hi != 0)
   3224                         goto return1;
   3225                     if (mi >= 21) {
   3226                         if (mi > 21)
   3227                             goto return1;
   3228                         if ((sign == 0) && (lo > 47483647))
   3229                             goto return1;
   3230                         if ((sign == 1) && (lo > 47483648))
   3231                             goto return1;
   3232                     }
   3233                 } else if (type->builtInType == XML_SCHEMAS_SHORT) {
   3234                     if ((mi != 0) || (hi != 0))
   3235                         goto return1;
   3236                     if ((sign == 1) && (lo > 32768))
   3237                         goto return1;
   3238                     if ((sign == 0) && (lo > 32767))
   3239                         goto return1;
   3240                 } else if (type->builtInType == XML_SCHEMAS_BYTE) {
   3241                     if ((mi != 0) || (hi != 0))
   3242                         goto return1;
   3243                     if ((sign == 1) && (lo > 128))
   3244                         goto return1;
   3245                     if ((sign == 0) && (lo > 127))
   3246                         goto return1;
   3247                 }
   3248                 if (val != NULL) {
   3249                     v = xmlSchemaNewValue(type->builtInType);
   3250                     if (v != NULL) {
   3251                         v->value.decimal.lo = lo;
   3252                         v->value.decimal.mi = mi;
   3253                         v->value.decimal.hi = hi;
   3254                         v->value.decimal.sign = sign;
   3255                         v->value.decimal.frac = 0;
   3256                         v->value.decimal.total = ret;
   3257                         *val = v;
   3258                     }
   3259                 }
   3260                 goto return0;
   3261             }
   3262         case XML_SCHEMAS_UINT:
   3263         case XML_SCHEMAS_ULONG:
   3264         case XML_SCHEMAS_USHORT:
   3265         case XML_SCHEMAS_UBYTE:{
   3266                 const xmlChar *cur = value;
   3267                 unsigned long lo, mi, hi;
   3268 
   3269                 if (cur == NULL)
   3270                     goto return1;
   3271                 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
   3272                 if (ret < 0)
   3273                     goto return1;
   3274                 if (*cur != 0)
   3275                     goto return1;
   3276                 if (type->builtInType == XML_SCHEMAS_ULONG) {
   3277                     if (hi >= 1844) {
   3278                         if (hi > 1844)
   3279                             goto return1;
   3280                         if (mi >= 67440737) {
   3281                             if (mi > 67440737)
   3282                                 goto return1;
   3283                             if (lo > 9551615)
   3284                                 goto return1;
   3285                         }
   3286                     }
   3287                 } else if (type->builtInType == XML_SCHEMAS_UINT) {
   3288                     if (hi != 0)
   3289                         goto return1;
   3290                     if (mi >= 42) {
   3291                         if (mi > 42)
   3292                             goto return1;
   3293                         if (lo > 94967295)
   3294                             goto return1;
   3295                     }
   3296                 } else if (type->builtInType == XML_SCHEMAS_USHORT) {
   3297                     if ((mi != 0) || (hi != 0))
   3298                         goto return1;
   3299                     if (lo > 65535)
   3300                         goto return1;
   3301                 } else if (type->builtInType == XML_SCHEMAS_UBYTE) {
   3302                     if ((mi != 0) || (hi != 0))
   3303                         goto return1;
   3304                     if (lo > 255)
   3305                         goto return1;
   3306                 }
   3307                 if (val != NULL) {
   3308                     v = xmlSchemaNewValue(type->builtInType);
   3309                     if (v != NULL) {
   3310                         v->value.decimal.lo = lo;
   3311                         v->value.decimal.mi = mi;
   3312                         v->value.decimal.hi = hi;
   3313                         v->value.decimal.sign = 0;
   3314                         v->value.decimal.frac = 0;
   3315                         v->value.decimal.total = ret;
   3316                         *val = v;
   3317                     }
   3318                 }
   3319                 goto return0;
   3320             }
   3321     }
   3322 
   3323   done:
   3324     if (norm != NULL)
   3325         xmlFree(norm);
   3326     return (ret);
   3327   return3:
   3328     if (norm != NULL)
   3329         xmlFree(norm);
   3330     return (3);
   3331   return1:
   3332     if (norm != NULL)
   3333         xmlFree(norm);
   3334     return (1);
   3335   return0:
   3336     if (norm != NULL)
   3337         xmlFree(norm);
   3338     return (0);
   3339   error:
   3340     if (norm != NULL)
   3341         xmlFree(norm);
   3342     return (-1);
   3343 }
   3344 
   3345 /**
   3346  * xmlSchemaValPredefTypeNode:
   3347  * @type: the predefined type
   3348  * @value: the value to check
   3349  * @val:  the return computed value
   3350  * @node:  the node containing the value
   3351  *
   3352  * Check that a value conforms to the lexical space of the predefined type.
   3353  * if true a value is computed and returned in @val.
   3354  *
   3355  * Returns 0 if this validates, a positive error code number otherwise
   3356  *         and -1 in case of internal or API error.
   3357  */
   3358 int
   3359 xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type, const xmlChar *value,
   3360 	                   xmlSchemaValPtr *val, xmlNodePtr node) {
   3361     return(xmlSchemaValAtomicType(type, value, val, node, 0,
   3362 	XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 1, 0));
   3363 }
   3364 
   3365 /**
   3366  * xmlSchemaValPredefTypeNodeNoNorm:
   3367  * @type: the predefined type
   3368  * @value: the value to check
   3369  * @val:  the return computed value
   3370  * @node:  the node containing the value
   3371  *
   3372  * Check that a value conforms to the lexical space of the predefined type.
   3373  * if true a value is computed and returned in @val.
   3374  * This one does apply any normalization to the value.
   3375  *
   3376  * Returns 0 if this validates, a positive error code number otherwise
   3377  *         and -1 in case of internal or API error.
   3378  */
   3379 int
   3380 xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type, const xmlChar *value,
   3381 				 xmlSchemaValPtr *val, xmlNodePtr node) {
   3382     return(xmlSchemaValAtomicType(type, value, val, node, 1,
   3383 	XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 0, 1));
   3384 }
   3385 
   3386 /**
   3387  * xmlSchemaValidatePredefinedType:
   3388  * @type: the predefined type
   3389  * @value: the value to check
   3390  * @val:  the return computed value
   3391  *
   3392  * Check that a value conforms to the lexical space of the predefined type.
   3393  * if true a value is computed and returned in @val.
   3394  *
   3395  * Returns 0 if this validates, a positive error code number otherwise
   3396  *         and -1 in case of internal or API error.
   3397  */
   3398 int
   3399 xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
   3400 	                        xmlSchemaValPtr *val) {
   3401     return(xmlSchemaValPredefTypeNode(type, value, val, NULL));
   3402 }
   3403 
   3404 /**
   3405  * xmlSchemaCompareDecimals:
   3406  * @x:  a first decimal value
   3407  * @y:  a second decimal value
   3408  *
   3409  * Compare 2 decimals
   3410  *
   3411  * Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error
   3412  */
   3413 static int
   3414 xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
   3415 {
   3416     xmlSchemaValPtr swp;
   3417     int order = 1, integx, integy, dlen;
   3418     unsigned long hi, mi, lo;
   3419 
   3420     /*
   3421      * First test: If x is -ve and not zero
   3422      */
   3423     if ((x->value.decimal.sign) &&
   3424 	((x->value.decimal.lo != 0) ||
   3425 	 (x->value.decimal.mi != 0) ||
   3426 	 (x->value.decimal.hi != 0))) {
   3427 	/*
   3428 	 * Then if y is -ve and not zero reverse the compare
   3429 	 */
   3430 	if ((y->value.decimal.sign) &&
   3431 	    ((y->value.decimal.lo != 0) ||
   3432 	     (y->value.decimal.mi != 0) ||
   3433 	     (y->value.decimal.hi != 0)))
   3434 	    order = -1;
   3435 	/*
   3436 	 * Otherwise (y >= 0) we have the answer
   3437 	 */
   3438 	else
   3439 	    return (-1);
   3440     /*
   3441      * If x is not -ve and y is -ve we have the answer
   3442      */
   3443     } else if ((y->value.decimal.sign) &&
   3444 	       ((y->value.decimal.lo != 0) ||
   3445 		(y->value.decimal.mi != 0) ||
   3446 		(y->value.decimal.hi != 0))) {
   3447         return (1);
   3448     }
   3449     /*
   3450      * If it's not simply determined by a difference in sign,
   3451      * then we need to compare the actual values of the two nums.
   3452      * To do this, we start by looking at the integral parts.
   3453      * If the number of integral digits differ, then we have our
   3454      * answer.
   3455      */
   3456     integx = x->value.decimal.total - x->value.decimal.frac;
   3457     integy = y->value.decimal.total - y->value.decimal.frac;
   3458     /*
   3459     * NOTE: We changed the "total" for values like "0.1"
   3460     *   (or "-0.1" or ".1") to be 1, which was 2 previously.
   3461     *   Therefore the special case, when such values are
   3462     *   compared with 0, needs to be handled separately;
   3463     *   otherwise a zero would be recognized incorrectly as
   3464     *   greater than those values. This has the nice side effect
   3465     *   that we gain an overall optimized comparison with zeroes.
   3466     * Note that a "0" has a "total" of 1 already.
   3467     */
   3468     if (integx == 1) {
   3469 	if (x->value.decimal.lo == 0) {
   3470 	    if (integy != 1)
   3471 		return -order;
   3472 	    else if (y->value.decimal.lo != 0)
   3473 		return -order;
   3474 	    else
   3475 		return(0);
   3476 	}
   3477     }
   3478     if (integy == 1) {
   3479 	if (y->value.decimal.lo == 0) {
   3480 	    if (integx != 1)
   3481 		return order;
   3482 	    else if (x->value.decimal.lo != 0)
   3483 		return order;
   3484 	    else
   3485 		return(0);
   3486 	}
   3487     }
   3488 
   3489     if (integx > integy)
   3490 	return order;
   3491     else if (integy > integx)
   3492 	return -order;
   3493 
   3494     /*
   3495      * If the number of integral digits is the same for both numbers,
   3496      * then things get a little more complicated.  We need to "normalize"
   3497      * the numbers in order to properly compare them.  To do this, we
   3498      * look at the total length of each number (length => number of
   3499      * significant digits), and divide the "shorter" by 10 (decreasing
   3500      * the length) until they are of equal length.
   3501      */
   3502     dlen = x->value.decimal.total - y->value.decimal.total;
   3503     if (dlen < 0) {	/* y has more digits than x */
   3504 	swp = x;
   3505 	hi = y->value.decimal.hi;
   3506 	mi = y->value.decimal.mi;
   3507 	lo = y->value.decimal.lo;
   3508 	dlen = -dlen;
   3509 	order = -order;
   3510     } else {		/* x has more digits than y */
   3511 	swp = y;
   3512 	hi = x->value.decimal.hi;
   3513 	mi = x->value.decimal.mi;
   3514 	lo = x->value.decimal.lo;
   3515     }
   3516     while (dlen > 8) {	/* in effect, right shift by 10**8 */
   3517 	lo = mi;
   3518 	mi = hi;
   3519 	hi = 0;
   3520 	dlen -= 8;
   3521     }
   3522     while (dlen > 0) {
   3523 	unsigned long rem1, rem2;
   3524 	rem1 = (hi % 10) * 100000000L;
   3525 	hi = hi / 10;
   3526 	rem2 = (mi % 10) * 100000000L;
   3527 	mi = (mi + rem1) / 10;
   3528 	lo = (lo + rem2) / 10;
   3529 	dlen--;
   3530     }
   3531     if (hi > swp->value.decimal.hi) {
   3532 	return order;
   3533     } else if (hi == swp->value.decimal.hi) {
   3534 	if (mi > swp->value.decimal.mi) {
   3535 	    return order;
   3536 	} else if (mi == swp->value.decimal.mi) {
   3537 	    if (lo > swp->value.decimal.lo) {
   3538 		return order;
   3539 	    } else if (lo == swp->value.decimal.lo) {
   3540 		if (x->value.decimal.total == y->value.decimal.total) {
   3541 		    return 0;
   3542 		} else {
   3543 		    return order;
   3544 		}
   3545 	    }
   3546 	}
   3547     }
   3548     return -order;
   3549 }
   3550 
   3551 /**
   3552  * xmlSchemaCompareDurations:
   3553  * @x:  a first duration value
   3554  * @y:  a second duration value
   3555  *
   3556  * Compare 2 durations
   3557  *
   3558  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
   3559  * case of error
   3560  */
   3561 static int
   3562 xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y)
   3563 {
   3564     long carry, mon, day;
   3565     double sec;
   3566     int invert = 1;
   3567     long xmon, xday, myear, minday, maxday;
   3568     static const long dayRange [2][12] = {
   3569         { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, },
   3570         { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} };
   3571 
   3572     if ((x == NULL) || (y == NULL))
   3573         return -2;
   3574 
   3575     /* months */
   3576     mon = x->value.dur.mon - y->value.dur.mon;
   3577 
   3578     /* seconds */
   3579     sec = x->value.dur.sec - y->value.dur.sec;
   3580     carry = (long)(sec / SECS_PER_DAY);
   3581     sec -= ((double)carry) * SECS_PER_DAY;
   3582 
   3583     /* days */
   3584     day = x->value.dur.day - y->value.dur.day + carry;
   3585 
   3586     /* easy test */
   3587     if (mon == 0) {
   3588         if (day == 0)
   3589             if (sec == 0.0)
   3590                 return 0;
   3591             else if (sec < 0.0)
   3592                 return -1;
   3593             else
   3594                 return 1;
   3595         else if (day < 0)
   3596             return -1;
   3597         else
   3598             return 1;
   3599     }
   3600 
   3601     if (mon > 0) {
   3602         if ((day >= 0) && (sec >= 0.0))
   3603             return 1;
   3604         else {
   3605             xmon = mon;
   3606             xday = -day;
   3607         }
   3608     } else if ((day <= 0) && (sec <= 0.0)) {
   3609         return -1;
   3610     } else {
   3611 	invert = -1;
   3612         xmon = -mon;
   3613         xday = day;
   3614     }
   3615 
   3616     myear = xmon / 12;
   3617     if (myear == 0) {
   3618 	minday = 0;
   3619 	maxday = 0;
   3620     } else {
   3621 	maxday = 366 * ((myear + 3) / 4) +
   3622 	         365 * ((myear - 1) % 4);
   3623 	minday = maxday - 1;
   3624     }
   3625 
   3626     xmon = xmon % 12;
   3627     minday += dayRange[0][xmon];
   3628     maxday += dayRange[1][xmon];
   3629 
   3630     if ((maxday == minday) && (maxday == xday))
   3631 	return(0); /* can this really happen ? */
   3632     if (maxday < xday)
   3633         return(-invert);
   3634     if (minday > xday)
   3635         return(invert);
   3636 
   3637     /* indeterminate */
   3638     return 2;
   3639 }
   3640 
   3641 /*
   3642  * macros for adding date/times and durations
   3643  */
   3644 #define FQUOTIENT(a,b)                  (floor(((double)a/(double)b)))
   3645 #define MODULO(a,b)                     (a - FQUOTIENT(a,b) * b)
   3646 #define FQUOTIENT_RANGE(a,low,high)     (FQUOTIENT((a-low),(high-low)))
   3647 #define MODULO_RANGE(a,low,high)        ((MODULO((a-low),(high-low)))+low)
   3648 
   3649 /**
   3650  * xmlSchemaDupVal:
   3651  * @v: the #xmlSchemaValPtr value to duplicate
   3652  *
   3653  * Makes a copy of @v. The calling program is responsible for freeing
   3654  * the returned value.
   3655  *
   3656  * returns a pointer to a duplicated #xmlSchemaValPtr or NULL if error.
   3657  */
   3658 static xmlSchemaValPtr
   3659 xmlSchemaDupVal (xmlSchemaValPtr v)
   3660 {
   3661     xmlSchemaValPtr ret = xmlSchemaNewValue(v->type);
   3662     if (ret == NULL)
   3663         return NULL;
   3664 
   3665     memcpy(ret, v, sizeof(xmlSchemaVal));
   3666     ret->next = NULL;
   3667     return ret;
   3668 }
   3669 
   3670 /**
   3671  * xmlSchemaCopyValue:
   3672  * @val:  the precomputed value to be copied
   3673  *
   3674  * Copies the precomputed value. This duplicates any string within.
   3675  *
   3676  * Returns the copy or NULL if a copy for a data-type is not implemented.
   3677  */
   3678 xmlSchemaValPtr
   3679 xmlSchemaCopyValue(xmlSchemaValPtr val)
   3680 {
   3681     xmlSchemaValPtr ret = NULL, prev = NULL, cur;
   3682 
   3683     /*
   3684     * Copy the string values.
   3685     */
   3686     while (val != NULL) {
   3687 	switch (val->type) {
   3688 	    case XML_SCHEMAS_ANYTYPE:
   3689 	    case XML_SCHEMAS_IDREFS:
   3690 	    case XML_SCHEMAS_ENTITIES:
   3691 	    case XML_SCHEMAS_NMTOKENS:
   3692 		xmlSchemaFreeValue(ret);
   3693 		return (NULL);
   3694 	    case XML_SCHEMAS_ANYSIMPLETYPE:
   3695 	    case XML_SCHEMAS_STRING:
   3696 	    case XML_SCHEMAS_NORMSTRING:
   3697 	    case XML_SCHEMAS_TOKEN:
   3698 	    case XML_SCHEMAS_LANGUAGE:
   3699 	    case XML_SCHEMAS_NAME:
   3700 	    case XML_SCHEMAS_NCNAME:
   3701 	    case XML_SCHEMAS_ID:
   3702 	    case XML_SCHEMAS_IDREF:
   3703 	    case XML_SCHEMAS_ENTITY:
   3704 	    case XML_SCHEMAS_NMTOKEN:
   3705 	    case XML_SCHEMAS_ANYURI:
   3706 		cur = xmlSchemaDupVal(val);
   3707 		if (val->value.str != NULL)
   3708 		    cur->value.str = xmlStrdup(BAD_CAST val->value.str);
   3709 		break;
   3710 	    case XML_SCHEMAS_QNAME:
   3711 	    case XML_SCHEMAS_NOTATION:
   3712 		cur = xmlSchemaDupVal(val);
   3713 		if (val->value.qname.name != NULL)
   3714 		    cur->value.qname.name =
   3715                     xmlStrdup(BAD_CAST val->value.qname.name);
   3716 		if (val->value.qname.uri != NULL)
   3717 		    cur->value.qname.uri =
   3718                     xmlStrdup(BAD_CAST val->value.qname.uri);
   3719 		break;
   3720 	    case XML_SCHEMAS_HEXBINARY:
   3721 		cur = xmlSchemaDupVal(val);
   3722 		if (val->value.hex.str != NULL)
   3723 		    cur->value.hex.str = xmlStrdup(BAD_CAST val->value.hex.str);
   3724 		break;
   3725 	    case XML_SCHEMAS_BASE64BINARY:
   3726 		cur = xmlSchemaDupVal(val);
   3727 		if (val->value.base64.str != NULL)
   3728 		    cur->value.base64.str =
   3729                     xmlStrdup(BAD_CAST val->value.base64.str);
   3730 		break;
   3731 	    default:
   3732 		cur = xmlSchemaDupVal(val);
   3733 		break;
   3734 	}
   3735 	if (ret == NULL)
   3736 	    ret = cur;
   3737 	else
   3738 	    prev->next = cur;
   3739 	prev = cur;
   3740 	val = val->next;
   3741     }
   3742     return (ret);
   3743 }
   3744 
   3745 /**
   3746  * _xmlSchemaDateAdd:
   3747  * @dt: an #xmlSchemaValPtr
   3748  * @dur: an #xmlSchemaValPtr of type #XS_DURATION
   3749  *
   3750  * Compute a new date/time from @dt and @dur. This function assumes @dt
   3751  * is either #XML_SCHEMAS_DATETIME, #XML_SCHEMAS_DATE, #XML_SCHEMAS_GYEARMONTH,
   3752  * or #XML_SCHEMAS_GYEAR. The returned #xmlSchemaVal is the same type as
   3753  * @dt. The calling program is responsible for freeing the returned value.
   3754  *
   3755  * Returns a pointer to a new #xmlSchemaVal or NULL if error.
   3756  */
   3757 static xmlSchemaValPtr
   3758 _xmlSchemaDateAdd (xmlSchemaValPtr dt, xmlSchemaValPtr dur)
   3759 {
   3760     xmlSchemaValPtr ret, tmp;
   3761     long carry, tempdays, temp;
   3762     xmlSchemaValDatePtr r, d;
   3763     xmlSchemaValDurationPtr u;
   3764 
   3765     if ((dt == NULL) || (dur == NULL))
   3766         return NULL;
   3767 
   3768     ret = xmlSchemaNewValue(dt->type);
   3769     if (ret == NULL)
   3770         return NULL;
   3771 
   3772     /* make a copy so we don't alter the original value */
   3773     tmp = xmlSchemaDupVal(dt);
   3774     if (tmp == NULL) {
   3775         xmlSchemaFreeValue(ret);
   3776         return NULL;
   3777     }
   3778 
   3779     r = &(ret->value.date);
   3780     d = &(tmp->value.date);
   3781     u = &(dur->value.dur);
   3782 
   3783     /* normalization */
   3784     if (d->mon == 0)
   3785         d->mon = 1;
   3786 
   3787     /* normalize for time zone offset */
   3788     u->sec -= (d->tzo * 60);
   3789     d->tzo = 0;
   3790 
   3791     /* normalization */
   3792     if (d->day == 0)
   3793         d->day = 1;
   3794 
   3795     /* month */
   3796     carry  = d->mon + u->mon;
   3797     r->mon = (unsigned int) MODULO_RANGE(carry, 1, 13);
   3798     carry  = (long) FQUOTIENT_RANGE(carry, 1, 13);
   3799 
   3800     /* year (may be modified later) */
   3801     r->year = d->year + carry;
   3802     if (r->year == 0) {
   3803         if (d->year > 0)
   3804             r->year--;
   3805         else
   3806             r->year++;
   3807     }
   3808 
   3809     /* time zone */
   3810     r->tzo     = d->tzo;
   3811     r->tz_flag = d->tz_flag;
   3812 
   3813     /* seconds */
   3814     r->sec = d->sec + u->sec;
   3815     carry  = (long) FQUOTIENT((long)r->sec, 60);
   3816     if (r->sec != 0.0) {
   3817         r->sec = MODULO(r->sec, 60.0);
   3818     }
   3819 
   3820     /* minute */
   3821     carry += d->min;
   3822     r->min = (unsigned int) MODULO(carry, 60);
   3823     carry  = (long) FQUOTIENT(carry, 60);
   3824 
   3825     /* hours */
   3826     carry  += d->hour;
   3827     r->hour = (unsigned int) MODULO(carry, 24);
   3828     carry   = (long)FQUOTIENT(carry, 24);
   3829 
   3830     /*
   3831      * days
   3832      * Note we use tempdays because the temporary values may need more
   3833      * than 5 bits
   3834      */
   3835     if ((VALID_YEAR(r->year)) && (VALID_MONTH(r->mon)) &&
   3836                   (d->day > MAX_DAYINMONTH(r->year, r->mon)))
   3837         tempdays = MAX_DAYINMONTH(r->year, r->mon);
   3838     else if (d->day < 1)
   3839         tempdays = 1;
   3840     else
   3841         tempdays = d->day;
   3842 
   3843     tempdays += u->day + carry;
   3844 
   3845     while (1) {
   3846         if (tempdays < 1) {
   3847             long tmon = (long) MODULO_RANGE((int)r->mon-1, 1, 13);
   3848             long tyr  = r->year + (long)FQUOTIENT_RANGE((int)r->mon-1, 1, 13);
   3849             if (tyr == 0)
   3850                 tyr--;
   3851 	    /*
   3852 	     * Coverity detected an overrun in daysInMonth
   3853 	     * of size 12 at position 12 with index variable "((r)->mon - 1)"
   3854 	     */
   3855 	    if (tmon < 1)
   3856 	        tmon = 1;
   3857 	    if (tmon > 12)
   3858 	        tmon = 12;
   3859             tempdays += MAX_DAYINMONTH(tyr, tmon);
   3860             carry = -1;
   3861         } else if (VALID_YEAR(r->year) && VALID_MONTH(r->mon) &&
   3862                    tempdays > (long) MAX_DAYINMONTH(r->year, r->mon)) {
   3863             tempdays = tempdays - MAX_DAYINMONTH(r->year, r->mon);
   3864             carry = 1;
   3865         } else
   3866             break;
   3867 
   3868         temp = r->mon + carry;
   3869         r->mon = (unsigned int) MODULO_RANGE(temp, 1, 13);
   3870         r->year = r->year + (unsigned int) FQUOTIENT_RANGE(temp, 1, 13);
   3871         if (r->year == 0) {
   3872             if (temp < 1)
   3873                 r->year--;
   3874             else
   3875                 r->year++;
   3876 	}
   3877     }
   3878 
   3879     r->day = tempdays;
   3880 
   3881     /*
   3882      * adjust the date/time type to the date values
   3883      */
   3884     if (ret->type != XML_SCHEMAS_DATETIME) {
   3885         if ((r->hour) || (r->min) || (r->sec))
   3886             ret->type = XML_SCHEMAS_DATETIME;
   3887         else if (ret->type != XML_SCHEMAS_DATE) {
   3888             if ((r->mon != 1) && (r->day != 1))
   3889                 ret->type = XML_SCHEMAS_DATE;
   3890             else if ((ret->type != XML_SCHEMAS_GYEARMONTH) && (r->mon != 1))
   3891                 ret->type = XML_SCHEMAS_GYEARMONTH;
   3892         }
   3893     }
   3894 
   3895     xmlSchemaFreeValue(tmp);
   3896 
   3897     return ret;
   3898 }
   3899 
   3900 /**
   3901  * xmlSchemaDateNormalize:
   3902  * @dt: an #xmlSchemaValPtr of a date/time type value.
   3903  * @offset: number of seconds to adjust @dt by.
   3904  *
   3905  * Normalize @dt to GMT time. The @offset parameter is subtracted from
   3906  * the return value is a time-zone offset is present on @dt.
   3907  *
   3908  * Returns a normalized copy of @dt or NULL if error.
   3909  */
   3910 static xmlSchemaValPtr
   3911 xmlSchemaDateNormalize (xmlSchemaValPtr dt, double offset)
   3912 {
   3913     xmlSchemaValPtr dur, ret;
   3914 
   3915     if (dt == NULL)
   3916         return NULL;
   3917 
   3918     if (((dt->type != XML_SCHEMAS_TIME) &&
   3919          (dt->type != XML_SCHEMAS_DATETIME) &&
   3920 	 (dt->type != XML_SCHEMAS_DATE)) || (dt->value.date.tzo == 0))
   3921         return xmlSchemaDupVal(dt);
   3922 
   3923     dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
   3924     if (dur == NULL)
   3925         return NULL;
   3926 
   3927     dur->value.date.sec -= offset;
   3928 
   3929     ret = _xmlSchemaDateAdd(dt, dur);
   3930     if (ret == NULL)
   3931         return NULL;
   3932 
   3933     xmlSchemaFreeValue(dur);
   3934 
   3935     /* ret->value.date.tzo = 0; */
   3936     return ret;
   3937 }
   3938 
   3939 /**
   3940  * _xmlSchemaDateCastYMToDays:
   3941  * @dt: an #xmlSchemaValPtr
   3942  *
   3943  * Convert mon and year of @dt to total number of days. Take the
   3944  * number of years since (or before) 1 AD and add the number of leap
   3945  * years. This is a function  because negative
   3946  * years must be handled a little differently and there is no zero year.
   3947  *
   3948  * Returns number of days.
   3949  */
   3950 static long
   3951 _xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt)
   3952 {
   3953     long ret;
   3954     int mon;
   3955 
   3956     mon = dt->value.date.mon;
   3957     if (mon <= 0) mon = 1; /* normalization */
   3958 
   3959     if (dt->value.date.year <= 0)
   3960         ret = (dt->value.date.year * 365) +
   3961               (((dt->value.date.year+1)/4)-((dt->value.date.year+1)/100)+
   3962                ((dt->value.date.year+1)/400)) +
   3963               DAY_IN_YEAR(0, mon, dt->value.date.year);
   3964     else
   3965         ret = ((dt->value.date.year-1) * 365) +
   3966               (((dt->value.date.year-1)/4)-((dt->value.date.year-1)/100)+
   3967                ((dt->value.date.year-1)/400)) +
   3968               DAY_IN_YEAR(0, mon, dt->value.date.year);
   3969 
   3970     return ret;
   3971 }
   3972 
   3973 /**
   3974  * TIME_TO_NUMBER:
   3975  * @dt:  an #xmlSchemaValPtr
   3976  *
   3977  * Calculates the number of seconds in the time portion of @dt.
   3978  *
   3979  * Returns seconds.
   3980  */
   3981 #define TIME_TO_NUMBER(dt)                              \
   3982     ((double)((dt->value.date.hour * SECS_PER_HOUR) +   \
   3983               (dt->value.date.min * SECS_PER_MIN) +	\
   3984               (dt->value.date.tzo * SECS_PER_MIN)) +	\
   3985                dt->value.date.sec)
   3986 
   3987 /**
   3988  * xmlSchemaCompareDates:
   3989  * @x:  a first date/time value
   3990  * @y:  a second date/time value
   3991  *
   3992  * Compare 2 date/times
   3993  *
   3994  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
   3995  * case of error
   3996  */
   3997 static int
   3998 xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
   3999 {
   4000     unsigned char xmask, ymask, xor_mask, and_mask;
   4001     xmlSchemaValPtr p1, p2, q1, q2;
   4002     long p1d, p2d, q1d, q2d;
   4003 
   4004     if ((x == NULL) || (y == NULL))
   4005         return -2;
   4006 
   4007     if (x->value.date.tz_flag) {
   4008 
   4009         if (!y->value.date.tz_flag) {
   4010             p1 = xmlSchemaDateNormalize(x, 0);
   4011             p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
   4012             /* normalize y + 14:00 */
   4013             q1 = xmlSchemaDateNormalize(y, (14 * SECS_PER_HOUR));
   4014 
   4015             q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
   4016             if (p1d < q1d) {
   4017 		xmlSchemaFreeValue(p1);
   4018 		xmlSchemaFreeValue(q1);
   4019                 return -1;
   4020 	    } else if (p1d == q1d) {
   4021                 double sec;
   4022 
   4023                 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
   4024                 if (sec < 0.0) {
   4025 		    xmlSchemaFreeValue(p1);
   4026 		    xmlSchemaFreeValue(q1);
   4027                     return -1;
   4028 		} else {
   4029 		    int ret = 0;
   4030                     /* normalize y - 14:00 */
   4031                     q2 = xmlSchemaDateNormalize(y, -(14 * SECS_PER_HOUR));
   4032                     q2d = _xmlSchemaDateCastYMToDays(q2) + q2->value.date.day;
   4033                     if (p1d > q2d)
   4034                         ret = 1;
   4035                     else if (p1d == q2d) {
   4036                         sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q2);
   4037                         if (sec > 0.0)
   4038                             ret = 1;
   4039                         else
   4040                             ret = 2; /* indeterminate */
   4041                     }
   4042 		    xmlSchemaFreeValue(p1);
   4043 		    xmlSchemaFreeValue(q1);
   4044 		    xmlSchemaFreeValue(q2);
   4045 		    if (ret != 0)
   4046 		        return(ret);
   4047                 }
   4048             } else {
   4049 		xmlSchemaFreeValue(p1);
   4050 		xmlSchemaFreeValue(q1);
   4051 	    }
   4052         }
   4053     } else if (y->value.date.tz_flag) {
   4054         q1 = xmlSchemaDateNormalize(y, 0);
   4055         q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
   4056 
   4057         /* normalize x - 14:00 */
   4058         p1 = xmlSchemaDateNormalize(x, -(14 * SECS_PER_HOUR));
   4059         p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
   4060 
   4061         if (p1d < q1d) {
   4062 	    xmlSchemaFreeValue(p1);
   4063 	    xmlSchemaFreeValue(q1);
   4064             return -1;
   4065 	} else if (p1d == q1d) {
   4066             double sec;
   4067 
   4068             sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
   4069             if (sec < 0.0) {
   4070 		xmlSchemaFreeValue(p1);
   4071 		xmlSchemaFreeValue(q1);
   4072                 return -1;
   4073 	    } else {
   4074 	        int ret = 0;
   4075                 /* normalize x + 14:00 */
   4076                 p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR));
   4077                 p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day;
   4078 
   4079                 if (p2d > q1d) {
   4080                     ret = 1;
   4081 		} else if (p2d == q1d) {
   4082                     sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1);
   4083                     if (sec > 0.0)
   4084                         ret = 1;
   4085                     else
   4086                         ret = 2; /* indeterminate */
   4087                 }
   4088 		xmlSchemaFreeValue(p1);
   4089 		xmlSchemaFreeValue(q1);
   4090 		xmlSchemaFreeValue(p2);
   4091 		if (ret != 0)
   4092 		    return(ret);
   4093             }
   4094 	} else {
   4095 	    xmlSchemaFreeValue(p1);
   4096 	    xmlSchemaFreeValue(q1);
   4097         }
   4098     }
   4099 
   4100     /*
   4101      * if the same type then calculate the difference
   4102      */
   4103     if (x->type == y->type) {
   4104         int ret = 0;
   4105         q1 = xmlSchemaDateNormalize(y, 0);
   4106         q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
   4107 
   4108         p1 = xmlSchemaDateNormalize(x, 0);
   4109         p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
   4110 
   4111         if (p1d < q1d) {
   4112             ret = -1;
   4113 	} else if (p1d > q1d) {
   4114             ret = 1;
   4115 	} else {
   4116             double sec;
   4117 
   4118             sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
   4119             if (sec < 0.0)
   4120                 ret = -1;
   4121             else if (sec > 0.0)
   4122                 ret = 1;
   4123 
   4124         }
   4125 	xmlSchemaFreeValue(p1);
   4126 	xmlSchemaFreeValue(q1);
   4127         return(ret);
   4128     }
   4129 
   4130     switch (x->type) {
   4131         case XML_SCHEMAS_DATETIME:
   4132             xmask = 0xf;
   4133             break;
   4134         case XML_SCHEMAS_DATE:
   4135             xmask = 0x7;
   4136             break;
   4137         case XML_SCHEMAS_GYEAR:
   4138             xmask = 0x1;
   4139             break;
   4140         case XML_SCHEMAS_GMONTH:
   4141             xmask = 0x2;
   4142             break;
   4143         case XML_SCHEMAS_GDAY:
   4144             xmask = 0x3;
   4145             break;
   4146         case XML_SCHEMAS_GYEARMONTH:
   4147             xmask = 0x3;
   4148             break;
   4149         case XML_SCHEMAS_GMONTHDAY:
   4150             xmask = 0x6;
   4151             break;
   4152         case XML_SCHEMAS_TIME:
   4153             xmask = 0x8;
   4154             break;
   4155         default:
   4156             xmask = 0;
   4157             break;
   4158     }
   4159 
   4160     switch (y->type) {
   4161         case XML_SCHEMAS_DATETIME:
   4162             ymask = 0xf;
   4163             break;
   4164         case XML_SCHEMAS_DATE:
   4165             ymask = 0x7;
   4166             break;
   4167         case XML_SCHEMAS_GYEAR:
   4168             ymask = 0x1;
   4169             break;
   4170         case XML_SCHEMAS_GMONTH:
   4171             ymask = 0x2;
   4172             break;
   4173         case XML_SCHEMAS_GDAY:
   4174             ymask = 0x3;
   4175             break;
   4176         case XML_SCHEMAS_GYEARMONTH:
   4177             ymask = 0x3;
   4178             break;
   4179         case XML_SCHEMAS_GMONTHDAY:
   4180             ymask = 0x6;
   4181             break;
   4182         case XML_SCHEMAS_TIME:
   4183             ymask = 0x8;
   4184             break;
   4185         default:
   4186             ymask = 0;
   4187             break;
   4188     }
   4189 
   4190     xor_mask = xmask ^ ymask;           /* mark type differences */
   4191     and_mask = xmask & ymask;           /* mark field specification */
   4192 
   4193     /* year */
   4194     if (xor_mask & 1)
   4195         return 2; /* indeterminate */
   4196     else if (and_mask & 1) {
   4197         if (x->value.date.year < y->value.date.year)
   4198             return -1;
   4199         else if (x->value.date.year > y->value.date.year)
   4200             return 1;
   4201     }
   4202 
   4203     /* month */
   4204     if (xor_mask & 2)
   4205         return 2; /* indeterminate */
   4206     else if (and_mask & 2) {
   4207         if (x->value.date.mon < y->value.date.mon)
   4208             return -1;
   4209         else if (x->value.date.mon > y->value.date.mon)
   4210             return 1;
   4211     }
   4212 
   4213     /* day */
   4214     if (xor_mask & 4)
   4215         return 2; /* indeterminate */
   4216     else if (and_mask & 4) {
   4217         if (x->value.date.day < y->value.date.day)
   4218             return -1;
   4219         else if (x->value.date.day > y->value.date.day)
   4220             return 1;
   4221     }
   4222 
   4223     /* time */
   4224     if (xor_mask & 8)
   4225         return 2; /* indeterminate */
   4226     else if (and_mask & 8) {
   4227         if (x->value.date.hour < y->value.date.hour)
   4228             return -1;
   4229         else if (x->value.date.hour > y->value.date.hour)
   4230             return 1;
   4231         else if (x->value.date.min < y->value.date.min)
   4232             return -1;
   4233         else if (x->value.date.min > y->value.date.min)
   4234             return 1;
   4235         else if (x->value.date.sec < y->value.date.sec)
   4236             return -1;
   4237         else if (x->value.date.sec > y->value.date.sec)
   4238             return 1;
   4239     }
   4240 
   4241     return 0;
   4242 }
   4243 
   4244 /**
   4245  * xmlSchemaComparePreserveReplaceStrings:
   4246  * @x:  a first string value
   4247  * @y:  a second string value
   4248  * @invert: inverts the result if x < y or x > y.
   4249  *
   4250  * Compare 2 string for their normalized values.
   4251  * @x is a string with whitespace of "preserve", @y is
   4252  * a string with a whitespace of "replace". I.e. @x could
   4253  * be an "xsd:string" and @y an "xsd:normalizedString".
   4254  *
   4255  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
   4256  * case of error
   4257  */
   4258 static int
   4259 xmlSchemaComparePreserveReplaceStrings(const xmlChar *x,
   4260 				       const xmlChar *y,
   4261 				       int invert)
   4262 {
   4263     int tmp;
   4264 
   4265     while ((*x != 0) && (*y != 0)) {
   4266 	if (IS_WSP_REPLACE_CH(*y)) {
   4267 	    if (! IS_WSP_SPACE_CH(*x)) {
   4268 		if ((*x - 0x20) < 0) {
   4269 		    if (invert)
   4270 			return(1);
   4271 		    else
   4272 			return(-1);
   4273 		} else {
   4274 		    if (invert)
   4275 			return(-1);
   4276 		    else
   4277 			return(1);
   4278 		}
   4279 	    }
   4280 	} else {
   4281 	    tmp = *x - *y;
   4282 	    if (tmp < 0) {
   4283 		if (invert)
   4284 		    return(1);
   4285 		else
   4286 		    return(-1);
   4287 	    }
   4288 	    if (tmp > 0) {
   4289 		if (invert)
   4290 		    return(-1);
   4291 		else
   4292 		    return(1);
   4293 	    }
   4294 	}
   4295 	x++;
   4296 	y++;
   4297     }
   4298     if (*x != 0) {
   4299 	if (invert)
   4300 	    return(-1);
   4301 	else
   4302 	    return(1);
   4303     }
   4304     if (*y != 0) {
   4305 	if (invert)
   4306 	    return(1);
   4307 	else
   4308 	    return(-1);
   4309     }
   4310     return(0);
   4311 }
   4312 
   4313 /**
   4314  * xmlSchemaComparePreserveCollapseStrings:
   4315  * @x:  a first string value
   4316  * @y:  a second string value
   4317  *
   4318  * Compare 2 string for their normalized values.
   4319  * @x is a string with whitespace of "preserve", @y is
   4320  * a string with a whitespace of "collapse". I.e. @x could
   4321  * be an "xsd:string" and @y an "xsd:normalizedString".
   4322  *
   4323  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
   4324  * case of error
   4325  */
   4326 static int
   4327 xmlSchemaComparePreserveCollapseStrings(const xmlChar *x,
   4328 				        const xmlChar *y,
   4329 					int invert)
   4330 {
   4331     int tmp;
   4332 
   4333     /*
   4334     * Skip leading blank chars of the collapsed string.
   4335     */
   4336     while IS_WSP_BLANK_CH(*y)
   4337 	y++;
   4338 
   4339     while ((*x != 0) && (*y != 0)) {
   4340 	if IS_WSP_BLANK_CH(*y) {
   4341 	    if (! IS_WSP_SPACE_CH(*x)) {
   4342 		/*
   4343 		* The yv character would have been replaced to 0x20.
   4344 		*/
   4345 		if ((*x - 0x20) < 0) {
   4346 		    if (invert)
   4347 			return(1);
   4348 		    else
   4349 			return(-1);
   4350 		} else {
   4351 		    if (invert)
   4352 			return(-1);
   4353 		    else
   4354 			return(1);
   4355 		}
   4356 	    }
   4357 	    x++;
   4358 	    y++;
   4359 	    /*
   4360 	    * Skip contiguous blank chars of the collapsed string.
   4361 	    */
   4362 	    while IS_WSP_BLANK_CH(*y)
   4363 		y++;
   4364 	} else {
   4365 	    tmp = *x++ - *y++;
   4366 	    if (tmp < 0) {
   4367 		if (invert)
   4368 		    return(1);
   4369 		else
   4370 		    return(-1);
   4371 	    }
   4372 	    if (tmp > 0) {
   4373 		if (invert)
   4374 		    return(-1);
   4375 		else
   4376 		    return(1);
   4377 	    }
   4378 	}
   4379     }
   4380     if (*x != 0) {
   4381 	 if (invert)
   4382 	     return(-1);
   4383 	 else
   4384 	     return(1);
   4385     }
   4386     if (*y != 0) {
   4387 	/*
   4388 	* Skip trailing blank chars of the collapsed string.
   4389 	*/
   4390 	while IS_WSP_BLANK_CH(*y)
   4391 	    y++;
   4392 	if (*y != 0) {
   4393 	    if (invert)
   4394 		return(1);
   4395 	    else
   4396 		return(-1);
   4397 	}
   4398     }
   4399     return(0);
   4400 }
   4401 
   4402 /**
   4403  * xmlSchemaComparePreserveCollapseStrings:
   4404  * @x:  a first string value
   4405  * @y:  a second string value
   4406  *
   4407  * Compare 2 string for their normalized values.
   4408  * @x is a string with whitespace of "preserve", @y is
   4409  * a string with a whitespace of "collapse". I.e. @x could
   4410  * be an "xsd:string" and @y an "xsd:normalizedString".
   4411  *
   4412  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
   4413  * case of error
   4414  */
   4415 static int
   4416 xmlSchemaCompareReplaceCollapseStrings(const xmlChar *x,
   4417 				       const xmlChar *y,
   4418 				       int invert)
   4419 {
   4420     int tmp;
   4421 
   4422     /*
   4423     * Skip leading blank chars of the collapsed string.
   4424     */
   4425     while IS_WSP_BLANK_CH(*y)
   4426 	y++;
   4427 
   4428     while ((*x != 0) && (*y != 0)) {
   4429 	if IS_WSP_BLANK_CH(*y) {
   4430 	    if (! IS_WSP_BLANK_CH(*x)) {
   4431 		/*
   4432 		* The yv character would have been replaced to 0x20.
   4433 		*/
   4434 		if ((*x - 0x20) < 0) {
   4435 		    if (invert)
   4436 			return(1);
   4437 		    else
   4438 			return(-1);
   4439 		} else {
   4440 		    if (invert)
   4441 			return(-1);
   4442 		    else
   4443 			return(1);
   4444 		}
   4445 	    }
   4446 	    x++;
   4447 	    y++;
   4448 	    /*
   4449 	    * Skip contiguous blank chars of the collapsed string.
   4450 	    */
   4451 	    while IS_WSP_BLANK_CH(*y)
   4452 		y++;
   4453 	} else {
   4454 	    if IS_WSP_BLANK_CH(*x) {
   4455 		/*
   4456 		* The xv character would have been replaced to 0x20.
   4457 		*/
   4458 		if ((0x20 - *y) < 0) {
   4459 		    if (invert)
   4460 			return(1);
   4461 		    else
   4462 			return(-1);
   4463 		} else {
   4464 		    if (invert)
   4465 			return(-1);
   4466 		    else
   4467 			return(1);
   4468 		}
   4469 	    }
   4470 	    tmp = *x++ - *y++;
   4471 	    if (tmp < 0)
   4472 		return(-1);
   4473 	    if (tmp > 0)
   4474 		return(1);
   4475 	}
   4476     }
   4477     if (*x != 0) {
   4478 	 if (invert)
   4479 	     return(-1);
   4480 	 else
   4481 	     return(1);
   4482     }
   4483     if (*y != 0) {
   4484 	/*
   4485 	* Skip trailing blank chars of the collapsed string.
   4486 	*/
   4487 	while IS_WSP_BLANK_CH(*y)
   4488 	    y++;
   4489 	if (*y != 0) {
   4490 	    if (invert)
   4491 		return(1);
   4492 	    else
   4493 		return(-1);
   4494 	}
   4495     }
   4496     return(0);
   4497 }
   4498 
   4499 
   4500 /**
   4501  * xmlSchemaCompareReplacedStrings:
   4502  * @x:  a first string value
   4503  * @y:  a second string value
   4504  *
   4505  * Compare 2 string for their normalized values.
   4506  *
   4507  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
   4508  * case of error
   4509  */
   4510 static int
   4511 xmlSchemaCompareReplacedStrings(const xmlChar *x,
   4512 				const xmlChar *y)
   4513 {
   4514     int tmp;
   4515 
   4516     while ((*x != 0) && (*y != 0)) {
   4517 	if IS_WSP_BLANK_CH(*y) {
   4518 	    if (! IS_WSP_BLANK_CH(*x)) {
   4519 		if ((*x - 0x20) < 0)
   4520 		    return(-1);
   4521 		else
   4522 		    return(1);
   4523 	    }
   4524 	} else {
   4525 	    if IS_WSP_BLANK_CH(*x) {
   4526 		if ((0x20 - *y) < 0)
   4527 		    return(-1);
   4528 		else
   4529 		    return(1);
   4530 	    }
   4531 	    tmp = *x - *y;
   4532 	    if (tmp < 0)
   4533 		return(-1);
   4534 	    if (tmp > 0)
   4535 		return(1);
   4536 	}
   4537 	x++;
   4538 	y++;
   4539     }
   4540     if (*x != 0)
   4541         return(1);
   4542     if (*y != 0)
   4543         return(-1);
   4544     return(0);
   4545 }
   4546 
   4547 /**
   4548  * xmlSchemaCompareNormStrings:
   4549  * @x:  a first string value
   4550  * @y:  a second string value
   4551  *
   4552  * Compare 2 string for their normalized values.
   4553  *
   4554  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
   4555  * case of error
   4556  */
   4557 static int
   4558 xmlSchemaCompareNormStrings(const xmlChar *x,
   4559 			    const xmlChar *y) {
   4560     int tmp;
   4561 
   4562     while (IS_BLANK_CH(*x)) x++;
   4563     while (IS_BLANK_CH(*y)) y++;
   4564     while ((*x != 0) && (*y != 0)) {
   4565 	if (IS_BLANK_CH(*x)) {
   4566 	    if (!IS_BLANK_CH(*y)) {
   4567 		tmp = *x - *y;
   4568 		return(tmp);
   4569 	    }
   4570 	    while (IS_BLANK_CH(*x)) x++;
   4571 	    while (IS_BLANK_CH(*y)) y++;
   4572 	} else {
   4573 	    tmp = *x++ - *y++;
   4574 	    if (tmp < 0)
   4575 		return(-1);
   4576 	    if (tmp > 0)
   4577 		return(1);
   4578 	}
   4579     }
   4580     if (*x != 0) {
   4581 	while (IS_BLANK_CH(*x)) x++;
   4582 	if (*x != 0)
   4583 	    return(1);
   4584     }
   4585     if (*y != 0) {
   4586 	while (IS_BLANK_CH(*y)) y++;
   4587 	if (*y != 0)
   4588 	    return(-1);
   4589     }
   4590     return(0);
   4591 }
   4592 
   4593 /**
   4594  * xmlSchemaCompareFloats:
   4595  * @x:  a first float or double value
   4596  * @y:  a second float or double value
   4597  *
   4598  * Compare 2 values
   4599  *
   4600  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
   4601  * case of error
   4602  */
   4603 static int
   4604 xmlSchemaCompareFloats(xmlSchemaValPtr x, xmlSchemaValPtr y) {
   4605     double d1, d2;
   4606 
   4607     if ((x == NULL) || (y == NULL))
   4608 	return(-2);
   4609 
   4610     /*
   4611      * Cast everything to doubles.
   4612      */
   4613     if (x->type == XML_SCHEMAS_DOUBLE)
   4614 	d1 = x->value.d;
   4615     else if (x->type == XML_SCHEMAS_FLOAT)
   4616 	d1 = x->value.f;
   4617     else
   4618 	return(-2);
   4619 
   4620     if (y->type == XML_SCHEMAS_DOUBLE)
   4621 	d2 = y->value.d;
   4622     else if (y->type == XML_SCHEMAS_FLOAT)
   4623 	d2 = y->value.f;
   4624     else
   4625 	return(-2);
   4626 
   4627     /*
   4628      * Check for special cases.
   4629      */
   4630     if (xmlXPathIsNaN(d1)) {
   4631 	if (xmlXPathIsNaN(d2))
   4632 	    return(0);
   4633 	return(1);
   4634     }
   4635     if (xmlXPathIsNaN(d2))
   4636 	return(-1);
   4637     if (d1 == xmlXPathPINF) {
   4638 	if (d2 == xmlXPathPINF)
   4639 	    return(0);
   4640         return(1);
   4641     }
   4642     if (d2 == xmlXPathPINF)
   4643         return(-1);
   4644     if (d1 == xmlXPathNINF) {
   4645 	if (d2 == xmlXPathNINF)
   4646 	    return(0);
   4647         return(-1);
   4648     }
   4649     if (d2 == xmlXPathNINF)
   4650         return(1);
   4651 
   4652     /*
   4653      * basic tests, the last one we should have equality, but
   4654      * portability is more important than speed and handling
   4655      * NaN or Inf in a portable way is always a challenge, so ...
   4656      */
   4657     if (d1 < d2)
   4658 	return(-1);
   4659     if (d1 > d2)
   4660 	return(1);
   4661     if (d1 == d2)
   4662 	return(0);
   4663     return(2);
   4664 }
   4665 
   4666 /**
   4667  * xmlSchemaCompareValues:
   4668  * @x:  a first value
   4669  * @xvalue: the first value as a string (optional)
   4670  * @xwtsp: the whitespace type
   4671  * @y:  a second value
   4672  * @xvalue: the second value as a string (optional)
   4673  * @ywtsp: the whitespace type
   4674  *
   4675  * Compare 2 values
   4676  *
   4677  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, 3 if not
   4678  * comparable and -2 in case of error
   4679  */
   4680 static int
   4681 xmlSchemaCompareValuesInternal(xmlSchemaValType xtype,
   4682 			       xmlSchemaValPtr x,
   4683 			       const xmlChar *xvalue,
   4684 			       xmlSchemaWhitespaceValueType xws,
   4685 			       xmlSchemaValType ytype,
   4686 			       xmlSchemaValPtr y,
   4687 			       const xmlChar *yvalue,
   4688 			       xmlSchemaWhitespaceValueType yws)
   4689 {
   4690     switch (xtype) {
   4691 	case XML_SCHEMAS_UNKNOWN:
   4692 	case XML_SCHEMAS_ANYTYPE:
   4693 	    return(-2);
   4694         case XML_SCHEMAS_INTEGER:
   4695         case XML_SCHEMAS_NPINTEGER:
   4696         case XML_SCHEMAS_NINTEGER:
   4697         case XML_SCHEMAS_NNINTEGER:
   4698         case XML_SCHEMAS_PINTEGER:
   4699         case XML_SCHEMAS_INT:
   4700         case XML_SCHEMAS_UINT:
   4701         case XML_SCHEMAS_LONG:
   4702         case XML_SCHEMAS_ULONG:
   4703         case XML_SCHEMAS_SHORT:
   4704         case XML_SCHEMAS_USHORT:
   4705         case XML_SCHEMAS_BYTE:
   4706         case XML_SCHEMAS_UBYTE:
   4707 	case XML_SCHEMAS_DECIMAL:
   4708 	    if ((x == NULL) || (y == NULL))
   4709 		return(-2);
   4710 	    if (ytype == xtype)
   4711 		return(xmlSchemaCompareDecimals(x, y));
   4712 	    if ((ytype == XML_SCHEMAS_DECIMAL) ||
   4713 		(ytype == XML_SCHEMAS_INTEGER) ||
   4714 		(ytype == XML_SCHEMAS_NPINTEGER) ||
   4715 		(ytype == XML_SCHEMAS_NINTEGER) ||
   4716 		(ytype == XML_SCHEMAS_NNINTEGER) ||
   4717 		(ytype == XML_SCHEMAS_PINTEGER) ||
   4718 		(ytype == XML_SCHEMAS_INT) ||
   4719 		(ytype == XML_SCHEMAS_UINT) ||
   4720 		(ytype == XML_SCHEMAS_LONG) ||
   4721 		(ytype == XML_SCHEMAS_ULONG) ||
   4722 		(ytype == XML_SCHEMAS_SHORT) ||
   4723 		(ytype == XML_SCHEMAS_USHORT) ||
   4724 		(ytype == XML_SCHEMAS_BYTE) ||
   4725 		(ytype == XML_SCHEMAS_UBYTE))
   4726 		return(xmlSchemaCompareDecimals(x, y));
   4727 	    return(-2);
   4728         case XML_SCHEMAS_DURATION:
   4729 	    if ((x == NULL) || (y == NULL))
   4730 		return(-2);
   4731 	    if (ytype == XML_SCHEMAS_DURATION)
   4732                 return(xmlSchemaCompareDurations(x, y));
   4733             return(-2);
   4734         case XML_SCHEMAS_TIME:
   4735         case XML_SCHEMAS_GDAY:
   4736         case XML_SCHEMAS_GMONTH:
   4737         case XML_SCHEMAS_GMONTHDAY:
   4738         case XML_SCHEMAS_GYEAR:
   4739         case XML_SCHEMAS_GYEARMONTH:
   4740         case XML_SCHEMAS_DATE:
   4741         case XML_SCHEMAS_DATETIME:
   4742 	    if ((x == NULL) || (y == NULL))
   4743 		return(-2);
   4744             if ((ytype == XML_SCHEMAS_DATETIME)  ||
   4745                 (ytype == XML_SCHEMAS_TIME)      ||
   4746                 (ytype == XML_SCHEMAS_GDAY)      ||
   4747                 (ytype == XML_SCHEMAS_GMONTH)    ||
   4748                 (ytype == XML_SCHEMAS_GMONTHDAY) ||
   4749                 (ytype == XML_SCHEMAS_GYEAR)     ||
   4750                 (ytype == XML_SCHEMAS_DATE)      ||
   4751                 (ytype == XML_SCHEMAS_GYEARMONTH))
   4752                 return (xmlSchemaCompareDates(x, y));
   4753             return (-2);
   4754 	/*
   4755 	* Note that we will support comparison of string types against
   4756 	* anySimpleType as well.
   4757 	*/
   4758 	case XML_SCHEMAS_ANYSIMPLETYPE:
   4759 	case XML_SCHEMAS_STRING:
   4760         case XML_SCHEMAS_NORMSTRING:
   4761         case XML_SCHEMAS_TOKEN:
   4762         case XML_SCHEMAS_LANGUAGE:
   4763         case XML_SCHEMAS_NMTOKEN:
   4764         case XML_SCHEMAS_NAME:
   4765         case XML_SCHEMAS_NCNAME:
   4766         case XML_SCHEMAS_ID:
   4767         case XML_SCHEMAS_IDREF:
   4768         case XML_SCHEMAS_ENTITY:
   4769         case XML_SCHEMAS_ANYURI:
   4770 	{
   4771 	    const xmlChar *xv, *yv;
   4772 
   4773 	    if (x == NULL)
   4774 		xv = xvalue;
   4775 	    else
   4776 		xv = x->value.str;
   4777 	    if (y == NULL)
   4778 		yv = yvalue;
   4779 	    else
   4780 		yv = y->value.str;
   4781 	    /*
   4782 	    * TODO: Compare those against QName.
   4783 	    */
   4784 	    if (ytype == XML_SCHEMAS_QNAME) {
   4785 		TODO
   4786 		if (y == NULL)
   4787 		    return(-2);
   4788 		return (-2);
   4789 	    }
   4790             if ((ytype == XML_SCHEMAS_ANYSIMPLETYPE) ||
   4791 		(ytype == XML_SCHEMAS_STRING) ||
   4792 		(ytype == XML_SCHEMAS_NORMSTRING) ||
   4793                 (ytype == XML_SCHEMAS_TOKEN) ||
   4794                 (ytype == XML_SCHEMAS_LANGUAGE) ||
   4795                 (ytype == XML_SCHEMAS_NMTOKEN) ||
   4796                 (ytype == XML_SCHEMAS_NAME) ||
   4797                 (ytype == XML_SCHEMAS_NCNAME) ||
   4798                 (ytype == XML_SCHEMAS_ID) ||
   4799                 (ytype == XML_SCHEMAS_IDREF) ||
   4800                 (ytype == XML_SCHEMAS_ENTITY) ||
   4801                 (ytype == XML_SCHEMAS_ANYURI)) {
   4802 
   4803 		if (xws == XML_SCHEMA_WHITESPACE_PRESERVE) {
   4804 
   4805 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) {
   4806 			/* TODO: What about x < y or x > y. */
   4807 			if (xmlStrEqual(xv, yv))
   4808 			    return (0);
   4809 			else
   4810 			    return (2);
   4811 		    } else if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
   4812 			return (xmlSchemaComparePreserveReplaceStrings(xv, yv, 0));
   4813 		    else if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
   4814 			return (xmlSchemaComparePreserveCollapseStrings(xv, yv, 0));
   4815 
   4816 		} else if (xws == XML_SCHEMA_WHITESPACE_REPLACE) {
   4817 
   4818 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
   4819 			return (xmlSchemaComparePreserveReplaceStrings(yv, xv, 1));
   4820 		    if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
   4821 			return (xmlSchemaCompareReplacedStrings(xv, yv));
   4822 		    if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
   4823 			return (xmlSchemaCompareReplaceCollapseStrings(xv, yv, 0));
   4824 
   4825 		} else if (xws == XML_SCHEMA_WHITESPACE_COLLAPSE) {
   4826 
   4827 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
   4828 			return (xmlSchemaComparePreserveCollapseStrings(yv, xv, 1));
   4829 		    if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
   4830 			return (xmlSchemaCompareReplaceCollapseStrings(yv, xv, 1));
   4831 		    if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
   4832 			return (xmlSchemaCompareNormStrings(xv, yv));
   4833 		} else
   4834 		    return (-2);
   4835 
   4836 	    }
   4837             return (-2);
   4838 	}
   4839         case XML_SCHEMAS_QNAME:
   4840 	case XML_SCHEMAS_NOTATION:
   4841 	    if ((x == NULL) || (y == NULL))
   4842 		return(-2);
   4843             if ((ytype == XML_SCHEMAS_QNAME) ||
   4844 		(ytype == XML_SCHEMAS_NOTATION)) {
   4845 		if ((xmlStrEqual(x->value.qname.name, y->value.qname.name)) &&
   4846 		    (xmlStrEqual(x->value.qname.uri, y->value.qname.uri)))
   4847 		    return(0);
   4848 		return(2);
   4849 	    }
   4850 	    return (-2);
   4851         case XML_SCHEMAS_FLOAT:
   4852         case XML_SCHEMAS_DOUBLE:
   4853 	    if ((x == NULL) || (y == NULL))
   4854 		return(-2);
   4855             if ((ytype == XML_SCHEMAS_FLOAT) ||
   4856                 (ytype == XML_SCHEMAS_DOUBLE))
   4857                 return (xmlSchemaCompareFloats(x, y));
   4858             return (-2);
   4859         case XML_SCHEMAS_BOOLEAN:
   4860 	    if ((x == NULL) || (y == NULL))
   4861 		return(-2);
   4862             if (ytype == XML_SCHEMAS_BOOLEAN) {
   4863 		if (x->value.b == y->value.b)
   4864 		    return(0);
   4865 		if (x->value.b == 0)
   4866 		    return(-1);
   4867 		return(1);
   4868 	    }
   4869 	    return (-2);
   4870         case XML_SCHEMAS_HEXBINARY:
   4871 	    if ((x == NULL) || (y == NULL))
   4872 		return(-2);
   4873             if (ytype == XML_SCHEMAS_HEXBINARY) {
   4874 	        if (x->value.hex.total == y->value.hex.total) {
   4875 		    int ret = xmlStrcmp(x->value.hex.str, y->value.hex.str);
   4876 		    if (ret > 0)
   4877 			return(1);
   4878 		    else if (ret == 0)
   4879 			return(0);
   4880 		}
   4881 		else if (x->value.hex.total > y->value.hex.total)
   4882 		    return(1);
   4883 
   4884 		return(-1);
   4885             }
   4886             return (-2);
   4887         case XML_SCHEMAS_BASE64BINARY:
   4888 	    if ((x == NULL) || (y == NULL))
   4889 		return(-2);
   4890             if (ytype == XML_SCHEMAS_BASE64BINARY) {
   4891                 if (x->value.base64.total == y->value.base64.total) {
   4892                     int ret = xmlStrcmp(x->value.base64.str,
   4893 		                        y->value.base64.str);
   4894                     if (ret > 0)
   4895                         return(1);
   4896                     else if (ret == 0)
   4897                         return(0);
   4898 		    else
   4899 		        return(-1);
   4900                 }
   4901                 else if (x->value.base64.total > y->value.base64.total)
   4902                     return(1);
   4903                 else
   4904                     return(-1);
   4905             }
   4906             return (-2);
   4907         case XML_SCHEMAS_IDREFS:
   4908         case XML_SCHEMAS_ENTITIES:
   4909         case XML_SCHEMAS_NMTOKENS:
   4910 	    TODO
   4911 	    break;
   4912     }
   4913     return -2;
   4914 }
   4915 
   4916 /**
   4917  * xmlSchemaCompareValues:
   4918  * @x:  a first value
   4919  * @y:  a second value
   4920  *
   4921  * Compare 2 values
   4922  *
   4923  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
   4924  * case of error
   4925  */
   4926 int
   4927 xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
   4928     xmlSchemaWhitespaceValueType xws, yws;
   4929 
   4930     if ((x == NULL) || (y == NULL))
   4931         return(-2);
   4932     if (x->type == XML_SCHEMAS_STRING)
   4933 	xws = XML_SCHEMA_WHITESPACE_PRESERVE;
   4934     else if (x->type == XML_SCHEMAS_NORMSTRING)
   4935         xws = XML_SCHEMA_WHITESPACE_REPLACE;
   4936     else
   4937         xws = XML_SCHEMA_WHITESPACE_COLLAPSE;
   4938 
   4939     if (y->type == XML_SCHEMAS_STRING)
   4940 	yws = XML_SCHEMA_WHITESPACE_PRESERVE;
   4941     else if (y->type == XML_SCHEMAS_NORMSTRING)
   4942         yws = XML_SCHEMA_WHITESPACE_REPLACE;
   4943     else
   4944         yws = XML_SCHEMA_WHITESPACE_COLLAPSE;
   4945 
   4946     return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
   4947 	y, NULL, yws));
   4948 }
   4949 
   4950 /**
   4951  * xmlSchemaCompareValuesWhtsp:
   4952  * @x:  a first value
   4953  * @xws: the whitespace value of x
   4954  * @y:  a second value
   4955  * @yws: the whitespace value of y
   4956  *
   4957  * Compare 2 values
   4958  *
   4959  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
   4960  * case of error
   4961  */
   4962 int
   4963 xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x,
   4964 			    xmlSchemaWhitespaceValueType xws,
   4965 			    xmlSchemaValPtr y,
   4966 			    xmlSchemaWhitespaceValueType yws)
   4967 {
   4968     if ((x == NULL) || (y == NULL))
   4969 	return(-2);
   4970     return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
   4971 	y, NULL, yws));
   4972 }
   4973 
   4974 /**
   4975  * xmlSchemaCompareValuesWhtspExt:
   4976  * @x:  a first value
   4977  * @xws: the whitespace value of x
   4978  * @y:  a second value
   4979  * @yws: the whitespace value of y
   4980  *
   4981  * Compare 2 values
   4982  *
   4983  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
   4984  * case of error
   4985  */
   4986 static int
   4987 xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype,
   4988 			       xmlSchemaValPtr x,
   4989 			       const xmlChar *xvalue,
   4990 			       xmlSchemaWhitespaceValueType xws,
   4991 			       xmlSchemaValType ytype,
   4992 			       xmlSchemaValPtr y,
   4993 			       const xmlChar *yvalue,
   4994 			       xmlSchemaWhitespaceValueType yws)
   4995 {
   4996     return(xmlSchemaCompareValuesInternal(xtype, x, xvalue, xws, ytype, y,
   4997 	yvalue, yws));
   4998 }
   4999 
   5000 /**
   5001  * xmlSchemaNormLen:
   5002  * @value:  a string
   5003  *
   5004  * Computes the UTF8 length of the normalized value of the string
   5005  *
   5006  * Returns the length or -1 in case of error.
   5007  */
   5008 static int
   5009 xmlSchemaNormLen(const xmlChar *value) {
   5010     const xmlChar *utf;
   5011     int ret = 0;
   5012 
   5013     if (value == NULL)
   5014 	return(-1);
   5015     utf = value;
   5016     while (IS_BLANK_CH(*utf)) utf++;
   5017     while (*utf != 0) {
   5018 	if (utf[0] & 0x80) {
   5019 	    if ((utf[1] & 0xc0) != 0x80)
   5020 		return(-1);
   5021 	    if ((utf[0] & 0xe0) == 0xe0) {
   5022 		if ((utf[2] & 0xc0) != 0x80)
   5023 		    return(-1);
   5024 		if ((utf[0] & 0xf0) == 0xf0) {
   5025 		    if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
   5026 			return(-1);
   5027 		    utf += 4;
   5028 		} else {
   5029 		    utf += 3;
   5030 		}
   5031 	    } else {
   5032 		utf += 2;
   5033 	    }
   5034 	} else if (IS_BLANK_CH(*utf)) {
   5035 	    while (IS_BLANK_CH(*utf)) utf++;
   5036 	    if (*utf == 0)
   5037 		break;
   5038 	} else {
   5039 	    utf++;
   5040 	}
   5041 	ret++;
   5042     }
   5043     return(ret);
   5044 }
   5045 
   5046 /**
   5047  * xmlSchemaGetFacetValueAsULong:
   5048  * @facet: an schemas type facet
   5049  *
   5050  * Extract the value of a facet
   5051  *
   5052  * Returns the value as a long
   5053  */
   5054 unsigned long
   5055 xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet)
   5056 {
   5057     /*
   5058     * TODO: Check if this is a decimal.
   5059     */
   5060     if (facet == NULL)
   5061         return 0;
   5062     return ((unsigned long) facet->val->value.decimal.lo);
   5063 }
   5064 
   5065 /**
   5066  * xmlSchemaValidateListSimpleTypeFacet:
   5067  * @facet:  the facet to check
   5068  * @value:  the lexical repr of the value to validate
   5069  * @actualLen:  the number of list items
   5070  * @expectedLen: the resulting expected number of list items
   5071  *
   5072  * Checks the value of a list simple type against a facet.
   5073  *
   5074  * Returns 0 if the value is valid, a positive error code
   5075  * number otherwise and -1 in case of an internal error.
   5076  */
   5077 int
   5078 xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet,
   5079 				     const xmlChar *value,
   5080 				     unsigned long actualLen,
   5081 				     unsigned long *expectedLen)
   5082 {
   5083     if (facet == NULL)
   5084         return(-1);
   5085     /*
   5086     * TODO: Check if this will work with large numbers.
   5087     * (compare value.decimal.mi and value.decimal.hi as well?).
   5088     */
   5089     if (facet->type == XML_SCHEMA_FACET_LENGTH) {
   5090 	if (actualLen != facet->val->value.decimal.lo) {
   5091 	    if (expectedLen != NULL)
   5092 		*expectedLen = facet->val->value.decimal.lo;
   5093 	    return (XML_SCHEMAV_CVC_LENGTH_VALID);
   5094 	}
   5095     } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
   5096 	if (actualLen < facet->val->value.decimal.lo) {
   5097 	    if (expectedLen != NULL)
   5098 		*expectedLen = facet->val->value.decimal.lo;
   5099 	    return (XML_SCHEMAV_CVC_MINLENGTH_VALID);
   5100 	}
   5101     } else if (facet->type == XML_SCHEMA_FACET_MAXLENGTH) {
   5102 	if (actualLen > facet->val->value.decimal.lo) {
   5103 	    if (expectedLen != NULL)
   5104 		*expectedLen = facet->val->value.decimal.lo;
   5105 	    return (XML_SCHEMAV_CVC_MAXLENGTH_VALID);
   5106 	}
   5107     } else
   5108 	/*
   5109 	* NOTE: That we can pass NULL as xmlSchemaValPtr to
   5110 	* xmlSchemaValidateFacet, since the remaining facet types
   5111 	* are: XML_SCHEMA_FACET_PATTERN, XML_SCHEMA_FACET_ENUMERATION.
   5112 	*/
   5113 	return(xmlSchemaValidateFacet(NULL, facet, value, NULL));
   5114     return (0);
   5115 }
   5116 
   5117 /**
   5118  * xmlSchemaValidateLengthFacet:
   5119  * @type:  the built-in type
   5120  * @facet:  the facet to check
   5121  * @value:  the lexical repr. of the value to be validated
   5122  * @val:  the precomputed value
   5123  * @ws: the whitespace type of the value
   5124  * @length: the actual length of the value
   5125  *
   5126  * Checka a value against a "length", "minLength" and "maxLength"
   5127  * facet; sets @length to the computed length of @value.
   5128  *
   5129  * Returns 0 if the value is valid, a positive error code
   5130  * otherwise and -1 in case of an internal or API error.
   5131  */
   5132 static int
   5133 xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet,
   5134 				     xmlSchemaValType valType,
   5135 				     const xmlChar *value,
   5136 				     xmlSchemaValPtr val,
   5137 				     unsigned long *length,
   5138 				     xmlSchemaWhitespaceValueType ws)
   5139 {
   5140     unsigned int len = 0;
   5141 
   5142     if ((length == NULL) || (facet == NULL))
   5143         return (-1);
   5144     *length = 0;
   5145     if ((facet->type != XML_SCHEMA_FACET_LENGTH) &&
   5146 	(facet->type != XML_SCHEMA_FACET_MAXLENGTH) &&
   5147 	(facet->type != XML_SCHEMA_FACET_MINLENGTH))
   5148 	return (-1);
   5149 
   5150     /*
   5151     * TODO: length, maxLength and minLength must be of type
   5152     * nonNegativeInteger only. Check if decimal is used somehow.
   5153     */
   5154     if ((facet->val == NULL) ||
   5155 	((facet->val->type != XML_SCHEMAS_DECIMAL) &&
   5156 	 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
   5157 	(facet->val->value.decimal.frac != 0)) {
   5158 	return(-1);
   5159     }
   5160     if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
   5161 	len = val->value.hex.total;
   5162     else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
   5163 	len = val->value.base64.total;
   5164     else {
   5165 	switch (valType) {
   5166 	    case XML_SCHEMAS_STRING:
   5167 	    case XML_SCHEMAS_NORMSTRING:
   5168 		if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
   5169 		    /*
   5170 		    * This is to ensure API compatibility with the old
   5171 		    * xmlSchemaValidateLengthFacet(). Anyway, this was and
   5172 		    * is not the correct handling.
   5173 		    * TODO: Get rid of this case somehow.
   5174 		    */
   5175 		    if (valType == XML_SCHEMAS_STRING)
   5176 			len = xmlUTF8Strlen(value);
   5177 		    else
   5178 			len = xmlSchemaNormLen(value);
   5179 		} else if (value != NULL) {
   5180 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
   5181 			len = xmlSchemaNormLen(value);
   5182 		    else
   5183 		    /*
   5184 		    * Should be OK for "preserve" as well.
   5185 		    */
   5186 		    len = xmlUTF8Strlen(value);
   5187 		}
   5188 		break;
   5189 	    case XML_SCHEMAS_IDREF:
   5190 	    case XML_SCHEMAS_TOKEN:
   5191 	    case XML_SCHEMAS_LANGUAGE:
   5192 	    case XML_SCHEMAS_NMTOKEN:
   5193 	    case XML_SCHEMAS_NAME:
   5194 	    case XML_SCHEMAS_NCNAME:
   5195 	    case XML_SCHEMAS_ID:
   5196 		/*
   5197 		* FIXME: What exactly to do with anyURI?
   5198 		*/
   5199 	    case XML_SCHEMAS_ANYURI:
   5200 		if (value != NULL)
   5201 		    len = xmlSchemaNormLen(value);
   5202 		break;
   5203 	    case XML_SCHEMAS_QNAME:
   5204 	    case XML_SCHEMAS_NOTATION:
   5205 		/*
   5206 		* For QName and NOTATION, those facets are
   5207 		* deprecated and should be ignored.
   5208 		*/
   5209 		return (0);
   5210 	    default:
   5211 		TODO
   5212 	}
   5213     }
   5214     *length = (unsigned long) len;
   5215     /*
   5216     * TODO: Return the whole expected value, i.e. "lo", "mi" and "hi".
   5217     */
   5218     if (facet->type == XML_SCHEMA_FACET_LENGTH) {
   5219 	if (len != facet->val->value.decimal.lo)
   5220 	    return(XML_SCHEMAV_CVC_LENGTH_VALID);
   5221     } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
   5222 	if (len < facet->val->value.decimal.lo)
   5223 	    return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
   5224     } else {
   5225 	if (len > facet->val->value.decimal.lo)
   5226 	    return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
   5227     }
   5228 
   5229     return (0);
   5230 }
   5231 
   5232 /**
   5233  * xmlSchemaValidateLengthFacet:
   5234  * @type:  the built-in type
   5235  * @facet:  the facet to check
   5236  * @value:  the lexical repr. of the value to be validated
   5237  * @val:  the precomputed value
   5238  * @length: the actual length of the value
   5239  *
   5240  * Checka a value against a "length", "minLength" and "maxLength"
   5241  * facet; sets @length to the computed length of @value.
   5242  *
   5243  * Returns 0 if the value is valid, a positive error code
   5244  * otherwise and -1 in case of an internal or API error.
   5245  */
   5246 int
   5247 xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type,
   5248 			     xmlSchemaFacetPtr facet,
   5249 			     const xmlChar *value,
   5250 			     xmlSchemaValPtr val,
   5251 			     unsigned long *length)
   5252 {
   5253     if (type == NULL)
   5254         return(-1);
   5255     return (xmlSchemaValidateLengthFacetInternal(facet,
   5256 	type->builtInType, value, val, length,
   5257 	XML_SCHEMA_WHITESPACE_UNKNOWN));
   5258 }
   5259 
   5260 /**
   5261  * xmlSchemaValidateLengthFacetWhtsp:
   5262  * @facet:  the facet to check
   5263  * @valType:  the built-in type
   5264  * @value:  the lexical repr. of the value to be validated
   5265  * @val:  the precomputed value
   5266  * @ws: the whitespace type of the value
   5267  * @length: the actual length of the value
   5268  *
   5269  * Checka a value against a "length", "minLength" and "maxLength"
   5270  * facet; sets @length to the computed length of @value.
   5271  *
   5272  * Returns 0 if the value is valid, a positive error code
   5273  * otherwise and -1 in case of an internal or API error.
   5274  */
   5275 int
   5276 xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet,
   5277 				  xmlSchemaValType valType,
   5278 				  const xmlChar *value,
   5279 				  xmlSchemaValPtr val,
   5280 				  unsigned long *length,
   5281 				  xmlSchemaWhitespaceValueType ws)
   5282 {
   5283     return (xmlSchemaValidateLengthFacetInternal(facet, valType, value, val,
   5284 	length, ws));
   5285 }
   5286 
   5287 /**
   5288  * xmlSchemaValidateFacetInternal:
   5289  * @facet:  the facet to check
   5290  * @fws: the whitespace type of the facet's value
   5291  * @valType: the built-in type of the value
   5292  * @value:  the lexical repr of the value to validate
   5293  * @val:  the precomputed value
   5294  * @ws: the whitespace type of the value
   5295  *
   5296  * Check a value against a facet condition
   5297  *
   5298  * Returns 0 if the element is schemas valid, a positive error code
   5299  *     number otherwise and -1 in case of internal or API error.
   5300  */
   5301 static int
   5302 xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,
   5303 			       xmlSchemaWhitespaceValueType fws,
   5304 			       xmlSchemaValType valType,
   5305 			       const xmlChar *value,
   5306 			       xmlSchemaValPtr val,
   5307 			       xmlSchemaWhitespaceValueType ws)
   5308 {
   5309     int ret;
   5310     int stringType;
   5311 
   5312     if (facet == NULL)
   5313 	return(-1);
   5314 
   5315     switch (facet->type) {
   5316 	case XML_SCHEMA_FACET_PATTERN:
   5317 	    /*
   5318 	    * NOTE that for patterns, the @value needs to be the normalized
   5319 	    * value, *not* the lexical initial value or the canonical value.
   5320 	    */
   5321 	    if (value == NULL)
   5322 		return(-1);
   5323 	    /*
   5324 	    * If string-derived type, regexp must be tested on the value space of
   5325 	    * the datatype.
   5326 	    * See https://www.w3.org/TR/xmlschema-2/#rf-pattern
   5327 	    */
   5328 	    stringType = val && ((val->type >= XML_SCHEMAS_STRING && val->type <= XML_SCHEMAS_NORMSTRING)
   5329 			      || (val->type >= XML_SCHEMAS_TOKEN && val->type <= XML_SCHEMAS_NCNAME));
   5330 	    ret = xmlRegexpExec(facet->regexp,
   5331 	                        (stringType && val->value.str) ? val->value.str : value);
   5332 	    if (ret == 1)
   5333 		return(0);
   5334 	    if (ret == 0)
   5335 		return(XML_SCHEMAV_CVC_PATTERN_VALID);
   5336 	    return(ret);
   5337 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
   5338 	    ret = xmlSchemaCompareValues(val, facet->val);
   5339 	    if (ret == -2)
   5340 		return(-1);
   5341 	    if (ret == -1)
   5342 		return(0);
   5343 	    return(XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID);
   5344 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
   5345 	    ret = xmlSchemaCompareValues(val, facet->val);
   5346 	    if (ret == -2)
   5347 		return(-1);
   5348 	    if ((ret == -1) || (ret == 0))
   5349 		return(0);
   5350 	    return(XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID);
   5351 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
   5352 	    ret = xmlSchemaCompareValues(val, facet->val);
   5353 	    if (ret == -2)
   5354 		return(-1);
   5355 	    if (ret == 1)
   5356 		return(0);
   5357 	    return(XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID);
   5358 	case XML_SCHEMA_FACET_MININCLUSIVE:
   5359 	    ret = xmlSchemaCompareValues(val, facet->val);
   5360 	    if (ret == -2)
   5361 		return(-1);
   5362 	    if ((ret == 1) || (ret == 0))
   5363 		return(0);
   5364 	    return(XML_SCHEMAV_CVC_MININCLUSIVE_VALID);
   5365 	case XML_SCHEMA_FACET_WHITESPACE:
   5366 	    /* TODO whitespaces */
   5367 	    /*
   5368 	    * NOTE: Whitespace should be handled to normalize
   5369 	    * the value to be validated against a the facets;
   5370 	    * not to normalize the value in-between.
   5371 	    */
   5372 	    return(0);
   5373 	case  XML_SCHEMA_FACET_ENUMERATION:
   5374 	    if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
   5375 		/*
   5376 		* This is to ensure API compatibility with the old
   5377 		* xmlSchemaValidateFacet().
   5378 		* TODO: Get rid of this case.
   5379 		*/
   5380 		if ((facet->value != NULL) &&
   5381 		    (xmlStrEqual(facet->value, value)))
   5382 		    return(0);
   5383 	    } else {
   5384 		ret = xmlSchemaCompareValuesWhtspExt(facet->val->type,
   5385 		    facet->val, facet->value, fws, valType, val,
   5386 		    value, ws);
   5387 		if (ret == -2)
   5388 		    return(-1);
   5389 		if (ret == 0)
   5390 		    return(0);
   5391 	    }
   5392 	    return(XML_SCHEMAV_CVC_ENUMERATION_VALID);
   5393 	case XML_SCHEMA_FACET_LENGTH:
   5394 	    /*
   5395 	    * SPEC (1.3) "if {primitive type definition} is QName or NOTATION,
   5396 	    * then any {value} is facet-valid."
   5397 	    */
   5398 	    if ((valType == XML_SCHEMAS_QNAME) ||
   5399 		(valType == XML_SCHEMAS_NOTATION))
   5400 		return (0);
   5401 	    /* No break on purpose. */
   5402 	case XML_SCHEMA_FACET_MAXLENGTH:
   5403 	case XML_SCHEMA_FACET_MINLENGTH: {
   5404 	    unsigned int len = 0;
   5405 
   5406 	    if ((valType == XML_SCHEMAS_QNAME) ||
   5407 		(valType == XML_SCHEMAS_NOTATION))
   5408 		return (0);
   5409 	    /*
   5410 	    * TODO: length, maxLength and minLength must be of type
   5411 	    * nonNegativeInteger only. Check if decimal is used somehow.
   5412 	    */
   5413 	    if ((facet->val == NULL) ||
   5414 		((facet->val->type != XML_SCHEMAS_DECIMAL) &&
   5415 		 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
   5416 		(facet->val->value.decimal.frac != 0)) {
   5417 		return(-1);
   5418 	    }
   5419 	    if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
   5420 		len = val->value.hex.total;
   5421 	    else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
   5422 		len = val->value.base64.total;
   5423 	    else {
   5424 		switch (valType) {
   5425 		    case XML_SCHEMAS_STRING:
   5426 		    case XML_SCHEMAS_NORMSTRING:
   5427 			if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
   5428 			    /*
   5429 			    * This is to ensure API compatibility with the old
   5430 			    * xmlSchemaValidateFacet(). Anyway, this was and
   5431 			    * is not the correct handling.
   5432 			    * TODO: Get rid of this case somehow.
   5433 			    */
   5434 			    if (valType == XML_SCHEMAS_STRING)
   5435 				len = xmlUTF8Strlen(value);
   5436 			    else
   5437 				len = xmlSchemaNormLen(value);
   5438 			} else if (value != NULL) {
   5439 			    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
   5440 				len = xmlSchemaNormLen(value);
   5441 			    else
   5442 				/*
   5443 				* Should be OK for "preserve" as well.
   5444 				*/
   5445 				len = xmlUTF8Strlen(value);
   5446 			}
   5447 			break;
   5448 		    case XML_SCHEMAS_IDREF:
   5449 		    case XML_SCHEMAS_TOKEN:
   5450 		    case XML_SCHEMAS_LANGUAGE:
   5451 		    case XML_SCHEMAS_NMTOKEN:
   5452 		    case XML_SCHEMAS_NAME:
   5453 		    case XML_SCHEMAS_NCNAME:
   5454 		    case XML_SCHEMAS_ID:
   5455 		    case XML_SCHEMAS_ANYURI:
   5456 			if (value != NULL)
   5457 			    len = xmlSchemaNormLen(value);
   5458 			break;
   5459 		    default:
   5460 		        TODO
   5461 		}
   5462 	    }
   5463 	    if (facet->type == XML_SCHEMA_FACET_LENGTH) {
   5464 		if (len != facet->val->value.decimal.lo)
   5465 		    return(XML_SCHEMAV_CVC_LENGTH_VALID);
   5466 	    } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
   5467 		if (len < facet->val->value.decimal.lo)
   5468 		    return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
   5469 	    } else {
   5470 		if (len > facet->val->value.decimal.lo)
   5471 		    return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
   5472 	    }
   5473 	    break;
   5474 	}
   5475 	case XML_SCHEMA_FACET_TOTALDIGITS:
   5476 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
   5477 
   5478 	    if ((facet->val == NULL) ||
   5479 		((facet->val->type != XML_SCHEMAS_PINTEGER) &&
   5480 		 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
   5481 		(facet->val->value.decimal.frac != 0)) {
   5482 		return(-1);
   5483 	    }
   5484 	    if ((val == NULL) ||
   5485 		((val->type != XML_SCHEMAS_DECIMAL) &&
   5486 		 (val->type != XML_SCHEMAS_INTEGER) &&
   5487 		 (val->type != XML_SCHEMAS_NPINTEGER) &&
   5488 		 (val->type != XML_SCHEMAS_NINTEGER) &&
   5489 		 (val->type != XML_SCHEMAS_NNINTEGER) &&
   5490 		 (val->type != XML_SCHEMAS_PINTEGER) &&
   5491 		 (val->type != XML_SCHEMAS_INT) &&
   5492 		 (val->type != XML_SCHEMAS_UINT) &&
   5493 		 (val->type != XML_SCHEMAS_LONG) &&
   5494 		 (val->type != XML_SCHEMAS_ULONG) &&
   5495 		 (val->type != XML_SCHEMAS_SHORT) &&
   5496 		 (val->type != XML_SCHEMAS_USHORT) &&
   5497 		 (val->type != XML_SCHEMAS_BYTE) &&
   5498 		 (val->type != XML_SCHEMAS_UBYTE))) {
   5499 		return(-1);
   5500 	    }
   5501 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
   5502 	        if (val->value.decimal.total > facet->val->value.decimal.lo)
   5503 	            return(XML_SCHEMAV_CVC_TOTALDIGITS_VALID);
   5504 
   5505 	    } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) {
   5506 	        if (val->value.decimal.frac > facet->val->value.decimal.lo)
   5507 		    return(XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID);
   5508 	    }
   5509 	    break;
   5510 	default:
   5511 	    TODO
   5512     }
   5513     return(0);
   5514 
   5515 }
   5516 
   5517 /**
   5518  * xmlSchemaValidateFacet:
   5519  * @base:  the base type
   5520  * @facet:  the facet to check
   5521  * @value:  the lexical repr of the value to validate
   5522  * @val:  the precomputed value
   5523  *
   5524  * Check a value against a facet condition
   5525  *
   5526  * Returns 0 if the element is schemas valid, a positive error code
   5527  *     number otherwise and -1 in case of internal or API error.
   5528  */
   5529 int
   5530 xmlSchemaValidateFacet(xmlSchemaTypePtr base,
   5531 	               xmlSchemaFacetPtr facet,
   5532 	               const xmlChar *value,
   5533 		       xmlSchemaValPtr val)
   5534 {
   5535     /*
   5536     * This tries to ensure API compatibility regarding the old
   5537     * xmlSchemaValidateFacet() and the new xmlSchemaValidateFacetInternal() and
   5538     * xmlSchemaValidateFacetWhtsp().
   5539     */
   5540     if (val != NULL)
   5541 	return(xmlSchemaValidateFacetInternal(facet,
   5542 	    XML_SCHEMA_WHITESPACE_UNKNOWN, val->type, value, val,
   5543 	    XML_SCHEMA_WHITESPACE_UNKNOWN));
   5544     else if (base != NULL)
   5545 	return(xmlSchemaValidateFacetInternal(facet,
   5546 	    XML_SCHEMA_WHITESPACE_UNKNOWN, base->builtInType, value, val,
   5547 	    XML_SCHEMA_WHITESPACE_UNKNOWN));
   5548     return(-1);
   5549 }
   5550 
   5551 /**
   5552  * xmlSchemaValidateFacetWhtsp:
   5553  * @facet:  the facet to check
   5554  * @fws: the whitespace type of the facet's value
   5555  * @valType: the built-in type of the value
   5556  * @value:  the lexical (or normalized for pattern) repr of the value to validate
   5557  * @val:  the precomputed value
   5558  * @ws: the whitespace type of the value
   5559  *
   5560  * Check a value against a facet condition. This takes value normalization
   5561  * according to the specified whitespace types into account.
   5562  * Note that @value needs to be the *normalized* value if the facet
   5563  * is of type "pattern".
   5564  *
   5565  * Returns 0 if the element is schemas valid, a positive error code
   5566  *     number otherwise and -1 in case of internal or API error.
   5567  */
   5568 int
   5569 xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet,
   5570 			    xmlSchemaWhitespaceValueType fws,
   5571 			    xmlSchemaValType valType,
   5572 			    const xmlChar *value,
   5573 			    xmlSchemaValPtr val,
   5574 			    xmlSchemaWhitespaceValueType ws)
   5575 {
   5576      return(xmlSchemaValidateFacetInternal(facet, fws, valType,
   5577 	 value, val, ws));
   5578 }
   5579 
   5580 #if 0
   5581 #ifndef DBL_DIG
   5582 #define DBL_DIG 16
   5583 #endif
   5584 #ifndef DBL_EPSILON
   5585 #define DBL_EPSILON 1E-9
   5586 #endif
   5587 
   5588 #define INTEGER_DIGITS DBL_DIG
   5589 #define FRACTION_DIGITS (DBL_DIG + 1)
   5590 #define EXPONENT_DIGITS (3 + 2)
   5591 
   5592 /**
   5593  * xmlXPathFormatNumber:
   5594  * @number:     number to format
   5595  * @buffer:     output buffer
   5596  * @buffersize: size of output buffer
   5597  *
   5598  * Convert the number into a string representation.
   5599  */
   5600 static void
   5601 xmlSchemaFormatFloat(double number, char buffer[], int buffersize)
   5602 {
   5603     switch (xmlXPathIsInf(number)) {
   5604     case 1:
   5605 	if (buffersize > (int)sizeof("INF"))
   5606 	    snprintf(buffer, buffersize, "INF");
   5607 	break;
   5608     case -1:
   5609 	if (buffersize > (int)sizeof("-INF"))
   5610 	    snprintf(buffer, buffersize, "-INF");
   5611 	break;
   5612     default:
   5613 	if (xmlXPathIsNaN(number)) {
   5614 	    if (buffersize > (int)sizeof("NaN"))
   5615 		snprintf(buffer, buffersize, "NaN");
   5616 	} else if (number == 0) {
   5617 	    snprintf(buffer, buffersize, "0.0E0");
   5618 	} else {
   5619 	    /* 3 is sign, decimal point, and terminating zero */
   5620 	    char work[DBL_DIG + EXPONENT_DIGITS + 3];
   5621 	    int integer_place, fraction_place;
   5622 	    char *ptr;
   5623 	    char *after_fraction;
   5624 	    double absolute_value;
   5625 	    int size;
   5626 
   5627 	    absolute_value = fabs(number);
   5628 
   5629 	    /*
   5630 	     * Result is in work, and after_fraction points
   5631 	     * just past the fractional part.
   5632 	     * Use scientific notation
   5633 	    */
   5634 	    integer_place = DBL_DIG + EXPONENT_DIGITS + 1;
   5635 	    fraction_place = DBL_DIG - 1;
   5636 	    snprintf(work, sizeof(work),"%*.*e",
   5637 		integer_place, fraction_place, number);
   5638 	    after_fraction = strchr(work + DBL_DIG, 'e');
   5639 	    /* Remove fractional trailing zeroes */
   5640 	    ptr = after_fraction;
   5641 	    while (*(--ptr) == '0')
   5642 		;
   5643 	    if (*ptr != '.')
   5644 	        ptr++;
   5645 	    while ((*ptr++ = *after_fraction++) != 0);
   5646 
   5647 	    /* Finally copy result back to caller */
   5648 	    size = strlen(work) + 1;
   5649 	    if (size > buffersize) {
   5650 		work[buffersize - 1] = 0;
   5651 		size = buffersize;
   5652 	    }
   5653 	    memmove(buffer, work, size);
   5654 	}
   5655 	break;
   5656     }
   5657 }
   5658 #endif
   5659 
   5660 /**
   5661  * xmlSchemaGetCanonValue:
   5662  * @val: the precomputed value
   5663  * @retValue: the returned value
   5664  *
   5665  * Get the canonical lexical representation of the value.
   5666  * The caller has to FREE the returned retValue.
   5667  *
   5668  * WARNING: Some value types are not supported yet, resulting
   5669  * in a @retValue of "???".
   5670  *
   5671  * TODO: XML Schema 1.0 does not define canonical representations
   5672  * for: duration, gYearMonth, gYear, gMonthDay, gMonth, gDay,
   5673  * anyURI, QName, NOTATION. This will be fixed in XML Schema 1.1.
   5674  *
   5675  *
   5676  * Returns 0 if the value could be built, 1 if the value type is
   5677  * not supported yet and -1 in case of API errors.
   5678  */
   5679 int
   5680 xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue)
   5681 {
   5682     if ((retValue == NULL) || (val == NULL))
   5683 	return (-1);
   5684     *retValue = NULL;
   5685     switch (val->type) {
   5686 	case XML_SCHEMAS_STRING:
   5687 	    if (val->value.str == NULL)
   5688 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
   5689 	    else
   5690 		*retValue =
   5691 		    BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
   5692 	    break;
   5693 	case XML_SCHEMAS_NORMSTRING:
   5694 	    if (val->value.str == NULL)
   5695 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
   5696 	    else {
   5697 		*retValue = xmlSchemaWhiteSpaceReplace(
   5698 		    (const xmlChar *) val->value.str);
   5699 		if ((*retValue) == NULL)
   5700 		    *retValue = BAD_CAST xmlStrdup(
   5701 			(const xmlChar *) val->value.str);
   5702 	    }
   5703 	    break;
   5704 	case XML_SCHEMAS_TOKEN:
   5705 	case XML_SCHEMAS_LANGUAGE:
   5706 	case XML_SCHEMAS_NMTOKEN:
   5707 	case XML_SCHEMAS_NAME:
   5708 	case XML_SCHEMAS_NCNAME:
   5709 	case XML_SCHEMAS_ID:
   5710 	case XML_SCHEMAS_IDREF:
   5711 	case XML_SCHEMAS_ENTITY:
   5712 	case XML_SCHEMAS_NOTATION: /* Unclear */
   5713 	case XML_SCHEMAS_ANYURI:   /* Unclear */
   5714 	    if (val->value.str == NULL)
   5715 		return (-1);
   5716 	    *retValue =
   5717 		BAD_CAST xmlSchemaCollapseString(BAD_CAST val->value.str);
   5718 	    if (*retValue == NULL)
   5719 		*retValue =
   5720 		    BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
   5721 	    break;
   5722 	case XML_SCHEMAS_QNAME:
   5723 	    /* TODO: Unclear in XML Schema 1.0. */
   5724 	    if (val->value.qname.uri == NULL) {
   5725 		*retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.qname.name);
   5726 		return (0);
   5727 	    } else {
   5728 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "{");
   5729 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
   5730 		    BAD_CAST val->value.qname.uri);
   5731 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
   5732 		    BAD_CAST "}");
   5733 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
   5734 		    BAD_CAST val->value.qname.uri);
   5735 	    }
   5736 	    break;
   5737 	case XML_SCHEMAS_DECIMAL:
   5738 	    /*
   5739 	    * TODO: Lookout for a more simple implementation.
   5740 	    */
   5741 	    if ((val->value.decimal.total == 1) &&
   5742 		(val->value.decimal.lo == 0)) {
   5743 		*retValue = xmlStrdup(BAD_CAST "0.0");
   5744 	    } else {
   5745 		xmlSchemaValDecimal dec = val->value.decimal;
   5746 		int bufsize;
   5747 		char *buf = NULL, *offs;
   5748 
   5749 		/* Add room for the decimal point as well. */
   5750 		bufsize = dec.total + 2;
   5751 		if (dec.sign)
   5752 		    bufsize++;
   5753 		/* Add room for leading/trailing zero. */
   5754 		if ((dec.frac == 0) || (dec.frac == dec.total))
   5755 		    bufsize++;
   5756 		buf = xmlMalloc(bufsize);
   5757 		if (buf == NULL)
   5758 		    return(-1);
   5759 		offs = buf;
   5760 		if (dec.sign)
   5761 		    *offs++ = '-';
   5762 		if (dec.frac == dec.total) {
   5763 		    *offs++ = '0';
   5764 		    *offs++ = '.';
   5765 		}
   5766 		if (dec.hi != 0)
   5767 		    snprintf(offs, bufsize - (offs - buf),
   5768 			"%lu%lu%lu", dec.hi, dec.mi, dec.lo);
   5769 		else if (dec.mi != 0)
   5770 		    snprintf(offs, bufsize - (offs - buf),
   5771 			"%lu%lu", dec.mi, dec.lo);
   5772 		else
   5773 		    snprintf(offs, bufsize - (offs - buf),
   5774 			"%lu", dec.lo);
   5775 
   5776 		if (dec.frac != 0) {
   5777 		    if (dec.frac != dec.total) {
   5778 			int diff = dec.total - dec.frac;
   5779 			/*
   5780 			* Insert the decimal point.
   5781 			*/
   5782 			memmove(offs + diff + 1, offs + diff, dec.frac +1);
   5783 			offs[diff] = '.';
   5784 		    } else {
   5785 			unsigned int i = 0;
   5786 			/*
   5787 			* Insert missing zeroes behind the decimal point.
   5788 			*/
   5789 			while (*(offs + i) != 0)
   5790 			    i++;
   5791 			if (i < dec.total) {
   5792 			    memmove(offs + (dec.total - i), offs, i +1);
   5793 			    memset(offs, '0', dec.total - i);
   5794 			}
   5795 		    }
   5796 		} else {
   5797 		    /*
   5798 		    * Append decimal point and zero.
   5799 		    */
   5800 		    offs = buf + bufsize - 1;
   5801 		    *offs-- = 0;
   5802 		    *offs-- = '0';
   5803 		    *offs-- = '.';
   5804 		}
   5805 		*retValue = BAD_CAST buf;
   5806 	    }
   5807 	    break;
   5808 	case XML_SCHEMAS_INTEGER:
   5809         case XML_SCHEMAS_PINTEGER:
   5810         case XML_SCHEMAS_NPINTEGER:
   5811         case XML_SCHEMAS_NINTEGER:
   5812         case XML_SCHEMAS_NNINTEGER:
   5813 	case XML_SCHEMAS_LONG:
   5814         case XML_SCHEMAS_BYTE:
   5815         case XML_SCHEMAS_SHORT:
   5816         case XML_SCHEMAS_INT:
   5817 	case XML_SCHEMAS_UINT:
   5818         case XML_SCHEMAS_ULONG:
   5819         case XML_SCHEMAS_USHORT:
   5820         case XML_SCHEMAS_UBYTE:
   5821 	    if ((val->value.decimal.total == 1) &&
   5822 		(val->value.decimal.lo == 0))
   5823 		*retValue = xmlStrdup(BAD_CAST "0");
   5824 	    else {
   5825 		xmlSchemaValDecimal dec = val->value.decimal;
   5826 		int bufsize = dec.total + 1;
   5827 
   5828 		/* Add room for the decimal point as well. */
   5829 		if (dec.sign)
   5830 		    bufsize++;
   5831 		*retValue = xmlMalloc(bufsize);
   5832 		if (*retValue == NULL)
   5833 		    return(-1);
   5834 		if (dec.hi != 0) {
   5835 		    if (dec.sign)
   5836 			snprintf((char *) *retValue, bufsize,
   5837 			    "-%lu%lu%lu", dec.hi, dec.mi, dec.lo);
   5838 		    else
   5839 			snprintf((char *) *retValue, bufsize,
   5840 			    "%lu%lu%lu", dec.hi, dec.mi, dec.lo);
   5841 		} else if (dec.mi != 0) {
   5842 		    if (dec.sign)
   5843 			snprintf((char *) *retValue, bufsize,
   5844 			    "-%lu%lu", dec.mi, dec.lo);
   5845 		    else
   5846 			snprintf((char *) *retValue, bufsize,
   5847 			    "%lu%lu", dec.mi, dec.lo);
   5848 		} else {
   5849 		    if (dec.sign)
   5850 			snprintf((char *) *retValue, bufsize, "-%lu", dec.lo);
   5851 		    else
   5852 			snprintf((char *) *retValue, bufsize, "%lu", dec.lo);
   5853 		}
   5854 	    }
   5855 	    break;
   5856 	case XML_SCHEMAS_BOOLEAN:
   5857 	    if (val->value.b)
   5858 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "true");
   5859 	    else
   5860 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "false");
   5861 	    break;
   5862 	case XML_SCHEMAS_DURATION: {
   5863 		char buf[100];
   5864 		unsigned long year;
   5865 		unsigned long mon, day, hour = 0, min = 0;
   5866 		double sec = 0, left;
   5867 
   5868 		/* TODO: Unclear in XML Schema 1.0 */
   5869 		/*
   5870 		* TODO: This results in a normalized output of the value
   5871 		* - which is NOT conformant to the spec -
   5872 		* since the exact values of each property are not
   5873 		* recoverable. Think about extending the structure to
   5874 		* provide a field for every property.
   5875 		*/
   5876 		year = (unsigned long) FQUOTIENT(labs(val->value.dur.mon), 12);
   5877 		mon = labs(val->value.dur.mon) - 12 * year;
   5878 
   5879 		day = (unsigned long) FQUOTIENT(fabs(val->value.dur.sec), 86400);
   5880 		left = fabs(val->value.dur.sec) - day * 86400;
   5881 		if (left > 0) {
   5882 		    hour = (unsigned long) FQUOTIENT(left, 3600);
   5883 		    left = left - (hour * 3600);
   5884 		    if (left > 0) {
   5885 			min = (unsigned long) FQUOTIENT(left, 60);
   5886 			sec = left - (min * 60);
   5887 		    }
   5888 		}
   5889 		if ((val->value.dur.mon < 0) || (val->value.dur.sec < 0))
   5890 		    snprintf(buf, 100, "P%luY%luM%luDT%luH%luM%.14gS",
   5891 			year, mon, day, hour, min, sec);
   5892 		else
   5893 		    snprintf(buf, 100, "-P%luY%luM%luDT%luH%luM%.14gS",
   5894 			year, mon, day, hour, min, sec);
   5895 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
   5896 	    }
   5897 	    break;
   5898 	case XML_SCHEMAS_GYEAR: {
   5899 		char buf[30];
   5900 		/* TODO: Unclear in XML Schema 1.0 */
   5901 		/* TODO: What to do with the timezone? */
   5902 		snprintf(buf, 30, "%04ld", val->value.date.year);
   5903 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
   5904 	    }
   5905 	    break;
   5906 	case XML_SCHEMAS_GMONTH: {
   5907 		/* TODO: Unclear in XML Schema 1.0 */
   5908 		/* TODO: What to do with the timezone? */
   5909 		*retValue = xmlMalloc(6);
   5910 		if (*retValue == NULL)
   5911 		    return(-1);
   5912 		snprintf((char *) *retValue, 6, "--%02u",
   5913 		    val->value.date.mon);
   5914 	    }
   5915 	    break;
   5916         case XML_SCHEMAS_GDAY: {
   5917 		/* TODO: Unclear in XML Schema 1.0 */
   5918 		/* TODO: What to do with the timezone? */
   5919 		*retValue = xmlMalloc(6);
   5920 		if (*retValue == NULL)
   5921 		    return(-1);
   5922 		snprintf((char *) *retValue, 6, "---%02u",
   5923 		    val->value.date.day);
   5924 	    }
   5925 	    break;
   5926         case XML_SCHEMAS_GMONTHDAY: {
   5927 		/* TODO: Unclear in XML Schema 1.0 */
   5928 		/* TODO: What to do with the timezone? */
   5929 		*retValue = xmlMalloc(8);
   5930 		if (*retValue == NULL)
   5931 		    return(-1);
   5932 		snprintf((char *) *retValue, 8, "--%02u-%02u",
   5933 		    val->value.date.mon, val->value.date.day);
   5934 	    }
   5935 	    break;
   5936         case XML_SCHEMAS_GYEARMONTH: {
   5937 		char buf[35];
   5938 		/* TODO: Unclear in XML Schema 1.0 */
   5939 		/* TODO: What to do with the timezone? */
   5940 		if (val->value.date.year < 0)
   5941 		    snprintf(buf, 35, "-%04ld-%02u",
   5942 			labs(val->value.date.year),
   5943 			val->value.date.mon);
   5944 		else
   5945 		    snprintf(buf, 35, "%04ld-%02u",
   5946 			val->value.date.year, val->value.date.mon);
   5947 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
   5948 	    }
   5949 	    break;
   5950 	case XML_SCHEMAS_TIME:
   5951 	    {
   5952 		char buf[30];
   5953 
   5954 		if (val->value.date.tz_flag) {
   5955 		    xmlSchemaValPtr norm;
   5956 
   5957 		    norm = xmlSchemaDateNormalize(val, 0);
   5958 		    if (norm == NULL)
   5959 			return (-1);
   5960 		    /*
   5961 		    * TODO: Check if "%.14g" is portable.
   5962 		    */
   5963 		    snprintf(buf, 30,
   5964 			"%02u:%02u:%02.14gZ",
   5965 			norm->value.date.hour,
   5966 			norm->value.date.min,
   5967 			norm->value.date.sec);
   5968 		    xmlSchemaFreeValue(norm);
   5969 		} else {
   5970 		    snprintf(buf, 30,
   5971 			"%02u:%02u:%02.14g",
   5972 			val->value.date.hour,
   5973 			val->value.date.min,
   5974 			val->value.date.sec);
   5975 		}
   5976 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
   5977 	    }
   5978 	    break;
   5979         case XML_SCHEMAS_DATE:
   5980 	    {
   5981 		char buf[30];
   5982 
   5983 		if (val->value.date.tz_flag) {
   5984 		    xmlSchemaValPtr norm;
   5985 
   5986 		    norm = xmlSchemaDateNormalize(val, 0);
   5987 		    if (norm == NULL)
   5988 			return (-1);
   5989 		    /*
   5990 		    * TODO: Append the canonical value of the
   5991 		    * recoverable timezone and not "Z".
   5992 		    */
   5993 		    snprintf(buf, 30,
   5994 			"%04ld:%02u:%02uZ",
   5995 			norm->value.date.year, norm->value.date.mon,
   5996 			norm->value.date.day);
   5997 		    xmlSchemaFreeValue(norm);
   5998 		} else {
   5999 		    snprintf(buf, 30,
   6000 			"%04ld:%02u:%02u",
   6001 			val->value.date.year, val->value.date.mon,
   6002 			val->value.date.day);
   6003 		}
   6004 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
   6005 	    }
   6006 	    break;
   6007         case XML_SCHEMAS_DATETIME:
   6008 	    {
   6009 		char buf[50];
   6010 
   6011 		if (val->value.date.tz_flag) {
   6012 		    xmlSchemaValPtr norm;
   6013 
   6014 		    norm = xmlSchemaDateNormalize(val, 0);
   6015 		    if (norm == NULL)
   6016 			return (-1);
   6017 		    /*
   6018 		    * TODO: Check if "%.14g" is portable.
   6019 		    */
   6020 		    snprintf(buf, 50,
   6021 			"%04ld:%02u:%02uT%02u:%02u:%02.14gZ",
   6022 			norm->value.date.year, norm->value.date.mon,
   6023 			norm->value.date.day, norm->value.date.hour,
   6024 			norm->value.date.min, norm->value.date.sec);
   6025 		    xmlSchemaFreeValue(norm);
   6026 		} else {
   6027 		    snprintf(buf, 50,
   6028 			"%04ld:%02u:%02uT%02u:%02u:%02.14g",
   6029 			val->value.date.year, val->value.date.mon,
   6030 			val->value.date.day, val->value.date.hour,
   6031 			val->value.date.min, val->value.date.sec);
   6032 		}
   6033 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
   6034 	    }
   6035 	    break;
   6036 	case XML_SCHEMAS_HEXBINARY:
   6037 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.hex.str);
   6038 	    break;
   6039 	case XML_SCHEMAS_BASE64BINARY:
   6040 	    /*
   6041 	    * TODO: Is the following spec piece implemented?:
   6042 	    * SPEC: "Note: For some values the canonical form defined
   6043 	    * above does not conform to [RFC 2045], which requires breaking
   6044 	    * with linefeeds at appropriate intervals."
   6045 	    */
   6046 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.base64.str);
   6047 	    break;
   6048 	case XML_SCHEMAS_FLOAT: {
   6049 		char buf[30];
   6050 		/*
   6051 		* |m| < 16777216, -149 <= e <= 104.
   6052 		* TODO: Handle, NaN, INF, -INF. The format is not
   6053 		* yet conformant. The c type float does not cover
   6054 		* the whole range.
   6055 		*/
   6056 		snprintf(buf, 30, "%01.14e", val->value.f);
   6057 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
   6058 	    }
   6059 	    break;
   6060 	case XML_SCHEMAS_DOUBLE: {
   6061 		char buf[40];
   6062 		/* |m| < 9007199254740992, -1075 <= e <= 970 */
   6063 		/*
   6064 		* TODO: Handle, NaN, INF, -INF. The format is not
   6065 		* yet conformant. The c type float does not cover
   6066 		* the whole range.
   6067 		*/
   6068 		snprintf(buf, 40, "%01.14e", val->value.d);
   6069 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
   6070 	    }
   6071 	    break;
   6072 	default:
   6073 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST "???");
   6074 	    return (1);
   6075     }
   6076     if (*retValue == NULL)
   6077 	return(-1);
   6078     return (0);
   6079 }
   6080 
   6081 /**
   6082  * xmlSchemaGetCanonValueWhtsp:
   6083  * @val: the precomputed value
   6084  * @retValue: the returned value
   6085  * @ws: the whitespace type of the value
   6086  *
   6087  * Get the canonical representation of the value.
   6088  * The caller has to free the returned @retValue.
   6089  *
   6090  * Returns 0 if the value could be built, 1 if the value type is
   6091  * not supported yet and -1 in case of API errors.
   6092  */
   6093 int
   6094 xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val,
   6095 			    const xmlChar **retValue,
   6096 			    xmlSchemaWhitespaceValueType ws)
   6097 {
   6098     if ((retValue == NULL) || (val == NULL))
   6099 	return (-1);
   6100     if ((ws == XML_SCHEMA_WHITESPACE_UNKNOWN) ||
   6101 	(ws > XML_SCHEMA_WHITESPACE_COLLAPSE))
   6102 	return (-1);
   6103 
   6104     *retValue = NULL;
   6105     switch (val->type) {
   6106 	case XML_SCHEMAS_STRING:
   6107 	    if (val->value.str == NULL)
   6108 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
   6109 	    else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
   6110 		*retValue = xmlSchemaCollapseString(val->value.str);
   6111 	    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
   6112 		*retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
   6113 	    if ((*retValue) == NULL)
   6114 		*retValue = BAD_CAST xmlStrdup(val->value.str);
   6115 	    break;
   6116 	case XML_SCHEMAS_NORMSTRING:
   6117 	    if (val->value.str == NULL)
   6118 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
   6119 	    else {
   6120 		if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
   6121 		    *retValue = xmlSchemaCollapseString(val->value.str);
   6122 		else
   6123 		    *retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
   6124 		if ((*retValue) == NULL)
   6125 		    *retValue = BAD_CAST xmlStrdup(val->value.str);
   6126 	    }
   6127 	    break;
   6128 	default:
   6129 	    return (xmlSchemaGetCanonValue(val, retValue));
   6130     }
   6131     return (0);
   6132 }
   6133 
   6134 /**
   6135  * xmlSchemaGetValType:
   6136  * @val: a schemas value
   6137  *
   6138  * Accessor for the type of a value
   6139  *
   6140  * Returns the xmlSchemaValType of the value
   6141  */
   6142 xmlSchemaValType
   6143 xmlSchemaGetValType(xmlSchemaValPtr val)
   6144 {
   6145     if (val == NULL)
   6146         return(XML_SCHEMAS_UNKNOWN);
   6147     return (val->type);
   6148 }
   6149 
   6150 #define bottom_xmlschemastypes
   6151 #include "elfgcchack.h"
   6152 #endif /* LIBXML_SCHEMAS_ENABLED */
   6153