← Back to team overview

zorba-coders team mailing list archive

[Merge] lp:~zorba-coders/zorba/bug-1123164 into lp:zorba

 

Paul J. Lucas has proposed merging lp:~zorba-coders/zorba/bug-1123164 into lp:zorba.

Commit message:
Rewrote format-number() code because it was simpler that try to hack fix the old code.

Requested reviews:
  Paul J. Lucas (paul-lucas)
Related bugs:
  Bug #1123164 in Zorba: "fn:format-number failures (at least 19)"
  https://bugs.launchpad.net/zorba/+bug/1123164

For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/bug-1123164/+merge/158254

Rewrote format-number() code because it was simpler that try to hack fix the old code.
-- 
https://code.launchpad.net/~zorba-coders/zorba/bug-1123164/+merge/158254
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'ChangeLog'
--- ChangeLog	2013-04-10 14:18:16 +0000
+++ ChangeLog	2013-04-11 00:34:24 +0000
@@ -71,6 +71,7 @@
   * Fixed bug #1099535  (xml:parse endless loop)
   * Fixed bug in optimizing fn:count over general-index probes
   * Fixed bug #866958  (Parsing error not explicit enough)
+  * Fixed bug #1123164 (fn:format-number failures (at least 19))
   * Fixed bug in computing the static type of a self-axis path step.
   * Fixed bug #867068: (Incorrect usage of XQDY0027)
   * Fixed bug: jsoniq constructor should not be const-folded

=== modified file 'include/zorba/pregenerated/diagnostic_list.h'
--- include/zorba/pregenerated/diagnostic_list.h	2013-04-02 21:46:10 +0000
+++ include/zorba/pregenerated/diagnostic_list.h	2013-04-11 00:34:24 +0000
@@ -148,6 +148,8 @@
 
 extern ZORBA_DLL_PUBLIC XQueryErrorCode XQST0094;
 
+extern ZORBA_DLL_PUBLIC XQueryErrorCode XQST0097;
+
 extern ZORBA_DLL_PUBLIC XQueryErrorCode XQST0098;
 
 extern ZORBA_DLL_PUBLIC XQueryErrorCode XQST0099;
@@ -158,6 +160,8 @@
 
 extern ZORBA_DLL_PUBLIC XQueryErrorCode XQST0111;
 
+extern ZORBA_DLL_PUBLIC XQueryErrorCode XQST0114;
+
 extern ZORBA_DLL_PUBLIC XQueryErrorCode XQST0123;
 
 extern ZORBA_DLL_PUBLIC XQueryErrorCode XPDY0002;

=== modified file 'modules/w3c/pregenerated/xqt-errors.xq'
--- modules/w3c/pregenerated/xqt-errors.xq	2013-04-02 21:46:10 +0000
+++ modules/w3c/pregenerated/xqt-errors.xq	2013-04-11 00:34:24 +0000
@@ -626,6 +626,15 @@
 
 (:~
  :
+ : It is a static error for a decimal-format to specify a value that is
+ : not valid for a given property.
+ : 
+ : @see http://www.w3.org/2005/xqt-errors
+:)
+declare variable $err:XQST0097 as xs:QName := fn:QName($err:NS, "err:XQST0097");
+
+(:~
+ :
  : It is a static error if, for any named or unnamed decimal format, the
  : properties representing characters used in a picture string do not each
  : have distinct values. These properties are decimal-separator-sign,
@@ -674,7 +683,17 @@
 
 (:~
  :
- : It is a static error if the name of a feature in require-feature is not recognized by the implementation.
+ : It is a static error for a decimal format declaration to define the
+ : same property more than once.
+ : 
+ : @see http://www.w3.org/2005/xqt-errors
+:)
+declare variable $err:XQST0114 as xs:QName := fn:QName($err:NS, "err:XQST0114");
+
+(:~
+ :
+ : It is a static error if the name of a feature in require-feature is not
+ : recognized by the implementation.
  : 
  : @see http://www.w3.org/2005/xqt-errors
 :)

=== modified file 'src/compiler/parser/FlexLexer.h'
--- src/compiler/parser/FlexLexer.h	2013-03-27 17:10:46 +0000
+++ src/compiler/parser/FlexLexer.h	2013-04-11 00:34:24 +0000
@@ -63,7 +63,7 @@
 	virtual ~FlexLexer()	{ }
 
 	const char* YYText() const	{ return yytext; }
-	int YYLeng()	const	{ return yyleng; }
+	size_t YYLeng()	const	{ return yyleng; }
 
 	virtual void
 		yy_switch_to_buffer( struct yy_buffer_state* new_buffer ) = 0;
@@ -93,7 +93,7 @@
 
 protected:
 	char* yytext;
-	int yyleng;
+	size_t yyleng;
 	int yylineno;		// only maintained if you use %option yylineno
 	int yy_flex_debug;	// only has effect with -d or "%option debug"
 };
@@ -130,8 +130,8 @@
 	virtual int yywrap();
 
 protected:
-	virtual int LexerInput( char* buf, int max_size );
-	virtual void LexerOutput( const char* buf, int size );
+	virtual size_t LexerInput( char* buf, size_t max_size );
+	virtual void LexerOutput( const char* buf, size_t size );
 	virtual void LexerError( const char* msg );
 
 	void yyunput( int c, char* buf_ptr );
@@ -160,7 +160,7 @@
 	char yy_hold_char;
 
 	// Number of characters read into yy_ch_buf.
-	int yy_n_chars;
+	size_t yy_n_chars;
 
 	// Points to current character in buffer.
 	char* yy_c_buf_p;

=== modified file 'src/compiler/parser/jsoniq_parser.cpp'
--- src/compiler/parser/jsoniq_parser.cpp	2013-04-07 19:06:10 +0000
+++ src/compiler/parser/jsoniq_parser.cpp	2013-04-11 00:34:24 +0000
@@ -3713,7 +3713,7 @@
 
 /* Line 690 of lalr1.cc  */
 #line 1626 "/home/colea/xquery/new-jsoniq/src/compiler/parser/jsoniq_parser.y"
-    { (yyval.strval) = "infinty"; }
+    { (yyval.strval) = "infinity"; }
     break;
 
   case 98:

=== modified file 'src/compiler/parser/jsoniq_parser.y'
--- src/compiler/parser/jsoniq_parser.y	2013-03-27 17:32:54 +0000
+++ src/compiler/parser/jsoniq_parser.y	2013-04-11 00:34:24 +0000
@@ -1623,7 +1623,7 @@
       DECIMAL_SEPARATOR   { $$ = "decimal-separator"; }
     | DIGIT               { $$ = "digit"; }
     | GROUPING_SEPARATOR  { $$ = "grouping-separator"; }
-    | INFINITY_VALUE      { $$ = "infinty"; }
+    | INFINITY_VALUE      { $$ = "infinity"; }
     | MINUS_SIGN          { $$ = "minus-sign"; }
     | NaN                 { $$ = "NaN"; }
     | PATTERN_SEPARATOR   { $$ = "pattern-separator"; }

=== modified file 'src/compiler/parser/xquery_parser.cpp'
--- src/compiler/parser/xquery_parser.cpp	2013-04-07 19:06:10 +0000
+++ src/compiler/parser/xquery_parser.cpp	2013-04-11 00:34:24 +0000
@@ -3757,7 +3757,7 @@
 
 /* Line 690 of lalr1.cc  */
 #line 1602 "/home/colea/xquery/new-jsoniq/src/compiler/parser/xquery_parser.y"
-    { (yyval.strval) = "infinty"; }
+    { (yyval.strval) = "infinity"; }
     break;
 
   case 96:

=== modified file 'src/compiler/parser/xquery_parser.y'
--- src/compiler/parser/xquery_parser.y	2013-03-20 23:33:11 +0000
+++ src/compiler/parser/xquery_parser.y	2013-04-11 00:34:24 +0000
@@ -1599,7 +1599,7 @@
       DECIMAL_SEPARATOR   { $$ = "decimal-separator"; }
     | DIGIT               { $$ = "digit"; }
     | GROUPING_SEPARATOR  { $$ = "grouping-separator"; }
-    | INFINITY_VALUE      { $$ = "infinty"; }
+    | INFINITY_VALUE      { $$ = "infinity"; }
     | MINUS_SIGN          { $$ = "minus-sign"; }
     | NaN                 { $$ = "NaN"; }
     | PATTERN_SEPARATOR   { $$ = "pattern-separator"; }

=== modified file 'src/compiler/translator/translator.cpp'
--- src/compiler/translator/translator.cpp	2013-04-08 22:59:58 +0000
+++ src/compiler/translator/translator.cpp	2013-04-11 00:34:24 +0000
@@ -2902,9 +2902,9 @@
     expand_no_default_qname(qnameItem, v.format_name, loc);
   }
 
-  DecimalFormat_t df = new DecimalFormat(v.is_default, qnameItem, v.param_list);
-  df->validate(loc);
-  theSctx->add_decimal_format(df, loc);
+  theSctx->add_decimal_format(
+    new DecimalFormat( v.is_default, qnameItem, v.param_list, loc ), loc
+  );
 
   return no_state;
 }

=== modified file 'src/context/decimal_format.cpp'
--- src/context/decimal_format.cpp	2013-02-07 17:24:36 +0000
+++ src/context/decimal_format.cpp	2013-04-11 00:34:24 +0000
@@ -16,68 +16,124 @@
 #include "stdafx.h"
 
 #include <zorba/api_shared_types.h>
+#include "common/shared_types.h"
 #include "context/decimal_format.h"
-#include "common/shared_types.h"
-
+#include "store/api/item.h"
+#include "util/stl_util.h"
+#include "util/utf8_util.h"
+#include "zorbaserialization/serialize_template_types.h"
 #include "zorbaserialization/serialize_zorba_types.h"
