diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 55cadab44504e863d8f4a99a1a2af3e32ccee389..5c7529b7293ff53e4fa566e3a096ec34f958e4ff 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -518,7 +518,7 @@
 
    <para>
     <table tocentry="1">
-     <title>Format-pictures for datetime to_char() version.</title>
+     <title>Format-pictures for date/time to_char() version.</title>
      <tgroup cols="2">
       <thead>
        <row>
@@ -662,12 +662,12 @@
 
    <para>
     All format-pictures	allow use suffixes (postfix / prefix). The suffix is 
-    always valid for near format-picture. The 'FX' is global prefix only.      
+    always valid for a near format-picture. The 'FX' is global prefix only.      
    </para>
 
    <para>
     <table tocentry="1">
-     <title>Suffixes for format-pictures for datetime to_char() version.</title>
+     <title>Suffixes for format-pictures for date/time to_char() version.</title>
      <tgroup cols="3">
       <thead>
        <row>
@@ -695,7 +695,7 @@
        <row>
 	<entry> FX </entry>
 	<entry> FX - (Fixed format) global format-picture switch. 
-	 the TO_DATETIME / TO_DATA skip blank space if this option is
+	 The TO_DATETIME / TO_DATE skip blank space if this option is
 	 not use. Must by used as first item in formt-picture. </entry>
 	<entry> FX Month DD Day </entry>
        </row>	
@@ -714,7 +714,7 @@
    </para>
    <para>
      '"' - string between a quotation marks is skipen and not is parsed. 
-     If you want write '"' to output you must use \\", exapmle '\\"YYYY Month\\"'.
+     If you want write '"' to output you must use \\", example '\\"YYYY Month\\"'.
    </para>
    <para>
      text - the PostgreSQL's to_char() support text without '"', but string 
@@ -776,7 +776,11 @@
        </row>
        <row>
 	<entry> PL </entry>
-	<entry> return plus sign on specified position (if number > 0) </entry>
+	<entry> return plus sign on specified position (if number > 0) - PostgreSQL extension </entry>
+       </row>
+       <row>
+	<entry> SG </entry>
+	<entry> return plus/minus sign on specified position - PostgreSQL extension </entry>
        </row>
        <row>
 	<entry> RN </entry>
@@ -784,7 +788,7 @@
        </row>
        <row>
 	<entry> TH or th </entry>
-	<entry> convert number to ordinal number (not convert numbers under zero and decimal numbers) </entry>
+	<entry> convert number to ordinal number (not convert numbers under zero and decimal numbers) - PostgreSQL extension </entry>
        </row>
        <row>
 	<entry> V </entry>
@@ -801,9 +805,12 @@
    </para>
 
    <para>
-    The PostgreSQL to_char() not support absurd to_char(0.1, '99.99') 
-    --> <ProgramListing> '   .10' </ProgramListing> format. 
-   </para>
+      Note: A sign formatted via 'SG', 'PL' or 'MI' is not anchor in number;
+      to_char(-12, 'S9999') produce: <ProgramListing> '  -12' </ProgramListing>, 
+      but to_char(-12, 'MI9999') produce: <ProgramListing> '-  12' </ProgramListing>. 
+      The Oracle not allow use 'MI' ahead of '9', in the Oracle must be it always
+      after '9'.
+   </para>   
 
    <para>
     <table tocentry="1">
@@ -825,16 +832,24 @@
         <entry><ProgramListing> 'Tuesday, 05:39:18' </ProgramListing></entry>
        </row>          
        <row>
-        <entry> to_char( 0.1, '99.99') </entry>
-        <entry><ProgramListing> '  0.10' </ProgramListing></entry>
+        <entry> to_char( -0.1, '99.99') </entry>
+        <entry><ProgramListing> ' -.10' </ProgramListing></entry>
+       </row>
+       <row>
+        <entry> to_char( -0.1, 'FM9.99') </entry>
+        <entry><ProgramListing> '-.1' </ProgramListing></entry>
        </row>
        <row>
         <entry> to_char( 0.1, '0.9') </entry>
         <entry><ProgramListing> ' 0.1' </ProgramListing></entry>
        </row>
        <row>
-        <entry> to_char( 0.1, '090.9') </entry>
-        <entry><ProgramListing> ' 000.1' </ProgramListing></entry>
+        <entry> to_char( 12, '9990999.9') </entry>
+        <entry><ProgramListing> '    0012.0' </ProgramListing></entry>
+       </row>
+       <row>
+        <entry> to_char( 12, 'FM9990999.9') </entry>
+        <entry><ProgramListing> '0012' </ProgramListing></entry>
        </row>
        <row>
         <entry> to_char( 485, '999') </entry>
@@ -844,18 +859,6 @@
         <entry> to_char( -485, '999') </entry>
         <entry><ProgramListing> '-485' </ProgramListing></entry>
        </row>
-       <row>
-        <entry> to_char( 485, '09999') </entry>
-        <entry><ProgramListing> ' 00485' </ProgramListing></entry>
-       </row>
-       <row>
-        <entry> to_char( 485, 'FM09999') </entry>
-        <entry><ProgramListing> '00485' </ProgramListing></entry>
-       </row>
-       <row>
-        <entry> to_char( 485, 'FM999') </entry>
-        <entry><ProgramListing> '485' </ProgramListing></entry>
-       </row>
        <row>
         <entry> to_char( 485, '9 9 9') </entry>
         <entry><ProgramListing> ' 4 8 5' </ProgramListing></entry>
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 3a5a942f050ca1dba3f8c22fa3e1f25a38d0202f..e8f6d2cd4772e126517ef812e1aad2064ed46169 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -1,15 +1,17 @@
 /* -----------------------------------------------------------------------
  * formatting.c
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.2 2000/01/26 06:33:49 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.3 2000/02/08 15:56:55 momjian Exp $
+ *
+ *
+ *   Portions Copyright (c) 1999-2000, PostgreSQL, Inc
+ *
  *
  *   TO_CHAR(); TO_DATETIME(); TO_DATE(); TO_NUMBER();  
  *
  *   The PostgreSQL routines for a DateTime/int/float/numeric formatting, 
  *   inspire with Oracle TO_CHAR() / TO_DATE() / TO_NUMBER() routines.  
  *
- *   1999 Karel Zak "Zakkr"
- *
  *
  *   Cache & Memory:
  *	Routines use (itself) internal cache for format pictures. If 
@@ -33,13 +35,16 @@
  *
  *  Supported types for to_char():
  *		
- *		DateTime, Numeric, int4, int8, float4, float8
+ *		Timestamp, DateTime, Numeric, int4, int8, float4, float8
  *
  *  Supported types for reverse conversion:
  *
  *		Datetime	- to_datetime()
  *		Date		- to_date()
  *		Numeric		- to_number()		
+ *  
+ * 
+ *	Karel Zak - Zakkr	
  *
  * -----------------------------------------------------------------------
  */
@@ -106,8 +111,8 @@
  * External (defined in PgSQL dt.c (datetime utils)) 
  * ----------
  */
-extern  char		*months[],		/* month abbreviation   */
-			*days[];		/* full days		*/
+extern  char		*months[],	/* month abbreviation   */
+			*days[];	/* full days		*/
 
 /* ----------
  * Format parser structs             
@@ -231,11 +236,13 @@ static int DCH_global_flag	= 0;
  */
 typedef struct {
 	int	pre,			/* (count) numbers before decimal */
-		pos,			/* (count) numbers after decimal  */
+		post,			/* (count) numbers after decimal  */
 		lsign,			/* want locales sign		  */
 		flag,			/* number parametrs		  */
 		pre_lsign_num,		/* tmp value for lsign		  */	
 		multi,			/* multiplier for 'V'		  */
+		zero_start,		/* position of first zero	  */
+		zero_end,		/* position of last zero	  */
 		need_locale;		/* needs it locale		  */ 
 } NUMDesc;
 
@@ -270,6 +277,7 @@ typedef struct {
 #define	IS_FILLMODE(_f)	((_f)->flag & NUM_F_FILLMODE)
 #define	IS_BRACKET(_f)	((_f)->flag & NUM_F_BRACKET)
 #define IS_MINUS(_f)	((_f)->flag & NUM_F_MINUS)
+#define IS_LSIGN(_f)	((_f)->flag & NUM_F_LSIGN)
 #define IS_PLUS(_f)	((_f)->flag & NUM_F_PLUS)
 #define IS_ROMAN(_f)	((_f)->flag & NUM_F_ROMAN)
 #define IS_MULTI(_f)	((_f)->flag & NUM_F_MULTI)
@@ -350,12 +358,13 @@ static KeySuffix DCH_suff[] = {
  *    Position for the keyword is simular as position in the enum DCH/NUM_poz 
  * (!)
  *
- * For fast search is used the 'int index[256-32]' (first 32 ascii chars is 
- * skiped), in this index is DCH_ enums for each ASCII position or -1 if 
- * char is not used in the KeyWord. Search example for string "MM":
- * 	1)	see in index to index[77-32] (77 = 'M'), 
- *	2)	take keywords position from index[77-32]
- *	3)	run sequential search in keywords[] from position   
+ * For fast search is used the 'int index[]', index is ascii table from position 
+ * 32 (' ') to 126 (~), in this index is DCH_ / NUM_ enums for each ASCII 
+ * position or -1 if char is not used in the KeyWord. Search example for 
+ * string "MM":
+ * 	1)	see in index to index['M' - 32], 
+ *	2)	take keywords position (enum DCH_MM) from index
+ *	3)	run sequential search in keywords[] from this position   
  *
  * ----------
  */
