Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFC] Decimal Floating Point support for GDB (Part 1: patch)
@ 2005-09-28  4:40 Wu Zhou
  2005-09-28 18:40 ` Eli Zaretskii
  2005-10-02 21:00 ` Daniel Jacobowitz
  0 siblings, 2 replies; 13+ messages in thread
From: Wu Zhou @ 2005-09-28  4:40 UTC (permalink / raw)
  To: gdb-patches

Hello all,

Let me firstly introduce some background for this.  

As we all know, most computers today support binary floating-point in 
hardware.  While suitable for many purposes, binary floating-point 
arithmetic has its own shorts, to say, it can't represent float data 
exactly.  This limits its application a little.

Decimal floating point can avoid this by using base 10 (decimal) exponents
and preserving those exponents where possible.  It is now discussed by an IEEE
WG to extend IEEE 754 standard to be incorporate.  And C standard committee is 
also discussing possibility to add it into C99 standard revision.  For 
more detailed description, please refer to: 
http://grouper.ieee.org/groups/754/revision.html,
http://www2.hursley.ibm.com/decimal/ and
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1107.htm.

Ben Elliston is now hosting a project trying to add DFP support into GCC 
in dfp-branch. (For some detail, please refer to
http://gcc.gnu.org/wiki/Decimal%20Floating-Point)

This patch is intended to add decimal floating point (DFP) support into
GDB.  It currently supports the printing and setting of DFP.  And also 
support displaying the dfp types in function argument and backtrace.  
If you think that any other features are also desired, please let me know.  
I will try to see whether it can also be supported.

Here goes the patch (testcase will be posted in another mail). Please 
review and comment, any suggestion, comments and ideas are highly 
appreciated.

2005-9-28  Wu Zhou  <woodzltc@cn.ibm.com>
	
	* gdbtypes.h (TYPE_FLAG_DECIMAL): New flag to indicate that this
	float type is decimal.
	* gdbtypes.h (TYPE_DECIMAL): New predicate to determine whether a
	type is decimal floating point.
	* dwarf2read.c (read_base_type): Read out decimal attribute and set
	type code and decimal flag.
	* dwarf2read.c (dwarf_base_type): Set the dwarf2 fundamental type 
	for different decimal types.
	* dwarf2read.c (dwarf_type_encoding_name): Set the type encoding 
	name for decimal floating point types.
	* c-exp.y (parse_number): Parse the decimal floating point, which 
	has a suffix ('df', 'dd' or 'dl') and return STRING here.
	* eval.c (evaluate_subexp_standard): Call value_set_dfp to set the 
	value of decimal floating point types. 
	* valops.c (value_set_dfp): New function, calling decimal_from_string
	to set the value of decimal floating point types.
	* valprint.c (print_floating): If decimal flag is set, call 
	decimal_to_string to print this floating variable.
	* dfp.h: New header file for decimal floating point support in GDB.
	main functions is decimal_from_string and decimal_to_string.
	* dfp.c: New source file for decimal floating point support in GDB.
	Implement decimal_from_string and decimal_to_strin.
	* Makefile.in: Add dfp.h and dfp.c.

Index: gdbtypes.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.h,v
retrieving revision 1.62
diff -c -p -r1.62 gdbtypes.h
*** gdbtypes.h	6 Apr 2005 17:01:25 -0000	1.62
--- gdbtypes.h	28 Sep 2005 04:32:14 -0000
*************** enum type_code
*** 304,309 ****
--- 304,314 ----
  
  #define TYPE_FLAG_FIXED_INSTANCE (1 << 15)
  
+ /* Differentiate decimal floating point from binary floating point types.  */
+ 
+ #define TYPE_FLAG_DECIMAL (1 << 16)
+ #define TYPE_DECIMAL(t) (TYPE_FLAGS (t) & TYPE_FLAG_DECIMAL)
+ 
  /*  Array bound type.  */
  enum array_bound_type
  {
Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.183
diff -c -p -r1.183 dwarf2read.c
*** dwarf2read.c	1 Aug 2005 04:06:27 -0000	1.183
--- dwarf2read.c	28 Sep 2005 04:32:43 -0000
*************** read_base_type (struct die_info *die, st
*** 4704,4709 ****
--- 4704,4713 ----
  	case DW_ATE_complex_float:
  	  code = TYPE_CODE_COMPLEX;
  	  break;
+         case DW_ATE_decimal_float:
+           code = TYPE_CODE_FLT;
+           type_flags |= TYPE_FLAG_DECIMAL;
+           break;
  	case DW_ATE_float:
  	  code = TYPE_CODE_FLT;
  	  break;
*************** dwarf_base_type (int encoding, int size,
*** 7408,7413 ****
--- 7412,7425 ----
  	  type = dwarf2_fundamental_type (objfile, FT_FLOAT, cu);
  	}
        return type;
+     case DW_ATE_decimal_float:
+       if (size == 16)
+ 	type = dwarf2_fundamental_type (objfile, FT_EXT_PREC_FLOAT, cu);
+       else if (size == 8)
+ 	type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT, cu);
+       else
+ 	type = dwarf2_fundamental_type (objfile, FT_FLOAT, cu);
+       return type;
      case DW_ATE_signed:
        switch (size)
  	{
*************** dwarf_type_encoding_name (unsigned enc)
*** 8248,8253 ****
--- 8260,8267 ----
        return "DW_ATE_boolean";
      case DW_ATE_complex_float:
        return "DW_ATE_complex_float";
+     case DW_ATE_decimal_float:
+       return "DW_ATE_decimal_float";
      case DW_ATE_float:
        return "DW_ATE_float";
      case DW_ATE_signed:
Index: c-exp.y
===================================================================
RCS file: /cvs/src/src/gdb/c-exp.y,v
retrieving revision 1.30
diff -c -p -r1.30 c-exp.y
*** c-exp.y	20 Sep 2005 08:55:55 -0000	1.30
--- c-exp.y	28 Sep 2005 04:32:50 -0000
*************** parse_number (p, len, parsed_float, puti
*** 1080,1085 ****
--- 1080,1096 ----
  
        p[len] = 0;	/* null-terminate the token */
  
+       /* If it ends at "df", "dd" or "dl", take it as type of decimal floating
+          point.  Return STRING for later string-to-dfp conversion.  */
+       if (p[len - 2] == 'd'
+ 	  && (p[len - 1] == 'f' || p[len - 1] == 'd' ||  p[len - 1] == 'l'))
+ 	{
+ 	  p[len - 2] = '\0';
+ 	  yylval.sval.ptr = p;
+ 	  yylval.sval.length = len - 2;
+ 	  return (STRING);
+ 	}
+ 
        if (sizeof (putithere->typed_val_float.dval) <= sizeof (float))
  	num = sscanf (p, "%g%s", (float *) &putithere->typed_val_float.dval,s);
        else if (sizeof (putithere->typed_val_float.dval) <= sizeof (double))
Index: eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.59
diff -c -p -r1.59 eval.c
*** eval.c	20 Sep 2005 06:25:34 -0000	1.59
--- eval.c	28 Sep 2005 04:32:56 -0000
*************** evaluate_subexp_standard (struct type *e
*** 1456,1461 ****
--- 1456,1471 ----
  
      case BINOP_ASSIGN:
        arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ 
+       /* If the type of arg1 is one of decimal floating point, then call
+ 	 value_set_dfp to assign arg2 to arg1.  */
+       if (TYPE_CODE (value_type (arg1)) == TYPE_CODE_FLT
+ 	  && TYPE_DECIMAL (value_type (arg1)))
+ 	{
+ 	  arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ 	  return value_set_dfp (arg1, arg2);
+ 	}
+ 
        arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
  
        /* Do special stuff for HP aCC pointers to members */
Index: valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.161
diff -c -p -r1.161 valops.c
*** valops.c	27 May 2005 04:39:32 -0000	1.161
--- valops.c	28 Sep 2005 04:33:03 -0000
***************
*** 44,49 ****
--- 44,50 ----
  #include "gdb_assert.h"
  #include "cp-support.h"
  #include "observer.h"
+ #include "dfp.h"
  
  extern int overload_debug;
  /* Local functions.  */
*************** value_fetch_lazy (struct value *val)
*** 518,523 ****
--- 519,558 ----
    return 0;
  }
  
+ /* Store the contents of FROMVAL into the location of TOVAL, which is a
+    decimal floating point.  Return a new value with the location of TOVAL
+    and contents of FROMVAL.  */
+ 
+ struct value *
+ value_set_dfp (struct value *toval, struct value *fromval)
+ {
+   struct type *type = value_type (toval);
+   gdb_byte *valaddr = value_contents_raw (toval);
+   char *string = (char *)(value_contents_all (fromval));
+   struct frame_id old_frame;
+   struct frame_info *fi;
+ 
+   /* Since modifying a register can trash the frame chain, and modifying memory
+      can trash the frame cache, we save the old frame and then restore the new
+      frame afterwards.  */
+   old_frame = get_frame_id (deprecated_selected_frame);
+   
+   if (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_DECIMAL (type))
+     {
+       unsigned int len = TYPE_LENGTH (type);
+       CORE_ADDR changed_addr = VALUE_ADDRESS (toval) + value_offset (toval);
+ 
+       decimal_from_string (valaddr, len, string);
+       write_memory (changed_addr, valaddr, len);
+     }
+ 
+   reinit_frame_cache ();
+   fi = frame_find_by_id (old_frame);
+   if (fi != NULL)
+     select_frame (fi);
+ 
+   return toval;
+ }
  
  /* Store the contents of FROMVAL into the location of TOVAL.
     Return a new value with the location of TOVAL and contents of FROMVAL.  */
Index: valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/valprint.c,v
retrieving revision 1.54
diff -c -p -r1.54 valprint.c
*** valprint.c	10 Jun 2005 06:07:32 -0000	1.54
--- valprint.c	28 Sep 2005 04:33:05 -0000
***************
*** 34,39 ****
--- 34,40 ----
  #include "valprint.h"
  #include "floatformat.h"
  #include "doublest.h"
+ #include "dfp.h"
  
  #include <errno.h>
  
*************** print_floating (const gdb_byte *valaddr,
*** 400,405 ****
--- 401,415 ----
    const struct floatformat *fmt = NULL;
    unsigned len = TYPE_LENGTH (type);
  
+   if (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_DECIMAL (type))
+     {
+       char decstr[100];
+ 
+       decimal_to_string (valaddr, len, decstr);
+       fputs_filtered (decstr, stream);
+       return;
+     }
+ 
    /* If it is a floating-point, check for obvious problems.  */
    if (TYPE_CODE (type) == TYPE_CODE_FLT)
      fmt = floatformat_from_type (type);
Index: dfp.h
===================================================================
RCS file: dfp.h
diff -N dfp.h
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- dfp.h	28 Sep 2005 04:33:05 -0000
***************
*** 0 ****
--- 1,103 ----
+ /* Decimal floating point support for GDB.
+ 
+    Copyright 2005 Free Software Foundation, Inc.
+ 
+    Contributed by Cygnus Support, using pieces from other GDB modules.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ 
+ /* Decimal floating point is one of the extension to IEEE 754, which is
+    described in http://grouper.ieee.org/groups/754/revision.html and
+    http://www2.hursley.ibm.com/decimal/.  It completes binary floating
+    point by representing floating point more exactly.  */
+ 
+ /* There is a project intended to add DFP support into GCC, described in
+    http://gcc.gnu.org/wiki/Decimal%20Floating-Point.  This file is intended
+    to add DFP support into GDB.  */
+ 
+ #ifndef DFP_H
+ #define DFP_H
+ #include <string.h>
+ #include <stdio.h>
+ #include <stdint.h>
+ 
+ /* The first byte for Infinity, NaN and sNaN.  */
+ #define DECIMAL_Inf     0x78        /* 0 11110 00 Infinity */
+ #define DECIMAL_NaN     0x7c        /* 0 11111 00 NaN */
+ #define DECIMAL_sNaN    0x7e        /* 0 11111 10 sNaN */
+ 
+ /* Parameters for _Decimal32.  */
+ #define DECIMAL32_Pmax   7            // maximum precision (digits)
+ #define DECIMAL32_Emax   96           // maximum adjusted exponent
+ #define DECIMAL32_Emin  -95           // minimum adjusted exponent
+ #define DECIMAL32_Bias   101          // bias for the exponent
+ 
+ /* Parameters for _Decimal64.  */
+ #define DECIMAL64_Pmax   16           // maximum precision (digits)
+ #define DECIMAL64_Emax   384          // maximum adjusted exponent
+ #define DECIMAL64_Emin  -383          // minimum adjusted exponent
+ #define DECIMAL64_Bias   398          // bias for the exponent
+ 
+ /* Parameters for _Decimal128.  */
+ #define DECIMAL128_Pmax   34          // maximum precision (digits)
+ #define DECIMAL128_Emax   6144        // maximum adjusted exponent
+ #define DECIMAL128_Emin  -6143        // minimum adjusted exponent
+ #define DECIMAL128_Bias   6176        // bias for the exponent
+ 
+ /* The parse errors found in the conversion routine from the string to
+    decimal types (decimal_from_string).  */
+ #define SYNTAX_ERROR 		0x00000001
+ #define COEFF_OUTOFRANGE 	0x00000002
+ #define EXP_OUTOFRANGE 		0x00000004
+ #define INVALID_CHAR 		0x00000008
+ #define DIGIT_EXPECTED 		0x00000010
+ 
+ #define X10(i)  (((i) << 1) + ((i) << 3))
+ #define X100(i) (((i) << 2) + ((i) << 5) + ((i) << 6))
+ 
+ /* Get the sign bit, combinator bits, exponent continuation bits of
+    _Decimal32, _Decimal64 and _Decimal128.  */
+ #define decimalGetSign(d)	((unsigned)(d)[0] >> 7)
+ #define decimalGetComb(d)	(((d)[0] & 0x7c) >> 2)
+ #define decimal32GetExpCon(d)	((((d)[0] & 0x03) << 4) | \
+ 				((unsigned)(d)[1] >> 4))
+ #define decimal64GetExpCon(d)	((((d)[0] & 0x03) << 6) | \
+ 				((unsigned)(d)[1] >> 2))
+ #define decimal128GetExpCon(d)	((((d)[0] & 0x03) << 10) | \
+ 				((unsigned)(d)[1] << 2) | \
+ 				((unsigned)(d)[2] >> 6)) 
+ 
+ /* Set the sign bit and combinator bits.  */
+ #define decimalSetSign(d, b) 	{ (d)[0] |= ((unsigned)(b) << 7);	}
+ #define decimalSetComb(d, b) 	{ (d)[0] |= ((unsigned)(b) << 2);	}
+ 
+ /* Set the exponent continuation bits of _Decimal32, _Decimal64 and 
+    _Decimal128.  */
+ #define decimal32SetExpCon(d, e) { (d)[0] |= (uint8_t)((e) >> 4); \
+ 			           (d)[1] |= (uint8_t)(((e) & 0x0F) << 4);  }
+ #define decimal64SetExpCon(d, e) { (d)[0] |= (uint8_t)((e) >> 6); \
+ 				   (d)[1] |= (uint8_t)(((e) & 0x3F) << 2);  }
+ #define decimal128SetExpCon(d, e) { (d)[0] |= (uint8_t)((e) >> 10); \
+ 				    (d)[1] = (uint8_t)(((e) & 0x03FC) >> 2); \
+ 				    (d)[2] |= (uint8_t)(((e) & 0x03) << 6);  } 
+ 
+ /* The conversion from decimal floating point to string, and reverse.  */
+ extern void decimal_to_string (const uint8_t *, int, char *);
+ extern int decimal_from_string (uint8_t *, int, char *);
+ 
+ #endif
Index: dfp.c
===================================================================
RCS file: dfp.c
diff -N dfp.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- dfp.c	28 Sep 2005 04:33:09 -0000
***************
*** 0 ****
--- 1,874 ----
+ /* Decimal floating point support for GDB.
+ 
+    Copyright 2005 Free Software Foundation, Inc.
+ 
+    Contributed by Cygnus Support, using pieces from other GDB modules.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ 
+ #include "defs.h"
+ #include "dfp.h"
+ #include <ctype.h>
+ 
+ /* The bits composition of decimal32, decimal64 and decimal128.
+    For decimal32: 
+      1 (sign) + 5 (combinator) + 6 (exponent) + 20 (coefficient) = 32 bits
+    For decimal64:
+      1 (sign) + 5 (combinator) + 8 (exponent) + 50 (coefficient) = 64 bits
+    For decimal128:
+      1 (sign) + 5 (combinator) + 12 (exponent) + 110 (coefficient) = 128 bits
+ 
+    For more detailed description, refer to the decimal encoding specification,
+    described in http://www2.hursley.ibm.com/decimal/decbits.html.  */
+ 
+ static const int bits[3][4] = { { 1, 5, 6, 20 },
+ 				{ 1, 5, 8, 50 },
+ 				{ 1, 5, 12, 110 } };
+ 
+ /* The mapping table from Densely Packed Decimal (DPD) to/from Binary.  Refer 
+    to http://www2.hursley.ibm.com/decimal/decbits.html for more detail.  */
+ 
+ const uint16_t DPD2BIN[1024]={    0,    1,    2,    3,    4,    5,    6,    7,
+     8,    9,   80,   81,  800,  801,  880,  881,   10,   11,   12,   13,   14,
+    15,   16,   17,   18,   19,   90,   91,  810,  811,  890,  891,   20,   21,
+    22,   23,   24,   25,   26,   27,   28,   29,   82,   83,  820,  821,  808,
+   809,   30,   31,   32,   33,   34,   35,   36,   37,   38,   39,   92,   93,
+   830,  831,  818,  819,   40,   41,   42,   43,   44,   45,   46,   47,   48,
+    49,   84,   85,  840,  841,   88,   89,   50,   51,   52,   53,   54,   55,
+    56,   57,   58,   59,   94,   95,  850,  851,   98,   99,   60,   61,   62,
+    63,   64,   65,   66,   67,   68,   69,   86,   87,  860,  861,  888,  889,
+    70,   71,   72,   73,   74,   75,   76,   77,   78,   79,   96,   97,  870,
+   871,  898,  899,  100,  101,  102,  103,  104,  105,  106,  107,  108,  109,
+   180,  181,  900,  901,  980,  981,  110,  111,  112,  113,  114,  115,  116,
+   117,  118,  119,  190,  191,  910,  911,  990,  991,  120,  121,  122,  123,
+   124,  125,  126,  127,  128,  129,  182,  183,  920,  921,  908,  909,  130,
+   131,  132,  133,  134,  135,  136,  137,  138,  139,  192,  193,  930,  931,
+   918,  919,  140,  141,  142,  143,  144,  145,  146,  147,  148,  149,  184,
+   185,  940,  941,  188,  189,  150,  151,  152,  153,  154,  155,  156,  157,
+   158,  159,  194,  195,  950,  951,  198,  199,  160,  161,  162,  163,  164,
+   165,  166,  167,  168,  169,  186,  187,  960,  961,  988,  989,  170,  171,
+   172,  173,  174,  175,  176,  177,  178,  179,  196,  197,  970,  971,  998,
+   999,  200,  201,  202,  203,  204,  205,  206,  207,  208,  209,  280,  281,
+   802,  803,  882,  883,  210,  211,  212,  213,  214,  215,  216,  217,  218,
+   219,  290,  291,  812,  813,  892,  893,  220,  221,  222,  223,  224,  225,
+   226,  227,  228,  229,  282,  283,  822,  823,  828,  829,  230,  231,  232,
+   233,  234,  235,  236,  237,  238,  239,  292,  293,  832,  833,  838,  839,
+   240,  241,  242,  243,  244,  245,  246,  247,  248,  249,  284,  285,  842,
+   843,  288,  289,  250,  251,  252,  253,  254,  255,  256,  257,  258,  259,
+   294,  295,  852,  853,  298,  299,  260,  261,  262,  263,  264,  265,  266,
+   267,  268,  269,  286,  287,  862,  863,  888,  889,  270,  271,  272,  273,
+   274,  275,  276,  277,  278,  279,  296,  297,  872,  873,  898,  899,  300,
+   301,  302,  303,  304,  305,  306,  307,  308,  309,  380,  381,  902,  903,
+   982,  983,  310,  311,  312,  313,  314,  315,  316,  317,  318,  319,  390,
+   391,  912,  913,  992,  993,  320,  321,  322,  323,  324,  325,  326,  327,
+   328,  329,  382,  383,  922,  923,  928,  929,  330,  331,  332,  333,  334,
+   335,  336,  337,  338,  339,  392,  393,  932,  933,  938,  939,  340,  341,
+   342,  343,  344,  345,  346,  347,  348,  349,  384,  385,  942,  943,  388,
+   389,  350,  351,  352,  353,  354,  355,  356,  357,  358,  359,  394,  395,
+   952,  953,  398,  399,  360,  361,  362,  363,  364,  365,  366,  367,  368,
+   369,  386,  387,  962,  963,  988,  989,  370,  371,  372,  373,  374,  375,
+   376,  377,  378,  379,  396,  397,  972,  973,  998,  999,  400,  401,  402,
+   403,  404,  405,  406,  407,  408,  409,  480,  481,  804,  805,  884,  885,
+   410,  411,  412,  413,  414,  415,  416,  417,  418,  419,  490,  491,  814,
+   815,  894,  895,  420,  421,  422,  423,  424,  425,  426,  427,  428,  429,
+   482,  483,  824,  825,  848,  849,  430,  431,  432,  433,  434,  435,  436,
+   437,  438,  439,  492,  493,  834,  835,  858,  859,  440,  441,  442,  443,
+   444,  445,  446,  447,  448,  449,  484,  485,  844,  845,  488,  489,  450,
+   451,  452,  453,  454,  455,  456,  457,  458,  459,  494,  495,  854,  855,
+   498,  499,  460,  461,  462,  463,  464,  465,  466,  467,  468,  469,  486,
+   487,  864,  865,  888,  889,  470,  471,  472,  473,  474,  475,  476,  477,
+   478,  479,  496,  497,  874,  875,  898,  899,  500,  501,  502,  503,  504,
+   505,  506,  507,  508,  509,  580,  581,  904,  905,  984,  985,  510,  511,
+   512,  513,  514,  515,  516,  517,  518,  519,  590,  591,  914,  915,  994,
+   995,  520,  521,  522,  523,  524,  525,  526,  527,  528,  529,  582,  583,
+   924,  925,  948,  949,  530,  531,  532,  533,  534,  535,  536,  537,  538,
+   539,  592,  593,  934,  935,  958,  959,  540,  541,  542,  543,  544,  545,
+   546,  547,  548,  549,  584,  585,  944,  945,  588,  589,  550,  551,  552,
+   553,  554,  555,  556,  557,  558,  559,  594,  595,  954,  955,  598,  599,
+   560,  561,  562,  563,  564,  565,  566,  567,  568,  569,  586,  587,  964,
+   965,  988,  989,  570,  571,  572,  573,  574,  575,  576,  577,  578,  579,
+   596,  597,  974,  975,  998,  999,  600,  601,  602,  603,  604,  605,  606,
+   607,  608,  609,  680,  681,  806,  807,  886,  887,  610,  611,  612,  613,
+   614,  615,  616,  617,  618,  619,  690,  691,  816,  817,  896,  897,  620,
+   621,  622,  623,  624,  625,  626,  627,  628,  629,  682,  683,  826,  827,
+   868,  869,  630,  631,  632,  633,  634,  635,  636,  637,  638,  639,  692,
+   693,  836,  837,  878,  879,  640,  641,  642,  643,  644,  645,  646,  647,
+   648,  649,  684,  685,  846,  847,  688,  689,  650,  651,  652,  653,  654,
+   655,  656,  657,  658,  659,  694,  695,  856,  857,  698,  699,  660,  661,
+   662,  663,  664,  665,  666,  667,  668,  669,  686,  687,  866,  867,  888,
+   889,  670,  671,  672,  673,  674,  675,  676,  677,  678,  679,  696,  697,
+   876,  877,  898,  899,  700,  701,  702,  703,  704,  705,  706,  707,  708,
+   709,  780,  781,  906,  907,  986,  987,  710,  711,  712,  713,  714,  715,
+   716,  717,  718,  719,  790,  791,  916,  917,  996,  997,  720,  721,  722,
+   723,  724,  725,  726,  727,  728,  729,  782,  783,  926,  927,  968,  969,
+   730,  731,  732,  733,  734,  735,  736,  737,  738,  739,  792,  793,  936,
+   937,  978,  979,  740,  741,  742,  743,  744,  745,  746,  747,  748,  749,
+   784,  785,  946,  947,  788,  789,  750,  751,  752,  753,  754,  755,  756,
+   757,  758,  759,  794,  795,  956,  957,  798,  799,  760,  761,  762,  763,
+   764,  765,  766,  767,  768,  769,  786,  787,  966,  967,  988,  989,  770,
+   771,  772,  773,  774,  775,  776,  777,  778,  779,  796,  797,  976,  977,
+   998,  999};
+ 
+ static uint16_t BIN2DPD[1000]={    0,    1,    2,    3,    4,    5,    6,    7,
+     8,    9,   16,   17,   18,   19,   20,   21,   22,   23,   24,   25,   32,
+    33,   34,   35,   36,   37,   38,   39,   40,   41,   48,   49,   50,   51,
+    52,   53,   54,   55,   56,   57,   64,   65,   66,   67,   68,   69,   70,
+    71,   72,   73,   80,   81,   82,   83,   84,   85,   86,   87,   88,   89,
+    96,   97,   98,   99,  100,  101,  102,  103,  104,  105,  112,  113,  114,
+   115,  116,  117,  118,  119,  120,  121,   10,   11,   42,   43,   74,   75,
+   106,  107,   78,   79,   26,   27,   58,   59,   90,   91,  122,  123,   94,
+    95,  128,  129,  130,  131,  132,  133,  134,  135,  136,  137,  144,  145,
+   146,  147,  148,  149,  150,  151,  152,  153,  160,  161,  162,  163,  164,
+   165,  166,  167,  168,  169,  176,  177,  178,  179,  180,  181,  182,  183,
+   184,  185,  192,  193,  194,  195,  196,  197,  198,  199,  200,  201,  208,
+   209,  210,  211,  212,  213,  214,  215,  216,  217,  224,  225,  226,  227,
+   228,  229,  230,  231,  232,  233,  240,  241,  242,  243,  244,  245,  246,
+   247,  248,  249,  138,  139,  170,  171,  202,  203,  234,  235,  206,  207,
+   154,  155,  186,  187,  218,  219,  250,  251,  222,  223,  256,  257,  258,
+   259,  260,  261,  262,  263,  264,  265,  272,  273,  274,  275,  276,  277,
+   278,  279,  280,  281,  288,  289,  290,  291,  292,  293,  294,  295,  296,
+   297,  304,  305,  306,  307,  308,  309,  310,  311,  312,  313,  320,  321,
+   322,  323,  324,  325,  326,  327,  328,  329,  336,  337,  338,  339,  340,
+   341,  342,  343,  344,  345,  352,  353,  354,  355,  356,  357,  358,  359,
+   360,  361,  368,  369,  370,  371,  372,  373,  374,  375,  376,  377,  266,
+   267,  298,  299,  330,  331,  362,  363,  334,  335,  282,  283,  314,  315,
+   346,  347,  378,  379,  350,  351,  384,  385,  386,  387,  388,  389,  390,
+   391,  392,  393,  400,  401,  402,  403,  404,  405,  406,  407,  408,  409,
+   416,  417,  418,  419,  420,  421,  422,  423,  424,  425,  432,  433,  434,
+   435,  436,  437,  438,  439,  440,  441,  448,  449,  450,  451,  452,  453,
+   454,  455,  456,  457,  464,  465,  466,  467,  468,  469,  470,  471,  472,
+   473,  480,  481,  482,  483,  484,  485,  486,  487,  488,  489,  496,  497,
+   498,  499,  500,  501,  502,  503,  504,  505,  394,  395,  426,  427,  458,
+   459,  490,  491,  462,  463,  410,  411,  442,  443,  474,  475,  506,  507,
+   478,  479,  512,  513,  514,  515,  516,  517,  518,  519,  520,  521,  528,
+   529,  530,  531,  532,  533,  534,  535,  536,  537,  544,  545,  546,  547,
+   548,  549,  550,  551,  552,  553,  560,  561,  562,  563,  564,  565,  566,
+   567,  568,  569,  576,  577,  578,  579,  580,  581,  582,  583,  584,  585,
+   592,  593,  594,  595,  596,  597,  598,  599,  600,  601,  608,  609,  610,
+   611,  612,  613,  614,  615,  616,  617,  624,  625,  626,  627,  628,  629,
+   630,  631,  632,  633,  522,  523,  554,  555,  586,  587,  618,  619,  590,
+   591,  538,  539,  570,  571,  602,  603,  634,  635,  606,  607,  640,  641,
+   642,  643,  644,  645,  646,  647,  648,  649,  656,  657,  658,  659,  660,
+   661,  662,  663,  664,  665,  672,  673,  674,  675,  676,  677,  678,  679,
+   680,  681,  688,  689,  690,  691,  692,  693,  694,  695,  696,  697,  704,
+   705,  706,  707,  708,  709,  710,  711,  712,  713,  720,  721,  722,  723,
+   724,  725,  726,  727,  728,  729,  736,  737,  738,  739,  740,  741,  742,
+   743,  744,  745,  752,  753,  754,  755,  756,  757,  758,  759,  760,  761,
+   650,  651,  682,  683,  714,  715,  746,  747,  718,  719,  666,  667,  698,
+   699,  730,  731,  762,  763,  734,  735,  768,  769,  770,  771,  772,  773,
+   774,  775,  776,  777,  784,  785,  786,  787,  788,  789,  790,  791,  792,
+   793,  800,  801,  802,  803,  804,  805,  806,  807,  808,  809,  816,  817,
+   818,  819,  820,  821,  822,  823,  824,  825,  832,  833,  834,  835,  836,
+   837,  838,  839,  840,  841,  848,  849,  850,  851,  852,  853,  854,  855,
+   856,  857,  864,  865,  866,  867,  868,  869,  870,  871,  872,  873,  880,
+   881,  882,  883,  884,  885,  886,  887,  888,  889,  778,  779,  810,  811,
+   842,  843,  874,  875,  846,  847,  794,  795,  826,  827,  858,  859,  890,
+   891,  862,  863,  896,  897,  898,  899,  900,  901,  902,  903,  904,  905,
+   912,  913,  914,  915,  916,  917,  918,  919,  920,  921,  928,  929,  930,
+   931,  932,  933,  934,  935,  936,  937,  944,  945,  946,  947,  948,  949,
+   950,  951,  952,  953,  960,  961,  962,  963,  964,  965,  966,  967,  968,
+   969,  976,  977,  978,  979,  980,  981,  982,  983,  984,  985,  992,  993,
+   994,  995,  996,  997,  998,  999, 1000, 1001, 1008, 1009, 1010, 1011, 1012,
+  1013, 1014, 1015, 1016, 1017,  906,  907,  938,  939,  970,  971, 1002, 1003,
+   974,  975,  922,  923,  954,  955,  986,  987, 1018, 1019,  990,  991,   12,
+    13,  268,  269,  524,  525,  780,  781,   46,   47,   28,   29,  284,  285,
+   540,  541,  796,  797,   62,   63,   44,   45,  300,  301,  556,  557,  812,
+   813,  302,  303,   60,   61,  316,  317,  572,  573,  828,  829,  318,  319,
+    76,   77,  332,  333,  588,  589,  844,  845,  558,  559,   92,   93,  348,
+   349,  604,  605,  860,  861,  574,  575,  108,  109,  364,  365,  620,  621,
+   876,  877,  814,  815,  124,  125,  380,  381,  636,  637,  892,  893,  830,
+   831,   14,   15,  270,  271,  526,  527,  782,  783,  110,  111,   30,   31,
+   286,  287,  542,  543,  798,  799,  126,  127,  140,  141,  396,  397,  652,
+   653,  908,  909,  174,  175,  156,  157,  412,  413,  668,  669,  924,  925,
+   190,  191,  172,  173,  428,  429,  684,  685,  940,  941,  430,  431,  188,
+   189,  444,  445,  700,  701,  956,  957,  446,  447,  204,  205,  460,  461,
+   716,  717,  972,  973,  686,  687,  220,  221,  476,  477,  732,  733,  988,
+   989,  702,  703,  236,  237,  492,  493,  748,  749, 1004, 1005,  942,  943,
+   252,  253,  508,  509,  764,  765, 1020, 1021,  958,  959,  142,  143,  398,
+   399,  654,  655,  910,  911,  238,  239,  158,  159,  414,  415,  670,  671,
+   926,  927,  254,  255 };
+ 
+ const uint8_t DPDMOD[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
+ const uint8_t POWER[3] = { 100, 10, 1};
+ 
+ static int remove_trailing_zeros (char *, char **);
+ static void string_error (int status, char current);
+ 
+ /* Convert deciaml type to its string representation.  LEN is the length
+    of the decimal type, 4 bytes for decimal32, 8 bytes for decimal64 and
+    16 bytes for decimal128.  */
+ void
+ decimal_to_string (const uint8_t *dec, int len, char *s)
+ {
+   int i;
+   uint8_t sign = decimalGetSign (dec);	/* The signedness of DEC.  */
+   uint8_t comb = decimalGetComb (dec);	/* Combinator, 5 bits.  */
+   uint8_t top = dec[0] & 0x7f;		/* Top byte, less sign bit.  */
+   int bindex;
+   char dfp_suffix[3];
+   uint8_t msd;		/* The most significant digit of coefficient.  */
+   int16_t exp;		/* Exponent, a signed number.  */
+   uint8_t line, column;
+   char cfirst[128];	/* The first character of coefficient.  */ 
+   char *clast = cfirst; /* The last character of coefficient.  */
+   int start = 0;	/* Found the first non-zero in the coefficient?  */
+   int cdigits;		/* The number of the digits in the coefficient.  */
+ 
+   /* Initialize some length-related data.  */
+   switch (len)
+     {
+     case 4:
+       bindex = 0;
+       strncpy (dfp_suffix, "df", 3);
+       exp = decimal32GetExpCon (dec) - DECIMAL32_Bias;
+       break;
+     case 8:
+       bindex = 1;
+       strncpy (dfp_suffix, "dd", 3);
+       exp = decimal64GetExpCon (dec) - DECIMAL64_Bias;
+       break;
+     case 16:
+       bindex = 2;
+       strncpy (dfp_suffix, "dl", 3);
+       exp = decimal128GetExpCon (dec) - DECIMAL128_Bias;
+       break;
+     default:
+       error ("We don't support decimal number of %d bytes yet.", len);
+     }
+ 
+   if (top >= DECIMAL_sNaN)
+     {
+       if (sign == 1)
+ 	strcpy (s, "-sNaN");
+       else
+ 	strcpy (s, "sNaN");
+       return;
+     }
+ 
+   if (top >= DECIMAL_NaN)
+     {
+       if (sign == 1)
+ 	strcpy (s, "-NaN");
+       else
+ 	strcpy (s, "NaN");
+       return;
+     }
+ 
+   if (top >= DECIMAL_Inf)
+     {
+       if (sign == 1)
+ 	strcpy (s, "-Infinity");
+       else
+ 	strcpy (s, "Infinity");
+       return;
+     }
+ 
+   /* This decimal is a finite number.  We try to get the MSD of the 
+      coefficient and the exponent first.  */
+   if (comb >= 0x18)
+     {
+       msd = 8 + (comb & 0x01);
+       exp += (comb & 0x06) << (bits[bindex][2] - 1);
+     }
+   else
+     {
+       msd = comb & 0x07;
+       exp += (comb & 0x18) << (bits[bindex][2] - 3);
+     }
+ 
+   /* From here on, we will try to get the string representation of the 
+      coefficient.  */
+   if (msd)
+     {
+       /* If MSD is non-zero, add it into coeff and set the start flag.  */
+       sprintf (clast, "%d", msd);
+       clast++;
+       start = 1;
+     }
+ 
+   /* We first get the starting position (line and column) of the coefficient.
+      Then get a group of 10 bits, transfer it to a unsigned short (dpdigits),
+      and get its corresponsing 3-digits representation (bin).  And then we
+      will add it into coeff and advance 10 bits to another group of 
+      10-bits until we get to the end.  In this process, we need to adapt the
+      string representaion of each 3-digits according to its real digit number
+      and the start flag.  */
+   line = (bits[bindex][0] + bits[bindex][1] + bits[bindex][2]) / 8;
+   column = (bits[bindex][0] + bits[bindex][1] + bits[bindex][2]) % 8;
+   for (i = 0; i < bits[bindex][3] / 10; i++)
+     {
+       uint16_t dpdigits = ((dec[line] & DPDMOD [7 - column]) << (2 + column))
+ 			  + (dec[line + 1] >> (6 - column));
+       uint16_t bin = DPD2BIN[dpdigits];
+ 
+       line++;
+       column += 2;
+       if (column == 8)
+ 	{
+ 	  column = 0;
+ 	  line++;
+ 	}
+ 
+       if (bin)
+ 	{
+ 	  if (!start)
+ 	    {
+ 	      sprintf (clast, "%d", bin);
+ 	      if (bin < 10)
+ 		clast += 1;
+ 	      else if (bin < 100)
+ 		clast += 2;
+ 	      else
+ 		clast += 3;
+ 	      start = 1;
+ 	    }
+ 	  else
+ 	    {
+ 	      if (bin < 10)
+ 		sprintf (clast, "00%d", bin);
+ 	      else if (bin < 100)
+ 		sprintf (clast, "0%d", bin);
+ 	      else
+ 		sprintf (clast, "%d", bin);
+ 	      clast += 3;
+ 	    }
+ 	}
+       else
+ 	{
+ 	  if (start)
+ 	    {
+ 	      sprintf(clast, "000");
+ 	      clast += 3;
+ 	    }
+ 	  continue;
+ 	}
+     }
+ 
+   /* If start still equals 0, then DEC is 0.  After adding a trailing '.'
+      and suffix, we can return to calling function at this point.  */
+   if (start == 0)
+     {
+       sprintf(s, "0.%s", dfp_suffix);
+       return;
+     }
+ 
+   exp += remove_trailing_zeros (cfirst, &clast);
+ 
+   /* If exp quals 0, then we already get DEC's string representation.  Add
+      a trailing '.' and suffix, and return.  */
+   if (exp == 0)
+     {
+       if (sign)
+ 	sprintf (s, "-%s.%s", cfirst, dfp_suffix);
+       else
+ 	sprintf (s, "%s.%s", cfirst, dfp_suffix);
+       return;
+     }
+ 
+   cdigits = (int)(clast - cfirst);
+   if (exp > 0  || (exp + cdigits) < -5)
+     {
+       char temps[128];		/* A temp string. */
+       char *c = temps;
+       char *digit;
+ 
+       if (sign)
+ 	{
+ 	  sprintf (c, "-");
+ 	  c++;
+ 	}
+ 
+       exp += cdigits - 1;
+       *c++ = *cfirst;
+       *c++ = '.';
+       for (digit = cfirst + 1; ;c++, digit++)
+ 	{
+ 	  if (digit == clast )
+ 	    break;
+ 	  *c = *digit;
+ 	}
+ 
+       if (exp > 0)
+ 	sprintf (c, "E+%d", exp);
+       else if (exp < 0)
+ 	sprintf (c, "E%d", exp);
+       else
+ 	*c = '\0';
+ 
+       sprintf (s, "%s%s", temps, dfp_suffix);
+     }
+   else
+     {
+       char temps[128];	/* A temp string.  */
+       char *c = temps;
+       char *digit = cfirst;
+ 
+       if (sign)
+         {
+           sprintf (c, "-");
+           c++;
+         }
+ 
+       /* Digits left to dot */
+       if ((cdigits + exp) > 0)
+         {
+           exp = cdigits + exp;
+           for (i = 0; i < exp; i++)
+             *c++ = *digit++;
+           sprintf (c, ".");
+           c++;
+         }
+       else
+         {
+           exp = -(exp + cdigits) + 1;
+           sprintf (c, "0.");
+           c += 2;
+           for (i = 1; i < exp; i++)
+             {
+               sprintf (c,"0");
+               c++;
+             }
+         }
+ 
+       for(;;c++, digit++)
+         {
+           if ( digit == clast )
+             break;
+           *c = *digit;
+         }
+       /* Trail temps with '\0'.  */
+       *c = '\0';
+       sprintf (s, "%s%s",temps, dfp_suffix);
+     }
+   return;
+ }
+ 
+ static int
+ remove_trailing_zeros (char *cfirst, char **pclast)
+ {
+   char *digit = *pclast - 1;
+   int trailing_zeros = 0;
+ 
+   while (digit >= cfirst)
+     if (*digit-- == '0')
+       trailing_zeros++;
+     else
+       break;
+ 
+   *pclast = *pclast - trailing_zeros;
+   **pclast = '\0';
+   return trailing_zeros;
+ }
+ 
+ int
+ decStrEq (const char *str1, const char *str2)
+ {
+   for (;;str1++, str2++)
+     {
+       if (*str1 == *str2)
+ 	{
+ 	  if (*str1 == '\0')
+ 	    break;
+ 	}
+       else
+ 	{
+ 	  if (tolower(*str1) != tolower(*str2))
+ 	    return 0;
+ 	}
+     }
+ 
+   return 1;
+ }
+ 
+ int
+ decimal_from_string (uint8_t *dec, int len, char *string)
+ {
+   int status = 0;
+   int i;
+   int sign = 0;                 /* The signedness of DEC.  */
+   int exp = 0;                  /* Exponent, a signed number.  */
+   int indicator = 0;		/* To indicate the type of the DEC.  */
+   int isZero = 0;               /* Is cofficient 0?  */
+   int lpad, rpad;               /* The number of left or right padding '0'.  */
+   const char *dotchar = NULL;   /* Where dot was found.  */
+   const char *cfirst;           /* The first digit of coefficient.  */
+   const char *clast = NULL;     /* The last digit of coefficient.  */
+   int   d=0;               	/* The count of digits in the coefficient.  */
+ 
+   int bindex;
+   int dfp_pmax, dfp_emax, dfp_emin, dfp_bias;
+ 
+   /* Initializing the dec array and type-related variables.  */
+ 
+   for (i = 0; i < len; i++)
+     dec[i] = 0;
+ 
+   switch (len)
+     {
+     case 4:
+       bindex = 0;
+       dfp_pmax = DECIMAL32_Pmax;
+       dfp_emax = DECIMAL32_Emax;
+       dfp_emin = DECIMAL32_Emin;
+       dfp_bias = DECIMAL32_Bias;
+       break;
+     case 8:
+       bindex = 1;
+       dfp_pmax = DECIMAL64_Pmax;
+       dfp_emax = DECIMAL64_Emax;
+       dfp_emin = DECIMAL64_Emin;
+       dfp_bias = DECIMAL64_Bias;
+       break;
+     case 16:
+       bindex = 2;
+       dfp_pmax = DECIMAL128_Pmax;
+       dfp_emax = DECIMAL128_Emax;
+       dfp_emin = DECIMAL128_Emin;
+       dfp_bias = DECIMAL128_Bias;
+       break;
+     default:
+       error ("There is no decimal floating point of length %d", len);
+     }
+ 
+   do
+     {
+       const char *c = string; 
+ 
+       /* Handle leading '-' or '+'.  */
+       if (*c == '-')
+ 	sign = 1;
+       if (*c == '-' || *c == '+')
+ 	c++;
+ 
+       /* We're at the start of the number.  */
+       cfirst = c;
+       for (;; c++)
+ 	{
+ 	  if (*c >= '0' && *c <= '9')
+ 	    { 
+ 	      /* Test for decimal digit.  */
+ 	      clast = c;
+ 	      d++;			/* Count of real digits.  */
+ 	      continue;			/* Still in decimal part.  */
+ 	    }
+ 	  if (*c != '.')
+ 	     break;			/* Done with decimal part.  */
+ 
+ 	  /* Find another dot, break and report error.  */
+ 	  if (dotchar != NULL)
+ 	    {
+ 	      clast = NULL;
+ 	      break;
+ 	    } 
+ 	  dotchar = c;			/* The offset into decimal part */
+ 	}
+ 
+       /* No decimal digits found, maybe Infinity or NaNs.  */
+       if (clast == NULL)
+ 	{
+ 	  if (decStrEq (c, "Infinity") || decStrEq (c, "Inf"))
+ 	    {
+ 	      indicator = DECIMAL_Inf;
+ 	      break;			/* All done.  */
+ 	    }
+ 	  else
+ 	    { /* A NaN expected. */
+ 	      status = SYNTAX_ERROR;		/* Assume the worst.  */
+ 	      indicator = DECIMAL_NaN;		/* Assume simple NaN.  */
+ 
+ 	      /* If c begins with 's' or 'S', it might be "sNaN".  */
+ 	      if (*c == 's' || *c == 'S')
+ 		{
+ 		  c++;
+ 		  indicator = DECIMAL_sNaN;
+ 		}
+ 	      /* Check caseless "NaN".  */
+ 	      if (!strcasecmp (c, "NaN"))
+ 		c += 3;
+ 	      else
+ 		string_error (INVALID_CHAR, *c);
+ 
+ 	      /* Skip leading 0s.  */
+ 	      for (cfirst = c; *cfirst == '0';)
+ 		cfirst++;
+ 	      if (*cfirst == '\0')
+ 		{ /* "NaN" or "sNaN", maybe with all 0s */
+ 		  status = 0;                   /* It's good.  */
+ 		  break;
+ 		}
+ 
+ 	      /* Something other than 0s; setup clast and d as usual.  */
+ 	      for (c = cfirst;; c++, d++)
+ 		{
+ 		  if (*c < '0' || *c > '9')
+ 		    break; 			/* Test for Arabic digit.  */
+ 		  clast = c;
+ 		}
+ 
+ 	      /* If not all digits, report error and exit.  */
+ 	      if (*c != '\0')
+ 		string_error (INVALID_CHAR, *c);
+ 
+ 	      /* Good; set status to ok.  */
+ 	      status = 0;
+ 	    }
+ 	}
+ 
+       /* If it is not at the end yet, we need to see whether it is the 
+ 	 exponent part.  */
+       if (*c != '\0')
+ 	{
+ 	  int esign = 0;
+ 	  const char *firstexp;	/* The first significant exponent digit.  */
+ 
+ 	  if (*c != 'e' && *c != 'E')
+ 	    string_error (INVALID_CHAR, *c);
+ 
+ 	  /* Found 'e' or 'E', process explicit exponent.  */
+ 	  c++;
+ 	  if (*c == '-')
+ 	    {
+ 	      esign = 1;
+ 	      c++;
+ 	    }
+ 	  else if (*c == '+')
+ 	    c++;
+ 	  
+ 	  if (*c == '\0')
+ 	    string_error (DIGIT_EXPECTED, *(c - 1));
+ 
+ 	  /* Strip insignificant zeros.  */
+ 	  for (; *c == '0' && *(c+1) != '\0';)
+ 	    c++;  
+ 
+ 	  firstexp = c;		/* Save exponent digit place.  */
+ 	  for (; ;c++)
+ 	    {
+ 	      if (*c < '0' || *c > '9')
+ 		break;    /* Not a digit.  */
+ 	      exp = X10 (exp) + (int)*c - (int)'0';
+ 	    }
+ 	  /* If it doesn't end on '\0', report the error.  */
+ 	  if (*c != '\0')
+ 	    string_error (INVALID_CHAR, *c);
+ 
+ 	  if (c - firstexp + 1 > 9)
+ 	    string_error (EXP_OUTOFRANGE, *c);
+ 
+ 	  if (esign)
+ 	    exp = -exp;
+ 	}
+ 
+       /* Handle decimal point... */
+       if (dotchar != NULL && dotchar < clast)
+ 	exp = exp - (clast - dotchar);
+ 
+       /* Strip leading zeros/dot (leave final if all 0's).  */
+       for (c = cfirst; c < clast; c++)
+ 	{
+ 	  if (*c == '0')
+ 	    d--;		/* 0 stripped.  */
+ 	  else if (*c != '.')
+ 	    break;
+ 	  cfirst++;		/* Step past leader.  */
+ 	}
+ 
+       /* Get the count of padding zeros and the value of exponent.  And
+ 	 if there are any out of range, report error.  */
+       rpad = 0;
+       if (d > dfp_pmax)
+ 	string_error (COEFF_OUTOFRANGE, 0);
+       else if (exp < (dfp_emin - dfp_pmax + 1) || exp > (dfp_emax - d +1))
+ 	string_error (EXP_OUTOFRANGE, 0);
+       else if (exp > (dfp_emax - dfp_pmax + 1))
+ 	{
+ 	  rpad += exp - (dfp_emax - dfp_pmax + 1);
+ 	  exp = dfp_emax - dfp_pmax + 1 + dfp_bias;
+ 	  lpad = dfp_pmax - d - rpad; 
+ 	}
+       else
+ 	{
+ 	  lpad = dfp_pmax - d;
+ 	  exp += dfp_bias;
+ 	} 
+ 
+     } while (0);
+ 
+   /* If status non-zero, there must be some error in the input string.  */
+ 
+   if (status)
+     string_error (status, 0);
+ 
+   /* Begin to transfer the string representation to decimal type.  */
+ 
+   if (sign)
+     decimalSetSign (dec, sign);
+ 
+   if (!indicator)
+     { 
+       char cc[128];	/* The string of coefficient continuation.  */
+       char *s = cc;
+       const char *c;
+       uint8_t comb;	/* Combinator, 5 bits.  */
+       uint8_t msd;	/* The most significant digit of coefficient.  */
+       uint8_t line, column;
+  
+       /* It is a finite number, we need to get MSD cofficient first.  */
+       if (lpad > 0)
+ 	{
+ 	  msd = 0;
+ 	  lpad -= 1;
+ 	}
+       else
+ 	{
+ 	  msd = *cfirst - '0';
+ 	  if (cfirst == clast)
+ 	    {
+ 	      cfirst = NULL;
+ 	    }
+ 	  else
+ 	    cfirst++;
+ 	}
+       if (msd == 0)
+ 	isZero = 1;
+ 
+       /* Set combinator bits.  */
+       if (msd >= 8)
+ 	comb = (msd & 0x1) + (((exp >> bits[bindex][2]) & 0x3) << 1) + 0x18;
+       else
+ 	comb = (msd & 0x7 ) + (((exp >> bits[bindex][2]) & 0x3) << 3);
+       decimalSetComb (dec, comb);
+ 
+       /* Set exponent continuation bits.  */
+       if (len == 4)
+ 	{
+ 	  exp &= 0x3F;
+ 	  decimal32SetExpCon (dec, exp);
+ 	}
+       if (len == 8)
+ 	{
+ 	  exp &= 0xFF;
+ 	  decimal64SetExpCon (dec, exp);
+ 	}
+       if (len == 16)
+ 	{
+ 	  exp &= 0x0FFF;
+ 	  decimal128SetExpCon (dec, exp);
+ 	}
+ 
+       /* Get the clean coefficient continuation string first.  */
+ 
+       while (lpad--)
+ 	*s++ = '0';
+ 
+       for (c = cfirst; c != NULL; c++)
+ 	{
+ 	  if (*c == '.')
+ 	    {
+ 	      if (c != clast)
+ 		continue;
+ 
+ 	      break;
+ 	    }
+ 	  *s = *c;
+ 	  s++;
+ 	  if (isZero && (*c != '0'))
+ 	    isZero = 0;
+ 	  if (c == clast)
+ 	    break;
+ 	}
+ 
+       while (rpad--)
+ 	*s++ = '0';
+ 
+       *s = '\0';
+ 
+       /* Then try to set these coefficient continuation bits in the resulting
+ 	 decimal variable.  */
+ 
+       line = (bits[bindex][0] + bits[bindex][1] + bits[bindex][2]) / 8;
+       column = (bits[bindex][0] + bits[bindex][1] + bits[bindex][2]) % 8;
+       s = cc;
+ 
+       for (i = 0; i < bits[bindex][3] / 10; i++)
+         {
+ 	  int j; 
+           uint16_t dpd, bin = 0;
+ 
+ 	  /* Firstly, get bin from cc string.  */
+ 	  for (j = 0; j < 3; j++)
+ 	    {
+ 	      bin += (*s - '0') * POWER[j];
+ 	      s++;
+ 	    }
+ 
+ 	  /* Then, map bin to DPD.  */
+ 	  dpd = BIN2DPD[bin];
+ 
+ 	  /* Last, set dec array using what we just got above.  */
+ 	  dec[line] |= (dpd >> (2+column));
+ 	  dec[line+1] |= ((dpd & DPDMOD[1+column]) << (6-column));
+ 
+ 	  /* Go on to the next 10-bits group.  */
+ 	  line++;
+ 	  column += 2;
+ 	  if (column == 8)
+ 	    {
+ 	      column = 0;
+ 	      line++;
+ 	    }
+ 	}
+     }
+   else
+     { /* It is Inf, sNaN or qNaN.  */ 
+       uint8_t comb;
+ 
+       if (indicator == DECIMAL_Inf)
+ 	{
+ 	  comb = 0x1E;
+ 	  decimalSetComb (dec, comb);
+ 	}
+       else
+ 	{
+ 	  comb = 0x1F;
+ 	  decimalSetComb (dec, comb);
+ 	  if (indicator == DECIMAL_sNaN)
+ 	    dec[0] |= 0x2;
+ 	}
+     }
+ 
+   return status;
+ }
+ 
+ static void
+ string_error (int status, char current)
+ {
+   switch (status)
+     {
+     case COEFF_OUTOFRANGE:
+       error ("The coefficient is out of range.");
+     case EXP_OUTOFRANGE:
+       error ("The exponent is out of range.");
+     case INVALID_CHAR:
+       error ("Invalid char found, near \'%c\'", current);
+     case DIGIT_EXPECTED:
+       error ("Digit expected, get a non-digit instead, near \'%c\'.", current);
+     case SYNTAX_ERROR:
+       error ("There are syntax error in the above decimal.");
+     }
+ }
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.753
diff -c -p -r1.753 Makefile.in
*** Makefile.in	10 Sep 2005 18:11:01 -0000	1.753
--- Makefile.in	28 Sep 2005 04:33:23 -0000
*************** dictionary_h = dictionary.h
*** 663,668 ****
--- 663,669 ----
  disasm_h = disasm.h
  doublest_h = doublest.h $(floatformat_h)
  dummy_frame_h = dummy-frame.h
+ dfp_h = dfp.h
  dwarf2expr_h = dwarf2expr.h
  dwarf2_frame_h = dwarf2-frame.h
  dwarf2loc_h = dwarf2loc.h
*************** COMMON_OBS = $(DEPFILES) $(YYOBJ) \
*** 896,902 ****
  	auxv.o \
  	bfd-target.o \
  	blockframe.o breakpoint.o findvar.o regcache.o \
! 	charset.o disasm.o dummy-frame.o \
  	source.o value.o eval.o valops.o valarith.o valprint.o printcmd.o \
  	block.o symtab.o symfile.o symmisc.o linespec.o dictionary.o \
  	infcall.o \
--- 897,903 ----
  	auxv.o \
  	bfd-target.o \
  	blockframe.o breakpoint.o findvar.o regcache.o \
! 	charset.o disasm.o dummy-frame.o dfp.o \
  	source.o value.o eval.o valops.o valarith.o valprint.o printcmd.o \
  	block.o symtab.o symfile.o symmisc.o linespec.o dictionary.o \
  	infcall.o \
*************** dsrec.o: dsrec.c $(defs_h) $(serial_h) $
*** 1885,1890 ****
--- 1886,1892 ----
  dummy-frame.o: dummy-frame.c $(defs_h) $(dummy_frame_h) $(regcache_h) \
  	$(frame_h) $(inferior_h) $(gdb_assert_h) $(frame_unwind_h) \
  	$(command_h) $(gdbcmd_h) $(gdb_string_h)
+ dfp.o: dfp.c $(defs_h) $(dfp_h)
  dve3900-rom.o: dve3900-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \
  	$(serial_h) $(inferior_h) $(command_h) $(gdb_string_h) $(regcache_h) \
  	$(mips_tdep_h)


Regards
- Wu Zhou


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] Decimal Floating Point support for GDB (Part 1: patch)
  2005-09-28  4:40 [RFC] Decimal Floating Point support for GDB (Part 1: patch) Wu Zhou
