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