@@ -512,7 +521,7 @@ static int DCH_index[256 - 32] = {
 /*
 0	1	2	3	4	5	6	7	8	9
 */
-	/*---- first 0..31 chars is skiped ----*/
+	/*---- first 0..31 chars are skiped ----*/
 
 		-1,	-1,	-1,	-1,	-1,	-1,	-1,	-1,
 -1,	-1,	-1,	-1,	-1,	-1,	-1,	-1,	-1,	-1,
@@ -562,18 +571,24 @@ typedef struct NUMProc
 {
 	int	type;		/* FROM_CHAR (TO_NUMBER) or TO_CHAR */
 
-	NUMDesc	*Num;		/* number description	*/	
+	NUMDesc	*Num;		/* number description		*/	
+	
+	int	sign,		/* '-' or '+'			*/
+		sign_wrote,	/* was sign write		*/
+		sign_pos,	/* pre number sign position	*/
+		num_count,	/* number of write digits 	*/
+		num_in,		/* is inside number		*/
+		num_curr,	/* current position in number 	*/
+		num_pre,	/* space before first number	*/
 	
-	int	sign,		/* '-' or '+'		*/
-		sign_wrote,	/* is sign wrote	*/
-		count_num,	/* number of non-write digits	*/
-		in_number,	/* is inside number	*/
-		pre_number;	/* space before number	*/
+		read_dec,	/* to_number - was read dec. point  */
+		read_post;	/* to_number - number of dec. digit */
 		
 	char	*number,	/* string with number	*/
 		*number_p,	/* pointer to current number pozition */
 		*inout,		/* in / out buffer	*/
 		*inout_p,	/* pointer to current inout pozition */
+		*last_relevant,	/* last relevant number after decimal point */
 		
 		*L_negative_sign,	/* Locale */
 		*L_positive_sign,
@@ -592,7 +607,7 @@ static KeySuffix *suff_search(char *str, KeySuffix *suf, int type);
 static void NUMDesc_prepare(NUMDesc *num, FormatNode *n);
 static void parse_format(FormatNode *node, char *str, KeyWord *kw, 
 		KeySuffix *suf, int *index, int ver, NUMDesc *Num);
-static char *DCH_action(FormatNode *node, char *inout, int flag);
+static char *DCH_processor(FormatNode *node, char *inout, int flag);
 
 #ifdef DEBUG_TO_FROM_CHAR
 	static void dump_index(KeyWord *k, int *index);
@@ -614,7 +629,9 @@ static FormatNode *NUM_cache( int len, char *CacheStr, FormatNode *CacheFormat,
 	   NUMDesc *CacheNum, NUMDesc *Num, char *pars_str, int *flag);
 static char *int_to_roman(int number);
 static void NUM_prepare_locale(NUMProc *Np);
-static int NUM_numpart(NUMProc *Np, int id);
+static char *get_last_relevant_decnum(char *num);
+static void NUM_numpart_from_char(NUMProc *Np, int id); 
+static void NUM_numpart_to_char(NUMProc *Np, int id); 
 static char *NUM_processor (FormatNode *node, NUMDesc *Num, char *inout, char *number, 
 					int plen, int sign, int type);
 
@@ -677,27 +694,37 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n)
 	switch(n->key->id) {
 		
 		case NUM_9:
+			if (IS_BRACKET(num))
+				elog(ERROR, "to_char/to_number(): '9' must be ahead of 'PR'.");   
+			
 			if (IS_MULTI(num)) {
 				++num->multi;
 				break;
 			}
 			if (IS_DECIMAL(num))
-				++num->pos;
+				++num->post;
 			else 
 				++num->pre;
 			break;
 		
 		case NUM_0:
-			if (num->pre == 0) 
+			if (IS_BRACKET(num))
+				elog(ERROR, "to_char/to_number(): '0' must be ahead of 'PR'.");   
+
+			if (!IS_ZERO(num) && !IS_DECIMAL(num)) {
 				num->flag |= NUM_F_ZERO; 
+				num->zero_start = num->pre + 1;
+			}
 			if (! IS_DECIMAL(num))
 				++num->pre;
 			else 
-				++num->pos;
+				++num->post;
+				
+			num->zero_end = num->pre + num->post;
 			break;	
 		
 		case NUM_B:
-			if (num->pre == 0 && num->pos == 0 && (! IS_ZERO(num)))
+			if (num->pre == 0 && num->post == 0 && (! IS_ZERO(num)))
 				num->flag |= NUM_F_BLANK; 				
 			break;		
 		
@@ -706,9 +733,9 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n)
 			num->need_locale = TRUE;
 		case NUM_DEC:
 			if (IS_DECIMAL(num))
-				elog(ERROR, "to_char/number(): not unique decimal poit."); 
+				elog(ERROR, "to_char/to_number(): not unique decimal poit."); 
 			if (IS_MULTI(num))
-				elog(ERROR, "to_char/number(): can't use 'V' and decimal poin together."); 	
+				elog(ERROR, "to_char/to_number(): can't use 'V' and decimal poin together."); 	
 			num->flag |= NUM_F_DECIMAL;
 			break;
 		
@@ -717,33 +744,53 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n)
 			break;
 		
 		case NUM_S:
+			if (IS_LSIGN(num))
+				elog(ERROR, "to_char/to_number(): not unique 'S'.");   
+			
+			if (IS_PLUS(num) || IS_MINUS(num) || IS_BRACKET(num))
+				elog(ERROR, "to_char/to_number(): can't use 'S' and 'PL'/'MI'/'SG'/'PR' together."); 	
+			
 			if (! IS_DECIMAL(num)) {
 				num->lsign = NUM_LSIGN_PRE;
 				num->pre_lsign_num = num->pre;
-				num->need_locale = TRUE;			
+				num->need_locale = TRUE;
+				num->flag |= NUM_F_LSIGN;
 				
 			} else if (num->lsign == NUM_LSIGN_NONE) {
 				num->lsign = NUM_LSIGN_POST;	
 				num->need_locale = TRUE;
+				num->flag |= NUM_F_LSIGN;
 			}	
 			break;
 		
 		case NUM_MI:
+			if (IS_LSIGN(num))
+				elog(ERROR, "to_char/to_number(): can't use 'S' and 'MI' together."); 	
+			
 			num->flag |= NUM_F_MINUS;
 			break;
 		
 		case NUM_PL:
+			if (IS_LSIGN(num))
+				elog(ERROR, "to_char/to_number(): can't use 'S' and 'PL' together."); 	
+			
 			num->flag |= NUM_F_PLUS;
 			break;		
 		
 		case NUM_SG:
+			if (IS_LSIGN(num))
+				elog(ERROR, "to_char/to_number(): can't use 'S' and 'SG' together."); 	
+			
 			num->flag |= NUM_F_MINUS;
 			num->flag |= NUM_F_PLUS;
 			break;
 		
 		case NUM_PR:
+			if (IS_LSIGN(num) || IS_PLUS(num) || IS_MINUS(num))
+				elog(ERROR, "to_char/to_number(): can't use 'PR' and 'S'/'PL'/'MI'/'SG' together.");   
 			num->flag |= NUM_F_BRACKET;
 			break;	
+	
 		case NUM_rn:
 		case NUM_RN:
 			num->flag |= NUM_F_ROMAN;
@@ -756,9 +803,12 @@ NUMDesc_prepare(NUMDesc *num, FormatNode *n)
 		
 		case NUM_V:
 			if (IS_DECIMAL(num))
-				elog(ERROR, "to_char/number(): can't use 'V' and decimal poin together."); 	
+				elog(ERROR, "to_char/to_number(): can't use 'V' and decimal poin together."); 	
 			num->flag |= NUM_F_MULTI;
 			break;	
+		
+		case NUM_E:
+			elog(ERROR, "to_char/to_number(): 'E' is not supported."); 	
 	}
 	
 	return;