@ 2005-09-28 18:40 ` Eli Zaretskii
  2005-09-29  2:12   ` Wu Zhou
  2005-10-02 21:00 ` Daniel Jacobowitz
  1 sibling, 1 reply; 13+ messages in thread
From: Eli Zaretskii @ 2005-09-28 18:40 UTC (permalink / raw)
  To: Wu Zhou; +Cc: gdb-patches

> Date: Wed, 28 Sep 2005 12:42:36 +0800 (CST)
> From: Wu Zhou <woodzltc@cn.ibm.com>
> 
> This patch is intended to add decimal floating point (DFP) support into
> GDB.  It currently supports the printing and setting of DFP.  And also 
> support displaying the dfp types in function argument and backtrace.  
> If you think that any other features are also desired, please let me know.  
> I will try to see whether it can also be supported.
> 
> Here goes the patch (testcase will be posted in another mail). Please 
> review and comment, any suggestion, comments and ideas are highly 
> appreciated.

Thanks.

I have a minor comment:

> +     default:
> +       error ("There is no decimal floating point of length %d", len);

Please make sure all the message strings are in _().  We are planning
to introduce intl support to GDB some day.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] Decimal Floating Point support for GDB (Part 1: patch)
  2005-09-28 18:40 ` Eli Zaretskii
