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