@@ -782,7 +832,7 @@ parse_format(FormatNode *node, char *str, KeyWord *kw,
 			last=0;
 
 #ifdef DEBUG_TO_FROM_CHAR
-	elog(DEBUG_elog_output, "to-from_char(): run parser.");
+	elog(DEBUG_elog_output, "to_char/number(): run parser.");
 #endif
 
 	n = node;
@@ -895,7 +945,7 @@ parse_format(FormatNode *node, char *str, KeyWord *kw,
  * ----------
  */
 static char *
-DCH_action(FormatNode *node, char *inout, int flag)
+DCH_processor(FormatNode *node, char *inout, int flag)
 {
 	FormatNode	*n;
 	char		*s;
@@ -919,7 +969,7 @@ DCH_action(FormatNode *node, char *inout, int flag)
 			len = n->key->action(n->key->id, s, n->suffix, flag, n); 	
 			if (len > 0) 
 				s += len;
-			else 
+			else if (len == -1)
 				continue;	
 				
 		} else {
@@ -972,8 +1022,8 @@ dump_node(FormatNode *node, int max)
 	
 	for(a=0, n=node; a<=max; n++, a++) {
 		if (n->type == NODE_TYPE_ACTION) 
-			elog(DEBUG_elog_output, "%d:\t NODE_TYPE_ACTION\t(%s,%s)", 
-					a, DUMP_THth(n->suffix), DUMP_FM(n->suffix));
+			elog(DEBUG_elog_output, "%d:\t NODE_TYPE_ACTION '%s'\t(%s,%s)", 
+					a, n->key->name, DUMP_THth(n->suffix), DUMP_FM(n->suffix));
 		else if (n->type == NODE_TYPE_CHAR) 
 			elog(DEBUG_elog_output, "%d:\t NODE_TYPE_CHAR '%c'", a, n->character);	
 		else if (n->type == NODE_TYPE_END) {
@@ -1221,7 +1271,7 @@ dch_global(int arg, char *inout, int suf, int flag, FormatNode *node)
 		DCH_global_flag	|= DCH_F_FX;
 		break;
 	}
-	return 0;
+	return -1;
 }
 
 /* ----------
@@ -1245,8 +1295,11 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node)
 				tm->tm_hour <13	? tm->tm_hour : tm->tm_hour-12);
 			if (S_THth(suf)) 
 				str_numth(p_inout, inout, 0);
-			if (S_FM(suf) || S_THth(suf)) return strlen(p_inout)-1;
-			else return 1;
+			if (S_FM(suf) || S_THth(suf)) 
+				return strlen(p_inout)-1;
+			else 
+				return 1;
+			
 		} else if (flag == FROM_CHAR) {
 			if (S_FM(suf)) {
 				sscanf(inout, "%d", &tm->tm_hour);
@@ -1255,15 +1308,18 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node)
 				sscanf(inout, "%02d", &tm->tm_hour);
 				return 1 + SKIP_THth(suf);
 			}
-				
 		}
+
 	case DCH_HH24:
 		if (flag == TO_CHAR) {
 			sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_hour);
 			if (S_THth(suf)) 
 				str_numth(p_inout, inout, S_TH_TYPE(suf));
-			if (S_FM(suf) || S_THth(suf)) return strlen(p_inout)-1;
-			else return 1;
+			if (S_FM(suf) || S_THth(suf)) 
+				return strlen(p_inout) -1;
+			else 
+				return 1;
+		
 		} else if (flag == FROM_CHAR) {
 			if (S_FM(suf)) {
 				sscanf(inout, "%d", &tm->tm_hour);
@@ -1273,13 +1329,17 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node)
 				return 1 + SKIP_THth(suf);
 			}
 		}
+		
 	case DCH_MI:	
 		if (flag == TO_CHAR) {
 			sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_min);
 			if (S_THth(suf)) 
 				str_numth(p_inout, inout, S_TH_TYPE(suf));
-			if (S_FM(suf) || S_THth(suf)) return strlen(p_inout)-1;
-			else return 1;
+			if (S_FM(suf) || S_THth(suf)) 
+				return strlen(p_inout)-1;
+			else 
+				return 1;
+		
 		} else if (flag == FROM_CHAR) {
 			if (S_FM(suf)) {
 				sscanf(inout, "%d", &tm->tm_min);
@@ -1294,8 +1354,11 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node)
 			sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_sec);
 			if (S_THth(suf)) 
 				str_numth(p_inout, inout, S_TH_TYPE(suf));
-			if (S_FM(suf) || S_THth(suf)) return strlen(p_inout)-1;
-			else return 1;
+			if (S_FM(suf) || S_THth(suf)) 
+				return strlen(p_inout) -1;
+			else 
+				return 1;
+		
 		} else if (flag == FROM_CHAR) {
 			if (S_FM(suf)) {
 				sscanf(inout, "%d", &tm->tm_sec);
@@ -1314,14 +1377,14 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node)
 				str_numth(p_inout, inout, S_TH_TYPE(suf));
 			return strlen(p_inout)-1;		
 		}  else if (flag == FROM_CHAR) 
-			elog(ERROR, "to_datatime: SSSS is not supported");
+			elog(ERROR, "to_datatime()/to_timestamp(): SSSS is not supported");
 	}	
-	return 0;	
+	return -1;	
 }
 
 #define CHECK_SEQ_SEARCH(_l, _s) {					\
 	if (_l <= 0) { 							\
-		elog(ERROR, "to_datatime: bad value for %s", _s);		\
+		elog(ERROR, "to_datatime()/to_timestamp(): bad value for %s", _s);		\
 	}								\
 }
 
@@ -1382,28 +1445,40 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
 	case DCH_MONTH:
 		strcpy(inout, months_full[ tm->tm_mon - 1]);		
 		sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, str_toupper(inout));	
-		if (S_FM(suf)) return strlen(p_inout)-1;
-		else return 8;
+		if (S_FM(suf)) 
+			return strlen(p_inout)-1;
+		else 
+			return 8;
+		
 	case DCH_Month:
 		sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, months_full[ tm->tm_mon -1 ]);		
-	        if (S_FM(suf)) return strlen(p_inout)-1;
-		else return 8;
+	        if (S_FM(suf)) 
+	        	return strlen(p_inout)-1;
+		else 
+			return 8;
+			
 	case DCH_month:
 		sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, months_full[ tm->tm_mon -1 ]);
 		*inout = tolower(*inout);
-	        if (S_FM(suf)) return strlen(p_inout)-1;
-		else return 8;
+	        if (S_FM(suf)) 
+	        	return strlen(p_inout)-1;
+		else 
+			return 8;
+			
 	case DCH_MON:
 		strcpy(inout, months[ tm->tm_mon -1 ]);		
 		inout = str_toupper(inout);
 		return 2;
+		
 	case DCH_Mon:
 		strcpy(inout, months[ tm->tm_mon -1 ]);		
 		return 2;     
+		
 	case DCH_mon:
 		strcpy(inout, months[ tm->tm_mon -1 ]);		
 		*inout = tolower(*inout);
 		return 2;
+		
 	case DCH_MM:
 		if (flag == TO_CHAR) {
 			sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_mon );
@@ -1411,7 +1486,9 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
 				str_numth(p_inout, inout, S_TH_TYPE(suf));
 			if (S_FM(suf) || S_THth(suf)) 
 				return strlen(p_inout)-1;
-			else return 1;
+			else 
+				return 1;
+				
 		} else if (flag == FROM_CHAR) {
 			if (S_FM(suf)) {
 				sscanf(inout, "%d", &tm->tm_mon);
@@ -1419,33 +1496,46 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
 			} else {
 				sscanf(inout, "%02d", &tm->tm_mon);
 				return 1 + SKIP_THth(suf);
-			}		
+			}	
 		}	
+		
 	case DCH_DAY:
 		strcpy(inout, days[ tm->tm_wday ]); 			        
 		sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, str_toupper(inout)); 
-	        if (S_FM(suf)) return strlen(p_inout)-1;
-		else return 8;	
+	        if (S_FM(suf)) 
+	        	return strlen(p_inout)-1;
+		else 
+			return 8;	
+			
 	case DCH_Day:
 		sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, days[ tm->tm_wday]);			
-	       	if (S_FM(suf)) return strlen(p_inout)-1;
-		else return 8;			
+	       	if (S_FM(suf)) 
+	       		return strlen(p_inout)-1;
+		else 
+			return 8;			
+			
 	case DCH_day:
 		sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, days[ tm->tm_wday]);			
 		*inout = tolower(*inout);
-	       	if (S_FM(suf)) return strlen(p_inout)-1;
-		else return 8;
+	       	if (S_FM(suf)) 
+	       		return strlen(p_inout)-1;
+		else 
+			return 8;
+			
 	case DCH_DY:	        
 		strcpy(inout, days[ tm->tm_wday]);
 		inout = str_toupper(inout);		
 		return 2;
+		
 	case DCH_Dy:
 		strcpy(inout, days[ tm->tm_wday]);			
 		return 2;			
+		
 	case DCH_dy:
 		strcpy(inout, days[ tm->tm_wday]);			
 		*inout = tolower(*inout);
 		return 2;
+		
 	case DCH_DDD:
 		if (flag == TO_CHAR) {
 			sprintf(inout, "%0*d", S_FM(suf) ? 0 : 3, tm->tm_yday);
@@ -1454,6 +1544,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
 			if (S_FM(suf) || S_THth(suf)) 
 				return strlen(p_inout)-1;
 			else return 2;
+			
 		} else if (flag == FROM_CHAR) {	
 			if (S_FM(suf)) {
 				sscanf(inout, "%d", &tm->tm_yday);
@@ -1463,6 +1554,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
 				return 2 + SKIP_THth(suf);
 			}	
 		}
+		
 	case DCH_DD:
 		if (flag == TO_CHAR) {	
 			sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_mday);	
@@ -1470,7 +1562,9 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
 				str_numth(p_inout, inout, S_TH_TYPE(suf));
 			if (S_FM(suf) || S_THth(suf)) 
 				return strlen(p_inout)-1;
-			else return 1;
+			else 
+				return 1;
+				
 		} else if (flag == FROM_CHAR) {	
 			if (S_FM(suf)) {
 				sscanf(inout, "%d", &tm->tm_mday);
@@ -1483,16 +1577,17 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
 	case DCH_D:
 		if (flag == TO_CHAR) {
 			sprintf(inout, "%d", tm->tm_wday+1);
-	        	if (S_THth(suf)) 
+	        	if (S_THth(suf)) {
 				str_numth(p_inout, inout, S_TH_TYPE(suf));
-			if (S_THth(suf)) 
 				return 2;
+	        	}
 	        	return 0;
 	        } else if (flag == FROM_CHAR) {	
 			sscanf(inout, "%1d", &tm->tm_wday);
 			if(tm->tm_wday) --tm->tm_wday;
 			return 0 + SKIP_THth(suf);
 		} 
+		
 	case DCH_WW:
 		if (flag == TO_CHAR) {
 			sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2,  
@@ -1501,19 +1596,23 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
 				str_numth(p_inout, inout, S_TH_TYPE(suf));
 			if (S_FM(suf) || S_THth(suf)) 
 				return strlen(p_inout)-1;
-			else return 1;
+			else 
+				return 1;
+			
 		}  else if (flag == FROM_CHAR)
-			elog(ERROR, "to_datatime: WW is not supported");
+			elog(ERROR, "to_datatime()/to_timestamp(): WW is not supported");
 	case DCH_Q:
 		if (flag == TO_CHAR) {
 			sprintf(inout, "%d", (tm->tm_mon-1)/3+1);		
-			if (S_THth(suf)) 
+			if (S_THth(suf)) {
 				str_numth(p_inout, inout, S_TH_TYPE(suf));
-			if (S_THth(suf)) 
 				return 2;
+	        	} 
 	        	return 0;
+	        	
 	        } else if (flag == FROM_CHAR)
-			elog(ERROR, "to_datatime: Q is not supported");
+			elog(ERROR, "to_datatime()/to_timestamp(): Q is not supported");
+			
 	case DCH_CC:
 		if (flag == TO_CHAR) {
 			i = tm->tm_year/100 +1;
@@ -1524,8 +1623,9 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
 			if (S_THth(suf)) 
 				str_numth(p_inout, inout, S_TH_TYPE(suf));
 			return strlen(p_inout)-1;
+			
 		} else if (flag == FROM_CHAR)
-			elog(ERROR, "to_datatime: CC is not supported");
+			elog(ERROR, "to_datatime()/to_timestamp(): CC is not supported");
 	case DCH_Y_YYY:	
 		if (flag == TO_CHAR) {
 			i= YEAR_ABS(tm->tm_year) / 1000;
@@ -1535,6 +1635,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
 			if (tm->tm_year < 0)
 				strcat(inout, BC_STR);	
 			return strlen(p_inout)-1;
+			
 		} else if (flag == FROM_CHAR) {
 			int	cc, yy;
 			sscanf(inout, "%d,%03d", &cc, &yy);
@@ -1552,6 +1653,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
 				tm->tm_year = tm->tm_year+1; 
 			return len-1;
 		}	
+		
 	case DCH_YYYY:
 		if (flag == TO_CHAR) {
 			if (tm->tm_year <= 9999 && tm->tm_year >= -9998)
@@ -1563,6 +1665,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
 			if (tm->tm_year < 0)
 				strcat(inout, BC_STR);
 			return strlen(p_inout)-1;
+			
 		} else if (flag == FROM_CHAR) {
 			sscanf(inout, "%d", &tm->tm_year);
 			if (!S_FM(suf) && tm->tm_year <= 9999 && tm->tm_year >= -9999)	
@@ -1577,73 +1680,92 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
 				tm->tm_year = tm->tm_year+1; 
 			return len-1;
 		}	
+		
 	case DCH_YYY:
 		if (flag == TO_CHAR) {
 			sprintf(buff, "%03d", YEAR_ABS(tm->tm_year));
 			i=strlen(buff);
 			strcpy(inout, buff+(i-3));
-			if (S_THth(suf)) 
+			if (S_THth(suf)) {
 				str_numth(p_inout, inout, S_TH_TYPE(suf));
-			if (S_THth(suf)) return 4;
+				return 4;
+			}
 			return 2;
+			
 		} else if (flag == FROM_CHAR) {
 			int	yy;
 			sscanf(inout, "%03d", &yy);
 			tm->tm_year = (tm->tm_year/1000)*1000 +yy;
 			return 2 +  SKIP_THth(suf);
-		}	
+		}
+			
 	case DCH_YY:
 		if (flag == TO_CHAR) {
 			sprintf(buff, "%02d", YEAR_ABS(tm->tm_year));
 			i=strlen(buff);
 			strcpy(inout, buff+(i-2));
-			if (S_THth(suf)) 
+			if (S_THth(suf)) {
 				str_numth(p_inout, inout, S_TH_TYPE(suf));
-			if (S_THth(suf)) return 3;
+				return 3;
+			}	
 			return 1;
+			
 		} else if (flag == FROM_CHAR) {
 			int	yy;
 			sscanf(inout, "%02d", &yy);
 			tm->tm_year = (tm->tm_year/100)*100 +yy;
 			return 1 +  SKIP_THth(suf);
 		}	
+		
 	case DCH_Y:
 		if (flag == TO_CHAR) {
 			sprintf(buff, "%1d", YEAR_ABS(tm->tm_year));
 			i=strlen(buff);
 			strcpy(inout, buff+(i-1));
-			if (S_THth(suf)) 
+			if (S_THth(suf)) {
 				str_numth(p_inout, inout, S_TH_TYPE(suf));
-			if (S_THth(suf)) return 2;
+				return 2;
+			}	
 			return 0;
+			
 		} else if (flag == FROM_CHAR) {
 			int	yy;
 			sscanf(inout, "%1d", &yy);
 			tm->tm_year = (tm->tm_year/10)*10 +yy;
 			return 0 +  SKIP_THth(suf);
 		}	
+		
 	case DCH_RM:
 		if (flag == TO_CHAR) {
 			sprintf(inout, "%*s", S_FM(suf) ? 0 : -4,   
 				rm_months[ 12 - tm->tm_mon ]);
-			if (S_FM(suf)) return strlen(p_inout)-1;
-			else return 3;
+			if (S_FM(suf)) 
+				return strlen(p_inout)-1;
+			else 
+				return 3;
+				
 		} else if (flag == FROM_CHAR) {
 			tm->tm_mon = 11-seq_search(inout, rm_months, ALL_UPPER, FULL_SIZ, &len);
 			CHECK_SEQ_SEARCH(len, "RM");
 			++tm->tm_mon;
-			if (S_FM(suf))	return len-1;
-			else 		return 3;
+			if (S_FM(suf))	
+				return len-1;
+			else 		
+				return 3;
 		}	
+		
 	case DCH_W:
 		if (flag == TO_CHAR) {
 			sprintf(inout, "%d", (tm->tm_mday - tm->tm_wday +7) / 7 );
-			if (S_THth(suf)) 
+			if (S_THth(suf)) {
 				str_numth(p_inout, inout, S_TH_TYPE(suf));
-			if (S_THth(suf)) return 2;
+				return 2;
+			}
 			return 0;
+			
 		} else if (flag == FROM_CHAR)
-			elog(ERROR, "to_datatime: W is not supported");
+			elog(ERROR, "to_datatime()/to_timestamp(): W is not supported");
+			
 	case DCH_J:
 		if (flag == TO_CHAR) {
 			sprintf(inout, "%d", date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));		
@@ -1651,9 +1773,9 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
 				str_numth(p_inout, inout, S_TH_TYPE(suf));
 			return strlen(p_inout)-1;
 		} else if (flag == FROM_CHAR)
-			elog(ERROR, "to_datatime: J is not supported");	
+			elog(ERROR, "to_datatime()/to_timestamp(): J is not supported");	
 	}	
-	return 0;	
+	return -1;	
 }
 
 /****************************************************************************
@@ -1699,7 +1821,7 @@ datetime_to_char(DateTime *dt, text *fmt)
 		datetime2tm(SetDateTime(*dt), &tz, tm, &fsec, &tzn);
 	} else {
 		if (datetime2tm(*dt, &tz, tm, &fsec, &tzn) != 0)
-			elog(ERROR, "to_char: Unable to convert datetime to tm");
+			elog(ERROR, "to_char(): Unable to convert datetime to tm");
 	}
 
 	tm->tm_wday = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + 1) % 7; 
@@ -1756,20 +1878,20 @@ datetime_to_char(DateTime *dt, text *fmt)
         		 */		
 			strncpy(CacheStr, str, DCH_CACHE_SIZE);
 				
+         		parse_format(CacheFormat, str, DCH_keywords, 
+         		     DCH_suff, DCH_index, DCH_TYPE, NULL);
+
 #ifdef DEBUG_TO_FROM_CHAR	 
 			/* dump_node(CacheFormat, len); */
 			/* dump_index(DCH_keywords, DCH_index); */
 #endif         	
-         		parse_format(CacheFormat, str, DCH_keywords, 
-         		     DCH_suff, DCH_index, DCH_TYPE, NULL);
-         		
          		(CacheFormat + len)->type = NODE_TYPE_END;	/* Paranoa? */	
         	}
 
         	format = CacheFormat;
 	}
 	
-	DCH_action(format, VARDATA(result), TO_CHAR);
+	DCH_processor(format, VARDATA(result), TO_CHAR);
 
 	if (flag)
 		pfree(format);
@@ -1888,7 +2010,7 @@ to_datetime(text *date_str, text *fmt)
 		/* dump_node(format, len); */
 #endif
 		VARDATA(date_str)[ VARSIZE(date_str) - VARHDRSZ ] = '\0';
-		DCH_action(format, VARDATA(date_str), FROM_CHAR);	
+		DCH_processor(format, VARDATA(date_str), FROM_CHAR);	
 
 		pfree(str);
 		
@@ -1939,7 +2061,7 @@ to_datetime(text *date_str, text *fmt)
 	NOTICE_TM; 
 #endif
 	if (tm2datetime(tm, fsec, &tz, result) != 0)
-        	elog(ERROR, "to_datatime: can't convert 'tm' to datetime.");
+        	elog(ERROR, "to_datatime()/to_timestamp(): can't convert 'tm' to datetime.");
 	
 	return result;
 }