@ 2005-09-29  2:12   ` Wu Zhou
  2005-09-29  3:34     ` Eli Zaretskii
  0 siblings, 1 reply; 13+ messages in thread
From: Wu Zhou @ 2005-09-29  2:12 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

Hi Eli,

On Wed, 28 Sep 2005, Eli Zaretskii wrote:

> > +     default:
> > +       error ("There is no decimal floating point of length %d", len);
> 
> Please make sure all the message strings are in _().  We are planning
> to introduce intl support to GDB some day.
> 

Thanks for your comment. I will incoporate this into the next version. Any 
other comments on this patch?
 
BTW, I have two other questions:

1. If this patch is accepted, do we also need any document?  IMO, maybe 
gdb user manual needed to be updated to reflect this feature.  But I am 
not sure which section?  What about gdb internal?  Do we need to update 
that too?

2. As you might know, dfp for gcc is also under development. And my patch 
depends on the availablity of that?  How did gdb handle this kind of 
situation before?  Did we need to wait until dfp is ready for gcc?

Thanks and Best Regards
- Wu Zhou

  


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] Decimal Floating Point support for GDB (Part 1: patch)
  2005-09-29  2:12   ` Wu Zhou
@ 2005-09-29  3:34     ` Eli Zaretskii
  0 siblings, 0 replies; 13+ messages in thread
