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