@@ -2012,9 +2134,13 @@ NUM_cache( int len, char *CacheStr, FormatNode *CacheFormat,
 		Num->flag 		= 0;	
 		Num->lsign		= 0;	
 		Num->pre		= 0;	
-		Num->pos		= 0;
+		Num->post		= 0;
          	Num->pre_lsign_num	= 0;
-		
+		Num->zero_start		= 0;
+		Num->zero_end		= 0;		
+		Num->need_locale	= 0;
+		Num->multi		= 0;
+
 		parse_format(format, str, NUM_keywords, 
          			NULL, NUM_index, NUM_TYPE, Num);
 	
@@ -2051,17 +2177,20 @@ NUM_cache( int len, char *CacheStr, FormatNode *CacheFormat,
 			CacheNum->flag 		= 0;	
 			CacheNum->lsign		= 0;	
 			CacheNum->pre		= 0;	
-			CacheNum->pos		= 0;
+			CacheNum->post		= 0;
          		CacheNum->pre_lsign_num	= 0;
         		CacheNum->need_locale	= 0;
         		CacheNum->multi		= 0; 	
+         		CacheNum->zero_start	= 0;
+         		CacheNum->zero_end	= 0;
+         	
+         		parse_format(CacheFormat, str, NUM_keywords, 
+         			NULL, NUM_index, NUM_TYPE, CacheNum);
          	
 #ifdef DEBUG_TO_FROM_CHAR	 
 			/* dump_node(CacheFormat, len); */
 			/* dump_index(NUM_keywords, NUM_index); */
-#endif         	
-         		parse_format(CacheFormat, str, NUM_keywords, 
-         			NULL, NUM_index, NUM_TYPE, CacheNum);
+#endif         	         	
          		
          		(CacheFormat + len)->type = NODE_TYPE_END;	/* Paranoa? */	
         	}
@@ -2072,10 +2201,12 @@ NUM_cache( int len, char *CacheStr, FormatNode *CacheFormat,
 		Num->flag 		= CacheNum->flag;
 		Num->lsign		= CacheNum->lsign;
 		Num->pre		= CacheNum->pre;
-		Num->pos		= CacheNum->pos;
+		Num->post		= CacheNum->post;
 		Num->pre_lsign_num 	= CacheNum->pre_lsign_num;	
 		Num->need_locale	= CacheNum->need_locale; 
 		Num->multi		= CacheNum->multi; 	
+		Num->zero_start		= CacheNum->zero_start;
+		Num->zero_end		= CacheNum->zero_end;
 
 		pfree(str);
 		return CacheFormat;
@@ -2210,213 +2341,332 @@ NUM_prepare_locale(NUMProc *Np)
 }
 
 /* ----------
- * SET SIGN macro - set 'S' or 'PR' befor number 	
+ * Return pointer of last relevant number after decimal point
+ *	12.0500	--> last relevant is '5'
  * ----------
- */
-#define SET_SIGN(_np) {								\
-	if ((_np)->sign_wrote==0) {							\
-		if (IS_BRACKET((_np)->Num)) {					\
-										\
-			*(_np)->inout_p = '<';					\
-			++(_np)->inout_p;					\
-			(_np)->sign_wrote = 1;					\
-										\
-		} else if ((_np)->Num->lsign==NUM_LSIGN_PRE && (! IS_BRACKET((_np)->Num)) &&	\
-			(! IS_MINUS((_np)->Num)) && (! IS_PLUS((_np)->Num))) {	\
-										\
-			if ((_np)->sign=='-') 					\
-				strcpy((_np)->inout_p, (_np)->L_negative_sign);	\
-			else 							\
-				strcpy((_np)->inout_p, (_np)->L_positive_sign);	\
-			(_np)->inout_p += strlen((_np)->inout_p);		\
-			(_np)->sign_wrote = 1;					\
-										\
-		} else {							\
-			if ((_np)->sign=='-' && (_np)->Num->lsign==NUM_LSIGN_NONE \
-				&& (! IS_BRACKET((_np)->Num)) && 		\
-				(! IS_MINUS((_np)->Num)) && (! IS_PLUS((_np)->Num))) {	\
-										\
-				*(_np)->inout_p = '-';					\
-				++(_np)->inout_p;						\
-				(_np)->sign_wrote=1;					\
-										\
-			} else if ((! IS_FILLMODE((_np)->Num)) && (_np)->Num->lsign==NUM_LSIGN_NONE && \
-				(! IS_BRACKET((_np)->Num)) && (! IS_MINUS((_np)->Num)) && (! IS_PLUS((_np)->Num))) {	\
-										\
-				*(_np)->inout_p = ' ';					\
-				++(_np)->inout_p;						\
-				(_np)->sign_wrote=1;					\
-			}							\
-		}								\
-	}									\
+ */ 
+static char *
+get_last_relevant_decnum(char *num)
+{
+	char	*result, 
+		*p = strchr(num, '.');
+	
+	elog(NOTICE, "CALL: get_last_relevant_decnum()");
+	
+	if (!p)	
+		p = num;
+	result = p;
+	
+	while(*(++p)) {
+		if (*p!='0')
+			result = p;
+	}
+	
+	return result;
 }
 
 /* ----------
- * Create number
- *	return FALSE if any work over current NUM_[0|9|D|DEC] must be skip
- *	in NUM_processor()   
+ * Number extraction for TO_NUMBER()
  * ----------
  */
-static int
-NUM_numpart(NUMProc *Np, int id) 
-{	
-	if (IS_ROMAN(Np->Num))
-		return FALSE;
-			
-	/* Note: in this elog() output not set '\0' in inout
-	elog(DEBUG_elog_output, "sign_w: %d, count: %d, plen %d, sn: %s, inout: '%s'", 
-		Np->sign_wrote, Np->count_num, Np->pre_number, Np->number_p, Np->inout);
-	*/
+static void
+NUM_numpart_from_char(NUMProc *Np, int id) 
+{
+	
+#ifdef DEBUG_TO_FROM_CHAR
+	elog(DEBUG_elog_output, " --- scan start --- ");
+#endif
+
+	if (*Np->inout_p == ' ') 
+		Np->inout_p++;		
 
 	/* ----------
-	 * Number extraction for TO_NUMBER()
+	 * read sign
 	 * ----------
 	 */
-	if (Np->type == FROM_CHAR) {
-		if (id == NUM_9 || id == NUM_0) {
-			if (!*(Np->number+1)) {
-				if (*Np->inout_p == '-' || 
-				     (IS_BRACKET(Np->Num) && 
-				      *Np->inout_p == '<' )) {
-				
-					*Np->number = '-';
-					Np->inout_p++;
-				
-				} else if (*Np->inout_p == '+') {
-				
-					*Np->number = '+';
-					Np->inout_p++;
-				
-				} else if (*Np->inout_p == ' ' && (! IS_FILLMODE(Np->Num))) {
-					Np->inout_p++;
-				} 
+	if (*Np->number == ' ' && (id == NUM_0 || id == NUM_9 || NUM_S)) {
+
+#ifdef DEBUG_TO_FROM_CHAR
+		elog(DEBUG_elog_output, "Try read sign (%c).", *Np->inout_p);
+#endif		
+		/* ----------
+		 * locale sign
+		 * ----------
+		 */
+		if (IS_LSIGN(Np->Num)) {
+		
+			int x = strlen(Np->L_negative_sign);
+			
+#ifdef DEBUG_TO_FROM_CHAR
+			elog(DEBUG_elog_output, "Try read locale sign (%c).", *Np->inout_p);
+#endif			
+			if (!strncmp(Np->inout_p, Np->L_negative_sign, x)) {
+				Np->inout_p += x-1;
+				*Np->number = '-';
+				return;
 			}
-			if (isdigit((unsigned char) *Np->inout_p)) {
-				*Np->number_p = *Np->inout_p;
-				Np->number_p++;
-			} 
-		} else {
-			if (id == NUM_DEC) {
-				*Np->number_p = '.';
-				Np->number_p++;
-				
-			} else if (id == NUM_D) {
-				
-				int x = strlen(Np->decimal);
-				
-				if (!strncmp(Np->inout_p, Np->decimal, x)) {
-					Np->inout_p += x-1;
-					*Np->number_p = '.';
-					Np->number_p++;
-				}	                    
+						
+			x = strlen(Np->L_positive_sign);
+			if (!strncmp(Np->inout_p, Np->L_positive_sign, x)) {
+				Np->inout_p += x-1;
+				*Np->number = '+';
+				return;
 			}
-		}	
-		return TRUE;		
-	}
+		}
 
-	/* ----------
-	 * Add blank space (pre number)
-	 * ----------
-	 */
-	if ((! IS_ZERO(Np->Num)) && (! IS_FILLMODE(Np->Num)) && Np->pre_number > 0) { 
-		*Np->inout_p = ' ';
-		--Np->pre_number;
-		--Np->count_num;
-		return TRUE;
-	} 
+#ifdef DEBUG_TO_FROM_CHAR
+		elog(DEBUG_elog_output, "Try read sipmle sign (%c).", *Np->inout_p);
+#endif		
+		/* ----------
+		 * simple + - < >
+		 * ----------
+		 */
+		if (*Np->inout_p == '-' || (IS_BRACKET(Np->Num) && 
+		    *Np->inout_p == '<' )) {
+			
+			*Np->number = '-';		/* set - */
+			Np->inout_p++;
+			
+		} else if (*Np->inout_p == '+') {
+				
+			*Np->number = '+';		/* set + */
+			Np->inout_p++;
+		} 		
+	}
 	
 	/* ----------
-	 * Add zero (pre number)
+	 * read digit
 	 * ----------
 	 */
-	if (IS_ZERO(Np->Num) && Np->pre_number > 0) {
-
-		SET_SIGN(Np);
-		*Np->inout_p='0';
-		--Np->pre_number;
-		--Np->count_num;
-		return TRUE;
-	}
+	if (isdigit((unsigned char) *Np->inout_p)) {
+		
+		if (Np->read_dec && Np->read_post == Np->Num->post)
+			return;
+		
+		*Np->number_p = *Np->inout_p;
+		Np->number_p++;
 	
-	if (IS_FILLMODE(Np->Num) && Np->pre_number > 0) { 
-		--Np->pre_number;
-		return FALSE;
-	}
+		if (Np->read_dec)
+			Np->read_post++;
+
+#ifdef DEBUG_TO_FROM_CHAR	
+		elog(DEBUG_elog_output, "Read digit (%c).", *Np->inout_p);
+#endif	
 	
 	/* ----------
-	 * Add sign or '<' or ' '
+	 * read decimal point
 	 * ----------
 	 */
-	if (Np->number_p==Np->number && Np->sign_wrote==0) {
-		SET_SIGN(Np);			
+	} else if (IS_DECIMAL(Np->Num)) {
+
+#ifdef DEBUG_TO_FROM_CHAR
+		elog(DEBUG_elog_output, "Try read decimal point (%c).", *Np->inout_p);
+#endif		
+		if (*Np->inout_p == '.') {
+		
+			*Np->number_p = '.';
+			Np->number_p++;
+			Np->read_dec = TRUE;
+			
+		} else {
+			
+			int x = strlen(Np->decimal);
+			
+#ifdef DEBUG_TO_FROM_CHAR
+			elog(DEBUG_elog_output, "Try read locale point (%c).", *Np->inout_p);
+#endif			
+			if (!strncmp(Np->inout_p, Np->decimal, x)) {
+				Np->inout_p += x-1;
+				*Np->number_p = '.';
+				Np->number_p++;
+				Np->read_dec = TRUE;
+			}
+		}
 	}	
+}
+
+/* ----------
+ * Add digit or sign to number-string
+ * ----------
+ */
+static void
+NUM_numpart_to_char(NUMProc *Np, int id) 
+{	
+	if (IS_ROMAN(Np->Num))
+		return;
+			
+	/* Note: in this elog() output not set '\0' in 'inout' */
+
+#ifdef DEBUG_TO_FROM_CHAR	
+	/*
+ 	 * Np->num_curr is number of current item in format-picture, it is not
+ 	 * current position in inout! 
+ 	 */
+	elog(DEBUG_elog_output, 
+	
+	"SIGN_WROTE: %d, CURRENT: %d, NUMBER_P: '%s', INOUT: '%s'", 
+		Np->sign_wrote, 
+		Np->num_curr,
+		Np->number_p, 
+		Np->inout);
+#endif	
+	Np->num_in = FALSE;
 	
 	/* ----------
-	 * Add decimal point
+	 * Write sign
 	 * ----------
 	 */
-	if (*Np->number_p=='.') {
-		strcpy(Np->inout_p, Np->decimal);
-		Np->inout_p += strlen(Np->inout_p);
-		if (*Np->number_p)
-			++Np->number_p;
-		return FALSE;	
-	}
-	
-	if (*Np->number_p) { 
-	
-		/* ----------
-		 * Copy number string to inout string
-		 * ----------
-		 */
-		*Np->inout_p = *Np->number_p;
-		++Np->number_p;	
+	if (Np->num_curr == Np->sign_pos && Np->sign_wrote==FALSE) {
+
+#ifdef DEBUG_TO_FROM_CHAR	
+		elog(DEBUG_elog_output, "Writing sign to position: %d", Np->num_curr);
+#endif	
+		if (IS_LSIGN(Np->Num)) {
 		
-		Np->in_number = 1;
+			/* ----------
+			 * Write locale SIGN 
+			 * ----------
+			 */
+			if (Np->sign=='-')		
+					strcpy(Np->inout_p, Np->L_negative_sign);
+				else 
+					strcpy(Np->inout_p, Np->L_positive_sign);
+			Np->inout_p += strlen(Np->inout_p);			
+		
+		} else if (IS_BRACKET(Np->Num)) {
+			*Np->inout_p = '<';		/* Write < */
+			++Np->inout_p;	
 		
+		} else if (Np->sign=='+') {
+			*Np->inout_p = ' ';		/* Write + */
+			++Np->inout_p;
+			
+		} else if (Np->sign=='-') {		/* Write - */
+			*Np->inout_p = '-';
+			++Np->inout_p;	
+		}	
+		Np->sign_wrote = TRUE;
+
+	} else if (Np->sign_wrote && IS_BRACKET(Np->Num) && 
+		  (Np->num_curr == Np->num_count + (Np->num_pre ? 1 : 0)
+		  			+ (IS_DECIMAL(Np->Num) ? 1 : 0))) {
 		/* ----------
-		 * Number end (set post 'S' or '>' 
+		 * Write close BRACKET
 		 * ----------
-		 */
-		if ((--Np->count_num)==0) {
-		
-			if (IS_BRACKET(Np->Num)) {
+		 */		
+#ifdef DEBUG_TO_FROM_CHAR
+		elog(DEBUG_elog_output, "Writing bracket to position %d", Np->num_curr);
+#endif		
+		*Np->inout_p = '>';			/* Write '>' */
+		++Np->inout_p;	
+	}
+	
+	/* ----------
+	 * digits / FM / Zero / Dec. point
+	 * ----------
+	 */
+	if (id == NUM_9 || id == NUM_0 || id == NUM_D || id == NUM_DEC || 
+	   (id == NUM_S && Np->num_curr < Np->num_pre)) {
+	
+		if (Np->num_curr < Np->num_pre && 
+		    (Np->Num->zero_start > Np->num_curr || !IS_ZERO(Np->Num))) {
+		    
+ 			/* ----------
+ 			 * Write blank space
+ 			 * ----------
+ 			 */ 			
+ 			if (!IS_FILLMODE(Np->Num)) { 
+ #ifdef DEBUG_TO_FROM_CHAR			
+ 				elog(DEBUG_elog_output, "Writing blank space to position %d", Np->num_curr);
+ #endif			
+ 				*Np->inout_p = ' ';		/* Write ' ' */
 				++Np->inout_p;
-				*Np->inout_p 	= '>';
-				Np->sign_wrote	=1;
 			}
+
+		} else if (IS_ZERO(Np->Num) && 
+			   Np->num_curr < Np->num_pre &&
+			   Np->Num->zero_start <= Np->num_curr) {
 		
-			if (Np->Num->lsign==NUM_LSIGN_POST && Np->sign_wrote==0) {
-				++Np->inout_p;
-				if (Np->sign=='-')
-					strcpy(Np->inout_p, Np->L_negative_sign);
-				else 
-					strcpy(Np->inout_p, Np->L_positive_sign);
-				Np->inout_p += strlen(Np->inout_p)-1;	
-				Np->sign_wrote = 1;
+			/* ----------
+			 * Write ZERO
+			 * ----------
+			 */
+#ifdef DEBUG_TO_FROM_CHAR		
+			elog(DEBUG_elog_output, "Writing zero to position %d", Np->num_curr);
+#endif			
+			*Np->inout_p = '0';		/* Write '0' */
+			++Np->inout_p;
+			Np->num_in = TRUE;
+		
+		} else {
+
+			/* ----------
+			* Write Decinal point 
+			* ----------
+		 	*/
+			if (*Np->number_p=='.') {
+			 
+				if (!Np->last_relevant || *Np->last_relevant!='.' ) {
+#ifdef DEBUG_TO_FROM_CHAR					
+					elog(DEBUG_elog_output, "Writing decimal point to position %d", Np->num_curr);
+#endif					
+					strcpy(Np->inout_p, Np->decimal);	/* Write DEC/D */
+					Np->inout_p += strlen(Np->inout_p);
+				
+				/* terrible Ora
+				 *	'0' -- 9.9 --> '0.'
+				 */
+				} else if (IS_FILLMODE(Np->Num) && *Np->number == '0' && 
+					   Np->last_relevant && *Np->last_relevant=='.' ) {
+					   
+					strcpy(Np->inout_p, Np->decimal);	/* Write DEC/D */
+					Np->inout_p += strlen(Np->inout_p);
+				}
+				
+			} else  {
+
+				/* ----------
+				 * Write Digits
+				 * ----------
+				 */
+				if (Np->last_relevant && Np->number_p > Np->last_relevant &&
+				    id != NUM_0)
+					;
+				
+				/* terrible Ora format: 
+				 *	'0.1' -- 9.9 --> '  .1' 
+				 */
+				else if (!IS_ZERO(Np->Num) && *Np->number == '0' && 
+				          Np->number == Np->number_p && Np->Num->post !=0) {
+					
+					if (!IS_FILLMODE(Np->Num)) {
+						*Np->inout_p = ' ';
+						++Np->inout_p;
+					
+					/* total terible Ora:
+					 *	'0' -- FM9.9 --> '0.'
+					 */	
+					} else if (Np->last_relevant && *Np->last_relevant=='.') { 
+						*Np->inout_p = '0';
+						++Np->inout_p;
+					}
+					
+				} else {
+#ifdef DEBUG_TO_FROM_CHAR
+					elog(DEBUG_elog_output, "Writing digit '%c' to position %d", *Np->number_p, Np->num_curr);
+#endif				
+					*Np->inout_p = *Np->number_p;	/* Write DIGIT */
+					++Np->inout_p;
+					Np->num_in = TRUE;
+				}	
 			}
-		}
-	} else	
-		return FALSE;
-	return TRUE;
+			++Np->number_p;
+		}	
+	}
+	
+	++Np->num_curr;
 }
 		
-/* ----------
- *  Master function for NUMBER version.
- *  type (variant):
- *	TO_CHAR 		
- *		-> create formatted string by course of FormatNode 
- *
- *	FROM_CHAR (TO_NUMBER) 	
- *		-> extract number string from formatted string (reverse TO_CHAR)
- *		
- *		- ! this version use non-string 'inout' VARDATA(), 
- *		  and 'plen' is used for VARSIZE()
- *		- value 'sign' is not used	
- *		- number is creating in Np->number and first position (*Np->number)
- *		  in this buffer is reserved for +/- sign	
- * ----------
- */
 static char *
 NUM_processor (FormatNode *node, NUMDesc *Num, char *inout, char *number, 
 					int plen, int sign, int type)
@@ -2427,32 +2677,24 @@ NUM_processor (FormatNode *node, NUMDesc *Num, char *inout, char *number,
 	Np->Num 	= Num;
 	Np->type	= type;
 	Np->number	= number;
-	
-	if (type == TO_CHAR) {
-		Np->pre_number 	= plen;
-		Np->sign	= sign;
-
-	} else if (type == FROM_CHAR) {	
-		Np->pre_number 	= 0; 
-		*Np->number	= ' ';	/* sign space */	
-		*(Np->number+1)	= '\0';	
-		Np->sign	= 0;
-	}	
-	
 	Np->inout	= inout;
-	
-	Np->sign_wrote	= Np->count_num	= Np->in_number	= 0;
-	
+	Np->last_relevant = NULL;
+	Np->read_post	= 0;
+	Np->read_dec	= FALSE;
+
+	if (Np->Num->zero_start)
+		--Np->Num->zero_start;
+
 	/* ---------- 
-	 * Roman corection 
+	 * Roman correction 
 	 * ----------
 	 */
 	if (IS_ROMAN(Np->Num)) {		
 		if (Np->type==FROM_CHAR)
-			elog(ERROR, "to_number: RN is not supported");	
+			elog(ERROR, "to_number(): RN is not supported");	
 			
-		Np->Num->lsign = Np->Num->pre_lsign_num = Np->Num->pos = 
-		Np->Num->pre = Np->pre_number = Np->sign = 0;
+		Np->Num->lsign = Np->Num->pre_lsign_num = Np->Num->post = 
+		Np->Num->pre = Np->num_pre = Np->sign = 0;
 		
 		if (IS_FILLMODE(Np->Num)){
 			Np->Num->flag = 0;
@@ -2462,37 +2704,128 @@ NUM_processor (FormatNode *node, NUMDesc *Num, char *inout, char *number,
 		}	
 		Np->Num->flag |= NUM_F_ROMAN; 
 	}
-
-	/* ---------- 
-	 * Check Num struct
+	
+	/* ----------
+	 * Sign
 	 * ----------
 	 */
-	if (Np->sign=='+')
-		Np->Num->flag &= ~NUM_F_BRACKET;
+	if (type == FROM_CHAR) {
+		Np->sign 	= FALSE; 
+		Np->sign_pos	= -1;
+	} else {
+		Np->sign = sign; 
+		
+		if (Np->sign != '-') {
+			Np->Num->flag &= ~NUM_F_BRACKET;
+			Np->Num->flag &= ~NUM_F_MINUS;
+		} else if (Np->sign != '+') {
+			Np->Num->flag &= ~NUM_F_PLUS;
+		}
 	
-	if (Np->Num->lsign == NUM_LSIGN_PRE && Np->Num->pre == Np->Num->pre_lsign_num)
-		Np->Num->lsign = NUM_LSIGN_POST;
+		if (Np->sign=='+' && IS_FILLMODE(Np->Num) && !IS_LSIGN(Np->Num)) 
+			Np->sign_wrote	= TRUE;		/* needn't sign */	
+		else
+			Np->sign_wrote  = FALSE;        /* need sign */
 
-	/* set counter (number of all digits) */ 
-	Np->count_num = Np->Num->pos + Np->Num->pre;
+		Np->sign_pos = -1;
 	
-	if (Np->type==TO_CHAR && IS_FILLMODE(Np->Num) && (! IS_ZERO(Np->Num)))
-		Np->count_num -= Np->pre_number;
+		if (Np->Num->lsign == NUM_LSIGN_PRE && Np->Num->pre == Np->Num->pre_lsign_num)
+			Np->Num->lsign = NUM_LSIGN_POST;
+	
+		/* MI/PL/SG - write sign itself and not in number */
+		if (IS_PLUS(Np->Num) || IS_MINUS(Np->Num))
+			Np->sign_wrote = TRUE;         /* needn't sign */
+	}
+
+	/* ----------
+	 * Count
+	 * ----------
+	 */
+	Np->num_count = Np->Num->post + Np->Num->pre -1;
+
+	if (type == TO_CHAR)  {
+		Np->num_pre = plen;
+
+		if (IS_FILLMODE(Np->Num)) {
+			if (IS_DECIMAL(Np->Num))
+				Np->last_relevant = get_last_relevant_decnum(
+					Np->number + 
+					((Np->Num->zero_end - Np->num_pre > 0) ? 
+					 Np->Num->zero_end - Np->num_pre : 0));
+		}	
+		
+		if (!Np->sign_wrote && Np->num_pre==0)
+			++Np->num_count;
+		
+	        if (!Np->sign_wrote) {
+	        
+	        	/* ----------
+	        	 * Set SING position
+	        	 * ----------
+	        	 */
+	        	if (Np->Num->lsign == NUM_LSIGN_POST) {
+	        		Np->sign_pos = Np->num_count + (Np->num_pre ? 1 : 0);
+	        	
+	        		if (IS_DECIMAL(Np->Num))	/* decimal point correctio */
+	        			++Np->sign_pos;
+	        	}
+	        	else if (IS_ZERO(Np->Num) && Np->num_pre > Np->Num->zero_start)
+	        		Np->sign_pos = Np->Num->zero_start ? Np->Num->zero_start : 0;         
+	        	
+	        	else
+	        		Np->sign_pos = Np->num_pre && !IS_FILLMODE(Np->Num) ? Np->num_pre : 0;         
+	        
+	        	/* ----------
+	        	 * terrible Ora format
+	        	 * ----------
+	        	 */
+			if (!IS_ZERO(Np->Num) && *Np->number == '0' && 
+	        	    !IS_FILLMODE(Np->Num) && Np->Num->post!=0) {
+	        		
+	        		++Np->sign_pos;
+	        		
+	        		if (IS_LSIGN(Np->Num)) {
+	        			if (Np->Num->lsign == NUM_LSIGN_PRE)
+	        				++Np->sign_pos;
+	        			else
+	        				--Np->sign_pos;	
+	        		}	
+	        	}
+	        }
+	        	
+	} else {
+		Np->num_pre = 0;
+		*Np->number	= ' ';		/* sign space */	
+		*(Np->number+1)	= '\0';	
+	}
+		
+	Np->num_in	= 0;
+	Np->num_curr 	= 0;	
 
 #ifdef DEBUG_TO_FROM_CHAR	
-	elog(DEBUG_elog_output, "NUM: '%s', PRE: %d, POS: %d, PLEN: %d, LSIGN: %d, DECIMAL: %d, MULTI: %d",
-			Np->number, Np->Num->pre, Np->Num->pos, 
-			Np->pre_number, Np->Num->lsign,IS_DECIMAL(Np->Num), 
-			Np->Num->multi); 
+	elog(DEBUG_elog_output, 
+	
+	"\n\tNUM: '%s'\n\tPRE: %d\n\tPOST: %d\n\tNUM_COUNT: %d\n\tNUM_PRE: %d\n\tSIGN_POS: %d\n\tSIGN_WROTE: %s\n\tZERO: %s\n\tZERO_START: %d\n\tZERO_END: %d\n\tLAST_RELEVANT: %s",
+			Np->number, 
+			Np->Num->pre, 
+			Np->Num->post,
+			Np->num_count, 
+			Np->num_pre,
+			Np->sign_pos,
+			Np->sign_wrote 		? "Yes" : "No",
+			IS_ZERO(Np->Num)	? "Yes" : "No",
+			Np->Num->zero_start,
+			Np->Num->zero_end,
+			Np->last_relevant ? Np->last_relevant : "<not set>"
+	);	
 #endif
+
 	/* ----------
 	 * Locale
 	 * ----------
 	 */
 	NUM_prepare_locale(Np);
 
-	/* need for DEBUG: memset(Np->inout, '\0', Np->count_num );*/
-
 	/* ----------
 	 * Processor direct cycle
 	 * ----------
@@ -2501,7 +2834,7 @@ NUM_processor (FormatNode *node, NUMDesc *Num, char *inout, char *number,
 		 Np->number_p=Np->number+1;  /* first char is space for sign */
 	else if (Np->type == TO_CHAR)
 		Np->number_p=Np->number;
-		
+
 	for(n=node, Np->inout_p=Np->inout; n->type != NODE_TYPE_END; n++) {
 		
 		if (Np->type == FROM_CHAR) {
@@ -2529,15 +2862,19 @@ NUM_processor (FormatNode *node, NUMDesc *Num, char *inout, char *number,
 			case NUM_0:
 			case NUM_DEC:
 			case NUM_D:
-			
-				if (NUM_numpart(Np, n->key->id))
-					break; 				
-				else
-					continue;
+			case NUM_S:
+			case NUM_PR:
+				if (Np->type == TO_CHAR) {
+					NUM_numpart_to_char(Np, n->key->id);
+					continue;	/* for() */
+				} else {
+					NUM_numpart_from_char(Np, n->key->id);
+					break;		/* switch() case: */
+				}
 			
 			case NUM_COMMA:
 				if (Np->type == TO_CHAR) {
-					if (!Np->in_number) {
+					if (!Np->num_in) {
 						if (IS_FILLMODE(Np->Num))
 							continue;
 						else
@@ -2546,7 +2883,7 @@ NUM_processor (FormatNode *node, NUMDesc *Num, char *inout, char *number,
 						*Np->inout_p = ',';
 				
 				} else if (Np->type == FROM_CHAR) {
-					if (!Np->in_number) {
+					if (!Np->num_in) {
 						if (IS_FILLMODE(Np->Num))
 							continue;
 					}
@@ -2555,7 +2892,7 @@ NUM_processor (FormatNode *node, NUMDesc *Num, char *inout, char *number,
 				
 			case NUM_G:
 				if (Np->type == TO_CHAR) {
-					if (!Np->in_number) {
+					if (!Np->num_in) {
 						if (IS_FILLMODE(Np->Num)) 
 							continue;
 						else {
@@ -2569,7 +2906,7 @@ NUM_processor (FormatNode *node, NUMDesc *Num, char *inout, char *number,
 					}
 					
 				} else if (Np->type == FROM_CHAR) {		
-					if (!Np->in_number) {
+					if (!Np->num_in) {
 						if (IS_FILLMODE(Np->Num)) 
 							continue;
 					}
@@ -2587,69 +2924,7 @@ NUM_processor (FormatNode *node, NUMDesc *Num, char *inout, char *number,
 				}
 				break;		
 				
-			case NUM_MI:
-				if (Np->sign_wrote==1 || IS_BRACKET(Np->Num)) {
-					if (Np->type == TO_CHAR)
-						continue; 
-					else
-						break;
-				}	
-				if (Np->type == TO_CHAR) {
-					if (Np->sign=='-')
-						*Np->inout_p = '-';
-					else	
-						*Np->inout_p = ' ';
-						
-				} else if (Np->type == FROM_CHAR) {
-					if (*Np->inout_p == '-')
-						*Np->number = '-';
-				}
-				Np->sign_wrote=1;
-				break;
-				
-			case NUM_PL:
-				if (Np->sign_wrote==1 || IS_BRACKET(Np->Num)) {
-					if (Np->type == TO_CHAR)
-						continue; 
-					else
-						break;
-				}
-				if (Np->type == TO_CHAR) {
-					if (Np->sign=='+')
-						*Np->inout_p = '+';
-					else
-						*Np->inout_p = ' ';
-						
-				}  else if (Np->type == FROM_CHAR) {
-					if (*Np->inout_p == '+')
-						*Np->number = '+';
-				}
-				Np->sign_wrote=1;       	
-				break;	
-				
-			case NUM_SG:
-				if (Np->sign_wrote==1 || IS_BRACKET(Np->Num)) {
-					if (Np->type == TO_CHAR)
-						continue; 
-					else
-						break;
-				}	
-				if (Np->type == TO_CHAR) 
-					*Np->inout_p = Np->sign;
-				
-				else if (Np->type == FROM_CHAR) {
-					if (*Np->inout_p == '-')
-						*Np->number = '-';
-					else if (*Np->inout_p == '+')
-						*Np->number = '+';	
-				}
-				Np->sign_wrote=1;
-				break;	
-				
 			case NUM_RN:
-				if (Np->type == FROM_CHAR) 
-					elog(ERROR, "TO_NUMBER: internal error #1");
-					
 				if (IS_FILLMODE(Np->Num)) {
 					strcpy(Np->inout_p, Np->number_p);	
 					Np->inout_p += strlen(Np->inout_p) - 1;
@@ -2658,9 +2933,6 @@ NUM_processor (FormatNode *node, NUMDesc *Num, char *inout, char *number,
 				break;	
 				
 			case NUM_rn:
-				if (Np->type == FROM_CHAR) 
-					elog(ERROR, "TO_NUMBER: internal error #2");
-				
 				if (IS_FILLMODE(Np->Num)) {
 					strcpy(Np->inout_p, str_tolower(Np->number_p));	
 					Np->inout_p += strlen(Np->inout_p) - 1;
@@ -2688,29 +2960,45 @@ NUM_processor (FormatNode *node, NUMDesc *Num, char *inout, char *number,
 				Np->inout_p += 1;
 				break;	
 			
-			case NUM_S:
-				/* ----------
-				 * 'S' for TO_CHAR is in NUM_numpart()
-				 * ----------
-				 */
-				if (Np->type == FROM_CHAR && Np->sign_wrote==FALSE) {
-					
-					int x = strlen(Np->L_negative_sign);
-					if (!strncmp(Np->inout_p, Np->L_negative_sign, x)) {
-						Np->inout_p += x-1;
+			case NUM_MI:
+				if (Np->type == TO_CHAR) {
+					if (Np->sign=='-')
+						*Np->inout_p = '-';
+					else	
+						*Np->inout_p = ' ';
+						
+				} else if (Np->type == FROM_CHAR) {
+					if (*Np->inout_p == '-')
 						*Np->number = '-';
-						break;
-					}
-					
-					x = strlen(Np->L_positive_sign);
-					if (!strncmp(Np->inout_p, Np->L_positive_sign, x)) {
-						Np->inout_p += x-1;
-						*Np->number = '+';
-						break;
-					}
-				} else
-					continue;
+				}
 				break;
+				
+			case NUM_PL:
+				if (Np->type == TO_CHAR) {
+					if (Np->sign=='+')
+						*Np->inout_p = '+';
+					else
+						*Np->inout_p = ' ';
+						
+				}  else if (Np->type == FROM_CHAR) {
+					if (*Np->inout_p == '+')
+						*Np->number = '+';
+				}
+				break;	
+				
+			case NUM_SG:
+				if (Np->type == TO_CHAR) 
+					*Np->inout_p = Np->sign;
+				
+				else if (Np->type == FROM_CHAR) {
+					if (*Np->inout_p == '-')
+						*Np->number = '-';
+					else if (*Np->inout_p == '+')
+						*Np->number = '+';	
+				}
+				break;	
+			
+			
 			default:
 				continue;
 				break;
@@ -2729,16 +3017,29 @@ NUM_processor (FormatNode *node, NUMDesc *Num, char *inout, char *number,
 	
 	if (Np->type == TO_CHAR) {
 		*Np->inout_p = '\0';
-		return Np->inout;
+		return Np->inout;	
 	
 	} else if (Np->type == FROM_CHAR) {
-		*Np->number_p = '\0';
+		
+		if (*(Np->number_p-1) == '.')
+			*(Np->number_p-1) = '\0';
+		else
+			*Np->number_p = '\0';
+			
+		/* ----------
+		 * Correction - precision of dec. number
+		 * ----------
+		 */
+		 Np->Num->post = Np->read_post;
+
 #ifdef DEBUG_TO_FROM_CHAR
 	        elog(DEBUG_elog_output, "TO_NUMBER (number): '%s'", Np->number);
 #endif
 		return Np->number;
 	} else
 		return NULL;	
+	
+	return NULL;	
 }
 
 /* ----------
@@ -2811,7 +3112,7 @@ numeric_to_number(text *value, text *fmt)
 	NUM_processor(format, &Num, VARDATA(value), numstr, 
 			VARSIZE(value) - VARHDRSZ, 0, FROM_CHAR);
 	
-	scale = Num.pos;
+	scale = Num.post;
 	precision = MAX(0, Num.pre) + scale;
 	
 	return numeric_in(numstr, 0, ((precision << 16) | scale) + VARHDRSZ);						
@@ -2853,7 +3154,7 @@ numeric_to_char(Numeric value, text *fmt)
 			Num.pre += Num.multi;
 		}
 		
-		orgnum = numeric_out( numeric_round(val, Num.pos) );
+		orgnum = numeric_out( numeric_round(val, Num.post) );
 		if (*orgnum == '-') { 					/* < 0 */
 			sign = '-';
 			numstr = orgnum+1; 
@@ -2872,10 +3173,10 @@ numeric_to_char(Numeric value, text *fmt)
 		else if (len > Num.pre) {
 			fill_str(numstr, '#', Num.pre);
 			*(numstr + Num.pre) = '.';
-			fill_str(numstr + 1 + Num.pre, '#', Num.pos);
+			fill_str(numstr + 1 + Num.pre, '#', Num.post);
 		} 
 	}	
-	/*dump_node(format, VARSIZE(fmt) - VARHDRSZ);*/
+
 	NUM_TOCHAR_finish;
 	return result;
 }
@@ -2921,16 +3222,16 @@ int4_to_char(int32 value, text *fmt)
 		} else
 			sign = '+';
 		
-		if (Num.pos) {
+		if (Num.post) {
 			int	i;
 			
-			numstr = palloc( len + 1 + Num.pos ); 
+			numstr = palloc( len + 1 + Num.post ); 
 			strcpy(numstr, orgnum + (*orgnum == '-' ? 1 : 0));
 			*(numstr + len) = '.';	
 			
-			for(i=len+1; i<=Num.pos+len+1; i++)
+			for(i=len+1; i<=Num.post+len+1; i++)
 				*(numstr+i) = '0';
-			*(numstr + Num.pos + len + 1)  = '\0';
+			*(numstr + Num.post + len + 1)  = '\0';
 			pfree(orgnum);
 			orgnum = numstr;  	 
 		} else
@@ -2941,12 +3242,10 @@ int4_to_char(int32 value, text *fmt)
 		else if (len > Num.pre) {
 			fill_str(numstr, '#', Num.pre);
 			*(numstr + Num.pre) = '.';
-			fill_str(numstr + 1 + Num.pre, '#', Num.pos);
+			fill_str(numstr + 1 + Num.pre, '#', Num.post);
 		}
 	}
 
-	/*dump_node(format, len);*/
-	
 	NUM_TOCHAR_finish;
 	return result;
 }
@@ -2993,16 +3292,16 @@ int8_to_char(int64 *value, text *fmt)
 		} else
 			sign = '+';
 		
-		if (Num.pos) {
+		if (Num.post) {
 			int	i;
 			
-			numstr = palloc( len + 1 + Num.pos ); 
+			numstr = palloc( len + 1 + Num.post ); 
 			strcpy(numstr, orgnum + (*orgnum == '-' ? 1 : 0));
 			*(numstr + len) = '.';	
 			
-			for(i=len+1; i<=Num.pos+len+1; i++)
+			for(i=len+1; i<=Num.post+len+1; i++)
 				*(numstr+i) = '0';
-			*(numstr + Num.pos + len + 1)  = '\0';
+			*(numstr + Num.post + len + 1)  = '\0';
 			pfree(orgnum);
 			orgnum = numstr;  	 
 		} else 
@@ -3013,7 +3312,7 @@ int8_to_char(int64 *value, text *fmt)
 		else if (len > Num.pre) {
 			fill_str(numstr, '#', Num.pre);
 			*(numstr + Num.pre) = '.';
-			fill_str(numstr + 1 + Num.pre, '#', Num.pos);
+			fill_str(numstr + 1 + Num.pre, '#', Num.post);
 		}	
 	}
 	
@@ -3058,10 +3357,10 @@ float4_to_char(float32 value, text *fmt)
 		if (Num.pre > len)
 			plen = Num.pre - len;
 		if (len >= FLT_DIG)
-		        Num.pos = 0;
-		else if (Num.pos + len > FLT_DIG)
-		        Num.pos = FLT_DIG - len;
-		sprintf(orgnum, "%.*f", Num.pos, *val);
+		        Num.post = 0;
+		else if (Num.post + len > FLT_DIG)
+		        Num.post = FLT_DIG - len;
+		sprintf(orgnum, "%.*f", Num.post, *val);
 		
 		if (*orgnum == '-') { 					/* < 0 */
 			sign = '-';
@@ -3081,7 +3380,7 @@ float4_to_char(float32 value, text *fmt)
 		else if (len > Num.pre) {
 			fill_str(numstr, '#', Num.pre);
 			*(numstr + Num.pre) = '.';
-			fill_str(numstr + 1 + Num.pre, '#', Num.pos);
+			fill_str(numstr + 1 + Num.pre, '#', Num.post);
 		} 
 	}
 	
@@ -3125,10 +3424,10 @@ float8_to_char(float64 value, text *fmt)
 		if (Num.pre > len)
 			plen = Num.pre - len;
 		if (len >= DBL_DIG)
-		        Num.pos = 0;
-		else if (Num.pos + len > DBL_DIG)
-		        Num.pos = DBL_DIG - len;
-		sprintf(orgnum, "%.*f", Num.pos, *val);
+		        Num.post = 0;
+		else if (Num.post + len > DBL_DIG)
+		        Num.post = DBL_DIG - len;
+		sprintf(orgnum, "%.*f", Num.post, *val);
 	
 		if (*orgnum == '-') { 					/* < 0 */
 			sign = '-';
@@ -3148,7 +3447,7 @@ float8_to_char(float64 value, text *fmt)
 		else if (len > Num.pre) {
 			fill_str(numstr, '#', Num.pre);
 			*(numstr + Num.pre) = '.';
-			fill_str(numstr + 1 + Num.pre, '#', Num.pos);
+			fill_str(numstr + 1 + Num.pre, '#', Num.post);
 		} 
 	}
 	
diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c
index 7688a753dbc830eef42a76669a7b4b34c0a8e976..1711eb269ad370183d88a290cedcd671b636ae56 100644
--- a/src/backend/utils/adt/pg_locale.c
+++ b/src/backend/utils/adt/pg_locale.c
@@ -1,12 +1,17 @@
 
-/*------
+/* -----------------------------------------------------------------------
  * pg_locale.c
  *
- *	The PostgreSQL locale utils.
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v 1.2 2000/02/08 15:56:55 momjian Exp $
  *
- *	2000 Karel Zak - Zakkr
  *
- *------
+ *   Portions Copyright (c) 1999-2000, PostgreSQL, Inc
+ *
+ *   The PostgreSQL locale utils.
+ *
+ *	Karel Zak - Zakkr
+ *
+ * -----------------------------------------------------------------------
  */
  
 #include <stdio.h>
diff --git a/src/include/utils/formatting.h b/src/include/utils/formatting.h
index b5b1a5ff1fafaf4cd160d861b5c02ce8e160fdff..51c649fd9da8dd3edea6167b295b2a61f15ce479 100644
--- a/src/include/utils/formatting.h
+++ b/src/include/utils/formatting.h
@@ -2,13 +2,15 @@
 /* -----------------------------------------------------------------------
  * formatting.h
  *
- * $Id: formatting.h,v 1.1 2000/01/25 23:53:56 momjian Exp $
+ * $Id: formatting.h,v 1.2 2000/02/08 15:56:57 momjian Exp $
  *
  *
+ *   Portions Copyright (c) 1999-2000, PostgreSQL, Inc
+ *
  *   The PostgreSQL routines for a DateTime/int/float/numeric formatting, 
  *   inspire with Oracle TO_CHAR() / TO_DATE() / TO_NUMBER() routines.  
  *
- *   1999 Karel Zak "Zakkr"
+ *   Karel Zak - Zakkr
  *
  * -----------------------------------------------------------------------
  */
diff --git a/src/include/utils/pg_locale.h b/src/include/utils/pg_locale.h
index e5aee46c9b334a050005de4be3ddc870e1ee0c2a..ac940c1b55e9d6784489fd4a308b22043dd0efb8 100644
--- a/src/include/utils/pg_locale.h
+++ b/src/include/utils/pg_locale.h
@@ -1,14 +1,19 @@
 
-/*------
+/* -----------------------------------------------------------------------
  * pg_locale.h
  *
- *	The PostgreSQL locale utils
+ * $Header: /cvsroot/pgsql/src/include/utils/pg_locale.h,v 1.2 2000/02/08 15:57:01 momjian Exp $
  *
- *	2000 Karel Zak - Zakkr
  *
- *------
- */ 
- 
+ *   Portions Copyright (c) 1999-2000, PostgreSQL, Inc
+ *
+ *   The PostgreSQL locale utils.
+ *
+ *	Karel Zak - Zakkr
+ *
+ * -----------------------------------------------------------------------
+ */
+  
  #ifndef _PG_LOCALE_
  #define _PG_LOCALE_