From: Eli Zaretskii @ 2005-09-29  3:34 UTC (permalink / raw)
  To: Wu Zhou; +Cc: gdb-patches

> Date: Thu, 29 Sep 2005 10:14:15 +0800 (CST)
> From: Wu Zhou <woodzltc@cn.ibm.com>
> cc: gdb-patches@sources.redhat.com
> 
> 1. If this patch is accepted, do we also need any document?  IMO, maybe 
> gdb user manual needed to be updated to reflect this feature.

I'm not sure; the similar "1234.565f" feature is not documented
anywhere.  I guess the idea is that a programmer in the C language
should know about this C feature, and GDB just supports the C language
by accepting its syntax for numbers.  Isn't the same true for your
additions, i.e., isn't "1234.56df" going to be a valid C number
syntax?

> What about gdb internal?  Do we need to update that too?

gdbint.texinfo should have a description of language-specific files,
what they do and how to build one for a new language.  One minor issue
that should be part of that description is the number syntax.  I'd be
thrilled to see such a description added to gdbint, but since there's
no such description now, I don't feel I can ask you to write a tiny
addition to a non-existent chapter.  But if you can find time to write
a full description of the C expression syntax support, I'd gratefully
review it.

> 2. As you might know, dfp for gcc is also under development. And my patch 
> depends on the availablity of that?  How did gdb handle this kind of 
> situation before?  Did we need to wait until dfp is ready for gcc?

There's no need to wait, IMHO, since this feature in GDB will not
cause any harm unless and until GDB sees some program whose DWARF info
includes these special tags.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] Decimal Floating Point support for GDB (Part 1: patch)
  2005-09-28  4:40 [RFC] Decimal Floating Point support for GDB (Part 1: patch) Wu Zhou
  2005-09-28 18:40 ` Eli Zaretskii
@ 2005-10-02 21:00 ` Daniel Jacobowitz
  2005-10-03 15:38   ` [RFC] Decimal Floating Point support for GDB (Part 1: patch)(a sidebar) Paul Gilliam
  2005-10-09  5:23   ` [RFC] Decimal Floating Point support for GDB (Part 1: patch) Wu Zhou
  1 sibling, 2 replies; 13+ messages in thread
From: Daniel Jacobowitz @ 2005-10-02 21:00 UTC (permalink / raw)
  To: Wu Zhou; +Cc: gdb-patches

On Wed, Sep 28, 2005 at 12:42:36PM +0800, Wu Zhou wrote:
> This patch is intended to add decimal floating point (DFP) support into
> GDB.  It currently supports the printing and setting of DFP.  And also 
> support displaying the dfp types in function argument and backtrace.  
> If you think that any other features are also desired, please let me know.  
> I will try to see whether it can also be supported.

I'm afraid I am not very happy with this approach :-(

	* c-exp.y (parse_number): Parse the decimal floating point, which 
	has a suffix ('df', 'dd' or 'dl') and return STRING here.

This certainly isn't right.  It produces several problems:

(gdb) p 1.2df
evaluation of this expression requires the target program to be active

[Side effect of string handling]

...

(gdb) p 1.2df
$1 = "1.2"

(gdb) p $1[1]
$2 = 46 '.'

(gdb) p (1.2df)
A syntax error in expression, near `'.

If we have a GDB type system representation for decimal floats, the C
parser should use it, and for lexing purposes it should probably be a
FLOAT.

I'm not familiar with the proposed C language changes, but GDB should
plan to support them properly; the same set of implicit or invalid
conversions, supported operations, et cetera.  We certainly don't need
to implement all that; the C interpreter is pretty casual.  But let's
consider them at least.  And maybe issue intelligent error messages.

> 	* dfp.h: New header file for decimal floating point support in GDB.
> 	main functions is decimal_from_string and decimal_to_string.
> 	* dfp.c: New source file for decimal floating point support in GDB.
> 	Implement decimal_from_string and decimal_to_strin.

The decNumber library is going to be (or already is) contributed to the
FSF and GPL-licensed. In that case, perhaps we can move it to the top
level of the repository, and use it to implement support in GDB.  The
alternative is adding a lot of sensitive numeric code to GDB that the
GDB developers won't know much about.

> 	* valops.c (value_set_dfp): New function, calling decimal_from_string
> 	to set the value of decimal floating point types.

This is wrong for a couple of reasons.  I think you're doing this to
avoid the cast to arg1's type in evaluate_subexp_standard; but in the
process you've ignored "noside" and binop_user_defined_p (assuming
eventual C++ support), and you're assuming that fromval is a string.
Which means that 'dfp_var1 = dfp_var2' is going to crash.  And
'dfp_var1 = "1.2"' would probably work, which is unlikely to be what
you wanted.

I recommend representing decimal floating point numbers in GDB as
decimal floating point numbers, not as strings.  Then it will be pretty
clear where in e.g. valarith.c to handle it.  Or, initially, reject it.

Oh, and in a couple of places your code says:

+    Contributed by Cygnus Support, using pieces from other GDB modules.

which is not true since you're contributing it :-)

-- 
Daniel Jacobowitz
CodeSourcery, LLC


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] Decimal Floating Point support for GDB (Part 1: patch)(a sidebar)
  2005-10-02 21:00 ` Daniel Jacobowitz
@ 2005-10-03 15:38   ` Paul Gilliam
  2005-10-03 15:41     ` Daniel Jacobowitz
  2005-10-09  5:23   ` [RFC] Decimal Floating Point support for GDB (Part 1: patch) Wu Zhou
  1 sibling, 1 reply; 13+ messages in thread
From: Paul Gilliam @ 2005-10-03 15:38 UTC (permalink / raw)
  To: gdb-patches; +Cc: Daniel Jacobowitz, Wu Zhou

On Sunday 02 October 2005 13:57, Daniel Jacobowitz wrote:
 (an > On Wed, Sep 28, 2005 at 12:42:36PM +0800, Wu Zhou wrote:
> 
> Oh, and in a couple of places your code says:
> 
> +    Contributed by Cygnus Support, using pieces from other GDB modules.
> 
> which is not true since you're contributing it :-)
> 
Daniel,

To what extreems (or not) should one try to maintain the provinounce of GPL-ed source?

In this case, -*something*- in the code Wu was contributing must have come from Cygnus.

How much of a 'back trail' should one try to maintain?

Is this spelled out anywhere or is it "folk wisdom" one obtains by reading all these mailing lists?

This is not a major question, but one I have come up against severial times before.

-=# Paul #=-


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] Decimal Floating Point support for GDB (Part 1: patch)(a sidebar)
  2005-10-03 15:38   ` [RFC] Decimal Floating Point support for GDB (Part 1: patch)(a sidebar) Paul Gilliam
@ 2005-10-03 15:41     ` Daniel Jacobowitz
  2005-10-09  4:06       ` Wu Zhou
  0 siblings, 1 reply; 13+ messages in thread
From: Daniel Jacobowitz @ 2005-10-03 15:41 UTC (permalink / raw)
  To: Paul Gilliam; +Cc: gdb-patches, Wu Zhou

On Mon, Oct 03, 2005 at 08:38:25AM -0700, Paul Gilliam wrote:
> On Sunday 02 October 2005 13:57, Daniel Jacobowitz wrote:
>  (an > On Wed, Sep 28, 2005 at 12:42:36PM +0800, Wu Zhou wrote:
> > 
> > Oh, and in a couple of places your code says:
> > 
> > +    Contributed by Cygnus Support, using pieces from other GDB modules.
> > 
> > which is not true since you're contributing it :-)
> > 
> Daniel,
> 
> To what extreems (or not) should one try to maintain the provinounce
> of GPL-ed source?
> 
> In this case, -*something*- in the code Wu was contributing must have
> come from Cygnus.

I sincerely doubt it since it's based on IBM-originated code.  I
presume he only copied the copyright notice.

> 
> How much of a 'back trail' should one try to maintain?
> 
> Is this spelled out anywhere or is it "folk wisdom" one obtains by
> reading all these mailing lists?
> 
> This is not a major question, but one I have come up against severial
> times before.

If you're copying a file that contains a contributed notice, then you
ought to leave it.  If you're just borrowing little bits from it, then
generally don't bother.

-- 
Daniel Jacobowitz
CodeSourcery, LLC


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] Decimal Floating Point support for GDB (Part 1: patch)(a sidebar)
  2005-10-03 15:41     ` Daniel Jacobowitz
@ 2005-10-09  4:06       ` Wu Zhou
  0 siblings, 0 replies; 13+ messages in thread
From: Wu Zhou @ 2005-10-09  4:06 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: Paul Gilliam, gdb-patches

On Mon, 3 Oct 2005, Daniel Jacobowitz wrote:

[snip]

> > In this case, -*something*- in the code Wu was contributing must have
> > come from Cygnus.
> 
> I sincerely doubt it since it's based on IBM-originated code.  I
> presume he only copied the copyright notice.

Daniel is right.  I copied the copyright notice and forgot to change the 
contributing person.  Sorry for the confusion.  And also sorry for 
replying lately (I am just back from a vacation).

Best Regards
- Wu Zhou


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] Decimal Floating Point support for GDB (Part 1: patch)
  2005-10-02 21:00 ` Daniel Jacobowitz
  2005-10-03 15:38   ` [RFC] Decimal Floating Point support for GDB (Part 1: patch)(a sidebar) Paul Gilliam
@ 2005-10-09  5:23   ` Wu Zhou
  2005-10-09 20:08     ` Daniel Jacobowitz
  1 sibling, 1 reply; 13+ messages in thread
From: Wu Zhou @ 2005-10-09  5:23 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches

Daniel,  thanks for your comments.  Please see below for my responses.

On Sun, 2 Oct 2005, Daniel Jacobowitz wrote:

> I'm afraid I am not very happy with this approach :-(
> 
> 	* c-exp.y (parse_number): Parse the decimal floating point, which 
> 	has a suffix ('df', 'dd' or 'dl') and return STRING here.

In fact.  I am not very happy with that either.  But this is what came out 
of my mind at this time, provided that gcc and glibc support for DFP is 
not ready yet.  If the gdb-building compiler already support dfp types 
(_Decimal32, _Decimal64 and _Decimal64) and sscanf (GDB uses it to parse 
floating point number) could recognize and scan decimal types, I won't 
adopt this method.

Lookin at this code again, it is more like a proof-of-concept.

> This certainly isn't right.  It produces several problems:
> 
> (gdb) p 1.2df
> evaluation of this expression requires the target program to be active

Didn't predict that.  So all string expression handling need the target 
program to be active?

> [Side effect of string handling]
>  
> (gdb) p 1.2df
> $1 = "1.2"

Predicted this.  It seems that it is still acceptable. Right? 
:-)

> 
> (gdb) p $1[1]
> $2 = 46 '.'
> 
> (gdb) p (1.2df)
> A syntax error in expression, near `'.

Didn't predict this.

> If we have a GDB type system representation for decimal floats, the C
> parser should use it, and for lexing purposes it should probably be a
> FLOAT.

Okay. I didn't thought of adding a gdb type for decimal floats.  Maybe I 
should (It seems to be a good approach).  But I am not very familar 
with GDB's type system.  Any clue about how to start?  adding a 
builtin_type for DFP and letting it have three or more fields (like sign, 
coefficient, exponent...)?  I will take some more looks into the code. 

> I'm not familiar with the proposed C language changes, but GDB should
> plan to support them properly; the same set of implicit or invalid
> conversions, supported operations, et cetera.  We certainly don't need
> to implement all that; the C interpreter is pretty casual.  But let's
> consider them at least.  And maybe issue intelligent error messages.

Our original plan is to only support part of these c99-enhancement 
proposal in GDB, mainly printing and setting of DFP types.  To support all 
these changes (including implicit/explicit conversion, arithmetic 
operation...), we may need to introduce decNumber library in (which we 
had thought that it won't be acceptable for GDB community).  If you think 
it is okay, maybe we can reconsider this method. 

> > 	* dfp.h: New header file for decimal floating point support in GDB.
> > 	main functions is decimal_from_string and decimal_to_string.
> > 	* dfp.c: New source file for decimal floating point support in GDB.
> > 	Implement decimal_from_string and decimal_to_strin.
> 
> The decNumber library is going to be (or already is) contributed to the
> FSF and GPL-licensed. In that case, perhaps we can move it to the top
> level of the repository, and use it to implement support in GDB.  The
> alternative is adding a lot of sensitive numeric code to GDB that the
> GDB developers won't know much about.
> 
> > 	* valops.c (value_set_dfp): New function, calling decimal_from_string
> > 	to set the value of decimal floating point types.
> 
> This is wrong for a couple of reasons.  I think you're doing this to
> avoid the cast to arg1's type in evaluate_subexp_standard; but in the
> process you've ignored "noside" and binop_user_defined_p (assuming
> eventual C++ support), and you're assuming that fromval is a string.
> Which means that 'dfp_var1 = dfp_var2' is going to crash.  And
> 'dfp_var1 = "1.2"' would probably work, which is unlikely to be what
> you wanted.

you are right.  I didn't thought of that.

> I recommend representing decimal floating point numbers in GDB as
> decimal floating point numbers, not as strings.  Then it will be pretty
> clear where in e.g. valarith.c to handle it.  Or, initially, reject it.

Okay, I will consider this seriously.  Thanks for your kind suggestion.

> Oh, and in a couple of places your code says:
> 
> +    Contributed by Cygnus Support, using pieces from other GDB modules.
> 
> which is not true since you're contributing it :-)

Stupid.  I forgot to change that.  Thanks for your reminder.

Best Regards
- Wu Zhou


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] Decimal Floating Point support for GDB (Part 1: patch)
  2005-10-09  5:23   ` [RFC] Decimal Floating Point support for GDB (Part 1: patch) Wu Zhou
@ 2005-10-09 20:08     ` Daniel Jacobowitz
  2005-10-12 14:42       ` Wu Zhou
  0 siblings, 1 reply; 13+ messages in thread
From: Daniel Jacobowitz @ 2005-10-09 20:08 UTC (permalink / raw)
  To: Wu Zhou; +Cc: gdb-patches

On Sun, Oct 09, 2005 at 01:27:10PM +0800, Wu Zhou wrote:
> > I'm afraid I am not very happy with this approach :-(
> > 
> > 	* c-exp.y (parse_number): Parse the decimal floating point, which 
> > 	has a suffix ('df', 'dd' or 'dl') and return STRING here.
> 
> In fact.  I am not very happy with that either.  But this is what came out 
> of my mind at this time, provided that gcc and glibc support for DFP is 
> not ready yet.  If the gdb-building compiler already support dfp types 
> (_Decimal32, _Decimal64 and _Decimal64) and sscanf (GDB uses it to parse 
> floating point number) could recognize and scan decimal types, I won't 
> adopt this method.

I'd rather work with decNumber than mix host and target types.

> > (gdb) p 1.2df
> > evaluation of this expression requires the target program to be active
> 
> Didn't predict that.  So all string expression handling need the target 
> program to be active?

Yes.  The expression 'print "1"' calls malloc(2) in the inferior
program to allocate space for the string, pokes the value into target
memory, and generally leaks a bit of memory too.

> > [Side effect of string handling]
> >  
> > (gdb) p 1.2df
> > $1 = "1.2"
> 
> Predicted this.  It seems that it is still acceptable. Right? 

Please no!  "p 1.2df" should give me back either 1.2 or 1.2df.

> > If we have a GDB type system representation for decimal floats, the C
> > parser should use it, and for lexing purposes it should probably be a
> > FLOAT.
> 
> Okay. I didn't thought of adding a gdb type for decimal floats.  Maybe I 
> should (It seems to be a good approach).  But I am not very familar 
> with GDB's type system.  Any clue about how to start?  adding a 
> builtin_type for DFP and letting it have three or more fields (like sign, 
> coefficient, exponent...)?  I will take some more looks into the code. 

Or just use the decNumber packed representation, in value_contents().
Take a look at all the references to FLOATFORMAT to see how we handle
floating point types.

We'd want to handle printing not only dfp variables, but dfp fields in
structures, et cetera.

