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 
   2396 		if (normOnTheFly)
   2397 		    while IS_WSP_BLANK_CH(*cur) cur++;
   2398 
   2399                 if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) {
   2400                     cur += 3;
   2401                     if (*cur != 0)
   2402                         goto return1;
   2403                     if (val != NULL) {
   2404                         if (type == xmlSchemaTypeFloatDef) {
   2405                             v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
   2406                             if (v != NULL) {
   2407                                 v->value.f = (float) xmlXPathNAN;
   2408                             } else {
   2409                                 xmlSchemaFreeValue(v);
   2410                                 goto error;
   2411                             }
   2412                         } else {
   2413                             v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
   2414                             if (v != NULL) {
   2415                                 v->value.d = xmlXPathNAN;
   2416                             } else {
   2417                                 xmlSchemaFreeValue(v);
   2418                                 goto error;
   2419                             }
   2420                         }
   2421                         *val = v;
   2422                     }
   2423                     goto return0;
   2424                 }
   2425                 if (*cur == '-') {
   2426                     neg = 1;
   2427                     cur++;
   2428                 }
   2429                 if ((cur[0] == 'I') && (cur[1] == 'N') && (cur[2] == 'F')) {
   2430                     cur += 3;
   2431                     if (*cur != 0)
   2432                         goto return1;
   2433                     if (val != NULL) {
   2434                         if (type == xmlSchemaTypeFloatDef) {
   2435                             v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
   2436                             if (v != NULL) {
   2437                                 if (neg)
   2438                                     v->value.f = (float) xmlXPathNINF;
   2439                                 else
   2440                                     v->value.f = (float) xmlXPathPINF;
   2441                             } else {
   2442                                 xmlSchemaFreeValue(v);
   2443                                 goto error;
   2444                             }
   2445                         } else {
   2446                             v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
   2447                             if (v != NULL) {
   2448                                 if (neg)
   2449                                     v->value.d = xmlXPathNINF;
   2450                                 else
   2451                                     v->value.d = xmlXPathPINF;
   2452                             } else {
   2453                                 xmlSchemaFreeValue(v);
   2454                                 goto error;
   2455                             }
   2456                         }
   2457                         *val = v;
   2458                     }
   2459                     goto return0;
   2460                 }
   2461                 if ((neg == 0) && (*cur == '+'))
   2462                     cur++;
   2463                 if ((cur[0] == 0) || (cur[0] == '+') || (cur[0] == '-'))
   2464                     goto return1;
   2465                 while ((*cur >= '0') && (*cur <= '9')) {
   2466                     cur++;
   2467                 }
   2468                 if (*cur == '.') {
   2469                     cur++;
   2470                     while ((*cur >= '0') && (*cur <= '9'))
   2471                         cur++;
   2472                 }
   2473                 if ((*cur == 'e') || (*cur == 'E')) {
   2474                     cur++;
   2475                     if ((*cur == '-') || (*cur == '+'))
   2476                         cur++;
   2477                     while ((*cur >= '0') && (*cur <= '9'))
   2478                         cur++;
   2479                 }
   2480 		if (normOnTheFly)
   2481 		    while IS_WSP_BLANK_CH(*cur) cur++;
   2482 
   2483                 if (*cur != 0)
   2484                     goto return1;
   2485                 if (val != NULL) {
   2486                     if (type == xmlSchemaTypeFloatDef) {
   2487                         v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
   2488                         if (v != NULL) {
   2489 			    /*
   2490 			    * TODO: sscanf seems not to give the correct
   2491 			    * value for extremely high/low values.
   2492 			    * E.g. "1E-149" results in zero.
   2493 			    */
   2494                             if (sscanf((const char *) value, "%f",
   2495                                  &(v->value.f)) == 1) {
   2496                                 *val = v;
   2497                             } else {
   2498                                 xmlSchemaFreeValue(v);
   2499                                 goto return1;
   2500                             }
   2501                         } else {
   2502                             goto error;
   2503                         }
   2504                     } else {
   2505                         v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
   2506                         if (v != NULL) {
   2507 			    /*
   2508 			    * TODO: sscanf seems not to give the correct
   2509 			    * value for extremely high/low values.
   2510 			    */
   2511                             if (sscanf((const char *) value, "%lf",
   2512                                  &(v->value.d)) == 1) {
   2513                                 *val = v;
   2514                             } else {
   2515                                 xmlSchemaFreeValue(v);
   2516                                 goto return1;
   2517                             }
   2518                         } else {
   2519                             goto error;
   2520                         }
   2521                     }
   2522                 }
   2523                 goto return0;
   2524             }
   2525         case XML_SCHEMAS_BOOLEAN:{
   2526                 const xmlChar *cur = value;
   2527 
   2528 		if (normOnTheFly) {
   2529 		    while IS_WSP_BLANK_CH(*cur) cur++;
   2530 		    if (*cur == '0') {
   2531 			ret = 0;
   2532 			cur++;
   2533 		    } else if (*cur == '1') {
   2534 			ret = 1;
   2535 			cur++;
   2536 		    } else if (*cur == 't') {
   2537 			cur++;
   2538 			if ((*cur++ == 'r') && (*cur++ == 'u') &&
   2539 			    (*cur++ == 'e')) {
   2540 			    ret = 1;
   2541 			} else
   2542 			    goto return1;
   2543 		    } else if (*cur == 'f') {
   2544 			cur++;
   2545 			if ((*cur++ == 'a') && (*cur++ == 'l') &&
   2546 			    (*cur++ == 's') && (*cur++ == 'e')) {
   2547 			    ret = 0;
   2548 			} else
   2549 			    goto return1;
   2550 		    } else
   2551 			goto return1;
   2552 		    if (*cur != 0) {
   2553 			while IS_WSP_BLANK_CH(*cur) cur++;
   2554 			if (*cur != 0)
   2555 			    goto return1;
   2556 		    }
   2557 		} else {
   2558 		    if ((cur[0] == '0') && (cur[1] == 0))
   2559 			ret = 0;
   2560 		    else if ((cur[0] == '1') && (cur[1] == 0))
   2561 			ret = 1;
   2562 		    else if ((cur[0] == 't') && (cur[1] == 'r')
   2563 			&& (cur[2] == 'u') && (cur[3] == 'e')
   2564 			&& (cur[4] == 0))
   2565 			ret = 1;
   2566 		    else if ((cur[0] == 'f') && (cur[1] == 'a')
   2567 			&& (cur[2] == 'l') && (cur[3] == 's')
   2568 			&& (cur[4] == 'e') && (cur[5] == 0))
   2569 			ret = 0;
   2570 		    else
   2571 			goto return1;
   2572 		}
   2573                 if (val != NULL) {
   2574                     v = xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN);
   2575                     if (v != NULL) {
   2576                         v->value.b = ret;
   2577                         *val = v;
   2578                     } else {
   2579                         goto error;
   2580                     }
   2581                 }
   2582                 goto return0;
   2583             }
   2584         case XML_SCHEMAS_TOKEN:{
   2585                 const xmlChar *cur = value;
   2586 
   2587 		if (! normOnTheFly) {
   2588 		    while (*cur != 0) {
   2589 			if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
   2590 			    goto return1;
   2591 			} else if (*cur == ' ') {
   2592 			    cur++;
   2593 			    if (*cur == 0)
   2594 				goto return1;
   2595 			    if (*cur == ' ')
   2596 				goto return1;
   2597 			} else {
   2598 			    cur++;
   2599 			}
   2600 		    }
   2601 		}
   2602                 if (val != NULL) {
   2603                     v = xmlSchemaNewValue(XML_SCHEMAS_TOKEN);
   2604                     if (v != NULL) {
   2605                         v->value.str = xmlStrdup(value);
   2606                         *val = v;
   2607                     } else {
   2608                         goto error;
   2609                     }
   2610                 }
   2611                 goto return0;
   2612             }
   2613         case XML_SCHEMAS_LANGUAGE:
   2614 	    if (normOnTheFly) {
   2615 		norm = xmlSchemaCollapseString(value);
   2616 		if (norm != NULL)
   2617 		    value = norm;
   2618 	    }
   2619             if (xmlCheckLanguageID(value) == 1) {
   2620                 if (val != NULL) {
   2621                     v = xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE);
   2622                     if (v != NULL) {
   2623                         v->value.str = xmlStrdup(value);
   2624                         *val = v;
   2625                     } else {
   2626                         goto error;
   2627                     }
   2628                 }
   2629                 goto return0;
   2630             }
   2631             goto return1;
   2632         case XML_SCHEMAS_NMTOKEN:
   2633             if (xmlValidateNMToken(value, 1) == 0) {
   2634                 if (val != NULL) {
   2635                     v = xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN);
   2636                     if (v != NULL) {
   2637                         v->value.str = xmlStrdup(value);
   2638                         *val = v;
   2639                     } else {
   2640                         goto error;
   2641                     }
   2642                 }
   2643                 goto return0;
   2644             }
   2645             goto return1;
   2646         case XML_SCHEMAS_NMTOKENS:
   2647             ret = xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef,
   2648                                              value, val, node);
   2649             if (ret > 0)
   2650                 ret = 0;
   2651             else
   2652                 ret = 1;
   2653             goto done;
   2654         case XML_SCHEMAS_NAME:
   2655             ret = xmlValidateName(value, 1);
   2656             if ((ret == 0) && (val != NULL) && (value != NULL)) {
   2657 		v = xmlSchemaNewValue(XML_SCHEMAS_NAME);
   2658 		if (v != NULL) {
   2659 		     const xmlChar *start = value, *end;
   2660 		     while (IS_BLANK_CH(*start)) start++;
   2661 		     end = start;
   2662 		     while ((*end != 0) && (!IS_BLANK_CH(*end))) end++;
   2663 		     v->value.str = xmlStrndup(start, end - start);
   2664 		    *val = v;
   2665 		} else {
   2666 		    goto error;
   2667 		}
   2668             }
   2669             goto done;
   2670         case XML_SCHEMAS_QNAME:{
   2671                 const xmlChar *uri = NULL;
   2672                 xmlChar *local = NULL;
   2673 
   2674                 ret = xmlValidateQName(value, 1);
   2675 		if (ret != 0)
   2676 		    goto done;
   2677                 if (node != NULL) {
   2678                     xmlChar *prefix;
   2679 		    xmlNsPtr ns;
   2680 
   2681                     local = xmlSplitQName2(value, &prefix);
   2682 		    ns = xmlSearchNs(node->doc, node, prefix);
   2683 		    if ((ns == NULL) && (prefix != NULL)) {
   2684 			xmlFree(prefix);
   2685 			if (local != NULL)
   2686 			    xmlFree(local);
   2687 			goto return1;
   2688 		    }
   2689 		    if (ns != NULL)
   2690 			uri = ns->href;
   2691                     if (prefix != NULL)
   2692                         xmlFree(prefix);
   2693                 }
   2694                 if (val != NULL) {
   2695                     v = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
   2696                     if (v == NULL) {
   2697 			if (local != NULL)
   2698 			    xmlFree(local);
   2699 			goto error;
   2700 		    }
   2701 		    if (local != NULL)
   2702 			v->value.qname.name = local;
   2703 		    else
   2704 			v->value.qname.name = xmlStrdup(value);
   2705 		    if (uri != NULL)
   2706 			v->value.qname.uri = xmlStrdup(uri);
   2707 		    *val = v;
   2708                 } else
   2709 		    if (local != NULL)
   2710 			xmlFree(local);
   2711                 goto done;
   2712             }
   2713         case XML_SCHEMAS_NCNAME:
   2714             ret = xmlValidateNCName(value, 1);
   2715             if ((ret == 0) && (val != NULL)) {
   2716                 v = xmlSchemaNewValue(XML_SCHEMAS_NCNAME);
   2717                 if (v != NULL) {
   2718                     v->value.str = xmlStrdup(value);
   2719                     *val = v;
   2720                 } else {
   2721                     goto error;
   2722                 }
   2723             }
   2724             goto done;
   2725         case XML_SCHEMAS_ID:
   2726             ret = xmlValidateNCName(value, 1);
   2727             if ((ret == 0) && (val != NULL)) {
   2728                 v = xmlSchemaNewValue(XML_SCHEMAS_ID);
   2729                 if (v != NULL) {
   2730                     v->value.str = xmlStrdup(value);
   2731                     *val = v;
   2732                 } else {
   2733                     goto error;
   2734                 }
   2735             }
   2736             if ((ret == 0) && (node != NULL) &&
   2737                 (node->type == XML_ATTRIBUTE_NODE)) {
   2738                 xmlAttrPtr attr = (xmlAttrPtr) node;
   2739 
   2740                 /*
   2741                  * NOTE: the IDness might have already be declared in the DTD
   2742                  */
   2743                 if (attr->atype != XML_ATTRIBUTE_ID) {
   2744                     xmlIDPtr res;
   2745                     xmlChar *strip;
   2746 
   2747                     strip = xmlSchemaStrip(value);
   2748                     if (strip != NULL) {
   2749                         res = xmlAddID(NULL, node->doc, strip, attr);
   2750                         xmlFree(strip);
   2751                     } else
   2752                         res = xmlAddID(NULL, node->doc, value, attr);
   2753                     if (res == NULL) {
   2754                         ret = 2;
   2755                     } else {
   2756                         attr->atype = XML_ATTRIBUTE_ID;
   2757                     }
   2758                 }
   2759             }
   2760             goto done;
   2761         case XML_SCHEMAS_IDREF:
   2762             ret = xmlValidateNCName(value, 1);
   2763             if ((ret == 0) && (val != NULL)) {
   2764 		v = xmlSchemaNewValue(XML_SCHEMAS_IDREF);
   2765 		if (v == NULL)
   2766 		    goto error;
   2767 		v->value.str = xmlStrdup(value);
   2768 		*val = v;
   2769             }
   2770             if ((ret == 0) && (node != NULL) &&
   2771                 (node->type == XML_ATTRIBUTE_NODE)) {
   2772                 xmlAttrPtr attr = (xmlAttrPtr) node;
   2773                 xmlChar *strip;
   2774 
   2775                 strip = xmlSchemaStrip(value);
   2776                 if (strip != NULL) {
   2777                     xmlAddRef(NULL, node->doc, strip, attr);
   2778                     xmlFree(strip);
   2779                 } else
   2780                     xmlAddRef(NULL, node->doc, value, attr);
   2781                 attr->atype = XML_ATTRIBUTE_IDREF;
   2782             }
   2783             goto done;
   2784         case XML_SCHEMAS_IDREFS:
   2785             ret = xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef,
   2786                                              value, val, node);
   2787             if (ret < 0)
   2788                 ret = 2;
   2789             else
   2790                 ret = 0;
   2791             if ((ret == 0) && (node != NULL) &&
   2792                 (node->type == XML_ATTRIBUTE_NODE)) {
   2793                 xmlAttrPtr attr = (xmlAttrPtr) node;
   2794 
   2795                 attr->atype = XML_ATTRIBUTE_IDREFS;
   2796             }
   2797             goto done;
   2798         case XML_SCHEMAS_ENTITY:{
   2799                 xmlChar *strip;
   2800 
   2801                 ret = xmlValidateNCName(value, 1);
   2802                 if ((node == NULL) || (node->doc == NULL))
   2803                     ret = 3;
   2804                 if (ret == 0) {
   2805                     xmlEntityPtr ent;
   2806 
   2807                     strip = xmlSchemaStrip(value);
   2808                     if (strip != NULL) {
   2809                         ent = xmlGetDocEntity(node->doc, strip);
   2810                         xmlFree(strip);
   2811                     } else {
   2812                         ent = xmlGetDocEntity(node->doc, value);
   2813                     }
   2814                     if ((ent == NULL) ||
   2815                         (ent->etype !=
   2816                          XML_EXTERNAL_GENERAL_UNPARSED_ENTITY))
   2817                         ret = 4;
   2818                 }
   2819                 if ((ret == 0) && (val != NULL)) {
   2820                     TODO;
   2821                 }
   2822                 if ((ret == 0) && (node != NULL) &&
   2823                     (node->type == XML_ATTRIBUTE_NODE)) {
   2824                     xmlAttrPtr attr = (xmlAttrPtr) node;
   2825 
   2826                     attr->atype = XML_ATTRIBUTE_ENTITY;
   2827                 }
   2828                 goto done;
   2829             }
   2830         case XML_SCHEMAS_ENTITIES:
   2831             if ((node == NULL) || (node->doc == NULL))
   2832                 goto return3;
   2833             ret = xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef,
   2834                                              value, val, node);
   2835             if (ret <= 0)
   2836                 ret = 1;
   2837             else
   2838                 ret = 0;
   2839             if ((ret == 0) && (node != NULL) &&
   2840                 (node->type == XML_ATTRIBUTE_NODE)) {
   2841                 xmlAttrPtr attr = (xmlAttrPtr) node;
   2842 
   2843                 attr->atype = XML_ATTRIBUTE_ENTITIES;
   2844             }
   2845             goto done;
   2846         case XML_SCHEMAS_NOTATION:{
   2847                 xmlChar *uri = NULL;
   2848                 xmlChar *local = NULL;
   2849 
   2850                 ret = xmlValidateQName(value, 1);
   2851                 if ((ret == 0) && (node != NULL)) {
   2852                     xmlChar *prefix;
   2853 
   2854                     local = xmlSplitQName2(value, &prefix);
   2855                     if (prefix != NULL) {
   2856                         xmlNsPtr ns;
   2857 
   2858                         ns = xmlSearchNs(node->doc, node, prefix);
   2859                         if (ns == NULL)
   2860                             ret = 1;
   2861                         else if (val != NULL)
   2862                             uri = xmlStrdup(ns->href);
   2863                     }
   2864                     if ((local != NULL) && ((val == NULL) || (ret != 0)))
   2865                         xmlFree(local);
   2866                     if (prefix != NULL)
   2867                         xmlFree(prefix);
   2868                 }
   2869                 if ((node == NULL) || (node->doc == NULL))
   2870                     ret = 3;
   2871                 if (ret == 0) {
   2872                     ret = xmlValidateNotationUse(NULL, node->doc, value);
   2873                     if (ret == 1)
   2874                         ret = 0;
   2875                     else
   2876                         ret = 1;
   2877                 }
   2878                 if ((ret == 0) && (val != NULL)) {
   2879                     v = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
   2880                     if (v != NULL) {
   2881                         if (local != NULL)
   2882                             v->value.qname.name = local;
   2883                         else
   2884                             v->value.qname.name = xmlStrdup(value);
   2885                         if (uri != NULL)
   2886                             v->value.qname.uri = uri;
   2887 
   2888                         *val = v;
   2889                     } else {
   2890                         if (local != NULL)
   2891                             xmlFree(local);
   2892                         if (uri != NULL)
   2893                             xmlFree(uri);
   2894                         goto error;
   2895                     }
   2896                 }
   2897                 goto done;
   2898             }
   2899         case XML_SCHEMAS_ANYURI:{
   2900                 if (*value != 0) {
   2901 		    xmlURIPtr uri;
   2902 		    if (normOnTheFly) {
   2903 			norm = xmlSchemaCollapseString(value);
   2904 			if (norm != NULL)
   2905 			    value = norm;
   2906 		    }
   2907                     uri = xmlParseURI((const char *) value);
   2908                     if (uri == NULL)
   2909                         goto return1;
   2910                     xmlFreeURI(uri);
   2911                 }
   2912 
   2913                 if (val != NULL) {
   2914                     v = xmlSchemaNewValue(XML_SCHEMAS_ANYURI);
   2915                     if (v == NULL)
   2916                         goto error;
   2917                     v->value.str = xmlStrdup(value);
   2918                     *val = v;
   2919                 }
   2920                 goto return0;
   2921             }
   2922         case XML_SCHEMAS_HEXBINARY:{
   2923                 const xmlChar *cur = value, *start;
   2924                 xmlChar *base;
   2925                 int total, i = 0;
   2926 
   2927                 if (cur == NULL)
   2928                     goto return1;
   2929 
   2930 		if (normOnTheFly)
   2931 		    while IS_WSP_BLANK_CH(*cur) cur++;
   2932 
   2933 		start = cur;
   2934                 while (((*cur >= '0') && (*cur <= '9')) ||
   2935                        ((*cur >= 'A') && (*cur <= 'F')) ||
   2936                        ((*cur >= 'a') && (*cur <= 'f'))) {
   2937                     i++;
   2938                     cur++;
   2939                 }
   2940 		if (normOnTheFly)
   2941 		    while IS_WSP_BLANK_CH(*cur) cur++;
   2942 
   2943                 if (*cur != 0)
   2944                     goto return1;
   2945                 if ((i % 2) != 0)
   2946                     goto return1;
   2947 
   2948                 if (val != NULL) {
   2949 
   2950                     v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY);
   2951                     if (v == NULL)
   2952                         goto error;
   2953 		    /*
   2954 		    * Copy only the normalized piece.
   2955 		    * CRITICAL TODO: Check this.
   2956 		    */
   2957                     cur = xmlStrndup(start, i);
   2958                     if (cur == NULL) {
   2959 		        xmlSchemaTypeErrMemory(node, "allocating hexbin data");
   2960                         xmlFree(v);
   2961                         goto return1;
   2962                     }
   2963 
   2964                     total = i / 2;      /* number of octets */
   2965 
   2966                     base = (xmlChar *) cur;
   2967                     while (i-- > 0) {
   2968                         if (*base >= 'a')
   2969                             *base = *base - ('a' - 'A');
   2970                         base++;
   2971                     }
   2972 
   2973                     v->value.hex.str = (xmlChar *) cur;
   2974                     v->value.hex.total = total;
   2975                     *val = v;
   2976                 }
   2977                 goto return0;
   2978             }
   2979         case XML_SCHEMAS_BASE64BINARY:{
   2980                 /* ISSUE:
   2981                  *
   2982                  * Ignore all stray characters? (yes, currently)
   2983                  * Worry about long lines? (no, currently)
   2984                  *
   2985                  * rfc2045.txt:
   2986                  *
   2987                  * "The encoded output stream must be represented in lines of
   2988                  * no more than 76 characters each.  All line breaks or other
   2989                  * characters not found in Table 1 must be ignored by decoding
   2990                  * software.  In base64 data, characters other than those in
   2991                  * Table 1, line breaks, and other white space probably
   2992                  * indicate a transmission error, about which a warning
   2993                  * message or even a message rejection might be appropriate
   2994                  * under some circumstances." */
   2995                 const xmlChar *cur = value;
   2996                 xmlChar *base;
   2997                 int total, i = 0, pad = 0;
   2998 
   2999                 if (cur == NULL)
   3000                     goto return1;
   3001 
   3002                 for (; *cur; ++cur) {
   3003                     int decc;
   3004 
   3005                     decc = _xmlSchemaBase64Decode(*cur);
   3006                     if (decc < 0) ;
   3007                     else if (decc < 64)
   3008                         i++;
   3009                     else
   3010                         break;
   3011                 }
   3012                 for (; *cur; ++cur) {
   3013                     int decc;
   3014 
   3015                     decc = _xmlSchemaBase64Decode(*cur);
   3016                     if (decc < 0) ;
   3017                     else if (decc < 64)
   3018                         goto return1;
   3019                     if (decc == 64)
   3020                         pad++;
   3021                 }
   3022 
   3023                 /* rfc2045.txt: "Special processing is performed if fewer than
   3024                  * 24 bits are available at the end of the data being encoded.
   3025                  * A full encoding quantum is always completed at the end of a
   3026                  * body.  When fewer than 24 input bits are available in an
   3027                  * input group, zero bits are added (on the right) to form an
   3028                  * integral number of 6-bit groups.  Padding at the end of the
   3029                  * data is performed using the "=" character.  Since all
   3030                  * base64 input is an integral number of octets, only the
   3031                  * following cases can arise: (1) the final quantum of
   3032                  * encoding input is an integral multiple of 24 bits; here,
   3033                  * the final unit of encoded output will be an integral
   3034                  * multiple ofindent: Standard input:701: Warning:old style
   3035 		 * assignment ambiguity in "=*".  Assuming "= *" 4 characters
   3036 		 * with no "=" padding, (2) the final
   3037                  * quantum of encoding input is exactly 8 bits; here, the
   3038                  * final unit of encoded output will be two characters
   3039                  * followed by two "=" padding characters, or (3) the final
   3040                  * quantum of encoding input is exactly 16 bits; here, the
   3041                  * final unit of encoded output will be three characters
   3042                  * followed by one "=" padding character." */
   3043 
   3044                 total = 3 * (i / 4);
   3045                 if (pad == 0) {
   3046                     if (i % 4 != 0)
   3047                         goto return1;
   3048                 } else if (pad == 1) {
   3049                     int decc;
   3050 
   3051                     if (i % 4 != 3)
   3052                         goto return1;
   3053                     for (decc = _xmlSchemaBase64Decode(*cur);
   3054                          (decc < 0) || (decc > 63);
   3055                          decc = _xmlSchemaBase64Decode(*cur))
   3056                         --cur;
   3057                     /* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00*/
   3058                     /* 00111100 -> 0x3c */
   3059                     if (decc & ~0x3c)
   3060                         goto return1;
   3061                     total += 2;
   3062                 } else if (pad == 2) {
   3063                     int decc;
   3064 
   3065                     if (i % 4 != 2)
   3066                         goto return1;
   3067                     for (decc = _xmlSchemaBase64Decode(*cur);
   3068                          (decc < 0) || (decc > 63);
   3069                          decc = _xmlSchemaBase64Decode(*cur))
   3070                         --cur;
   3071                     /* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */
   3072                     /* 00110000 -> 0x30 */
   3073                     if (decc & ~0x30)
   3074                         goto return1;
   3075                     total += 1;
   3076                 } else
   3077                     goto return1;
   3078 
   3079                 if (val != NULL) {
   3080                     v = xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY);
   3081                     if (v == NULL)
   3082                         goto error;
   3083                     base =
   3084                         (xmlChar *) xmlMallocAtomic((i + pad + 1) *
   3085                                                     sizeof(xmlChar));
   3086                     if (base == NULL) {
   3087 		        xmlSchemaTypeErrMemory(node, "allocating base64 data");
   3088                         xmlFree(v);
   3089                         goto return1;
   3090                     }
   3091                     v->value.base64.str = base;
   3092                     for (cur = value; *cur; ++cur)
   3093                         if (_xmlSchemaBase64Decode(*cur) >= 0) {
   3094                             *base = *cur;
   3095                             ++base;
   3096                         }
   3097                     *base = 0;
   3098                     v->value.base64.total = total;
   3099                     *val = v;
   3100                 }
   3101                 goto return0;
   3102             }
   3103         case XML_SCHEMAS_INTEGER:
   3104         case XML_SCHEMAS_PINTEGER:
   3105         case XML_SCHEMAS_NPINTEGER:
   3106         case XML_SCHEMAS_NINTEGER:
   3107         case XML_SCHEMAS_NNINTEGER:{
   3108                 const xmlChar *cur = value;
   3109                 unsigned long lo, mi, hi;
   3110                 int sign = 0;
   3111 
   3112                 if (cur == NULL)
   3113                     goto return1;
   3114 		if (normOnTheFly)
   3115 		    while IS_WSP_BLANK_CH(*cur) cur++;
   3116                 if (*cur == '-') {
   3117                     sign = 1;
   3118                     cur++;
   3119                 } else if (*cur == '+')
   3120                     cur++;
   3121                 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
   3122                 if (ret < 0)
   3123                     goto return1;
   3124 		if (normOnTheFly)
   3125 		    while IS_WSP_BLANK_CH(*cur) cur++;
   3126                 if (*cur != 0)
   3127                     goto return1;
   3128                 if (type->builtInType == XML_SCHEMAS_NPINTEGER) {
   3129                     if ((sign == 0) &&
   3130                         ((hi != 0) || (mi != 0) || (lo != 0)))
   3131                         goto return1;
   3132                 } else if (type->builtInType == XML_SCHEMAS_PINTEGER) {
   3133                     if (sign == 1)
   3134                         goto return1;
   3135                     if ((hi == 0) && (mi == 0) && (lo == 0))
   3136                         goto return1;
   3137                 } else if (type->builtInType == XML_SCHEMAS_NINTEGER) {
   3138                     if (sign == 0)
   3139                         goto return1;
   3140                     if ((hi == 0) && (mi == 0) && (lo == 0))
   3141                         goto return1;
   3142                 } else if (type->builtInType == XML_SCHEMAS_NNINTEGER) {
   3143                     if ((sign == 1) &&
   3144                         ((hi != 0) || (mi != 0) || (lo != 0)))
   3145                         goto return1;
   3146                 }
   3147                 if (val != NULL) {
   3148                     v = xmlSchemaNewValue(type->builtInType);
   3149                     if (v != NULL) {
   3150 			if (ret == 0)
   3151 			    ret++;
   3152                         v->value.decimal.lo = lo;
   3153                         v->value.decimal.mi = mi;
   3154                         v->value.decimal.hi = hi;
   3155                         v->value.decimal.sign = sign;
   3156                         v->value.decimal.frac = 0;
   3157                         v->value.decimal.total = ret;
   3158                         *val = v;
   3159                     }
   3160                 }
   3161                 goto return0;
   3162             }
   3163         case XML_SCHEMAS_LONG:
   3164         case XML_SCHEMAS_BYTE:
   3165         case XML_SCHEMAS_SHORT:
   3166         case XML_SCHEMAS_INT:{
   3167                 const xmlChar *cur = value;
   3168                 unsigned long lo, mi, hi;
   3169                 int sign = 0;
   3170 
   3171                 if (cur == NULL)
   3172                     goto return1;
   3173                 if (*cur == '-') {
   3174                     sign = 1;
   3175                     cur++;
   3176                 } else if (*cur == '+')
   3177                     cur++;
   3178                 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
   3179                 if (ret < 0)
   3180                     goto return1;
   3181                 if (*cur != 0)
   3182                     goto return1;
   3183                 if (type->builtInType == XML_SCHEMAS_LONG) {
   3184                     if (hi >= 922) {
   3185                         if (hi > 922)
   3186                             goto return1;
   3187                         if (mi >= 33720368) {
   3188                             if (mi > 33720368)
   3189                                 goto return1;
   3190                             if ((sign == 0) && (lo > 54775807))
   3191                                 goto return1;
   3192                             if ((sign == 1) && (lo > 54775808))
   3193                                 goto return1;
   3194                         }
   3195                     }
   3196                 } else if (type->builtInType == XML_SCHEMAS_INT) {
   3197                     if (hi != 0)
   3198                         goto return1;
   3199                     if (mi >= 21) {
   3200                         if (mi > 21)
   3201                             goto return1;
   3202                         if ((sign == 0) && (lo > 47483647))
   3203                             goto return1;
   3204                         if ((sign == 1) && (lo > 47483648))
   3205                             goto return1;
   3206                     }
   3207                 } else if (type->builtInType == XML_SCHEMAS_SHORT) {
   3208                     if ((mi != 0) || (hi != 0))
   3209                         goto return1;
   3210                     if ((sign == 1) && (lo > 32768))
   3211                         goto return1;
   3212                     if ((sign == 0) && (lo > 32767))
   3213                         goto return1;
   3214                 } else if (type->builtInType == XML_SCHEMAS_BYTE) {
   3215                     if ((mi != 0) || (hi != 0))
   3216                         goto return1;
   3217                     if ((sign == 1) && (lo > 128))
   3218                         goto return1;
   3219                     if ((sign == 0) && (lo > 127))
   3220                         goto return1;
   3221                 }
   3222                 if (val != NULL) {
   3223                     v = xmlSchemaNewValue(type->builtInType);
   3224                     if (v != NULL) {
   3225                         v->value.decimal.lo = lo;
   3226                         v->value.decimal.mi = mi;
   3227                         v->value.decimal.hi = hi;
   3228                         v->value.decimal.sign = sign;
   3229                         v->value.decimal.frac = 0;
   3230                         v->value.decimal.total = ret;
   3231                         *val = v;
   3232                     }
   3233                 }
   3234                 goto return0;
   3235             }
   3236         case XML_SCHEMAS_UINT:
   3237         case XML_SCHEMAS_ULONG:
   3238         case XML_SCHEMAS_USHORT:
   3239         case XML_SCHEMAS_UBYTE:{
   3240                 const xmlChar *cur = value;
   3241                 unsigned long lo, mi, hi;
   3242 
   3243                 if (cur == NULL)
   3244                     goto return1;
   3245                 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
   3246                 if (ret < 0)
   3247                     goto return1;
   3248                 if (*cur != 0)
   3249                     goto return1;
   3250                 if (type->builtInType == XML_SCHEMAS_ULONG) {
   3251                     if (hi >= 1844) {
   3252                         if (hi > 1844)
   3253                             goto return1;
   3254                         if (mi >= 67440737) {
   3255                             if (mi > 67440737)
   3256                                 goto return1;
   3257                             if (lo > 9551615)
   3258                                 goto return1;
   3259                         }
   3260                     }
   3261                 } else if (type->builtInType == XML_SCHEMAS_UINT) {
   3262                     if (hi != 0)
   3263                         goto return1;
   3264                     if (mi >= 42) {
   3265                         if (mi > 42)
   3266                             goto return1;
   3267                         if (lo > 94967295)
   3268                             goto return1;
   3269                     }
   3270                 } else if (type->builtInType == XML_SCHEMAS_USHORT) {
   3271                     if ((mi != 0) || (hi != 0))
   3272                         goto return1;
   3273                     if (lo > 65535)
   3274                         goto return1;
   3275                 } else if (type->builtInType == XML_SCHEMAS_UBYTE) {
   3276                     if ((mi != 0) || (hi != 0))
   3277                         goto return1;
   3278                     if (lo > 255)
   3279                         goto return1;
   3280                 }
   3281                 if (val != NULL) {
   3282                     v = xmlSchemaNewValue(type->builtInType);
   3283                     if (v != NULL) {
   3284                         v->value.decimal.lo = lo;
   3285                         v->value.decimal.mi = mi;
   3286                         v->value.decimal.hi = hi;
   3287                         v->value.decimal.sign = 0;
   3288                         v->value.decimal.frac = 0;
   3289                         v->value.decimal.total = ret;
   3290                         *val = v;
   3291                     }
   3292                 }
   3293                 goto return0;
   3294             }
   3295     }
   3296 
   3297   done:
   3298     if (norm != NULL)
   3299         xmlFree(norm);
   3300     return (ret);
   3301   return3:
   3302     if (norm != NULL)
   3303         xmlFree(norm);
   3304     return (3);
   3305   return1:
   3306     if (norm != NULL)
   3307         xmlFree(norm);
   3308     return (1);
   3309   return0:
   3310     if (norm != NULL)
   3311         xmlFree(norm);
   3312     return (0);
   3313   error:
   3314     if (norm != NULL)
   3315         xmlFree(norm);
   3316     return (-1);
   3317 }
   3318 
   3319 /**
   3320  * xmlSchemaValPredefTypeNode:
   3321  * @type: the predefined type
   3322  * @value: the value to check
   3323  * @val:  the return computed value
   3324  * @node:  the node containing the value
   3325  *
   3326  * Check that a value conforms to the lexical space of the predefined type.
   3327  * if true a value is computed and returned in @val.
   3328  *
   3329  * Returns 0 if this validates, a positive error code number otherwise
   3330  *         and -1 in case of internal or API error.
   3331  */
   3332 int
   3333 xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type, const xmlChar *value,
   3334 	                   xmlSchemaValPtr *val, xmlNodePtr node) {
   3335     return(xmlSchemaValAtomicType(type, value, val, node, 0,
   3336 	XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 1, 0));
   3337 }
   3338 
   3339 /**
   3340  * xmlSchemaValPredefTypeNodeNoNorm:
   3341  * @type: the predefined type
   3342  * @value: the value to check
   3343  * @val:  the return computed value
   3344  * @node:  the node containing the value
   3345  *
   3346  * Check that a value conforms to the lexical space of the predefined type.
   3347  * if true a value is computed and returned in @val.
   3348  * This one does apply any normalization to the value.
   3349  *
   3350  * Returns 0 if this validates, a positive error code number otherwise
   3351  *         and -1 in case of internal or API error.
   3352  */
   3353 int
   3354 xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type, const xmlChar *value,
   3355 				 xmlSchemaValPtr *val, xmlNodePtr node) {
   3356     return(xmlSchemaValAtomicType(type, value, val, node, 1,
   3357 	XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 0, 1));
   3358 }
   3359 
   3360 /**
   3361  * xmlSchemaValidatePredefinedType:
   3362  * @type: the predefined type
   3363  * @value: the value to check
   3364  * @val:  the return computed value
   3365  *
   3366  * Check that a value conforms to the lexical space of the predefined type.
   3367  * if true a value is computed and returned in @val.
   3368  *
   3369  * Returns 0 if this validates, a positive error code number otherwise
   3370  *         and -1 in case of internal or API error.
   3371  */
   3372 int
   3373 xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
   3374 	                        xmlSchemaValPtr *val) {
   3375     return(xmlSchemaValPredefTypeNode(type, value, val, NULL));
   3376 }
   3377 
   3378 /**
   3379  * xmlSchemaCompareDecimals:
   3380  * @x:  a first decimal value
   3381  * @y:  a second decimal value
   3382  *
   3383  * Compare 2 decimals
   3384  *
   3385  * Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error
   3386  */
   3387 static int
   3388 xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
   3389 {
   3390     xmlSchemaValPtr swp;
   3391     int order = 1, integx, integy, dlen;
   3392     unsigned long hi, mi, lo;
   3393 
   3394     /*
   3395      * First test: If x is -ve and not zero
   3396      */
   3397     if ((x->value.decimal.sign) &&
   3398 	((x->value.decimal.lo != 0) ||
   3399 	 (x->value.decimal.mi != 0) ||
   3400 	 (x->value.decimal.hi != 0))) {
   3401 	/*
   3402 	 * Then if y is -ve and not zero reverse the compare
   3403 	 */
   3404 	if ((y->value.decimal.sign) &&
   3405 	    ((y->value.decimal.lo != 0) ||
   3406 	     (y->value.decimal.mi != 0) ||
   3407 	     (y->value.decimal.hi != 0)))
   3408 	    order = -1;
   3409 	/*
   3410 	 * Otherwise (y >= 0) we have the answer
   3411 	 */
   3412 	else
   3413 	    return (-1);
   3414     /*
   3415      * If x is not -ve and y is -ve we have the answer
   3416      */
   3417     } else if ((y->value.decimal.sign) &&
   3418 	       ((y->value.decimal.lo != 0) ||
   3419 		(y->value.decimal.mi != 0) ||
   3420 		(y->value.decimal.hi != 0))) {
   3421         return (1);
   3422     }
   3423     /*
   3424      * If it's not simply determined by a difference in sign,
   3425      * then we need to compare the actual values of the two nums.
   3426      * To do this, we start by looking at the integral parts.
   3427      * If the number of integral digits differ, then we have our
   3428      * answer.
   3429      */
   3430     integx = x->value.decimal.total - x->value.decimal.frac;
   3431     integy = y->value.decimal.total - y->value.decimal.frac;
   3432     /*
   3433     * NOTE: We changed the "total" for values like "0.1"
   3434     *   (or "-0.1" or ".1") to be 1, which was 2 previously.
   3435     *   Therefore the special case, when such values are
   3436     *   compared with 0, needs to be handled separately;
   3437     *   otherwise a zero would be recognized incorrectly as
   3438     *   greater than those values. This has the nice side effect
   3439     *   that we gain an overall optimized comparison with zeroes.
   3440     * Note that a "0" has a "total" of 1 already.
   3441     */
   3442     if (integx == 1) {
   3443 	if (x->value.decimal.lo == 0) {
   3444 	    if (integy != 1)
   3445 		return -order;
   3446 	    else if (y->value.decimal.lo != 0)
   3447 		return -order;
   3448 	    else
   3449 		return(0);
   3450 	}
   3451     }
   3452     if (integy == 1) {
   3453 	if (y->value.decimal.lo == 0) {
   3454 	    if (integx != 1)
   3455 		return order;
   3456 	    else if (x->value.decimal.lo != 0)
   3457 		return order;
   3458 	    else
   3459 		return(0);
   3460 	}
   3461     }
   3462 
   3463     if (integx > integy)
   3464 	return order;
   3465     else if (integy > integx)
   3466 	return -order;
   3467 
   3468     /*
   3469      * If the number of integral digits is the same for both numbers,
   3470      * then things get a little more complicated.  We need to "normalize"
   3471      * the numbers in order to properly compare them.  To do this, we
   3472      * look at the total length of each number (length => number of
   3473      * significant digits), and divide the "shorter" by 10 (decreasing
   3474      * the length) until they are of equal length.
   3475      */
   3476     dlen = x->value.decimal.total - y->value.decimal.total;
   3477     if (dlen < 0) {	/* y has more digits than x */
   3478 	swp = x;
   3479 	hi = y->value.decimal.hi;
   3480 	mi = y->value.decimal.mi;
   3481 	lo = y->value.decimal.lo;
   3482 	dlen = -dlen;
   3483 	order = -order;
   3484     } else {		/* x has more digits than y */
   3485 	swp = y;
   3486 	hi = x->value.decimal.hi;
   3487 	mi = x->value.decimal.mi;
   3488 	lo = x->value.decimal.lo;
   3489     }
   3490     while (dlen > 8) {	/* in effect, right shift by 10**8 */
   3491 	lo = mi;
   3492 	mi = hi;
   3493 	hi = 0;
   3494 	dlen -= 8;
   3495     }
   3496     while (dlen > 0) {
   3497 	unsigned long rem1, rem2;
   3498 	rem1 = (hi % 10) * 100000000L;
   3499 	hi = hi / 10;
   3500 	rem2 = (mi % 10) * 100000000L;
   3501 	mi = (mi + rem1) / 10;
   3502 	lo = (lo + rem2) / 10;
   3503 	dlen--;
   3504     }
   3505     if (hi > swp->value.decimal.hi) {
   3506 	return order;
   3507     } else if (hi == swp->value.decimal.hi) {
   3508 	if (mi > swp->value.decimal.mi) {
   3509 	    return order;
   3510 	} else if (mi == swp->value.decimal.mi) {
   3511 	    if (lo > swp->value.decimal.lo) {
   3512 		return order;
   3513 	    } else if (lo == swp->value.decimal.lo) {
   3514 		if (x->value.decimal.total == y->value.decimal.total) {
   3515 		    return 0;
   3516 		} else {
   3517 		    return order;
   3518 		}
   3519 	    }
   3520 	}
   3521     }
   3522     return -order;
   3523 }
   3524 
   3525 /**
   3526  * xmlSchemaCompareDurations:
   3527  * @x:  a first duration value
   3528  * @y:  a second duration value
   3529  *
   3530  * Compare 2 durations
   3531  *
   3532  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
   3533  * case of error
   3534  */
   3535 static int
   3536 xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y)
   3537 {
   3538     long carry, mon, day;
   3539     double sec;
   3540     int invert = 1;
   3541     long xmon, xday, myear, minday, maxday;
   3542     static const long dayRange [2][12] = {
   3543         { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, },
   3544         { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} };
   3545 
   3546     if ((x == NULL) || (y == NULL))
   3547         return -2;
   3548 
   3549     /* months */
   3550     mon = x->value.dur.mon - y->value.dur.mon;
   3551 
   3552     /* seconds */
   3553     sec = x->value.dur.sec - y->value.dur.sec;
   3554     carry = (long)sec / SECS_PER_DAY;
   3555     sec -= (double)(carry * SECS_PER_DAY);
   3556 
   3557     /* days */
   3558     day = x->value.dur.day - y->value.dur.day + carry;
   3559 
   3560     /* easy test */
   3561     if (mon == 0) {
   3562         if (day == 0)
   3563             if (sec == 0.0)
   3564                 return 0;
   3565             else if (sec < 0.0)
   3566                 return -1;
   3567             else
   3568                 return 1;
   3569         else if (day < 0)
   3570             return -1;
   3571         else
   3572             return 1;
   3573     }
   3574 
   3575     if (mon > 0) {
   3576         if ((day >= 0) && (sec >= 0.0))
   3577             return 1;
   3578         else {
   3579             xmon = mon;
   3580             xday = -day;
   3581         }
   3582     } else if ((day <= 0) && (sec <= 0.0)) {
   3583         return -1;
   3584     } else {
   3585 	invert = -1;
   3586         xmon = -mon;
   3587         xday = day;
   3588     }
   3589 
   3590     myear = xmon / 12;
   3591     if (myear == 0) {
   3592 	minday = 0;
   3593 	maxday = 0;
   3594     } else {
   3595 	maxday = 366 * ((myear + 3) / 4) +
   3596 	         365 * ((myear - 1) % 4);
   3597 	minday = maxday - 1;
   3598     }
   3599 
   3600     xmon = xmon % 12;
   3601     minday += dayRange[0][xmon];
   3602     maxday += dayRange[1][xmon];
   3603 
   3604     if ((maxday == minday) && (maxday == xday))
   3605 	return(0); /* can this really happen ? */
   3606     if (maxday < xday)
   3607         return(-invert);
   3608     if (minday > xday)
   3609         return(invert);
   3610 
   3611     /* indeterminate */
   3612     return 2;
   3613 }
   3614 
   3615 /*
   3616  * macros for adding date/times and durations
   3617  */
   3618 #define FQUOTIENT(a,b)                  (floor(((double)a/(double)b)))
   3619 #define MODULO(a,b)                     (a - FQUOTIENT(a,b) * b)
   3620 #define FQUOTIENT_RANGE(a,low,high)     (FQUOTIENT((a-low),(high-low)))
   3621 #define MODULO_RANGE(a,low,high)        ((MODULO((a-low),(high-low)))+low)
   3622 
   3623 /**
   3624  * xmlSchemaDupVal:
   3625  * @v: the #xmlSchemaValPtr value to duplicate
   3626  *
   3627  * Makes a copy of @v. The calling program is responsible for freeing
   3628  * the returned value.
   3629  *
   3630  * returns a pointer to a duplicated #xmlSchemaValPtr or NULL if error.
   3631  */
   3632 static xmlSchemaValPtr
   3633 xmlSchemaDupVal (xmlSchemaValPtr v)
   3634 {
   3635     xmlSchemaValPtr ret = xmlSchemaNewValue(v->type);
   3636     if (ret == NULL)
   3637         return NULL;
   3638 
   3639     memcpy(ret, v, sizeof(xmlSchemaVal));
   3640     ret->next = NULL;
   3641     return ret;
   3642 }
   3643 
   3644 /**
   3645  * xmlSchemaCopyValue:
   3646  * @val:  the precomputed value to be copied
   3647  *
   3648  * Copies the precomputed value. This duplicates any string within.
   3649  *
   3650  * Returns the copy or NULL if a copy for a data-type is not implemented.
   3651  */
   3652 xmlSchemaValPtr
   3653 xmlSchemaCopyValue(xmlSchemaValPtr val)
   3654 {
   3655     xmlSchemaValPtr ret = NULL, prev = NULL, cur;
   3656 
   3657     /*
   3658     * Copy the string values.
   3659     */
   3660     while (val != NULL) {
   3661 	switch (val->type) {
   3662 	    case XML_SCHEMAS_ANYTYPE:
   3663 	    case XML_SCHEMAS_IDREFS:
   3664 	    case XML_SCHEMAS_ENTITIES:
   3665 	    case XML_SCHEMAS_NMTOKENS:
   3666 		xmlSchemaFreeValue(ret);
   3667 		return (NULL);
   3668 	    case XML_SCHEMAS_ANYSIMPLETYPE:
   3669 	    case XML_SCHEMAS_STRING:
   3670 	    case XML_SCHEMAS_NORMSTRING:
   3671 	    case XML_SCHEMAS_TOKEN:
   3672 	    case XML_SCHEMAS_LANGUAGE:
   3673 	    case XML_SCHEMAS_NAME:
   3674 	    case XML_SCHEMAS_NCNAME:
   3675 	    case XML_SCHEMAS_ID:
   3676 	    case XML_SCHEMAS_IDREF:
   3677 	    case XML_SCHEMAS_ENTITY:
   3678 	    case XML_SCHEMAS_NMTOKEN:
   3679 	    case XML_SCHEMAS_ANYURI:
   3680 		cur = xmlSchemaDupVal(val);
   3681 		if (val->value.str != NULL)
   3682 		    cur->value.str = xmlStrdup(BAD_CAST val->value.str);
   3683 		break;
   3684 	    case XML_SCHEMAS_QNAME:
   3685 	    case XML_SCHEMAS_NOTATION:
   3686 		cur = xmlSchemaDupVal(val);
   3687 		if (val->value.qname.name != NULL)
   3688 		    cur->value.qname.name =
   3689                     xmlStrdup(BAD_CAST val->value.qname.name);
   3690 		if (val->value.qname.uri != NULL)
   3691 		    cur->value.qname.uri =
   3692                     xmlStrdup(BAD_CAST val->value.qname.uri);
   3693 		break;
   3694 	    case XML_SCHEMAS_HEXBINARY:
   3695 		cur = xmlSchemaDupVal(val);
   3696 		if (val->value.hex.str != NULL)
   3697 		    cur->value.hex.str = xmlStrdup(BAD_CAST val->value.hex.str);
   3698 		break;
   3699 	    case XML_SCHEMAS_BASE64BINARY:
   3700 		cur = xmlSchemaDupVal(val);
   3701 		if (val->value.base64.str != NULL)
   3702 		    cur->value.base64.str =
   3703                     xmlStrdup(BAD_CAST val->value.base64.str);
   3704 		break;
   3705 	    default:
   3706 		cur = xmlSchemaDupVal(val);
   3707 		break;
   3708 	}
   3709 	if (ret == NULL)
   3710 	    ret = cur;
   3711 	else
   3712 	    prev->next = cur;
   3713 	prev = cur;
   3714 	val = val->next;
   3715     }
   3716     return (ret);
   3717 }
   3718 
   3719 /**
   3720  * _xmlSchemaDateAdd:
   3721  * @dt: an #xmlSchemaValPtr
   3722  * @dur: an #xmlSchemaValPtr of type #XS_DURATION
   3723  *
   3724  * Compute a new date/time from @dt and @dur. This function assumes @dt
   3725  * is either #XML_SCHEMAS_DATETIME, #XML_SCHEMAS_DATE, #XML_SCHEMAS_GYEARMONTH,
   3726  * or #XML_SCHEMAS_GYEAR. The returned #xmlSchemaVal is the same type as
   3727  * @dt. The calling program is responsible for freeing the returned value.
   3728  *
   3729  * Returns a pointer to a new #xmlSchemaVal or NULL if error.
   3730  */
   3731 static xmlSchemaValPtr
   3732 _xmlSchemaDateAdd (xmlSchemaValPtr dt, xmlSchemaValPtr dur)
   3733 {
   3734     xmlSchemaValPtr ret, tmp;
   3735     long carry, tempdays, temp;
   3736     xmlSchemaValDatePtr r, d;
   3737     xmlSchemaValDurationPtr u;
   3738 
   3739     if ((dt == NULL) || (dur == NULL))
   3740         return NULL;
   3741 
   3742     ret = xmlSchemaNewValue(dt->type);
   3743     if (ret == NULL)
   3744         return NULL;
   3745 
   3746     /* make a copy so we don't alter the original value */
   3747     tmp = xmlSchemaDupVal(dt);
   3748     if (tmp == NULL) {
   3749         xmlSchemaFreeValue(ret);
   3750         return NULL;
   3751     }
   3752 
   3753     r = &(ret->value.date);
   3754     d = &(tmp->value.date);
   3755     u = &(dur->value.dur);
   3756 
   3757     /* normalization */
   3758     if (d->mon == 0)
   3759         d->mon = 1;
   3760 
   3761     /* normalize for time zone offset */
   3762     u->sec -= (d->tzo * 60);
   3763     d->tzo = 0;
   3764 
   3765     /* normalization */
   3766     if (d->day == 0)
   3767         d->day = 1;
   3768 
   3769     /* month */
   3770     carry  = d->mon + u->mon;
   3771     r->mon = (unsigned int) MODULO_RANGE(carry, 1, 13);
   3772     carry  = (long) FQUOTIENT_RANGE(carry, 1, 13);
   3773 
   3774     /* year (may be modified later) */
   3775     r->year = d->year + carry;
   3776     if (r->year == 0) {
   3777         if (d->year > 0)
   3778             r->year--;
   3779         else
   3780             r->year++;
   3781     }
   3782 
   3783     /* time zone */
   3784     r->tzo     = d->tzo;
   3785     r->tz_flag = d->tz_flag;
   3786 
   3787     /* seconds */
   3788     r->sec = d->sec + u->sec;
   3789     carry  = (long) FQUOTIENT((long)r->sec, 60);
   3790     if (r->sec != 0.0) {
   3791         r->sec = MODULO(r->sec, 60.0);
   3792     }
   3793 
   3794     /* minute */
   3795     carry += d->min;
   3796     r->min = (unsigned int) MODULO(carry, 60);
   3797     carry  = (long) FQUOTIENT(carry, 60);
   3798 
   3799     /* hours */
   3800     carry  += d->hour;
   3801     r->hour = (unsigned int) MODULO(carry, 24);
   3802     carry   = (long)FQUOTIENT(carry, 24);
   3803 
   3804     /*
   3805      * days
   3806      * Note we use tempdays because the temporary values may need more
   3807      * than 5 bits
   3808      */
   3809     if ((VALID_YEAR(r->year)) && (VALID_MONTH(r->mon)) &&
   3810                   (d->day > MAX_DAYINMONTH(r->year, r->mon)))
   3811         tempdays = MAX_DAYINMONTH(r->year, r->mon);
   3812     else if (d->day < 1)
   3813         tempdays = 1;
   3814     else
   3815         tempdays = d->day;
   3816 
   3817     tempdays += u->day + carry;
   3818 
   3819     while (1) {
   3820         if (tempdays < 1) {
   3821             long tmon = (long) MODULO_RANGE((int)r->mon-1, 1, 13);
   3822             long tyr  = r->year + (long)FQUOTIENT_RANGE((int)r->mon-1, 1, 13);
   3823             if (tyr == 0)
   3824                 tyr--;
   3825 	    /*
   3826 	     * Coverity detected an overrun in daysInMonth
   3827 	     * of size 12 at position 12 with index variable "((r)->mon - 1)"
   3828 	     */
   3829 	    if (tmon < 0)
   3830 	        tmon = 0;
   3831 	    if (tmon > 12)
   3832 	        tmon = 12;
   3833             tempdays += MAX_DAYINMONTH(tyr, tmon);
   3834             carry = -1;
   3835         } else if (tempdays > (long) MAX_DAYINMONTH(r->year, r->mon)) {
   3836             tempdays = tempdays - MAX_DAYINMONTH(r->year, r->mon);
   3837             carry = 1;
   3838         } else
   3839             break;
   3840 
   3841         temp = r->mon + carry;
   3842         r->mon = (unsigned int) MODULO_RANGE(temp, 1, 13);
   3843         r->year = r->year + (unsigned int) FQUOTIENT_RANGE(temp, 1, 13);
   3844         if (r->year == 0) {
   3845             if (temp < 1)
   3846                 r->year--;
   3847             else
   3848                 r->year++;
   3849 	}
   3850     }
   3851 
   3852     r->day = tempdays;
   3853 
   3854     /*
   3855      * adjust the date/time type to the date values
   3856      */
   3857     if (ret->type != XML_SCHEMAS_DATETIME) {
   3858         if ((r->hour) || (r->min) || (r->sec))
   3859             ret->type = XML_SCHEMAS_DATETIME;
   3860         else if (ret->type != XML_SCHEMAS_DATE) {
   3861             if ((r->mon != 1) && (r->day != 1))
   3862                 ret->type = XML_SCHEMAS_DATE;
   3863             else if ((ret->type != XML_SCHEMAS_GYEARMONTH) && (r->mon != 1))
   3864                 ret->type = XML_SCHEMAS_GYEARMONTH;
   3865         }
   3866     }
   3867 
   3868     xmlSchemaFreeValue(tmp);
   3869 
   3870     return ret;
   3871 }
   3872 
   3873 /**
   3874  * xmlSchemaDateNormalize:
   3875  * @dt: an #xmlSchemaValPtr of a date/time type value.
   3876  * @offset: number of seconds to adjust @dt by.
   3877  *
   3878  * Normalize @dt to GMT time. The @offset parameter is subtracted from
   3879  * the return value is a time-zone offset is present on @dt.
   3880  *
   3881  * Returns a normalized copy of @dt or NULL if error.
   3882  */
   3883 static xmlSchemaValPtr
   3884 xmlSchemaDateNormalize (xmlSchemaValPtr dt, double offset)
   3885 {
   3886     xmlSchemaValPtr dur, ret;
   3887 
   3888     if (dt == NULL)
   3889         return NULL;
   3890 
   3891     if (((dt->type != XML_SCHEMAS_TIME) &&
   3892          (dt->type != XML_SCHEMAS_DATETIME) &&
   3893 	 (dt->type != XML_SCHEMAS_DATE)) || (dt->value.date.tzo == 0))
   3894         return xmlSchemaDupVal(dt);
   3895 
   3896     dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
   3897     if (dur == NULL)
   3898         return NULL;
   3899 
   3900     dur->value.date.sec -= offset;
   3901 
   3902     ret = _xmlSchemaDateAdd(dt, dur);
   3903     if (ret == NULL)
   3904         return NULL;
   3905 
   3906     xmlSchemaFreeValue(dur);
   3907 
   3908     /* ret->value.date.tzo = 0; */
   3909     return ret;
   3910 }
   3911 
   3912 /**
   3913  * _xmlSchemaDateCastYMToDays:
   3914  * @dt: an #xmlSchemaValPtr
   3915  *
   3916  * Convert mon and year of @dt to total number of days. Take the
   3917  * number of years since (or before) 1 AD and add the number of leap
   3918  * years. This is a function  because negative
   3919  * years must be handled a little differently and there is no zero year.
   3920  *
   3921  * Returns number of days.
   3922  */
   3923 static long
   3924 _xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt)
   3925 {
   3926     long ret;
   3927     int mon;
   3928 
   3929     mon = dt->value.date.mon;
   3930     if (mon <= 0) mon = 1; /* normalization */
   3931 
   3932     if (dt->value.date.year <= 0)
   3933         ret = (dt->value.date.year * 365) +
   3934               (((dt->value.date.year+1)/4)-((dt->value.date.year+1)/100)+
   3935                ((dt->value.date.year+1)/400)) +
   3936               DAY_IN_YEAR(0, mon, dt->value.date.year);
   3937     else
   3938         ret = ((dt->value.date.year-1) * 365) +
   3939               (((dt->value.date.year-1)/4)-((dt->value.date.year-1)/100)+
   3940                ((dt->value.date.year-1)/400)) +
   3941               DAY_IN_YEAR(0, mon, dt->value.date.year);
   3942 
   3943     return ret;
   3944 }
   3945 
   3946 /**
   3947  * TIME_TO_NUMBER:
   3948  * @dt:  an #xmlSchemaValPtr
   3949  *
   3950  * Calculates the number of seconds in the time portion of @dt.
   3951  *
   3952  * Returns seconds.
   3953  */
   3954 #define TIME_TO_NUMBER(dt)                              \
   3955     ((double)((dt->value.date.hour * SECS_PER_HOUR) +   \
   3956               (dt->value.date.min * SECS_PER_MIN) +	\
   3957               (dt->value.date.tzo * SECS_PER_MIN)) +	\
   3958                dt->value.date.sec)
   3959 
   3960 /**
   3961  * xmlSchemaCompareDates:
   3962  * @x:  a first date/time value
   3963  * @y:  a second date/time value
   3964  *
   3965  * Compare 2 date/times
   3966  *
   3967  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
   3968  * case of error
   3969  */
   3970 static int
   3971 xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
   3972 {
   3973     unsigned char xmask, ymask, xor_mask, and_mask;
   3974     xmlSchemaValPtr p1, p2, q1, q2;
   3975     long p1d, p2d, q1d, q2d;
   3976 
   3977     if ((x == NULL) || (y == NULL))
   3978         return -2;
   3979 
   3980     if (x->value.date.tz_flag) {
   3981 
   3982         if (!y->value.date.tz_flag) {
   3983             p1 = xmlSchemaDateNormalize(x, 0);
   3984             p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
   3985             /* normalize y + 14:00 */
   3986             q1 = xmlSchemaDateNormalize(y, (14 * SECS_PER_HOUR));
   3987 
   3988             q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
   3989             if (p1d < q1d) {
   3990 		xmlSchemaFreeValue(p1);
   3991 		xmlSchemaFreeValue(q1);
   3992                 return -1;
   3993 	    } else if (p1d == q1d) {
   3994                 double sec;
   3995 
   3996                 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
   3997                 if (sec < 0.0) {
   3998 		    xmlSchemaFreeValue(p1);
   3999 		    xmlSchemaFreeValue(q1);
   4000                     return -1;
   4001 		} else {
   4002 		    int ret = 0;
   4003                     /* normalize y - 14:00 */
   4004                     q2 = xmlSchemaDateNormalize(y, -(14 * SECS_PER_HOUR));
   4005                     q2d = _xmlSchemaDateCastYMToDays(q2) + q2->value.date.day;
   4006                     if (p1d > q2d)
   4007                         ret = 1;
   4008                     else if (p1d == q2d) {
   4009                         sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q2);
   4010                         if (sec > 0.0)
   4011                             ret = 1;
   4012                         else
   4013                             ret = 2; /* indeterminate */
   4014                     }
   4015 		    xmlSchemaFreeValue(p1);
   4016 		    xmlSchemaFreeValue(q1);
   4017 		    xmlSchemaFreeValue(q2);
   4018 		    if (ret != 0)
   4019 		        return(ret);
   4020                 }
   4021             } else {
   4022 		xmlSchemaFreeValue(p1);
   4023 		xmlSchemaFreeValue(q1);
   4024 	    }
   4025         }
   4026     } else if (y->value.date.tz_flag) {
   4027         q1 = xmlSchemaDateNormalize(y, 0);
   4028         q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
   4029 
   4030         /* normalize x - 14:00 */
   4031         p1 = xmlSchemaDateNormalize(x, -(14 * SECS_PER_HOUR));
   4032         p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
   4033 
   4034         if (p1d < q1d) {
   4035 	    xmlSchemaFreeValue(p1);
   4036 	    xmlSchemaFreeValue(q1);
   4037             return -1;
   4038 	} else if (p1d == q1d) {
   4039             double sec;
   4040 
   4041             sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
   4042             if (sec < 0.0) {
   4043 		xmlSchemaFreeValue(p1);
   4044 		xmlSchemaFreeValue(q1);
   4045                 return -1;
   4046 	    } else {
   4047 	        int ret = 0;
   4048                 /* normalize x + 14:00 */
   4049                 p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR));
   4050                 p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day;
   4051 
   4052                 if (p2d > q1d) {
   4053                     ret = 1;
   4054 		} else if (p2d == q1d) {
   4055                     sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1);
   4056                     if (sec > 0.0)
   4057                         ret = 1;
   4058                     else
   4059                         ret = 2; /* indeterminate */
   4060                 }
   4061 		xmlSchemaFreeValue(p1);
   4062 		xmlSchemaFreeValue(q1);
   4063 		xmlSchemaFreeValue(p2);
   4064 		if (ret != 0)
   4065 		    return(ret);
   4066             }
   4067 	} else {
   4068 	    xmlSchemaFreeValue(p1);
   4069 	    xmlSchemaFreeValue(q1);
   4070         }
   4071     }
   4072 
   4073     /*
   4074      * if the same type then calculate the difference
   4075      */
   4076     if (x->type == y->type) {
   4077         int ret = 0;
   4078         q1 = xmlSchemaDateNormalize(y, 0);
   4079         q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
   4080 
   4081         p1 = xmlSchemaDateNormalize(x, 0);
   4082         p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
   4083 
   4084         if (p1d < q1d) {
   4085             ret = -1;
   4086 	} else if (p1d > q1d) {
   4087             ret = 1;
   4088 	} else {
   4089             double sec;
   4090 
   4091             sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
   4092             if (sec < 0.0)
   4093                 ret = -1;
   4094             else if (sec > 0.0)
   4095                 ret = 1;
   4096 
   4097         }
   4098 	xmlSchemaFreeValue(p1);
   4099 	xmlSchemaFreeValue(q1);
   4100         return(ret);
   4101     }
   4102 
   4103     switch (x->type) {
   4104         case XML_SCHEMAS_DATETIME:
   4105             xmask = 0xf;
   4106             break;
   4107         case XML_SCHEMAS_DATE:
   4108             xmask = 0x7;
   4109             break;
   4110         case XML_SCHEMAS_GYEAR:
   4111             xmask = 0x1;
   4112             break;
   4113         case XML_SCHEMAS_GMONTH:
   4114             xmask = 0x2;
   4115             break;
   4116         case XML_SCHEMAS_GDAY:
   4117             xmask = 0x3;
   4118             break;
   4119         case XML_SCHEMAS_GYEARMONTH:
   4120             xmask = 0x3;
   4121             break;
   4122         case XML_SCHEMAS_GMONTHDAY:
   4123             xmask = 0x6;
   4124             break;
   4125         case XML_SCHEMAS_TIME:
   4126             xmask = 0x8;
   4127             break;
   4128         default:
   4129             xmask = 0;
   4130             break;
   4131     }
   4132 
   4133     switch (y->type) {
   4134         case XML_SCHEMAS_DATETIME:
   4135             ymask = 0xf;
   4136             break;
   4137         case XML_SCHEMAS_DATE:
   4138             ymask = 0x7;
   4139             break;
   4140         case XML_SCHEMAS_GYEAR:
   4141             ymask = 0x1;
   4142             break;
   4143         case XML_SCHEMAS_GMONTH:
   4144             ymask = 0x2;
   4145             break;
   4146         case XML_SCHEMAS_GDAY:
   4147             ymask = 0x3;
   4148             break;
   4149         case XML_SCHEMAS_GYEARMONTH:
   4150             ymask = 0x3;
   4151             break;
   4152         case XML_SCHEMAS_GMONTHDAY:
   4153             ymask = 0x6;
   4154             break;
   4155         case XML_SCHEMAS_TIME:
   4156             ymask = 0x8;
   4157             break;
   4158         default:
   4159             ymask = 0;
   4160             break;
   4161     }
   4162 
   4163     xor_mask = xmask ^ ymask;           /* mark type differences */
   4164     and_mask = xmask & ymask;           /* mark field specification */
   4165 
   4166     /* year */
   4167     if (xor_mask & 1)
   4168         return 2; /* indeterminate */
   4169     else if (and_mask & 1) {
   4170         if (x->value.date.year < y->value.date.year)
   4171             return -1;
   4172         else if (x->value.date.year > y->value.date.year)
   4173             return 1;
   4174     }
   4175 
   4176     /* month */
   4177     if (xor_mask & 2)
   4178         return 2; /* indeterminate */
   4179     else if (and_mask & 2) {
   4180         if (x->value.date.mon < y->value.date.mon)
   4181             return -1;
   4182         else if (x->value.date.mon > y->value.date.mon)
   4183             return 1;
   4184     }
   4185 
   4186     /* day */
   4187     if (xor_mask & 4)
   4188         return 2; /* indeterminate */
   4189     else if (and_mask & 4) {
   4190         if (x->value.date.day < y->value.date.day)
   4191             return -1;
   4192         else if (x->value.date.day > y->value.date.day)
   4193             return 1;
   4194     }
   4195 
   4196     /* time */
   4197     if (xor_mask & 8)
   4198         return 2; /* indeterminate */
   4199     else if (and_mask & 8) {
   4200         if (x->value.date.hour < y->value.date.hour)
   4201             return -1;
   4202         else if (x->value.date.hour > y->value.date.hour)
   4203             return 1;
   4204         else if (x->value.date.min < y->value.date.min)
   4205             return -1;
   4206         else if (x->value.date.min > y->value.date.min)
   4207             return 1;
   4208         else if (x->value.date.sec < y->value.date.sec)
   4209             return -1;
   4210         else if (x->value.date.sec > y->value.date.sec)
   4211             return 1;
   4212     }
   4213 
   4214     return 0;
   4215 }
   4216 
   4217 /**
   4218  * xmlSchemaComparePreserveReplaceStrings:
   4219  * @x:  a first string value
   4220  * @y:  a second string value
   4221  * @invert: inverts the result if x < y or x > y.
   4222  *
   4223  * Compare 2 string for their normalized values.
   4224  * @x is a string with whitespace of "preserve", @y is
   4225  * a string with a whitespace of "replace". I.e. @x could
   4226  * be an "xsd:string" and @y an "xsd:normalizedString".
   4227  *
   4228  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
   4229  * case of error
   4230  */
   4231 static int
   4232 xmlSchemaComparePreserveReplaceStrings(const xmlChar *x,
   4233 				       const xmlChar *y,
   4234 				       int invert)
   4235 {
   4236     int tmp;
   4237 
   4238     while ((*x != 0) && (*y != 0)) {
   4239 	if (IS_WSP_REPLACE_CH(*y)) {
   4240 	    if (! IS_WSP_SPACE_CH(*x)) {
   4241 		if ((*x - 0x20) < 0) {
   4242 		    if (invert)
   4243 			return(1);
   4244 		    else
   4245 			return(-1);
   4246 		} else {
   4247 		    if (invert)
   4248 			return(-1);
   4249 		    else
   4250 			return(1);
   4251 		}
   4252 	    }
   4253 	} else {
   4254 	    tmp = *x - *y;
   4255 	    if (tmp < 0) {
   4256 		if (invert)
   4257 		    return(1);
   4258 		else
   4259 		    return(-1);
   4260 	    }
   4261 	    if (tmp > 0) {
   4262 		if (invert)
   4263 		    return(-1);
   4264 		else
   4265 		    return(1);
   4266 	    }
   4267 	}
   4268 	x++;
   4269 	y++;
   4270     }
   4271     if (*x != 0) {
   4272 	if (invert)
   4273 	    return(-1);
   4274 	else
   4275 	    return(1);
   4276     }
   4277     if (*y != 0) {
   4278 	if (invert)
   4279 	    return(1);
   4280 	else
   4281 	    return(-1);
   4282     }
   4283     return(0);
   4284 }
   4285 
   4286 /**
   4287  * xmlSchemaComparePreserveCollapseStrings:
   4288  * @x:  a first string value
   4289  * @y:  a second string value
   4290  *
   4291  * Compare 2 string for their normalized values.
   4292  * @x is a string with whitespace of "preserve", @y is
   4293  * a string with a whitespace of "collapse". I.e. @x could
   4294  * be an "xsd:string" and @y an "xsd:normalizedString".
   4295  *
   4296  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
   4297  * case of error
   4298  */
   4299 static int
   4300 xmlSchemaComparePreserveCollapseStrings(const xmlChar *x,
   4301 				        const xmlChar *y,
   4302 					int invert)
   4303 {
   4304     int tmp;
   4305 
   4306     /*
   4307     * Skip leading blank chars of the collapsed string.
   4308     */
   4309     while IS_WSP_BLANK_CH(*y)
   4310 	y++;
   4311 
   4312     while ((*x != 0) && (*y != 0)) {
   4313 	if IS_WSP_BLANK_CH(*y) {
   4314 	    if (! IS_WSP_SPACE_CH(*x)) {
   4315 		/*
   4316 		* The yv character would have been replaced to 0x20.
   4317 		*/
   4318 		if ((*x - 0x20) < 0) {
   4319 		    if (invert)
   4320 			return(1);
   4321 		    else
   4322 			return(-1);
   4323 		} else {
   4324 		    if (invert)
   4325 			return(-1);
   4326 		    else
   4327 			return(1);
   4328 		}
   4329 	    }
   4330 	    x++;
   4331 	    y++;
   4332 	    /*
   4333 	    * Skip contiguous blank chars of the collapsed string.
   4334 	    */
   4335 	    while IS_WSP_BLANK_CH(*y)
   4336 		y++;
   4337 	} else {
   4338 	    tmp = *x++ - *y++;
   4339 	    if (tmp < 0) {
   4340 		if (invert)
   4341 		    return(1);
   4342 		else
   4343 		    return(-1);
   4344 	    }
   4345 	    if (tmp > 0) {
   4346 		if (invert)
   4347 		    return(-1);
   4348 		else
   4349 		    return(1);
   4350 	    }
   4351 	}
   4352     }
   4353     if (*x != 0) {
   4354 	 if (invert)
   4355 	     return(-1);
   4356 	 else
   4357 	     return(1);
   4358     }
   4359     if (*y != 0) {
   4360 	/*
   4361 	* Skip trailing blank chars of the collapsed string.
   4362 	*/
   4363 	while IS_WSP_BLANK_CH(*y)
   4364 	    y++;
   4365 	if (*y != 0) {
   4366 	    if (invert)
   4367 		return(1);
   4368 	    else
   4369 		return(-1);
   4370 	}
   4371     }
   4372     return(0);
   4373 }
   4374 
   4375 /**
   4376  * xmlSchemaComparePreserveCollapseStrings:
   4377  * @x:  a first string value
   4378  * @y:  a second string value
   4379  *
   4380  * Compare 2 string for their normalized values.
   4381  * @x is a string with whitespace of "preserve", @y is
   4382  * a string with a whitespace of "collapse". I.e. @x could
   4383  * be an "xsd:string" and @y an "xsd:normalizedString".
   4384  *
   4385  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
   4386  * case of error
   4387  */
   4388 static int
   4389 xmlSchemaCompareReplaceCollapseStrings(const xmlChar *x,
   4390 				       const xmlChar *y,
   4391 				       int invert)
   4392 {
   4393     int tmp;
   4394 
   4395     /*
   4396     * Skip leading blank chars of the collapsed string.
   4397     */
   4398     while IS_WSP_BLANK_CH(*y)
   4399 	y++;
   4400 
   4401     while ((*x != 0) && (*y != 0)) {
   4402 	if IS_WSP_BLANK_CH(*y) {
   4403 	    if (! IS_WSP_BLANK_CH(*x)) {
   4404 		/*
   4405 		* The yv character would have been replaced to 0x20.
   4406 		*/
   4407 		if ((*x - 0x20) < 0) {
   4408 		    if (invert)
   4409 			return(1);
   4410 		    else
   4411 			return(-1);
   4412 		} else {
   4413 		    if (invert)
   4414 			return(-1);
   4415 		    else
   4416 			return(1);
   4417 		}
   4418 	    }
   4419 	    x++;
   4420 	    y++;
   4421 	    /*
   4422 	    * Skip contiguous blank chars of the collapsed string.
   4423 	    */
   4424 	    while IS_WSP_BLANK_CH(*y)
   4425 		y++;
   4426 	} else {
   4427 	    if IS_WSP_BLANK_CH(*x) {
   4428 		/*
   4429 		* The xv character would have been replaced to 0x20.
   4430 		*/
   4431 		if ((0x20 - *y) < 0) {
   4432 		    if (invert)
   4433 			return(1);
   4434 		    else
   4435 			return(-1);
   4436 		} else {
   4437 		    if (invert)
   4438 			return(-1);
   4439 		    else
   4440 			return(1);
   4441 		}
   4442 	    }
   4443 	    tmp = *x++ - *y++;
   4444 	    if (tmp < 0)
   4445 		return(-1);
   4446 	    if (tmp > 0)
   4447 		return(1);
   4448 	}
   4449     }
   4450     if (*x != 0) {
   4451 	 if (invert)
   4452 	     return(-1);
   4453 	 else
   4454 	     return(1);
   4455     }
   4456     if (*y != 0) {
   4457 	/*
   4458 	* Skip trailing blank chars of the collapsed string.
   4459 	*/
   4460 	while IS_WSP_BLANK_CH(*y)
   4461 	    y++;
   4462 	if (*y != 0) {
   4463 	    if (invert)
   4464 		return(1);
   4465 	    else
   4466 		return(-1);
   4467 	}
   4468     }
   4469     return(0);
   4470 }
   4471 
   4472 
   4473 /**
   4474  * xmlSchemaCompareReplacedStrings:
   4475  * @x:  a first string value
   4476  * @y:  a second string value
   4477  *
   4478  * Compare 2 string for their normalized values.
   4479  *
   4480  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
   4481  * case of error
   4482  */
   4483 static int
   4484 xmlSchemaCompareReplacedStrings(const xmlChar *x,
   4485 				const xmlChar *y)
   4486 {
   4487     int tmp;
   4488 
   4489     while ((*x != 0) && (*y != 0)) {
   4490 	if IS_WSP_BLANK_CH(*y) {
   4491 	    if (! IS_WSP_BLANK_CH(*x)) {
   4492 		if ((*x - 0x20) < 0)
   4493     		    return(-1);
   4494 		else
   4495 		    return(1);
   4496 	    }
   4497 	} else {
   4498 	    if IS_WSP_BLANK_CH(*x) {
   4499 		if ((0x20 - *y) < 0)
   4500     		    return(-1);
   4501 		else
   4502 		    return(1);
   4503 	    }
   4504 	    tmp = *x - *y;
   4505 	    if (tmp < 0)
   4506     		return(-1);
   4507 	    if (tmp > 0)
   4508     		return(1);
   4509 	}
   4510 	x++;
   4511 	y++;
   4512     }
   4513     if (*x != 0)
   4514         return(1);
   4515     if (*y != 0)
   4516         return(-1);
   4517     return(0);
   4518 }
   4519 
   4520 /**
   4521  * xmlSchemaCompareNormStrings:
   4522  * @x:  a first string value
   4523  * @y:  a second string value
   4524  *
   4525  * Compare 2 string for their normalized values.
   4526  *
   4527  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
   4528  * case of error
   4529  */
   4530 static int
   4531 xmlSchemaCompareNormStrings(const xmlChar *x,
   4532 			    const xmlChar *y) {
   4533     int tmp;
   4534 
   4535     while (IS_BLANK_CH(*x)) x++;
   4536     while (IS_BLANK_CH(*y)) y++;
   4537     while ((*x != 0) && (*y != 0)) {
   4538 	if (IS_BLANK_CH(*x)) {
   4539 	    if (!IS_BLANK_CH(*y)) {
   4540 		tmp = *x - *y;
   4541 		return(tmp);
   4542 	    }
   4543 	    while (IS_BLANK_CH(*x)) x++;
   4544 	    while (IS_BLANK_CH(*y)) y++;
   4545 	} else {
   4546 	    tmp = *x++ - *y++;
   4547 	    if (tmp < 0)
   4548 		return(-1);
   4549 	    if (tmp > 0)
   4550 		return(1);
   4551 	}
   4552     }
   4553     if (*x != 0) {
   4554 	while (IS_BLANK_CH(*x)) x++;
   4555 	if (*x != 0)
   4556 	    return(1);
   4557     }
   4558     if (*y != 0) {
   4559 	while (IS_BLANK_CH(*y)) y++;
   4560 	if (*y != 0)
   4561 	    return(-1);
   4562     }
   4563     return(0);
   4564 }
   4565 
   4566 /**
   4567  * xmlSchemaCompareFloats:
   4568  * @x:  a first float or double value
   4569  * @y:  a second float or double value
   4570  *
   4571  * Compare 2 values
   4572  *
   4573  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
   4574  * case of error
   4575  */
   4576 static int
   4577 xmlSchemaCompareFloats(xmlSchemaValPtr x, xmlSchemaValPtr y) {
   4578     double d1, d2;
   4579 
   4580     if ((x == NULL) || (y == NULL))
   4581 	return(-2);
   4582 
   4583     /*
   4584      * Cast everything to doubles.
   4585      */
   4586     if (x->type == XML_SCHEMAS_DOUBLE)
   4587 	d1 = x->value.d;
   4588     else if (x->type == XML_SCHEMAS_FLOAT)
   4589 	d1 = x->value.f;
   4590     else
   4591 	return(-2);
   4592 
   4593     if (y->type == XML_SCHEMAS_DOUBLE)
   4594 	d2 = y->value.d;
   4595     else if (y->type == XML_SCHEMAS_FLOAT)
   4596 	d2 = y->value.f;
   4597     else
   4598 	return(-2);
   4599 
   4600     /*
   4601      * Check for special cases.
   4602      */
   4603     if (xmlXPathIsNaN(d1)) {
   4604 	if (xmlXPathIsNaN(d2))
   4605 	    return(0);
   4606 	return(1);
   4607     }
   4608     if (xmlXPathIsNaN(d2))
   4609 	return(-1);
   4610     if (d1 == xmlXPathPINF) {
   4611 	if (d2 == xmlXPathPINF)
   4612 	    return(0);
   4613         return(1);
   4614     }
   4615     if (d2 == xmlXPathPINF)
   4616         return(-1);
   4617     if (d1 == xmlXPathNINF) {
   4618 	if (d2 == xmlXPathNINF)
   4619 	    return(0);
   4620         return(-1);
   4621     }
   4622     if (d2 == xmlXPathNINF)
   4623         return(1);
   4624 
   4625     /*
   4626      * basic tests, the last one we should have equality, but
   4627      * portability is more important than speed and handling
   4628      * NaN or Inf in a portable way is always a challenge, so ...
   4629      */
   4630     if (d1 < d2)
   4631 	return(-1);
   4632     if (d1 > d2)
   4633 	return(1);
   4634     if (d1 == d2)
   4635 	return(0);
   4636     return(2);
   4637 }
   4638 
   4639 /**
   4640  * xmlSchemaCompareValues:
   4641  * @x:  a first value
   4642  * @xvalue: the first value as a string (optional)
   4643  * @xwtsp: the whitespace type
   4644  * @y:  a second value
   4645  * @xvalue: the second value as a string (optional)
   4646  * @ywtsp: the whitespace type
   4647  *
   4648  * Compare 2 values
   4649  *
   4650  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, 3 if not
   4651  * comparable and -2 in case of error
   4652  */
   4653 static int
   4654 xmlSchemaCompareValuesInternal(xmlSchemaValType xtype,
   4655 			       xmlSchemaValPtr x,
   4656 			       const xmlChar *xvalue,
   4657 			       xmlSchemaWhitespaceValueType xws,
   4658 			       xmlSchemaValType ytype,
   4659 			       xmlSchemaValPtr y,
   4660 			       const xmlChar *yvalue,
   4661 			       xmlSchemaWhitespaceValueType yws)
   4662 {
   4663     switch (xtype) {
   4664 	case XML_SCHEMAS_UNKNOWN:
   4665 	case XML_SCHEMAS_ANYTYPE:
   4666 	    return(-2);
   4667         case XML_SCHEMAS_INTEGER:
   4668         case XML_SCHEMAS_NPINTEGER:
   4669         case XML_SCHEMAS_NINTEGER:
   4670         case XML_SCHEMAS_NNINTEGER:
   4671         case XML_SCHEMAS_PINTEGER:
   4672         case XML_SCHEMAS_INT:
   4673         case XML_SCHEMAS_UINT:
   4674         case XML_SCHEMAS_LONG:
   4675         case XML_SCHEMAS_ULONG:
   4676         case XML_SCHEMAS_SHORT:
   4677         case XML_SCHEMAS_USHORT:
   4678         case XML_SCHEMAS_BYTE:
   4679         case XML_SCHEMAS_UBYTE:
   4680 	case XML_SCHEMAS_DECIMAL:
   4681 	    if ((x == NULL) || (y == NULL))
   4682 		return(-2);
   4683 	    if (ytype == xtype)
   4684 		return(xmlSchemaCompareDecimals(x, y));
   4685 	    if ((ytype == XML_SCHEMAS_DECIMAL) ||
   4686 		(ytype == XML_SCHEMAS_INTEGER) ||
   4687 		(ytype == XML_SCHEMAS_NPINTEGER) ||
   4688 		(ytype == XML_SCHEMAS_NINTEGER) ||
   4689 		(ytype == XML_SCHEMAS_NNINTEGER) ||
   4690 		(ytype == XML_SCHEMAS_PINTEGER) ||
   4691 		(ytype == XML_SCHEMAS_INT) ||
   4692 		(ytype == XML_SCHEMAS_UINT) ||
   4693 		(ytype == XML_SCHEMAS_LONG) ||
   4694 		(ytype == XML_SCHEMAS_ULONG) ||
   4695 		(ytype == XML_SCHEMAS_SHORT) ||
   4696 		(ytype == XML_SCHEMAS_USHORT) ||
   4697 		(ytype == XML_SCHEMAS_BYTE) ||
   4698 		(ytype == XML_SCHEMAS_UBYTE))
   4699 		return(xmlSchemaCompareDecimals(x, y));
   4700 	    return(-2);
   4701         case XML_SCHEMAS_DURATION:
   4702 	    if ((x == NULL) || (y == NULL))
   4703 		return(-2);
   4704 	    if (ytype == XML_SCHEMAS_DURATION)
   4705                 return(xmlSchemaCompareDurations(x, y));
   4706             return(-2);
   4707         case XML_SCHEMAS_TIME:
   4708         case XML_SCHEMAS_GDAY:
   4709         case XML_SCHEMAS_GMONTH:
   4710         case XML_SCHEMAS_GMONTHDAY:
   4711         case XML_SCHEMAS_GYEAR:
   4712         case XML_SCHEMAS_GYEARMONTH:
   4713         case XML_SCHEMAS_DATE:
   4714         case XML_SCHEMAS_DATETIME:
   4715 	    if ((x == NULL) || (y == NULL))
   4716 		return(-2);
   4717             if ((ytype == XML_SCHEMAS_DATETIME)  ||
   4718                 (ytype == XML_SCHEMAS_TIME)      ||
   4719                 (ytype == XML_SCHEMAS_GDAY)      ||
   4720                 (ytype == XML_SCHEMAS_GMONTH)    ||
   4721                 (ytype == XML_SCHEMAS_GMONTHDAY) ||
   4722                 (ytype == XML_SCHEMAS_GYEAR)     ||
   4723                 (ytype == XML_SCHEMAS_DATE)      ||
   4724                 (ytype == XML_SCHEMAS_GYEARMONTH))
   4725                 return (xmlSchemaCompareDates(x, y));
   4726             return (-2);
   4727 	/*
   4728 	* Note that we will support comparison of string types against
   4729 	* anySimpleType as well.
   4730 	*/
   4731 	case XML_SCHEMAS_ANYSIMPLETYPE:
   4732 	case XML_SCHEMAS_STRING:
   4733         case XML_SCHEMAS_NORMSTRING:
   4734         case XML_SCHEMAS_TOKEN:
   4735         case XML_SCHEMAS_LANGUAGE:
   4736         case XML_SCHEMAS_NMTOKEN:
   4737         case XML_SCHEMAS_NAME:
   4738         case XML_SCHEMAS_NCNAME:
   4739         case XML_SCHEMAS_ID:
   4740         case XML_SCHEMAS_IDREF:
   4741         case XML_SCHEMAS_ENTITY:
   4742         case XML_SCHEMAS_ANYURI:
   4743 	{
   4744 	    const xmlChar *xv, *yv;
   4745 
   4746 	    if (x == NULL)
   4747 		xv = xvalue;
   4748 	    else
   4749 		xv = x->value.str;
   4750 	    if (y == NULL)
   4751 		yv = yvalue;
   4752 	    else
   4753 		yv = y->value.str;
   4754 	    /*
   4755 	    * TODO: Compare those against QName.
   4756 	    */
   4757 	    if (ytype == XML_SCHEMAS_QNAME) {
   4758 		TODO
   4759 		if (y == NULL)
   4760 		    return(-2);
   4761 		return (-2);
   4762 	    }
   4763             if ((ytype == XML_SCHEMAS_ANYSIMPLETYPE) ||
   4764 		(ytype == XML_SCHEMAS_STRING) ||
   4765 		(ytype == XML_SCHEMAS_NORMSTRING) ||
   4766                 (ytype == XML_SCHEMAS_TOKEN) ||
   4767                 (ytype == XML_SCHEMAS_LANGUAGE) ||
   4768                 (ytype == XML_SCHEMAS_NMTOKEN) ||
   4769                 (ytype == XML_SCHEMAS_NAME) ||
   4770                 (ytype == XML_SCHEMAS_NCNAME) ||
   4771                 (ytype == XML_SCHEMAS_ID) ||
   4772                 (ytype == XML_SCHEMAS_IDREF) ||
   4773                 (ytype == XML_SCHEMAS_ENTITY) ||
   4774                 (ytype == XML_SCHEMAS_ANYURI)) {
   4775 
   4776 		if (xws == XML_SCHEMA_WHITESPACE_PRESERVE) {
   4777 
   4778 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) {
   4779 			/* TODO: What about x < y or x > y. */
   4780 			if (xmlStrEqual(xv, yv))
   4781 			    return (0);
   4782 			else
   4783 			    return (2);
   4784 		    } else if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
   4785 			return (xmlSchemaComparePreserveReplaceStrings(xv, yv, 0));
   4786 		    else if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
   4787 			return (xmlSchemaComparePreserveCollapseStrings(xv, yv, 0));
   4788 
   4789 		} else if (xws == XML_SCHEMA_WHITESPACE_REPLACE) {
   4790 
   4791 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
   4792 			return (xmlSchemaComparePreserveReplaceStrings(yv, xv, 1));
   4793 		    if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
   4794 			return (xmlSchemaCompareReplacedStrings(xv, yv));
   4795 		    if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
   4796 			return (xmlSchemaCompareReplaceCollapseStrings(xv, yv, 0));
   4797 
   4798 		} else if (xws == XML_SCHEMA_WHITESPACE_COLLAPSE) {
   4799 
   4800 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
   4801 			return (xmlSchemaComparePreserveCollapseStrings(yv, xv, 1));
   4802 		    if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
   4803 			return (xmlSchemaCompareReplaceCollapseStrings(yv, xv, 1));
   4804 		    if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
   4805 			return (xmlSchemaCompareNormStrings(xv, yv));
   4806 		} else
   4807 		    return (-2);
   4808 
   4809 	    }
   4810             return (-2);
   4811 	}
   4812         case XML_SCHEMAS_QNAME:
   4813 	case XML_SCHEMAS_NOTATION:
   4814 	    if ((x == NULL) || (y == NULL))
   4815 		return(-2);
   4816             if ((ytype == XML_SCHEMAS_QNAME) ||
   4817 		(ytype == XML_SCHEMAS_NOTATION)) {
   4818 		if ((xmlStrEqual(x->value.qname.name, y->value.qname.name)) &&
   4819 		    (xmlStrEqual(x->value.qname.uri, y->value.qname.uri)))
   4820 		    return(0);
   4821 		return(2);
   4822 	    }
   4823 	    return (-2);
   4824         case XML_SCHEMAS_FLOAT:
   4825         case XML_SCHEMAS_DOUBLE:
   4826 	    if ((x == NULL) || (y == NULL))
   4827 		return(-2);
   4828             if ((ytype == XML_SCHEMAS_FLOAT) ||
   4829                 (ytype == XML_SCHEMAS_DOUBLE))
   4830                 return (xmlSchemaCompareFloats(x, y));
   4831             return (-2);
   4832         case XML_SCHEMAS_BOOLEAN:
   4833 	    if ((x == NULL) || (y == NULL))
   4834 		return(-2);
   4835             if (ytype == XML_SCHEMAS_BOOLEAN) {
   4836 		if (x->value.b == y->value.b)
   4837 		    return(0);
   4838 		if (x->value.b == 0)
   4839 		    return(-1);
   4840 		return(1);
   4841 	    }
   4842 	    return (-2);
   4843         case XML_SCHEMAS_HEXBINARY:
   4844 	    if ((x == NULL) || (y == NULL))
   4845 		return(-2);
   4846             if (ytype == XML_SCHEMAS_HEXBINARY) {
   4847 	        if (x->value.hex.total == y->value.hex.total) {
   4848 		    int ret = xmlStrcmp(x->value.hex.str, y->value.hex.str);
   4849 		    if (ret > 0)
   4850 			return(1);
   4851 		    else if (ret == 0)
   4852 			return(0);
   4853 		}
   4854 		else if (x->value.hex.total > y->value.hex.total)
   4855 		    return(1);
   4856 
   4857 		return(-1);
   4858             }
   4859             return (-2);
   4860         case XML_SCHEMAS_BASE64BINARY:
   4861 	    if ((x == NULL) || (y == NULL))
   4862 		return(-2);
   4863             if (ytype == XML_SCHEMAS_BASE64BINARY) {
   4864                 if (x->value.base64.total == y->value.base64.total) {
   4865                     int ret = xmlStrcmp(x->value.base64.str,
   4866 		                        y->value.base64.str);
   4867                     if (ret > 0)
   4868                         return(1);
   4869                     else if (ret == 0)
   4870                         return(0);
   4871 		    else
   4872 		        return(-1);
   4873                 }
   4874                 else if (x->value.base64.total > y->value.base64.total)
   4875                     return(1);
   4876                 else
   4877                     return(-1);
   4878             }
   4879             return (-2);
   4880         case XML_SCHEMAS_IDREFS:
   4881         case XML_SCHEMAS_ENTITIES:
   4882         case XML_SCHEMAS_NMTOKENS:
   4883 	    TODO
   4884 	    break;
   4885     }
   4886     return -2;
   4887 }
   4888 
   4889 /**
   4890  * xmlSchemaCompareValues:
   4891  * @x:  a first value
   4892  * @y:  a second value
   4893  *
   4894  * Compare 2 values
   4895  *
   4896  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
   4897  * case of error
   4898  */
   4899 int
   4900 xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
   4901     xmlSchemaWhitespaceValueType xws, yws;
   4902 
   4903     if ((x == NULL) || (y == NULL))
   4904         return(-2);
   4905     if (x->type == XML_SCHEMAS_STRING)
   4906 	xws = XML_SCHEMA_WHITESPACE_PRESERVE;
   4907     else if (x->type == XML_SCHEMAS_NORMSTRING)
   4908         xws = XML_SCHEMA_WHITESPACE_REPLACE;
   4909     else
   4910         xws = XML_SCHEMA_WHITESPACE_COLLAPSE;
   4911 
   4912     if (y->type == XML_SCHEMAS_STRING)
   4913 	yws = XML_SCHEMA_WHITESPACE_PRESERVE;
   4914     else if (x->type == XML_SCHEMAS_NORMSTRING)
   4915         yws = XML_SCHEMA_WHITESPACE_REPLACE;
   4916     else
   4917         yws = XML_SCHEMA_WHITESPACE_COLLAPSE;
   4918 
   4919     return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
   4920 	y, NULL, yws));
   4921 }
   4922 
   4923 /**
   4924  * xmlSchemaCompareValuesWhtsp:
   4925  * @x:  a first value
   4926  * @xws: the whitespace value of x
   4927  * @y:  a second value
   4928  * @yws: the whitespace value of y
   4929  *
   4930  * Compare 2 values
   4931  *
   4932  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
   4933  * case of error
   4934  */
   4935 int
   4936 xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x,
   4937 			    xmlSchemaWhitespaceValueType xws,
   4938 			    xmlSchemaValPtr y,
   4939 			    xmlSchemaWhitespaceValueType yws)
   4940 {
   4941     if ((x == NULL) || (y == NULL))
   4942 	return(-2);
   4943     return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
   4944 	y, NULL, yws));
   4945 }
   4946 
   4947 /**
   4948  * xmlSchemaCompareValuesWhtspExt:
   4949  * @x:  a first value
   4950  * @xws: the whitespace value of x
   4951  * @y:  a second value
   4952  * @yws: the whitespace value of y
   4953  *
   4954  * Compare 2 values
   4955  *
   4956  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
   4957  * case of error
   4958  */
   4959 static int
   4960 xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype,
   4961 			       xmlSchemaValPtr x,
   4962 			       const xmlChar *xvalue,
   4963 			       xmlSchemaWhitespaceValueType xws,
   4964 			       xmlSchemaValType ytype,
   4965 			       xmlSchemaValPtr y,
   4966 			       const xmlChar *yvalue,
   4967 			       xmlSchemaWhitespaceValueType yws)
   4968 {
   4969     return(xmlSchemaCompareValuesInternal(xtype, x, xvalue, xws, ytype, y,
   4970 	yvalue, yws));
   4971 }
   4972 
   4973 /**
   4974  * xmlSchemaNormLen:
   4975  * @value:  a string
   4976  *
   4977  * Computes the UTF8 length of the normalized value of the string
   4978  *
   4979  * Returns the length or -1 in case of error.
   4980  */
   4981 static int
   4982 xmlSchemaNormLen(const xmlChar *value) {
   4983     const xmlChar *utf;
   4984     int ret = 0;
   4985 
   4986     if (value == NULL)
   4987 	return(-1);
   4988     utf = value;
   4989     while (IS_BLANK_CH(*utf)) utf++;
   4990     while (*utf != 0) {
   4991 	if (utf[0] & 0x80) {
   4992 	    if ((utf[1] & 0xc0) != 0x80)
   4993 		return(-1);
   4994 	    if ((utf[0] & 0xe0) == 0xe0) {
   4995 		if ((utf[2] & 0xc0) != 0x80)
   4996 		    return(-1);
   4997 		if ((utf[0] & 0xf0) == 0xf0) {
   4998 		    if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
   4999 			return(-1);
   5000 		    utf += 4;
   5001 		} else {
   5002 		    utf += 3;
   5003 		}
   5004 	    } else {
   5005 		utf += 2;
   5006 	    }
   5007 	} else if (IS_BLANK_CH(*utf)) {
   5008 	    while (IS_BLANK_CH(*utf)) utf++;
   5009 	    if (*utf == 0)
   5010 		break;
   5011 	} else {
   5012 	    utf++;
   5013 	}
   5014 	ret++;
   5015     }
   5016     return(ret);
   5017 }
   5018 
   5019 /**
   5020  * xmlSchemaGetFacetValueAsULong:
   5021  * @facet: an schemas type facet
   5022  *
   5023  * Extract the value of a facet
   5024  *
   5025  * Returns the value as a long
   5026  */
   5027 unsigned long
   5028 xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet)
   5029 {
   5030     /*
   5031     * TODO: Check if this is a decimal.
   5032     */
   5033     if (facet == NULL)
   5034         return 0;
   5035     return ((unsigned long) facet->val->value.decimal.lo);
   5036 }
   5037 
   5038 /**
   5039  * xmlSchemaValidateListSimpleTypeFacet:
   5040  * @facet:  the facet to check
   5041  * @value:  the lexical repr of the value to validate
   5042  * @actualLen:  the number of list items
   5043  * @expectedLen: the resulting expected number of list items
   5044  *
   5045  * Checks the value of a list simple type against a facet.
   5046  *
   5047  * Returns 0 if the value is valid, a positive error code
   5048  * number otherwise and -1 in case of an internal error.
   5049  */
   5050 int
   5051 xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet,
   5052 				     const xmlChar *value,
   5053 				     unsigned long actualLen,
   5054 				     unsigned long *expectedLen)
   5055 {
   5056     if (facet == NULL)
   5057         return(-1);
   5058     /*
   5059     * TODO: Check if this will work with large numbers.
   5060     * (compare value.decimal.mi and value.decimal.hi as well?).
   5061     */
   5062     if (facet->type == XML_SCHEMA_FACET_LENGTH) {
   5063 	if (actualLen != facet->val->value.decimal.lo) {
   5064 	    if (expectedLen != NULL)
   5065 		*expectedLen = facet->val->value.decimal.lo;
   5066 	    return (XML_SCHEMAV_CVC_LENGTH_VALID);
   5067 	}
   5068     } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
   5069 	if (actualLen < facet->val->value.decimal.lo) {
   5070 	    if (expectedLen != NULL)
   5071 		*expectedLen = facet->val->value.decimal.lo;
   5072 	    return (XML_SCHEMAV_CVC_MINLENGTH_VALID);
   5073 	}
   5074     } else if (facet->type == XML_SCHEMA_FACET_MAXLENGTH) {
   5075 	if (actualLen > facet->val->value.decimal.lo) {
   5076 	    if (expectedLen != NULL)
   5077 		*expectedLen = facet->val->value.decimal.lo;
   5078 	    return (XML_SCHEMAV_CVC_MAXLENGTH_VALID);
   5079 	}
   5080     } else
   5081 	/*
   5082 	* NOTE: That we can pass NULL as xmlSchemaValPtr to
   5083 	* xmlSchemaValidateFacet, since the remaining facet types
   5084 	* are: XML_SCHEMA_FACET_PATTERN, XML_SCHEMA_FACET_ENUMERATION.
   5085 	*/
   5086 	return(xmlSchemaValidateFacet(NULL, facet, value, NULL));
   5087     return (0);
   5088 }
   5089 
   5090 /**
   5091  * xmlSchemaValidateLengthFacet:
   5092  * @type:  the built-in type
   5093  * @facet:  the facet to check
   5094  * @value:  the lexical repr. of the value to be validated
   5095  * @val:  the precomputed value
   5096  * @ws: the whitespace type of the value
   5097  * @length: the actual length of the value
   5098  *
   5099  * Checka a value against a "length", "minLength" and "maxLength"
   5100  * facet; sets @length to the computed length of @value.
   5101  *
   5102  * Returns 0 if the value is valid, a positive error code
   5103  * otherwise and -1 in case of an internal or API error.
   5104  */
   5105 static int
   5106 xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet,
   5107 				     xmlSchemaTypeType valType,
   5108 				     const xmlChar *value,
   5109 				     xmlSchemaValPtr val,
   5110 				     unsigned long *length,
   5111 				     xmlSchemaWhitespaceValueType ws)
   5112 {
   5113     unsigned int len = 0;
   5114 
   5115     if ((length == NULL) || (facet == NULL))
   5116         return (-1);
   5117     *length = 0;
   5118     if ((facet->type != XML_SCHEMA_FACET_LENGTH) &&
   5119 	(facet->type != XML_SCHEMA_FACET_MAXLENGTH) &&
   5120 	(facet->type != XML_SCHEMA_FACET_MINLENGTH))
   5121 	return (-1);
   5122 
   5123     /*
   5124     * TODO: length, maxLength and minLength must be of type
   5125     * nonNegativeInteger only. Check if decimal is used somehow.
   5126     */
   5127     if ((facet->val == NULL) ||
   5128 	((facet->val->type != XML_SCHEMAS_DECIMAL) &&
   5129 	 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
   5130 	(facet->val->value.decimal.frac != 0)) {
   5131 	return(-1);
   5132     }
   5133     if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
   5134 	len = val->value.hex.total;
   5135     else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
   5136 	len = val->value.base64.total;
   5137     else {
   5138 	switch (valType) {
   5139 	    case XML_SCHEMAS_STRING:
   5140 	    case XML_SCHEMAS_NORMSTRING:
   5141 		if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
   5142 		    /*
   5143 		    * This is to ensure API compatibility with the old
   5144 		    * xmlSchemaValidateLengthFacet(). Anyway, this was and
   5145 		    * is not the correct handling.
   5146 		    * TODO: Get rid of this case somehow.
   5147 		    */
   5148 		    if (valType == XML_SCHEMAS_STRING)
   5149 			len = xmlUTF8Strlen(value);
   5150 		    else
   5151 			len = xmlSchemaNormLen(value);
   5152 		} else if (value != NULL) {
   5153 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
   5154 			len = xmlSchemaNormLen(value);
   5155 		    else
   5156 		    /*
   5157 		    * Should be OK for "preserve" as well.
   5158 		    */
   5159 		    len = xmlUTF8Strlen(value);
   5160 		}
   5161 		break;
   5162 	    case XML_SCHEMAS_IDREF:
   5163 	    case XML_SCHEMAS_TOKEN:
   5164 	    case XML_SCHEMAS_LANGUAGE:
   5165 	    case XML_SCHEMAS_NMTOKEN:
   5166 	    case XML_SCHEMAS_NAME:
   5167 	    case XML_SCHEMAS_NCNAME:
   5168 	    case XML_SCHEMAS_ID:
   5169 		/*
   5170 		* FIXME: What exactly to do with anyURI?
   5171 		*/
   5172 	    case XML_SCHEMAS_ANYURI:
   5173 		if (value != NULL)
   5174 		    len = xmlSchemaNormLen(value);
   5175 		break;
   5176 	    case XML_SCHEMAS_QNAME:
   5177  	    case XML_SCHEMAS_NOTATION:
   5178  		/*
   5179 		* For QName and NOTATION, those facets are
   5180 		* deprecated and should be ignored.
   5181  		*/
   5182 		return (0);
   5183 	    default:
   5184 		TODO
   5185 	}
   5186     }
   5187     *length = (unsigned long) len;
   5188     /*
   5189     * TODO: Return the whole expected value, i.e. "lo", "mi" and "hi".
   5190     */
   5191     if (facet->type == XML_SCHEMA_FACET_LENGTH) {
   5192 	if (len != facet->val->value.decimal.lo)
   5193 	    return(XML_SCHEMAV_CVC_LENGTH_VALID);
   5194     } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
   5195 	if (len < facet->val->value.decimal.lo)
   5196 	    return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
   5197     } else {
   5198 	if (len > facet->val->value.decimal.lo)
   5199 	    return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
   5200     }
   5201 
   5202     return (0);
   5203 }
   5204 
   5205 /**
   5206  * xmlSchemaValidateLengthFacet:
   5207  * @type:  the built-in type
   5208  * @facet:  the facet to check
   5209  * @value:  the lexical repr. of the value to be validated
   5210  * @val:  the precomputed value
   5211  * @length: the actual length of the value
   5212  *
   5213  * Checka a value against a "length", "minLength" and "maxLength"
   5214  * facet; sets @length to the computed length of @value.
   5215  *
   5216  * Returns 0 if the value is valid, a positive error code
   5217  * otherwise and -1 in case of an internal or API error.
   5218  */
   5219 int
   5220 xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type,
   5221 			     xmlSchemaFacetPtr facet,
   5222 			     const xmlChar *value,
   5223 			     xmlSchemaValPtr val,
   5224 			     unsigned long *length)
   5225 {
   5226     if (type == NULL)
   5227         return(-1);
   5228     return (xmlSchemaValidateLengthFacetInternal(facet,
   5229 	type->builtInType, value, val, length,
   5230 	XML_SCHEMA_WHITESPACE_UNKNOWN));
   5231 }
   5232 
   5233 /**
   5234  * xmlSchemaValidateLengthFacetWhtsp:
   5235  * @facet:  the facet to check
   5236  * @valType:  the built-in type
   5237  * @value:  the lexical repr. of the value to be validated
   5238  * @val:  the precomputed value
   5239  * @ws: the whitespace type of the value
   5240  * @length: the actual length of the value
   5241  *
   5242  * Checka a value against a "length", "minLength" and "maxLength"
   5243  * facet; sets @length to the computed length of @value.
   5244  *
   5245  * Returns 0 if the value is valid, a positive error code
   5246  * otherwise and -1 in case of an internal or API error.
   5247  */
   5248 int
   5249 xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet,
   5250 				  xmlSchemaValType valType,
   5251 				  const xmlChar *value,
   5252 				  xmlSchemaValPtr val,
   5253 				  unsigned long *length,
   5254 				  xmlSchemaWhitespaceValueType ws)
   5255 {
   5256     return (xmlSchemaValidateLengthFacetInternal(facet, valType, value, val,
   5257 	length, ws));
   5258 }
   5259 
   5260 /**
   5261  * xmlSchemaValidateFacetInternal:
   5262  * @facet:  the facet to check
   5263  * @fws: the whitespace type of the facet's value
   5264  * @valType: the built-in type of the value
   5265  * @value:  the lexical repr of the value to validate
   5266  * @val:  the precomputed value
   5267  * @ws: the whitespace type of the value
   5268  *
   5269  * Check a value against a facet condition
   5270  *
   5271  * Returns 0 if the element is schemas valid, a positive error code
   5272  *     number otherwise and -1 in case of internal or API error.
   5273  */
   5274 static int
   5275 xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,
   5276 			       xmlSchemaWhitespaceValueType fws,
   5277 			       xmlSchemaValType valType,
   5278 			       const xmlChar *value,
   5279 			       xmlSchemaValPtr val,
   5280 			       xmlSchemaWhitespaceValueType ws)
   5281 {
   5282     int ret;
   5283 
   5284     if (facet == NULL)
   5285 	return(-1);
   5286 
   5287     switch (facet->type) {
   5288 	case XML_SCHEMA_FACET_PATTERN:
   5289 	    /*
   5290 	    * NOTE that for patterns, the @value needs to be the normalized
   5291 	    * value, *not* the lexical initial value or the canonical value.
   5292 	    */
   5293 	    if (value == NULL)
   5294 		return(-1);
   5295 	    ret = xmlRegexpExec(facet->regexp, value);
   5296 	    if (ret == 1)
   5297 		return(0);
   5298 	    if (ret == 0)
   5299 		return(XML_SCHEMAV_CVC_PATTERN_VALID);
   5300 	    return(ret);
   5301 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
   5302 	    ret = xmlSchemaCompareValues(val, facet->val);
   5303 	    if (ret == -2)
   5304 		return(-1);
   5305 	    if (ret == -1)
   5306 		return(0);
   5307 	    return(XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID);
   5308 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
   5309 	    ret = xmlSchemaCompareValues(val, facet->val);
   5310 	    if (ret == -2)
   5311 		return(-1);
   5312 	    if ((ret == -1) || (ret == 0))
   5313 		return(0);
   5314 	    return(XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID);
   5315 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
   5316 	    ret = xmlSchemaCompareValues(val, facet->val);
   5317 	    if (ret == -2)
   5318 		return(-1);
   5319 	    if (ret == 1)
   5320 		return(0);
   5321 	    return(XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID);
   5322 	case XML_SCHEMA_FACET_MININCLUSIVE:
   5323 	    ret = xmlSchemaCompareValues(val, facet->val);
   5324 	    if (ret == -2)
   5325 		return(-1);
   5326 	    if ((ret == 1) || (ret == 0))
   5327 		return(0);
   5328 	    return(XML_SCHEMAV_CVC_MININCLUSIVE_VALID);
   5329 	case XML_SCHEMA_FACET_WHITESPACE:
   5330 	    /* TODO whitespaces */
   5331 	    /*
   5332 	    * NOTE: Whitespace should be handled to normalize
   5333 	    * the value to be validated against a the facets;
   5334 	    * not to normalize the value in-between.
   5335 	    */
   5336 	    return(0);
   5337 	case  XML_SCHEMA_FACET_ENUMERATION:
   5338 	    if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
   5339 		/*
   5340 		* This is to ensure API compatibility with the old
   5341 		* xmlSchemaValidateFacet().
   5342 		* TODO: Get rid of this case.
   5343 		*/
   5344 		if ((facet->value != NULL) &&
   5345 		    (xmlStrEqual(facet->value, value)))
   5346 		    return(0);
   5347 	    } else {
   5348 		ret = xmlSchemaCompareValuesWhtspExt(facet->val->type,
   5349 		    facet->val, facet->value, fws, valType, val,
   5350 		    value, ws);
   5351 		if (ret == -2)
   5352 		    return(-1);
   5353 		if (ret == 0)
   5354 		    return(0);
   5355 	    }
   5356 	    return(XML_SCHEMAV_CVC_ENUMERATION_VALID);
   5357 	case XML_SCHEMA_FACET_LENGTH:
   5358 	    /*
   5359 	    * SPEC (1.3) "if {primitive type definition} is QName or NOTATION,
   5360 	    * then any {value} is facet-valid."
   5361 	    */
   5362 	    if ((valType == XML_SCHEMAS_QNAME) ||
   5363 		(valType == XML_SCHEMAS_NOTATION))
   5364 		return (0);
   5365 	    /* No break on purpose. */
   5366 	case XML_SCHEMA_FACET_MAXLENGTH:
   5367 	case XML_SCHEMA_FACET_MINLENGTH: {
   5368 	    unsigned int len = 0;
   5369 
   5370 	    if ((valType == XML_SCHEMAS_QNAME) ||
   5371 		(valType == XML_SCHEMAS_NOTATION))
   5372 		return (0);
   5373 	    /*
   5374 	    * TODO: length, maxLength and minLength must be of type
   5375 	    * nonNegativeInteger only. Check if decimal is used somehow.
   5376 	    */
   5377 	    if ((facet->val == NULL) ||
   5378 		((facet->val->type != XML_SCHEMAS_DECIMAL) &&
   5379 		 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
   5380 		(facet->val->value.decimal.frac != 0)) {
   5381 		return(-1);
   5382 	    }
   5383 	    if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
   5384 		len = val->value.hex.total;
   5385 	    else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
   5386 		len = val->value.base64.total;
   5387 	    else {
   5388 		switch (valType) {
   5389 		    case XML_SCHEMAS_STRING:
   5390 		    case XML_SCHEMAS_NORMSTRING:
   5391 			if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
   5392 			    /*
   5393 			    * This is to ensure API compatibility with the old
   5394 			    * xmlSchemaValidateFacet(). Anyway, this was and
   5395 			    * is not the correct handling.
   5396 			    * TODO: Get rid of this case somehow.
   5397 			    */
   5398 			    if (valType == XML_SCHEMAS_STRING)
   5399 				len = xmlUTF8Strlen(value);
   5400 			    else
   5401 				len = xmlSchemaNormLen(value);
   5402 			} else if (value != NULL) {
   5403 			    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
   5404 				len = xmlSchemaNormLen(value);
   5405 			    else
   5406 				/*
   5407 				* Should be OK for "preserve" as well.
   5408 				*/
   5409 				len = xmlUTF8Strlen(value);
   5410 			}
   5411 			break;
   5412 	    	    case XML_SCHEMAS_IDREF:
   5413 		    case XML_SCHEMAS_TOKEN:
   5414 		    case XML_SCHEMAS_LANGUAGE:
   5415 		    case XML_SCHEMAS_NMTOKEN:
   5416 		    case XML_SCHEMAS_NAME:
   5417 		    case XML_SCHEMAS_NCNAME:
   5418 		    case XML_SCHEMAS_ID:
   5419 		    case XML_SCHEMAS_ANYURI:
   5420 			if (value != NULL)
   5421 		    	    len = xmlSchemaNormLen(value);
   5422 		    	break;
   5423 		    default:
   5424 		        TODO
   5425 	    	}
   5426 	    }
   5427 	    if (facet->type == XML_SCHEMA_FACET_LENGTH) {
   5428 		if (len != facet->val->value.decimal.lo)
   5429 		    return(XML_SCHEMAV_CVC_LENGTH_VALID);
   5430 	    } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
   5431 		if (len < facet->val->value.decimal.lo)
   5432 		    return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
   5433 	    } else {
   5434 		if (len > facet->val->value.decimal.lo)
   5435 		    return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
   5436 	    }
   5437 	    break;
   5438 	}
   5439 	case XML_SCHEMA_FACET_TOTALDIGITS:
   5440 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
   5441 
   5442 	    if ((facet->val == NULL) ||
   5443 		((facet->val->type != XML_SCHEMAS_PINTEGER) &&
   5444 		 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
   5445 		(facet->val->value.decimal.frac != 0)) {
   5446 		return(-1);
   5447 	    }
   5448 	    if ((val == NULL) ||
   5449 		((val->type != XML_SCHEMAS_DECIMAL) &&
   5450 		 (val->type != XML_SCHEMAS_INTEGER) &&
   5451 		 (val->type != XML_SCHEMAS_NPINTEGER) &&
   5452 		 (val->type != XML_SCHEMAS_NINTEGER) &&
   5453 		 (val->type != XML_SCHEMAS_NNINTEGER) &&
   5454 		 (val->type != XML_SCHEMAS_PINTEGER) &&
   5455 		 (val->type != XML_SCHEMAS_INT) &&
   5456 		 (val->type != XML_SCHEMAS_UINT) &&
   5457 		 (val->type != XML_SCHEMAS_LONG) &&
   5458 		 (val->type != XML_SCHEMAS_ULONG) &&
   5459 		 (val->type != XML_SCHEMAS_SHORT) &&
   5460 		 (val->type != XML_SCHEMAS_USHORT) &&
   5461 		 (val->type != XML_SCHEMAS_BYTE) &&
   5462 		 (val->type != XML_SCHEMAS_UBYTE))) {
   5463 		return(-1);
   5464 	    }
   5465 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
   5466 	        if (val->value.decimal.total > facet->val->value.decimal.lo)
   5467 	            return(XML_SCHEMAV_CVC_TOTALDIGITS_VALID);
   5468 
   5469 	    } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) {
   5470 	        if (val->value.decimal.frac > facet->val->value.decimal.lo)
   5471 		    return(XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID);
   5472 	    }
   5473 	    break;
   5474 	default:
   5475 	    TODO
   5476     }
   5477     return(0);
   5478 
   5479 }
   5480 
   5481 /**
   5482  * xmlSchemaValidateFacet:
   5483  * @base:  the base type
   5484  * @facet:  the facet to check
   5485  * @value:  the lexical repr of the value to validate
   5486  * @val:  the precomputed value
   5487  *
   5488  * Check a value against a facet condition
   5489  *
   5490  * Returns 0 if the element is schemas valid, a positive error code
   5491  *     number otherwise and -1 in case of internal or API error.
   5492  */
   5493 int
   5494 xmlSchemaValidateFacet(xmlSchemaTypePtr base,
   5495 	               xmlSchemaFacetPtr facet,
   5496 	               const xmlChar *value,
   5497 		       xmlSchemaValPtr val)
   5498 {
   5499     /*
   5500     * This tries to ensure API compatibility regarding the old
   5501     * xmlSchemaValidateFacet() and the new xmlSchemaValidateFacetInternal() and
   5502     * xmlSchemaValidateFacetWhtsp().
   5503     */
   5504     if (val != NULL)
   5505 	return(xmlSchemaValidateFacetInternal(facet,
   5506 	    XML_SCHEMA_WHITESPACE_UNKNOWN, val->type, value, val,
   5507 	    XML_SCHEMA_WHITESPACE_UNKNOWN));
   5508     else if (base != NULL)
   5509 	return(xmlSchemaValidateFacetInternal(facet,
   5510 	    XML_SCHEMA_WHITESPACE_UNKNOWN, base->builtInType, value, val,
   5511 	    XML_SCHEMA_WHITESPACE_UNKNOWN));
   5512     return(-1);
   5513 }
   5514 
   5515 /**
   5516  * xmlSchemaValidateFacetWhtsp:
   5517  * @facet:  the facet to check
   5518  * @fws: the whitespace type of the facet's value
   5519  * @valType: the built-in type of the value
   5520  * @value:  the lexical (or normalized for pattern) repr of the value to validate
   5521  * @val:  the precomputed value
   5522  * @ws: the whitespace type of the value
   5523  *
   5524  * Check a value against a facet condition. This takes value normalization
   5525  * according to the specified whitespace types into account.
   5526  * Note that @value needs to be the *normalized* value if the facet
   5527  * is of type "pattern".
   5528  *
   5529  * Returns 0 if the element is schemas valid, a positive error code
   5530  *     number otherwise and -1 in case of internal or API error.
   5531  */
   5532 int
   5533 xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet,
   5534 			    xmlSchemaWhitespaceValueType fws,
   5535 			    xmlSchemaValType valType,
   5536 			    const xmlChar *value,
   5537 			    xmlSchemaValPtr val,
   5538 			    xmlSchemaWhitespaceValueType ws)
   5539 {
   5540      return(xmlSchemaValidateFacetInternal(facet, fws, valType,
   5541 	 value, val, ws));
   5542 }
   5543 
   5544 #if 0
   5545 #ifndef DBL_DIG
   5546 #define DBL_DIG 16
   5547 #endif
   5548 #ifndef DBL_EPSILON
   5549 #define DBL_EPSILON 1E-9
   5550 #endif
   5551 
   5552 #define INTEGER_DIGITS DBL_DIG
   5553 #define FRACTION_DIGITS (DBL_DIG + 1)
   5554 #define EXPONENT_DIGITS (3 + 2)
   5555 
   5556 /**
   5557  * xmlXPathFormatNumber:
   5558  * @number:     number to format
   5559  * @buffer:     output buffer
   5560  * @buffersize: size of output buffer
   5561  *
   5562  * Convert the number into a string representation.
   5563  */
   5564 static void
   5565 xmlSchemaFormatFloat(double number, char buffer[], int buffersize)
   5566 {
   5567     switch (xmlXPathIsInf(number)) {
   5568     case 1:
   5569 	if (buffersize > (int)sizeof("INF"))
   5570 	    snprintf(buffer, buffersize, "INF");
   5571 	break;
   5572     case -1:
   5573 	if (buffersize > (int)sizeof("-INF"))
   5574 	    snprintf(buffer, buffersize, "-INF");
   5575 	break;
   5576     default:
   5577 	if (xmlXPathIsNaN(number)) {
   5578 	    if (buffersize > (int)sizeof("NaN"))
   5579 		snprintf(buffer, buffersize, "NaN");
   5580 	} else if (number == 0) {
   5581 	    snprintf(buffer, buffersize, "0.0E0");
   5582 	} else {
   5583 	    /* 3 is sign, decimal point, and terminating zero */
   5584 	    char work[DBL_DIG + EXPONENT_DIGITS + 3];
   5585 	    int integer_place, fraction_place;
   5586 	    char *ptr;
   5587 	    char *after_fraction;
   5588 	    double absolute_value;
   5589 	    int size;
   5590 
   5591 	    absolute_value = fabs(number);
   5592 
   5593 	    /*
   5594 	     * Result is in work, and after_fraction points
   5595 	     * just past the fractional part.
   5596 	     * Use scientific notation
   5597 	    */
   5598 	    integer_place = DBL_DIG + EXPONENT_DIGITS + 1;
   5599 	    fraction_place = DBL_DIG - 1;
   5600 	    snprintf(work, sizeof(work),"%*.*e",
   5601 		integer_place, fraction_place, number);
   5602 	    after_fraction = strchr(work + DBL_DIG, 'e');
   5603 	    /* Remove fractional trailing zeroes */
   5604 	    ptr = after_fraction;
   5605 	    while (*(--ptr) == '0')
   5606 		;
   5607 	    if (*ptr != '.')
   5608 	        ptr++;
   5609 	    while ((*ptr++ = *after_fraction++) != 0);
   5610 
   5611 	    /* Finally copy result back to caller */
   5612 	    size = strlen(work) + 1;
   5613 	    if (size > buffersize) {
   5614 		work[buffersize - 1] = 0;
   5615 		size = buffersize;
   5616 	    }
   5617 	    memmove(buffer, work, size);
   5618 	}
   5619 	break;
   5620     }
   5621 }
   5622 #endif
   5623 
   5624 /**
   5625  * xmlSchemaGetCanonValue:
   5626  * @val: the precomputed value
   5627  * @retValue: the returned value
   5628  *
   5629  * Get a the cononical lexical representation of the value.
   5630  * The caller has to FREE the returned retValue.
   5631  *
   5632  * WARNING: Some value types are not supported yet, resulting
   5633  * in a @retValue of "???".
   5634  *
   5635  * TODO: XML Schema 1.0 does not define canonical representations
   5636  * for: duration, gYearMonth, gYear, gMonthDay, gMonth, gDay,
   5637  * anyURI, QName, NOTATION. This will be fixed in XML Schema 1.1.
   5638  *
   5639  *
   5640  * Returns 0 if the value could be built, 1 if the value type is
   5641  * not supported yet and -1 in case of API errors.
   5642  */
   5643 int
   5644 xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue)
   5645 {
   5646     if ((retValue == NULL) || (val == NULL))
   5647 	return (-1);
   5648     *retValue = NULL;
   5649     switch (val->type) {
   5650 	case XML_SCHEMAS_STRING:
   5651 	    if (val->value.str == NULL)
   5652 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
   5653 	    else
   5654 		*retValue =
   5655 		    BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
   5656 	    break;
   5657 	case XML_SCHEMAS_NORMSTRING:
   5658 	    if (val->value.str == NULL)
   5659 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
   5660 	    else {
   5661 		*retValue = xmlSchemaWhiteSpaceReplace(
   5662 		    (const xmlChar *) val->value.str);
   5663 		if ((*retValue) == NULL)
   5664 		    *retValue = BAD_CAST xmlStrdup(
   5665 			(const xmlChar *) val->value.str);
   5666 	    }
   5667 	    break;
   5668 	case XML_SCHEMAS_TOKEN:
   5669 	case XML_SCHEMAS_LANGUAGE:
   5670 	case XML_SCHEMAS_NMTOKEN:
   5671 	case XML_SCHEMAS_NAME:
   5672 	case XML_SCHEMAS_NCNAME:
   5673 	case XML_SCHEMAS_ID:
   5674 	case XML_SCHEMAS_IDREF:
   5675 	case XML_SCHEMAS_ENTITY:
   5676 	case XML_SCHEMAS_NOTATION: /* Unclear */
   5677 	case XML_SCHEMAS_ANYURI:   /* Unclear */
   5678 	    if (val->value.str == NULL)
   5679 		return (-1);
   5680 	    *retValue =
   5681 		BAD_CAST xmlSchemaCollapseString(BAD_CAST val->value.str);
   5682 	    if (*retValue == NULL)
   5683 		*retValue =
   5684 		    BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
   5685 	    break;
   5686 	case XML_SCHEMAS_QNAME:
   5687 	    /* TODO: Unclear in XML Schema 1.0. */
   5688 	    if (val->value.qname.uri == NULL) {
   5689 		*retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.qname.name);
   5690 		return (0);
   5691 	    } else {
   5692 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "{");
   5693 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
   5694 		    BAD_CAST val->value.qname.uri);
   5695 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
   5696 		    BAD_CAST "}");
   5697 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
   5698 		    BAD_CAST val->value.qname.uri);
   5699 	    }
   5700 	    break;
   5701 	case XML_SCHEMAS_DECIMAL:
   5702 	    /*
   5703 	    * TODO: Lookout for a more simple implementation.
   5704 	    */
   5705 	    if ((val->value.decimal.total == 1) &&
   5706 		(val->value.decimal.lo == 0)) {
   5707 		*retValue = xmlStrdup(BAD_CAST "0.0");
   5708 	    } else {
   5709 		xmlSchemaValDecimal dec = val->value.decimal;
   5710 		int bufsize;
   5711 		char *buf = NULL, *offs;
   5712 
   5713 		/* Add room for the decimal point as well. */
   5714 		bufsize = dec.total + 2;
   5715 		if (dec.sign)
   5716 		    bufsize++;
   5717 		/* Add room for leading/trailing zero. */
   5718 		if ((dec.frac == 0) || (dec.frac == dec.total))
   5719 		    bufsize++;
   5720 		buf = xmlMalloc(bufsize);
   5721 		if (buf == NULL)
   5722 		    return(-1);
   5723 		offs = buf;
   5724 		if (dec.sign)
   5725 		    *offs++ = '-';
   5726 		if (dec.frac == dec.total) {
   5727 		    *offs++ = '0';
   5728 		    *offs++ = '.';
   5729 		}
   5730 		if (dec.hi != 0)
   5731 		    snprintf(offs, bufsize - (offs - buf),
   5732 			"%lu%lu%lu", dec.hi, dec.mi, dec.lo);
   5733 		else if (dec.mi != 0)
   5734 		    snprintf(offs, bufsize - (offs - buf),
   5735 			"%lu%lu", dec.mi, dec.lo);
   5736 		else
   5737 		    snprintf(offs, bufsize - (offs - buf),
   5738 			"%lu", dec.lo);
   5739 
   5740 		if (dec.frac != 0) {
   5741 		    if (dec.frac != dec.total) {
   5742 			int diff = dec.total - dec.frac;
   5743 			/*
   5744 			* Insert the decimal point.
   5745 			*/
   5746 			memmove(offs + diff + 1, offs + diff, dec.frac +1);
   5747 			offs[diff] = '.';
   5748 		    } else {
   5749 			unsigned int i = 0;
   5750 			/*
   5751 			* Insert missing zeroes behind the decimal point.
   5752 			*/
   5753 			while (*(offs + i) != 0)
   5754 			    i++;
   5755 			if (i < dec.total) {
   5756 			    memmove(offs + (dec.total - i), offs, i +1);
   5757 			    memset(offs, '0', dec.total - i);
   5758 			}
   5759 		    }
   5760 		} else {
   5761 		    /*
   5762 		    * Append decimal point and zero.
   5763 		    */
   5764 		    offs = buf + bufsize - 1;
   5765 		    *offs-- = 0;
   5766 		    *offs-- = '0';
   5767 		    *offs-- = '.';
   5768 		}
   5769 		*retValue = BAD_CAST buf;
   5770 	    }
   5771 	    break;
   5772 	case XML_SCHEMAS_INTEGER:
   5773         case XML_SCHEMAS_PINTEGER:
   5774         case XML_SCHEMAS_NPINTEGER:
   5775         case XML_SCHEMAS_NINTEGER:
   5776         case XML_SCHEMAS_NNINTEGER:
   5777 	case XML_SCHEMAS_LONG:
   5778         case XML_SCHEMAS_BYTE:
   5779         case XML_SCHEMAS_SHORT:
   5780         case XML_SCHEMAS_INT:
   5781 	case XML_SCHEMAS_UINT:
   5782         case XML_SCHEMAS_ULONG:
   5783         case XML_SCHEMAS_USHORT:
   5784         case XML_SCHEMAS_UBYTE:
   5785 	    if ((val->value.decimal.total == 1) &&
   5786 		(val->value.decimal.lo == 0))
   5787 		*retValue = xmlStrdup(BAD_CAST "0");
   5788 	    else {
   5789 		xmlSchemaValDecimal dec = val->value.decimal;
   5790 		int bufsize = dec.total + 1;
   5791 
   5792 		/* Add room for the decimal point as well. */
   5793 		if (dec.sign)
   5794 		    bufsize++;
   5795 		*retValue = xmlMalloc(bufsize);
   5796 		if (*retValue == NULL)
   5797 		    return(-1);
   5798 		if (dec.hi != 0) {
   5799 		    if (dec.sign)
   5800 			snprintf((char *) *retValue, bufsize,
   5801 			    "-%lu%lu%lu", dec.hi, dec.mi, dec.lo);
   5802 		    else
   5803 			snprintf((char *) *retValue, bufsize,
   5804 			    "%lu%lu%lu", dec.hi, dec.mi, dec.lo);
   5805 		} else if (dec.mi != 0) {
   5806 		    if (dec.sign)
   5807 			snprintf((char *) *retValue, bufsize,
   5808 			    "-%lu%lu", dec.mi, dec.lo);
   5809 		    else
   5810 			snprintf((char *) *retValue, bufsize,
   5811 			    "%lu%lu", dec.mi, dec.lo);
   5812 		} else {
   5813 		    if (dec.sign)
   5814 			snprintf((char *) *retValue, bufsize, "-%lu", dec.lo);
   5815 		    else
   5816 			snprintf((char *) *retValue, bufsize, "%lu", dec.lo);
   5817 		}
   5818 	    }
   5819 	    break;
   5820 	case XML_SCHEMAS_BOOLEAN:
   5821 	    if (val->value.b)
   5822 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "true");
   5823 	    else
   5824 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "false");
   5825 	    break;
   5826 	case XML_SCHEMAS_DURATION: {
   5827 		char buf[100];
   5828 		unsigned long year;
   5829 		unsigned long mon, day, hour = 0, min = 0;
   5830 		double sec = 0, left;
   5831 
   5832 		/* TODO: Unclear in XML Schema 1.0 */
   5833 		/*
   5834 		* TODO: This results in a normalized output of the value
   5835 		* - which is NOT conformant to the spec -
   5836 		* since the exact values of each property are not
   5837 		* recoverable. Think about extending the structure to
   5838 		* provide a field for every property.
   5839 		*/
   5840 		year = (unsigned long) FQUOTIENT(labs(val->value.dur.mon), 12);
   5841 		mon = labs(val->value.dur.mon) - 12 * year;
   5842 
   5843 		day = (unsigned long) FQUOTIENT(fabs(val->value.dur.sec), 86400);
   5844 		left = fabs(val->value.dur.sec) - day * 86400;
   5845 		if (left > 0) {
   5846 		    hour = (unsigned long) FQUOTIENT(left, 3600);
   5847 		    left = left - (hour * 3600);
   5848 		    if (left > 0) {
   5849 			min = (unsigned long) FQUOTIENT(left, 60);
   5850 			sec = left - (min * 60);
   5851 		    }
   5852 		}
   5853 		if ((val->value.dur.mon < 0) || (val->value.dur.sec < 0))
   5854 		    snprintf(buf, 100, "P%luY%luM%luDT%luH%luM%.14gS",
   5855 			year, mon, day, hour, min, sec);
   5856 		else
   5857 		    snprintf(buf, 100, "-P%luY%luM%luDT%luH%luM%.14gS",
   5858 			year, mon, day, hour, min, sec);
   5859 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
   5860 	    }
   5861 	    break;
   5862 	case XML_SCHEMAS_GYEAR: {
   5863 		char buf[30];
   5864 		/* TODO: Unclear in XML Schema 1.0 */
   5865 		/* TODO: What to do with the timezone? */
   5866 		snprintf(buf, 30, "%04ld", val->value.date.year);
   5867 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
   5868 	    }
   5869 	    break;
   5870 	case XML_SCHEMAS_GMONTH: {
   5871 		/* TODO: Unclear in XML Schema 1.0 */
   5872 		/* TODO: What to do with the timezone? */
   5873 		*retValue = xmlMalloc(6);
   5874 		if (*retValue == NULL)
   5875 		    return(-1);
   5876 		snprintf((char *) *retValue, 6, "--%02u",
   5877 		    val->value.date.mon);
   5878 	    }
   5879 	    break;
   5880         case XML_SCHEMAS_GDAY: {
   5881 		/* TODO: Unclear in XML Schema 1.0 */
   5882 		/* TODO: What to do with the timezone? */
   5883 		*retValue = xmlMalloc(6);
   5884 		if (*retValue == NULL)
   5885 		    return(-1);
   5886 		snprintf((char *) *retValue, 6, "---%02u",
   5887 		    val->value.date.day);
   5888 	    }
   5889 	    break;
   5890         case XML_SCHEMAS_GMONTHDAY: {
   5891 		/* TODO: Unclear in XML Schema 1.0 */
   5892 		/* TODO: What to do with the timezone? */
   5893 		*retValue = xmlMalloc(8);
   5894 		if (*retValue == NULL)
   5895 		    return(-1);
   5896 		snprintf((char *) *retValue, 8, "--%02u-%02u",
   5897 		    val->value.date.mon, val->value.date.day);
   5898 	    }
   5899 	    break;
   5900         case XML_SCHEMAS_GYEARMONTH: {
   5901 		char buf[35];
   5902 		/* TODO: Unclear in XML Schema 1.0 */
   5903 		/* TODO: What to do with the timezone? */
   5904 		if (val->value.date.year < 0)
   5905 		    snprintf(buf, 35, "-%04ld-%02u",
   5906 			labs(val->value.date.year),
   5907 			val->value.date.mon);
   5908 		else
   5909 		    snprintf(buf, 35, "%04ld-%02u",
   5910 			val->value.date.year, val->value.date.mon);
   5911 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
   5912 	    }
   5913 	    break;
   5914 	case XML_SCHEMAS_TIME:
   5915 	    {
   5916 		char buf[30];
   5917 
   5918 		if (val->value.date.tz_flag) {
   5919 		    xmlSchemaValPtr norm;
   5920 
   5921 		    norm = xmlSchemaDateNormalize(val, 0);
   5922 		    if (norm == NULL)
   5923 			return (-1);
   5924 		    /*
   5925 		    * TODO: Check if "%.14g" is portable.
   5926 		    */
   5927 		    snprintf(buf, 30,
   5928 			"%02u:%02u:%02.14gZ",
   5929 			norm->value.date.hour,
   5930 			norm->value.date.min,
   5931 			norm->value.date.sec);
   5932 		    xmlSchemaFreeValue(norm);
   5933 		} else {
   5934 		    snprintf(buf, 30,
   5935 			"%02u:%02u:%02.14g",
   5936 			val->value.date.hour,
   5937 			val->value.date.min,
   5938 			val->value.date.sec);
   5939 		}
   5940 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
   5941 	    }
   5942 	    break;
   5943         case XML_SCHEMAS_DATE:
   5944 	    {
   5945 		char buf[30];
   5946 
   5947 		if (val->value.date.tz_flag) {
   5948 		    xmlSchemaValPtr norm;
   5949 
   5950 		    norm = xmlSchemaDateNormalize(val, 0);
   5951 		    if (norm == NULL)
   5952 			return (-1);
   5953 		    /*
   5954 		    * TODO: Append the canonical value of the
   5955 		    * recoverable timezone and not "Z".
   5956 		    */
   5957 		    snprintf(buf, 30,
   5958 			"%04ld:%02u:%02uZ",
   5959 			norm->value.date.year, norm->value.date.mon,
   5960 			norm->value.date.day);
   5961 		    xmlSchemaFreeValue(norm);
   5962 		} else {
   5963 		    snprintf(buf, 30,
   5964 			"%04ld:%02u:%02u",
   5965 			val->value.date.year, val->value.date.mon,
   5966 			val->value.date.day);
   5967 		}
   5968 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
   5969 	    }
   5970 	    break;
   5971         case XML_SCHEMAS_DATETIME:
   5972 	    {
   5973 		char buf[50];
   5974 
   5975 		if (val->value.date.tz_flag) {
   5976 		    xmlSchemaValPtr norm;
   5977 
   5978 		    norm = xmlSchemaDateNormalize(val, 0);
   5979 		    if (norm == NULL)
   5980 			return (-1);
   5981 		    /*
   5982 		    * TODO: Check if "%.14g" is portable.
   5983 		    */
   5984 		    snprintf(buf, 50,
   5985 			"%04ld:%02u:%02uT%02u:%02u:%02.14gZ",
   5986 			norm->value.date.year, norm->value.date.mon,
   5987 			norm->value.date.day, norm->value.date.hour,
   5988 			norm->value.date.min, norm->value.date.sec);
   5989 		    xmlSchemaFreeValue(norm);
   5990 		} else {
   5991 		    snprintf(buf, 50,
   5992 			"%04ld:%02u:%02uT%02u:%02u:%02.14g",
   5993 			val->value.date.year, val->value.date.mon,
   5994 			val->value.date.day, val->value.date.hour,
   5995 			val->value.date.min, val->value.date.sec);
   5996 		}
   5997 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
   5998 	    }
   5999 	    break;
   6000 	case XML_SCHEMAS_HEXBINARY:
   6001 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.hex.str);
   6002 	    break;
   6003 	case XML_SCHEMAS_BASE64BINARY:
   6004 	    /*
   6005 	    * TODO: Is the following spec piece implemented?:
   6006 	    * SPEC: "Note: For some values the canonical form defined
   6007 	    * above does not conform to [RFC 2045], which requires breaking
   6008 	    * with linefeeds at appropriate intervals."
   6009 	    */
   6010 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.base64.str);
   6011 	    break;
   6012 	case XML_SCHEMAS_FLOAT: {
   6013 		char buf[30];
   6014 		/*
   6015 		* |m| < 16777216, -149 <= e <= 104.
   6016 		* TODO: Handle, NaN, INF, -INF. The format is not
   6017 		* yet conformant. The c type float does not cover
   6018 		* the whole range.
   6019 		*/
   6020 		snprintf(buf, 30, "%01.14e", val->value.f);
   6021 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
   6022 	    }
   6023 	    break;
   6024 	case XML_SCHEMAS_DOUBLE: {
   6025 		char buf[40];
   6026 		/* |m| < 9007199254740992, -1075 <= e <= 970 */
   6027 		/*
   6028 		* TODO: Handle, NaN, INF, -INF. The format is not
   6029 		* yet conformant. The c type float does not cover
   6030 		* the whole range.
   6031 		*/
   6032 		snprintf(buf, 40, "%01.14e", val->value.d);
   6033 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
   6034 	    }
   6035 	    break;
   6036 	default:
   6037 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST "???");
   6038 	    return (1);
   6039     }
   6040     if (*retValue == NULL)
   6041 	return(-1);
   6042     return (0);
   6043 }
   6044 
   6045 /**
   6046  * xmlSchemaGetCanonValueWhtsp:
   6047  * @val: the precomputed value
   6048  * @retValue: the returned value
   6049  * @ws: the whitespace type of the value
   6050  *
   6051  * Get a the cononical representation of the value.
   6052  * The caller has to free the returned @retValue.
   6053  *
   6054  * Returns 0 if the value could be built, 1 if the value type is
   6055  * not supported yet and -1 in case of API errors.
   6056  */
   6057 int
   6058 xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val,
   6059 			    const xmlChar **retValue,
   6060 			    xmlSchemaWhitespaceValueType ws)
   6061 {
   6062     if ((retValue == NULL) || (val == NULL))
   6063 	return (-1);
   6064     if ((ws == XML_SCHEMA_WHITESPACE_UNKNOWN) ||
   6065 	(ws > XML_SCHEMA_WHITESPACE_COLLAPSE))
   6066 	return (-1);
   6067 
   6068     *retValue = NULL;
   6069     switch (val->type) {
   6070 	case XML_SCHEMAS_STRING:
   6071 	    if (val->value.str == NULL)
   6072 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
   6073 	    else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
   6074 		*retValue = xmlSchemaCollapseString(val->value.str);
   6075 	    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
   6076 		*retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
   6077 	    if ((*retValue) == NULL)
   6078 		*retValue = BAD_CAST xmlStrdup(val->value.str);
   6079 	    break;
   6080 	case XML_SCHEMAS_NORMSTRING:
   6081 	    if (val->value.str == NULL)
   6082 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
   6083 	    else {
   6084 		if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
   6085 		    *retValue = xmlSchemaCollapseString(val->value.str);
   6086 		else
   6087 		    *retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
   6088 		if ((*retValue) == NULL)
   6089 		    *retValue = BAD_CAST xmlStrdup(val->value.str);
   6090 	    }
   6091 	    break;
   6092 	default:
   6093 	    return (xmlSchemaGetCanonValue(val, retValue));
   6094     }
   6095     return (0);
   6096 }
   6097 
   6098 /**
   6099  * xmlSchemaGetValType:
   6100  * @val: a schemas value
   6101  *
   6102  * Accessor for the type of a value
   6103  *
   6104  * Returns the xmlSchemaValType of the value
   6105  */
   6106 xmlSchemaValType
   6107 xmlSchemaGetValType(xmlSchemaValPtr val)
   6108 {
   6109     if (val == NULL)
   6110         return(XML_SCHEMAS_UNKNOWN);
   6111     return (val->type);
   6112 }
   6113 
   6114 #define bottom_xmlschemastypes
   6115 #include "elfgcchack.h"
   6116 #endif /* LIBXML_SCHEMAS_ENABLED */
   6117