-#include "zorbaserialization/serialize_template_types.h"
-
-#include "store/api/item.h"
 
 namespace zorba {
 
 SERIALIZABLE_CLASS_VERSIONS(DecimalFormat)
 
-
-DecimalFormat::DecimalFormat(
-    bool isDefault,
-    const store::Item_t& qname,
-    const param_vector_type& params)
-  :
-  theIsDefault(isDefault),
-  theName(qname),
-  theParams(params)
-{
-}
-
-
-void DecimalFormat::serialize(::zorba::serialization::Archiver& ar)
-{
-  ar & theIsDefault;
-  ar & theName;
-  ar & theParams;
-}
-
-
-bool DecimalFormat::isPictureStringProperty(zstring propertyName)
-{
-  if (propertyName == "decimal-separator" ||
-      propertyName == "grouping-separator" ||
-      propertyName == "percent" ||
-      propertyName == "per-mille" ||
-      propertyName == "zero-digit" ||
-      propertyName == "digit" ||
-      propertyName == "pattern-separator")
-    return true;
-  else
-    return false;
-}
-
-bool DecimalFormat::validate(const QueryLoc& loc) const
-{
-  for (unsigned int i = 0; i<theParams.size()-1; i++)
-    for (unsigned int j = i+1; j<theParams.size(); j++)
-    {
-      if (isPictureStringProperty(theParams[i].first)
-          &&
-          isPictureStringProperty(theParams[j].first)
-          &&
-          theParams[i].second == theParams[j].second)
-        throw XQUERY_EXCEPTION(err::XQST0098, ERROR_PARAMS(theParams[i].first, theParams[j].first), ERROR_LOC(loc));
+///////////////////////////////////////////////////////////////////////////////
+
+DecimalFormat::DecimalFormat( bool is_default, const store::Item_t& qname,
+                              ctor_properties_type const &properties,
+                              QueryLoc const &loc ) :
+  is_default_( is_default ),
+  qname_( qname )
+{
+  for ( ctor_properties_type::size_type i = 0; i < properties.size() - 1;
+        ++i ) {
+    for ( ctor_properties_type::size_type j = i + 1; j < properties.size();
+          ++j ) {
+      if ( i == j )
+        continue;
+      if ( properties[i].first == properties[j].first ) {
+        //
+        // XQuery 3.0 4.10: It is a static error for a decimal format
+        // declaration to define the same property more than once.
+        //
+        throw XQUERY_EXCEPTION(
+          err::XQST0114,
+          ERROR_PARAMS( properties[i].first ),
+          ERROR_LOC( loc )
+        );
+      }
+      if ( properties[i].second == properties[j].second ) {
+        //
+        // Ibid: It is a static error if, for any named or unnamed decimal
+        // format, the properties representing characters used in a picture
+        // string do not have distinct values.
+        //
+        throw XQUERY_EXCEPTION(
+          err::XQST0098,
+          ERROR_PARAMS(
+            properties[i].second, properties[i].first, properties[j].first
+          ),
+          ERROR_LOC( loc )
+        );
+      }
+    } // for ( ... j ... )
+  } // for ( ... i ... )
+
+  FOR_EACH( ctor_properties_type, property, properties )
+    properties_[ property->first ] = property->second;
+
+  struct property_attribute {
+    char const *name;
+    bool is_string;
+    char const *default_value;
+  };
+
+  static property_attribute const attributes[] = {
+    { "decimal-separator" , false, "."            },
+    { "digit"             , false, "#"            },
+    { "grouping-separator", false, ","            },
+    { "infinity"          , true , "Infinity"     },
+    { "minus-sign"        , false, "-"            },
+    { "NaN"               , true , "Nan"          },
+    { "pattern-separator" , false, ";"            },
+    { "percent"           , false, "%"            },
+    { "per-mille"         , false, "\xE2\x80\xB0" },
+    { "zero-digit"        , false, "0"            },
+    { 0, false, 0 }
+  };
+
+  for ( property_attribute const *attr = attributes; attr->name; ++attr ) {
+    value_type &value = properties_[ attr->name ];
+    if ( value.empty() )
+      value = attr->default_value;
+    else if ( !attr->is_string && utf8::length( value ) > 1 ) {
+      //
+      // Ibid: It is a static error for a decimal format declaration to specify
+      // a value that is not valid for a given property.
+      //
+      throw XQUERY_EXCEPTION(
+        err::XQST0097,
+        ERROR_PARAMS( value, attr->name, ZED( XQST0097_MustBeChar ) ),
+        ERROR_LOC( loc )
+      );
     }
-
-  return true;
-}
+  }
+
+  //
+  // XQuery 3.0 2.1.1: zero-digit specifies the character used for the zero-
+  // digit-symbol; the default value is the digit zero (0). This character must
+  // be a digit (category Nd in the Unicode property database), and it must
+  // have the numeric value zero.
+  //
+  value_type const &zero_digit = properties_[ "zero-digit" ];
+  unicode::code_point const zero_digit_cp = utf8::decode( zero_digit.c_str() );
+  unicode::code_point zero_cp;
+  if ( !unicode::is_Nd( zero_digit_cp, &zero_cp ) || zero_digit_cp != zero_cp )
+    throw XQUERY_EXCEPTION(
+      err::XQST0097,
+      ERROR_PARAMS( zero_digit, "zero-digit", ZED( XQST0097_MustBeZeroDigit ) ),
+      ERROR_LOC( loc )
+    );
+}
+
+void DecimalFormat::serialize( serialization::Archiver &ar ) {
+  ar & is_default_;
+  ar & qname_;
+  ar & properties_;
+}
+
+///////////////////////////////////////////////////////////////////////////////
 
 }	// namespace zorba
 /* vim:set et sw=2 ts=2: */

=== modified file 'src/context/decimal_format.h'
--- src/context/decimal_format.h	2013-02-07 17:24:36 +0000
+++ src/context/decimal_format.h	2013-04-11 00:34:24 +0000
@@ -17,60 +17,52 @@
 #ifndef ZORBA_DECIMAL_FORMAT_H
 #define ZORBA_DECIMAL_FORMAT_H
 
+#include <utility>                      /* for pair */
+#include <map>
 #include <vector>
 
 #include "common/shared_types.h"
-
+#include "store/api/item.h"
+#include "util/unordered_map.h"
+#include "zorbaserialization/class_serializer.h"
 #include "zorbatypes/zstring.h"
 
-#include "zorbaserialization/class_serializer.h"
-
-#include "store/api/item.h"
-
-
-namespace zorba
-{
-
-class DecimalFormat : public SimpleRCObject
-{
+///////////////////////////////////////////////////////////////////////////////
+
+namespace zorba {
+
+class DecimalFormat : public SimpleRCObject {
 public:
-  typedef std::vector<std::pair<zstring,zstring> > param_vector_type;
+  typedef zstring name_type;
+  typedef zstring value_type;
 
-protected:
-  bool              theIsDefault;
-  store::Item_t     theName;
-  param_vector_type theParams;
+  typedef std::vector< std::pair<name_type,value_type> > ctor_properties_type;
+  typedef std::map<name_type,value_type> properties_type;
 
 public:
   SERIALIZABLE_CLASS(DecimalFormat)
   SERIALIZABLE_CLASS_CONSTRUCTOR2(DecimalFormat, SimpleRCObject)
-  void serialize(::zorba::serialization::Archiver& ar);
-
-protected:
-  // Returns true if the given property represents characters used in a
-  // picture string. These properties are decimal-separator-sign,
-  // grouping-separator, percent-sign, per-mille-sign, zero-digit,
-  // digit-sign, and pattern-separator-sign.
-  static bool isPictureStringProperty(zstring propertyName);
+  void serialize( serialization::Archiver& );
 
 public:
-  DecimalFormat(
-        bool isDefault,
-        const store::Item_t& qname,
-        const param_vector_type& params);
-
-  bool isDefault() const { return theIsDefault; }
-
-  const store::Item* getName() const { return theName.getp(); }
-
-  const param_vector_type* getParamVector() const { return &theParams; }
-
-  bool validate(const QueryLoc& loc) const;
+  DecimalFormat( bool is_default, store::Item_t const &qname,
+                 ctor_properties_type const &properties, QueryLoc const &loc );
+
+  store::Item const* getName() const { return qname_.getp(); }
+  properties_type const& getProperties() const { return properties_; }
+  bool isDefault() const { return is_default_; }
+
+private:
+  bool            is_default_;
+  store::Item_t   qname_;
+  properties_type properties_;
 };
 
 
 typedef rchandle<DecimalFormat> DecimalFormat_t;
 
+///////////////////////////////////////////////////////////////////////////////
+
 } /* namespace zorba */
 #endif /* ZORBA_DECIMAL_FORMAT_H */
 

=== modified file 'src/diagnostics/diagnostic_en.xml'
--- src/diagnostics/diagnostic_en.xml	2013-04-08 22:59:58 +0000
+++ src/diagnostics/diagnostic_en.xml	2013-04-11 00:34:24 +0000
@@ -264,13 +264,12 @@
 
     <diagnostic code="XPTY0004">
       <comment>
-       It is a type error if, during the static analysis phase, an expression
-       is found to have a static type that is not appropriate for the context
-       in which the expression occurs, or during the dynamic evaluation phase,
-       the dynamic type of a value does not match a required type as specified
-       by the matching rules in 2.5.4 SequenceType Matching.
+        It is a type error if, during the static analysis phase, an expression
+        is found to have a static type that is not appropriate for the context
+        in which the expression occurs, or during the dynamic evaluation phase,
+        the dynamic type of a value does not match a required type as specified
+        by the matching rules in 2.5.4 SequenceType Matching.
       </comment>
-
       <value>$1</value>
 
       <entry key="NoReturnTypePromote_234">
@@ -293,10 +292,6 @@
         <value>$2 can not be treated as type $3</value>
       </entry>
 
-      <entry key="FormatNumber_2">
-        <value>first parameter to format-number() function is type $2 that is not allowed</value>
-      </entry>
-
       <entry key="JSONIQ_SELECTOR">
         <value>can not atomize and/or cast value of type $2 to string</value>
       </entry>
@@ -765,15 +760,29 @@
       <value>"$1": grouping variable not defined in the same flwor expression as the group-by clause</value>
     </diagnostic>
 
+    <diagnostic code="XQST0097">
+      <comment>
+        It is a static error for a decimal-format to specify a value that is
+        not valid for a given property.
+      </comment>
+      <value>"$1": illegal value for decimal format property "$2"${: 3}</value>
+      <entry key="MustBeChar">
+        <value>must be a single character</value>
+      </entry>
+      <entry key="MustBeZeroDigit">
+        <value>must be a digit (Unicode category Nd) and represent zero</value>
+      </entry>
+    </diagnostic>
+
     <diagnostic code="XQST0098">
       <comment>
-       It is a static error if, for any named or unnamed decimal format, the
-       properties representing characters used in a picture string do not each
-       have distinct values. These properties are decimal-separator-sign,
-       grouping-separator, percent-sign, per-mille-sign, zero-digit,
-       digit-sign, and pattern-separator-sign.
+        It is a static error if, for any named or unnamed decimal format, the
+        properties representing characters used in a picture string do not each
+        have distinct values. These properties are decimal-separator-sign,
+        grouping-separator, percent-sign, per-mille-sign, zero-digit,
+        digit-sign, and pattern-separator-sign.
       </comment>
-      <value>properties "$1" and "$2", representing characters used in picture string, do not have distinct values</value>
+      <value>"$1": value of properties "$1" and "$2" for characters used a in picture string is the same but must be distinct</value>
     </diagnostic>
 
     <diagnostic code="XQST0099">
@@ -814,9 +823,18 @@
       <value>$1</value>
     </diagnostic>
 
+    <diagnostic code="XQST0114">
+      <comment>
+        It is a static error for a decimal format declaration to define the
+        same property more than once.
+      </comment>
+      <value>"$1": duplicate decimal format property</value>
+    </diagnostic>
+
     <diagnostic code="XQST0123">
       <comment>
-       It is a static error if the name of a feature in require-feature is not recognized by the implementation.
+       It is a static error if the name of a feature in require-feature is not
+       recognized by the implementation.
       </comment>
       <value>$1</value>
     </diagnostic>
@@ -1319,6 +1337,12 @@
         Invalid decimal/integer format picture string.
       </comment>
       <value>"$1": invalid picture string for decimal/integer${: 2}</value>
+      <entry key="NoOptDigitAfterMandatory_3">
+        <value>'$3': optional-digit-sign in integer part of sub-picture may not follow a member of the decimal-digit-family</value>
+      </entry>
+      <entry key="NoMandatoryDigitAfterOpt_3">
+        <value>'$3': member of decimal-digit-family in fractional part of a sub-picture may not follow an optional-digit-sign</value>
+      </entry>
       <entry key="BadCharacter_3">
         <value>'$3': invalid character</value>
       </entry>
@@ -1337,9 +1361,21 @@
       <entry key="EmptyFormat">
         <value>empty primary format</value>
       </entry>
+      <entry key="MultipleSign_3">
+        <value>"$3": multiple such signs are illegal</value>
+      </entry>
+      <entry key="MustHaveOptOrMandatoryDigit">
+        <value>sub-picture must contain at least one optional or mandatory digit</value>
+      </entry>
+      <entry key="NoActivePassiveActive">
+        <value>"$3": active character may not follow passive that follows active</value>
+      </entry>
       <entry key="NoAdjacentGroupSep_3">
         <value>"$3": grouping separator must not be adjacent to others</value>
       </entry>
+      <entry key="NoDecimalGroupingAdjacent_34">
+        <value>decimal-separator-sign ('$3') and grouping-separator-sign ('$4') may not be adjacent</value>
+      </entry>
       <entry key="NoGroupSepAtStart_3">
         <value>"$3": grouping separator illegal at start of decimal-digit-pattern</value>
       </entry>
@@ -1349,6 +1385,9 @@
       <entry key="NoOptDigitAfterMandatory">
         <value>"#": optional-digit-sign must precede all mandatory-digit-signs</value>
       </entry>
+      <entry key="NoPercentPermille">
+        <value>sub-picture must not contain more than one percent-sign or per-mille-sign or one of each</value>
+      </entry>
     </diagnostic>
 
     <diagnostic code="FODT0001">
@@ -4363,30 +4402,6 @@
       <value>a DOCTYPE declaration must appear before any element or text node, and at most once</value>
     </entry>
 
-    <entry key="FormatNumberDuplicates">
-      <value>: a sub-picture must not contain more than one of the "$3" sign</value>
-    </entry>
-
-    <entry key="FormatNumberGroupingAdjacentToDecimal">
-      <value>: a sub-picture must not contain a grouping-separator-sign adjacent to a decimal-separator-sign</value>
-    </entry>
-
-    <entry key="FormatNumberIntegerPart">
-      <value>: the integer part of a sub-picture must not contain a member of the decimal-digit-family that is followed by an optional-digit-sign</value>
-    </entry>
-
-    <entry key="FormatNumberFractionalPart">
-      <value>: the fractional part of a sub-picture must not contain an optional-digit-sign that is followed by a member of the decimal-digit-family</value>
-    </entry>
-
-    <entry key="FormatNumberPercentPermille">
-      <value>: a sub-picture must not contain more than one percent-sign or per-mille-sign, and it must not contain one of each</value>
-    </entry>
-
-    <entry key="FormatNumberAtLeastOneOptionalOrDecimal">
-      <value>: a sub-picture must contain at least one character that is an optional-digit-sign or a member of the decimal-digit-family</value>
-    </entry>
-
     <entry key="FUNCTION">
       <value>function</value>
     </entry>

=== modified file 'src/diagnostics/pregenerated/diagnostic_list.cpp'
--- src/diagnostics/pregenerated/diagnostic_list.cpp	2013-04-02 21:46:10 +0000
+++ src/diagnostics/pregenerated/diagnostic_list.cpp	2013-04-11 00:34:24 +0000
@@ -205,6 +205,9 @@
 XQueryErrorCode XQST0094( "XQST0094" );
 
 
+XQueryErrorCode XQST0097( "XQST0097" );
+
+
 XQueryErrorCode XQST0098( "XQST0098" );
 
 
@@ -220,6 +223,9 @@
 XQueryErrorCode XQST0111( "XQST0111" );
 
 
+XQueryErrorCode XQST0114( "XQST0114" );
+
+
 XQueryErrorCode XQST0123( "XQST0123" );
 
 

=== modified file 'src/diagnostics/pregenerated/dict_en.cpp'
--- src/diagnostics/pregenerated/dict_en.cpp	2013-04-08 22:59:58 +0000
+++ src/diagnostics/pregenerated/dict_en.cpp	2013-04-11 00:34:24 +0000
@@ -255,11 +255,13 @@
   { "XQST0090", "\"$1\": invalid character reference in XML $2" },
   { "XQST0093", "\"$1\": module must not depend on itself" },
   { "XQST0094", "\"$1\": grouping variable not defined in the same flwor expression as the group-by clause" },
-  { "XQST0098", "properties \"$1\" and \"$2\", representing characters used in picture string, do not have distinct values" },
+  { "XQST0097", "\"$1\": illegal value for decimal format property \"$2\"${: 3}" },
+  { "XQST0098", "\"$1\": value of properties \"$1\" and \"$2\" for characters used a in picture string is the same but must be distinct" },
   { "XQST0099", "module contains more than one context item declaration" },
   { "XQST0103", "$1: non-distinct variable in window clause" },
   { "XQST0106", "$1: multiple annotations with $2 names" },
   { "XQST0111", "$1" },
+  { "XQST0114", "\"$1\": duplicate decimal format property" },
   { "XQST0123", "$1" },
   { "XQTY0024", "element constructor content sequence must not have an attribute node following a non-attribute node" },
   { "XQTY0030", "validate argument must be exactly one document or element node" },
@@ -623,10 +625,17 @@
   { "~FODF1310_DigitNotSameFamily_34", "\"$3\": digit not from same digit family as $4" },
   { "~FODF1310_DupFormatModifier_3", "\"$3\": duplicate format modifier" },
   { "~FODF1310_EmptyFormat", "empty primary format" },
+  { "~FODF1310_MultipleSign_3", "\"$3\": multiple such signs are illegal" },
+  { "~FODF1310_MustHaveOptOrMandatoryDigit", "sub-picture must contain at least one optional or mandatory digit" },
+  { "~FODF1310_NoActivePassiveActive", "\"$3\": active character may not follow passive that follows active" },
   { "~FODF1310_NoAdjacentGroupSep_3", "\"$3\": grouping separator must not be adjacent to others" },
+  { "~FODF1310_NoDecimalGroupingAdjacent_34", "decimal-separator-sign ('$3') and grouping-separator-sign ('$4') may not be adjacent" },
   { "~FODF1310_NoGroupSepAtEnd_3", "\"$3\": grouping separator illegal at end of decimal-digit-pattern" },
   { "~FODF1310_NoGroupSepAtStart_3", "\"$3\": grouping separator illegal at start of decimal-digit-pattern" },
+  { "~FODF1310_NoMandatoryDigitAfterOpt_3", "'$3': member of decimal-digit-family in fractional part of a sub-picture may not follow an optional-digit-sign" },
   { "~FODF1310_NoOptDigitAfterMandatory", "\"#\": optional-digit-sign must precede all mandatory-digit-signs" },
+  { "~FODF1310_NoOptDigitAfterMandatory_3", "'$3': optional-digit-sign in integer part of sub-picture may not follow a member of the decimal-digit-family" },
+  { "~FODF1310_NoPercentPermille", "sub-picture must not contain more than one percent-sign or per-mille-sign or one of each" },
   { "~FOFD1340_Bad2ndModifierHere_3", "'$3': valid second presentation modifier invalid here" },
   { "~FOFD1340_Bad2ndModifier_3", "'$3': invalid second presentation modifier" },
   { "~FOFD1340_BadComponent_3", "'$3': invalid component specifier" },
@@ -659,12 +668,6 @@
   { "~FileNotFoundOrReadable", "file not found or readable" },
   { "~FnNilledArgNotNode", "fn:nilled() argument not a node" },
   { "~FnOnlyInXQueryVersion_3", "function only available in XQuery $3" },
-  { "~FormatNumberAtLeastOneOptionalOrDecimal", ": a sub-picture must contain at least one character that is an optional-digit-sign or a member of the decimal-digit-family" },
-  { "~FormatNumberDuplicates", ": a sub-picture must not contain more than one of the \"$3\" sign" },
-  { "~FormatNumberFractionalPart", ": the fractional part of a sub-picture must not contain an optional-digit-sign that is followed by a member of the decimal-digit-family" },
-  { "~FormatNumberGroupingAdjacentToDecimal", ": a sub-picture must not contain a grouping-separator-sign adjacent to a decimal-separator-sign" },
-  { "~FormatNumberIntegerPart", ": the integer part of a sub-picture must not contain a member of the decimal-digit-family that is followed by an optional-digit-sign" },
-  { "~FormatNumberPercentPermille", ": a sub-picture must not contain more than one percent-sign or per-mille-sign, and it must not contain one of each" },
   { "~FullTextNotEnabled", "full-text was not enabled in this build" },
   { "~FunctionFailedErrorCodeMessage_234", "$2 failed (error $3): $4" },
   { "~FunctionFailed_23o", "$2 failed${: 3}" },
@@ -952,7 +955,6 @@
   { "~XPST0008_VariableName_2", "\"$2\": undeclared variable" },
   { "~XPST0051_Atomic_2", "\"$2\": not defined an atomic type" },
   { "~XPST0051_GenAtomic_2", "\"$2\": not defined a generalized atomic type" },
-  { "~XPTY0004_FormatNumber_2", "first parameter to format-number() function is type $2 that is not allowed" },
   { "~XPTY0004_JSONIQ_SELECTOR", "can not atomize and/or cast value of type $2 to string" },
   { "~XPTY0004_MultiValuedGroupingKey", "atomization of grouping variable produces more than one item" },
   { "~XPTY0004_NoMultiSeqTypePromotion_2", "sequence of more than one item can not be promoted to type $2" },
@@ -970,6 +972,8 @@
   { "~XQST0046_BadHexDigit_3", "'$3': invalid hexedecimal digit" },
   { "~XQST0059_SpecificationMessage", "\"$2\": target namespace not found for schema/module${ \"3\"}${: 4}" },
   { "~XQST0059_XercesMessage", "$2,$3: error in schema${ with System ID \"4\"}${ with Public ID \"5\"}${: 6}" },
+  { "~XQST0097_MustBeChar", "must be a single character" },
+  { "~XQST0097_MustBeZeroDigit", "must be a digit (Unicode category Nd) and represent zero" },
   { "~XQST0106_CONFLICTING", "conflicting" },
   { "~XQST0106_THE_SAME", "the same" },
   { "~XUDY0021_AttributeName", "\"$3\": attribute with the same name already exists" },

=== modified file 'src/diagnostics/pregenerated/dict_zed_keys.h'
--- src/diagnostics/pregenerated/dict_zed_keys.h	2013-04-08 22:59:58 +0000
+++ src/diagnostics/pregenerated/dict_zed_keys.h	2013-04-11 00:34:24 +0000
@@ -45,7 +45,6 @@
 #define ZED_XPTY0004_NoTypePromote_23 "~XPTY0004_NoTypePromote_23"
 #define ZED_XPTY0004_NoMultiSeqTypePromotion_2 "~XPTY0004_NoMultiSeqTypePromotion_2"
 #define ZED_XPTY0004_NoTreatAs_23 "~XPTY0004_NoTreatAs_23"
-#define ZED_XPTY0004_FormatNumber_2 "~XPTY0004_FormatNumber_2"
 #define ZED_XPTY0004_JSONIQ_SELECTOR "~XPTY0004_JSONIQ_SELECTOR"
 #define ZED_XPTY0004_MultiValuedGroupingKey "~XPTY0004_MultiValuedGroupingKey"
 #define ZED_XPTY0117_NodeCast "~XPTY0117_NodeCast"
@@ -53,6 +52,8 @@
 #define ZED_XQST0046_BadHexDigit_3 "~XQST0046_BadHexDigit_3"
 #define ZED_XQST0059_SpecificationMessage "~XQST0059_SpecificationMessage"
 #define ZED_XQST0059_XercesMessage "~XQST0059_XercesMessage"
+#define ZED_XQST0097_MustBeChar "~XQST0097_MustBeChar"
+#define ZED_XQST0097_MustBeZeroDigit "~XQST0097_MustBeZeroDigit"
 #define ZED_XQST0106_THE_SAME "~XQST0106_THE_SAME"
 #define ZED_XQST0106_CONFLICTING "~XQST0106_CONFLICTING"
 #define ZED_XPDY0002_VariableHasNoValue_2 "~XPDY0002_VariableHasNoValue_2"
@@ -83,16 +84,23 @@
 #define ZED_FOCA0002_BadLexicalQName_2 "~FOCA0002_BadLexicalQName_2"
 #define ZED_FOCA0002_NoURIforPrefix_2 "~FOCA0002_NoURIforPrefix_2"
 #define ZED_FOCA0002_NoCastTo_234 "~FOCA0002_NoCastTo_234"
+#define ZED_FODF1310_NoOptDigitAfterMandatory_3 "~FODF1310_NoOptDigitAfterMandatory_3"
+#define ZED_FODF1310_NoMandatoryDigitAfterOpt_3 "~FODF1310_NoMandatoryDigitAfterOpt_3"
 #define ZED_FODF1310_BadCharacter_3 "~FODF1310_BadCharacter_3"
 #define ZED_FODF1310_BadFormatModifier_3 "~FODF1310_BadFormatModifier_3"
 #define ZED_FODF1310_BadFormatModifierHere_3 "~FODF1310_BadFormatModifierHere_3"
 #define ZED_FODF1310_DigitNotSameFamily_34 "~FODF1310_DigitNotSameFamily_34"
 #define ZED_FODF1310_DupFormatModifier_3 "~FODF1310_DupFormatModifier_3"
 #define ZED_FODF1310_EmptyFormat "~FODF1310_EmptyFormat"
+#define ZED_FODF1310_MultipleSign_3 "~FODF1310_MultipleSign_3"
+#define ZED_FODF1310_MustHaveOptOrMandatoryDigit "~FODF1310_MustHaveOptOrMandatoryDigit"
+#define ZED_FODF1310_NoActivePassiveActive "~FODF1310_NoActivePassiveActive"
 #define ZED_FODF1310_NoAdjacentGroupSep_3 "~FODF1310_NoAdjacentGroupSep_3"
+#define ZED_FODF1310_NoDecimalGroupingAdjacent_34 "~FODF1310_NoDecimalGroupingAdjacent_34"
 #define ZED_FODF1310_NoGroupSepAtStart_3 "~FODF1310_NoGroupSepAtStart_3"
 #define ZED_FODF1310_NoGroupSepAtEnd_3 "~FODF1310_NoGroupSepAtEnd_3"
 #define ZED_FODF1310_NoOptDigitAfterMandatory "~FODF1310_NoOptDigitAfterMandatory"
+#define ZED_FODF1310_NoPercentPermille "~FODF1310_NoPercentPermille"
 #define ZED_FORG0001_BadHexDigit_2 "~FORG0001_BadHexDigit_2"
 #define ZED_FORG0001_Base64BadChar_2 "~FORG0001_Base64BadChar_2"
 #define ZED_FORG0001_Base64Multiple4 "~FORG0001_Base64Multiple4"
@@ -363,12 +371,6 @@
 #define ZED_ParseFragmentInvalidOptions "~ParseFragmentInvalidOptions"
 #define ZED_ParseFragmentDoctypeNotAllowed "~ParseFragmentDoctypeNotAllowed"
 #define ZED_ParseFragmentDoctypeNotAllowedHere "~ParseFragmentDoctypeNotAllowedHere"
-#define ZED_FormatNumberDuplicates "~FormatNumberDuplicates"
-#define ZED_FormatNumberGroupingAdjacentToDecimal "~FormatNumberGroupingAdjacentToDecimal"
-#define ZED_FormatNumberIntegerPart "~FormatNumberIntegerPart"
-#define ZED_FormatNumberFractionalPart "~FormatNumberFractionalPart"
-#define ZED_FormatNumberPercentPermille "~FormatNumberPercentPermille"
-#define ZED_FormatNumberAtLeastOneOptionalOrDecimal "~FormatNumberAtLeastOneOptionalOrDecimal"
 #define ZED_FUNCTION "~FUNCTION"
 #define ZED_ANNOTATION "~ANNOTATION"
 #define ZED_libxml_ERR_1 "~libxml_ERR_1"

=== modified file 'src/runtime/CMakeLists.txt'
--- src/runtime/CMakeLists.txt	2013-03-28 20:00:55 +0000
+++ src/runtime/CMakeLists.txt	2013-04-11 00:34:24 +0000
@@ -133,6 +133,7 @@
   json/snelson.cpp
   numerics/NumericsImpl.cpp
   numerics/format_integer.cpp
+  numerics/format_number.cpp
   sequences/SequencesImpl.cpp
   visitors/iterprinter.cpp
   update/update.cpp

=== modified file 'src/runtime/numerics/format_integer.cpp'
--- src/runtime/numerics/format_integer.cpp	2013-04-07 17:56:27 +0000
+++ src/runtime/numerics/format_integer.cpp	2013-04-11 00:34:24 +0000
@@ -43,6 +43,8 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+namespace {
+
 struct picture {
   enum primary_type {
     arabic,       // '1' : 0 1 2 ... 10 11 12 ...
@@ -105,6 +107,8 @@
   // default picture& operator=(picture const&) is fine
 };
 
+} // namespace
+
 ///////////////////////////////////////////////////////////////////////////////
 
 /**
@@ -246,7 +250,8 @@
           } else {                      // must be a grouping-separator
             grouping_cp = pic_cp;       // remember for later
             u_dest.insert( 0, 1, grouping_cp );
-            --mandatory_grouping_seps;
+            if ( mandatory_grouping_seps )
+              --mandatory_grouping_seps;
           }
         } else {                        // have exhausted the picture
           if ( pic.primary.grouping_interval &&
@@ -361,7 +366,7 @@
                            QueryLoc const &loc ) {
   if ( picture_str.empty() ) {
     //
-    // XQuery 3.0 F&O: 4.6.1: The primary format token is always present and
+    // XQuery 3.0 F&O 4.6.1: The primary format token is always present and
     // must not be zero-length.
     //
 empty_format:
@@ -443,8 +448,8 @@
   if ( is_decimal_digit_pattern ) {
     if ( cp != '#' && unicode::is_grouping_separator( cp ) ) {
       //
-      // Ibid: 4.6.1: A grouping-separator-sign must not appear at the start
-      // ... of the decimal-digit-pattern ....
+      // Ibid 4.6.1: A grouping-separator-sign must not appear at the start ...
+      // of the decimal-digit-pattern ....
       //
       throw XQUERY_EXCEPTION(
         err::FODF1310,
@@ -809,9 +814,9 @@
 
     if ( !lang ) {
       //
-      // XQuery 3.0 F&O: 4.6.1: If the $lang argument is absent, or is set to
-      // an empty sequence, or is invalid, or is not a language supported by
-      // the implementation, then the number is formatted using the default
+      // XQuery 3.0 F&O 4.6.1: If the $lang argument is absent, or is set to an
+      // empty sequence, or is invalid, or is not a language supported by the
+      // implementation, then the number is formatted using the default
       // language from the dynamic context.
       //
       planState.theLocalDynCtx->get_locale( &lang, &country );

=== added file 'src/runtime/numerics/format_number.cpp'
--- src/runtime/numerics/format_number.cpp	1970-01-01 00:00:00 +0000
+++ src/runtime/numerics/format_number.cpp	2013-04-11 00:34:24 +0000
@@ -0,0 +1,848 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "stdafx.h"
+
+#include <vector>
+
+#include "common/shared_types.h"
+#include "compiler/api/compilercb.h"
+#include "context/static_context.h"
+#include "diagnostics/xquery_diagnostics.h"
+#include "runtime/core/arithmetic_impl.h"
+#include "runtime/numerics/numerics.h"
+#include "runtime/visitors/planiter_visitor.h"
+#include "store/api/item.h"
+#include "store/api/item_factory.h"
+#include "system/globalenv.h"
+#include "types/casting.h"
+#include "types/typeconstants.h"
+#include "types/typeops.h"
+#include "util/xml_util.h"
+#include "zorbatypes/zorbatypes_decl.h"
+
+namespace zorba {
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace {
+
+struct picture {
+
+  struct part {
+    zstring format;
+    int mandatory_grouping_seps;
+    int minimum_size;
+    union {
+      int grouping_interval;            // only in integer part
+      int maximum_size;                 // only in fractional part
+    };
+
+    part() {
+      mandatory_grouping_seps = minimum_size = maximum_size = 0;
+    }
+  };
+
+  struct sub_picture {
+    zstring format;
+    zstring prefix, suffix;
+    bool has_decimal_separator;
+    bool has_percent;
+    bool has_per_mille;
+    part integer_part, fractional_part;
+
+    sub_picture() {
+      has_decimal_separator = has_percent = has_per_mille = false;
+    }
+  };
+
+  zstring format;                       // original $picture
+  sub_picture pos_subpicture, neg_subpicture;
+
+  // See XQuery F&O 3.0 4.7.1.
+  enum var_type {
+    decimal_separator_sign,
+    grouping_separator_sign,
+    infinity,
+    mandatory_digit_sign,
+    minus_sign,
+    NaN,
+    optional_digit_sign,
+    pattern_separator_sign,
+    percent_sign,
+    per_mille_sign,
+    NUM_VARS
+  };
+
+  zstring var[ NUM_VARS ];
+  unicode::code_point var_cp[ NUM_VARS ];
+
+  picture() {
+    var[ decimal_separator_sign ] = ".";
+    var[ grouping_separator_sign ] = ",";
+    var[ infinity ] = "Infinity";
+    var[ mandatory_digit_sign ] = "0";
+    var[ minus_sign ] = "-";
+    var[ NaN ] = "NaN";
+    var[ optional_digit_sign ] = "#";
+    var[ pattern_separator_sign ] = ";";
+    var[ percent_sign ] = "%";
+    var[ per_mille_sign ] = "\xE2\x80\xB0";
+    set_format_codepoints();
+  }
+
+  // default picture(picture const&) is fine
+  // default picture& operator=(picture const&) is fine
+
+  void set_format_codepoints() {
+    for ( int i = 0; i < NUM_VARS; ++i )
+      var_cp[i] = utf8::decode( var[i].c_str() );
+  }
+};
+
+} // namespace
+
+#define VAR(NAME) var[ ::zorba::picture::NAME ]
+#define VAR_CP(NAME) var_cp[ ::zorba::picture::NAME ]
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void check_multiple( zstring const &sub_pic, zstring const &sign,
+                            picture const &pic, QueryLoc const &loc ) {
+  zstring::size_type const pos = sub_pic.find( sign );
+  if ( pos != zstring::npos &&
+       sub_pic.find( sign, pos + sign.size() ) != zstring::npos ) {
+    throw XQUERY_EXCEPTION(
+      err::FODF1310,
+      ERROR_PARAMS( pic.format, ZED( FODF1310_MultipleSign_3 ), sign ),
+      ERROR_LOC( loc )
+    );
+  }
+}
+
+static void format_integer_part( zstring const &value,
+                                 picture::sub_picture const &sub_pic,
+                                 picture const &pic, zstring *dest ) {
+  zstring::const_reverse_iterator n_i( value.rbegin() );
+  zstring::const_reverse_iterator const n_end( value.rend() );
+
+  picture::part const &part = sub_pic.integer_part;
+
+  utf8_string<zstring const> const u_format( part.format );
+  utf8_string<zstring const>::const_reverse_iterator
+    format_i( u_format.rbegin() );
+  utf8_string<zstring const>::const_reverse_iterator const
+    format_end( u_format.rend() );
+
+  int digit_pos = 0;
+  bool just_inserted_grouping_separator = false;
+  int minimum_size = part.minimum_size;
+  int mandatory_grouping_seps = part.mandatory_grouping_seps;
+  utf8_string<zstring> u_dest( *dest );
+
+  //
+  // Step through both the integer part and sub-picture from right-to-left.
+  //
+  while ( n_i != n_end || format_i != format_end ) {
+    unicode::code_point digit_cp = pic.VAR_CP( mandatory_digit_sign );
+    if ( n_i != n_end )
+      digit_cp += *n_i - '0';
+    if ( format_i != format_end ) {     // haven't exhausted the picture
+      if ( !minimum_size && !mandatory_grouping_seps && n_i == n_end )
+        break;
+      unicode::code_point const format_cp = *format_i++;
+      if ( format_cp == pic.VAR_CP( optional_digit_sign ) ||
+           unicode::is_Nd( format_cp ) ) {
+        u_dest.insert( 0, 1, digit_cp );
+        if ( n_i != n_end ) ++n_i;
+        ++digit_pos;
+        just_inserted_grouping_separator = false;
+        if ( minimum_size )
+          --minimum_size;
+      } else {                          // must be a grouping-separator
+        u_dest.insert( 0, 1, pic.VAR_CP( grouping_separator_sign ) );
+        just_inserted_grouping_separator = true;
+        if ( mandatory_grouping_seps )
+          --mandatory_grouping_seps;
+      }
+    } else {                            // have exhausted the picture
+      if ( part.grouping_interval && !(digit_pos % part.grouping_interval) ) {
+        if ( just_inserted_grouping_separator )
+          just_inserted_grouping_separator = false;
+        else {
+          u_dest.insert( 0, 1, pic.VAR_CP( grouping_separator_sign ) );
+          just_inserted_grouping_separator = true;
+          continue;
+        }
+      }
+      u_dest.insert( 0, 1, digit_cp );
+      if ( n_i != n_end ) ++n_i;
+      ++digit_pos;
+    }
+  } // while
+}
+
+static void format_fractional_part( zstring const &value,
+                                    picture::sub_picture const &sub_pic,
+                                    picture const &pic, zstring *dest ) {
+  zstring::const_iterator n_i( value.begin() );
+  zstring::const_iterator const n_end( value.end() );
+
+  picture::part const &part = sub_pic.fractional_part;
+
+  utf8_string<zstring const> const u_format( part.format );
+  utf8_string<zstring const>::const_iterator format_i( u_format.begin() );
+  utf8_string<zstring const>::const_iterator const format_end( u_format.end() );
+
+  int minumum_size = part.minimum_size;
+  int mandatory_grouping_seps = part.mandatory_grouping_seps;
+  utf8_string<zstring> u_dest( *dest );
+
+  //
+  // Step through both the fractional part and sub-picture from left-to-right.
+  //
+  while ( n_i != n_end || format_i != format_end ) {
+    unicode::code_point digit_cp = pic.VAR_CP( mandatory_digit_sign );
+    if ( n_i != n_end )
+      digit_cp += *n_i - '0';
+    if ( format_i != format_end ) {     // haven't exhausted the picture
+      if ( !minumum_size && !mandatory_grouping_seps && n_i == n_end )
+        break;
+      unicode::code_point const format_cp = *format_i++;
+      if ( format_cp == pic.VAR_CP( optional_digit_sign ) ||
+           unicode::is_Nd( format_cp ) ) {
+        u_dest += digit_cp;
+        if ( n_i != n_end ) ++n_i;
+        if ( minumum_size )
+          --minumum_size;
+      } else {                          // must be a grouping-separator
+        u_dest += pic.VAR_CP( grouping_separator_sign );
+        if ( mandatory_grouping_seps )
+          --mandatory_grouping_seps;
+      }
+    } else {                            // have exhausted the picture
+      u_dest += digit_cp;
+      if ( n_i != n_end ) ++n_i;
+    }
+  } // while
+}
+
+static void format_number( store::Item_t &number_item, picture const &pic,
+                           TypeManager const *tm, QueryLoc const &loc,
+                           zstring *dest ) {
+  if ( number_item->isNaN() ) {
+    //
+    // XQuery F&O 3.0 4.7.5: If the input number is NaN (not a number), the
+    // result is the specified NaN-symbol (with no prefix or suffix).
+    //
+    *dest = pic.VAR( NaN );
+    return;
+  }
+
+  store::Item_t double_item;
+  GenericCast::castToAtomic(
+    double_item, number_item, &*GENV_TYPESYSTEM.DOUBLE_TYPE_ONE, tm, nullptr,
+    loc
+  );
+
+  store::Item_t zero;
+  GENV_ITEMFACTORY->createDouble( zero, xs_double::zero() );
+
+  //
+  // Ibid: [T]he positive sub-picture and its associated variables are used if
+  // the input number is positive, and the negative sub-picture and its
+  // associated variables are used otherwise.
+  //
+  bool const is_negative = double_item->compare( zero ) < 0;
+  picture::sub_picture const &sub_pic =
+    is_negative ? pic.neg_subpicture : pic.pos_subpicture;
+
+  if ( double_item->isPosOrNegInf() ) {
+    //
+    // Ibid: If the input number is positive or negative infinity, the result
+    // is the concatenation of the appropriate prefix, the infinity-symbol, and
+    // the appropriate suffix.
+    //
+    *dest  = sub_pic.prefix;
+    *dest += pic.VAR( infinity );
+    *dest += sub_pic.suffix;
+    return;
+  }
+
+  //
+  // Ibid: If the sub-picture contains a percent-sign, the number is multiplied
+  // by 100. If the sub-picture contains a per-mille-sign, the number is
+  // multiplied by 1000. The resulting number is referred to ... as the
+  // adjusted number.
+  //
+  xs_double adjusted_number( double_item->getDoubleValue().abs() );
+  if ( sub_pic.has_percent )
+    adjusted_number *= 100;
+  else if ( sub_pic.has_per_mille )
+    adjusted_number *= 1000;
+
+  //
+  // Ibid: This value is then rounded so that it uses no more than maximum-
+  // fractional-part-size digits in its fractional part. The rounded number is
+  // defined to be the result of converting the adjusted number to an
+  // xs:decimal value, as described above, and then calling the function
+  // fn:round-half-to-even with this converted number as the first argument and
+  // the maximum-fractional-part-size as the second argument.
+  //
+  adjusted_number = adjusted_number.roundHalfToEven(
+    xs_integer( sub_pic.fractional_part.maximum_size )
+  );
+
+  //
+  // Ibid: If the number of digits to the left of the decimal-separator-sign is
+  // less than minimum-integer-part-size, leading zero-digit-sign characters
+  // are added to pad out to that size.
+  //
+  // Ibid: If the number of digits to the right of the decimal-separator-sign
+  // is less than minimum-fractional-part-size, trailing zero-digit-sign
+  // characters are added to pad out to that size.
+  //
+  zstring const number_str( adjusted_number.toString( true ) );
+  zstring::size_type const decimal_separator_pos = number_str.find( '.' );
+  zstring integer_str, fractional_str;
+  integer_str = number_str.substr( 0, decimal_separator_pos );
+  ascii::left_pad( &integer_str, sub_pic.integer_part.minimum_size, '0' );
+  if ( decimal_separator_pos != zstring::npos )
+    fractional_str = number_str.substr( decimal_separator_pos + 1 );
+  ascii::right_pad(
+    &fractional_str, sub_pic.fractional_part.minimum_size, '0'
+  );
+
+  format_integer_part( integer_str, sub_pic, pic, dest );
+  // Insert prefix afterwards so as not to complicate format_integer_part().
+  dest->insert( 0, sub_pic.prefix );
+
+  if ( sub_pic.has_decimal_separator && !fractional_str.empty() ) {
+    *dest += pic.VAR( decimal_separator_sign );
+    format_fractional_part( fractional_str, sub_pic, pic, dest );
+  }
+  *dest += sub_pic.suffix;
+}
+
+static bool is_allowed_type( store::Item const *type_qname ) {
+  RootTypeManager const &rtm = GENV_TYPESYSTEM;
+  return type_qname->equals( rtm.XS_FLOAT_QNAME )
+      || type_qname->equals( rtm.XS_DOUBLE_QNAME )
+      || type_qname->equals( rtm.XS_DECIMAL_QNAME )
+      || type_qname->equals( rtm.XS_INTEGER_QNAME )
+      || type_qname->equals( rtm.XS_INT_QNAME )
+      || type_qname->equals( rtm.XS_LONG_QNAME )
+      || type_qname->equals( rtm.XS_SHORT_QNAME )
+      || type_qname->equals( rtm.XS_BYTE_QNAME )
+      || type_qname->equals( rtm.XS_NON_NEGATIVE_INTEGER_QNAME )
+      || type_qname->equals( rtm.XS_NON_POSITIVE_INTEGER_QNAME )
+      || type_qname->equals( rtm.XS_NEGATIVE_INTEGER_QNAME )
+      || type_qname->equals( rtm.XS_POSITIVE_INTEGER_QNAME )
+      || type_qname->equals( rtm.XS_UNSIGNED_INT_QNAME )
+      || type_qname->equals( rtm.XS_UNSIGNED_LONG_QNAME )
+      || type_qname->equals( rtm.XS_UNSIGNED_SHORT_QNAME )
+      || type_qname->equals( rtm.XS_UNSIGNED_BYTE_QNAME );
+}
+
+static void parse_subpicture( picture::sub_picture *sub_pic,
+                              picture const &pic, QueryLoc const &loc ) {
+  if ( sub_pic->format.empty() )
+    return;
+
+  picture::part picture::sub_picture::*cur_part =
+    &picture::sub_picture::integer_part;
+
+  bool got_active = false;
+  bool got_grouping_separator = false;    // used only for integer part
+  bool got_mandatory_digit = false;
+  bool got_optional_digit = false;
+  bool got_part_mandatory_digit = false;
+  bool got_part_optional_digit = false;
+  bool got_passive_after_active = false;
+  bool grouping_interval_possible = true; // used only for integer part
+  bool just_got_decimal_separator = false;
+  bool just_got_grouping_separator = false;
+
+  int grouping_interval = 0;              // used only for integer part
+  int grouping_separators = 0;
+
+  utf8::size_type decimal_separator_pos = utf8::npos;
+  utf8::size_type leftmost_active_pos = utf8::npos;
+  utf8::size_type rightmost_active_pos = utf8::npos;
+  utf8::size_type pos = 0;
+  utf8::size_type prev_grouping_pos = utf8::npos;
+
+  unicode::code_point cp, zero_cp;
+
+  utf8_string<zstring> u_format( sub_pic->format );
+  utf8_string<zstring>::const_iterator u( u_format.begin() );
+  utf8_string<zstring>::const_iterator const u_end( u_format.end() );
+
+  for ( ; u != u_end; ++u, ++pos ) {
+    cp = *u;
+
+    if ( cp == pic.VAR_CP( decimal_separator_sign ) ) {
+      if ( decimal_separator_pos != utf8::npos ) {
+        //
+        // XQuery F&O 3.0 4.7.3: A sub-picture must not contain more than one
+        // decimal-separator-sign.
+        //
+        goto got_multiple_signs;
+      }
+      if ( just_got_grouping_separator ) {
+        //
+        // Ibid: A sub-picture must not contain a grouping-separator-sign
+        // adjacent to a decimal-separator-sign.
+        //
+        goto got_decimal_grouping_adjacent;
+      }
+      cur_part = &picture::sub_picture::fractional_part;
+      decimal_separator_pos = pos;
+      got_part_mandatory_digit = got_part_optional_digit = false;
+      just_got_decimal_separator = true;
+      just_got_grouping_separator = false;
+      sub_pic->has_decimal_separator = true;
+      goto set_active;
+    }
+
+    if ( cp == pic.VAR_CP( grouping_separator_sign ) ) {
+      if ( just_got_decimal_separator ) {
+        //
+        // Ibid: A sub-picture must not contain a grouping-separator-sign
+        // adjacent to a decimal-separator-sign.
+        //
+        goto got_decimal_grouping_adjacent;
+      }
+      just_got_decimal_separator = false;
+      just_got_grouping_separator = true;
+      ++grouping_separators;
+
+      if ( decimal_separator_pos == utf8::npos &&
+           grouping_interval_possible ) {
+        //
+        // [I]f these integer-part-grouping-positions are at regular intervals
+        // (that is, if they form a sequence N, 2N, 3N, ... for some integer
+        // value N, including the case where there is only one number in the
+        // list), then the sequence contains all integer multiples of N as far
+        // as necessary to accommodate the largest possible number.
+        //
+        if ( !got_grouping_separator )
+          got_grouping_separator = true;
+        else if ( !grouping_interval )
+          grouping_interval = pos - prev_grouping_pos;
+        else if ( pos - prev_grouping_pos != grouping_interval )
+          grouping_interval_possible = false;
+        prev_grouping_pos = pos + 1;
+      }
+
+      goto set_active;
+    }
+
+    just_got_decimal_separator = just_got_grouping_separator = false;
+
+    if ( cp == pic.VAR_CP( optional_digit_sign ) ) {
+      if ( decimal_separator_pos != utf8::npos ) {
+        //
+        // Ibid 4.7.4: The maximum-fractional-part-size is set to the total
+        // number of optional-digit-sign and decimal-digit-family characters
+        // found in the fractional part of the sub-picture.
+        //
+        ++sub_pic->fractional_part.maximum_size;
+      } else if ( got_part_mandatory_digit ) {
+        //
+        // Ibid 4.7.3: The integer part of a sub-picture must not contain a
+        // member of the decimal-digit-family that is followed by an optional-
+        // digit-sign.
+        //
+        throw XQUERY_EXCEPTION(
+          err::FODF1310,
+          ERROR_PARAMS(
+            pic.format,
+            ZED( FODF1310_NoOptDigitAfterMandatory_3 ),
+            unicode::printable_cp( cp )
+          ),
+          ERROR_LOC( loc )
+        );
+      }
+      got_optional_digit = got_part_optional_digit = true;
+      goto set_active;
+    }
+
+    if ( cp == pic.VAR_CP( percent_sign ) ) {
+      //
+      // Ibid 4.7.3: A sub-picture must not contain more than one percent-sign
+      // or per-mille-sign, and it must not contain one of each.
+      //
+      if ( sub_pic->has_percent )
+        goto got_multiple_signs;
+      if ( sub_pic->has_per_mille )
+        goto got_percent_per_mille;
+      sub_pic->has_percent = true;
+    }
+
+    else if ( cp == pic.VAR_CP( per_mille_sign ) ) {
+      //
+      // Ibid: A sub-picture must not contain more than one percent-sign or
+      // per-mille-sign, and it must not contain one of each.
+      //
+      if ( sub_pic->has_per_mille )
+        goto got_multiple_signs;
+      if ( sub_pic->has_percent )
+        goto got_percent_per_mille;
+      sub_pic->has_per_mille = true;
+    }
+
+    else if ( unicode::is_Nd( cp, &zero_cp ) &&
+              zero_cp == pic.VAR_CP( mandatory_digit_sign ) ) {
+      if ( decimal_separator_pos != utf8::npos ) {
+        if ( got_part_optional_digit ) {
+          //
+          // Ibid: The fractional part of a sub-picture must not contain an
+          // optional-digit-sign that is followed by a member of the decimal-
+          // digit-family.
+          //
+          throw XQUERY_EXCEPTION(
+            err::FODF1310,
+            ERROR_PARAMS(
+              pic.format,
+              ZED( FODF1310_NoMandatoryDigitAfterOpt_3 ),
+              unicode::printable_cp( cp )
+            ),
+            ERROR_LOC( loc )
+          );
+        }
+        //
+        // Ibid 4.7.4: The maximum-fractional-part-size is set to the total
+        // number of optional-digit-sign and decimal-digit-family characters
+        // found in the fractional part of the sub-picture.
+        //
+        ++sub_pic->fractional_part.maximum_size;
+      }
+      got_mandatory_digit = got_part_mandatory_digit = true;
+
+      //
+      // Ibid 4.7.4: The minimum-integer-part-size is an integer indicating the
+      // minimum number of digits that will appear to the left of the decimal-
+      // separator-sign. It is normally set to the number of decimal-digit-
+      // family characters found in the integer part of the sub-picture.
+      //
+      // Ibid: The minimum-fractional-part-size is set to the number of
+      // decimal-digit-family characters found in the fractional part of the
+      // sub-picture.
+      //
+      ++(sub_pic->*cur_part).minimum_size;
+
+      goto set_active;
+    }
+
+    if ( got_active )
+      got_passive_after_active = true;
+    continue;
+
+set_active:
+    //
+    // XQuery F&O 3.0 4.7.3: The ... variables decimal-separator-sign,
+    // grouping-sign, decimal-digit-family, optional-digit-sign and pattern-
+    // separator-sign are classified as active characters, and all other
+    // characters (including the percent-sign and per-mille-sign) are
+    // classified as passive characters.
+    //
+    if ( got_passive_after_active && got_active ) {
+      //
+      // Ibid 4.7.3: A sub-picture must not contain a passive character that is
+      // preceded by an active character and that is followed by another active
+      // character.
+      //
+      // In other words, you can't have active-passive-active.
+      //
+      throw XQUERY_EXCEPTION(
+        err::FODF1310,
+        ERROR_PARAMS(
+          pic.format,
+          ZED( FODF1310_NoActivePassiveActive ),
+          unicode::printable_cp( cp )
+        ),
+        ERROR_LOC( loc )
+      );
+    }
+    got_active = true;
+
+    if ( leftmost_active_pos == utf8::npos )
+      leftmost_active_pos = pos;
+    //if ( decimal_separator_pos != utf8::npos )
+      rightmost_active_pos = pos;
+  } // for
+
+  if ( !(got_optional_digit || got_mandatory_digit) ) {
+    throw XQUERY_EXCEPTION(
+      //
+      // Ibid: A sub-picture must contain at least one character that is an
+      // optional-digit-sign or a member of the decimal-digit-family.
+      //
+      err::FODF1310,
+      ERROR_PARAMS( ZED( FODF1310_MustHaveOptOrMandatoryDigit ) ),
+      ERROR_LOC( loc )
+    );
+  }
+
+  if ( grouping_interval_possible ) {
+    if ( decimal_separator_pos != utf8::npos )
+      pos = decimal_separator_pos;
+    if ( !grouping_interval ) {
+      if ( got_grouping_separator ) {
+        //
+        // There's only a single grouping separator, e.g., "1,000".
+        //
+        grouping_interval = pos - prev_grouping_pos;
+      }
+    } else if ( pos - prev_grouping_pos != grouping_interval ) {
+      //
+      // There are multiple grouping separators, but they're not equally spaced
+      // from the last digit, e.g., "1,000,00".  (This is most likely a mistake
+      // on the part of the user.)
+      //
+      grouping_interval = 0;
+    }
+    sub_pic->integer_part.grouping_interval = grouping_interval;
+  } else
+    sub_pic->integer_part.mandatory_grouping_seps = grouping_separators;
+
+  //
+  // Ibid 4.7.4: [I]f the sub-picture contains no decimal-digit-family
+  // character and no decimal-separator-sign, [the minimum-integer-part-size]
+  // is set to one.
+  //
+  if ( !got_mandatory_digit && decimal_separator_pos == utf8::npos )
+    sub_pic->integer_part.minimum_size = 1;
+
+  if ( rightmost_active_pos != utf8::npos &&
+       rightmost_active_pos + 1 < u_format.size() ) {
+    //
+    // Ibid: The suffix is set to contain all passive characters to the right
+    // of the rightmost active character in the fractional part of the
+    // sub-picture.
+    //
+    // Note: must do suffix first so calling erase() won't invalidate
+    // leftmost_active_pos.
+    // 
+    sub_pic->suffix = u_format.substr( rightmost_active_pos + 1 );
+    u_format.erase( rightmost_active_pos + 1 );
+  }
+  if ( leftmost_active_pos != utf8::npos ) {
+    //
+    // Ibid: The prefix is set to contain all passive characters in the
+    // sub-picture to the left of the leftmost active character.
+    //
+    sub_pic->prefix = u_format.substr( 0, leftmost_active_pos );
+    u_format.erase( 0, leftmost_active_pos );
+
+    if ( decimal_separator_pos != utf8::npos ) {
+      //
+      // Adjust decimal_separator_pos by number of characters erased above.
+      //
+      decimal_separator_pos -= leftmost_active_pos;
+    }
+  }
+
+  sub_pic->integer_part.format = u_format.substr( 0, decimal_separator_pos );
+  if ( decimal_separator_pos != utf8::npos ) {
+    sub_pic->fractional_part.format =
+      u_format.substr( decimal_separator_pos + 1 );
+  }
+
+  return;
+
+got_decimal_grouping_adjacent:
+  throw XQUERY_EXCEPTION(
+    err::FODF1310,
+    ERROR_PARAMS(
+      pic.format,
+      ZED( FODF1310_NoDecimalGroupingAdjacent_34 ),
+      unicode::printable_cp( pic.VAR_CP( decimal_separator_sign )  ),
+      unicode::printable_cp( pic.VAR_CP( grouping_separator_sign ) )
+    ),
+    ERROR_LOC( loc )
+  );
+
+got_multiple_signs:
+  throw XQUERY_EXCEPTION(
+    err::FODF1310,
+    ERROR_PARAMS(
+      pic.format,
+      ZED( FODF1310_MultipleSign_3 ),
+      unicode::printable_cp( cp )
+    ),
+    ERROR_LOC( loc )
+  );
+
+got_percent_per_mille:
+  throw XQUERY_EXCEPTION(
+    err::FODF1310,
+    ERROR_PARAMS( pic.format, ZED( FODF1310_NoPercentPermille ) ),
+    ERROR_LOC( loc )
+  );
+}
+
+static void parse_picture( picture *pic, QueryLoc const &loc ) {
+  check_multiple( pic->format, pic->VAR( pattern_separator_sign ), *pic, loc );
+
+  zstring::size_type const pos =
+    pic->format.find( pic->VAR( pattern_separator_sign ) );
+
+  pic->pos_subpicture.format = pic->format.substr( 0, pos );
+  if ( pos != zstring::npos ) {
+    pic->neg_subpicture.format =
+      pic->format.substr( pos + pic->VAR( pattern_separator_sign ).size() );
+  }
+
+  parse_subpicture( &pic->pos_subpicture, *pic, loc );
+  if ( pic->neg_subpicture.format.empty() ) {
+    pic->neg_subpicture = pic->pos_subpicture;
+    //
+    // Ibid: If the picture string contains only one sub-picture, the prefix
+    // for the negative sub-picture is set by concatenating the minus-sign
+    // character and the prefix for the positive sub-picture (if any), in that
+    // order.
+    //
+    pic->neg_subpicture.prefix = pic->VAR( minus_sign );
+    pic->neg_subpicture.prefix += pic->pos_subpicture.prefix;
+  } else
+    parse_subpicture( &pic->neg_subpicture, *pic, loc );
+}
+
+static void set_format( DecimalFormat_t const &df, picture *pic ) {
+  //
+  // See XQuery 3.9 2.1.1 and XQuery F&O 3.0 4.7.1.
+  //
+  FOR_EACH( DecimalFormat::properties_type, prop, df->getProperties() ) {
+    if ( prop->first == "decimal-separator" )
+      pic->VAR( decimal_separator_sign ) = prop->second;
+    else if ( prop->first == "digit" )
+      pic->VAR( optional_digit_sign ) = prop->second;
+    else if ( prop->first == "grouping-separator" )
+      pic->VAR( grouping_separator_sign ) = prop->second;
+    else if ( prop->first == "infinity" )
+      pic->VAR( infinity ) = prop->second;
+    else if ( prop->first == "minus-sign" )
+      pic->VAR( minus_sign ) = prop->second;
+    else if ( prop->first == "NaN" )
+      pic->VAR( NaN ) = prop->second;
+    else if ( prop->first == "pattern-separator" )
+      pic->VAR( pattern_separator_sign ) = prop->second;
+    else if ( prop->first == "percent" )
+      pic->VAR( percent_sign ) = prop->second;
+    else if ( prop->first == "per-mille" )
+      pic->VAR( per_mille_sign ) = prop->second;
+    else if ( prop->first == "zero-digit" )
+      pic->VAR( mandatory_digit_sign ) = prop->second;
+  }
+  pic->set_format_codepoints();
+}
+
+bool FormatNumberIterator::nextImpl( store::Item_t &result,
+                                     PlanState& planState ) const {
+  DecimalFormat_t df;
+  store::Item_t format_name_item;
+  store::Item_t item, value;
+  picture pic;
+  zstring result_str;
+  PlanIteratorState *state;
+
+  DEFAULT_STACK_INIT( PlanIteratorState, state, planState );
+
+  if ( !consumeNext( value, theChildren[0].getp(), planState ) ||
+       !is_allowed_type( value->getType() ) ) {
+    //
+    // XQuery F&O 3.0 4.7.2: If the supplied value of the $value argument is an
+    // empty sequence, the function behaves as if the supplied value were the
+    // xs:double value NaN.
+    //
+    // Ibid: The $value argument may be of any numeric data type (xs:double,
+    // xs:float, xs:decimal, or their subtypes including xs:integer).
+    //
+    GENV_ITEMFACTORY->createDouble( value, xs_double::nan() );
+  }
+
+  consumeNext( item, theChildren[1].getp(), planState );
+  item->getStringValue2( pic.format );
+
+  if ( theChildren.size() >= 3 )
+    consumeNext( format_name_item, theChildren[2].getp(), planState );
+
+  if ( theChildren.size() < 3 || !format_name_item ) {
+    df = planState.theCompilerCB->theRootSctx->get_decimal_format( NULL );
+  } else {
+
+    zstring format_name( format_name_item->getStringValue() );
+    ascii::trim_whitespace( format_name );
+    zstring prefix, local;
+    if ( !xml::split_name( format_name, &prefix, &local ) ||
+         prefix.empty() ) {
+      GENV_ITEMFACTORY->createQName( format_name_item, "", "", format_name );
+    } else {
+      zstring ns;
+      if ( theSctx->lookup_ns( ns, prefix, loc, false ) ) {
+        GENV_ITEMFACTORY->createQName( format_name_item, ns, prefix, local );
+      } else {
+        //
+        // The prefix is not in the known namespaces so the only posibility
+        // left is for the function to be invoked from an EnclosedIterator.
+        //
+        if ( planState.theNodeConstuctionPath.empty() )
+          throw XQUERY_EXCEPTION(
+            err::FODF1280,
+            ERROR_PARAMS( format_name ),
+            ERROR_LOC( loc )
+          );
+        store::NsBindings bindings;
+        planState.theNodeConstuctionPath.top()->
+          getNamespaceBindings( bindings );
+        FOR_EACH( store::NsBindings, binding, bindings ) {
+          if ( prefix == binding->first ) {
+            GENV_ITEMFACTORY->createQName(
+              format_name_item, binding->second, prefix, local
+            );
+            break;
+          }
+        }
+      }
+    }
+
+    if ( format_name_item.isNull() )
+      throw XQUERY_EXCEPTION(
+        err::FODF1280, ERROR_PARAMS( "<null>" ), ERROR_LOC( loc )
+      );
+    df = planState.theCompilerCB->theRootSctx->
+      get_decimal_format( format_name_item );
+    if ( !df )
+      throw XQUERY_EXCEPTION(
+        err::FODF1280, ERROR_PARAMS( format_name_item->getStringValue() ),
+        ERROR_LOC( loc )
+      );
+
+  } // if ( theChildren.size() < 3 ... )
+
+  if ( !df.isNull() )
+    set_format( df, &pic );
+  parse_picture( &pic, loc );
+  format_number( value, pic, theSctx->get_typemanager(), loc, &result_str );
+  STACK_PUSH( GENV_ITEMFACTORY->createString( result, result_str ), state );
+  STACK_END (state);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace zorba
+/* vim:set et sw=2 ts=2: */

=== modified file 'src/runtime/numerics/numerics_impl.cpp'
--- src/runtime/numerics/numerics_impl.cpp	2013-03-04 21:00:58 +0000
+++ src/runtime/numerics/numerics_impl.cpp	2013-04-11 00:34:24 +0000
@@ -27,7 +27,6 @@
 #include "system/globalenv.h"
 
 #include "util/tracer.h"
-#include "util/utf8_string.h"
 
 #include "types/casting.h"
 #include "types/typeconstants.h"
@@ -396,576 +395,5 @@
   STACK_END (state);
 }
 
-//XQuery 3.0 functions
-/*******************************************************************************
-
-********************************************************************************/
-static const char* decimal_separator_param = "decimal-separator";
-static const char* grouping_separator_param = "grouping-separator";
-static const char* infinity_param = "infinity";
-static const char* minus_sign_param = "minus-sign";
-static const char* nan_param = "NaN";
-static const char* percent_param = "percent";
-static const char* per_mille_param = "per-mille";
-static const char* zero_digit_param = "zero-digit";
-static const char* digit_param = "digit";
-static const char* pattern_separator_param = "pattern-separator";
-
-
-class FormatNumberInfo
-{
-public:
-  QueryLoc loc;
-  // Separators
-  zstring decimal_separator;
-  zstring grouping_separator;
-  zstring percent;
-  zstring per_mille;
-  zstring zero_digit;
-  zstring digit_sign;
-  zstring pattern_separator;
-  zstring infinity;
-  zstring NaN;
-  zstring minus;
-  
-  zstring pictureString; // The original picture string, used for debugging and error reporting
-
-  class PartInfo
-  {
-  public:
-    zstring str;
-    std::vector<int> grouping_pos;
-    int N;
-    int minimum_size;
-    int maximum_size;
-    PartInfo() :  N(-1), minimum_size(0), maximum_size(0) {};
-  };
-
-  class SubPictureInfo
-  {
-  public:
-    zstring str;
-    zstring prefix;
-    zstring suffix;
-    PartInfo integer_part;
-    PartInfo fractional_part;
-    SubPictureInfo() { }
-  } pos_subpicture, neg_subpicture;
-
-  FormatNumberInfo() :
-    decimal_separator( "." ),
-    grouping_separator( "," ),
-    percent( "%" ),
-    zero_digit( "0" ),
-    digit_sign( "#" ),
-    pattern_separator( ";" ),
-    infinity( "Infinity" ),
-    NaN( "NaN" ),
-    minus( "-" )
-  {
-    utf8_string<zstring> u_per_mille( per_mille );
-    u_per_mille = (unicode::code_point)0x2030;
-  }
-
-  void readFormat(const DecimalFormat_t& df_t)
-  {
-    if (df_t.isNull())
-      return;
-
-    const DecimalFormat::param_vector_type* params = df_t->getParamVector();
-
-    for ( DecimalFormat::param_vector_type::const_iterator it = params->begin(); it != params->end(); it++)
-    {
-      if (it->first == decimal_separator_param)
-        decimal_separator = it->second.c_str();
-      else if (it->first == grouping_separator_param)
-        grouping_separator = it->second.c_str();
-      else if (it->first == infinity_param)
-        infinity = it->second.c_str();
-      else if (it->first == minus_sign_param)
-        minus = it->second.c_str();
-      else if (it->first == nan_param)
-        NaN = it->second.c_str();
-      else if (it->first == percent_param)
-        percent = it->second.c_str();
-      else if (it->first == per_mille_param)
-        per_mille = it->second.c_str();
-      else if (it->first == zero_digit_param)
-        zero_digit = it->second.c_str();
-      else if (it->first == digit_param)
-        digit_sign = it->second.c_str();
-      else if (it->first == pattern_separator_param)
-        pattern_separator = it->second.c_str();
-    }
-  }
-};
-
-
-// returns an error if there are two or more instances of the given pattern in the string
-static void errorIfTwoOrMore(zstring const& part, const char* sep, FormatNumberInfo& info)
-{
-  zstring::size_type const pos = part.find(sep);
-
-  if (pos != zstring::npos)
-  {
-    if (part.find(sep, strlen(sep), pos+1) != zstring::npos)
-      throw XQUERY_EXCEPTION(err::FODF1310, ERROR_PARAMS(info.pictureString, ZED(FormatNumberDuplicates), sep), ERROR_LOC(info.loc));
-  }
-}
-
-
-static void parsePart(
-    FormatNumberInfo& info,
-    FormatNumberInfo::PartInfo& part,
-    bool fractional = false)
-{
-  zstring& str = part.str;
-  if (str.empty())
-    return;
-
-  errorIfTwoOrMore(str, info.percent.c_str(), info);
-  errorIfTwoOrMore(str, info.per_mille.c_str(), info);
-
-  if (str.find(info.percent.c_str()) != zstring::npos &&
-      str.find(info.per_mille.c_str()) != zstring::npos)
-  {
-    throw XQUERY_EXCEPTION(err::FODF1310, ERROR_PARAMS(info.pictureString, ZED(FormatNumberPercentPermille)), ERROR_LOC(info.loc));
-  }
-
-  if (str.find(info.digit_sign.c_str()) == zstring::npos &&
-      str.find(info.zero_digit.c_str()) == zstring::npos)
-  {
-    throw XQUERY_EXCEPTION(err::FODF1310, ERROR_PARAMS(info.pictureString, ZED(FormatNumberAtLeastOneOptionalOrDecimal)), ERROR_LOC(info.loc));
-  }
-
-  // get grouping separators
-  int digit_signs = 0;
-  int zero_signs = 0;
-  int start = fractional? 0 : (int)str.size()-1;
-  int end = fractional? (int)str.size() : -1;
-  int delta = fractional? 1 : -1;
-  int first_digit_sign = -1;
-  int last_zero_sign = -1;
-  while (start != end)
-  {
-    zstring::value_type ch = str[start];
-    if (info.digit_sign[0] == ch)
-    {
-      if (first_digit_sign == -1)
-        first_digit_sign = start;
-      digit_signs++;
-    }
-    else if (info.zero_digit[0] == ch)
-    {
-      last_zero_sign = start;
-      zero_signs++;
-    }
-    else if (info.grouping_separator[0] == ch)
-      part.grouping_pos.push_back(digit_signs+zero_signs);
-    start += delta;
-  }
-
-  if (first_digit_sign != -1 && last_zero_sign != -1)
-  {
-    if (!fractional && first_digit_sign > last_zero_sign)
-      throw XQUERY_EXCEPTION(err::FODF1310, ERROR_PARAMS(info.pictureString, ZED(FormatNumberIntegerPart)), ERROR_LOC(info.loc));    
-    else if (fractional && first_digit_sign < last_zero_sign)
-      throw XQUERY_EXCEPTION(err::FODF1310, ERROR_PARAMS(info.pictureString, ZED(FormatNumberFractionalPart)), ERROR_LOC(info.loc));
-  }
-
-  if (part.grouping_pos.size() > 0 && part.grouping_pos[0] == 0)
-    throw XQUERY_EXCEPTION(err::FODF1310, ERROR_PARAMS(info.pictureString, ZED(FormatNumberGroupingAdjacentToDecimal)), ERROR_LOC(info.loc));
-
-  if (part.grouping_pos.size() > 0)
-  {
-    part.N = part.grouping_pos[0];
-    for (unsigned int i=1; i<part.grouping_pos.size(); i++)
-      if ((part.grouping_pos[i] % part.N) != 0)
-      {
-        part.N = -1;
-        break;
-      }
-  }
-
-  part.minimum_size = zero_signs;
-  if (!fractional &&
-      zero_signs == 0 &&
-      str.find(info.decimal_separator.c_str()) == zstring::npos)
-  {
-    part.minimum_size = 1;
-  }
-
-  if (fractional)
-    part.maximum_size = digit_signs + zero_signs;
-}
-
-
-static void parseSubpicture(
-    FormatNumberInfo::SubPictureInfo& sub_picture,
-    FormatNumberInfo& info)
-{
-  int chars;
-  zstring& str = sub_picture.str;
-  if (str.empty())
-    return;
-
-  errorIfTwoOrMore(str, info.decimal_separator.c_str(), info);
-  zstring::size_type pos = str.find(info.decimal_separator.c_str());
-  if (pos != zstring::npos)
-  {
-    sub_picture.integer_part.str = str.substr(0, pos);
-    sub_picture.fractional_part.str = str.substr(pos+1, str.size()-pos);
-  }
-  else
-    sub_picture.integer_part.str = str;
-
-  parsePart(info, sub_picture.integer_part);
-  parsePart(info, sub_picture.fractional_part, true);
-
-  // prefix
-  zstring temp = sub_picture.integer_part.str;
-  chars = (int)temp.size();
-  for (int i = 0; i < chars; i++)
-  {
-    zstring::value_type ch = temp[i];
-    if (info.decimal_separator[0] == ch || info.grouping_separator[0] == ch || info.zero_digit[0] == ch
-      || info.digit_sign[0] == ch || info.pattern_separator[0] == ch || i == chars-1)
-    {
-      sub_picture.prefix = temp.substr(0, i);
-      break;
-    }
-  }
-  // suffix
-  temp = sub_picture.fractional_part.str;
-  chars = (int)temp.size();
-  for (int i=chars-1; i >= 0; i--)
-  {
-    zstring::value_type ch = temp[i];
-    if (info.decimal_separator[0] == ch || info.grouping_separator[0] == ch || info.zero_digit[0] == ch
-      || info.digit_sign[0] == ch || info.pattern_separator[0] == ch || i == 0)
-    {
-      sub_picture.suffix = temp.substr(i+1, chars-i-1);
-      break;
-    }
-  }
-}
-
-
-static void parsePicture(FormatNumberInfo& info)
-{
-  errorIfTwoOrMore(info.pictureString, info.pattern_separator.c_str(), info);
-
-  zstring::size_type pos = info.pictureString.find(info.pattern_separator.c_str());
-  if (pos != zstring::npos)
-  {
-    info.pos_subpicture.str = info.pictureString.substr(0, pos);
-    info.neg_subpicture.str = info.pictureString.substr(pos+1, info.pictureString.size() - pos);
-  }
-  else
-    info.pos_subpicture.str = info.pictureString;
-
-  parseSubpicture(info.pos_subpicture, info);
-  if (info.neg_subpicture.str.empty())
-  {
-    info.neg_subpicture = info.pos_subpicture;
-    zstring temp(info.minus);
-    temp.append(info.pos_subpicture.prefix);
-    info.neg_subpicture.prefix = temp;
-  }
-  else
-    parseSubpicture(info.neg_subpicture, info);
-}
-
-
-static bool isAllowedType(store::Item* type_qname)
-{
-  const RootTypeManager& rtm = GENV_TYPESYSTEM;
-
-  if (type_qname->equals(rtm.XS_FLOAT_QNAME)
-    || type_qname->equals(rtm.XS_DOUBLE_QNAME)
-    || type_qname->equals(rtm.XS_DECIMAL_QNAME)
-    || type_qname->equals(rtm.XS_INTEGER_QNAME)
-    || type_qname->equals(rtm.XS_NON_POSITIVE_INTEGER_QNAME)
-    || type_qname->equals(rtm.XS_NEGATIVE_INTEGER_QNAME)
-    || type_qname->equals(rtm.XS_LONG_QNAME)
-    || type_qname->equals(rtm.XS_INT_QNAME)
-    || type_qname->equals(rtm.XS_SHORT_QNAME)
-    || type_qname->equals(rtm.XS_BYTE_QNAME)
-    || type_qname->equals(rtm.XS_NON_NEGATIVE_INTEGER_QNAME)
-    || type_qname->equals(rtm.XS_UNSIGNED_LONG_QNAME)
-    || type_qname->equals(rtm.XS_UNSIGNED_INT_QNAME)
-    || type_qname->equals(rtm.XS_UNSIGNED_SHORT_QNAME)
-    || type_qname->equals(rtm.XS_UNSIGNED_BYTE_QNAME)
-    || type_qname->equals(rtm.XS_POSITIVE_INTEGER_QNAME))
-    return true;
-  else
-    return false;
-}
-
-// returns n zeros "0". n can be <=0 and then the function will return ""
-static zstring createZeros(int n)
-{
-  zstring result;
-  // bugfix for bug #3134696
-  // if called from formatNumber with n = -1
-  if (n > 0) {
-    result.append(n, '0');
-  }
-  return result;
-}
-
-
-static void formatGroupings(
-    zstring& result,
-    const zstring& str,
-    FormatNumberInfo::PartInfo& part,
-    FormatNumberInfo& info)
-{
-  unsigned int grouping_index = 0;
-
-  result.clear();
-
-  long len = (long)str.size();
-
-  for (long i = len-1; i >= 0; i--)
-  {
-    char ch = str[i];
-
-    if (((grouping_index < part.grouping_pos.size()
-        &&
-        len-i-1 == part.grouping_pos[grouping_index])
-      ||
-      (part.N != -1
-        &&
-        len-1-i != 0
-        &&
-        ((len-1-i) % part.N) == 0))
-      &&
-      ch != '-')
-    {
-      result.append(info.grouping_separator);
-      if (grouping_index < part.grouping_pos.size())
-        grouping_index++;
-      while (grouping_index < part.grouping_pos.size()
-          &&
-          part.grouping_pos[grouping_index] == part.grouping_pos[grouping_index-1])
-      {
-        result.append(info.grouping_separator);
-        grouping_index++;
-      }
-    }
-
-    if (ch == '0')
-      result.append(info.zero_digit);
-    else if (ch == '-')
-      ; // skip the '-' sign
-    else
-      result.push_back(ch);
-  }
-}
-
-
-static void formatNumber(
-    zstring& resultString,
-    store::Item_t& number,
-    FormatNumberInfo& info,
-    const TypeManager* tm,
-    const QueryLoc& loc)
-{
-  const RootTypeManager& rtm = GENV_TYPESYSTEM;
-
-  if (number->isNaN())
-  {
-    resultString.append(info.NaN);
-    return;
-  }
-
-  store::Item_t zero;
-  store::Item_t doubleItem;
-  FormatNumberInfo::SubPictureInfo& sub_picture = info.pos_subpicture;
-
-  GENV_ITEMFACTORY->createDouble(zero, xs_double::zero());
-
-  GenericCast::castToAtomic(doubleItem, number, &*rtm.DOUBLE_TYPE_ONE, tm, NULL, loc);
-
-  if (doubleItem->compare(zero) == -1)
-  {
-    sub_picture = info.neg_subpicture;
-  }
-
-  if (doubleItem->isPosOrNegInf())
-  {
-    resultString.append(sub_picture.prefix);
-    resultString.append(info.infinity);
-    resultString.append(sub_picture.suffix);
-    return;
-  }
-
-  xs_double adjusted = doubleItem->getDoubleValue();
-
-  if (sub_picture.str.find(info.percent) != zstring::npos)
-    adjusted *= 100;
-  else if (sub_picture.str.find(info.per_mille) != zstring::npos)
-    adjusted *= 1000;
-
-  adjusted = adjusted.roundHalfToEven(Integer(sub_picture.fractional_part.maximum_size));
-
-  zstring converted = adjusted.toString(true);
-
-  // process min sizes
-  zstring integer_part;
-  zstring fractional_part;
-  zstring::size_type pos = converted.find(".", 0, 1);
-  if (pos == zstring::npos)
-  {
-    integer_part = converted;
-  }
-  else
-  {
-    integer_part = converted.substr(0, pos);
-    fractional_part = converted.substr(pos+1, converted.size() - pos + 1);
-  }
-
-  // Add zeros
-  zstring temp = createZeros((int)(sub_picture.integer_part.minimum_size - integer_part.size()));
-  temp.append(integer_part);
-  integer_part = temp;
-  fractional_part.append(createZeros((int)(sub_picture.fractional_part.minimum_size - fractional_part.size())));
-
-  // groupings
-  zstring integer_part_result;
-  zstring fractional_part_result;
-  formatGroupings(integer_part_result, integer_part, sub_picture.integer_part, info);
-
-  zstring tmp;
-  ascii::reverse(integer_part_result, &tmp);
-  integer_part_result.swap(tmp);
-
-  tmp.clear();
-  ascii::reverse(fractional_part, &tmp);
-  fractional_part.swap(tmp);
-
-  formatGroupings(fractional_part_result,
-                  fractional_part,
-                  sub_picture.fractional_part,
-                  info);
-
-  resultString.append(sub_picture.prefix);
-  resultString.append(integer_part_result);
-  if (fractional_part.size() != 0)
-  {
-    resultString.append(info.decimal_separator);
-    resultString.append(fractional_part_result);
-  }
-  resultString.append(sub_picture.suffix);
-}
-
-
-bool
-FormatNumberIterator::nextImpl(store::Item_t& result, PlanState& planState) const
-{
-  zstring resultString;
-  store::Item_t numberItem, pictureItem;
-  store::Item_t formatName = NULL;
-  FormatNumberInfo info;
-  DecimalFormat_t df_t;
-
-  PlanIteratorState* state;
-  DEFAULT_STACK_INIT ( PlanIteratorState, state, planState );
-
-  if (!consumeNext(result, theChildren[0].getp(), planState ))
-  {
-    // Got void, assume NaN, return "NaN"
-    GENV_ITEMFACTORY->createDouble(result, xs_double::nan());
-  }
-
-  {
-    info.loc = loc;
-    if (!isAllowedType(result->getType()))
-    {
-      RAISE_ERROR(err::XPTY0004, info.loc,
-      ERROR_PARAMS(ZED(XPTY0004_FormatNumber_2), result->getType()->getStringValue()));
-    }
-
-    consumeNext(pictureItem, theChildren[1].getp(), planState);
-    
-    if (theChildren.size() == 3)
-      consumeNext(formatName, theChildren[2].getp(), planState);
-
-    if (theChildren.size() < 3 || formatName.getp() == NULL)
-    {
-      df_t = planState.theCompilerCB->theRootSctx->get_decimal_format(NULL);
-    }
-    else
-    {
-      do // use a do/while to avoid a horde of nested if/then/elses
-      {
-        // The formatName is a string, which must be interpreted as a QName -> 
-        // must resolve the namespace, if any
-        zstring tmpFormatName = formatName->getStringValue();
-        formatName = NULL;
-        if (tmpFormatName.find(':') ==  zstring::npos)
-        {
-          GENV_ITEMFACTORY->createQName(formatName, "", "", tmpFormatName);
-          break;
-        }
-
-        zstring ns;
-        zstring prefix = tmpFormatName.substr(0, tmpFormatName.find(':'));
-        if (theSctx->lookup_ns(ns, prefix, loc, false))
-        {
-          GENV_ITEMFACTORY->createQName(formatName,
-                                        ns,
-                                        prefix,
-                                        tmpFormatName.substr(tmpFormatName.find(':')+1));
-          break;
-        }
-
-        // The prefix is not in the known namespaces, the only posibility left is for the function to be invoked from an EnclosedIterator
-        if (planState.theNodeConstuctionPath.empty())
-        {
-          RAISE_ERROR(err::FODF1280, loc, ERROR_PARAMS(tmpFormatName));
-        }
-
-        store::NsBindings bindings;
-        planState.theNodeConstuctionPath.top()->getNamespaceBindings(bindings);
-        for (unsigned int i = 0; i < bindings.size(); i++)
-        {
-          if (prefix == bindings[i].first)
-          {
-            GENV_ITEMFACTORY->createQName(formatName,
-                                          bindings[i].second,
-                                          prefix,
-                                          tmpFormatName.substr(tmpFormatName.find(':')+1));
-            break;
-          }
-        }
-      } while(0);
-
-      if (formatName.isNull())
-        throw XQUERY_EXCEPTION(
-          err::FODF1280, ERROR_PARAMS( "<null>" ), ERROR_LOC( loc )
-        );
-
-      if ( (df_t = planState.theCompilerCB->theRootSctx->get_decimal_format(formatName)).getp() == NULL )
-        throw XQUERY_EXCEPTION(
-          err::FODF1280, ERROR_PARAMS( formatName->getStringValue() ),
-          ERROR_LOC( loc )
-        );
-
-    } // if (theChildren.size() < 3)
-
-    info.readFormat(df_t);
-
-    info.pictureString = pictureItem->getStringValue();
-    parsePicture(info);
-    formatNumber(resultString, result, info, theSctx->get_typemanager(), loc);
-
-    STACK_PUSH (GENV_ITEMFACTORY->createString(result, resultString), state);
-  }
-
-  STACK_END (state);
-}
-
 } // namespace zorba
 /* vim:set et sw=2 ts=2: */

=== modified file 'src/util/utf8_util_base.h'
--- src/util/utf8_util_base.h	2013-02-07 17:24:36 +0000
+++ src/util/utf8_util_base.h	2013-04-11 00:34:24 +0000
@@ -133,7 +133,7 @@
 }
 
 /**
- * Decodes the next Unicode character.
+ * Decodes the next Unicode character and advances the iterator.
  *
  * @tparam OctetIterator The iterator to use to iterate over the underlying
  * byte sequence.
@@ -146,6 +146,17 @@
 unicode::code_point next_char( OctetIterator &i );
 
 /**
+ * Decodes the next Unicode character.
+ *
+ * @param p A pointer to the first byte of a UTF-8 byte sequence comprising a
+ * Unicode character.
+ * @return Returns the Unicode code-point of the next character.
+ */
+inline unicode::code_point decode( storage_type const *p ) {
+  return next_char( p );
+}
+
+/**
  * Decodes the previous Unicode character.
  *
  * @tparam OctetIterator The iterator to use to iterate over the underlying

=== modified file 'src/zorbatypes/floatimpl.h'
--- src/zorbatypes/floatimpl.h	2013-03-22 19:06:44 +0000
+++ src/zorbatypes/floatimpl.h	2013-04-11 00:34:24 +0000
@@ -216,6 +216,7 @@
 
   ////////// math functions ///////////////////////////////////////////////////
 
+  FloatImpl abs() const;
   FloatImpl acos() const;
   FloatImpl acosh() const;
   FloatImpl asin() const;
@@ -799,6 +800,11 @@
 ////////// math functions /////////////////////////////////////////////////////
 
 template<typename F>
+inline FloatImpl<F> FloatImpl<F>::abs() const {
+  return FloatImpl<F>( std::fabs( value_ ) );
+}
+
+template<typename F>
 inline FloatImpl<F> FloatImpl<F>::acosh() const {
   // formula from www.mathworks.com
   return FloatImpl<F>(

=== modified file 'test/fots/CMakeLists.txt'
--- test/fots/CMakeLists.txt	2013-04-10 17:05:01 +0000
+++ test/fots/CMakeLists.txt	2013-04-11 00:34:24 +0000
@@ -148,25 +148,16 @@
 EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-011 0)
 EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-en152 21558)
 EXPECTED_FOTS_FAILURE (fn-format-integer format-integer-044 1162631)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat14 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat15 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat34 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat38 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat40 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat41 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat42 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat60a 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat60m 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat60o 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat60q 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat63 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat64 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat70 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat71 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat81 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat83 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat87 0)
-EXPECTED_FOTS_FAILURE (fn-format-number numberformat88 0)
+EXPECTED_FOTS_FAILURE (fn-format-number numberformat41 1167427)
+EXPECTED_FOTS_FAILURE (fn-format-number numberformat42 1167427)
+EXPECTED_FOTS_FAILURE (fn-format-number numberformat60a 1167609)
+EXPECTED_FOTS_FAILURE (fn-format-number numberformat60m 1167609)
+EXPECTED_FOTS_FAILURE (fn-format-number numberformat60o 1167609)
+EXPECTED_FOTS_FAILURE (fn-format-number numberformat60q 1167609)
+EXPECTED_FOTS_FAILURE (fn-format-number numberformat63 1167609)
+EXPECTED_FOTS_FAILURE (fn-format-number numberformat83 1167643)
+EXPECTED_FOTS_FAILURE (fn-format-number numberformat87 1167641)
+EXPECTED_FOTS_FAILURE (fn-format-number numberformat88 1167641)
 EXPECTED_FOTS_FAILURE (fn-generate-id generate-id-001 0)
 EXPECTED_FOTS_FAILURE (fn-generate-id generate-id-002 0)
 EXPECTED_FOTS_FAILURE (fn-generate-id generate-id-003 0)

=== renamed directory 'test/rbkt/ExpQueryResults/zorba/math/format_integer' => 'test/rbkt/ExpQueryResults/zorba/numerics/format-integer'
=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-integer/format-integer-1-11.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-integer/format-integer-1-11.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-integer/format-integer-1-11.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added directory 'test/rbkt/ExpQueryResults/zorba/numerics/format-number'
=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-01.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-01.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-02.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-02.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-02.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-03.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-03.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-03.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-04.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-04.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-04.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-05.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-05.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-05.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-06.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-06.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-06.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-07.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-07.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-07.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-08.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-08.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-08.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-09.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-09.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-09.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-10.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-10.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-10.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-11.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-11.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-11.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-12.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-12.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-12.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-13.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-13.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-13.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-14.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-14.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-14.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-15.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-15.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-15.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-decimal-format-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-decimal-format-01.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-decimal-format-01.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-decimal-format-02.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-decimal-format-02.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-decimal-format-02.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-decimal-format-03.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-decimal-format-03.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-decimal-format-03.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-empty.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-empty.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number/format-number-empty.xml.res	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+true

=== removed file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number1.xml.res	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number1.xml.res	1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-1 12

=== removed file 'test/rbkt/ExpQueryResults/zorba/numerics/format-number2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/numerics/format-number2.xml.res	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/numerics/format-number2.xml.res	1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-NaN

=== renamed directory 'test/rbkt/Queries/zorba/math/format_integer' => 'test/rbkt/Queries/zorba/numerics/format-integer'
=== added file 'test/rbkt/Queries/zorba/numerics/format-integer/format-integer-1-11.xq'
--- test/rbkt/Queries/zorba/numerics/format-integer/format-integer-1-11.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-integer/format-integer-1-11.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-integer( 1234, "#,###" ) eq "1,234"

=== added directory 'test/rbkt/Queries/zorba/numerics/format-number'
=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-01.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-01.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-01.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( 1, "0" ) eq "1"

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-02.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-02.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-02.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( 1, "#" ) eq "1"

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-03.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-03.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-03.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( -1, "0" ) eq "-1"

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-04.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-04.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-04.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( .14, "1%" ) eq "14%"

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-05.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-05.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-05.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( 12345678.9, "9,999.99" ) eq "12,345,678.90"

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-06.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-06.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-06.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( 123.9, "9999" ) eq "0124"

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-07.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-07.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-07.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( -6, "000" ) eq "-006"

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-08.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-08.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-08.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( 42, "1;-1" ) eq "42"

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-09.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-09.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-09.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( -42, "1;-1" ) eq "-42"

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-10.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-10.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-10.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( -42, "1;(1)" ) eq "(42)"

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-11.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-11.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-11.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( 1.2, "p#.#s" ) eq "p1.2s"

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-12.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-12.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-12.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( 42, "#,###" ) eq "42"

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-13.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-13.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-13.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( 1234, "###,###" ) eq "1,234"

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-14.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-14.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-14.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( 42, "0.00" ) eq "42.00"

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-15.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-15.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-15.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( 1234567890.123456, ",000.000" ) eq "1,234,567,890.123"

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-1.spec'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-1.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-1.spec	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FODF1310

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-1.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-1.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( 1, "1;1;" )

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-2.spec'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-2.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-2.spec	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FODF1310

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-2.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-2.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-2.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( 1, "1.1." )

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-3.spec'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-3.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-3.spec	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FODF1310

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-3.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-3.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-3.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( .14, "1%%" )

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-4.spec'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-4.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-4.spec	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FODF1310

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-4.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-4.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-MultipleSign-4.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( .014, "1‰‰" )

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-MustHaveOptOrMandatoryDigit.spec'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-MustHaveOptOrMandatoryDigit.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-MustHaveOptOrMandatoryDigit.spec	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FODF1310

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-MustHaveOptOrMandatoryDigit.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-MustHaveOptOrMandatoryDigit.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-MustHaveOptOrMandatoryDigit.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( 1, "." )

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-NoActivePassiveActive.spec'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-NoActivePassiveActive.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-NoActivePassiveActive.spec	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FODF1310

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-NoActivePassiveActive.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-NoActivePassiveActive.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-NoActivePassiveActive.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( .14, "1%1" )

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-NoDecimalGroupingAdjacent-1.spec'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-NoDecimalGroupingAdjacent-1.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-NoDecimalGroupingAdjacent-1.spec	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FODF1310

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-NoDecimalGroupingAdjacent-1.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-NoDecimalGroupingAdjacent-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-NoDecimalGroupingAdjacent-1.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( 1, "1,." )

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-NoDecimalGroupingAdjacent-2.spec'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-NoDecimalGroupingAdjacent-2.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-NoDecimalGroupingAdjacent-2.spec	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FODF1310

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-NoDecimalGroupingAdjacent-2.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-NoDecimalGroupingAdjacent-2.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-NoDecimalGroupingAdjacent-2.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( 1, "1.," )

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-NoMandatoryDigitAfterOpt.spec'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-NoMandatoryDigitAfterOpt.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-NoMandatoryDigitAfterOpt.spec	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FODF1310

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-NoMandatoryDigitAfterOpt.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-NoMandatoryDigitAfterOpt.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-NoMandatoryDigitAfterOpt.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( 1, "0.#0" )

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-NoOptDigitAfterMandatory.spec'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-NoOptDigitAfterMandatory.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-NoOptDigitAfterMandatory.spec	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FODF1310

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-NoOptDigitAfterMandatory.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-NoOptDigitAfterMandatory.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-NoOptDigitAfterMandatory.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( 1, "0#" )

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-NoPercentPermille-1.spec'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-NoPercentPermille-1.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-NoPercentPermille-1.spec	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FODF1310

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-NoPercentPermille-1.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-NoPercentPermille-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-NoPercentPermille-1.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( .014, "1%‰" )

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-NoPercentPermille-2.spec'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-NoPercentPermille-2.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-NoPercentPermille-2.spec	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FODF1310

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-NoPercentPermille-2.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-NoPercentPermille-2.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-NoPercentPermille-2.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,1 @@
+fn:format-number( .014, "1‰%" )

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-decimal-format-01.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-decimal-format-01.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-decimal-format-01.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,5 @@
+declare decimal-format local:de
+  decimal-separator = ","
+  grouping-separator = ".";
+
+fn:format-number( 1234.567, "#.###,##", "local:de" ) eq "1.234,57"

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-decimal-format-02.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-decimal-format-02.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-decimal-format-02.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,3 @@
+declare decimal-format local:th zero-digit = "๐";
+
+fn:format-number( 1234.567, "#,###.##", "local:th" ) eq "๑,๒๓๔.๕๗"

=== added file 'test/rbkt/Queries/zorba/numerics/format-number/format-number-decimal-format-03.xq'
--- test/rbkt/Queries/zorba/numerics/format-number/format-number-decimal-format-03.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-decimal-format-03.xq	2013-04-11 00:34:24 +0000
@@ -0,0 +1,3 @@
+declare default decimal-format infinity = "off-the-scale";
+
+fn:format-number( 1 div 0e0, "###############################" ) eq "off-the-scale"

=== renamed file 'test/rbkt/Queries/zorba/numerics/format-number2.xq' => 'test/rbkt/Queries/zorba/numerics/format-number/format-number-empty.xq'
--- test/rbkt/Queries/zorba/numerics/format-number2.xq	2013-02-07 17:24:36 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number/format-number-empty.xq	2013-04-11 00:34:24 +0000
@@ -1,1 +1,1 @@
-fn:format-number((), "0")
+fn:format-number( (), "0" ) eq "NaN"

=== removed file 'test/rbkt/Queries/zorba/numerics/format-number1.xq'
--- test/rbkt/Queries/zorba/numerics/format-number1.xq	2013-02-07 17:24:36 +0000
+++ test/rbkt/Queries/zorba/numerics/format-number1.xq	1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-fn:format-number(1, ""), fn:format-number(12, "0")


Follow ups