-- 
Daniel Jacobowitz
CodeSourcery, LLC


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] Decimal Floating Point support for GDB (Part 1: patch)
  2005-10-09 20:08     ` Daniel Jacobowitz
@ 2005-10-12 14:42       ` Wu Zhou
  2005-10-12 14:49         ` Daniel Jacobowitz
  0 siblings, 1 reply; 13+ messages in thread
From: Wu Zhou @ 2005-10-12 14:42 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: bje, gdb-patches


On Sun, 9 Oct 2005, Daniel Jacobowitz wrote:
> On Sun, Oct 09, 2005 at 01:27:10PM +0800, Wu Zhou wrote:
> > > I'm afraid I am not very happy with this approach :-(
> > > 
> > > 	* c-exp.y (parse_number): Parse the decimal floating point, which 
> > > 	has a suffix ('df', 'dd' or 'dl') and return STRING here.
> > 
> > In fact.  I am not very happy with that either.  But this is what came out 
> > of my mind at this time, provided that gcc and glibc support for DFP is 
> > not ready yet.  If the gdb-building compiler already support dfp types 
> > (_Decimal32, _Decimal64 and _Decimal64) and sscanf (GDB uses it to parse 
> > floating point number) could recognize and scan decimal types, I won't 
> > adopt this method.
> 
> I'd rather work with decNumber than mix host and target types.

> > > If we have a GDB type system representation for decimal floats, the C
> > > parser should use it, and for lexing purposes it should probably be a
> > > FLOAT.
> > 
> > Okay. I didn't thought of adding a gdb type for decimal floats.  Maybe I 
> > should (It seems to be a good approach).  But I am not very familar 
> > with GDB's type system.  Any clue about how to start?  adding a 
> > builtin_type for DFP and letting it have three or more fields (like sign, 
> > coefficient, exponent...)?  I will take some more looks into the code. 
> 
> Or just use the decNumber packed representation, in value_contents().
> Take a look at all the references to FLOATFORMAT to see how we handle
> floating point types.

I did had some looks at FLOATFORMAT, but found that there are quite
some difference between DFP encoding format and normal binary floating
encoding format: for example, dfp's fields is composed of combinator
bits, exponent continuation bits and coefficient continuation bits.  
While most bfp floatformat is composed of two fields (exponent bits 
and coefficient bits).  And they also have different representation 
for non-finite number (infinity and NaN).  

So I am now thinking of adding a builtin type other than TYPE_CODE_FLT to
represent dfp.  This type (I am thinking of using TYPE_CODE_DECFLT) will 
have three fundamental type like TYPE_CODE_FLT for different sizes. In the
fields it will have four fields: signedness, combinator, exponent 
continuation and coefficient continuation.  And these fields will merged 
together into value.aligner.contents.  In this way, we can not only 
support the setting and printing of dfp types (constants or variables), 
but also can add other feature (such as arithmetic operation) as needed. 

Is there any clear deficiency in this method?  Do you think that it is 
feasible? and also extensible?  I will start to code in this direction if 
there is not any obvous weakness.

Best Regards
- Wu Zhou


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] Decimal Floating Point support for GDB (Part 1: patch)
  2005-10-12 14:42       ` Wu Zhou
@ 2005-10-12 14:49         ` Daniel Jacobowitz
  2005-10-18 10:02           ` [RFC] Decimal Floating Point support for GDB (Part 1: patch - Rewrited) Wu Zhou
  0 siblings, 1 reply; 13+ messages in thread
From: Daniel Jacobowitz @ 2005-10-12 14:49 UTC (permalink / raw)
  To: Wu Zhou; +Cc: bje, gdb-patches

On Wed, Oct 12, 2005 at 10:46:22PM +0800, Wu Zhou wrote:
> > Or just use the decNumber packed representation, in value_contents().
> > Take a look at all the references to FLOATFORMAT to see how we handle
> > floating point types.
> 
> I did had some looks at FLOATFORMAT, but found that there are quite
> some difference between DFP encoding format and normal binary floating
> encoding format: for example, dfp's fields is composed of combinator
> bits, exponent continuation bits and coefficient continuation bits.  
> While most bfp floatformat is composed of two fields (exponent bits 
> and coefficient bits).  And they also have different representation 
> for non-finite number (infinity and NaN).  

Yes, sorry - I wasn't suggesting that you define floatformats for
these, just that you handle them in the same set of places that we
handle floatformats.

> So I am now thinking of adding a builtin type other than TYPE_CODE_FLT to
> represent dfp.  This type (I am thinking of using TYPE_CODE_DECFLT) will 
> have three fundamental type like TYPE_CODE_FLT for different sizes. In the
> fields it will have four fields: signedness, combinator, exponent 
> continuation and coefficient continuation.  And these fields will merged 
> together into value.aligner.contents.  In this way, we can not only 
> support the setting and printing of dfp types (constants or variables), 
> but also can add other feature (such as arithmetic operation) as needed. 
> 
> Is there any clear deficiency in this method?  Do you think that it is 
> feasible? and also extensible?  I will start to code in this direction if 
> there is not any obvous weakness.

This may be what you're saying, but the only copy of the data should be
in value_contents, not duplicated in unpacked form elsewhere.

Yes, I think introducing a new type code is a good idea; that will be
more robust than reusing TYPE_CODE_FLT.  There are 230 references to
TYPE_CODE_FLT in gdb; many of them you'd want to handle DECFLT the same
way, but many you wouldn't.  For instance, calling functions which take
decimal floating point arguments.

-- 
Daniel Jacobowitz
CodeSourcery, LLC


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [RFC] Decimal Floating Point support for GDB (Part 1: patch - Rewrited)
  2005-10-12 14:49         ` Daniel Jacobowitz
@ 2005-10-18 10:02           ` Wu Zhou
  0 siblings, 0 replies; 13+ messages in thread
From: Wu Zhou @ 2005-10-18 10:02 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: bje, gdb-patches

Hi Daniel,

I had rewrited the dfp patch using the method we discussed in this thread.  
Most the problems you mentioned is gone with this new patch now, (you can 
see that in the following testcase patch). It can work with DFP constants 
without a running program, won't print DFP constant as string any more.  
It can handle assigning statement "dfp1=dfp2" besides normal DFP value 
setting.  It could also handle negative operation on DFP values.  

However, it can't handle any other arithmetic operation at this time.  It 
can't handle DFP conversion (explicitly or implicitly) either.  I am now 
reluctant to do that.  But I think the current code is more extensible 
than before if we need to add these feature.

Appended is the patch.  It is tested with the latest dfp-branch gcc on x86 
with "-msse" option.  All the dfp testcases (will post in another mail) 
passed.  And don't see any regression failure on other testcases.  Please 
review and comment.  Thanks a lot.

2005-10-18  Wu Zhou  <woodzltc@cn.ibm.com>

	* expression.h (enum exp_opcode): Add an opcode (OP_DECDOUBLE) for
	DFP constants.
	(union exp_element): Add decdoubleconst to represent DFP elements,
	which is 16 bytes by default.
	* parse.c (write_exp_elt_decdblcst): New function.  Called by
	c-exp.y.
	(operator_length_standard): Set operator length for OP_DECDOUBLE.
	* c-exp.y (YYSTYPE): Add typed_val_decfloat for decimal floating 
	point in YYSTYPE union.
	Add token DECFLOAT for typed_val_decfloat.
	Add expression element handling code for DECFLOAT.
	(parse_number): Parse DFP constants, which end with suffix 'df',
	'dd' or 'dl'.  Return DECFLOAT.
	* c-lang.c (c_create_fundamental_type): Create fundamental types
	for DFP.
	* c-valprint.c (c_val_print): Call print_decimal_floating to print
	DFP values.
	* dwarf2read.c (read_base_type): Read DW_ATE_decimal_float attribute
	code and return TYPE_CODE_DECFLT.
	(dwarf_base_type): Set dwarf2_fundamental_type for DFP values.
	* eval.c (evaluate_subexp_standard): Call value_from_decdouble to
	handle OP_DECDOUBLE.
	* gdbtypes.h: Add three fundamental types for DFP.
	(enum type_code): Add TYPE_CODE_DECFLT as a type code for DFP.
	(struct builtin_type): Add builtin_decfloat, builtin_decdouble
	and builtin_declong.
	* gdbtypes.c: Add three builtin types for DFP.
	(build_gdbtypes): Build these three builtin types for DFP.
	(gdbtypes_post_init): Initialize builtin_decfloat, builtin_decdouble
	and builtin_declong.
	(_initialize_gdbtypes): FIXME.  Don't know what it does for.  
	Maybe it is not needed?
	* valprint.c (print_decimal_floating): New function to print DFP
	values.
	* value.c (value_from_decdouble): New function to get the value
	from a decimal double.
	* valarith.c (value_neg): Add some code to handle the negation
	operation of DFP values.
	* dfp.h: New header file for decimal floating point support in
	GDB.
	* dfp.c: New source file for decimal floating point support in
	GDB.  Implement decimal_from_string and decimal_to_string.
	* Makefile.in: Add dfp.h and dfp.c.
	
Index: c-exp.y
===================================================================
RCS file: /cvs/src/src/gdb/c-exp.y,v
retrieving revision 1.30
diff -c -3 -p -r1.30 c-exp.y
*** c-exp.y	20 Sep 2005 08:55:55 -0000	1.30
--- c-exp.y	18 Oct 2005 08:18:32 -0000
*************** Foundation, Inc., 59 Temple Place - Suit
*** 52,57 ****
--- 52,58 ----
  #include "charset.h"
  #include "block.h"
  #include "cp-support.h"
+ #include "dfp.h"
  
  /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
     as well as gratuitiously global symbol names, so we can have multiple
*************** void yyerror (char *);
*** 130,135 ****
--- 131,140 ----
        DOUBLEST dval;
        struct type *type;
      } typed_val_float;
+     struct {
+       gdb_byte val[16];
+       struct type *type;
+     } typed_val_decfloat;
      struct symbol *sym;
      struct type *tval;
      struct stoken sval;
*************** static int parse_number (char *, int, in
*** 162,167 ****
--- 167,173 ----
  
  %token <typed_val_int> INT
  %token <typed_val_float> FLOAT
+ %token <typed_val_decfloat> DECFLOAT
  
  /* Both NAME and TYPENAME tokens represent symbols in the input,
     and both convey their data as strings.
*************** exp	:	FLOAT
*** 496,501 ****
--- 502,514 ----
  			  write_exp_elt_opcode (OP_DOUBLE); }
  	;
  
+ exp	:	DECFLOAT
+ 			{ write_exp_elt_opcode (OP_DECDOUBLE);
+ 			  write_exp_elt_type ($1.type);
+ 			  write_exp_elt_decdblcst ($1.val);
+ 			  write_exp_elt_opcode (OP_DECDOUBLE); }
+ 	;
+ 
  exp	:	variable
  	;
  
*************** parse_number (p, len, parsed_float, puti
*** 1080,1085 ****
--- 1093,1131 ----
  
        p[len] = 0;	/* null-terminate the token */
  
+       /* If it ends at "df", "dd" or "dl", take it as type of decimal floating
+          point.  Return DECFLOAT.  */
+ 
+       if (p[len - 2] == 'd' && p[len - 1] == 'f')
+ 	{
+ 	  p[len - 2] = '\0';
+ 	  putithere->typed_val_decfloat.type = 
+ 	    builtin_type (current_gdbarch)->builtin_decfloat;
+ 	  decimal_from_string (putithere->typed_val_decfloat.val, 4, p);
+ 	  p[len] = saved_char;
+ 	  return (DECFLOAT);
+ 	}
+ 
+       if (p[len - 2] == 'd' && p[len - 1] == 'd')
+ 	{
+ 	  p[len - 2] = '\0';
+ 	  putithere->typed_val_decfloat.type = 
+ 	    builtin_type (current_gdbarch)->builtin_decdouble;
+ 	  decimal_from_string (putithere->typed_val_decfloat.val, 8, p);
+ 	  p[len] = saved_char;
+ 	  return (DECFLOAT);
+ 	}
+ 
+       if (p[len - 2] == 'd' && p[len - 1] == 'l')
+ 	{
+ 	  p[len - 2] = '\0';
+ 	  putithere->typed_val_decfloat.type = 
+ 	    builtin_type (current_gdbarch)->builtin_declong;
+ 	  decimal_from_string (putithere->typed_val_decfloat.val, 16, p);
+ 	  p[len] = saved_char;
+ 	  return (DECFLOAT);
+ 	}
+ 
        if (sizeof (putithere->typed_val_float.dval) <= sizeof (float))
  	num = sscanf (p, "%g%s", (float *) &putithere->typed_val_float.dval,s);
        else if (sizeof (putithere->typed_val_float.dval) <= sizeof (double))
Index: c-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/c-lang.c,v
retrieving revision 1.38
diff -c -3 -p -r1.38 c-lang.c
*** c-lang.c	3 Oct 2005 21:21:20 -0000	1.38
--- c-lang.c	18 Oct 2005 08:18:35 -0000
*************** c_create_fundamental_type (struct objfil
*** 322,327 ****
--- 322,342 ----
  			TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
  			0, "long double", objfile);
        break;
+     case FT_DECFLOAT:
+       type = init_type (TYPE_CODE_DECFLT,
+ 			32 / 8,
+ 			0, "decimal float", objfile);
+       break;
+     case FT_DBL_PREC_DECFLOAT:
+       type = init_type (TYPE_CODE_DECFLT,
+ 			64 / 8,
+ 			0, "decimal double", objfile);
+       break;
+     case FT_EXT_PREC_DECFLOAT:
+       type = init_type (TYPE_CODE_DECFLT,
+ 			128 / 8,
+ 			0, "decimal long double", objfile);
+       break;
      case FT_COMPLEX:
        type = init_type (TYPE_CODE_FLT,
  			2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
Index: c-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/c-valprint.c,v
retrieving revision 1.37
diff -c -3 -p -r1.37 c-valprint.c
*** c-valprint.c	9 May 2005 21:20:30 -0000	1.37
--- c-valprint.c	18 Oct 2005 08:18:37 -0000
*************** c_val_print (struct type *type, const gd
*** 435,440 ****
--- 435,451 ----
  	}
        break;
  
+     case TYPE_CODE_DECFLT:
+       if (format)
+ 	{
+ 	  print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
+ 	}
+       else
+ 	{
+ 	  print_decimal_floating (valaddr + embedded_offset, type, stream);
+ 	}
+       break;
+ 
      case TYPE_CODE_METHOD:
        {
  	struct value *v = value_at (type, address);
Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.183
diff -c -3 -p -r1.183 dwarf2read.c
*** dwarf2read.c	1 Aug 2005 04:06:27 -0000	1.183
--- dwarf2read.c	18 Oct 2005 08:19:27 -0000
*************** read_base_type (struct die_info *die, st
*** 4704,4709 ****
--- 4704,4712 ----
  	case DW_ATE_complex_float:
  	  code = TYPE_CODE_COMPLEX;
  	  break;
+ 	case DW_ATE_decimal_float:
+ 	  code = TYPE_CODE_DECFLT;
+ 	  break;
  	case DW_ATE_float:
  	  code = TYPE_CODE_FLT;
  	  break;
*************** dwarf_base_type (int encoding, int size,
*** 7408,7413 ****
--- 7411,7424 ----
  	  type = dwarf2_fundamental_type (objfile, FT_FLOAT, cu);
  	}
        return type;
+     case DW_ATE_decimal_float:
+       if (size == 16)
+ 	type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_DECFLOAT, cu);
+       else if (size == 8)
+ 	type = dwarf2_fundamental_type (objfile, FT_EXT_PREC_DECFLOAT, cu);
+       else
+ 	type = dwarf2_fundamental_type (objfile, FT_DECFLOAT, cu);
+       return type;
      case DW_ATE_signed:
        switch (size)
  	{
Index: eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.59
diff -c -3 -p -r1.59 eval.c
*** eval.c	20 Sep 2005 06:25:34 -0000	1.59
--- eval.c	18 Oct 2005 08:19:43 -0000
*************** evaluate_subexp_standard (struct type *e
*** 447,452 ****
--- 447,457 ----
        return value_from_double (exp->elts[pc + 1].type,
  				exp->elts[pc + 2].doubleconst);
  
+     case OP_DECDOUBLE:
+       (*pos) += 3;
+       return value_from_decdouble (expect_type, exp->elts[pc + 1].type,
+ 				exp->elts[pc + 2].decdoubleconst);
+ 
      case OP_VAR_VALUE:
        (*pos) += 3;
        if (noside == EVAL_SKIP)
Index: expression.h
===================================================================
RCS file: /cvs/src/src/gdb/expression.h,v
retrieving revision 1.17
diff -c -3 -p -r1.17 expression.h
*** expression.h	20 Sep 2005 06:31:59 -0000	1.17
--- expression.h	18 Oct 2005 08:19:45 -0000
*************** enum exp_opcode
*** 327,332 ****
--- 327,337 ----
      /* A F90 array range operator (for "exp:exp", "exp:", ":exp" and ":").  */
      OP_F90_RANGE,
  
+     /* OP_DECDOUBLE is followed by a type pointer in the next exp_element
+        and a dec long constant value in the following exp_element.
+        Then comes another OP_DECDOUBLE.  */
+     OP_DECDOUBLE,
+ 
       /* First extension operator.  Individual language modules define
          extra operators they need as constants with values 
          OP_LANGUAGE_SPECIFIC0 + k, for k >= 0, using a separate 
*************** union exp_element
*** 354,359 ****
--- 359,365 ----
      struct symbol *symbol;
      LONGEST longconst;
      DOUBLEST doubleconst;
+     gdb_byte decdoubleconst[16];
      /* Really sizeof (union exp_element) characters (or less for the last
         element of a string).  */
      char string;
Index: gdbtypes.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.c,v
retrieving revision 1.101
diff -c -3 -p -r1.101 gdbtypes.c
*** gdbtypes.c	27 Jun 2005 08:38:13 -0000	1.101
--- gdbtypes.c	18 Oct 2005 08:20:03 -0000
*************** struct type *builtin_type_int128;
*** 73,78 ****
--- 73,84 ----
  struct type *builtin_type_uint128;
  struct type *builtin_type_bool;
  
+ /* The following three are about decimal floating point types, which are now 
+    considered as potential extension to C99 standard.  */ 
+ struct type *builtin_type_decfloat;
+ struct type *builtin_type_decdouble;
+ struct type *builtin_type_declong;
+ 
  /* 128 bit long vector types */
  struct type *builtin_type_v2_double;
  struct type *builtin_type_v4_float;
*************** build_gdbtypes (void)
*** 3197,3202 ****
--- 3203,3223 ----
  #if 0
    TYPE_FLOATFORMAT (builtin_type_long_double) = TARGET_LONG_DOUBLE_FORMAT;
  #endif
+ 
+   /* Builtin types for decimal floating point types.  */
+   builtin_type_decfloat =
+     init_type (TYPE_CODE_DECFLT, 32 / 8,
+ 	       0,
+ 	       "decimal float", (struct objfile *) NULL);
+   builtin_type_decdouble =
+     init_type (TYPE_CODE_DECFLT, 64 / 8,
+                0,
+                "decimal double", (struct objfile *) NULL);
+   builtin_type_declong =
+     init_type (TYPE_CODE_DECFLT, 128 / 8,
+ 	       0,
+ 	       "decimal long double", (struct objfile *) NULL);
+ 
    builtin_type_complex =
      init_type (TYPE_CODE_COMPLEX, 2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
  	       0,
*************** gdbtypes_post_init (struct gdbarch *gdba
*** 3422,3427 ****
--- 3443,3463 ----
  	       0,
  	       "bool", (struct objfile *) NULL);
  
+   /* The following three are about decimal floating point types, which are 
+      32-bits, 64-bits and 128-bits respectively.  */
+   builtin_type->builtin_decfloat = 
+    init_type (TYPE_CODE_DECFLT, 32 / 8,
+                0,
+                "decimal float", (struct objfile *) NULL);
+   builtin_type->builtin_decdouble =
+     init_type (TYPE_CODE_DECFLT, 64 / 8,
+                0,
+                "decimal double", (struct objfile *) NULL);
+   builtin_type->builtin_declong =
+     init_type (TYPE_CODE_DECFLT, 128 / 8,
+                0,
+                "decimal long double", (struct objfile *) NULL);
+ 
    /* Pointer/Address types. */
  
    /* NOTE: on some targets, addresses and pointers are not necessarily
*************** _initialize_gdbtypes (void)
*** 3560,3565 ****
--- 3596,3604 ----
    DEPRECATED_REGISTER_GDBARCH_SWAP (builtin_type_void_func_ptr);
    DEPRECATED_REGISTER_GDBARCH_SWAP (builtin_type_CORE_ADDR);
    DEPRECATED_REGISTER_GDBARCH_SWAP (builtin_type_bfd_vma);
+   DEPRECATED_REGISTER_GDBARCH_SWAP (builtin_type_decfloat);
+   DEPRECATED_REGISTER_GDBARCH_SWAP (builtin_type_decdouble);
+   DEPRECATED_REGISTER_GDBARCH_SWAP (builtin_type_declong);
    deprecated_register_gdbarch_swap (NULL, 0, build_gdbtypes);
  
    /* Note: These types do not need to be swapped - they are target
Index: gdbtypes.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.h,v
retrieving revision 1.62
diff -c -3 -p -r1.62 gdbtypes.h
*** gdbtypes.h	6 Apr 2005 17:01:25 -0000	1.62
--- gdbtypes.h	18 Oct 2005 08:20:14 -0000
*************** struct block;
*** 65,71 ****
  #define FT_UNSIGNED_BYTE	27
  #define FT_TEMPLATE_ARG		28
  
! #define FT_NUM_MEMBERS		29	/* Highest FT_* above, plus one. */
  
  /* Some macros for char-based bitfields.  */
  
--- 65,76 ----
  #define FT_UNSIGNED_BYTE	27
  #define FT_TEMPLATE_ARG		28
  
! /* The following three fundamental types are for decimal floating point.  */
! #define FT_DECFLOAT		29	
! #define FT_DBL_PREC_DECFLOAT	30
! #define FT_EXT_PREC_DECFLOAT	31	
! 
! #define FT_NUM_MEMBERS		32	/* Highest FT_* above, plus one. */
  
  /* Some macros for char-based bitfields.  */
  
*************** enum type_code
*** 156,162 ****
      TYPE_CODE_TEMPLATE,		/* C++ template */
      TYPE_CODE_TEMPLATE_ARG,	/* C++ template arg */
  
!     TYPE_CODE_NAMESPACE		/* C++ namespace.  */
    };
  
  /* For now allow source to use TYPE_CODE_CLASS for C++ classes, as an
--- 161,169 ----
      TYPE_CODE_TEMPLATE,		/* C++ template */
      TYPE_CODE_TEMPLATE_ARG,	/* C++ template arg */
  
!     TYPE_CODE_NAMESPACE,	/* C++ namespace.  */
! 
!     TYPE_CODE_DECFLT		/* Decimal floating point.  */
    };
  
  /* For now allow source to use TYPE_CODE_CLASS for C++ classes, as an
*************** struct builtin_type
*** 1002,1007 ****
--- 1009,1017 ----
    struct type *builtin_bool;
    struct type *builtin_long_long;
    struct type *builtin_unsigned_long_long;
+   struct type *builtin_decfloat;
+   struct type *builtin_decdouble;
+   struct type *builtin_declong;
  };
  
  /* Return the type table for the specified architecture.  */
*************** extern struct type *builtin_type_complex
*** 1025,1030 ****
--- 1035,1043 ----
  extern struct type *builtin_type_double_complex;
  extern struct type *builtin_type_string;
  extern struct type *builtin_type_bool;
+ extern struct type *builtin_type_decfloat;
+ extern struct type *builtin_type_decdouble;
+ extern struct type *builtin_type_declong;
  
  /* Address/pointer types: */
  /* (C) Language `pointer to data' type.  Some target platforms use an
Index: parse.c
===================================================================
RCS file: /cvs/src/src/gdb/parse.c,v
retrieving revision 1.50
diff -c -3 -p -r1.50 parse.c
*** parse.c	20 Sep 2005 06:25:34 -0000	1.50
--- parse.c	18 Oct 2005 08:20:23 -0000
*************** write_exp_elt_dblcst (DOUBLEST expelt)
*** 235,240 ****
--- 235,252 ----
  }
  
  void
+ write_exp_elt_decdblcst (gdb_byte expelt[16])
+ {
+   union exp_element tmp;
+   int index;
+ 
+   for (index = 0; index < 16; index++)
+     tmp.decdoubleconst[index] = expelt[index];
+ 
+   write_exp_elt (tmp);
+ }
+ 
+ void
  write_exp_elt_type (struct type *expelt)
  {
    union exp_element tmp;
*************** operator_length_standard (struct express
*** 856,861 ****
--- 868,874 ----
  
      case OP_LONG:
      case OP_DOUBLE:
+     case OP_DECDOUBLE:
      case OP_VAR_VALUE:
        oplen = 4;
        break;
Index: valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/valprint.c,v
retrieving revision 1.56
diff -c -3 -p -r1.56 valprint.c
*** valprint.c	10 Oct 2005 01:03:59 -0000	1.56
--- valprint.c	18 Oct 2005 08:20:33 -0000
*************** print_floating (const gdb_byte *valaddr,
*** 464,469 ****
--- 464,481 ----
  }
  
  void
+ print_decimal_floating (const gdb_byte *valaddr, struct type *type,
+ 		struct ui_file *stream)
+ {
+   char decstr[128];
+   unsigned len = TYPE_LENGTH (type);
+ 
+   decimal_to_string (valaddr, len, decstr);
+   fputs_filtered (decstr, stream);
+   return;
+ }
+ 
+ void
  print_binary_chars (struct ui_file *stream, const gdb_byte *valaddr,
  		    unsigned len)
  {
Index: value.c
===================================================================
RCS file: /cvs/src/src/gdb/value.c,v
retrieving revision 1.31
diff -c -3 -p -r1.31 value.c
*** value.c	2 Aug 2005 03:13:50 -0000	1.31
--- value.c	18 Oct 2005 08:20:41 -0000
*************** value_from_double (struct type *type, DO
*** 1534,1539 ****
--- 1534,1562 ----
  }
  
  struct value *
+ value_from_decdouble (struct type *expect_type, struct type *type, 
+ 		      gdb_byte decbytes[16])
+ {
+   struct value *val = allocate_value (type);
+   int len = TYPE_LENGTH (type);
+ 
+   if (expect_type)
+     {
+       int expect_len = TYPE_LENGTH (expect_type);
+       char decstr[128];
+       int real_len;
+ 
+       decimal_to_string (decbytes, len, decstr);
+       real_len = strlen (decstr);
+       decstr [real_len - 2] = '\0';
+       decimal_from_string (decbytes, expect_len, decstr);
+     }
+ 
+   memcpy (value_contents_raw (val), decbytes, len);
+   return val;
+ }
+ 
+ struct value *
  coerce_ref (struct value *arg)
  {
    struct type *value_type_arg_tmp = check_typedef (value_type (arg));
Index: valarith.c
===================================================================
RCS file: /cvs/src/src/gdb/valarith.c,v
retrieving revision 1.43
diff -c -3 -p -r1.43 valarith.c
*** valarith.c	21 Aug 2005 09:33:11 -0000	1.43
--- valarith.c	18 Oct 2005 08:20:51 -0000
*************** value_neg (struct value *arg1)
*** 1375,1380 ****
--- 1375,1389 ----
  
    type = check_typedef (value_type (arg1));
  
+   if (TYPE_CODE (type) == TYPE_CODE_DECFLT)
+     {
+       struct value *val = allocate_value (result_type);
+       gdb_byte *decbytes = value_contents (arg1);
+       decbytes[0] = decbytes[0] | 0x80;
+       memcpy (value_contents_raw (val), decbytes, 16);
+       return val;
+     }
+ 
    if (TYPE_CODE (type) == TYPE_CODE_FLT)
      return value_from_double (result_type, -value_as_double (arg1));
    else if (is_integral_type (type))
Index: dfp.h
===================================================================
RCS file: dfp.h
diff -N dfp.h
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- dfp.h	18 Oct 2005 08:20:51 -0000
***************
*** 0 ****
--- 1,101 ----
+ /* Decimal floating point support for GDB.
+ 
+    Copyright 2005 Free Software Foundation, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ 
+ /* Decimal floating point is one of the extension to IEEE 754, which is
+    described in http://grouper.ieee.org/groups/754/revision.html and
+    http://www2.hursley.ibm.com/decimal/.  It completes binary floating
+    point by representing floating point more exactly.  */
+ 
+ /* There is a project intended to add DFP support into GCC, described in
+    http://gcc.gnu.org/wiki/Decimal%20Floating-Point.  This file is intended
+    to add DFP support into GDB.  */
+ 
+ #ifndef DFP_H
+ #define DFP_H
+ #include <string.h>
+ #include <stdio.h>
+ #include <stdint.h>
+ 
+ /* The first byte for Infinity, NaN and sNaN.  */
+ #define DECIMAL_Inf     0x78        /* 0 11110 00 Infinity */
+ #define DECIMAL_NaN     0x7c        /* 0 11111 00 NaN */
+ #define DECIMAL_sNaN    0x7e        /* 0 11111 10 sNaN */
+ 
+ /* Parameters for _Decimal32.  */
+ #define DECIMAL32_Pmax   7            // maximum precision (digits)
+ #define DECIMAL32_Emax   96           // maximum adjusted exponent
+ #define DECIMAL32_Emin  -95           // minimum adjusted exponent
+ #define DECIMAL32_Bias   101          // bias for the exponent
+ 
+ /* Parameters for _Decimal64.  */
+ #define DECIMAL64_Pmax   16           // maximum precision (digits)
+ #define DECIMAL64_Emax   384          // maximum adjusted exponent
+ #define DECIMAL64_Emin  -383          // minimum adjusted exponent
+ #define DECIMAL64_Bias   398          // bias for the exponent
+ 
+ /* Parameters for _Decimal128.  */
+ #define DECIMAL128_Pmax   34          // maximum precision (digits)
+ #define DECIMAL128_Emax   6144        // maximum adjusted exponent
+ #define DECIMAL128_Emin  -6143        // minimum adjusted exponent
+ #define DECIMAL128_Bias   6176        // bias for the exponent
+ 
+ /* The parse errors found in the conversion routine from the string to
+    decimal types (decimal_from_string).  */
+ #define SYNTAX_ERROR 		0x00000001
+ #define COEFF_OUTOFRANGE 	0x00000002
+ #define EXP_OUTOFRANGE 		0x00000004
+ #define INVALID_CHAR 		0x00000008
+ #define DIGIT_EXPECTED 		0x00000010
+ 
+ #define X10(i)  (((i) << 1) + ((i) << 3))
+ #define X100(i) (((i) << 2) + ((i) << 5) + ((i) << 6))
+ 
+ /* Get the sign bit, combinator bits, exponent continuation bits of
+    _Decimal32, _Decimal64 and _Decimal128.  */
+ #define decimalGetSign(d)	((unsigned)(d)[0] >> 7)
+ #define decimalGetComb(d)	(((d)[0] & 0x7c) >> 2)
+ #define decimal32GetExpCon(d)	((((d)[0] & 0x03) << 4) | \
+ 				((unsigned)(d)[1] >> 4))
+ #define decimal64GetExpCon(d)	((((d)[0] & 0x03) << 6) | \
+ 				((unsigned)(d)[1] >> 2))
+ #define decimal128GetExpCon(d)	((((d)[0] & 0x03) << 10) | \
+ 				((unsigned)(d)[1] << 2) | \
+ 				((unsigned)(d)[2] >> 6)) 
+ 
+ /* Set the sign bit and combinator bits.  */
+ #define decimalSetSign(d, b) 	{ (d)[0] |= ((unsigned)(b) << 7);	}
+ #define decimalSetComb(d, b) 	{ (d)[0] |= ((unsigned)(b) << 2);	}
+ 
+ /* Set the exponent continuation bits of _Decimal32, _Decimal64 and 
+    _Decimal128.  */
+ #define decimal32SetExpCon(d, e) { (d)[0] |= (uint8_t)((e) >> 4); \
+ 			           (d)[1] |= (uint8_t)(((e) & 0x0F) << 4);  }
+ #define decimal64SetExpCon(d, e) { (d)[0] |= (uint8_t)((e) >> 6); \
+ 				   (d)[1] |= (uint8_t)(((e) & 0x3F) << 2);  }
+ #define decimal128SetExpCon(d, e) { (d)[0] |= (uint8_t)((e) >> 10); \
+ 				    (d)[1] = (uint8_t)(((e) & 0x03FC) >> 2); \
+ 				    (d)[2] |= (uint8_t)(((e) & 0x03) << 6);  } 
+ 
+ /* The conversion from decimal floating point to string, and reverse.  */
+ extern void decimal_to_string (const uint8_t *, int, char *);
+ extern int decimal_from_string (uint8_t *, int, char *);
+ 
+ #endif
Index: dfp.c
===================================================================
RCS file: dfp.c
diff -N dfp.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- dfp.c	18 Oct 2005 08:21:05 -0000
***************
*** 0 ****
--- 1,872 ----
+ /* Decimal floating point support for GDB.
+ 
+    Copyright 2005 Free Software Foundation, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ 
+ #include "defs.h"
+ #include "dfp.h"
+ #include <ctype.h>
+ 
+ /* The bits composition of decimal32, decimal64 and decimal128.
+    For decimal32: 
+      1 (sign) + 5 (combinator) + 6 (exponent) + 20 (coefficient) = 32 bits
+    For decimal64:
+      1 (sign) + 5 (combinator) + 8 (exponent) + 50 (coefficient) = 64 bits
+    For decimal128:
+      1 (sign) + 5 (combinator) + 12 (exponent) + 110 (coefficient) = 128 bits
+ 
+    For more detailed description, refer to the decimal encoding specification,
+    described in http://www2.hursley.ibm.com/decimal/decbits.html.  */
+ 
+ static const int bits[3][4] = { { 1, 5, 6, 20 },
+ 				{ 1, 5, 8, 50 },
+ 				{ 1, 5, 12, 110 } };
+ 
+ /* The mapping table from Densely Packed Decimal (DPD) to/from Binary.  Refer 
+    to http://www2.hursley.ibm.com/decimal/decbits.html for more detail.  */
+ 
+ const uint16_t DPD2BIN[1024]={    0,    1,    2,    3,    4,    5,    6,    7,
+     8,    9,   80,   81,  800,  801,  880,  881,   10,   11,   12,   13,   14,
+    15,   16,   17,   18,   19,   90,   91,  810,  811,  890,  891,   20,   21,
+    22,   23,   24,   25,   26,   27,   28,   29,   82,   83,  820,  821,  808,
+   809,   30,   31,   32,   33,   34,   35,   36,   37,   38,   39,   92,   93,
+   830,  831,  818,  819,   40,   41,   42,   43,   44,   45,   46,   47,   48,
+    49,   84,   85,  840,  841,   88,   89,   50,   51,   52,   53,   54,   55,
+    56,   57,   58,   59,   94,   95,  850,  851,   98,   99,   60,   61,   62,
+    63,   64,   65,   66,   67,   68,   69,   86,   87,  860,  861,  888,  889,
+    70,   71,   72,   73,   74,   75,   76,   77,   78,   79,   96,   97,  870,
+   871,  898,  899,  100,  101,  102,  103,  104,  105,  106,  107,  108,  109,
+   180,  181,  900,  901,  980,  981,  110,  111,  112,  113,  114,  115,  116,
+   117,  118,  119,  190,  191,  910,  911,  990,  991,  120,  121,  122,  123,
+   124,  125,  126,  127,  128,  129,  182,  183,  920,  921,  908,  909,  130,
+   131,  132,  133,  134,  135,  136,  137,  138,  139,  192,  193,  930,  931,
+   918,  919,  140,  141,  142,  143,  144,  145,  146,  147,  148,  149,  184,
+   185,  940,  941,  188,  189,  150,  151,  152,  153,  154,  155,  156,  157,
+   158,  159,  194,  195,  950,  951,  198,  199,  160,  161,  162,  163,  164,
+   165,  166,  167,  168,  169,  186,  187,  960,  961,  988,  989,  170,  171,
+   172,  173,  174,  175,  176,  177,  178,  179,  196,  197,  970,  971,  998,
+   999,  200,  201,  202,  203,  204,  205,  206,  207,  208,  209,  280,  281,
+   802,  803,  882,  883,  210,  211,  212,  213,  214,  215,  216,  217,  218,
+   219,  290,  291,  812,  813,  892,  893,  220,  221,  222,  223,  224,  225,
+   226,  227,  228,  229,  282,  283,  822,  823,  828,  829,  230,  231,  232,
+   233,  234,  235,  236,  237,  238,  239,  292,  293,  832,  833,  838,  839,
+   240,  241,  242,  243,  244,  245,  246,  247,  248,  249,  284,  285,  842,
+   843,  288,  289,  250,  251,  252,  253,  254,  255,  256,  257,  258,  259,
+   294,  295,  852,  853,  298,  299,  260,  261,  262,  263,  264,  265,  266,
+   267,  268,  269,  286,  287,  862,  863,  888,  889,  270,  271,  272,  273,
+   274,  275,  276,  277,  278,  279,  296,  297,  872,  873,  898,  899,  300,
+   301,  302,  303,  304,  305,  306,  307,  308,  309,  380,  381,  902,  903,
+   982,  983,  310,  311,  312,  313,  314,  315,  316,  317,  318,  319,  390,
+   391,  912,  913,  992,  993,  320,  321,  322,  323,  324,  325,  326,  327,
+   328,  329,  382,  383,  922,  923,  928,  929,  330,  331,  332,  333,  334,
+   335,  336,  337,  338,  339,  392,  393,  932,  933,  938,  939,  340,  341,
+   342,  343,  344,  345,  346,  347,  348,  349,  384,  385,  942,  943,  388,
+   389,  350,  351,  352,  353,  354,  355,  356,  357,  358,  359,  394,  395,
+   952,  953,  398,  399,  360,  361,  362,  363,  364,  365,  366,  367,  368,
+   369,  386,  387,  962,  963,  988,  989,  370,  371,  372,  373,  374,  375,
+   376,  377,  378,  379,  396,  397,  972,  973,  998,  999,  400,  401,  402,
+   403,  404,  405,  406,  407,  408,  409,  480,  481,  804,  805,  884,  885,
+   410,  411,  412,  413,  414,  415,  416,  417,  418,  419,  490,  491,  814,
+   815,  894,  895,  420,  421,  422,  423,  424,  425,  426,  427,  428,  429,
+   482,  483,  824,  825,  848,  849,  430,  431,  432,  433,  434,  435,  436,
+   437,  438,  439,  492,  493,  834,  835,  858,  859,  440,  441,  442,  443,
+   444,  445,  446,  447,  448,  449,  484,  485,  844,  845,  488,  489,  450,
+   451,  452,  453,  454,  455,  456,  457,  458,  459,  494,  495,  854,  855,
+   498,  499,  460,  461,  462,  463,  464,  465,  466,  467,  468,  469,  486,
+   487,  864,  865,  888,  889,  470,  471,  472,  473,  474,  475,  476,  477,
+   478,  479,  496,  497,  874,  875,  898,  899,  500,  501,  502,  503,  504,
+   505,  506,  507,  508,  509,  580,  581,  904,  905,  984,  985,  510,  511,
+   512,  513,  514,  515,  516,  517,  518,  519,  590,  591,  914,  915,  994,
+   995,  520,  521,  522,  523,  524,  525,  526,  527,  528,  529,  582,  583,
+   924,  925,  948,  949,  530,  531,  532,  533,  534,  535,  536,  537,  538,
+   539,  592,  593,  934,  935,  958,  959,  540,  541,  542,  543,  544,  545,
+   546,  547,  548,  549,  584,  585,  944,  945,  588,  589,  550,  551,  552,
+   553,  554,  555,  556,  557,  558,  559,  594,  595,  954,  955,  598,  599,
+   560,  561,  562,  563,  564,  565,  566,  567,  568,  569,  586,  587,  964,
+   965,  988,  989,  570,  571,  572,  573,  574,  575,  576,  577,  578,  579,
+   596,  597,  974,  975,  998,  999,  600,  601,  602,  603,  604,  605,  606,
+   607,  608,  609,  680,  681,  806,  807,  886,  887,  610,  611,  612,  613,
+   614,  615,  616,  617,  618,  619,  690,  691,  816,  817,  896,  897,  620,
+   621,  622,  623,  624,  625,  626,  627,  628,  629,  682,  683,  826,  827,
+   868,  869,  630,  631,  632,  633,  634,  635,  636,  637,  638,  639,  692,
+   693,  836,  837,  878,  879,  640,  641,  642,  643,  644,  645,  646,  647,
+   648,  649,  684,  685,  846,  847,  688,  689,  650,  651,  652,  653,  654,
+   655,  656,  657,  658,  659,  694,  695,  856,  857,  698,  699,  660,  661,
+   662,  663,  664,  665,  666,  667,  668,  669,  686,  687,  866,  867,  888,
+   889,  670,  671,  672,  673,  674,  675,  676,  677,  678,  679,  696,  697,
+   876,  877,  898,  899,  700,  701,  702,  703,  704,  705,  706,  707,  708,
+   709,  780,  781,  906,  907,  986,  987,  710,  711,  712,  713,  714,  715,
+   716,  717,  718,  719,  790,  791,  916,  917,  996,  997,  720,  721,  722,
+   723,  724,  725,  726,  727,  728,  729,  782,  783,  926,  927,  968,  969,
+   730,  731,  732,  733,  734,  735,  736,  737,  738,  739,  792,  793,  936,
+   937,  978,  979,  740,  741,  742,  743,  744,  745,  746,  747,  748,  749,
+   784,  785,  946,  947,  788,  789,  750,  751,  752,  753,  754,  755,  756,
+   757,  758,  759,  794,  795,  956,  957,  798,  799,  760,  761,  762,  763,
+   764,  765,  766,  767,  768,  769,  786,  787,  966,  967,  988,  989,  770,
+   771,  772,  773,  774,  775,  776,  777,  778,  779,  796,  797,  976,  977,
+   998,  999};
+ 
+ static uint16_t BIN2DPD[1000]={    0,    1,    2,    3,    4,    5,    6,    7,
+     8,    9,   16,   17,   18,   19,   20,   21,   22,   23,   24,   25,   32,
+    33,   34,   35,   36,   37,   38,   39,   40,   41,   48,   49,   50,   51,
+    52,   53,   54,   55,   56,   57,   64,   65,   66,   67,   68,   69,   70,
+    71,   72,   73,   80,   81,   82,   83,   84,   85,   86,   87,   88,   89,
+    96,   97,   98,   99,  100,  101,  102,  103,  104,  105,  112,  113,  114,
+   115,  116,  117,  118,  119,  120,  121,   10,   11,   42,   43,   74,   75,
+   106,  107,   78,   79,   26,   27,   58,   59,   90,   91,  122,  123,   94,
+    95,  128,  129,  130,  131,  132,  133,  134,  135,  136,  137,  144,  145,
+   146,  147,  148,  149,  150,  151,  152,  153,  160,  161,  162,  163,  164,
+   165,  166,  167,  168,  169,  176,  177,  178,  179,  180,  181,  182,  183,
+   184,  185,  192,  193,  194,  195,  196,  197,  198,  199,  200,  201,  208,
+   209,  210,  211,  212,  213,  214,  215,  216,  217,  224,  225,  226,  227,
+   228,  229,  230,  231,  232,  233,  240,  241,  242,  243,  244,  245,  246,
+   247,  248,  249,  138,  139,  170,  171,  202,  203,  234,  235,  206,  207,
+   154,  155,  186,  187,  218,  219,  250,  251,  222,  223,  256,  257,  258,
+   259,  260,  261,  262,  263,  264,  265,  272,  273,  274,  275,  276,  277,
+   278,  279,  280,  281,  288,  289,  290,  291,  292,  293,  294,  295,  296,
+   297,  304,  305,  306,  307,  308,  309,  310,  311,  312,  313,  320,  321,
+   322,  323,  324,  325,  326,  327,  328,  329,  336,  337,  338,  339,  340,
+   341,  342,  343,  344,  345,  352,  353,  354,  355,  356,  357,  358,  359,
+   360,  361,  368,  369,  370,  371,  372,  373,  374,  375,  376,  377,  266,
+   267,  298,  299,  330,  331,  362,  363,  334,  335,  282,  283,  314,  315,
+   346,  347,  378,  379,  350,  351,  384,  385,  386,  387,  388,  389,  390,
+   391,  392,  393,  400,  401,  402,  403,  404,  405,  406,  407,  408,  409,
+   416,  417,  418,  419,  420,  421,  422,  423,  424,  425,  432,  433,  434,
+   435,  436,  437,  438,  439,  440,  441,  448,  449,  450,  451,  452,  453,
+   454,  455,  456,  457,  464,  465,  466,  467,  468,  469,  470,  471,  472,
+   473,  480,  481,  482,  483,  484,  485,  486,  487,  488,  489,  496,  497,
+   498,  499,  500,  501,  502,  503,  504,  505,  394,  395,  426,  427,  458,
+   459,  490,  491,  462,  463,  410,  411,  442,  443,  474,  475,  506,  507,
+   478,  479,  512,  513,  514,  515,  516,  517,  518,  519,  520,  521,  528,
+   529,  530,  531,  532,  533,  534,  535,  536,  537,  544,  545,  546,  547,
+   548,  549,  550,  551,  552,  553,  560,  561,  562,  563,  564,  565,  566,
+   567,  568,  569,  576,  577,  578,  579,  580,  581,  582,  583,  584,  585,
+   592,  593,  594,  595,  596,  597,  598,  599,  600,  601,  608,  609,  610,
+   611,  612,  613,  614,  615,  616,  617,  624,  625,  626,  627,  628,  629,
+   630,  631,  632,  633,  522,  523,  554,  555,  586,  587,  618,  619,  590,
+   591,  538,  539,  570,  571,  602,  603,  634,  635,  606,  607,  640,  641,
+   642,  643,  644,  645,  646,  647,  648,  649,  656,  657,  658,  659,  660,
+   661,  662,  663,  664,  665,  672,  673,  674,  675,  676,  677,  678,  679,
+   680,  681,  688,  689,  690,  691,  692,  693,  694,  695,  696,  697,  704,
+   705,  706,  707,  708,  709,  710,  711,  712,  713,  720,  721,  722,  723,
+   724,  725,  726,  727,  728,  729,  736,  737,  738,  739,  740,  741,  742,
+   743,  744,  745,  752,  753,  754,  755,  756,  757,  758,  759,  760,  761,
+   650,  651,  682,  683,  714,  715,  746,  747,  718,  719,  666,  667,  698,
+   699,  730,  731,  762,  763,  734,  735,  768,  769,  770,  771,  772,  773,
+   774,  775,  776,  777,  784,  785,  786,  787,  788,  789,  790,  791,  792,
+   793,  800,  801,  802,  803,  804,  805,  806,  807,  808,  809,  816,  817,
+   818,  819,  820,  821,  822,  823,  824,  825,  832,  833,  834,  835,  836,
+   837,  838,  839,  840,  841,  848,  849,  850,  851,  852,  853,  854,  855,
+   856,  857,  864,  865,  866,  867,  868,  869,  870,  871,  872,  873,  880,
+   881,  882,  883,  884,  885,  886,  887,  888,  889,  778,  779,  810,  811,
+   842,  843,  874,  875,  846,  847,  794,  795,  826,  827,  858,  859,  890,
+   891,  862,  863,  896,  897,  898,  899,  900,  901,  902,  903,  904,  905,
+   912,  913,  914,  915,  916,  917,  918,  919,  920,  921,  928,  929,  930,
+   931,  932,  933,  934,  935,  936,  937,  944,  945,  946,  947,  948,  949,
+   950,  951,  952,  953,  960,  961,  962,  963,  964,  965,  966,  967,  968,
+   969,  976,  977,  978,  979,  980,  981,  982,  983,  984,  985,  992,  993,
+   994,  995,  996,  997,  998,  999, 1000, 1001, 1008, 1009, 1010, 1011, 1012,
+  1013, 1014, 1015, 1016, 1017,  906,  907,  938,  939,  970,  971, 1002, 1003,
+   974,  975,  922,  923,  954,  955,  986,  987, 1018, 1019,  990,  991,   12,
+    13,  268,  269,  524,  525,  780,  781,   46,   47,   28,   29,  284,  285,
+   540,  541,  796,  797,   62,   63,   44,   45,  300,  301,  556,  557,  812,
+   813,  302,  303,   60,   61,  316,  317,  572,  573,  828,  829,  318,  319,
+    76,   77,  332,  333,  588,  589,  844,  845,  558,  559,   92,   93,  348,
+   349,  604,  605,  860,  861,  574,  575,  108,  109,  364,  365,  620,  621,
+   876,  877,  814,  815,  124,  125,  380,  381,  636,  637,  892,  893,  830,
+   831,   14,   15,  270,  271,  526,  527,  782,  783,  110,  111,   30,   31,
+   286,  287,  542,  543,  798,  799,  126,  127,  140,  141,  396,  397,  652,
+   653,  908,  909,  174,  175,  156,  157,  412,  413,  668,  669,  924,  925,
+   190,  191,  172,  173,  428,  429,  684,  685,  940,  941,  430,  431,  188,
+   189,  444,  445,  700,  701,  956,  957,  446,  447,  204,  205,  460,  461,
+   716,  717,  972,  973,  686,  687,  220,  221,  476,  477,  732,  733,  988,
+   989,  702,  703,  236,  237,  492,  493,  748,  749, 1004, 1005,  942,  943,
+   252,  253,  508,  509,  764,  765, 1020, 1021,  958,  959,  142,  143,  398,
+   399,  654,  655,  910,  911,  238,  239,  158,  159,  414,  415,  670,  671,
+   926,  927,  254,  255 };
+ 
+ const uint8_t DPDMOD[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
+ const uint8_t POWER[3] = { 100, 10, 1};
+ 
+ static int remove_trailing_zeros (char *, char **);
+ static void string_error (int status, char current);
+ 
+ /* Convert deciaml type to its string representation.  LEN is the length
+    of the decimal type, 4 bytes for decimal32, 8 bytes for decimal64 and
+    16 bytes for decimal128.  */
+ void
+ decimal_to_string (const uint8_t *dec, int len, char *s)
+ {
+   int i;
+   uint8_t sign = decimalGetSign (dec);	/* The signedness of DEC.  */
+   uint8_t comb = decimalGetComb (dec);	/* Combinator, 5 bits.  */
+   uint8_t top = dec[0] & 0x7f;		/* Top byte, less sign bit.  */
+   int bindex;
+   char dfp_suffix[3];
+   uint8_t msd;		/* The most significant digit of coefficient.  */
+   int16_t exp;		/* Exponent, a signed number.  */
+   uint8_t line, column;
+   char cfirst[128];	/* The first character of coefficient.  */ 
+   char *clast = cfirst; /* The last character of coefficient.  */
+   int start = 0;	/* Found the first non-zero in the coefficient?  */
+   int cdigits;		/* The number of the digits in the coefficient.  */
+ 
+   /* Initialize some length-related data.  */
+   switch (len)
+     {
+     case 4:
+       bindex = 0;
+       strncpy (dfp_suffix, "df", 3);
+       exp = decimal32GetExpCon (dec) - DECIMAL32_Bias;
+       break;
+     case 8:
+       bindex = 1;
+       strncpy (dfp_suffix, "dd", 3);
+       exp = decimal64GetExpCon (dec) - DECIMAL64_Bias;
+       break;
+     case 16:
+       bindex = 2;
+       strncpy (dfp_suffix, "dl", 3);
+       exp = decimal128GetExpCon (dec) - DECIMAL128_Bias;
+       break;
+     default:
+       error ("We don't support decimal number of %d bytes yet.", len);
+     }
+ 
+   if (top >= DECIMAL_sNaN)
+     {
+       if (sign == 1)
+ 	strcpy (s, "-sNaN");
+       else
+ 	strcpy (s, "sNaN");
+       return;
+     }
+ 
+   if (top >= DECIMAL_NaN)
+     {
+       if (sign == 1)
+ 	strcpy (s, "-NaN");
+       else
+ 	strcpy (s, "NaN");
+       return;
+     }
+ 
+   if (top >= DECIMAL_Inf)
+     {
+       if (sign == 1)
+ 	strcpy (s, "-Infinity");
+       else
+ 	strcpy (s, "Infinity");
+       return;
+     }
+ 
+   /* This decimal is a finite number.  We try to get the MSD of the 
+      coefficient and the exponent first.  */
+   if (comb >= 0x18)
+     {
+       msd = 8 + (comb & 0x01);
+       exp += (comb & 0x06) << (bits[bindex][2] - 1);
+     }
+   else
+     {
+       msd = comb & 0x07;
+       exp += (comb & 0x18) << (bits[bindex][2] - 3);
+     }
+ 
+   /* From here on, we will try to get the string representation of the 
+      coefficient.  */
+   if (msd)
+     {
+       /* If MSD is non-zero, add it into coeff and set the start flag.  */
+       sprintf (clast, "%d", msd);
+       clast++;
+       start = 1;
+     }
+ 
+   /* We first get the starting position (line and column) of the coefficient.
+      Then get a group of 10 bits, transfer it to a unsigned short (dpdigits),
+      and get its corresponsing 3-digits representation (bin).  And then we
+      will add it into coeff and advance 10 bits to another group of 
+      10-bits until we get to the end.  In this process, we need to adapt the
+      string representaion of each 3-digits according to its real digit number
+      and the start flag.  */
+   line = (bits[bindex][0] + bits[bindex][1] + bits[bindex][2]) / 8;
+   column = (bits[bindex][0] + bits[bindex][1] + bits[bindex][2]) % 8;
+   for (i = 0; i < bits[bindex][3] / 10; i++)
+     {
+       uint16_t dpdigits = ((dec[line] & DPDMOD [7 - column]) << (2 + column))
+ 			  + (dec[line + 1] >> (6 - column));
+       uint16_t bin = DPD2BIN[dpdigits];
+ 
+       line++;
+       column += 2;
+       if (column == 8)
+ 	{
+ 	  column = 0;
+ 	  line++;
+ 	}
+ 
+       if (bin)
+ 	{
+ 	  if (!start)
+ 	    {
+ 	      sprintf (clast, "%d", bin);
+ 	      if (bin < 10)
+ 		clast += 1;
+ 	      else if (bin < 100)
+ 		clast += 2;
+ 	      else
+ 		clast += 3;
+ 	      start = 1;
+ 	    }
+ 	  else
+ 	    {
+ 	      if (bin < 10)
+ 		sprintf (clast, "00%d", bin);
+ 	      else if (bin < 100)
+ 		sprintf (clast, "0%d", bin);
+ 	      else
+ 		sprintf (clast, "%d", bin);
+ 	      clast += 3;
+ 	    }
+ 	}
+       else
+ 	{
+ 	  if (start)
+ 	    {
+ 	      sprintf(clast, "000");
+ 	      clast += 3;
+ 	    }
+ 	  continue;
+ 	}
+     }
+ 
+   /* If start still equals 0, then DEC is 0.  After adding a trailing '.'
+      and suffix, we can return to calling function at this point.  */
+   if (start == 0)
+     {
+       sprintf(s, "0.%s", dfp_suffix);
+       return;
+     }
+ 
+   exp += remove_trailing_zeros (cfirst, &clast);
+ 
+   /* If exp quals 0, then we already get DEC's string representation.  Add
+      a trailing '.' and suffix, and return.  */
+   if (exp == 0)
+     {
+       if (sign)
+ 	sprintf (s, "-%s.%s", cfirst, dfp_suffix);
+       else
+ 	sprintf (s, "%s.%s", cfirst, dfp_suffix);
+       return;
+     }
+ 
+   cdigits = (int)(clast - cfirst);
+   if (exp > 0  || (exp + cdigits) < -5)
+     {
+       char temps[128];		/* A temp string. */
+       char *c = temps;
+       char *digit;
+ 
+       if (sign)
+ 	{
+ 	  sprintf (c, "-");
+ 	  c++;
+ 	}
+ 
+       exp += cdigits - 1;
+       *c++ = *cfirst;
+       *c++ = '.';
+       for (digit = cfirst + 1; ;c++, digit++)
+ 	{
+ 	  if (digit == clast )
+ 	    break;
+ 	  *c = *digit;
+ 	}
+ 
+       if (exp > 0)
+ 	sprintf (c, "E+%d", exp);
+       else if (exp < 0)
+ 	sprintf (c, "E%d", exp);
+       else
+ 	*c = '\0';
+ 
+       sprintf (s, "%s%s", temps, dfp_suffix);
+     }
+   else
+     {
+       char temps[128];	/* A temp string.  */
+       char *c = temps;
+       char *digit = cfirst;
+ 
+       if (sign)
+         {
+           sprintf (c, "-");
+           c++;
+         }
+ 
+       /* Digits left to dot */
+       if ((cdigits + exp) > 0)
+         {
+           exp = cdigits + exp;
+           for (i = 0; i < exp; i++)
+             *c++ = *digit++;
+           sprintf (c, ".");
+           c++;
+         }
+       else
+         {
+           exp = -(exp + cdigits) + 1;
+           sprintf (c, "0.");
+           c += 2;
+           for (i = 1; i < exp; i++)
+             {
+               sprintf (c,"0");
+               c++;
+             }
+         }
+ 
+       for(;;c++, digit++)
+         {
+           if ( digit == clast )
+             break;
+           *c = *digit;
+         }
+       /* Trail temps with '\0'.  */
+       *c = '\0';
+       sprintf (s, "%s%s",temps, dfp_suffix);
+     }
+   return;
+ }
+ 
+ static int
+ remove_trailing_zeros (char *cfirst, char **pclast)
+ {
+   char *digit = *pclast - 1;
+   int trailing_zeros = 0;
+ 
+   while (digit >= cfirst)
+     if (*digit-- == '0')
+       trailing_zeros++;
+     else
+       break;
+ 
+   *pclast = *pclast - trailing_zeros;
+   **pclast = '\0';
+   return trailing_zeros;
+ }
+ 
+ int
+ decStrEq (const char *str1, const char *str2)
+ {
+   for (;;str1++, str2++)
+     {
+       if (*str1 == *str2)
+ 	{
+ 	  if (*str1 == '\0')
+ 	    break;
+ 	}
+       else
+ 	{
+ 	  if (tolower(*str1) != tolower(*str2))
+ 	    return 0;
+ 	}
+     }
+ 
+   return 1;
+ }
+ 
+ int
+ decimal_from_string (uint8_t *dec, int len, char *string)
+ {
+   int status = 0;
+   int i;
+   int sign = 0;                 /* The signedness of DEC.  */
+   int exp = 0;                  /* Exponent, a signed number.  */
+   int indicator = 0;		/* To indicate the type of the DEC.  */
+   int isZero = 0;               /* Is cofficient 0?  */
+   int lpad, rpad;               /* The number of left or right padding '0'.  */
+   const char *dotchar = NULL;   /* Where dot was found.  */
+   const char *cfirst;           /* The first digit of coefficient.  */
+   const char *clast = NULL;     /* The last digit of coefficient.  */
+   int   d=0;               	/* The count of digits in the coefficient.  */
+ 
+   int bindex;
+   int dfp_pmax, dfp_emax, dfp_emin, dfp_bias;
+ 
+   /* Initializing the dec array and type-related variables.  */
+ 
+   for (i = 0; i < len; i++)
+     dec[i] = 0;
+ 
+   switch (len)
+     {
+     case 4:
+       bindex = 0;
+       dfp_pmax = DECIMAL32_Pmax;
+       dfp_emax = DECIMAL32_Emax;
+       dfp_emin = DECIMAL32_Emin;
+       dfp_bias = DECIMAL32_Bias;
+       break;
+     case 8:
+       bindex = 1;
+       dfp_pmax = DECIMAL64_Pmax;
+       dfp_emax = DECIMAL64_Emax;
+       dfp_emin = DECIMAL64_Emin;
+       dfp_bias = DECIMAL64_Bias;
+       break;
+     case 16:
+       bindex = 2;
+       dfp_pmax = DECIMAL128_Pmax;
+       dfp_emax = DECIMAL128_Emax;
+       dfp_emin = DECIMAL128_Emin;
+       dfp_bias = DECIMAL128_Bias;
+       break;
+     default:
+       error ("There is no decimal floating point of length %d", len);
+     }
+ 
+   do
+     {
+       const char *c = string; 
+ 
+       /* Handle leading '-' or '+'.  */
+       if (*c == '-')
+ 	sign = 1;
+       if (*c == '-' || *c == '+')
+ 	c++;
+ 
+       /* We're at the start of the number.  */
+       cfirst = c;
+       for (;; c++)
+ 	{
+ 	  if (*c >= '0' && *c <= '9')
+ 	    { 
+ 	      /* Test for decimal digit.  */
+ 	      clast = c;
+ 	      d++;			/* Count of real digits.  */
+ 	      continue;			/* Still in decimal part.  */
+ 	    }
+ 	  if (*c != '.')
+ 	     break;			/* Done with decimal part.  */
+ 
+ 	  /* Find another dot, break and report error.  */
+ 	  if (dotchar != NULL)
+ 	    {
+ 	      clast = NULL;
+ 	      break;
+ 	    } 
+ 	  dotchar = c;			/* The offset into decimal part */
+ 	}
+ 
+       /* No decimal digits found, maybe Infinity or NaNs.  */
+       if (clast == NULL)
+ 	{
+ 	  if (decStrEq (c, "Infinity") || decStrEq (c, "Inf"))
+ 	    {
+ 	      indicator = DECIMAL_Inf;
+ 	      break;			/* All done.  */
+ 	    }
+ 	  else
+ 	    { /* A NaN expected. */
+ 	      status = SYNTAX_ERROR;		/* Assume the worst.  */
+ 	      indicator = DECIMAL_NaN;		/* Assume simple NaN.  */
+ 
+ 	      /* If c begins with 's' or 'S', it might be "sNaN".  */
+ 	      if (*c == 's' || *c == 'S')
+ 		{
+ 		  c++;
+ 		  indicator = DECIMAL_sNaN;
+ 		}
+ 	      /* Check caseless "NaN".  */
+ 	      if (!strcasecmp (c, "NaN"))
+ 		c += 3;
+ 	      else
+ 		string_error (INVALID_CHAR, *c);
+ 
+ 	      /* Skip leading 0s.  */
+ 	      for (cfirst = c; *cfirst == '0';)
+ 		cfirst++;
+ 	      if (*cfirst == '\0')
+ 		{ /* "NaN" or "sNaN", maybe with all 0s */
+ 		  status = 0;                   /* It's good.  */
+ 		  break;
+ 		}
+ 
+ 	      /* Something other than 0s; setup clast and d as usual.  */
+ 	      for (c = cfirst;; c++, d++)
+ 		{
+ 		  if (*c < '0' || *c > '9')
+ 		    break; 			/* Test for Arabic digit.  */
+ 		  clast = c;
+ 		}
+ 
+ 	      /* If not all digits, report error and exit.  */
+ 	      if (*c != '\0')
+ 		string_error (INVALID_CHAR, *c);
+ 
+ 	      /* Good; set status to ok.  */
+ 	      status = 0;
+ 	    }
+ 	}
+ 
+       /* If it is not at the end yet, we need to see whether it is the 
+ 	 exponent part.  */
+       if (*c != '\0')
+ 	{
+ 	  int esign = 0;
+ 	  const char *firstexp;	/* The first significant exponent digit.  */
+ 
+ 	  if (*c != 'e' && *c != 'E')
+ 	    string_error (INVALID_CHAR, *c);
+ 
+ 	  /* Found 'e' or 'E', process explicit exponent.  */
+ 	  c++;
+ 	  if (*c == '-')
+ 	    {
+ 	      esign = 1;
+ 	      c++;
+ 	    }
+ 	  else if (*c == '+')
+ 	    c++;
+ 	  
+ 	  if (*c == '\0')
+ 	    string_error (DIGIT_EXPECTED, *(c - 1));
+ 
+ 	  /* Strip insignificant zeros.  */
+ 	  for (; *c == '0' && *(c+1) != '\0';)
+ 	    c++;  
+ 
+ 	  firstexp = c;		/* Save exponent digit place.  */
+ 	  for (; ;c++)
+ 	    {
+ 	      if (*c < '0' || *c > '9')
+ 		break;    /* Not a digit.  */
+ 	      exp = X10 (exp) + (int)*c - (int)'0';
+ 	    }
+ 	  /* If it doesn't end on '\0', report the error.  */
+ 	  if (*c != '\0')
+ 	    string_error (INVALID_CHAR, *c);
+ 
+ 	  if (c - firstexp + 1 > 9)
+ 	    string_error (EXP_OUTOFRANGE, *c);
+ 
+ 	  if (esign)
+ 	    exp = -exp;
+ 	}
+ 
+       /* Handle decimal point... */
+       if (dotchar != NULL && dotchar < clast)
+ 	exp = exp - (clast - dotchar);
+ 
+       /* Strip leading zeros/dot (leave final if all 0's).  */
+       for (c = cfirst; c < clast; c++)
+ 	{
+ 	  if (*c == '0')
+ 	    d--;		/* 0 stripped.  */
+ 	  else if (*c != '.')
+ 	    break;
+ 	  cfirst++;		/* Step past leader.  */
+ 	}
+ 
+       /* Get the count of padding zeros and the value of exponent.  And
+ 	 if there are any out of range, report error.  */
+       rpad = 0;
+       if (d > dfp_pmax)
+ 	string_error (COEFF_OUTOFRANGE, 0);
+       else if (exp < (dfp_emin - dfp_pmax + 1) || exp > (dfp_emax - d +1))
+ 	string_error (EXP_OUTOFRANGE, 0);
+       else if (exp > (dfp_emax - dfp_pmax + 1))
+ 	{
+ 	  rpad += exp - (dfp_emax - dfp_pmax + 1);
+ 	  exp = dfp_emax - dfp_pmax + 1 + dfp_bias;
+ 	  lpad = dfp_pmax - d - rpad; 
+ 	}
+       else
+ 	{
+ 	  lpad = dfp_pmax - d;
+ 	  exp += dfp_bias;
+ 	} 
+ 
+     } while (0);
+ 
+   /* If status non-zero, there must be some error in the input string.  */
+ 
+   if (status)
+     string_error (status, 0);
+ 
+   /* Begin to transfer the string representation to decimal type.  */
+ 
+   if (sign)
+     decimalSetSign (dec, sign);
+ 
+   if (!indicator)
+     { 
+       char cc[128];	/* The string of coefficient continuation.  */
+       char *s = cc;
+       const char *c;
+       uint8_t comb;	/* Combinator, 5 bits.  */
+       uint8_t msd;	/* The most significant digit of coefficient.  */
+       uint8_t line, column;
+  
+       /* It is a finite number, we need to get MSD cofficient first.  */
+       if (lpad > 0)
+ 	{
+ 	  msd = 0;
+ 	  lpad -= 1;
+ 	}
+       else
+ 	{
+ 	  msd = *cfirst - '0';
+ 	  if (cfirst == clast)
+ 	    {
+ 	      cfirst = NULL;
+ 	    }
+ 	  else
+ 	    cfirst++;
+ 	}
+       if (msd == 0)
+ 	isZero = 1;
+ 
+       /* Set combinator bits.  */
+       if (msd >= 8)
+ 	comb = (msd & 0x1) + (((exp >> bits[bindex][2]) & 0x3) << 1) + 0x18;
+       else
+ 	comb = (msd & 0x7 ) + (((exp >> bits[bindex][2]) & 0x3) << 3);
+       decimalSetComb (dec, comb);
+ 
+       /* Set exponent continuation bits.  */
+       if (len == 4)
+ 	{
+ 	  exp &= 0x3F;
+ 	  decimal32SetExpCon (dec, exp);
+ 	}
+       if (len == 8)
+ 	{
+ 	  exp &= 0xFF;
+ 	  decimal64SetExpCon (dec, exp);
+ 	}
+       if (len == 16)
+ 	{
+ 	  exp &= 0x0FFF;
+ 	  decimal128SetExpCon (dec, exp);
+ 	}
+ 
+       /* Get the clean coefficient continuation string first.  */
+ 
+       while (lpad--)
+ 	*s++ = '0';
+ 
+       for (c = cfirst; c != NULL; c++)
+ 	{
+ 	  if (*c == '.')
+ 	    {
+ 	      if (c != clast)
+ 		continue;
+ 
+ 	      break;
+ 	    }
+ 	  *s = *c;
+ 	  s++;
+ 	  if (isZero && (*c != '0'))
+ 	    isZero = 0;
+ 	  if (c == clast)
+ 	    break;
+ 	}
+ 
+       while (rpad--)
+ 	*s++ = '0';
+ 
+       *s = '\0';
+ 
+       /* Then try to set these coefficient continuation bits in the resulting
+ 	 decimal variable.  */
+ 
+       line = (bits[bindex][0] + bits[bindex][1] + bits[bindex][2]) / 8;
+       column = (bits[bindex][0] + bits[bindex][1] + bits[bindex][2]) % 8;
+       s = cc;
+ 
+       for (i = 0; i < bits[bindex][3] / 10; i++)
+         {
+ 	  int j; 
+           uint16_t dpd, bin = 0;
+ 
+ 	  /* Firstly, get bin from cc string.  */
+ 	  for (j = 0; j < 3; j++)
+ 	    {
+ 	      bin += (*s - '0') * POWER[j];
+ 	      s++;
+ 	    }
+ 
+ 	  /* Then, map bin to DPD.  */
+ 	  dpd = BIN2DPD[bin];
+ 
+ 	  /* Last, set dec array using what we just got above.  */
+ 	  dec[line] |= (dpd >> (2+column));
+ 	  dec[line+1] |= ((dpd & DPDMOD[1+column]) << (6-column));
+ 
+ 	  /* Go on to the next 10-bits group.  */
+ 	  line++;
+ 	  column += 2;
+ 	  if (column == 8)
+ 	    {
+ 	      column = 0;
+ 	      line++;
+ 	    }
+ 	}
+     }
+   else
+     { /* It is Inf, sNaN or qNaN.  */ 
+       uint8_t comb;
+ 
+       if (indicator == DECIMAL_Inf)
+ 	{
+ 	  comb = 0x1E;
+ 	  decimalSetComb (dec, comb);
+ 	}
+       else
+ 	{
+ 	  comb = 0x1F;
+ 	  decimalSetComb (dec, comb);
+ 	  if (indicator == DECIMAL_sNaN)
+ 	    dec[0] |= 0x2;
+ 	}
+     }
+ 
+   return status;
+ }
+ 
+ static void
+ string_error (int status, char current)
+ {
+   switch (status)
+     {
+     case COEFF_OUTOFRANGE:
+       error ("The coefficient is out of range.");
+     case EXP_OUTOFRANGE:
+       error ("The exponent is out of range.");
+     case INVALID_CHAR:
+       error ("Invalid char found by dfp, near \'%c\'", current);
+     case DIGIT_EXPECTED:
+       error ("Digit expected, get a non-digit instead, near \'%c\'.", current);
+     case SYNTAX_ERROR:
+       error ("There are syntax error in the above decimal.");
+     }
+ }
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.756
diff -c -3 -p -r1.756 Makefile.in
*** Makefile.in	13 Oct 2005 09:31:59 -0000	1.756
--- Makefile.in	18 Oct 2005 08:22:06 -0000
*************** dictionary_h = dictionary.h
*** 663,668 ****
--- 663,669 ----
  disasm_h = disasm.h
  doublest_h = doublest.h $(floatformat_h)
  dummy_frame_h = dummy-frame.h
+ dfp_h = dfp.h
  dwarf2expr_h = dwarf2expr.h
  dwarf2_frame_h = dwarf2-frame.h
  dwarf2loc_h = dwarf2loc.h
*************** COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $
*** 896,902 ****
  	auxv.o \
  	bfd-target.o \
  	blockframe.o breakpoint.o findvar.o regcache.o \
! 	charset.o disasm.o dummy-frame.o \
  	source.o value.o eval.o valops.o valarith.o valprint.o printcmd.o \
  	block.o symtab.o symfile.o symmisc.o linespec.o dictionary.o \
  	infcall.o \
--- 897,903 ----
  	auxv.o \
  	bfd-target.o \
  	blockframe.o breakpoint.o findvar.o regcache.o \
! 	charset.o disasm.o dummy-frame.o dfp.o \
  	source.o value.o eval.o valops.o valarith.o valprint.o printcmd.o \
  	block.o symtab.o symfile.o symmisc.o linespec.o dictionary.o \
  	infcall.o \
*************** dsrec.o: dsrec.c $(defs_h) $(serial_h) $
*** 1883,1888 ****
--- 1884,1890 ----
  dummy-frame.o: dummy-frame.c $(defs_h) $(dummy_frame_h) $(regcache_h) \
  	$(frame_h) $(inferior_h) $(gdb_assert_h) $(frame_unwind_h) \
  	$(command_h) $(gdbcmd_h) $(gdb_string_h)
+ dfp.o: dfp.c $(defs_h) $(dfp_h)
  dve3900-rom.o: dve3900-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \
  	$(serial_h) $(inferior_h) $(command_h) $(gdb_string_h) $(regcache_h) \
  	$(mips_tdep_h)
		 

Best Regards
- Wu Zhou


On Wed, 12 Oct 2005, Daniel Jacobowitz wrote:

> On Wed, Oct 12, 2005 at 10:46:22PM +0800, Wu Zhou wrote:
> > > Or just use the decNumber packed representation, in value_contents().
> > > Take a look at all the references to FLOATFORMAT to see how we handle
> > > floating point types.
> > 
> > I did had some looks at FLOATFORMAT, but found that there are quite
> > some difference between DFP encoding format and normal binary floating
> > encoding format: for example, dfp's fields is composed of combinator
> > bits, exponent continuation bits and coefficient continuation bits.  
> > While most bfp floatformat is composed of two fields (exponent bits 
> > and coefficient bits).  And they also have different representation 
> > for non-finite number (infinity and NaN).  
> 
> Yes, sorry - I wasn't suggesting that you define floatformats for
> these, just that you handle them in the same set of places that we
> handle floatformats.
> 
> > So I am now thinking of adding a builtin type other than TYPE_CODE_FLT to
> > represent dfp.  This type (I am thinking of using TYPE_CODE_DECFLT) will 
> > have three fundamental type like TYPE_CODE_FLT for different sizes. In the
> > fields it will have four fields: signedness, combinator, exponent 
> > continuation and coefficient continuation.  And these fields will merged 
> > together into value.aligner.contents.  In this way, we can not only 
> > support the setting and printing of dfp types (constants or variables), 
> > but also can add other feature (such as arithmetic operation) as needed. 
> > 
> > Is there any clear deficiency in this method?  Do you think that it is 
> > feasible? and also extensible?  I will start to code in this direction if 
> > there is not any obvous weakness.
> 
> This may be what you're saying, but the only copy of the data should be
> in value_contents, not duplicated in unpacked form elsewhere.
> 
> Yes, I think introducing a new type code is a good idea; that will be
> more robust than reusing TYPE_CODE_FLT.  There are 230 references to
> TYPE_CODE_FLT in gdb; many of them you'd want to handle DECFLT the same
> way, but many you wouldn't.  For instance, calling functions which take
> decimal floating point arguments.
> 
> -- 
> Daniel Jacobowitz
> CodeSourcery, LLC
> 
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2005-10-18 10:02 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-09-28  4:40 [RFC] Decimal Floating Point support for GDB (Part 1: patch) Wu Zhou
2005-09-28 18:40 ` Eli Zaretskii
2005-09-29  2:12   ` Wu Zhou
2005-09-29  3:34     ` Eli Zaretskii
2005-10-02 21:00 ` Daniel Jacobowitz
2005-10-03 15:38   ` [RFC] Decimal Floating Point support for GDB (Part 1: patch)(a sidebar) Paul Gilliam
2005-10-03 15:41     ` Daniel Jacobowitz
2005-10-09  4:06       ` Wu Zhou
2005-10-09  5:23   ` [RFC] Decimal Floating Point support for GDB (Part 1: patch) Wu Zhou
2005-10-09 20:08     ` Daniel Jacobowitz
2005-10-12 14:42       ` Wu Zhou
2005-10-12 14:49         ` Daniel Jacobowitz
2005-10-18 10:02           ` [RFC] Decimal Floating Point support for GDB (Part 1: patch - Rewrited) Wu Zhou

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox