1 /* -----------------------------------------------------------------------
2  * formatting.c
3  *
4  * src/backend/utils/adt/formatting.c
5  *
6  *
7  *	 Portions Copyright (c) 1999-2017, PostgreSQL Global Development Group
8  *
9  *
10  *	 TO_CHAR(); TO_TIMESTAMP(); TO_DATE(); TO_NUMBER();
11  *
12  *	 The PostgreSQL routines for a timestamp/int/float/numeric formatting,
13  *	 inspired by the Oracle TO_CHAR() / TO_DATE() / TO_NUMBER() routines.
14  *
15  *
16  *	 Cache & Memory:
17  *	Routines use (itself) internal cache for format pictures.
18  *
19  *	The cache uses a static buffer and is persistent across transactions.  If
20  *	the format-picture is bigger than the cache buffer, the parser is called
21  *	always.
22  *
23  *	 NOTE for Number version:
24  *	All in this version is implemented as keywords ( => not used
25  *	suffixes), because a format picture is for *one* item (number)
26  *	only. It not is as a timestamp version, where each keyword (can)
27  *	has suffix.
28  *
29  *	 NOTE for Timestamp routines:
30  *	In this module the POSIX 'struct tm' type is *not* used, but rather
31  *	PgSQL type, which has tm_mon based on one (*non* zero) and
32  *	year *not* based on 1900, but is used full year number.
33  *	Module supports AD / BC / AM / PM.
34  *
35  *	Supported types for to_char():
36  *
37  *		Timestamp, Numeric, int4, int8, float4, float8
38  *
39  *	Supported types for reverse conversion:
40  *
41  *		Timestamp	- to_timestamp()
42  *		Date		- to_date()
43  *		Numeric		- to_number()
44  *
45  *
46  *	Karel Zak
47  *
48  * TODO
49  *	- better number building (formatting) / parsing, now it isn't
50  *		  ideal code
51  *	- use Assert()
52  *	- add support for abstime
53  *	- add support for roman number to standard number conversion
54  *	- add support for number spelling
55  *	- add support for string to string formatting (we must be better
56  *	  than Oracle :-),
57  *		to_char('Hello', 'X X X X X') -> 'H e l l o'
58  *
59  * -----------------------------------------------------------------------
60  */
61 
62 #ifdef DEBUG_TO_FROM_CHAR
63 #define DEBUG_elog_output	DEBUG3
64 #endif
65 
66 #include "postgres.h"
67 
68 #include <ctype.h>
69 #include <unistd.h>
70 #include <math.h>
71 #include <float.h>
72 #include <limits.h>
73 
74 /*
75  * towlower() and friends should be in <wctype.h>, but some pre-C99 systems
76  * declare them in <wchar.h>.
77  */
78 #ifdef HAVE_WCHAR_H
79 #include <wchar.h>
80 #endif
81 #ifdef HAVE_WCTYPE_H
82 #include <wctype.h>
83 #endif
84 
85 #ifdef USE_ICU
86 #include <unicode/ustring.h>
87 /* ICU might have a different definition of "bool", don't buy it */
88 #ifdef bool
89 #undef bool
90 #endif
91 #endif
92 
93 #include "catalog/pg_collation.h"
94 #include "mb/pg_wchar.h"
95 #include "parser/scansup.h"
96 #include "utils/builtins.h"
97 #include "utils/date.h"
98 #include "utils/datetime.h"
99 #include "utils/formatting.h"
100 #include "utils/int8.h"
101 #include "utils/numeric.h"
102 #include "utils/pg_locale.h"
103 
104 /* ----------
105  * Routines type
106  * ----------
107  */
108 #define DCH_TYPE		1		/* DATE-TIME version	*/
109 #define NUM_TYPE		2		/* NUMBER version	*/
110 
111 /* ----------
112  * KeyWord Index (ascii from position 32 (' ') to 126 (~))
113  * ----------
114  */
115 #define KeyWord_INDEX_SIZE		('~' - ' ')
116 #define KeyWord_INDEX_FILTER(_c)	((_c) <= ' ' || (_c) >= '~' ? 0 : 1)
117 
118 /* ----------
119  * Maximal length of one node
120  * ----------
121  */
122 #define DCH_MAX_ITEM_SIZ	   12	/* max localized day name		*/
123 #define NUM_MAX_ITEM_SIZ		8	/* roman number (RN has 15 chars)	*/
124 
125 /* ----------
126  * More is in float.c
127  * ----------
128  */
129 #define MAXFLOATWIDTH	60
130 #define MAXDOUBLEWIDTH	500
131 
132 
133 /* ----------
134  * Format parser structs
135  * ----------
136  */
137 typedef struct
138 {
139 	char	   *name;			/* suffix string		*/
140 	int			len,			/* suffix length		*/
141 				id,				/* used in node->suffix */
142 				type;			/* prefix / postfix			*/
143 } KeySuffix;
144 
145 /* ----------
146  * FromCharDateMode
147  * ----------
148  *
149  * This value is used to nominate one of several distinct (and mutually
150  * exclusive) date conventions that a keyword can belong to.
151  */
152 typedef enum
153 {
154 	FROM_CHAR_DATE_NONE = 0,	/* Value does not affect date mode. */
155 	FROM_CHAR_DATE_GREGORIAN,	/* Gregorian (day, month, year) style date */
156 	FROM_CHAR_DATE_ISOWEEK		/* ISO 8601 week date */
157 } FromCharDateMode;
158 
159 typedef struct FormatNode FormatNode;
160 
161 typedef struct
162 {
163 	const char *name;
164 	int			len;
165 	int			id;
166 	bool		is_digit;
167 	FromCharDateMode date_mode;
168 } KeyWord;
169 
170 struct FormatNode
171 {
172 	int			type;			/* node type			*/
173 	const KeyWord *key;			/* if node type is KEYWORD	*/
174 	char		character;		/* if node type is CHAR		*/
175 	int			suffix;			/* keyword suffix		*/
176 };
177 
178 #define NODE_TYPE_END		1
179 #define NODE_TYPE_ACTION	2
180 #define NODE_TYPE_CHAR		3
181 
182 #define SUFFTYPE_PREFIX		1
183 #define SUFFTYPE_POSTFIX	2
184 
185 #define CLOCK_24_HOUR		0
186 #define CLOCK_12_HOUR		1
187 
188 
189 /* ----------
190  * Full months
191  * ----------
192  */
193 static const char *const months_full[] = {
194 	"January", "February", "March", "April", "May", "June", "July",
195 	"August", "September", "October", "November", "December", NULL
196 };
197 
198 static const char *const days_short[] = {
199 	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL
200 };
201 
202 /* ----------
203  * AD / BC
204  * ----------
205  *	There is no 0 AD.  Years go from 1 BC to 1 AD, so we make it
206  *	positive and map year == -1 to year zero, and shift all negative
207  *	years up one.  For interval years, we just return the year.
208  */
209 #define ADJUST_YEAR(year, is_interval)	((is_interval) ? (year) : ((year) <= 0 ? -((year) - 1) : (year)))
210 
211 #define A_D_STR		"A.D."
212 #define a_d_STR		"a.d."
213 #define AD_STR		"AD"
214 #define ad_STR		"ad"
215 
216 #define B_C_STR		"B.C."
217 #define b_c_STR		"b.c."
218 #define BC_STR		"BC"
219 #define bc_STR		"bc"
220 
221 /*
222  * AD / BC strings for seq_search.
223  *
224  * These are given in two variants, a long form with periods and a standard
225  * form without.
226  *
227  * The array is laid out such that matches for AD have an even index, and
228  * matches for BC have an odd index.  So the boolean value for BC is given by
229  * taking the array index of the match, modulo 2.
230  */
231 static const char *const adbc_strings[] = {ad_STR, bc_STR, AD_STR, BC_STR, NULL};
232 static const char *const adbc_strings_long[] = {a_d_STR, b_c_STR, A_D_STR, B_C_STR, NULL};
233 
234 /* ----------
235  * AM / PM
236  * ----------
237  */
238 #define A_M_STR		"A.M."
239 #define a_m_STR		"a.m."
240 #define AM_STR		"AM"
241 #define am_STR		"am"
242 
243 #define P_M_STR		"P.M."
244 #define p_m_STR		"p.m."
245 #define PM_STR		"PM"
246 #define pm_STR		"pm"
247 
248 /*
249  * AM / PM strings for seq_search.
250  *
251  * These are given in two variants, a long form with periods and a standard
252  * form without.
253  *
254  * The array is laid out such that matches for AM have an even index, and
255  * matches for PM have an odd index.  So the boolean value for PM is given by
256  * taking the array index of the match, modulo 2.
257  */
258 static const char *const ampm_strings[] = {am_STR, pm_STR, AM_STR, PM_STR, NULL};
259 static const char *const ampm_strings_long[] = {a_m_STR, p_m_STR, A_M_STR, P_M_STR, NULL};
260 
261 /* ----------
262  * Months in roman-numeral
263  * (Must be in reverse order for seq_search (in FROM_CHAR), because
264  *	'VIII' must have higher precedence than 'V')
265  * ----------
266  */
267 static const char *const rm_months_upper[] =
268 {"XII", "XI", "X", "IX", "VIII", "VII", "VI", "V", "IV", "III", "II", "I", NULL};
269 
270 static const char *const rm_months_lower[] =
271 {"xii", "xi", "x", "ix", "viii", "vii", "vi", "v", "iv", "iii", "ii", "i", NULL};
272 
273 /* ----------
274  * Roman numbers
275  * ----------
276  */
277 static const char *const rm1[] = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", NULL};
278 static const char *const rm10[] = {"X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", NULL};
279 static const char *const rm100[] = {"C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", NULL};
280 
281 /* ----------
282  * Ordinal postfixes
283  * ----------
284  */
285 static const char *const numTH[] = {"ST", "ND", "RD", "TH", NULL};
286 static const char *const numth[] = {"st", "nd", "rd", "th", NULL};
287 
288 /* ----------
289  * Flags & Options:
290  * ----------
291  */
292 #define TH_UPPER		1
293 #define TH_LOWER		2
294 
295 /* ----------
296  * Number description struct
297  * ----------
298  */
299 typedef struct
300 {
301 	int			pre,			/* (count) numbers before decimal */
302 				post,			/* (count) numbers after decimal  */
303 				lsign,			/* want locales sign		  */
304 				flag,			/* number parameters		  */
305 				pre_lsign_num,	/* tmp value for lsign		  */
306 				multi,			/* multiplier for 'V'		  */
307 				zero_start,		/* position of first zero	  */
308 				zero_end,		/* position of last zero	  */
309 				need_locale;	/* needs it locale		  */
310 } NUMDesc;
311 
312 /* ----------
313  * Flags for NUMBER version
314  * ----------
315  */
316 #define NUM_F_DECIMAL		(1 << 1)
317 #define NUM_F_LDECIMAL		(1 << 2)
318 #define NUM_F_ZERO			(1 << 3)
319 #define NUM_F_BLANK			(1 << 4)
320 #define NUM_F_FILLMODE		(1 << 5)
321 #define NUM_F_LSIGN			(1 << 6)
322 #define NUM_F_BRACKET		(1 << 7)
323 #define NUM_F_MINUS			(1 << 8)
324 #define NUM_F_PLUS			(1 << 9)
325 #define NUM_F_ROMAN			(1 << 10)
326 #define NUM_F_MULTI			(1 << 11)
327 #define NUM_F_PLUS_POST		(1 << 12)
328 #define NUM_F_MINUS_POST	(1 << 13)
329 #define NUM_F_EEEE			(1 << 14)
330 
331 #define NUM_LSIGN_PRE	(-1)
332 #define NUM_LSIGN_POST	1
333 #define NUM_LSIGN_NONE	0
334 
335 /* ----------
336  * Tests
337  * ----------
338  */
339 #define IS_DECIMAL(_f)	((_f)->flag & NUM_F_DECIMAL)
340 #define IS_LDECIMAL(_f) ((_f)->flag & NUM_F_LDECIMAL)
341 #define IS_ZERO(_f) ((_f)->flag & NUM_F_ZERO)
342 #define IS_BLANK(_f)	((_f)->flag & NUM_F_BLANK)
343 #define IS_FILLMODE(_f) ((_f)->flag & NUM_F_FILLMODE)
344 #define IS_BRACKET(_f)	((_f)->flag & NUM_F_BRACKET)
345 #define IS_MINUS(_f)	((_f)->flag & NUM_F_MINUS)
346 #define IS_LSIGN(_f)	((_f)->flag & NUM_F_LSIGN)
347 #define IS_PLUS(_f) ((_f)->flag & NUM_F_PLUS)
348 #define IS_ROMAN(_f)	((_f)->flag & NUM_F_ROMAN)
349 #define IS_MULTI(_f)	((_f)->flag & NUM_F_MULTI)
350 #define IS_EEEE(_f)		((_f)->flag & NUM_F_EEEE)
351 
352 /* ----------
353  * Format picture cache
354  *
355  * We will cache datetime format pictures up to DCH_CACHE_SIZE bytes long;
356  * likewise number format pictures up to NUM_CACHE_SIZE bytes long.
357  *
358  * For simplicity, the cache entries are fixed-size, so they allow for the
359  * worst case of a FormatNode for each byte in the picture string.
360  *
361  * The max number of entries in the caches is DCH_CACHE_ENTRIES
362  * resp. NUM_CACHE_ENTRIES.
363  * ----------
364  */
365 #define NUM_CACHE_SIZE		64
366 #define NUM_CACHE_ENTRIES	20
367 #define DCH_CACHE_SIZE		128
368 #define DCH_CACHE_ENTRIES	20
369 
370 typedef struct
371 {
372 	FormatNode	format[DCH_CACHE_SIZE + 1];
373 	char		str[DCH_CACHE_SIZE + 1];
374 	bool		valid;
375 	int			age;
376 } DCHCacheEntry;
377 
378 typedef struct
379 {
380 	FormatNode	format[NUM_CACHE_SIZE + 1];
381 	char		str[NUM_CACHE_SIZE + 1];
382 	bool		valid;
383 	int			age;
384 	NUMDesc		Num;
385 } NUMCacheEntry;
386 
387 /* global cache for date/time format pictures */
388 static DCHCacheEntry DCHCache[DCH_CACHE_ENTRIES];
389 static int	n_DCHCache = 0;		/* current number of entries */
390 static int	DCHCounter = 0;		/* aging-event counter */
391 
392 /* global cache for number format pictures */
393 static NUMCacheEntry NUMCache[NUM_CACHE_ENTRIES];
394 static int	n_NUMCache = 0;		/* current number of entries */
395 static int	NUMCounter = 0;		/* aging-event counter */
396 
397 /* ----------
398  * For char->date/time conversion
399  * ----------
400  */
401 typedef struct
402 {
403 	FromCharDateMode mode;
404 	int			hh,
405 				pm,
406 				mi,
407 				ss,
408 				ssss,
409 				d,				/* stored as 1-7, Sunday = 1, 0 means missing */
410 				dd,
411 				ddd,
412 				mm,
413 				ms,
414 				year,
415 				bc,
416 				ww,
417 				w,
418 				cc,
419 				j,
420 				us,
421 				yysz,			/* is it YY or YYYY ? */
422 				clock;			/* 12 or 24 hour clock? */
423 } TmFromChar;
424 
425 #define ZERO_tmfc(_X) memset(_X, 0, sizeof(TmFromChar))
426 
427 /* ----------
428  * Debug
429  * ----------
430  */
431 #ifdef DEBUG_TO_FROM_CHAR
432 #define DEBUG_TMFC(_X) \
433 		elog(DEBUG_elog_output, "TMFC:\nmode %d\nhh %d\npm %d\nmi %d\nss %d\nssss %d\nd %d\ndd %d\nddd %d\nmm %d\nms: %d\nyear %d\nbc %d\nww %d\nw %d\ncc %d\nj %d\nus: %d\nyysz: %d\nclock: %d", \
434 			(_X)->mode, (_X)->hh, (_X)->pm, (_X)->mi, (_X)->ss, (_X)->ssss, \
435 			(_X)->d, (_X)->dd, (_X)->ddd, (_X)->mm, (_X)->ms, (_X)->year, \
436 			(_X)->bc, (_X)->ww, (_X)->w, (_X)->cc, (_X)->j, (_X)->us, \
437 			(_X)->yysz, (_X)->clock)
438 #define DEBUG_TM(_X) \
439 		elog(DEBUG_elog_output, "TM:\nsec %d\nyear %d\nmin %d\nwday %d\nhour %d\nyday %d\nmday %d\nnisdst %d\nmon %d\n",\
440 			(_X)->tm_sec, (_X)->tm_year,\
441 			(_X)->tm_min, (_X)->tm_wday, (_X)->tm_hour, (_X)->tm_yday,\
442 			(_X)->tm_mday, (_X)->tm_isdst, (_X)->tm_mon)
443 #else
444 #define DEBUG_TMFC(_X)
445 #define DEBUG_TM(_X)
446 #endif
447 
448 /* ----------
449  * Datetime to char conversion
450  * ----------
451  */
452 typedef struct TmToChar
453 {
454 	struct pg_tm tm;			/* classic 'tm' struct */
455 	fsec_t		fsec;			/* fractional seconds */
456 	const char *tzn;			/* timezone */
457 } TmToChar;
458 
459 #define tmtcTm(_X)	(&(_X)->tm)
460 #define tmtcTzn(_X) ((_X)->tzn)
461 #define tmtcFsec(_X)	((_X)->fsec)
462 
463 #define ZERO_tm(_X) \
464 do {	\
465 	(_X)->tm_sec  = (_X)->tm_year = (_X)->tm_min = (_X)->tm_wday = \
466 	(_X)->tm_hour = (_X)->tm_yday = (_X)->tm_isdst = 0; \
467 	(_X)->tm_mday = (_X)->tm_mon  = 1; \
468 } while(0)
469 
470 #define ZERO_tmtc(_X) \
471 do { \
472 	ZERO_tm( tmtcTm(_X) ); \
473 	tmtcFsec(_X) = 0; \
474 	tmtcTzn(_X) = NULL; \
475 } while(0)
476 
477 /*
478  *	to_char(time) appears to to_char() as an interval, so this check
479  *	is really for interval and time data types.
480  */
481 #define INVALID_FOR_INTERVAL  \
482 do { \
483 	if (is_interval) \
484 		ereport(ERROR, \
485 				(errcode(ERRCODE_INVALID_DATETIME_FORMAT), \
486 				 errmsg("invalid format specification for an interval value"), \
487 				 errhint("Intervals are not tied to specific calendar dates."))); \
488 } while(0)
489 
490 /*****************************************************************************
491  *			KeyWord definitions
492  *****************************************************************************/
493 
494 /* ----------
495  * Suffixes:
496  * ----------
497  */
498 #define DCH_S_FM	0x01
499 #define DCH_S_TH	0x02
500 #define DCH_S_th	0x04
501 #define DCH_S_SP	0x08
502 #define DCH_S_TM	0x10
503 
504 /* ----------
505  * Suffix tests
506  * ----------
507  */
508 #define S_THth(_s)	((((_s) & DCH_S_TH) || ((_s) & DCH_S_th)) ? 1 : 0)
509 #define S_TH(_s)	(((_s) & DCH_S_TH) ? 1 : 0)
510 #define S_th(_s)	(((_s) & DCH_S_th) ? 1 : 0)
511 #define S_TH_TYPE(_s)	(((_s) & DCH_S_TH) ? TH_UPPER : TH_LOWER)
512 
513 /* Oracle toggles FM behavior, we don't; see docs. */
514 #define S_FM(_s)	(((_s) & DCH_S_FM) ? 1 : 0)
515 #define S_SP(_s)	(((_s) & DCH_S_SP) ? 1 : 0)
516 #define S_TM(_s)	(((_s) & DCH_S_TM) ? 1 : 0)
517 
518 /* ----------
519  * Suffixes definition for DATE-TIME TO/FROM CHAR
520  * ----------
521  */
522 #define TM_SUFFIX_LEN	2
523 
524 static const KeySuffix DCH_suff[] = {
525 	{"FM", 2, DCH_S_FM, SUFFTYPE_PREFIX},
526 	{"fm", 2, DCH_S_FM, SUFFTYPE_PREFIX},
527 	{"TM", TM_SUFFIX_LEN, DCH_S_TM, SUFFTYPE_PREFIX},
528 	{"tm", 2, DCH_S_TM, SUFFTYPE_PREFIX},
529 	{"TH", 2, DCH_S_TH, SUFFTYPE_POSTFIX},
530 	{"th", 2, DCH_S_th, SUFFTYPE_POSTFIX},
531 	{"SP", 2, DCH_S_SP, SUFFTYPE_POSTFIX},
532 	/* last */
533 	{NULL, 0, 0, 0}
534 };
535 
536 
537 /* ----------
538  * Format-pictures (KeyWord).
539  *
540  * The KeyWord field; alphabetic sorted, *BUT* strings alike is sorted
541  *		  complicated -to-> easy:
542  *
543  *	(example: "DDD","DD","Day","D" )
544  *
545  * (this specific sort needs the algorithm for sequential search for strings,
546  * which not has exact end; -> How keyword is in "HH12blabla" ? - "HH"
547  * or "HH12"? You must first try "HH12", because "HH" is in string, but
548  * it is not good.
549  *
550  * (!)
551  *	 - Position for the keyword is similar as position in the enum DCH/NUM_poz.
552  * (!)
553  *
554  * For fast search is used the 'int index[]', index is ascii table from position
555  * 32 (' ') to 126 (~), in this index is DCH_ / NUM_ enums for each ASCII
556  * position or -1 if char is not used in the KeyWord. Search example for
557  * string "MM":
558  *	1)	see in index to index['M' - 32],
559  *	2)	take keywords position (enum DCH_MI) from index
560  *	3)	run sequential search in keywords[] from this position
561  *
562  * ----------
563  */
564 
565 typedef enum
566 {
567 	DCH_A_D,
568 	DCH_A_M,
569 	DCH_AD,
570 	DCH_AM,
571 	DCH_B_C,
572 	DCH_BC,
573 	DCH_CC,
574 	DCH_DAY,
575 	DCH_DDD,
576 	DCH_DD,
577 	DCH_DY,
578 	DCH_Day,
579 	DCH_Dy,
580 	DCH_D,
581 	DCH_FX,						/* global suffix */
582 	DCH_HH24,
583 	DCH_HH12,
584 	DCH_HH,
585 	DCH_IDDD,
586 	DCH_ID,
587 	DCH_IW,
588 	DCH_IYYY,
589 	DCH_IYY,
590 	DCH_IY,
591 	DCH_I,
592 	DCH_J,
593 	DCH_MI,
594 	DCH_MM,
595 	DCH_MONTH,
596 	DCH_MON,
597 	DCH_MS,
598 	DCH_Month,
599 	DCH_Mon,
600 	DCH_OF,
601 	DCH_P_M,
602 	DCH_PM,
603 	DCH_Q,
604 	DCH_RM,
605 	DCH_SSSS,
606 	DCH_SS,
607 	DCH_TZ,
608 	DCH_US,
609 	DCH_WW,
610 	DCH_W,
611 	DCH_Y_YYY,
612 	DCH_YYYY,
613 	DCH_YYY,
614 	DCH_YY,
615 	DCH_Y,
616 	DCH_a_d,
617 	DCH_a_m,
618 	DCH_ad,
619 	DCH_am,
620 	DCH_b_c,
621 	DCH_bc,
622 	DCH_cc,
623 	DCH_day,
624 	DCH_ddd,
625 	DCH_dd,
626 	DCH_dy,
627 	DCH_d,
628 	DCH_fx,
629 	DCH_hh24,
630 	DCH_hh12,
631 	DCH_hh,
632 	DCH_iddd,
633 	DCH_id,
634 	DCH_iw,
635 	DCH_iyyy,
636 	DCH_iyy,
637 	DCH_iy,
638 	DCH_i,
639 	DCH_j,
640 	DCH_mi,
641 	DCH_mm,
642 	DCH_month,
643 	DCH_mon,
644 	DCH_ms,
645 	DCH_p_m,
646 	DCH_pm,
647 	DCH_q,
648 	DCH_rm,
649 	DCH_ssss,
650 	DCH_ss,
651 	DCH_tz,
652 	DCH_us,
653 	DCH_ww,
654 	DCH_w,
655 	DCH_y_yyy,
656 	DCH_yyyy,
657 	DCH_yyy,
658 	DCH_yy,
659 	DCH_y,
660 
661 	/* last */
662 	_DCH_last_
663 }			DCH_poz;
664 
665 typedef enum
666 {
667 	NUM_COMMA,
668 	NUM_DEC,
669 	NUM_0,
670 	NUM_9,
671 	NUM_B,
672 	NUM_C,
673 	NUM_D,
674 	NUM_E,
675 	NUM_FM,
676 	NUM_G,
677 	NUM_L,
678 	NUM_MI,
679 	NUM_PL,
680 	NUM_PR,
681 	NUM_RN,
682 	NUM_SG,
683 	NUM_SP,
684 	NUM_S,
685 	NUM_TH,
686 	NUM_V,
687 	NUM_b,
688 	NUM_c,
689 	NUM_d,
690 	NUM_e,
691 	NUM_fm,
692 	NUM_g,
693 	NUM_l,
694 	NUM_mi,
695 	NUM_pl,
696 	NUM_pr,
697 	NUM_rn,
698 	NUM_sg,
699 	NUM_sp,
700 	NUM_s,
701 	NUM_th,
702 	NUM_v,
703 
704 	/* last */
705 	_NUM_last_
706 }			NUM_poz;
707 
708 /* ----------
709  * KeyWords for DATE-TIME version
710  * ----------
711  */
712 static const KeyWord DCH_keywords[] = {
713 /*	name, len, id, is_digit, date_mode */
714 	{"A.D.", 4, DCH_A_D, FALSE, FROM_CHAR_DATE_NONE},	/* A */
715 	{"A.M.", 4, DCH_A_M, FALSE, FROM_CHAR_DATE_NONE},
716 	{"AD", 2, DCH_AD, FALSE, FROM_CHAR_DATE_NONE},
717 	{"AM", 2, DCH_AM, FALSE, FROM_CHAR_DATE_NONE},
718 	{"B.C.", 4, DCH_B_C, FALSE, FROM_CHAR_DATE_NONE},	/* B */
719 	{"BC", 2, DCH_BC, FALSE, FROM_CHAR_DATE_NONE},
720 	{"CC", 2, DCH_CC, TRUE, FROM_CHAR_DATE_NONE},	/* C */
721 	{"DAY", 3, DCH_DAY, FALSE, FROM_CHAR_DATE_NONE},	/* D */
722 	{"DDD", 3, DCH_DDD, TRUE, FROM_CHAR_DATE_GREGORIAN},
723 	{"DD", 2, DCH_DD, TRUE, FROM_CHAR_DATE_GREGORIAN},
724 	{"DY", 2, DCH_DY, FALSE, FROM_CHAR_DATE_NONE},
725 	{"Day", 3, DCH_Day, FALSE, FROM_CHAR_DATE_NONE},
726 	{"Dy", 2, DCH_Dy, FALSE, FROM_CHAR_DATE_NONE},
727 	{"D", 1, DCH_D, TRUE, FROM_CHAR_DATE_GREGORIAN},
728 	{"FX", 2, DCH_FX, FALSE, FROM_CHAR_DATE_NONE},	/* F */
729 	{"HH24", 4, DCH_HH24, TRUE, FROM_CHAR_DATE_NONE},	/* H */
730 	{"HH12", 4, DCH_HH12, TRUE, FROM_CHAR_DATE_NONE},
731 	{"HH", 2, DCH_HH, TRUE, FROM_CHAR_DATE_NONE},
732 	{"IDDD", 4, DCH_IDDD, TRUE, FROM_CHAR_DATE_ISOWEEK},	/* I */
733 	{"ID", 2, DCH_ID, TRUE, FROM_CHAR_DATE_ISOWEEK},
734 	{"IW", 2, DCH_IW, TRUE, FROM_CHAR_DATE_ISOWEEK},
735 	{"IYYY", 4, DCH_IYYY, TRUE, FROM_CHAR_DATE_ISOWEEK},
736 	{"IYY", 3, DCH_IYY, TRUE, FROM_CHAR_DATE_ISOWEEK},
737 	{"IY", 2, DCH_IY, TRUE, FROM_CHAR_DATE_ISOWEEK},
738 	{"I", 1, DCH_I, TRUE, FROM_CHAR_DATE_ISOWEEK},
739 	{"J", 1, DCH_J, TRUE, FROM_CHAR_DATE_NONE}, /* J */
740 	{"MI", 2, DCH_MI, TRUE, FROM_CHAR_DATE_NONE},	/* M */
741 	{"MM", 2, DCH_MM, TRUE, FROM_CHAR_DATE_GREGORIAN},
742 	{"MONTH", 5, DCH_MONTH, FALSE, FROM_CHAR_DATE_GREGORIAN},
743 	{"MON", 3, DCH_MON, FALSE, FROM_CHAR_DATE_GREGORIAN},
744 	{"MS", 2, DCH_MS, TRUE, FROM_CHAR_DATE_NONE},
745 	{"Month", 5, DCH_Month, FALSE, FROM_CHAR_DATE_GREGORIAN},
746 	{"Mon", 3, DCH_Mon, FALSE, FROM_CHAR_DATE_GREGORIAN},
747 	{"OF", 2, DCH_OF, FALSE, FROM_CHAR_DATE_NONE},	/* O */
748 	{"P.M.", 4, DCH_P_M, FALSE, FROM_CHAR_DATE_NONE},	/* P */
749 	{"PM", 2, DCH_PM, FALSE, FROM_CHAR_DATE_NONE},
750 	{"Q", 1, DCH_Q, TRUE, FROM_CHAR_DATE_NONE}, /* Q */
751 	{"RM", 2, DCH_RM, FALSE, FROM_CHAR_DATE_GREGORIAN}, /* R */
752 	{"SSSS", 4, DCH_SSSS, TRUE, FROM_CHAR_DATE_NONE},	/* S */
753 	{"SS", 2, DCH_SS, TRUE, FROM_CHAR_DATE_NONE},
754 	{"TZ", 2, DCH_TZ, FALSE, FROM_CHAR_DATE_NONE},	/* T */
755 	{"US", 2, DCH_US, TRUE, FROM_CHAR_DATE_NONE},	/* U */
756 	{"WW", 2, DCH_WW, TRUE, FROM_CHAR_DATE_GREGORIAN},	/* W */
757 	{"W", 1, DCH_W, TRUE, FROM_CHAR_DATE_GREGORIAN},
758 	{"Y,YYY", 5, DCH_Y_YYY, TRUE, FROM_CHAR_DATE_GREGORIAN},	/* Y */
759 	{"YYYY", 4, DCH_YYYY, TRUE, FROM_CHAR_DATE_GREGORIAN},
760 	{"YYY", 3, DCH_YYY, TRUE, FROM_CHAR_DATE_GREGORIAN},
761 	{"YY", 2, DCH_YY, TRUE, FROM_CHAR_DATE_GREGORIAN},
762 	{"Y", 1, DCH_Y, TRUE, FROM_CHAR_DATE_GREGORIAN},
763 	{"a.d.", 4, DCH_a_d, FALSE, FROM_CHAR_DATE_NONE},	/* a */
764 	{"a.m.", 4, DCH_a_m, FALSE, FROM_CHAR_DATE_NONE},
765 	{"ad", 2, DCH_ad, FALSE, FROM_CHAR_DATE_NONE},
766 	{"am", 2, DCH_am, FALSE, FROM_CHAR_DATE_NONE},
767 	{"b.c.", 4, DCH_b_c, FALSE, FROM_CHAR_DATE_NONE},	/* b */
768 	{"bc", 2, DCH_bc, FALSE, FROM_CHAR_DATE_NONE},
769 	{"cc", 2, DCH_CC, TRUE, FROM_CHAR_DATE_NONE},	/* c */
770 	{"day", 3, DCH_day, FALSE, FROM_CHAR_DATE_NONE},	/* d */
771 	{"ddd", 3, DCH_DDD, TRUE, FROM_CHAR_DATE_GREGORIAN},
772 	{"dd", 2, DCH_DD, TRUE, FROM_CHAR_DATE_GREGORIAN},
773 	{"dy", 2, DCH_dy, FALSE, FROM_CHAR_DATE_NONE},
774 	{"d", 1, DCH_D, TRUE, FROM_CHAR_DATE_GREGORIAN},
775 	{"fx", 2, DCH_FX, FALSE, FROM_CHAR_DATE_NONE},	/* f */
776 	{"hh24", 4, DCH_HH24, TRUE, FROM_CHAR_DATE_NONE},	/* h */
777 	{"hh12", 4, DCH_HH12, TRUE, FROM_CHAR_DATE_NONE},
778 	{"hh", 2, DCH_HH, TRUE, FROM_CHAR_DATE_NONE},
779 	{"iddd", 4, DCH_IDDD, TRUE, FROM_CHAR_DATE_ISOWEEK},	/* i */
780 	{"id", 2, DCH_ID, TRUE, FROM_CHAR_DATE_ISOWEEK},
781 	{"iw", 2, DCH_IW, TRUE, FROM_CHAR_DATE_ISOWEEK},
782 	{"iyyy", 4, DCH_IYYY, TRUE, FROM_CHAR_DATE_ISOWEEK},
783 	{"iyy", 3, DCH_IYY, TRUE, FROM_CHAR_DATE_ISOWEEK},
784 	{"iy", 2, DCH_IY, TRUE, FROM_CHAR_DATE_ISOWEEK},
785 	{"i", 1, DCH_I, TRUE, FROM_CHAR_DATE_ISOWEEK},
786 	{"j", 1, DCH_J, TRUE, FROM_CHAR_DATE_NONE}, /* j */
787 	{"mi", 2, DCH_MI, TRUE, FROM_CHAR_DATE_NONE},	/* m */
788 	{"mm", 2, DCH_MM, TRUE, FROM_CHAR_DATE_GREGORIAN},
789 	{"month", 5, DCH_month, FALSE, FROM_CHAR_DATE_GREGORIAN},
790 	{"mon", 3, DCH_mon, FALSE, FROM_CHAR_DATE_GREGORIAN},
791 	{"ms", 2, DCH_MS, TRUE, FROM_CHAR_DATE_NONE},
792 	{"p.m.", 4, DCH_p_m, FALSE, FROM_CHAR_DATE_NONE},	/* p */
793 	{"pm", 2, DCH_pm, FALSE, FROM_CHAR_DATE_NONE},
794 	{"q", 1, DCH_Q, TRUE, FROM_CHAR_DATE_NONE}, /* q */
795 	{"rm", 2, DCH_rm, FALSE, FROM_CHAR_DATE_GREGORIAN}, /* r */
796 	{"ssss", 4, DCH_SSSS, TRUE, FROM_CHAR_DATE_NONE},	/* s */
797 	{"ss", 2, DCH_SS, TRUE, FROM_CHAR_DATE_NONE},
798 	{"tz", 2, DCH_tz, FALSE, FROM_CHAR_DATE_NONE},	/* t */
799 	{"us", 2, DCH_US, TRUE, FROM_CHAR_DATE_NONE},	/* u */
800 	{"ww", 2, DCH_WW, TRUE, FROM_CHAR_DATE_GREGORIAN},	/* w */
801 	{"w", 1, DCH_W, TRUE, FROM_CHAR_DATE_GREGORIAN},
802 	{"y,yyy", 5, DCH_Y_YYY, TRUE, FROM_CHAR_DATE_GREGORIAN},	/* y */
803 	{"yyyy", 4, DCH_YYYY, TRUE, FROM_CHAR_DATE_GREGORIAN},
804 	{"yyy", 3, DCH_YYY, TRUE, FROM_CHAR_DATE_GREGORIAN},
805 	{"yy", 2, DCH_YY, TRUE, FROM_CHAR_DATE_GREGORIAN},
806 	{"y", 1, DCH_Y, TRUE, FROM_CHAR_DATE_GREGORIAN},
807 
808 	/* last */
809 	{NULL, 0, 0, 0, 0}
810 };
811 
812 /* ----------
813  * KeyWords for NUMBER version
814  *
815  * The is_digit and date_mode fields are not relevant here.
816  * ----------
817  */
818 static const KeyWord NUM_keywords[] = {
819 /*	name, len, id			is in Index */
820 	{",", 1, NUM_COMMA},		/* , */
821 	{".", 1, NUM_DEC},			/* . */
822 	{"0", 1, NUM_0},			/* 0 */
823 	{"9", 1, NUM_9},			/* 9 */
824 	{"B", 1, NUM_B},			/* B */
825 	{"C", 1, NUM_C},			/* C */
826 	{"D", 1, NUM_D},			/* D */
827 	{"EEEE", 4, NUM_E},			/* E */
828 	{"FM", 2, NUM_FM},			/* F */
829 	{"G", 1, NUM_G},			/* G */
830 	{"L", 1, NUM_L},			/* L */
831 	{"MI", 2, NUM_MI},			/* M */
832 	{"PL", 2, NUM_PL},			/* P */
833 	{"PR", 2, NUM_PR},
834 	{"RN", 2, NUM_RN},			/* R */
835 	{"SG", 2, NUM_SG},			/* S */
836 	{"SP", 2, NUM_SP},
837 	{"S", 1, NUM_S},
838 	{"TH", 2, NUM_TH},			/* T */
839 	{"V", 1, NUM_V},			/* V */
840 	{"b", 1, NUM_B},			/* b */
841 	{"c", 1, NUM_C},			/* c */
842 	{"d", 1, NUM_D},			/* d */
843 	{"eeee", 4, NUM_E},			/* e */
844 	{"fm", 2, NUM_FM},			/* f */
845 	{"g", 1, NUM_G},			/* g */
846 	{"l", 1, NUM_L},			/* l */
847 	{"mi", 2, NUM_MI},			/* m */
848 	{"pl", 2, NUM_PL},			/* p */
849 	{"pr", 2, NUM_PR},
850 	{"rn", 2, NUM_rn},			/* r */
851 	{"sg", 2, NUM_SG},			/* s */
852 	{"sp", 2, NUM_SP},
853 	{"s", 1, NUM_S},
854 	{"th", 2, NUM_th},			/* t */
855 	{"v", 1, NUM_V},			/* v */
856 
857 	/* last */
858 	{NULL, 0, 0}
859 };
860 
861 
862 /* ----------
863  * KeyWords index for DATE-TIME version
864  * ----------
865  */
866 static const int DCH_index[KeyWord_INDEX_SIZE] = {
867 /*
868 0	1	2	3	4	5	6	7	8	9
869 */
870 	/*---- first 0..31 chars are skipped ----*/
871 
872 	-1, -1, -1, -1, -1, -1, -1, -1,
873 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
874 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
875 	-1, -1, -1, -1, -1, DCH_A_D, DCH_B_C, DCH_CC, DCH_DAY, -1,
876 	DCH_FX, -1, DCH_HH24, DCH_IDDD, DCH_J, -1, -1, DCH_MI, -1, DCH_OF,
877 	DCH_P_M, DCH_Q, DCH_RM, DCH_SSSS, DCH_TZ, DCH_US, -1, DCH_WW, -1, DCH_Y_YYY,
878 	-1, -1, -1, -1, -1, -1, -1, DCH_a_d, DCH_b_c, DCH_cc,
879 	DCH_day, -1, DCH_fx, -1, DCH_hh24, DCH_iddd, DCH_j, -1, -1, DCH_mi,
880 	-1, -1, DCH_p_m, DCH_q, DCH_rm, DCH_ssss, DCH_tz, DCH_us, -1, DCH_ww,
881 	-1, DCH_y_yyy, -1, -1, -1, -1
882 
883 	/*---- chars over 126 are skipped ----*/
884 };
885 
886 /* ----------
887  * KeyWords index for NUMBER version
888  * ----------
889  */
890 static const int NUM_index[KeyWord_INDEX_SIZE] = {
891 /*
892 0	1	2	3	4	5	6	7	8	9
893 */
894 	/*---- first 0..31 chars are skipped ----*/
895 
896 	-1, -1, -1, -1, -1, -1, -1, -1,
897 	-1, -1, -1, -1, NUM_COMMA, -1, NUM_DEC, -1, NUM_0, -1,
898 	-1, -1, -1, -1, -1, -1, -1, NUM_9, -1, -1,
899 	-1, -1, -1, -1, -1, -1, NUM_B, NUM_C, NUM_D, NUM_E,
900 	NUM_FM, NUM_G, -1, -1, -1, -1, NUM_L, NUM_MI, -1, -1,
901 	NUM_PL, -1, NUM_RN, NUM_SG, NUM_TH, -1, NUM_V, -1, -1, -1,
902 	-1, -1, -1, -1, -1, -1, -1, -1, NUM_b, NUM_c,
903 	NUM_d, NUM_e, NUM_fm, NUM_g, -1, -1, -1, -1, NUM_l, NUM_mi,
904 	-1, -1, NUM_pl, -1, NUM_rn, NUM_sg, NUM_th, -1, NUM_v, -1,
905 	-1, -1, -1, -1, -1, -1
906 
907 	/*---- chars over 126 are skipped ----*/
908 };
909 
910 /* ----------
911  * Number processor struct
912  * ----------
913  */
914 typedef struct NUMProc
915 {
916 	bool		is_to_char;
917 	NUMDesc    *Num;			/* number description		*/
918 
919 	int			sign,			/* '-' or '+'			*/
920 				sign_wrote,		/* was sign write		*/
921 				num_count,		/* number of write digits	*/
922 				num_in,			/* is inside number		*/
923 				num_curr,		/* current position in number	*/
924 				out_pre_spaces, /* spaces before first digit	*/
925 
926 				read_dec,		/* to_number - was read dec. point	*/
927 				read_post,		/* to_number - number of dec. digit */
928 				read_pre;		/* to_number - number non-dec. digit */
929 
930 	char	   *number,			/* string with number	*/
931 			   *number_p,		/* pointer to current number position */
932 			   *inout,			/* in / out buffer	*/
933 			   *inout_p,		/* pointer to current inout position */
934 			   *last_relevant,	/* last relevant number after decimal point */
935 
936 			   *L_negative_sign,	/* Locale */
937 			   *L_positive_sign,
938 			   *decimal,
939 			   *L_thousands_sep,
940 			   *L_currency_symbol;
941 } NUMProc;
942 
943 
944 /* ----------
945  * Functions
946  * ----------
947  */
948 static const KeyWord *index_seq_search(const char *str, const KeyWord *kw,
949 				 const int *index);
950 static const KeySuffix *suff_search(const char *str, const KeySuffix *suf, int type);
951 static void NUMDesc_prepare(NUMDesc *num, FormatNode *n);
952 static void parse_format(FormatNode *node, const char *str, const KeyWord *kw,
953 			 const KeySuffix *suf, const int *index, int ver, NUMDesc *Num);
954 
955 static void DCH_to_char(FormatNode *node, bool is_interval,
956 			TmToChar *in, char *out, Oid collid);
957 static void DCH_from_char(FormatNode *node, const char *in, TmFromChar *out);
958 
959 #ifdef DEBUG_TO_FROM_CHAR
960 static void dump_index(const KeyWord *k, const int *index);
961 static void dump_node(FormatNode *node, int max);
962 #endif
963 
964 static const char *get_th(char *num, int type);
965 static char *str_numth(char *dest, char *num, int type);
966 static int	adjust_partial_year_to_2020(int year);
967 static int	strspace_len(const char *str);
968 static void from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode);
969 static void from_char_set_int(int *dest, const int value, const FormatNode *node);
970 static int	from_char_parse_int_len(int *dest, const char **src, const int len, FormatNode *node);
971 static int	from_char_parse_int(int *dest, const char **src, FormatNode *node);
972 static int	seq_search(const char *name, const char *const *array, int *len);
973 static int	from_char_seq_search(int *dest, const char **src,
974 								 const char *const *array,
975 								 FormatNode *node);
976 static void do_to_timestamp(text *date_txt, text *fmt,
977 				struct pg_tm *tm, fsec_t *fsec);
978 static char *fill_str(char *str, int c, int max);
979 static FormatNode *NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree);
980 static char *int_to_roman(int number);
981 static void NUM_prepare_locale(NUMProc *Np);
982 static char *get_last_relevant_decnum(char *num);
983 static void NUM_numpart_from_char(NUMProc *Np, int id, int input_len);
984 static void NUM_numpart_to_char(NUMProc *Np, int id);
985 static char *NUM_processor(FormatNode *node, NUMDesc *Num, char *inout,
986 			  char *number, int from_char_input_len, int to_char_out_pre_spaces,
987 			  int sign, bool is_to_char, Oid collid);
988 static DCHCacheEntry *DCH_cache_getnew(const char *str);
989 static DCHCacheEntry *DCH_cache_search(const char *str);
990 static DCHCacheEntry *DCH_cache_fetch(const char *str);
991 static NUMCacheEntry *NUM_cache_getnew(const char *str);
992 static NUMCacheEntry *NUM_cache_search(const char *str);
993 static NUMCacheEntry *NUM_cache_fetch(const char *str);
994 
995 
996 /* ----------
997  * Fast sequential search, use index for data selection which
998  * go to seq. cycle (it is very fast for unwanted strings)
999  * (can't be used binary search in format parsing)
1000  * ----------
1001  */
1002 static const KeyWord *
index_seq_search(const char * str,const KeyWord * kw,const int * index)1003 index_seq_search(const char *str, const KeyWord *kw, const int *index)
1004 {
1005 	int			poz;
1006 
1007 	if (!KeyWord_INDEX_FILTER(*str))
1008 		return NULL;
1009 
1010 	if ((poz = *(index + (*str - ' '))) > -1)
1011 	{
1012 		const KeyWord *k = kw + poz;
1013 
1014 		do
1015 		{
1016 			if (strncmp(str, k->name, k->len) == 0)
1017 				return k;
1018 			k++;
1019 			if (!k->name)
1020 				return NULL;
1021 		} while (*str == *k->name);
1022 	}
1023 	return NULL;
1024 }
1025 
1026 static const KeySuffix *
suff_search(const char * str,const KeySuffix * suf,int type)1027 suff_search(const char *str, const KeySuffix *suf, int type)
1028 {
1029 	const KeySuffix *s;
1030 
1031 	for (s = suf; s->name != NULL; s++)
1032 	{
1033 		if (s->type != type)
1034 			continue;
1035 
1036 		if (strncmp(str, s->name, s->len) == 0)
1037 			return s;
1038 	}
1039 	return NULL;
1040 }
1041 
1042 /* ----------
1043  * Prepare NUMDesc (number description struct) via FormatNode struct
1044  * ----------
1045  */
1046 static void
NUMDesc_prepare(NUMDesc * num,FormatNode * n)1047 NUMDesc_prepare(NUMDesc *num, FormatNode *n)
1048 {
1049 	if (n->type != NODE_TYPE_ACTION)
1050 		return;
1051 
1052 	if (IS_EEEE(num) && n->key->id != NUM_E)
1053 		ereport(ERROR,
1054 				(errcode(ERRCODE_SYNTAX_ERROR),
1055 				 errmsg("\"EEEE\" must be the last pattern used")));
1056 
1057 	switch (n->key->id)
1058 	{
1059 		case NUM_9:
1060 			if (IS_BRACKET(num))
1061 				ereport(ERROR,
1062 						(errcode(ERRCODE_SYNTAX_ERROR),
1063 						 errmsg("\"9\" must be ahead of \"PR\"")));
1064 			if (IS_MULTI(num))
1065 			{
1066 				++num->multi;
1067 				break;
1068 			}
1069 			if (IS_DECIMAL(num))
1070 				++num->post;
1071 			else
1072 				++num->pre;
1073 			break;
1074 
1075 		case NUM_0:
1076 			if (IS_BRACKET(num))
1077 				ereport(ERROR,
1078 						(errcode(ERRCODE_SYNTAX_ERROR),
1079 						 errmsg("\"0\" must be ahead of \"PR\"")));
1080 			if (!IS_ZERO(num) && !IS_DECIMAL(num))
1081 			{
1082 				num->flag |= NUM_F_ZERO;
1083 				num->zero_start = num->pre + 1;
1084 			}
1085 			if (!IS_DECIMAL(num))
1086 				++num->pre;
1087 			else
1088 				++num->post;
1089 
1090 			num->zero_end = num->pre + num->post;
1091 			break;
1092 
1093 		case NUM_B:
1094 			if (num->pre == 0 && num->post == 0 && (!IS_ZERO(num)))
1095 				num->flag |= NUM_F_BLANK;
1096 			break;
1097 
1098 		case NUM_D:
1099 			num->flag |= NUM_F_LDECIMAL;
1100 			num->need_locale = TRUE;
1101 			/* FALLTHROUGH */
1102 		case NUM_DEC:
1103 			if (IS_DECIMAL(num))
1104 				ereport(ERROR,
1105 						(errcode(ERRCODE_SYNTAX_ERROR),
1106 						 errmsg("multiple decimal points")));
1107 			if (IS_MULTI(num))
1108 				ereport(ERROR,
1109 						(errcode(ERRCODE_SYNTAX_ERROR),
1110 						 errmsg("cannot use \"V\" and decimal point together")));
1111 			num->flag |= NUM_F_DECIMAL;
1112 			break;
1113 
1114 		case NUM_FM:
1115 			num->flag |= NUM_F_FILLMODE;
1116 			break;
1117 
1118 		case NUM_S:
1119 			if (IS_LSIGN(num))
1120 				ereport(ERROR,
1121 						(errcode(ERRCODE_SYNTAX_ERROR),
1122 						 errmsg("cannot use \"S\" twice")));
1123 			if (IS_PLUS(num) || IS_MINUS(num) || IS_BRACKET(num))
1124 				ereport(ERROR,
1125 						(errcode(ERRCODE_SYNTAX_ERROR),
1126 						 errmsg("cannot use \"S\" and \"PL\"/\"MI\"/\"SG\"/\"PR\" together")));
1127 			if (!IS_DECIMAL(num))
1128 			{
1129 				num->lsign = NUM_LSIGN_PRE;
1130 				num->pre_lsign_num = num->pre;
1131 				num->need_locale = TRUE;
1132 				num->flag |= NUM_F_LSIGN;
1133 			}
1134 			else if (num->lsign == NUM_LSIGN_NONE)
1135 			{
1136 				num->lsign = NUM_LSIGN_POST;
1137 				num->need_locale = TRUE;
1138 				num->flag |= NUM_F_LSIGN;
1139 			}
1140 			break;
1141 
1142 		case NUM_MI:
1143 			if (IS_LSIGN(num))
1144 				ereport(ERROR,
1145 						(errcode(ERRCODE_SYNTAX_ERROR),
1146 						 errmsg("cannot use \"S\" and \"MI\" together")));
1147 			num->flag |= NUM_F_MINUS;
1148 			if (IS_DECIMAL(num))
1149 				num->flag |= NUM_F_MINUS_POST;
1150 			break;
1151 
1152 		case NUM_PL:
1153 			if (IS_LSIGN(num))
1154 				ereport(ERROR,
1155 						(errcode(ERRCODE_SYNTAX_ERROR),
1156 						 errmsg("cannot use \"S\" and \"PL\" together")));
1157 			num->flag |= NUM_F_PLUS;
1158 			if (IS_DECIMAL(num))
1159 				num->flag |= NUM_F_PLUS_POST;
1160 			break;
1161 
1162 		case NUM_SG:
1163 			if (IS_LSIGN(num))
1164 				ereport(ERROR,
1165 						(errcode(ERRCODE_SYNTAX_ERROR),
1166 						 errmsg("cannot use \"S\" and \"SG\" together")));
1167 			num->flag |= NUM_F_MINUS;
1168 			num->flag |= NUM_F_PLUS;
1169 			break;
1170 
1171 		case NUM_PR:
1172 			if (IS_LSIGN(num) || IS_PLUS(num) || IS_MINUS(num))
1173 				ereport(ERROR,
1174 						(errcode(ERRCODE_SYNTAX_ERROR),
1175 						 errmsg("cannot use \"PR\" and \"S\"/\"PL\"/\"MI\"/\"SG\" together")));
1176 			num->flag |= NUM_F_BRACKET;
1177 			break;
1178 
1179 		case NUM_rn:
1180 		case NUM_RN:
1181 			num->flag |= NUM_F_ROMAN;
1182 			break;
1183 
1184 		case NUM_L:
1185 		case NUM_G:
1186 			num->need_locale = TRUE;
1187 			break;
1188 
1189 		case NUM_V:
1190 			if (IS_DECIMAL(num))
1191 				ereport(ERROR,
1192 						(errcode(ERRCODE_SYNTAX_ERROR),
1193 						 errmsg("cannot use \"V\" and decimal point together")));
1194 			num->flag |= NUM_F_MULTI;
1195 			break;
1196 
1197 		case NUM_E:
1198 			if (IS_EEEE(num))
1199 				ereport(ERROR,
1200 						(errcode(ERRCODE_SYNTAX_ERROR),
1201 						 errmsg("cannot use \"EEEE\" twice")));
1202 			if (IS_BLANK(num) || IS_FILLMODE(num) || IS_LSIGN(num) ||
1203 				IS_BRACKET(num) || IS_MINUS(num) || IS_PLUS(num) ||
1204 				IS_ROMAN(num) || IS_MULTI(num))
1205 				ereport(ERROR,
1206 						(errcode(ERRCODE_SYNTAX_ERROR),
1207 						 errmsg("\"EEEE\" is incompatible with other formats"),
1208 						 errdetail("\"EEEE\" may only be used together with digit and decimal point patterns.")));
1209 			num->flag |= NUM_F_EEEE;
1210 			break;
1211 	}
1212 }
1213 
1214 /* ----------
1215  * Format parser, search small keywords and keyword's suffixes, and make
1216  * format-node tree.
1217  *
1218  * for DATE-TIME & NUMBER version
1219  * ----------
1220  */
1221 static void
parse_format(FormatNode * node,const char * str,const KeyWord * kw,const KeySuffix * suf,const int * index,int ver,NUMDesc * Num)1222 parse_format(FormatNode *node, const char *str, const KeyWord *kw,
1223 			 const KeySuffix *suf, const int *index, int ver, NUMDesc *Num)
1224 {
1225 	const KeySuffix *s;
1226 	FormatNode *n;
1227 	int			node_set = 0,
1228 				suffix,
1229 				last = 0;
1230 
1231 #ifdef DEBUG_TO_FROM_CHAR
1232 	elog(DEBUG_elog_output, "to_char/number(): run parser");
1233 #endif
1234 
1235 	n = node;
1236 
1237 	while (*str)
1238 	{
1239 		suffix = 0;
1240 
1241 		/*
1242 		 * Prefix
1243 		 */
1244 		if (ver == DCH_TYPE && (s = suff_search(str, suf, SUFFTYPE_PREFIX)) != NULL)
1245 		{
1246 			suffix |= s->id;
1247 			if (s->len)
1248 				str += s->len;
1249 		}
1250 
1251 		/*
1252 		 * Keyword
1253 		 */
1254 		if (*str && (n->key = index_seq_search(str, kw, index)) != NULL)
1255 		{
1256 			n->type = NODE_TYPE_ACTION;
1257 			n->suffix = 0;
1258 			node_set = 1;
1259 			if (n->key->len)
1260 				str += n->key->len;
1261 
1262 			/*
1263 			 * NUM version: Prepare global NUMDesc struct
1264 			 */
1265 			if (ver == NUM_TYPE)
1266 				NUMDesc_prepare(Num, n);
1267 
1268 			/*
1269 			 * Postfix
1270 			 */
1271 			if (ver == DCH_TYPE && *str && (s = suff_search(str, suf, SUFFTYPE_POSTFIX)) != NULL)
1272 			{
1273 				suffix |= s->id;
1274 				if (s->len)
1275 					str += s->len;
1276 			}
1277 		}
1278 		else if (*str)
1279 		{
1280 			/*
1281 			 * Special characters '\' and '"'
1282 			 */
1283 			if (*str == '"' && last != '\\')
1284 			{
1285 				int			x = 0;
1286 
1287 				while (*(++str))
1288 				{
1289 					if (*str == '"' && x != '\\')
1290 					{
1291 						str++;
1292 						break;
1293 					}
1294 					else if (*str == '\\' && x != '\\')
1295 					{
1296 						x = '\\';
1297 						continue;
1298 					}
1299 					n->type = NODE_TYPE_CHAR;
1300 					n->character = *str;
1301 					n->key = NULL;
1302 					n->suffix = 0;
1303 					++n;
1304 					x = *str;
1305 				}
1306 				node_set = 0;
1307 				suffix = 0;
1308 				last = 0;
1309 			}
1310 			else if (*str && *str == '\\' && last != '\\' && *(str + 1) == '"')
1311 			{
1312 				last = *str;
1313 				str++;
1314 			}
1315 			else if (*str)
1316 			{
1317 				n->type = NODE_TYPE_CHAR;
1318 				n->character = *str;
1319 				n->key = NULL;
1320 				node_set = 1;
1321 				last = 0;
1322 				str++;
1323 			}
1324 		}
1325 
1326 		/* end */
1327 		if (node_set)
1328 		{
1329 			if (n->type == NODE_TYPE_ACTION)
1330 				n->suffix = suffix;
1331 			++n;
1332 
1333 			n->suffix = 0;
1334 			node_set = 0;
1335 		}
1336 	}
1337 
1338 	n->type = NODE_TYPE_END;
1339 	n->suffix = 0;
1340 }
1341 
1342 /* ----------
1343  * DEBUG: Dump the FormatNode Tree (debug)
1344  * ----------
1345  */
1346 #ifdef DEBUG_TO_FROM_CHAR
1347 
1348 #define DUMP_THth(_suf) (S_TH(_suf) ? "TH" : (S_th(_suf) ? "th" : " "))
1349 #define DUMP_FM(_suf)	(S_FM(_suf) ? "FM" : " ")
1350 
1351 static void
dump_node(FormatNode * node,int max)1352 dump_node(FormatNode *node, int max)
1353 {
1354 	FormatNode *n;
1355 	int			a;
1356 
1357 	elog(DEBUG_elog_output, "to_from-char(): DUMP FORMAT");
1358 
1359 	for (a = 0, n = node; a <= max; n++, a++)
1360 	{
1361 		if (n->type == NODE_TYPE_ACTION)
1362 			elog(DEBUG_elog_output, "%d:\t NODE_TYPE_ACTION '%s'\t(%s,%s)",
1363 				 a, n->key->name, DUMP_THth(n->suffix), DUMP_FM(n->suffix));
1364 		else if (n->type == NODE_TYPE_CHAR)
1365 			elog(DEBUG_elog_output, "%d:\t NODE_TYPE_CHAR '%c'", a, n->character);
1366 		else if (n->type == NODE_TYPE_END)
1367 		{
1368 			elog(DEBUG_elog_output, "%d:\t NODE_TYPE_END", a);
1369 			return;
1370 		}
1371 		else
1372 			elog(DEBUG_elog_output, "%d:\t unknown NODE!", a);
1373 	}
1374 }
1375 #endif							/* DEBUG */
1376 
1377 /*****************************************************************************
1378  *			Private utils
1379  *****************************************************************************/
1380 
1381 /* ----------
1382  * Return ST/ND/RD/TH for simple (1..9) numbers
1383  * type --> 0 upper, 1 lower
1384  * ----------
1385  */
1386 static const char *
get_th(char * num,int type)1387 get_th(char *num, int type)
1388 {
1389 	int			len = strlen(num),
1390 				last,
1391 				seclast;
1392 
1393 	last = *(num + (len - 1));
1394 	if (!isdigit((unsigned char) last))
1395 		ereport(ERROR,
1396 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1397 				 errmsg("\"%s\" is not a number", num)));
1398 
1399 	/*
1400 	 * All "teens" (<x>1[0-9]) get 'TH/th', while <x>[02-9][123] still get
1401 	 * 'ST/st', 'ND/nd', 'RD/rd', respectively
1402 	 */
1403 	if ((len > 1) && ((seclast = num[len - 2]) == '1'))
1404 		last = 0;
1405 
1406 	switch (last)
1407 	{
1408 		case '1':
1409 			if (type == TH_UPPER)
1410 				return numTH[0];
1411 			return numth[0];
1412 		case '2':
1413 			if (type == TH_UPPER)
1414 				return numTH[1];
1415 			return numth[1];
1416 		case '3':
1417 			if (type == TH_UPPER)
1418 				return numTH[2];
1419 			return numth[2];
1420 		default:
1421 			if (type == TH_UPPER)
1422 				return numTH[3];
1423 			return numth[3];
1424 	}
1425 }
1426 
1427 /* ----------
1428  * Convert string-number to ordinal string-number
1429  * type --> 0 upper, 1 lower
1430  * ----------
1431  */
1432 static char *
str_numth(char * dest,char * num,int type)1433 str_numth(char *dest, char *num, int type)
1434 {
1435 	if (dest != num)
1436 		strcpy(dest, num);
1437 	strcat(dest, get_th(num, type));
1438 	return dest;
1439 }
1440 
1441 /*****************************************************************************
1442  *			upper/lower/initcap functions
1443  *****************************************************************************/
1444 
1445 #ifdef USE_ICU
1446 
1447 typedef int32_t (*ICU_Convert_Func) (UChar *dest, int32_t destCapacity,
1448 									 const UChar *src, int32_t srcLength,
1449 									 const char *locale,
1450 									 UErrorCode *pErrorCode);
1451 
1452 static int32_t
icu_convert_case(ICU_Convert_Func func,pg_locale_t mylocale,UChar ** buff_dest,UChar * buff_source,int32_t len_source)1453 icu_convert_case(ICU_Convert_Func func, pg_locale_t mylocale,
1454 				 UChar **buff_dest, UChar *buff_source, int32_t len_source)
1455 {
1456 	UErrorCode	status;
1457 	int32_t		len_dest;
1458 
1459 	len_dest = len_source;		/* try first with same length */
1460 	*buff_dest = palloc(len_dest * sizeof(**buff_dest));
1461 	status = U_ZERO_ERROR;
1462 	len_dest = func(*buff_dest, len_dest, buff_source, len_source,
1463 					mylocale->info.icu.locale, &status);
1464 	if (status == U_BUFFER_OVERFLOW_ERROR)
1465 	{
1466 		/* try again with adjusted length */
1467 		pfree(*buff_dest);
1468 		*buff_dest = palloc(len_dest * sizeof(**buff_dest));
1469 		status = U_ZERO_ERROR;
1470 		len_dest = func(*buff_dest, len_dest, buff_source, len_source,
1471 						mylocale->info.icu.locale, &status);
1472 	}
1473 	if (U_FAILURE(status))
1474 		ereport(ERROR,
1475 				(errmsg("case conversion failed: %s", u_errorName(status))));
1476 	return len_dest;
1477 }
1478 
1479 static int32_t
u_strToTitle_default_BI(UChar * dest,int32_t destCapacity,const UChar * src,int32_t srcLength,const char * locale,UErrorCode * pErrorCode)1480 u_strToTitle_default_BI(UChar *dest, int32_t destCapacity,
1481 						const UChar *src, int32_t srcLength,
1482 						const char *locale,
1483 						UErrorCode *pErrorCode)
1484 {
1485 	return u_strToTitle(dest, destCapacity, src, srcLength,
1486 						NULL, locale, pErrorCode);
1487 }
1488 
1489 #endif							/* USE_ICU */
1490 
1491 /*
1492  * If the system provides the needed functions for wide-character manipulation
1493  * (which are all standardized by C99), then we implement upper/lower/initcap
1494  * using wide-character functions, if necessary.  Otherwise we use the
1495  * traditional <ctype.h> functions, which of course will not work as desired
1496  * in multibyte character sets.  Note that in either case we are effectively
1497  * assuming that the database character encoding matches the encoding implied
1498  * by LC_CTYPE.
1499  *
1500  * If the system provides locale_t and associated functions (which are
1501  * standardized by Open Group's XBD), we can support collations that are
1502  * neither default nor C.  The code is written to handle both combinations
1503  * of have-wide-characters and have-locale_t, though it's rather unlikely
1504  * a platform would have the latter without the former.
1505  */
1506 
1507 /*
1508  * collation-aware, wide-character-aware lower function
1509  *
1510  * We pass the number of bytes so we can pass varlena and char*
1511  * to this function.  The result is a palloc'd, null-terminated string.
1512  */
1513 char *
str_tolower(const char * buff,size_t nbytes,Oid collid)1514 str_tolower(const char *buff, size_t nbytes, Oid collid)
1515 {
1516 	char	   *result;
1517 
1518 	if (!buff)
1519 		return NULL;
1520 
1521 	/* C/POSIX collations use this path regardless of database encoding */
1522 	if (lc_ctype_is_c(collid))
1523 	{
1524 		result = asc_tolower(buff, nbytes);
1525 	}
1526 	else
1527 	{
1528 		pg_locale_t mylocale = 0;
1529 
1530 		if (collid != DEFAULT_COLLATION_OID)
1531 		{
1532 			if (!OidIsValid(collid))
1533 			{
1534 				/*
1535 				 * This typically means that the parser could not resolve a
1536 				 * conflict of implicit collations, so report it that way.
1537 				 */
1538 				ereport(ERROR,
1539 						(errcode(ERRCODE_INDETERMINATE_COLLATION),
1540 						 errmsg("could not determine which collation to use for lower() function"),
1541 						 errhint("Use the COLLATE clause to set the collation explicitly.")));
1542 			}
1543 			mylocale = pg_newlocale_from_collation(collid);
1544 		}
1545 
1546 #ifdef USE_ICU
1547 		if (mylocale && mylocale->provider == COLLPROVIDER_ICU)
1548 		{
1549 			int32_t		len_uchar;
1550 			int32_t		len_conv;
1551 			UChar	   *buff_uchar;
1552 			UChar	   *buff_conv;
1553 
1554 			len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes);
1555 			len_conv = icu_convert_case(u_strToLower, mylocale,
1556 										&buff_conv, buff_uchar, len_uchar);
1557 			icu_from_uchar(&result, buff_conv, len_conv);
1558 			pfree(buff_uchar);
1559 			pfree(buff_conv);
1560 		}
1561 		else
1562 #endif
1563 		{
1564 #ifdef USE_WIDE_UPPER_LOWER
1565 			if (pg_database_encoding_max_length() > 1)
1566 			{
1567 				wchar_t    *workspace;
1568 				size_t		curr_char;
1569 				size_t		result_size;
1570 
1571 				/* Overflow paranoia */
1572 				if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
1573 					ereport(ERROR,
1574 							(errcode(ERRCODE_OUT_OF_MEMORY),
1575 							 errmsg("out of memory")));
1576 
1577 				/* Output workspace cannot have more codes than input bytes */
1578 				workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
1579 
1580 				char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale);
1581 
1582 				for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
1583 				{
1584 #ifdef HAVE_LOCALE_T
1585 					if (mylocale)
1586 						workspace[curr_char] = towlower_l(workspace[curr_char], mylocale->info.lt);
1587 					else
1588 #endif
1589 						workspace[curr_char] = towlower(workspace[curr_char]);
1590 				}
1591 
1592 				/*
1593 				 * Make result large enough; case change might change number
1594 				 * of bytes
1595 				 */
1596 				result_size = curr_char * pg_database_encoding_max_length() + 1;
1597 				result = palloc(result_size);
1598 
1599 				wchar2char(result, workspace, result_size, mylocale);
1600 				pfree(workspace);
1601 			}
1602 			else
1603 #endif							/* USE_WIDE_UPPER_LOWER */
1604 			{
1605 				char	   *p;
1606 
1607 				result = pnstrdup(buff, nbytes);
1608 
1609 				/*
1610 				 * Note: we assume that tolower_l() will not be so broken as
1611 				 * to need an isupper_l() guard test.  When using the default
1612 				 * collation, we apply the traditional Postgres behavior that
1613 				 * forces ASCII-style treatment of I/i, but in non-default
1614 				 * collations you get exactly what the collation says.
1615 				 */
1616 				for (p = result; *p; p++)
1617 				{
1618 #ifdef HAVE_LOCALE_T
1619 					if (mylocale)
1620 						*p = tolower_l((unsigned char) *p, mylocale->info.lt);
1621 					else
1622 #endif
1623 						*p = pg_tolower((unsigned char) *p);
1624 				}
1625 			}
1626 		}
1627 	}
1628 
1629 	return result;
1630 }
1631 
1632 /*
1633  * collation-aware, wide-character-aware upper function
1634  *
1635  * We pass the number of bytes so we can pass varlena and char*
1636  * to this function.  The result is a palloc'd, null-terminated string.
1637  */
1638 char *
str_toupper(const char * buff,size_t nbytes,Oid collid)1639 str_toupper(const char *buff, size_t nbytes, Oid collid)
1640 {
1641 	char	   *result;
1642 
1643 	if (!buff)
1644 		return NULL;
1645 
1646 	/* C/POSIX collations use this path regardless of database encoding */
1647 	if (lc_ctype_is_c(collid))
1648 	{
1649 		result = asc_toupper(buff, nbytes);
1650 	}
1651 	else
1652 	{
1653 		pg_locale_t mylocale = 0;
1654 
1655 		if (collid != DEFAULT_COLLATION_OID)
1656 		{
1657 			if (!OidIsValid(collid))
1658 			{
1659 				/*
1660 				 * This typically means that the parser could not resolve a
1661 				 * conflict of implicit collations, so report it that way.
1662 				 */
1663 				ereport(ERROR,
1664 						(errcode(ERRCODE_INDETERMINATE_COLLATION),
1665 						 errmsg("could not determine which collation to use for upper() function"),
1666 						 errhint("Use the COLLATE clause to set the collation explicitly.")));
1667 			}
1668 			mylocale = pg_newlocale_from_collation(collid);
1669 		}
1670 
1671 #ifdef USE_ICU
1672 		if (mylocale && mylocale->provider == COLLPROVIDER_ICU)
1673 		{
1674 			int32_t		len_uchar,
1675 						len_conv;
1676 			UChar	   *buff_uchar;
1677 			UChar	   *buff_conv;
1678 
1679 			len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes);
1680 			len_conv = icu_convert_case(u_strToUpper, mylocale,
1681 										&buff_conv, buff_uchar, len_uchar);
1682 			icu_from_uchar(&result, buff_conv, len_conv);
1683 			pfree(buff_uchar);
1684 			pfree(buff_conv);
1685 		}
1686 		else
1687 #endif
1688 		{
1689 #ifdef USE_WIDE_UPPER_LOWER
1690 			if (pg_database_encoding_max_length() > 1)
1691 			{
1692 				wchar_t    *workspace;
1693 				size_t		curr_char;
1694 				size_t		result_size;
1695 
1696 				/* Overflow paranoia */
1697 				if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
1698 					ereport(ERROR,
1699 							(errcode(ERRCODE_OUT_OF_MEMORY),
1700 							 errmsg("out of memory")));
1701 
1702 				/* Output workspace cannot have more codes than input bytes */
1703 				workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
1704 
1705 				char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale);
1706 
1707 				for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
1708 				{
1709 #ifdef HAVE_LOCALE_T
1710 					if (mylocale)
1711 						workspace[curr_char] = towupper_l(workspace[curr_char], mylocale->info.lt);
1712 					else
1713 #endif
1714 						workspace[curr_char] = towupper(workspace[curr_char]);
1715 				}
1716 
1717 				/*
1718 				 * Make result large enough; case change might change number
1719 				 * of bytes
1720 				 */
1721 				result_size = curr_char * pg_database_encoding_max_length() + 1;
1722 				result = palloc(result_size);
1723 
1724 				wchar2char(result, workspace, result_size, mylocale);
1725 				pfree(workspace);
1726 			}
1727 			else
1728 #endif							/* USE_WIDE_UPPER_LOWER */
1729 			{
1730 				char	   *p;
1731 
1732 				result = pnstrdup(buff, nbytes);
1733 
1734 				/*
1735 				 * Note: we assume that toupper_l() will not be so broken as
1736 				 * to need an islower_l() guard test.  When using the default
1737 				 * collation, we apply the traditional Postgres behavior that
1738 				 * forces ASCII-style treatment of I/i, but in non-default
1739 				 * collations you get exactly what the collation says.
1740 				 */
1741 				for (p = result; *p; p++)
1742 				{
1743 #ifdef HAVE_LOCALE_T
1744 					if (mylocale)
1745 						*p = toupper_l((unsigned char) *p, mylocale->info.lt);
1746 					else
1747 #endif
1748 						*p = pg_toupper((unsigned char) *p);
1749 				}
1750 			}
1751 		}
1752 	}
1753 
1754 	return result;
1755 }
1756 
1757 /*
1758  * collation-aware, wide-character-aware initcap function
1759  *
1760  * We pass the number of bytes so we can pass varlena and char*
1761  * to this function.  The result is a palloc'd, null-terminated string.
1762  */
1763 char *
str_initcap(const char * buff,size_t nbytes,Oid collid)1764 str_initcap(const char *buff, size_t nbytes, Oid collid)
1765 {
1766 	char	   *result;
1767 	int			wasalnum = false;
1768 
1769 	if (!buff)
1770 		return NULL;
1771 
1772 	/* C/POSIX collations use this path regardless of database encoding */
1773 	if (lc_ctype_is_c(collid))
1774 	{
1775 		result = asc_initcap(buff, nbytes);
1776 	}
1777 	else
1778 	{
1779 		pg_locale_t mylocale = 0;
1780 
1781 		if (collid != DEFAULT_COLLATION_OID)
1782 		{
1783 			if (!OidIsValid(collid))
1784 			{
1785 				/*
1786 				 * This typically means that the parser could not resolve a
1787 				 * conflict of implicit collations, so report it that way.
1788 				 */
1789 				ereport(ERROR,
1790 						(errcode(ERRCODE_INDETERMINATE_COLLATION),
1791 						 errmsg("could not determine which collation to use for initcap() function"),
1792 						 errhint("Use the COLLATE clause to set the collation explicitly.")));
1793 			}
1794 			mylocale = pg_newlocale_from_collation(collid);
1795 		}
1796 
1797 #ifdef USE_ICU
1798 		if (mylocale && mylocale->provider == COLLPROVIDER_ICU)
1799 		{
1800 			int32_t		len_uchar,
1801 						len_conv;
1802 			UChar	   *buff_uchar;
1803 			UChar	   *buff_conv;
1804 
1805 			len_uchar = icu_to_uchar(&buff_uchar, buff, nbytes);
1806 			len_conv = icu_convert_case(u_strToTitle_default_BI, mylocale,
1807 										&buff_conv, buff_uchar, len_uchar);
1808 			icu_from_uchar(&result, buff_conv, len_conv);
1809 			pfree(buff_uchar);
1810 			pfree(buff_conv);
1811 		}
1812 		else
1813 #endif
1814 		{
1815 #ifdef USE_WIDE_UPPER_LOWER
1816 			if (pg_database_encoding_max_length() > 1)
1817 			{
1818 				wchar_t    *workspace;
1819 				size_t		curr_char;
1820 				size_t		result_size;
1821 
1822 				/* Overflow paranoia */
1823 				if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
1824 					ereport(ERROR,
1825 							(errcode(ERRCODE_OUT_OF_MEMORY),
1826 							 errmsg("out of memory")));
1827 
1828 				/* Output workspace cannot have more codes than input bytes */
1829 				workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
1830 
1831 				char2wchar(workspace, nbytes + 1, buff, nbytes, mylocale);
1832 
1833 				for (curr_char = 0; workspace[curr_char] != 0; curr_char++)
1834 				{
1835 #ifdef HAVE_LOCALE_T
1836 					if (mylocale)
1837 					{
1838 						if (wasalnum)
1839 							workspace[curr_char] = towlower_l(workspace[curr_char], mylocale->info.lt);
1840 						else
1841 							workspace[curr_char] = towupper_l(workspace[curr_char], mylocale->info.lt);
1842 						wasalnum = iswalnum_l(workspace[curr_char], mylocale->info.lt);
1843 					}
1844 					else
1845 #endif
1846 					{
1847 						if (wasalnum)
1848 							workspace[curr_char] = towlower(workspace[curr_char]);
1849 						else
1850 							workspace[curr_char] = towupper(workspace[curr_char]);
1851 						wasalnum = iswalnum(workspace[curr_char]);
1852 					}
1853 				}
1854 
1855 				/*
1856 				 * Make result large enough; case change might change number
1857 				 * of bytes
1858 				 */
1859 				result_size = curr_char * pg_database_encoding_max_length() + 1;
1860 				result = palloc(result_size);
1861 
1862 				wchar2char(result, workspace, result_size, mylocale);
1863 				pfree(workspace);
1864 			}
1865 			else
1866 #endif							/* USE_WIDE_UPPER_LOWER */
1867 			{
1868 				char	   *p;
1869 
1870 				result = pnstrdup(buff, nbytes);
1871 
1872 				/*
1873 				 * Note: we assume that toupper_l()/tolower_l() will not be so
1874 				 * broken as to need guard tests.  When using the default
1875 				 * collation, we apply the traditional Postgres behavior that
1876 				 * forces ASCII-style treatment of I/i, but in non-default
1877 				 * collations you get exactly what the collation says.
1878 				 */
1879 				for (p = result; *p; p++)
1880 				{
1881 #ifdef HAVE_LOCALE_T
1882 					if (mylocale)
1883 					{
1884 						if (wasalnum)
1885 							*p = tolower_l((unsigned char) *p, mylocale->info.lt);
1886 						else
1887 							*p = toupper_l((unsigned char) *p, mylocale->info.lt);
1888 						wasalnum = isalnum_l((unsigned char) *p, mylocale->info.lt);
1889 					}
1890 					else
1891 #endif
1892 					{
1893 						if (wasalnum)
1894 							*p = pg_tolower((unsigned char) *p);
1895 						else
1896 							*p = pg_toupper((unsigned char) *p);
1897 						wasalnum = isalnum((unsigned char) *p);
1898 					}
1899 				}
1900 			}
1901 		}
1902 	}
1903 
1904 	return result;
1905 }
1906 
1907 /*
1908  * ASCII-only lower function
1909  *
1910  * We pass the number of bytes so we can pass varlena and char*
1911  * to this function.  The result is a palloc'd, null-terminated string.
1912  */
1913 char *
asc_tolower(const char * buff,size_t nbytes)1914 asc_tolower(const char *buff, size_t nbytes)
1915 {
1916 	char	   *result;
1917 	char	   *p;
1918 
1919 	if (!buff)
1920 		return NULL;
1921 
1922 	result = pnstrdup(buff, nbytes);
1923 
1924 	for (p = result; *p; p++)
1925 		*p = pg_ascii_tolower((unsigned char) *p);
1926 
1927 	return result;
1928 }
1929 
1930 /*
1931  * ASCII-only upper function
1932  *
1933  * We pass the number of bytes so we can pass varlena and char*
1934  * to this function.  The result is a palloc'd, null-terminated string.
1935  */
1936 char *
asc_toupper(const char * buff,size_t nbytes)1937 asc_toupper(const char *buff, size_t nbytes)
1938 {
1939 	char	   *result;
1940 	char	   *p;
1941 
1942 	if (!buff)
1943 		return NULL;
1944 
1945 	result = pnstrdup(buff, nbytes);
1946 
1947 	for (p = result; *p; p++)
1948 		*p = pg_ascii_toupper((unsigned char) *p);
1949 
1950 	return result;
1951 }
1952 
1953 /*
1954  * ASCII-only initcap function
1955  *
1956  * We pass the number of bytes so we can pass varlena and char*
1957  * to this function.  The result is a palloc'd, null-terminated string.
1958  */
1959 char *
asc_initcap(const char * buff,size_t nbytes)1960 asc_initcap(const char *buff, size_t nbytes)
1961 {
1962 	char	   *result;
1963 	char	   *p;
1964 	int			wasalnum = false;
1965 
1966 	if (!buff)
1967 		return NULL;
1968 
1969 	result = pnstrdup(buff, nbytes);
1970 
1971 	for (p = result; *p; p++)
1972 	{
1973 		char		c;
1974 
1975 		if (wasalnum)
1976 			*p = c = pg_ascii_tolower((unsigned char) *p);
1977 		else
1978 			*p = c = pg_ascii_toupper((unsigned char) *p);
1979 		/* we don't trust isalnum() here */
1980 		wasalnum = ((c >= 'A' && c <= 'Z') ||
1981 					(c >= 'a' && c <= 'z') ||
1982 					(c >= '0' && c <= '9'));
1983 	}
1984 
1985 	return result;
1986 }
1987 
1988 /* convenience routines for when the input is null-terminated */
1989 
1990 static char *
str_tolower_z(const char * buff,Oid collid)1991 str_tolower_z(const char *buff, Oid collid)
1992 {
1993 	return str_tolower(buff, strlen(buff), collid);
1994 }
1995 
1996 static char *
str_toupper_z(const char * buff,Oid collid)1997 str_toupper_z(const char *buff, Oid collid)
1998 {
1999 	return str_toupper(buff, strlen(buff), collid);
2000 }
2001 
2002 static char *
str_initcap_z(const char * buff,Oid collid)2003 str_initcap_z(const char *buff, Oid collid)
2004 {
2005 	return str_initcap(buff, strlen(buff), collid);
2006 }
2007 
2008 static char *
asc_tolower_z(const char * buff)2009 asc_tolower_z(const char *buff)
2010 {
2011 	return asc_tolower(buff, strlen(buff));
2012 }
2013 
2014 static char *
asc_toupper_z(const char * buff)2015 asc_toupper_z(const char *buff)
2016 {
2017 	return asc_toupper(buff, strlen(buff));
2018 }
2019 
2020 /* asc_initcap_z is not currently needed */
2021 
2022 
2023 /* ----------
2024  * Skip TM / th in FROM_CHAR
2025  *
2026  * If S_THth is on, skip two chars, assuming there are two available
2027  * ----------
2028  */
2029 #define SKIP_THth(ptr, _suf) \
2030 	do { \
2031 		if (S_THth(_suf)) \
2032 		{ \
2033 			if (*(ptr)) (ptr)++; \
2034 			if (*(ptr)) (ptr)++; \
2035 		} \
2036 	} while (0)
2037 
2038 
2039 #ifdef DEBUG_TO_FROM_CHAR
2040 /* -----------
2041  * DEBUG: Call for debug and for index checking; (Show ASCII char
2042  * and defined keyword for each used position
2043  * ----------
2044  */
2045 static void
dump_index(const KeyWord * k,const int * index)2046 dump_index(const KeyWord *k, const int *index)
2047 {
2048 	int			i,
2049 				count = 0,
2050 				free_i = 0;
2051 
2052 	elog(DEBUG_elog_output, "TO-FROM_CHAR: Dump KeyWord Index:");
2053 
2054 	for (i = 0; i < KeyWord_INDEX_SIZE; i++)
2055 	{
2056 		if (index[i] != -1)
2057 		{
2058 			elog(DEBUG_elog_output, "\t%c: %s, ", i + 32, k[index[i]].name);
2059 			count++;
2060 		}
2061 		else
2062 		{
2063 			free_i++;
2064 			elog(DEBUG_elog_output, "\t(%d) %c %d", i, i + 32, index[i]);
2065 		}
2066 	}
2067 	elog(DEBUG_elog_output, "\n\t\tUsed positions: %d,\n\t\tFree positions: %d",
2068 		 count, free_i);
2069 }
2070 #endif							/* DEBUG */
2071 
2072 /* ----------
2073  * Return TRUE if next format picture is not digit value
2074  * ----------
2075  */
2076 static bool
is_next_separator(FormatNode * n)2077 is_next_separator(FormatNode *n)
2078 {
2079 	if (n->type == NODE_TYPE_END)
2080 		return FALSE;
2081 
2082 	if (n->type == NODE_TYPE_ACTION && S_THth(n->suffix))
2083 		return TRUE;
2084 
2085 	/*
2086 	 * Next node
2087 	 */
2088 	n++;
2089 
2090 	/* end of format string is treated like a non-digit separator */
2091 	if (n->type == NODE_TYPE_END)
2092 		return TRUE;
2093 
2094 	if (n->type == NODE_TYPE_ACTION)
2095 	{
2096 		if (n->key->is_digit)
2097 			return FALSE;
2098 
2099 		return TRUE;
2100 	}
2101 	else if (isdigit((unsigned char) n->character))
2102 		return FALSE;
2103 
2104 	return TRUE;				/* some non-digit input (separator) */
2105 }
2106 
2107 
2108 static int
adjust_partial_year_to_2020(int year)2109 adjust_partial_year_to_2020(int year)
2110 {
2111 	/*
2112 	 * Adjust all dates toward 2020; this is effectively what happens when we
2113 	 * assume '70' is 1970 and '69' is 2069.
2114 	 */
2115 	/* Force 0-69 into the 2000's */
2116 	if (year < 70)
2117 		return year + 2000;
2118 	/* Force 70-99 into the 1900's */
2119 	else if (year < 100)
2120 		return year + 1900;
2121 	/* Force 100-519 into the 2000's */
2122 	else if (year < 520)
2123 		return year + 2000;
2124 	/* Force 520-999 into the 1000's */
2125 	else if (year < 1000)
2126 		return year + 1000;
2127 	else
2128 		return year;
2129 }
2130 
2131 
2132 static int
strspace_len(const char * str)2133 strspace_len(const char *str)
2134 {
2135 	int			len = 0;
2136 
2137 	while (*str && isspace((unsigned char) *str))
2138 	{
2139 		str++;
2140 		len++;
2141 	}
2142 	return len;
2143 }
2144 
2145 /*
2146  * Set the date mode of a from-char conversion.
2147  *
2148  * Puke if the date mode has already been set, and the caller attempts to set
2149  * it to a conflicting mode.
2150  */
2151 static void
from_char_set_mode(TmFromChar * tmfc,const FromCharDateMode mode)2152 from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode)
2153 {
2154 	if (mode != FROM_CHAR_DATE_NONE)
2155 	{
2156 		if (tmfc->mode == FROM_CHAR_DATE_NONE)
2157 			tmfc->mode = mode;
2158 		else if (tmfc->mode != mode)
2159 			ereport(ERROR,
2160 					(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2161 					 errmsg("invalid combination of date conventions"),
2162 					 errhint("Do not mix Gregorian and ISO week date "
2163 							 "conventions in a formatting template.")));
2164 	}
2165 }
2166 
2167 /*
2168  * Set the integer pointed to by 'dest' to the given value.
2169  *
2170  * Puke if the destination integer has previously been set to some other
2171  * non-zero value.
2172  */
2173 static void
from_char_set_int(int * dest,const int value,const FormatNode * node)2174 from_char_set_int(int *dest, const int value, const FormatNode *node)
2175 {
2176 	if (*dest != 0 && *dest != value)
2177 		ereport(ERROR,
2178 				(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2179 				 errmsg("conflicting values for \"%s\" field in formatting string",
2180 						node->key->name),
2181 				 errdetail("This value contradicts a previous setting for "
2182 						   "the same field type.")));
2183 	*dest = value;
2184 }
2185 
2186 /*
2187  * Read a single integer from the source string, into the int pointed to by
2188  * 'dest'. If 'dest' is NULL, the result is discarded.
2189  *
2190  * In fixed-width mode (the node does not have the FM suffix), consume at most
2191  * 'len' characters.  However, any leading whitespace isn't counted in 'len'.
2192  *
2193  * We use strtol() to recover the integer value from the source string, in
2194  * accordance with the given FormatNode.
2195  *
2196  * If the conversion completes successfully, src will have been advanced to
2197  * point at the character immediately following the last character used in the
2198  * conversion.
2199  *
2200  * Return the number of characters consumed.
2201  *
2202  * Note that from_char_parse_int() provides a more convenient wrapper where
2203  * the length of the field is the same as the length of the format keyword (as
2204  * with DD and MI).
2205  */
2206 static int
from_char_parse_int_len(int * dest,const char ** src,const int len,FormatNode * node)2207 from_char_parse_int_len(int *dest, const char **src, const int len, FormatNode *node)
2208 {
2209 	long		result;
2210 	char		copy[DCH_MAX_ITEM_SIZ + 1];
2211 	const char *init = *src;
2212 	int			used;
2213 
2214 	/*
2215 	 * Skip any whitespace before parsing the integer.
2216 	 */
2217 	*src += strspace_len(*src);
2218 
2219 	Assert(len <= DCH_MAX_ITEM_SIZ);
2220 	used = (int) strlcpy(copy, *src, len + 1);
2221 
2222 	if (S_FM(node->suffix) || is_next_separator(node))
2223 	{
2224 		/*
2225 		 * This node is in Fill Mode, or the next node is known to be a
2226 		 * non-digit value, so we just slurp as many characters as we can get.
2227 		 */
2228 		char	   *endptr;
2229 
2230 		errno = 0;
2231 		result = strtol(init, &endptr, 10);
2232 		*src = endptr;
2233 	}
2234 	else
2235 	{
2236 		/*
2237 		 * We need to pull exactly the number of characters given in 'len' out
2238 		 * of the string, and convert those.
2239 		 */
2240 		char	   *last;
2241 
2242 		if (used < len)
2243 			ereport(ERROR,
2244 					(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2245 					 errmsg("source string too short for \"%s\" formatting field",
2246 							node->key->name),
2247 					 errdetail("Field requires %d characters, but only %d "
2248 							   "remain.",
2249 							   len, used),
2250 					 errhint("If your source string is not fixed-width, try "
2251 							 "using the \"FM\" modifier.")));
2252 
2253 		errno = 0;
2254 		result = strtol(copy, &last, 10);
2255 		used = last - copy;
2256 
2257 		if (used > 0 && used < len)
2258 			ereport(ERROR,
2259 					(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2260 					 errmsg("invalid value \"%s\" for \"%s\"",
2261 							copy, node->key->name),
2262 					 errdetail("Field requires %d characters, but only %d "
2263 							   "could be parsed.", len, used),
2264 					 errhint("If your source string is not fixed-width, try "
2265 							 "using the \"FM\" modifier.")));
2266 
2267 		*src += used;
2268 	}
2269 
2270 	if (*src == init)
2271 		ereport(ERROR,
2272 				(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2273 				 errmsg("invalid value \"%s\" for \"%s\"",
2274 						copy, node->key->name),
2275 				 errdetail("Value must be an integer.")));
2276 
2277 	if (errno == ERANGE || result < INT_MIN || result > INT_MAX)
2278 		ereport(ERROR,
2279 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2280 				 errmsg("value for \"%s\" in source string is out of range",
2281 						node->key->name),
2282 				 errdetail("Value must be in the range %d to %d.",
2283 						   INT_MIN, INT_MAX)));
2284 
2285 	if (dest != NULL)
2286 		from_char_set_int(dest, (int) result, node);
2287 	return *src - init;
2288 }
2289 
2290 /*
2291  * Call from_char_parse_int_len(), using the length of the format keyword as
2292  * the expected length of the field.
2293  *
2294  * Don't call this function if the field differs in length from the format
2295  * keyword (as with HH24; the keyword length is 4, but the field length is 2).
2296  * In such cases, call from_char_parse_int_len() instead to specify the
2297  * required length explicitly.
2298  */
2299 static int
from_char_parse_int(int * dest,const char ** src,FormatNode * node)2300 from_char_parse_int(int *dest, const char **src, FormatNode *node)
2301 {
2302 	return from_char_parse_int_len(dest, src, node->key->len, node);
2303 }
2304 
2305 /*
2306  * Sequentially search null-terminated "array" for a case-insensitive match
2307  * to the initial character(s) of "name".
2308  *
2309  * Returns array index of match, or -1 for no match.
2310  *
2311  * *len is set to the length of the match, or 0 for no match.
2312  *
2313  * Case-insensitivity is defined per pg_tolower, so this is only
2314  * suitable for comparisons to ASCII strings.
2315  */
2316 static int
seq_search(const char * name,const char * const * array,int * len)2317 seq_search(const char *name, const char *const *array, int *len)
2318 {
2319 	unsigned char firstc;
2320 	const char *const *a;
2321 
2322 	*len = 0;
2323 
2324 	/* empty string can't match anything */
2325 	if (!*name)
2326 		return -1;
2327 
2328 	/* we handle first char specially to gain some speed */
2329 	firstc = pg_tolower((unsigned char) *name);
2330 
2331 	for (a = array; *a != NULL; a++)
2332 	{
2333 		const char *p;
2334 		const char *n;
2335 
2336 		/* compare first chars */
2337 		if (pg_tolower((unsigned char) **a) != firstc)
2338 			continue;
2339 
2340 		/* compare rest of string */
2341 		for (p = *a + 1, n = name + 1;; p++, n++)
2342 		{
2343 			/* return success if we matched whole array entry */
2344 			if (*p == '\0')
2345 			{
2346 				*len = n - name;
2347 				return a - array;
2348 			}
2349 			/* else, must have another character in "name" ... */
2350 			if (*n == '\0')
2351 				break;
2352 			/* ... and it must match */
2353 			if (pg_tolower((unsigned char) *p) !=
2354 				pg_tolower((unsigned char) *n))
2355 				break;
2356 		}
2357 	}
2358 
2359 	return -1;
2360 }
2361 
2362 /*
2363  * Perform a sequential search in 'array' for an entry matching the first
2364  * character(s) of the 'src' string case-insensitively.
2365  *
2366  * If a match is found, copy the array index of the match into the integer
2367  * pointed to by 'dest', advance 'src' to the end of the part of the string
2368  * which matched, and return the number of characters consumed.
2369  *
2370  * If the string doesn't match, throw an error.
2371  *
2372  * 'node' is used only for error reports: node->key->name identifies the
2373  * field type we were searching for.
2374  */
2375 static int
from_char_seq_search(int * dest,const char ** src,const char * const * array,FormatNode * node)2376 from_char_seq_search(int *dest, const char **src, const char *const *array,
2377 					 FormatNode *node)
2378 {
2379 	int			len;
2380 
2381 	*dest = seq_search(*src, array, &len);
2382 
2383 	if (len <= 0)
2384 	{
2385 		/*
2386 		 * In the error report, truncate the string at the next whitespace (if
2387 		 * any) to avoid including irrelevant data.
2388 		 */
2389 		char	   *copy = pstrdup(*src);
2390 		char	   *c;
2391 
2392 		for (c = copy; *c; c++)
2393 		{
2394 			if (scanner_isspace(*c))
2395 			{
2396 				*c = '\0';
2397 				break;
2398 			}
2399 		}
2400 
2401 		ereport(ERROR,
2402 				(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
2403 				 errmsg("invalid value \"%s\" for \"%s\"",
2404 						copy, node->key->name),
2405 				 errdetail("The given value did not match any of the allowed "
2406 						   "values for this field.")));
2407 	}
2408 	*src += len;
2409 	return len;
2410 }
2411 
2412 /* ----------
2413  * Process a TmToChar struct as denoted by a list of FormatNodes.
2414  * The formatted data is written to the string pointed to by 'out'.
2415  * ----------
2416  */
2417 static void
DCH_to_char(FormatNode * node,bool is_interval,TmToChar * in,char * out,Oid collid)2418 DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid collid)
2419 {
2420 	FormatNode *n;
2421 	char	   *s;
2422 	struct pg_tm *tm = &in->tm;
2423 	int			i;
2424 
2425 	/* cache localized days and months */
2426 	cache_locale_time();
2427 
2428 	s = out;
2429 	for (n = node; n->type != NODE_TYPE_END; n++)
2430 	{
2431 		if (n->type != NODE_TYPE_ACTION)
2432 		{
2433 			*s = n->character;
2434 			s++;
2435 			continue;
2436 		}
2437 
2438 		switch (n->key->id)
2439 		{
2440 			case DCH_A_M:
2441 			case DCH_P_M:
2442 				strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2443 					   ? P_M_STR : A_M_STR);
2444 				s += strlen(s);
2445 				break;
2446 			case DCH_AM:
2447 			case DCH_PM:
2448 				strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2449 					   ? PM_STR : AM_STR);
2450 				s += strlen(s);
2451 				break;
2452 			case DCH_a_m:
2453 			case DCH_p_m:
2454 				strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2455 					   ? p_m_STR : a_m_STR);
2456 				s += strlen(s);
2457 				break;
2458 			case DCH_am:
2459 			case DCH_pm:
2460 				strcpy(s, (tm->tm_hour % HOURS_PER_DAY >= HOURS_PER_DAY / 2)
2461 					   ? pm_STR : am_STR);
2462 				s += strlen(s);
2463 				break;
2464 			case DCH_HH:
2465 			case DCH_HH12:
2466 
2467 				/*
2468 				 * display time as shown on a 12-hour clock, even for
2469 				 * intervals
2470 				 */
2471 				sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
2472 						tm->tm_hour % (HOURS_PER_DAY / 2) == 0 ? HOURS_PER_DAY / 2 :
2473 						tm->tm_hour % (HOURS_PER_DAY / 2));
2474 				if (S_THth(n->suffix))
2475 					str_numth(s, s, S_TH_TYPE(n->suffix));
2476 				s += strlen(s);
2477 				break;
2478 			case DCH_HH24:
2479 				sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_hour >= 0) ? 2 : 3,
2480 						tm->tm_hour);
2481 				if (S_THth(n->suffix))
2482 					str_numth(s, s, S_TH_TYPE(n->suffix));
2483 				s += strlen(s);
2484 				break;
2485 			case DCH_MI:
2486 				sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_min >= 0) ? 2 : 3,
2487 						tm->tm_min);
2488 				if (S_THth(n->suffix))
2489 					str_numth(s, s, S_TH_TYPE(n->suffix));
2490 				s += strlen(s);
2491 				break;
2492 			case DCH_SS:
2493 				sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_sec >= 0) ? 2 : 3,
2494 						tm->tm_sec);
2495 				if (S_THth(n->suffix))
2496 					str_numth(s, s, S_TH_TYPE(n->suffix));
2497 				s += strlen(s);
2498 				break;
2499 			case DCH_MS:		/* millisecond */
2500 				sprintf(s, "%03d", (int) (in->fsec / INT64CONST(1000)));
2501 				if (S_THth(n->suffix))
2502 					str_numth(s, s, S_TH_TYPE(n->suffix));
2503 				s += strlen(s);
2504 				break;
2505 			case DCH_US:		/* microsecond */
2506 				sprintf(s, "%06d", (int) in->fsec);
2507 				if (S_THth(n->suffix))
2508 					str_numth(s, s, S_TH_TYPE(n->suffix));
2509 				s += strlen(s);
2510 				break;
2511 			case DCH_SSSS:
2512 				sprintf(s, "%d", tm->tm_hour * SECS_PER_HOUR +
2513 						tm->tm_min * SECS_PER_MINUTE +
2514 						tm->tm_sec);
2515 				if (S_THth(n->suffix))
2516 					str_numth(s, s, S_TH_TYPE(n->suffix));
2517 				s += strlen(s);
2518 				break;
2519 			case DCH_tz:
2520 				INVALID_FOR_INTERVAL;
2521 				if (tmtcTzn(in))
2522 				{
2523 					/* We assume here that timezone names aren't localized */
2524 					char	   *p = asc_tolower_z(tmtcTzn(in));
2525 
2526 					strcpy(s, p);
2527 					pfree(p);
2528 					s += strlen(s);
2529 				}
2530 				break;
2531 			case DCH_TZ:
2532 				INVALID_FOR_INTERVAL;
2533 				if (tmtcTzn(in))
2534 				{
2535 					strcpy(s, tmtcTzn(in));
2536 					s += strlen(s);
2537 				}
2538 				break;
2539 			case DCH_OF:
2540 				INVALID_FOR_INTERVAL;
2541 				sprintf(s, "%c%0*d",
2542 						(tm->tm_gmtoff >= 0) ? '+' : '-',
2543 						S_FM(n->suffix) ? 0 : 2,
2544 						abs((int) tm->tm_gmtoff) / SECS_PER_HOUR);
2545 				s += strlen(s);
2546 				if (abs((int) tm->tm_gmtoff) % SECS_PER_HOUR != 0)
2547 				{
2548 					sprintf(s, ":%02d",
2549 							(abs((int) tm->tm_gmtoff) % SECS_PER_HOUR) / SECS_PER_MINUTE);
2550 					s += strlen(s);
2551 				}
2552 				break;
2553 			case DCH_A_D:
2554 			case DCH_B_C:
2555 				INVALID_FOR_INTERVAL;
2556 				strcpy(s, (tm->tm_year <= 0 ? B_C_STR : A_D_STR));
2557 				s += strlen(s);
2558 				break;
2559 			case DCH_AD:
2560 			case DCH_BC:
2561 				INVALID_FOR_INTERVAL;
2562 				strcpy(s, (tm->tm_year <= 0 ? BC_STR : AD_STR));
2563 				s += strlen(s);
2564 				break;
2565 			case DCH_a_d:
2566 			case DCH_b_c:
2567 				INVALID_FOR_INTERVAL;
2568 				strcpy(s, (tm->tm_year <= 0 ? b_c_STR : a_d_STR));
2569 				s += strlen(s);
2570 				break;
2571 			case DCH_ad:
2572 			case DCH_bc:
2573 				INVALID_FOR_INTERVAL;
2574 				strcpy(s, (tm->tm_year <= 0 ? bc_STR : ad_STR));
2575 				s += strlen(s);
2576 				break;
2577 			case DCH_MONTH:
2578 				INVALID_FOR_INTERVAL;
2579 				if (!tm->tm_mon)
2580 					break;
2581 				if (S_TM(n->suffix))
2582 				{
2583 					char	   *str = str_toupper_z(localized_full_months[tm->tm_mon - 1], collid);
2584 
2585 					if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2586 						strcpy(s, str);
2587 					else
2588 						ereport(ERROR,
2589 								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2590 								 errmsg("localized string format value too long")));
2591 				}
2592 				else
2593 					sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2594 							asc_toupper_z(months_full[tm->tm_mon - 1]));
2595 				s += strlen(s);
2596 				break;
2597 			case DCH_Month:
2598 				INVALID_FOR_INTERVAL;
2599 				if (!tm->tm_mon)
2600 					break;
2601 				if (S_TM(n->suffix))
2602 				{
2603 					char	   *str = str_initcap_z(localized_full_months[tm->tm_mon - 1], collid);
2604 
2605 					if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2606 						strcpy(s, str);
2607 					else
2608 						ereport(ERROR,
2609 								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2610 								 errmsg("localized string format value too long")));
2611 				}
2612 				else
2613 					sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2614 							months_full[tm->tm_mon - 1]);
2615 				s += strlen(s);
2616 				break;
2617 			case DCH_month:
2618 				INVALID_FOR_INTERVAL;
2619 				if (!tm->tm_mon)
2620 					break;
2621 				if (S_TM(n->suffix))
2622 				{
2623 					char	   *str = str_tolower_z(localized_full_months[tm->tm_mon - 1], collid);
2624 
2625 					if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2626 						strcpy(s, str);
2627 					else
2628 						ereport(ERROR,
2629 								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2630 								 errmsg("localized string format value too long")));
2631 				}
2632 				else
2633 					sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2634 							asc_tolower_z(months_full[tm->tm_mon - 1]));
2635 				s += strlen(s);
2636 				break;
2637 			case DCH_MON:
2638 				INVALID_FOR_INTERVAL;
2639 				if (!tm->tm_mon)
2640 					break;
2641 				if (S_TM(n->suffix))
2642 				{
2643 					char	   *str = str_toupper_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2644 
2645 					if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2646 						strcpy(s, str);
2647 					else
2648 						ereport(ERROR,
2649 								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2650 								 errmsg("localized string format value too long")));
2651 				}
2652 				else
2653 					strcpy(s, asc_toupper_z(months[tm->tm_mon - 1]));
2654 				s += strlen(s);
2655 				break;
2656 			case DCH_Mon:
2657 				INVALID_FOR_INTERVAL;
2658 				if (!tm->tm_mon)
2659 					break;
2660 				if (S_TM(n->suffix))
2661 				{
2662 					char	   *str = str_initcap_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2663 
2664 					if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2665 						strcpy(s, str);
2666 					else
2667 						ereport(ERROR,
2668 								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2669 								 errmsg("localized string format value too long")));
2670 				}
2671 				else
2672 					strcpy(s, months[tm->tm_mon - 1]);
2673 				s += strlen(s);
2674 				break;
2675 			case DCH_mon:
2676 				INVALID_FOR_INTERVAL;
2677 				if (!tm->tm_mon)
2678 					break;
2679 				if (S_TM(n->suffix))
2680 				{
2681 					char	   *str = str_tolower_z(localized_abbrev_months[tm->tm_mon - 1], collid);
2682 
2683 					if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2684 						strcpy(s, str);
2685 					else
2686 						ereport(ERROR,
2687 								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2688 								 errmsg("localized string format value too long")));
2689 				}
2690 				else
2691 					strcpy(s, asc_tolower_z(months[tm->tm_mon - 1]));
2692 				s += strlen(s);
2693 				break;
2694 			case DCH_MM:
2695 				sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (tm->tm_mon >= 0) ? 2 : 3,
2696 						tm->tm_mon);
2697 				if (S_THth(n->suffix))
2698 					str_numth(s, s, S_TH_TYPE(n->suffix));
2699 				s += strlen(s);
2700 				break;
2701 			case DCH_DAY:
2702 				INVALID_FOR_INTERVAL;
2703 				if (S_TM(n->suffix))
2704 				{
2705 					char	   *str = str_toupper_z(localized_full_days[tm->tm_wday], collid);
2706 
2707 					if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2708 						strcpy(s, str);
2709 					else
2710 						ereport(ERROR,
2711 								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2712 								 errmsg("localized string format value too long")));
2713 				}
2714 				else
2715 					sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2716 							asc_toupper_z(days[tm->tm_wday]));
2717 				s += strlen(s);
2718 				break;
2719 			case DCH_Day:
2720 				INVALID_FOR_INTERVAL;
2721 				if (S_TM(n->suffix))
2722 				{
2723 					char	   *str = str_initcap_z(localized_full_days[tm->tm_wday], collid);
2724 
2725 					if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2726 						strcpy(s, str);
2727 					else
2728 						ereport(ERROR,
2729 								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2730 								 errmsg("localized string format value too long")));
2731 				}
2732 				else
2733 					sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2734 							days[tm->tm_wday]);
2735 				s += strlen(s);
2736 				break;
2737 			case DCH_day:
2738 				INVALID_FOR_INTERVAL;
2739 				if (S_TM(n->suffix))
2740 				{
2741 					char	   *str = str_tolower_z(localized_full_days[tm->tm_wday], collid);
2742 
2743 					if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2744 						strcpy(s, str);
2745 					else
2746 						ereport(ERROR,
2747 								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2748 								 errmsg("localized string format value too long")));
2749 				}
2750 				else
2751 					sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -9,
2752 							asc_tolower_z(days[tm->tm_wday]));
2753 				s += strlen(s);
2754 				break;
2755 			case DCH_DY:
2756 				INVALID_FOR_INTERVAL;
2757 				if (S_TM(n->suffix))
2758 				{
2759 					char	   *str = str_toupper_z(localized_abbrev_days[tm->tm_wday], collid);
2760 
2761 					if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2762 						strcpy(s, str);
2763 					else
2764 						ereport(ERROR,
2765 								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2766 								 errmsg("localized string format value too long")));
2767 				}
2768 				else
2769 					strcpy(s, asc_toupper_z(days_short[tm->tm_wday]));
2770 				s += strlen(s);
2771 				break;
2772 			case DCH_Dy:
2773 				INVALID_FOR_INTERVAL;
2774 				if (S_TM(n->suffix))
2775 				{
2776 					char	   *str = str_initcap_z(localized_abbrev_days[tm->tm_wday], collid);
2777 
2778 					if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2779 						strcpy(s, str);
2780 					else
2781 						ereport(ERROR,
2782 								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2783 								 errmsg("localized string format value too long")));
2784 				}
2785 				else
2786 					strcpy(s, days_short[tm->tm_wday]);
2787 				s += strlen(s);
2788 				break;
2789 			case DCH_dy:
2790 				INVALID_FOR_INTERVAL;
2791 				if (S_TM(n->suffix))
2792 				{
2793 					char	   *str = str_tolower_z(localized_abbrev_days[tm->tm_wday], collid);
2794 
2795 					if (strlen(str) <= (n->key->len + TM_SUFFIX_LEN) * DCH_MAX_ITEM_SIZ)
2796 						strcpy(s, str);
2797 					else
2798 						ereport(ERROR,
2799 								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2800 								 errmsg("localized string format value too long")));
2801 				}
2802 				else
2803 					strcpy(s, asc_tolower_z(days_short[tm->tm_wday]));
2804 				s += strlen(s);
2805 				break;
2806 			case DCH_DDD:
2807 			case DCH_IDDD:
2808 				sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 3,
2809 						(n->key->id == DCH_DDD) ?
2810 						tm->tm_yday :
2811 						date2isoyearday(tm->tm_year, tm->tm_mon, tm->tm_mday));
2812 				if (S_THth(n->suffix))
2813 					str_numth(s, s, S_TH_TYPE(n->suffix));
2814 				s += strlen(s);
2815 				break;
2816 			case DCH_DD:
2817 				sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2, tm->tm_mday);
2818 				if (S_THth(n->suffix))
2819 					str_numth(s, s, S_TH_TYPE(n->suffix));
2820 				s += strlen(s);
2821 				break;
2822 			case DCH_D:
2823 				INVALID_FOR_INTERVAL;
2824 				sprintf(s, "%d", tm->tm_wday + 1);
2825 				if (S_THth(n->suffix))
2826 					str_numth(s, s, S_TH_TYPE(n->suffix));
2827 				s += strlen(s);
2828 				break;
2829 			case DCH_ID:
2830 				INVALID_FOR_INTERVAL;
2831 				sprintf(s, "%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
2832 				if (S_THth(n->suffix))
2833 					str_numth(s, s, S_TH_TYPE(n->suffix));
2834 				s += strlen(s);
2835 				break;
2836 			case DCH_WW:
2837 				sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
2838 						(tm->tm_yday - 1) / 7 + 1);
2839 				if (S_THth(n->suffix))
2840 					str_numth(s, s, S_TH_TYPE(n->suffix));
2841 				s += strlen(s);
2842 				break;
2843 			case DCH_IW:
2844 				sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : 2,
2845 						date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday));
2846 				if (S_THth(n->suffix))
2847 					str_numth(s, s, S_TH_TYPE(n->suffix));
2848 				s += strlen(s);
2849 				break;
2850 			case DCH_Q:
2851 				if (!tm->tm_mon)
2852 					break;
2853 				sprintf(s, "%d", (tm->tm_mon - 1) / 3 + 1);
2854 				if (S_THth(n->suffix))
2855 					str_numth(s, s, S_TH_TYPE(n->suffix));
2856 				s += strlen(s);
2857 				break;
2858 			case DCH_CC:
2859 				if (is_interval)	/* straight calculation */
2860 					i = tm->tm_year / 100;
2861 				else
2862 				{
2863 					if (tm->tm_year > 0)
2864 						/* Century 20 == 1901 - 2000 */
2865 						i = (tm->tm_year - 1) / 100 + 1;
2866 					else
2867 						/* Century 6BC == 600BC - 501BC */
2868 						i = tm->tm_year / 100 - 1;
2869 				}
2870 				if (i <= 99 && i >= -99)
2871 					sprintf(s, "%0*d", S_FM(n->suffix) ? 0 : (i >= 0) ? 2 : 3, i);
2872 				else
2873 					sprintf(s, "%d", i);
2874 				if (S_THth(n->suffix))
2875 					str_numth(s, s, S_TH_TYPE(n->suffix));
2876 				s += strlen(s);
2877 				break;
2878 			case DCH_Y_YYY:
2879 				i = ADJUST_YEAR(tm->tm_year, is_interval) / 1000;
2880 				sprintf(s, "%d,%03d", i,
2881 						ADJUST_YEAR(tm->tm_year, is_interval) - (i * 1000));
2882 				if (S_THth(n->suffix))
2883 					str_numth(s, s, S_TH_TYPE(n->suffix));
2884 				s += strlen(s);
2885 				break;
2886 			case DCH_YYYY:
2887 			case DCH_IYYY:
2888 				sprintf(s, "%0*d",
2889 						S_FM(n->suffix) ? 0 :
2890 						(ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 4 : 5,
2891 						(n->key->id == DCH_YYYY ?
2892 						 ADJUST_YEAR(tm->tm_year, is_interval) :
2893 						 ADJUST_YEAR(date2isoyear(tm->tm_year,
2894 												  tm->tm_mon,
2895 												  tm->tm_mday),
2896 									 is_interval)));
2897 				if (S_THth(n->suffix))
2898 					str_numth(s, s, S_TH_TYPE(n->suffix));
2899 				s += strlen(s);
2900 				break;
2901 			case DCH_YYY:
2902 			case DCH_IYY:
2903 				sprintf(s, "%0*d",
2904 						S_FM(n->suffix) ? 0 :
2905 						(ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 3 : 4,
2906 						(n->key->id == DCH_YYY ?
2907 						 ADJUST_YEAR(tm->tm_year, is_interval) :
2908 						 ADJUST_YEAR(date2isoyear(tm->tm_year,
2909 												  tm->tm_mon,
2910 												  tm->tm_mday),
2911 									 is_interval)) % 1000);
2912 				if (S_THth(n->suffix))
2913 					str_numth(s, s, S_TH_TYPE(n->suffix));
2914 				s += strlen(s);
2915 				break;
2916 			case DCH_YY:
2917 			case DCH_IY:
2918 				sprintf(s, "%0*d",
2919 						S_FM(n->suffix) ? 0 :
2920 						(ADJUST_YEAR(tm->tm_year, is_interval) >= 0) ? 2 : 3,
2921 						(n->key->id == DCH_YY ?
2922 						 ADJUST_YEAR(tm->tm_year, is_interval) :
2923 						 ADJUST_YEAR(date2isoyear(tm->tm_year,
2924 												  tm->tm_mon,
2925 												  tm->tm_mday),
2926 									 is_interval)) % 100);
2927 				if (S_THth(n->suffix))
2928 					str_numth(s, s, S_TH_TYPE(n->suffix));
2929 				s += strlen(s);
2930 				break;
2931 			case DCH_Y:
2932 			case DCH_I:
2933 				sprintf(s, "%1d",
2934 						(n->key->id == DCH_Y ?
2935 						 ADJUST_YEAR(tm->tm_year, is_interval) :
2936 						 ADJUST_YEAR(date2isoyear(tm->tm_year,
2937 												  tm->tm_mon,
2938 												  tm->tm_mday),
2939 									 is_interval)) % 10);
2940 				if (S_THth(n->suffix))
2941 					str_numth(s, s, S_TH_TYPE(n->suffix));
2942 				s += strlen(s);
2943 				break;
2944 			case DCH_RM:
2945 				/* FALLTHROUGH */
2946 			case DCH_rm:
2947 
2948 				/*
2949 				 * For intervals, values like '12 month' will be reduced to 0
2950 				 * month and some years.  These should be processed.
2951 				 */
2952 				if (!tm->tm_mon && !tm->tm_year)
2953 					break;
2954 				else
2955 				{
2956 					int			mon = 0;
2957 					const char *const *months;
2958 
2959 					if (n->key->id == DCH_RM)
2960 						months = rm_months_upper;
2961 					else
2962 						months = rm_months_lower;
2963 
2964 					/*
2965 					 * Compute the position in the roman-numeral array.  Note
2966 					 * that the contents of the array are reversed, December
2967 					 * being first and January last.
2968 					 */
2969 					if (tm->tm_mon == 0)
2970 					{
2971 						/*
2972 						 * This case is special, and tracks the case of full
2973 						 * interval years.
2974 						 */
2975 						mon = tm->tm_year >= 0 ? 0 : MONTHS_PER_YEAR - 1;
2976 					}
2977 					else if (tm->tm_mon < 0)
2978 					{
2979 						/*
2980 						 * Negative case.  In this case, the calculation is
2981 						 * reversed, where -1 means December, -2 November,
2982 						 * etc.
2983 						 */
2984 						mon = -1 * (tm->tm_mon + 1);
2985 					}
2986 					else
2987 					{
2988 						/*
2989 						 * Common case, with a strictly positive value.  The
2990 						 * position in the array matches with the value of
2991 						 * tm_mon.
2992 						 */
2993 						mon = MONTHS_PER_YEAR - tm->tm_mon;
2994 					}
2995 
2996 					sprintf(s, "%*s", S_FM(n->suffix) ? 0 : -4,
2997 							months[mon]);
2998 					s += strlen(s);
2999 				}
3000 				break;
3001 			case DCH_W:
3002 				sprintf(s, "%d", (tm->tm_mday - 1) / 7 + 1);
3003 				if (S_THth(n->suffix))
3004 					str_numth(s, s, S_TH_TYPE(n->suffix));
3005 				s += strlen(s);
3006 				break;
3007 			case DCH_J:
3008 				sprintf(s, "%d", date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
3009 				if (S_THth(n->suffix))
3010 					str_numth(s, s, S_TH_TYPE(n->suffix));
3011 				s += strlen(s);
3012 				break;
3013 		}
3014 	}
3015 
3016 	*s = '\0';
3017 }
3018 
3019 /* ----------
3020  * Process a string as denoted by a list of FormatNodes.
3021  * The TmFromChar struct pointed to by 'out' is populated with the results.
3022  *
3023  * Note: we currently don't have any to_interval() function, so there
3024  * is no need here for INVALID_FOR_INTERVAL checks.
3025  * ----------
3026  */
3027 static void
DCH_from_char(FormatNode * node,const char * in,TmFromChar * out)3028 DCH_from_char(FormatNode *node, const char *in, TmFromChar *out)
3029 {
3030 	FormatNode *n;
3031 	const char *s;
3032 	int			len,
3033 				value;
3034 	bool		fx_mode = false;
3035 
3036 	for (n = node, s = in; n->type != NODE_TYPE_END && *s != '\0'; n++)
3037 	{
3038 		if (n->type != NODE_TYPE_ACTION)
3039 		{
3040 			/*
3041 			 * Separator, so consume one character from input string.  Notice
3042 			 * we don't insist that the consumed character match the format's
3043 			 * character.
3044 			 */
3045 			s++;
3046 			continue;
3047 		}
3048 
3049 		/* Ignore spaces before fields when not in FX (fixed width) mode */
3050 		if (!fx_mode && n->key->id != DCH_FX)
3051 		{
3052 			while (*s != '\0' && isspace((unsigned char) *s))
3053 				s++;
3054 		}
3055 
3056 		from_char_set_mode(out, n->key->date_mode);
3057 
3058 		switch (n->key->id)
3059 		{
3060 			case DCH_FX:
3061 				fx_mode = true;
3062 				break;
3063 			case DCH_A_M:
3064 			case DCH_P_M:
3065 			case DCH_a_m:
3066 			case DCH_p_m:
3067 				from_char_seq_search(&value, &s, ampm_strings_long,
3068 									 n);
3069 				from_char_set_int(&out->pm, value % 2, n);
3070 				out->clock = CLOCK_12_HOUR;
3071 				break;
3072 			case DCH_AM:
3073 			case DCH_PM:
3074 			case DCH_am:
3075 			case DCH_pm:
3076 				from_char_seq_search(&value, &s, ampm_strings,
3077 									 n);
3078 				from_char_set_int(&out->pm, value % 2, n);
3079 				out->clock = CLOCK_12_HOUR;
3080 				break;
3081 			case DCH_HH:
3082 			case DCH_HH12:
3083 				from_char_parse_int_len(&out->hh, &s, 2, n);
3084 				out->clock = CLOCK_12_HOUR;
3085 				SKIP_THth(s, n->suffix);
3086 				break;
3087 			case DCH_HH24:
3088 				from_char_parse_int_len(&out->hh, &s, 2, n);
3089 				SKIP_THth(s, n->suffix);
3090 				break;
3091 			case DCH_MI:
3092 				from_char_parse_int(&out->mi, &s, n);
3093 				SKIP_THth(s, n->suffix);
3094 				break;
3095 			case DCH_SS:
3096 				from_char_parse_int(&out->ss, &s, n);
3097 				SKIP_THth(s, n->suffix);
3098 				break;
3099 			case DCH_MS:		/* millisecond */
3100 				len = from_char_parse_int_len(&out->ms, &s, 3, n);
3101 
3102 				/*
3103 				 * 25 is 0.25 and 250 is 0.25 too; 025 is 0.025 and not 0.25
3104 				 */
3105 				out->ms *= len == 1 ? 100 :
3106 					len == 2 ? 10 : 1;
3107 
3108 				SKIP_THth(s, n->suffix);
3109 				break;
3110 			case DCH_US:		/* microsecond */
3111 				len = from_char_parse_int_len(&out->us, &s, 6, n);
3112 
3113 				out->us *= len == 1 ? 100000 :
3114 					len == 2 ? 10000 :
3115 					len == 3 ? 1000 :
3116 					len == 4 ? 100 :
3117 					len == 5 ? 10 : 1;
3118 
3119 				SKIP_THth(s, n->suffix);
3120 				break;
3121 			case DCH_SSSS:
3122 				from_char_parse_int(&out->ssss, &s, n);
3123 				SKIP_THth(s, n->suffix);
3124 				break;
3125 			case DCH_tz:
3126 			case DCH_TZ:
3127 			case DCH_OF:
3128 				ereport(ERROR,
3129 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3130 						 errmsg("formatting field \"%s\" is only supported in to_char",
3131 								n->key->name)));
3132 				break;
3133 			case DCH_A_D:
3134 			case DCH_B_C:
3135 			case DCH_a_d:
3136 			case DCH_b_c:
3137 				from_char_seq_search(&value, &s, adbc_strings_long,
3138 									 n);
3139 				from_char_set_int(&out->bc, value % 2, n);
3140 				break;
3141 			case DCH_AD:
3142 			case DCH_BC:
3143 			case DCH_ad:
3144 			case DCH_bc:
3145 				from_char_seq_search(&value, &s, adbc_strings,
3146 									 n);
3147 				from_char_set_int(&out->bc, value % 2, n);
3148 				break;
3149 			case DCH_MONTH:
3150 			case DCH_Month:
3151 			case DCH_month:
3152 				from_char_seq_search(&value, &s, months_full,
3153 									 n);
3154 				from_char_set_int(&out->mm, value + 1, n);
3155 				break;
3156 			case DCH_MON:
3157 			case DCH_Mon:
3158 			case DCH_mon:
3159 				from_char_seq_search(&value, &s, months,
3160 									 n);
3161 				from_char_set_int(&out->mm, value + 1, n);
3162 				break;
3163 			case DCH_MM:
3164 				from_char_parse_int(&out->mm, &s, n);
3165 				SKIP_THth(s, n->suffix);
3166 				break;
3167 			case DCH_DAY:
3168 			case DCH_Day:
3169 			case DCH_day:
3170 				from_char_seq_search(&value, &s, days,
3171 									 n);
3172 				from_char_set_int(&out->d, value, n);
3173 				out->d++;
3174 				break;
3175 			case DCH_DY:
3176 			case DCH_Dy:
3177 			case DCH_dy:
3178 				from_char_seq_search(&value, &s, days_short,
3179 									 n);
3180 				from_char_set_int(&out->d, value, n);
3181 				out->d++;
3182 				break;
3183 			case DCH_DDD:
3184 				from_char_parse_int(&out->ddd, &s, n);
3185 				SKIP_THth(s, n->suffix);
3186 				break;
3187 			case DCH_IDDD:
3188 				from_char_parse_int_len(&out->ddd, &s, 3, n);
3189 				SKIP_THth(s, n->suffix);
3190 				break;
3191 			case DCH_DD:
3192 				from_char_parse_int(&out->dd, &s, n);
3193 				SKIP_THth(s, n->suffix);
3194 				break;
3195 			case DCH_D:
3196 				from_char_parse_int(&out->d, &s, n);
3197 				SKIP_THth(s, n->suffix);
3198 				break;
3199 			case DCH_ID:
3200 				from_char_parse_int_len(&out->d, &s, 1, n);
3201 				/* Shift numbering to match Gregorian where Sunday = 1 */
3202 				if (++out->d > 7)
3203 					out->d = 1;
3204 				SKIP_THth(s, n->suffix);
3205 				break;
3206 			case DCH_WW:
3207 			case DCH_IW:
3208 				from_char_parse_int(&out->ww, &s, n);
3209 				SKIP_THth(s, n->suffix);
3210 				break;
3211 			case DCH_Q:
3212 
3213 				/*
3214 				 * We ignore 'Q' when converting to date because it is unclear
3215 				 * which date in the quarter to use, and some people specify
3216 				 * both quarter and month, so if it was honored it might
3217 				 * conflict with the supplied month. That is also why we don't
3218 				 * throw an error.
3219 				 *
3220 				 * We still parse the source string for an integer, but it
3221 				 * isn't stored anywhere in 'out'.
3222 				 */
3223 				from_char_parse_int((int *) NULL, &s, n);
3224 				SKIP_THth(s, n->suffix);
3225 				break;
3226 			case DCH_CC:
3227 				from_char_parse_int(&out->cc, &s, n);
3228 				SKIP_THth(s, n->suffix);
3229 				break;
3230 			case DCH_Y_YYY:
3231 				{
3232 					int			matched,
3233 								years,
3234 								millennia,
3235 								nch;
3236 
3237 					matched = sscanf(s, "%d,%03d%n", &millennia, &years, &nch);
3238 					if (matched < 2)
3239 						ereport(ERROR,
3240 								(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3241 								 errmsg("invalid input string for \"Y,YYY\"")));
3242 					years += (millennia * 1000);
3243 					from_char_set_int(&out->year, years, n);
3244 					out->yysz = 4;
3245 					s += nch;
3246 					SKIP_THth(s, n->suffix);
3247 				}
3248 				break;
3249 			case DCH_YYYY:
3250 			case DCH_IYYY:
3251 				from_char_parse_int(&out->year, &s, n);
3252 				out->yysz = 4;
3253 				SKIP_THth(s, n->suffix);
3254 				break;
3255 			case DCH_YYY:
3256 			case DCH_IYY:
3257 				if (from_char_parse_int(&out->year, &s, n) < 4)
3258 					out->year = adjust_partial_year_to_2020(out->year);
3259 				out->yysz = 3;
3260 				SKIP_THth(s, n->suffix);
3261 				break;
3262 			case DCH_YY:
3263 			case DCH_IY:
3264 				if (from_char_parse_int(&out->year, &s, n) < 4)
3265 					out->year = adjust_partial_year_to_2020(out->year);
3266 				out->yysz = 2;
3267 				SKIP_THth(s, n->suffix);
3268 				break;
3269 			case DCH_Y:
3270 			case DCH_I:
3271 				if (from_char_parse_int(&out->year, &s, n) < 4)
3272 					out->year = adjust_partial_year_to_2020(out->year);
3273 				out->yysz = 1;
3274 				SKIP_THth(s, n->suffix);
3275 				break;
3276 			case DCH_RM:
3277 			case DCH_rm:
3278 				from_char_seq_search(&value, &s, rm_months_lower,
3279 									 n);
3280 				from_char_set_int(&out->mm, MONTHS_PER_YEAR - value, n);
3281 				break;
3282 			case DCH_W:
3283 				from_char_parse_int(&out->w, &s, n);
3284 				SKIP_THth(s, n->suffix);
3285 				break;
3286 			case DCH_J:
3287 				from_char_parse_int(&out->j, &s, n);
3288 				SKIP_THth(s, n->suffix);
3289 				break;
3290 		}
3291 	}
3292 }
3293 
3294 /* select a DCHCacheEntry to hold the given format picture */
3295 static DCHCacheEntry *
DCH_cache_getnew(const char * str)3296 DCH_cache_getnew(const char *str)
3297 {
3298 	DCHCacheEntry *ent;
3299 
3300 	/* counter overflow check - paranoia? */
3301 	if (DCHCounter >= (INT_MAX - DCH_CACHE_ENTRIES))
3302 	{
3303 		DCHCounter = 0;
3304 
3305 		for (ent = DCHCache; ent < (DCHCache + DCH_CACHE_ENTRIES); ent++)
3306 			ent->age = (++DCHCounter);
3307 	}
3308 
3309 	/*
3310 	 * If cache is full, remove oldest entry (or recycle first not-valid one)
3311 	 */
3312 	if (n_DCHCache >= DCH_CACHE_ENTRIES)
3313 	{
3314 		DCHCacheEntry *old = DCHCache + 0;
3315 
3316 #ifdef DEBUG_TO_FROM_CHAR
3317 		elog(DEBUG_elog_output, "cache is full (%d)", n_DCHCache);
3318 #endif
3319 		if (old->valid)
3320 		{
3321 			for (ent = DCHCache + 1; ent < (DCHCache + DCH_CACHE_ENTRIES); ent++)
3322 			{
3323 				if (!ent->valid)
3324 				{
3325 					old = ent;
3326 					break;
3327 				}
3328 				if (ent->age < old->age)
3329 					old = ent;
3330 			}
3331 		}
3332 #ifdef DEBUG_TO_FROM_CHAR
3333 		elog(DEBUG_elog_output, "OLD: '%s' AGE: %d", old->str, old->age);
3334 #endif
3335 		old->valid = false;
3336 		StrNCpy(old->str, str, DCH_CACHE_SIZE + 1);
3337 		old->age = (++DCHCounter);
3338 		/* caller is expected to fill format, then set valid */
3339 		return old;
3340 	}
3341 	else
3342 	{
3343 #ifdef DEBUG_TO_FROM_CHAR
3344 		elog(DEBUG_elog_output, "NEW (%d)", n_DCHCache);
3345 #endif
3346 		ent = DCHCache + n_DCHCache;
3347 		ent->valid = false;
3348 		StrNCpy(ent->str, str, DCH_CACHE_SIZE + 1);
3349 		ent->age = (++DCHCounter);
3350 		/* caller is expected to fill format, then set valid */
3351 		++n_DCHCache;
3352 		return ent;
3353 	}
3354 }
3355 
3356 /* look for an existing DCHCacheEntry matching the given format picture */
3357 static DCHCacheEntry *
DCH_cache_search(const char * str)3358 DCH_cache_search(const char *str)
3359 {
3360 	int			i;
3361 	DCHCacheEntry *ent;
3362 
3363 	/* counter overflow check - paranoia? */
3364 	if (DCHCounter >= (INT_MAX - DCH_CACHE_ENTRIES))
3365 	{
3366 		DCHCounter = 0;
3367 
3368 		for (ent = DCHCache; ent < (DCHCache + DCH_CACHE_ENTRIES); ent++)
3369 			ent->age = (++DCHCounter);
3370 	}
3371 
3372 	for (i = 0, ent = DCHCache; i < n_DCHCache; i++, ent++)
3373 	{
3374 		if (ent->valid && strcmp(ent->str, str) == 0)
3375 		{
3376 			ent->age = (++DCHCounter);
3377 			return ent;
3378 		}
3379 	}
3380 
3381 	return NULL;
3382 }
3383 
3384 /* Find or create a DCHCacheEntry for the given format picture */
3385 static DCHCacheEntry *
DCH_cache_fetch(const char * str)3386 DCH_cache_fetch(const char *str)
3387 {
3388 	DCHCacheEntry *ent;
3389 
3390 	if ((ent = DCH_cache_search(str)) == NULL)
3391 	{
3392 		/*
3393 		 * Not in the cache, must run parser and save a new format-picture to
3394 		 * the cache.  Do not mark the cache entry valid until parsing
3395 		 * succeeds.
3396 		 */
3397 		ent = DCH_cache_getnew(str);
3398 
3399 		parse_format(ent->format, str, DCH_keywords,
3400 					 DCH_suff, DCH_index, DCH_TYPE, NULL);
3401 
3402 		ent->valid = true;
3403 	}
3404 	return ent;
3405 }
3406 
3407 /*
3408  * Format a date/time or interval into a string according to fmt.
3409  * We parse fmt into a list of FormatNodes.  This is then passed to DCH_to_char
3410  * for formatting.
3411  */
3412 static text *
datetime_to_char_body(TmToChar * tmtc,text * fmt,bool is_interval,Oid collid)3413 datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval, Oid collid)
3414 {
3415 	FormatNode *format;
3416 	char	   *fmt_str,
3417 			   *result;
3418 	bool		incache;
3419 	int			fmt_len;
3420 	text	   *res;
3421 
3422 	/*
3423 	 * Convert fmt to C string
3424 	 */
3425 	fmt_str = text_to_cstring(fmt);
3426 	fmt_len = strlen(fmt_str);
3427 
3428 	/*
3429 	 * Allocate workspace for result as C string
3430 	 */
3431 	result = palloc((fmt_len * DCH_MAX_ITEM_SIZ) + 1);
3432 	*result = '\0';
3433 
3434 	if (fmt_len > DCH_CACHE_SIZE)
3435 	{
3436 		/*
3437 		 * Allocate new memory if format picture is bigger than static cache
3438 		 * and do not use cache (call parser always)
3439 		 */
3440 		incache = FALSE;
3441 
3442 		format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
3443 
3444 		parse_format(format, fmt_str, DCH_keywords,
3445 					 DCH_suff, DCH_index, DCH_TYPE, NULL);
3446 	}
3447 	else
3448 	{
3449 		/*
3450 		 * Use cache buffers
3451 		 */
3452 		DCHCacheEntry *ent = DCH_cache_fetch(fmt_str);
3453 
3454 		incache = TRUE;
3455 		format = ent->format;
3456 	}
3457 
3458 	/* The real work is here */
3459 	DCH_to_char(format, is_interval, tmtc, result, collid);
3460 
3461 	if (!incache)
3462 		pfree(format);
3463 
3464 	pfree(fmt_str);
3465 
3466 	/* convert C-string result to TEXT format */
3467 	res = cstring_to_text(result);
3468 
3469 	pfree(result);
3470 	return res;
3471 }
3472 
3473 /****************************************************************************
3474  *				Public routines
3475  ***************************************************************************/
3476 
3477 /* -------------------
3478  * TIMESTAMP to_char()
3479  * -------------------
3480  */
3481 Datum
timestamp_to_char(PG_FUNCTION_ARGS)3482 timestamp_to_char(PG_FUNCTION_ARGS)
3483 {
3484 	Timestamp	dt = PG_GETARG_TIMESTAMP(0);
3485 	text	   *fmt = PG_GETARG_TEXT_PP(1),
3486 			   *res;
3487 	TmToChar	tmtc;
3488 	struct pg_tm *tm;
3489 	int			thisdate;
3490 
3491 	if (VARSIZE_ANY_EXHDR(fmt) <= 0 || TIMESTAMP_NOT_FINITE(dt))
3492 		PG_RETURN_NULL();
3493 
3494 	ZERO_tmtc(&tmtc);
3495 	tm = tmtcTm(&tmtc);
3496 
3497 	if (timestamp2tm(dt, NULL, tm, &tmtcFsec(&tmtc), NULL, NULL) != 0)
3498 		ereport(ERROR,
3499 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3500 				 errmsg("timestamp out of range")));
3501 
3502 	thisdate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
3503 	tm->tm_wday = (thisdate + 1) % 7;
3504 	tm->tm_yday = thisdate - date2j(tm->tm_year, 1, 1) + 1;
3505 
3506 	if (!(res = datetime_to_char_body(&tmtc, fmt, false, PG_GET_COLLATION())))
3507 		PG_RETURN_NULL();
3508 
3509 	PG_RETURN_TEXT_P(res);
3510 }
3511 
3512 Datum
timestamptz_to_char(PG_FUNCTION_ARGS)3513 timestamptz_to_char(PG_FUNCTION_ARGS)
3514 {
3515 	TimestampTz dt = PG_GETARG_TIMESTAMP(0);
3516 	text	   *fmt = PG_GETARG_TEXT_PP(1),
3517 			   *res;
3518 	TmToChar	tmtc;
3519 	int			tz;
3520 	struct pg_tm *tm;
3521 	int			thisdate;
3522 
3523 	if (VARSIZE_ANY_EXHDR(fmt) <= 0 || TIMESTAMP_NOT_FINITE(dt))
3524 		PG_RETURN_NULL();
3525 
3526 	ZERO_tmtc(&tmtc);
3527 	tm = tmtcTm(&tmtc);
3528 
3529 	if (timestamp2tm(dt, &tz, tm, &tmtcFsec(&tmtc), &tmtcTzn(&tmtc), NULL) != 0)
3530 		ereport(ERROR,
3531 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3532 				 errmsg("timestamp out of range")));
3533 
3534 	thisdate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
3535 	tm->tm_wday = (thisdate + 1) % 7;
3536 	tm->tm_yday = thisdate - date2j(tm->tm_year, 1, 1) + 1;
3537 
3538 	if (!(res = datetime_to_char_body(&tmtc, fmt, false, PG_GET_COLLATION())))
3539 		PG_RETURN_NULL();
3540 
3541 	PG_RETURN_TEXT_P(res);
3542 }
3543 
3544 
3545 /* -------------------
3546  * INTERVAL to_char()
3547  * -------------------
3548  */
3549 Datum
interval_to_char(PG_FUNCTION_ARGS)3550 interval_to_char(PG_FUNCTION_ARGS)
3551 {
3552 	Interval   *it = PG_GETARG_INTERVAL_P(0);
3553 	text	   *fmt = PG_GETARG_TEXT_PP(1),
3554 			   *res;
3555 	TmToChar	tmtc;
3556 	struct pg_tm *tm;
3557 
3558 	if (VARSIZE_ANY_EXHDR(fmt) <= 0)
3559 		PG_RETURN_NULL();
3560 
3561 	ZERO_tmtc(&tmtc);
3562 	tm = tmtcTm(&tmtc);
3563 
3564 	if (interval2tm(*it, tm, &tmtcFsec(&tmtc)) != 0)
3565 		PG_RETURN_NULL();
3566 
3567 	/* wday is meaningless, yday approximates the total span in days */
3568 	tm->tm_yday = (tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon) * DAYS_PER_MONTH + tm->tm_mday;
3569 
3570 	if (!(res = datetime_to_char_body(&tmtc, fmt, true, PG_GET_COLLATION())))
3571 		PG_RETURN_NULL();
3572 
3573 	PG_RETURN_TEXT_P(res);
3574 }
3575 
3576 /* ---------------------
3577  * TO_TIMESTAMP()
3578  *
3579  * Make Timestamp from date_str which is formatted at argument 'fmt'
3580  * ( to_timestamp is reverse to_char() )
3581  * ---------------------
3582  */
3583 Datum
to_timestamp(PG_FUNCTION_ARGS)3584 to_timestamp(PG_FUNCTION_ARGS)
3585 {
3586 	text	   *date_txt = PG_GETARG_TEXT_PP(0);
3587 	text	   *fmt = PG_GETARG_TEXT_PP(1);
3588 	Timestamp	result;
3589 	int			tz;
3590 	struct pg_tm tm;
3591 	fsec_t		fsec;
3592 
3593 	do_to_timestamp(date_txt, fmt, &tm, &fsec);
3594 
3595 	tz = DetermineTimeZoneOffset(&tm, session_timezone);
3596 
3597 	if (tm2timestamp(&tm, fsec, &tz, &result) != 0)
3598 		ereport(ERROR,
3599 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3600 				 errmsg("timestamp out of range")));
3601 
3602 	PG_RETURN_TIMESTAMP(result);
3603 }
3604 
3605 /* ----------
3606  * TO_DATE
3607  *	Make Date from date_str which is formated at argument 'fmt'
3608  * ----------
3609  */
3610 Datum
to_date(PG_FUNCTION_ARGS)3611 to_date(PG_FUNCTION_ARGS)
3612 {
3613 	text	   *date_txt = PG_GETARG_TEXT_PP(0);
3614 	text	   *fmt = PG_GETARG_TEXT_PP(1);
3615 	DateADT		result;
3616 	struct pg_tm tm;
3617 	fsec_t		fsec;
3618 
3619 	do_to_timestamp(date_txt, fmt, &tm, &fsec);
3620 
3621 	/* Prevent overflow in Julian-day routines */
3622 	if (!IS_VALID_JULIAN(tm.tm_year, tm.tm_mon, tm.tm_mday))
3623 		ereport(ERROR,
3624 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3625 				 errmsg("date out of range: \"%s\"",
3626 						text_to_cstring(date_txt))));
3627 
3628 	result = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) - POSTGRES_EPOCH_JDATE;
3629 
3630 	/* Now check for just-out-of-range dates */
3631 	if (!IS_VALID_DATE(result))
3632 		ereport(ERROR,
3633 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3634 				 errmsg("date out of range: \"%s\"",
3635 						text_to_cstring(date_txt))));
3636 
3637 	PG_RETURN_DATEADT(result);
3638 }
3639 
3640 /*
3641  * do_to_timestamp: shared code for to_timestamp and to_date
3642  *
3643  * Parse the 'date_txt' according to 'fmt', return results as a struct pg_tm
3644  * and fractional seconds.
3645  *
3646  * We parse 'fmt' into a list of FormatNodes, which is then passed to
3647  * DCH_from_char to populate a TmFromChar with the parsed contents of
3648  * 'date_txt'.
3649  *
3650  * The TmFromChar is then analysed and converted into the final results in
3651  * struct 'tm' and 'fsec'.
3652  */
3653 static void
do_to_timestamp(text * date_txt,text * fmt,struct pg_tm * tm,fsec_t * fsec)3654 do_to_timestamp(text *date_txt, text *fmt,
3655 				struct pg_tm *tm, fsec_t *fsec)
3656 {
3657 	FormatNode *format;
3658 	TmFromChar	tmfc;
3659 	int			fmt_len;
3660 	char	   *date_str;
3661 	int			fmask;
3662 
3663 	date_str = text_to_cstring(date_txt);
3664 
3665 	ZERO_tmfc(&tmfc);
3666 	ZERO_tm(tm);
3667 	*fsec = 0;
3668 	fmask = 0;					/* bit mask for ValidateDate() */
3669 
3670 	fmt_len = VARSIZE_ANY_EXHDR(fmt);
3671 
3672 	if (fmt_len)
3673 	{
3674 		char	   *fmt_str;
3675 		bool		incache;
3676 
3677 		fmt_str = text_to_cstring(fmt);
3678 
3679 		if (fmt_len > DCH_CACHE_SIZE)
3680 		{
3681 			/*
3682 			 * Allocate new memory if format picture is bigger than static
3683 			 * cache and do not use cache (call parser always)
3684 			 */
3685 			incache = FALSE;
3686 
3687 			format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
3688 
3689 			parse_format(format, fmt_str, DCH_keywords,
3690 						 DCH_suff, DCH_index, DCH_TYPE, NULL);
3691 		}
3692 		else
3693 		{
3694 			/*
3695 			 * Use cache buffers
3696 			 */
3697 			DCHCacheEntry *ent = DCH_cache_fetch(fmt_str);
3698 
3699 			incache = TRUE;
3700 			format = ent->format;
3701 		}
3702 
3703 #ifdef DEBUG_TO_FROM_CHAR
3704 		/* dump_node(format, fmt_len); */
3705 		/* dump_index(DCH_keywords, DCH_index); */
3706 #endif
3707 
3708 		DCH_from_char(format, date_str, &tmfc);
3709 
3710 		pfree(fmt_str);
3711 		if (!incache)
3712 			pfree(format);
3713 	}
3714 
3715 	DEBUG_TMFC(&tmfc);
3716 
3717 	/*
3718 	 * Convert to_date/to_timestamp input fields to standard 'tm'
3719 	 */
3720 	if (tmfc.ssss)
3721 	{
3722 		int			x = tmfc.ssss;
3723 
3724 		tm->tm_hour = x / SECS_PER_HOUR;
3725 		x %= SECS_PER_HOUR;
3726 		tm->tm_min = x / SECS_PER_MINUTE;
3727 		x %= SECS_PER_MINUTE;
3728 		tm->tm_sec = x;
3729 	}
3730 
3731 	if (tmfc.ss)
3732 		tm->tm_sec = tmfc.ss;
3733 	if (tmfc.mi)
3734 		tm->tm_min = tmfc.mi;
3735 	if (tmfc.hh)
3736 		tm->tm_hour = tmfc.hh;
3737 
3738 	if (tmfc.clock == CLOCK_12_HOUR)
3739 	{
3740 		if (tm->tm_hour < 1 || tm->tm_hour > HOURS_PER_DAY / 2)
3741 			ereport(ERROR,
3742 					(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3743 					 errmsg("hour \"%d\" is invalid for the 12-hour clock",
3744 							tm->tm_hour),
3745 					 errhint("Use the 24-hour clock, or give an hour between 1 and 12.")));
3746 
3747 		if (tmfc.pm && tm->tm_hour < HOURS_PER_DAY / 2)
3748 			tm->tm_hour += HOURS_PER_DAY / 2;
3749 		else if (!tmfc.pm && tm->tm_hour == HOURS_PER_DAY / 2)
3750 			tm->tm_hour = 0;
3751 	}
3752 
3753 	if (tmfc.year)
3754 	{
3755 		/*
3756 		 * If CC and YY (or Y) are provided, use YY as 2 low-order digits for
3757 		 * the year in the given century.  Keep in mind that the 21st century
3758 		 * AD runs from 2001-2100, not 2000-2099; 6th century BC runs from
3759 		 * 600BC to 501BC.
3760 		 */
3761 		if (tmfc.cc && tmfc.yysz <= 2)
3762 		{
3763 			if (tmfc.bc)
3764 				tmfc.cc = -tmfc.cc;
3765 			tm->tm_year = tmfc.year % 100;
3766 			if (tm->tm_year)
3767 			{
3768 				if (tmfc.cc >= 0)
3769 					tm->tm_year += (tmfc.cc - 1) * 100;
3770 				else
3771 					tm->tm_year = (tmfc.cc + 1) * 100 - tm->tm_year + 1;
3772 			}
3773 			else
3774 			{
3775 				/* find century year for dates ending in "00" */
3776 				tm->tm_year = tmfc.cc * 100 + ((tmfc.cc >= 0) ? 0 : 1);
3777 			}
3778 		}
3779 		else
3780 		{
3781 			/* If a 4-digit year is provided, we use that and ignore CC. */
3782 			tm->tm_year = tmfc.year;
3783 			if (tmfc.bc)
3784 				tm->tm_year = -tm->tm_year;
3785 			/* correct for our representation of BC years */
3786 			if (tm->tm_year < 0)
3787 				tm->tm_year++;
3788 		}
3789 		fmask |= DTK_M(YEAR);
3790 	}
3791 	else if (tmfc.cc)
3792 	{
3793 		/* use first year of century */
3794 		if (tmfc.bc)
3795 			tmfc.cc = -tmfc.cc;
3796 		if (tmfc.cc >= 0)
3797 			/* +1 because 21st century started in 2001 */
3798 			tm->tm_year = (tmfc.cc - 1) * 100 + 1;
3799 		else
3800 			/* +1 because year == 599 is 600 BC */
3801 			tm->tm_year = tmfc.cc * 100 + 1;
3802 		fmask |= DTK_M(YEAR);
3803 	}
3804 
3805 	if (tmfc.j)
3806 	{
3807 		j2date(tmfc.j, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3808 		fmask |= DTK_DATE_M;
3809 	}
3810 
3811 	if (tmfc.ww)
3812 	{
3813 		if (tmfc.mode == FROM_CHAR_DATE_ISOWEEK)
3814 		{
3815 			/*
3816 			 * If tmfc.d is not set, then the date is left at the beginning of
3817 			 * the ISO week (Monday).
3818 			 */
3819 			if (tmfc.d)
3820 				isoweekdate2date(tmfc.ww, tmfc.d, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3821 			else
3822 				isoweek2date(tmfc.ww, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3823 			fmask |= DTK_DATE_M;
3824 		}
3825 		else
3826 			tmfc.ddd = (tmfc.ww - 1) * 7 + 1;
3827 	}
3828 
3829 	if (tmfc.w)
3830 		tmfc.dd = (tmfc.w - 1) * 7 + 1;
3831 	if (tmfc.dd)
3832 	{
3833 		tm->tm_mday = tmfc.dd;
3834 		fmask |= DTK_M(DAY);
3835 	}
3836 	if (tmfc.mm)
3837 	{
3838 		tm->tm_mon = tmfc.mm;
3839 		fmask |= DTK_M(MONTH);
3840 	}
3841 
3842 	if (tmfc.ddd && (tm->tm_mon <= 1 || tm->tm_mday <= 1))
3843 	{
3844 		/*
3845 		 * The month and day field have not been set, so we use the
3846 		 * day-of-year field to populate them.  Depending on the date mode,
3847 		 * this field may be interpreted as a Gregorian day-of-year, or an ISO
3848 		 * week date day-of-year.
3849 		 */
3850 
3851 		if (!tm->tm_year && !tmfc.bc)
3852 			ereport(ERROR,
3853 					(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
3854 					 errmsg("cannot calculate day of year without year information")));
3855 
3856 		if (tmfc.mode == FROM_CHAR_DATE_ISOWEEK)
3857 		{
3858 			int			j0;		/* zeroth day of the ISO year, in Julian */
3859 
3860 			j0 = isoweek2j(tm->tm_year, 1) - 1;
3861 
3862 			j2date(j0 + tmfc.ddd, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
3863 			fmask |= DTK_DATE_M;
3864 		}
3865 		else
3866 		{
3867 			const int  *y;
3868 			int			i;
3869 
3870 			static const int ysum[2][13] = {
3871 				{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
3872 			{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};
3873 
3874 			y = ysum[isleap(tm->tm_year)];
3875 
3876 			for (i = 1; i <= MONTHS_PER_YEAR; i++)
3877 			{
3878 				if (tmfc.ddd <= y[i])
3879 					break;
3880 			}
3881 			if (tm->tm_mon <= 1)
3882 				tm->tm_mon = i;
3883 
3884 			if (tm->tm_mday <= 1)
3885 				tm->tm_mday = tmfc.ddd - y[i - 1];
3886 
3887 			fmask |= DTK_M(MONTH) | DTK_M(DAY);
3888 		}
3889 	}
3890 
3891 	if (tmfc.ms)
3892 		*fsec += tmfc.ms * 1000;
3893 	if (tmfc.us)
3894 		*fsec += tmfc.us;
3895 
3896 	/* Range-check date fields according to bit mask computed above */
3897 	if (fmask != 0)
3898 	{
3899 		/* We already dealt with AD/BC, so pass isjulian = true */
3900 		int			dterr = ValidateDate(fmask, true, false, false, tm);
3901 
3902 		if (dterr != 0)
3903 		{
3904 			/*
3905 			 * Force the error to be DTERR_FIELD_OVERFLOW even if ValidateDate
3906 			 * said DTERR_MD_FIELD_OVERFLOW, because we don't want to print an
3907 			 * irrelevant hint about datestyle.
3908 			 */
3909 			DateTimeParseError(DTERR_FIELD_OVERFLOW, date_str, "timestamp");
3910 		}
3911 	}
3912 
3913 	/* Range-check time fields too */
3914 	if (tm->tm_hour < 0 || tm->tm_hour >= HOURS_PER_DAY ||
3915 		tm->tm_min < 0 || tm->tm_min >= MINS_PER_HOUR ||
3916 		tm->tm_sec < 0 || tm->tm_sec >= SECS_PER_MINUTE ||
3917 		*fsec < INT64CONST(0) || *fsec >= USECS_PER_SEC)
3918 		DateTimeParseError(DTERR_FIELD_OVERFLOW, date_str, "timestamp");
3919 
3920 	DEBUG_TM(tm);
3921 
3922 	pfree(date_str);
3923 }
3924 
3925 
3926 /**********************************************************************
3927  *	the NUMBER version part
3928  *********************************************************************/
3929 
3930 
3931 static char *
fill_str(char * str,int c,int max)3932 fill_str(char *str, int c, int max)
3933 {
3934 	memset(str, c, max);
3935 	*(str + max) = '\0';
3936 	return str;
3937 }
3938 
3939 #define zeroize_NUM(_n) \
3940 do { \
3941 	(_n)->flag		= 0;	\
3942 	(_n)->lsign		= 0;	\
3943 	(_n)->pre		= 0;	\
3944 	(_n)->post		= 0;	\
3945 	(_n)->pre_lsign_num = 0;	\
3946 	(_n)->need_locale	= 0;	\
3947 	(_n)->multi		= 0;	\
3948 	(_n)->zero_start	= 0;	\
3949 	(_n)->zero_end		= 0;	\
3950 } while(0)
3951 
3952 /* select a NUMCacheEntry to hold the given format picture */
3953 static NUMCacheEntry *
NUM_cache_getnew(const char * str)3954 NUM_cache_getnew(const char *str)
3955 {
3956 	NUMCacheEntry *ent;
3957 
3958 	/* counter overflow check - paranoia? */
3959 	if (NUMCounter >= (INT_MAX - NUM_CACHE_ENTRIES))
3960 	{
3961 		NUMCounter = 0;
3962 
3963 		for (ent = NUMCache; ent < (NUMCache + NUM_CACHE_ENTRIES); ent++)
3964 			ent->age = (++NUMCounter);
3965 	}
3966 
3967 	/*
3968 	 * If cache is full, remove oldest entry (or recycle first not-valid one)
3969 	 */
3970 	if (n_NUMCache >= NUM_CACHE_ENTRIES)
3971 	{
3972 		NUMCacheEntry *old = NUMCache + 0;
3973 
3974 #ifdef DEBUG_TO_FROM_CHAR
3975 		elog(DEBUG_elog_output, "Cache is full (%d)", n_NUMCache);
3976 #endif
3977 		if (old->valid)
3978 		{
3979 			for (ent = NUMCache + 1; ent < (NUMCache + NUM_CACHE_ENTRIES); ent++)
3980 			{
3981 				if (!ent->valid)
3982 				{
3983 					old = ent;
3984 					break;
3985 				}
3986 				if (ent->age < old->age)
3987 					old = ent;
3988 			}
3989 		}
3990 #ifdef DEBUG_TO_FROM_CHAR
3991 		elog(DEBUG_elog_output, "OLD: \"%s\" AGE: %d", old->str, old->age);
3992 #endif
3993 		old->valid = false;
3994 		StrNCpy(old->str, str, NUM_CACHE_SIZE + 1);
3995 		old->age = (++NUMCounter);
3996 		/* caller is expected to fill format and Num, then set valid */
3997 		return old;
3998 	}
3999 	else
4000 	{
4001 #ifdef DEBUG_TO_FROM_CHAR
4002 		elog(DEBUG_elog_output, "NEW (%d)", n_NUMCache);
4003 #endif
4004 		ent = NUMCache + n_NUMCache;
4005 		ent->valid = false;
4006 		StrNCpy(ent->str, str, NUM_CACHE_SIZE + 1);
4007 		ent->age = (++NUMCounter);
4008 		/* caller is expected to fill format and Num, then set valid */
4009 		++n_NUMCache;
4010 		return ent;
4011 	}
4012 }
4013 
4014 /* look for an existing NUMCacheEntry matching the given format picture */
4015 static NUMCacheEntry *
NUM_cache_search(const char * str)4016 NUM_cache_search(const char *str)
4017 {
4018 	int			i;
4019 	NUMCacheEntry *ent;
4020 
4021 	/* counter overflow check - paranoia? */
4022 	if (NUMCounter >= (INT_MAX - NUM_CACHE_ENTRIES))
4023 	{
4024 		NUMCounter = 0;
4025 
4026 		for (ent = NUMCache; ent < (NUMCache + NUM_CACHE_ENTRIES); ent++)
4027 			ent->age = (++NUMCounter);
4028 	}
4029 
4030 	for (i = 0, ent = NUMCache; i < n_NUMCache; i++, ent++)
4031 	{
4032 		if (ent->valid && strcmp(ent->str, str) == 0)
4033 		{
4034 			ent->age = (++NUMCounter);
4035 			return ent;
4036 		}
4037 	}
4038 
4039 	return NULL;
4040 }
4041 
4042 /* Find or create a NUMCacheEntry for the given format picture */
4043 static NUMCacheEntry *
NUM_cache_fetch(const char * str)4044 NUM_cache_fetch(const char *str)
4045 {
4046 	NUMCacheEntry *ent;
4047 
4048 	if ((ent = NUM_cache_search(str)) == NULL)
4049 	{
4050 		/*
4051 		 * Not in the cache, must run parser and save a new format-picture to
4052 		 * the cache.  Do not mark the cache entry valid until parsing
4053 		 * succeeds.
4054 		 */
4055 		ent = NUM_cache_getnew(str);
4056 
4057 		zeroize_NUM(&ent->Num);
4058 
4059 		parse_format(ent->format, str, NUM_keywords,
4060 					 NULL, NUM_index, NUM_TYPE, &ent->Num);
4061 
4062 		ent->valid = true;
4063 	}
4064 	return ent;
4065 }
4066 
4067 /* ----------
4068  * Cache routine for NUM to_char version
4069  * ----------
4070  */
4071 static FormatNode *
NUM_cache(int len,NUMDesc * Num,text * pars_str,bool * shouldFree)4072 NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree)
4073 {
4074 	FormatNode *format = NULL;
4075 	char	   *str;
4076 
4077 	str = text_to_cstring(pars_str);
4078 
4079 	if (len > NUM_CACHE_SIZE)
4080 	{
4081 		/*
4082 		 * Allocate new memory if format picture is bigger than static cache
4083 		 * and do not use cache (call parser always)
4084 		 */
4085 		format = (FormatNode *) palloc((len + 1) * sizeof(FormatNode));
4086 
4087 		*shouldFree = true;
4088 
4089 		zeroize_NUM(Num);
4090 
4091 		parse_format(format, str, NUM_keywords,
4092 					 NULL, NUM_index, NUM_TYPE, Num);
4093 	}
4094 	else
4095 	{
4096 		/*
4097 		 * Use cache buffers
4098 		 */
4099 		NUMCacheEntry *ent = NUM_cache_fetch(str);
4100 
4101 		*shouldFree = false;
4102 
4103 		format = ent->format;
4104 
4105 		/*
4106 		 * Copy cache to used struct
4107 		 */
4108 		Num->flag = ent->Num.flag;
4109 		Num->lsign = ent->Num.lsign;
4110 		Num->pre = ent->Num.pre;
4111 		Num->post = ent->Num.post;
4112 		Num->pre_lsign_num = ent->Num.pre_lsign_num;
4113 		Num->need_locale = ent->Num.need_locale;
4114 		Num->multi = ent->Num.multi;
4115 		Num->zero_start = ent->Num.zero_start;
4116 		Num->zero_end = ent->Num.zero_end;
4117 	}
4118 
4119 #ifdef DEBUG_TO_FROM_CHAR
4120 	/* dump_node(format, len); */
4121 	dump_index(NUM_keywords, NUM_index);
4122 #endif
4123 
4124 	pfree(str);
4125 	return format;
4126 }
4127 
4128 
4129 static char *
int_to_roman(int number)4130 int_to_roman(int number)
4131 {
4132 	int			len = 0,
4133 				num = 0;
4134 	char	   *p = NULL,
4135 			   *result,
4136 				numstr[5];
4137 
4138 	result = (char *) palloc(16);
4139 	*result = '\0';
4140 
4141 	if (number > 3999 || number < 1)
4142 	{
4143 		fill_str(result, '#', 15);
4144 		return result;
4145 	}
4146 	len = snprintf(numstr, sizeof(numstr), "%d", number);
4147 
4148 	for (p = numstr; *p != '\0'; p++, --len)
4149 	{
4150 		num = *p - 49;			/* 48 ascii + 1 */
4151 		if (num < 0)
4152 			continue;
4153 
4154 		if (len > 3)
4155 		{
4156 			while (num-- != -1)
4157 				strcat(result, "M");
4158 		}
4159 		else
4160 		{
4161 			if (len == 3)
4162 				strcat(result, rm100[num]);
4163 			else if (len == 2)
4164 				strcat(result, rm10[num]);
4165 			else if (len == 1)
4166 				strcat(result, rm1[num]);
4167 		}
4168 	}
4169 	return result;
4170 }
4171 
4172 
4173 
4174 /* ----------
4175  * Locale
4176  * ----------
4177  */
4178 static void
NUM_prepare_locale(NUMProc * Np)4179 NUM_prepare_locale(NUMProc *Np)
4180 {
4181 	if (Np->Num->need_locale)
4182 	{
4183 		struct lconv *lconv;
4184 
4185 		/*
4186 		 * Get locales
4187 		 */
4188 		lconv = PGLC_localeconv();
4189 
4190 		/*
4191 		 * Positive / Negative number sign
4192 		 */
4193 		if (lconv->negative_sign && *lconv->negative_sign)
4194 			Np->L_negative_sign = lconv->negative_sign;
4195 		else
4196 			Np->L_negative_sign = "-";
4197 
4198 		if (lconv->positive_sign && *lconv->positive_sign)
4199 			Np->L_positive_sign = lconv->positive_sign;
4200 		else
4201 			Np->L_positive_sign = "+";
4202 
4203 		/*
4204 		 * Number decimal point
4205 		 */
4206 		if (lconv->decimal_point && *lconv->decimal_point)
4207 			Np->decimal = lconv->decimal_point;
4208 
4209 		else
4210 			Np->decimal = ".";
4211 
4212 		if (!IS_LDECIMAL(Np->Num))
4213 			Np->decimal = ".";
4214 
4215 		/*
4216 		 * Number thousands separator
4217 		 *
4218 		 * Some locales (e.g. broken glibc pt_BR), have a comma for decimal,
4219 		 * but "" for thousands_sep, so we set the thousands_sep too.
4220 		 * http://archives.postgresql.org/pgsql-hackers/2007-11/msg00772.php
4221 		 */
4222 		if (lconv->thousands_sep && *lconv->thousands_sep)
4223 			Np->L_thousands_sep = lconv->thousands_sep;
4224 		/* Make sure thousands separator doesn't match decimal point symbol. */
4225 		else if (strcmp(Np->decimal, ",") !=0)
4226 			Np->L_thousands_sep = ",";
4227 		else
4228 			Np->L_thousands_sep = ".";
4229 
4230 		/*
4231 		 * Currency symbol
4232 		 */
4233 		if (lconv->currency_symbol && *lconv->currency_symbol)
4234 			Np->L_currency_symbol = lconv->currency_symbol;
4235 		else
4236 			Np->L_currency_symbol = " ";
4237 	}
4238 	else
4239 	{
4240 		/*
4241 		 * Default values
4242 		 */
4243 		Np->L_negative_sign = "-";
4244 		Np->L_positive_sign = "+";
4245 		Np->decimal = ".";
4246 
4247 		Np->L_thousands_sep = ",";
4248 		Np->L_currency_symbol = " ";
4249 	}
4250 }
4251 
4252 /* ----------
4253  * Return pointer of last relevant number after decimal point
4254  *	12.0500 --> last relevant is '5'
4255  *	12.0000 --> last relevant is '.'
4256  * If there is no decimal point, return NULL (which will result in same
4257  * behavior as if FM hadn't been specified).
4258  * ----------
4259  */
4260 static char *
get_last_relevant_decnum(char * num)4261 get_last_relevant_decnum(char *num)
4262 {
4263 	char	   *result,
4264 			   *p = strchr(num, '.');
4265 
4266 #ifdef DEBUG_TO_FROM_CHAR
4267 	elog(DEBUG_elog_output, "get_last_relevant_decnum()");
4268 #endif
4269 
4270 	if (!p)
4271 		return NULL;
4272 
4273 	result = p;
4274 
4275 	while (*(++p))
4276 	{
4277 		if (*p != '0')
4278 			result = p;
4279 	}
4280 
4281 	return result;
4282 }
4283 
4284 /* ----------
4285  * Number extraction for TO_NUMBER()
4286  * ----------
4287  */
4288 static void
NUM_numpart_from_char(NUMProc * Np,int id,int input_len)4289 NUM_numpart_from_char(NUMProc *Np, int id, int input_len)
4290 {
4291 	bool		isread = FALSE;
4292 
4293 #ifdef DEBUG_TO_FROM_CHAR
4294 	elog(DEBUG_elog_output, " --- scan start --- id=%s",
4295 		 (id == NUM_0 || id == NUM_9) ? "NUM_0/9" : id == NUM_DEC ? "NUM_DEC" : "???");
4296 #endif
4297 
4298 #define OVERLOAD_TEST	(Np->inout_p >= Np->inout + input_len)
4299 #define AMOUNT_TEST(_s) (input_len-(Np->inout_p-Np->inout) >= _s)
4300 
4301 	if (OVERLOAD_TEST)
4302 		return;
4303 
4304 	if (*Np->inout_p == ' ')
4305 		Np->inout_p++;
4306 
4307 	if (OVERLOAD_TEST)
4308 		return;
4309 
4310 	/*
4311 	 * read sign before number
4312 	 */
4313 	if (*Np->number == ' ' && (id == NUM_0 || id == NUM_9) &&
4314 		(Np->read_pre + Np->read_post) == 0)
4315 	{
4316 #ifdef DEBUG_TO_FROM_CHAR
4317 		elog(DEBUG_elog_output, "Try read sign (%c), locale positive: %s, negative: %s",
4318 			 *Np->inout_p, Np->L_positive_sign, Np->L_negative_sign);
4319 #endif
4320 
4321 		/*
4322 		 * locale sign
4323 		 */
4324 		if (IS_LSIGN(Np->Num) && Np->Num->lsign == NUM_LSIGN_PRE)
4325 		{
4326 			int			x = 0;
4327 
4328 #ifdef DEBUG_TO_FROM_CHAR
4329 			elog(DEBUG_elog_output, "Try read locale pre-sign (%c)", *Np->inout_p);
4330 #endif
4331 			if ((x = strlen(Np->L_negative_sign)) &&
4332 				AMOUNT_TEST(x) &&
4333 				strncmp(Np->inout_p, Np->L_negative_sign, x) == 0)
4334 			{
4335 				Np->inout_p += x;
4336 				*Np->number = '-';
4337 			}
4338 			else if ((x = strlen(Np->L_positive_sign)) &&
4339 					 AMOUNT_TEST(x) &&
4340 					 strncmp(Np->inout_p, Np->L_positive_sign, x) == 0)
4341 			{
4342 				Np->inout_p += x;
4343 				*Np->number = '+';
4344 			}
4345 		}
4346 		else
4347 		{
4348 #ifdef DEBUG_TO_FROM_CHAR
4349 			elog(DEBUG_elog_output, "Try read simple sign (%c)", *Np->inout_p);
4350 #endif
4351 
4352 			/*
4353 			 * simple + - < >
4354 			 */
4355 			if (*Np->inout_p == '-' || (IS_BRACKET(Np->Num) &&
4356 										*Np->inout_p == '<'))
4357 			{
4358 				*Np->number = '-';	/* set - */
4359 				Np->inout_p++;
4360 			}
4361 			else if (*Np->inout_p == '+')
4362 			{
4363 				*Np->number = '+';	/* set + */
4364 				Np->inout_p++;
4365 			}
4366 		}
4367 	}
4368 
4369 	if (OVERLOAD_TEST)
4370 		return;
4371 
4372 #ifdef DEBUG_TO_FROM_CHAR
4373 	elog(DEBUG_elog_output, "Scan for numbers (%c), current number: '%s'", *Np->inout_p, Np->number);
4374 #endif
4375 
4376 	/*
4377 	 * read digit or decimal point
4378 	 */
4379 	if (isdigit((unsigned char) *Np->inout_p))
4380 	{
4381 		if (Np->read_dec && Np->read_post == Np->Num->post)
4382 			return;
4383 
4384 		*Np->number_p = *Np->inout_p;
4385 		Np->number_p++;
4386 
4387 		if (Np->read_dec)
4388 			Np->read_post++;
4389 		else
4390 			Np->read_pre++;
4391 
4392 		isread = TRUE;
4393 
4394 #ifdef DEBUG_TO_FROM_CHAR
4395 		elog(DEBUG_elog_output, "Read digit (%c)", *Np->inout_p);
4396 #endif
4397 	}
4398 	else if (IS_DECIMAL(Np->Num) && Np->read_dec == FALSE)
4399 	{
4400 		/*
4401 		 * We need not test IS_LDECIMAL(Np->Num) explicitly here, because
4402 		 * Np->decimal is always just "." if we don't have a D format token.
4403 		 * So we just unconditionally match to Np->decimal.
4404 		 */
4405 		int			x = strlen(Np->decimal);
4406 
4407 #ifdef DEBUG_TO_FROM_CHAR
4408 		elog(DEBUG_elog_output, "Try read decimal point (%c)",
4409 			 *Np->inout_p);
4410 #endif
4411 		if (x && AMOUNT_TEST(x) && strncmp(Np->inout_p, Np->decimal, x) == 0)
4412 		{
4413 			Np->inout_p += x - 1;
4414 			*Np->number_p = '.';
4415 			Np->number_p++;
4416 			Np->read_dec = TRUE;
4417 			isread = TRUE;
4418 		}
4419 	}
4420 
4421 	if (OVERLOAD_TEST)
4422 		return;
4423 
4424 	/*
4425 	 * Read sign behind "last" number
4426 	 *
4427 	 * We need sign detection because determine exact position of post-sign is
4428 	 * difficult:
4429 	 *
4430 	 * FM9999.9999999S	   -> 123.001- 9.9S			   -> .5- FM9.999999MI ->
4431 	 * 5.01-
4432 	 */
4433 	if (*Np->number == ' ' && Np->read_pre + Np->read_post > 0)
4434 	{
4435 		/*
4436 		 * locale sign (NUM_S) is always anchored behind a last number, if: -
4437 		 * locale sign expected - last read char was NUM_0/9 or NUM_DEC - and
4438 		 * next char is not digit
4439 		 */
4440 		if (IS_LSIGN(Np->Num) && isread &&
4441 			(Np->inout_p + 1) < Np->inout + input_len &&
4442 			!isdigit((unsigned char) *(Np->inout_p + 1)))
4443 		{
4444 			int			x;
4445 			char	   *tmp = Np->inout_p++;
4446 
4447 #ifdef DEBUG_TO_FROM_CHAR
4448 			elog(DEBUG_elog_output, "Try read locale post-sign (%c)", *Np->inout_p);
4449 #endif
4450 			if ((x = strlen(Np->L_negative_sign)) &&
4451 				AMOUNT_TEST(x) &&
4452 				strncmp(Np->inout_p, Np->L_negative_sign, x) == 0)
4453 			{
4454 				Np->inout_p += x - 1;	/* -1 .. NUM_processor() do inout_p++ */
4455 				*Np->number = '-';
4456 			}
4457 			else if ((x = strlen(Np->L_positive_sign)) &&
4458 					 AMOUNT_TEST(x) &&
4459 					 strncmp(Np->inout_p, Np->L_positive_sign, x) == 0)
4460 			{
4461 				Np->inout_p += x - 1;	/* -1 .. NUM_processor() do inout_p++ */
4462 				*Np->number = '+';
4463 			}
4464 			if (*Np->number == ' ')
4465 				/* no sign read */
4466 				Np->inout_p = tmp;
4467 		}
4468 
4469 		/*
4470 		 * try read non-locale sign, it's happen only if format is not exact
4471 		 * and we cannot determine sign position of MI/PL/SG, an example:
4472 		 *
4473 		 * FM9.999999MI			   -> 5.01-
4474 		 *
4475 		 * if (.... && IS_LSIGN(Np->Num)==FALSE) prevents read wrong formats
4476 		 * like to_number('1 -', '9S') where sign is not anchored to last
4477 		 * number.
4478 		 */
4479 		else if (isread == FALSE && IS_LSIGN(Np->Num) == FALSE &&
4480 				 (IS_PLUS(Np->Num) || IS_MINUS(Np->Num)))
4481 		{
4482 #ifdef DEBUG_TO_FROM_CHAR
4483 			elog(DEBUG_elog_output, "Try read simple post-sign (%c)", *Np->inout_p);
4484 #endif
4485 
4486 			/*
4487 			 * simple + -
4488 			 */
4489 			if (*Np->inout_p == '-' || *Np->inout_p == '+')
4490 				/* NUM_processor() do inout_p++ */
4491 				*Np->number = *Np->inout_p;
4492 		}
4493 	}
4494 }
4495 
4496 #define IS_PREDEC_SPACE(_n) \
4497 		(IS_ZERO((_n)->Num)==FALSE && \
4498 		 (_n)->number == (_n)->number_p && \
4499 		 *(_n)->number == '0' && \
4500 				 (_n)->Num->post != 0)
4501 
4502 /* ----------
4503  * Add digit or sign to number-string
4504  * ----------
4505  */
4506 static void
NUM_numpart_to_char(NUMProc * Np,int id)4507 NUM_numpart_to_char(NUMProc *Np, int id)
4508 {
4509 	int			end;
4510 
4511 	if (IS_ROMAN(Np->Num))
4512 		return;
4513 
4514 	/* Note: in this elog() output not set '\0' in 'inout' */
4515 
4516 #ifdef DEBUG_TO_FROM_CHAR
4517 
4518 	/*
4519 	 * Np->num_curr is number of current item in format-picture, it is not
4520 	 * current position in inout!
4521 	 */
4522 	elog(DEBUG_elog_output,
4523 		 "SIGN_WROTE: %d, CURRENT: %d, NUMBER_P: \"%s\", INOUT: \"%s\"",
4524 		 Np->sign_wrote,
4525 		 Np->num_curr,
4526 		 Np->number_p,
4527 		 Np->inout);
4528 #endif
4529 	Np->num_in = FALSE;
4530 
4531 	/*
4532 	 * Write sign if real number will write to output Note: IS_PREDEC_SPACE()
4533 	 * handle "9.9" --> " .1"
4534 	 */
4535 	if (Np->sign_wrote == FALSE &&
4536 		(Np->num_curr >= Np->out_pre_spaces || (IS_ZERO(Np->Num) && Np->Num->zero_start == Np->num_curr)) &&
4537 		(IS_PREDEC_SPACE(Np) == FALSE || (Np->last_relevant && *Np->last_relevant == '.')))
4538 	{
4539 		if (IS_LSIGN(Np->Num))
4540 		{
4541 			if (Np->Num->lsign == NUM_LSIGN_PRE)
4542 			{
4543 				if (Np->sign == '-')
4544 					strcpy(Np->inout_p, Np->L_negative_sign);
4545 				else
4546 					strcpy(Np->inout_p, Np->L_positive_sign);
4547 				Np->inout_p += strlen(Np->inout_p);
4548 				Np->sign_wrote = TRUE;
4549 			}
4550 		}
4551 		else if (IS_BRACKET(Np->Num))
4552 		{
4553 			*Np->inout_p = Np->sign == '+' ? ' ' : '<';
4554 			++Np->inout_p;
4555 			Np->sign_wrote = TRUE;
4556 		}
4557 		else if (Np->sign == '+')
4558 		{
4559 			if (!IS_FILLMODE(Np->Num))
4560 			{
4561 				*Np->inout_p = ' '; /* Write + */
4562 				++Np->inout_p;
4563 			}
4564 			Np->sign_wrote = TRUE;
4565 		}
4566 		else if (Np->sign == '-')
4567 		{						/* Write - */
4568 			*Np->inout_p = '-';
4569 			++Np->inout_p;
4570 			Np->sign_wrote = TRUE;
4571 		}
4572 	}
4573 
4574 
4575 	/*
4576 	 * digits / FM / Zero / Dec. point
4577 	 */
4578 	if (id == NUM_9 || id == NUM_0 || id == NUM_D || id == NUM_DEC)
4579 	{
4580 		if (Np->num_curr < Np->out_pre_spaces &&
4581 			(Np->Num->zero_start > Np->num_curr || !IS_ZERO(Np->Num)))
4582 		{
4583 			/*
4584 			 * Write blank space
4585 			 */
4586 			if (!IS_FILLMODE(Np->Num))
4587 			{
4588 				*Np->inout_p = ' '; /* Write ' ' */
4589 				++Np->inout_p;
4590 			}
4591 		}
4592 		else if (IS_ZERO(Np->Num) &&
4593 				 Np->num_curr < Np->out_pre_spaces &&
4594 				 Np->Num->zero_start <= Np->num_curr)
4595 		{
4596 			/*
4597 			 * Write ZERO
4598 			 */
4599 			*Np->inout_p = '0'; /* Write '0' */
4600 			++Np->inout_p;
4601 			Np->num_in = TRUE;
4602 		}
4603 		else
4604 		{
4605 			/*
4606 			 * Write Decimal point
4607 			 */
4608 			if (*Np->number_p == '.')
4609 			{
4610 				if (!Np->last_relevant || *Np->last_relevant != '.')
4611 				{
4612 					strcpy(Np->inout_p, Np->decimal);	/* Write DEC/D */
4613 					Np->inout_p += strlen(Np->inout_p);
4614 				}
4615 
4616 				/*
4617 				 * Ora 'n' -- FM9.9 --> 'n.'
4618 				 */
4619 				else if (IS_FILLMODE(Np->Num) &&
4620 						 Np->last_relevant && *Np->last_relevant == '.')
4621 				{
4622 					strcpy(Np->inout_p, Np->decimal);	/* Write DEC/D */
4623 					Np->inout_p += strlen(Np->inout_p);
4624 				}
4625 			}
4626 			else
4627 			{
4628 				/*
4629 				 * Write Digits
4630 				 */
4631 				if (Np->last_relevant && Np->number_p > Np->last_relevant &&
4632 					id != NUM_0)
4633 					;
4634 
4635 				/*
4636 				 * '0.1' -- 9.9 --> '  .1'
4637 				 */
4638 				else if (IS_PREDEC_SPACE(Np))
4639 				{
4640 					if (!IS_FILLMODE(Np->Num))
4641 					{
4642 						*Np->inout_p = ' ';
4643 						++Np->inout_p;
4644 					}
4645 
4646 					/*
4647 					 * '0' -- FM9.9 --> '0.'
4648 					 */
4649 					else if (Np->last_relevant && *Np->last_relevant == '.')
4650 					{
4651 						*Np->inout_p = '0';
4652 						++Np->inout_p;
4653 					}
4654 				}
4655 				else
4656 				{
4657 					*Np->inout_p = *Np->number_p;	/* Write DIGIT */
4658 					++Np->inout_p;
4659 					Np->num_in = TRUE;
4660 				}
4661 			}
4662 			/* do no exceed string length */
4663 			if (*Np->number_p)
4664 				++Np->number_p;
4665 		}
4666 
4667 		end = Np->num_count + (Np->out_pre_spaces ? 1 : 0) + (IS_DECIMAL(Np->Num) ? 1 : 0);
4668 
4669 		if (Np->last_relevant && Np->last_relevant == Np->number_p)
4670 			end = Np->num_curr;
4671 
4672 		if (Np->num_curr + 1 == end)
4673 		{
4674 			if (Np->sign_wrote == TRUE && IS_BRACKET(Np->Num))
4675 			{
4676 				*Np->inout_p = Np->sign == '+' ? ' ' : '>';
4677 				++Np->inout_p;
4678 			}
4679 			else if (IS_LSIGN(Np->Num) && Np->Num->lsign == NUM_LSIGN_POST)
4680 			{
4681 				if (Np->sign == '-')
4682 					strcpy(Np->inout_p, Np->L_negative_sign);
4683 				else
4684 					strcpy(Np->inout_p, Np->L_positive_sign);
4685 				Np->inout_p += strlen(Np->inout_p);
4686 			}
4687 		}
4688 	}
4689 
4690 	++Np->num_curr;
4691 }
4692 
4693 static char *
NUM_processor(FormatNode * node,NUMDesc * Num,char * inout,char * number,int from_char_input_len,int to_char_out_pre_spaces,int sign,bool is_to_char,Oid collid)4694 NUM_processor(FormatNode *node, NUMDesc *Num, char *inout,
4695 			  char *number, int from_char_input_len, int to_char_out_pre_spaces,
4696 			  int sign, bool is_to_char, Oid collid)
4697 {
4698 	FormatNode *n;
4699 	NUMProc		_Np,
4700 			   *Np = &_Np;
4701 
4702 	MemSet(Np, 0, sizeof(NUMProc));
4703 
4704 	Np->Num = Num;
4705 	Np->is_to_char = is_to_char;
4706 	Np->number = number;
4707 	Np->inout = inout;
4708 	Np->last_relevant = NULL;
4709 	Np->read_post = 0;
4710 	Np->read_pre = 0;
4711 	Np->read_dec = FALSE;
4712 
4713 	if (Np->Num->zero_start)
4714 		--Np->Num->zero_start;
4715 
4716 	if (IS_EEEE(Np->Num))
4717 	{
4718 		if (!Np->is_to_char)
4719 			ereport(ERROR,
4720 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4721 					 errmsg("\"EEEE\" not supported for input")));
4722 		return strcpy(inout, number);
4723 	}
4724 
4725 	/*
4726 	 * Roman correction
4727 	 */
4728 	if (IS_ROMAN(Np->Num))
4729 	{
4730 		if (!Np->is_to_char)
4731 			ereport(ERROR,
4732 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4733 					 errmsg("\"RN\" not supported for input")));
4734 
4735 		Np->Num->lsign = Np->Num->pre_lsign_num = Np->Num->post =
4736 			Np->Num->pre = Np->out_pre_spaces = Np->sign = 0;
4737 
4738 		if (IS_FILLMODE(Np->Num))
4739 		{
4740 			Np->Num->flag = 0;
4741 			Np->Num->flag |= NUM_F_FILLMODE;
4742 		}
4743 		else
4744 			Np->Num->flag = 0;
4745 		Np->Num->flag |= NUM_F_ROMAN;
4746 	}
4747 
4748 	/*
4749 	 * Sign
4750 	 */
4751 	if (is_to_char)
4752 	{
4753 		Np->sign = sign;
4754 
4755 		/* MI/PL/SG - write sign itself and not in number */
4756 		if (IS_PLUS(Np->Num) || IS_MINUS(Np->Num))
4757 		{
4758 			if (IS_PLUS(Np->Num) && IS_MINUS(Np->Num) == FALSE)
4759 				Np->sign_wrote = FALSE; /* need sign */
4760 			else
4761 				Np->sign_wrote = TRUE;	/* needn't sign */
4762 		}
4763 		else
4764 		{
4765 			if (Np->sign != '-')
4766 			{
4767 				if (IS_BRACKET(Np->Num) && IS_FILLMODE(Np->Num))
4768 					Np->Num->flag &= ~NUM_F_BRACKET;
4769 				if (IS_MINUS(Np->Num))
4770 					Np->Num->flag &= ~NUM_F_MINUS;
4771 			}
4772 			else if (Np->sign != '+' && IS_PLUS(Np->Num))
4773 				Np->Num->flag &= ~NUM_F_PLUS;
4774 
4775 			if (Np->sign == '+' && IS_FILLMODE(Np->Num) && IS_LSIGN(Np->Num) == FALSE)
4776 				Np->sign_wrote = TRUE;	/* needn't sign */
4777 			else
4778 				Np->sign_wrote = FALSE; /* need sign */
4779 
4780 			if (Np->Num->lsign == NUM_LSIGN_PRE && Np->Num->pre == Np->Num->pre_lsign_num)
4781 				Np->Num->lsign = NUM_LSIGN_POST;
4782 		}
4783 	}
4784 	else
4785 		Np->sign = FALSE;
4786 
4787 	/*
4788 	 * Count
4789 	 */
4790 	Np->num_count = Np->Num->post + Np->Num->pre - 1;
4791 
4792 	if (is_to_char)
4793 	{
4794 		Np->out_pre_spaces = to_char_out_pre_spaces;
4795 
4796 		if (IS_FILLMODE(Np->Num) && IS_DECIMAL(Np->Num))
4797 		{
4798 			Np->last_relevant = get_last_relevant_decnum(Np->number);
4799 
4800 			/*
4801 			 * If any '0' specifiers are present, make sure we don't strip
4802 			 * those digits.
4803 			 */
4804 			if (Np->last_relevant && Np->Num->zero_end > Np->out_pre_spaces)
4805 			{
4806 				char	   *last_zero;
4807 
4808 				last_zero = Np->number + (Np->Num->zero_end - Np->out_pre_spaces);
4809 				if (Np->last_relevant < last_zero)
4810 					Np->last_relevant = last_zero;
4811 			}
4812 		}
4813 
4814 		if (Np->sign_wrote == FALSE && Np->out_pre_spaces == 0)
4815 			++Np->num_count;
4816 	}
4817 	else
4818 	{
4819 		Np->out_pre_spaces = 0;
4820 		*Np->number = ' ';		/* sign space */
4821 		*(Np->number + 1) = '\0';
4822 	}
4823 
4824 	Np->num_in = 0;
4825 	Np->num_curr = 0;
4826 
4827 #ifdef DEBUG_TO_FROM_CHAR
4828 	elog(DEBUG_elog_output,
4829 		 "\n\tSIGN: '%c'\n\tNUM: '%s'\n\tPRE: %d\n\tPOST: %d\n\tNUM_COUNT: %d\n\tNUM_PRE: %d\n\tSIGN_WROTE: %s\n\tZERO: %s\n\tZERO_START: %d\n\tZERO_END: %d\n\tLAST_RELEVANT: %s\n\tBRACKET: %s\n\tPLUS: %s\n\tMINUS: %s\n\tFILLMODE: %s\n\tROMAN: %s\n\tEEEE: %s",
4830 		 Np->sign,
4831 		 Np->number,
4832 		 Np->Num->pre,
4833 		 Np->Num->post,
4834 		 Np->num_count,
4835 		 Np->out_pre_spaces,
4836 		 Np->sign_wrote ? "Yes" : "No",
4837 		 IS_ZERO(Np->Num) ? "Yes" : "No",
4838 		 Np->Num->zero_start,
4839 		 Np->Num->zero_end,
4840 		 Np->last_relevant ? Np->last_relevant : "<not set>",
4841 		 IS_BRACKET(Np->Num) ? "Yes" : "No",
4842 		 IS_PLUS(Np->Num) ? "Yes" : "No",
4843 		 IS_MINUS(Np->Num) ? "Yes" : "No",
4844 		 IS_FILLMODE(Np->Num) ? "Yes" : "No",
4845 		 IS_ROMAN(Np->Num) ? "Yes" : "No",
4846 		 IS_EEEE(Np->Num) ? "Yes" : "No"
4847 		);
4848 #endif
4849 
4850 	/*
4851 	 * Locale
4852 	 */
4853 	NUM_prepare_locale(Np);
4854 
4855 	/*
4856 	 * Processor direct cycle
4857 	 */
4858 	if (Np->is_to_char)
4859 		Np->number_p = Np->number;
4860 	else
4861 		Np->number_p = Np->number + 1;	/* first char is space for sign */
4862 
4863 	for (n = node, Np->inout_p = Np->inout; n->type != NODE_TYPE_END; n++)
4864 	{
4865 		if (!Np->is_to_char)
4866 		{
4867 			/*
4868 			 * Check non-string inout end
4869 			 */
4870 			if (Np->inout_p >= Np->inout + from_char_input_len)
4871 				break;
4872 		}
4873 
4874 		/*
4875 		 * Format pictures actions
4876 		 */
4877 		if (n->type == NODE_TYPE_ACTION)
4878 		{
4879 			/*
4880 			 * Create/reading digit/zero/blank/sing
4881 			 *
4882 			 * 'NUM_S' note: The locale sign is anchored to number and we
4883 			 * read/write it when we work with first or last number
4884 			 * (NUM_0/NUM_9). This is reason why NUM_S missing in follow
4885 			 * switch().
4886 			 */
4887 			switch (n->key->id)
4888 			{
4889 				case NUM_9:
4890 				case NUM_0:
4891 				case NUM_DEC:
4892 				case NUM_D:
4893 					if (Np->is_to_char)
4894 					{
4895 						NUM_numpart_to_char(Np, n->key->id);
4896 						continue;	/* for() */
4897 					}
4898 					else
4899 					{
4900 						NUM_numpart_from_char(Np, n->key->id, from_char_input_len);
4901 						break;	/* switch() case: */
4902 					}
4903 
4904 				case NUM_COMMA:
4905 					if (Np->is_to_char)
4906 					{
4907 						if (!Np->num_in)
4908 						{
4909 							if (IS_FILLMODE(Np->Num))
4910 								continue;
4911 							else
4912 								*Np->inout_p = ' ';
4913 						}
4914 						else
4915 							*Np->inout_p = ',';
4916 					}
4917 					else
4918 					{
4919 						if (!Np->num_in)
4920 						{
4921 							if (IS_FILLMODE(Np->Num))
4922 								continue;
4923 						}
4924 					}
4925 					break;
4926 
4927 				case NUM_G:
4928 					if (Np->is_to_char)
4929 					{
4930 						if (!Np->num_in)
4931 						{
4932 							if (IS_FILLMODE(Np->Num))
4933 								continue;
4934 							else
4935 							{
4936 								int			x = strlen(Np->L_thousands_sep);
4937 
4938 								memset(Np->inout_p, ' ', x);
4939 								Np->inout_p += x - 1;
4940 							}
4941 						}
4942 						else
4943 						{
4944 							strcpy(Np->inout_p, Np->L_thousands_sep);
4945 							Np->inout_p += strlen(Np->inout_p) - 1;
4946 						}
4947 					}
4948 					else
4949 					{
4950 						if (!Np->num_in)
4951 						{
4952 							if (IS_FILLMODE(Np->Num))
4953 								continue;
4954 						}
4955 						Np->inout_p += strlen(Np->L_thousands_sep) - 1;
4956 					}
4957 					break;
4958 
4959 				case NUM_L:
4960 					if (Np->is_to_char)
4961 					{
4962 						strcpy(Np->inout_p, Np->L_currency_symbol);
4963 						Np->inout_p += strlen(Np->inout_p) - 1;
4964 					}
4965 					else
4966 						Np->inout_p += strlen(Np->L_currency_symbol) - 1;
4967 					break;
4968 
4969 				case NUM_RN:
4970 					if (IS_FILLMODE(Np->Num))
4971 					{
4972 						strcpy(Np->inout_p, Np->number_p);
4973 						Np->inout_p += strlen(Np->inout_p) - 1;
4974 					}
4975 					else
4976 					{
4977 						sprintf(Np->inout_p, "%15s", Np->number_p);
4978 						Np->inout_p += strlen(Np->inout_p) - 1;
4979 					}
4980 					break;
4981 
4982 				case NUM_rn:
4983 					if (IS_FILLMODE(Np->Num))
4984 					{
4985 						strcpy(Np->inout_p, asc_tolower_z(Np->number_p));
4986 						Np->inout_p += strlen(Np->inout_p) - 1;
4987 					}
4988 					else
4989 					{
4990 						sprintf(Np->inout_p, "%15s", asc_tolower_z(Np->number_p));
4991 						Np->inout_p += strlen(Np->inout_p) - 1;
4992 					}
4993 					break;
4994 
4995 				case NUM_th:
4996 					if (IS_ROMAN(Np->Num) || *Np->number == '#' ||
4997 						Np->sign == '-' || IS_DECIMAL(Np->Num))
4998 						continue;
4999 
5000 					if (Np->is_to_char)
5001 						strcpy(Np->inout_p, get_th(Np->number, TH_LOWER));
5002 					Np->inout_p += 1;
5003 					break;
5004 
5005 				case NUM_TH:
5006 					if (IS_ROMAN(Np->Num) || *Np->number == '#' ||
5007 						Np->sign == '-' || IS_DECIMAL(Np->Num))
5008 						continue;
5009 
5010 					if (Np->is_to_char)
5011 						strcpy(Np->inout_p, get_th(Np->number, TH_UPPER));
5012 					Np->inout_p += 1;
5013 					break;
5014 
5015 				case NUM_MI:
5016 					if (Np->is_to_char)
5017 					{
5018 						if (Np->sign == '-')
5019 							*Np->inout_p = '-';
5020 						else if (IS_FILLMODE(Np->Num))
5021 							continue;
5022 						else
5023 							*Np->inout_p = ' ';
5024 					}
5025 					else
5026 					{
5027 						if (*Np->inout_p == '-')
5028 							*Np->number = '-';
5029 					}
5030 					break;
5031 
5032 				case NUM_PL:
5033 					if (Np->is_to_char)
5034 					{
5035 						if (Np->sign == '+')
5036 							*Np->inout_p = '+';
5037 						else if (IS_FILLMODE(Np->Num))
5038 							continue;
5039 						else
5040 							*Np->inout_p = ' ';
5041 					}
5042 					else
5043 					{
5044 						if (*Np->inout_p == '+')
5045 							*Np->number = '+';
5046 					}
5047 					break;
5048 
5049 				case NUM_SG:
5050 					if (Np->is_to_char)
5051 						*Np->inout_p = Np->sign;
5052 
5053 					else
5054 					{
5055 						if (*Np->inout_p == '-')
5056 							*Np->number = '-';
5057 						else if (*Np->inout_p == '+')
5058 							*Np->number = '+';
5059 					}
5060 					break;
5061 
5062 
5063 				default:
5064 					continue;
5065 					break;
5066 			}
5067 		}
5068 		else
5069 		{
5070 			/*
5071 			 * Remove to output char from input in TO_CHAR
5072 			 */
5073 			if (Np->is_to_char)
5074 				*Np->inout_p = n->character;
5075 		}
5076 		Np->inout_p++;
5077 	}
5078 
5079 	if (Np->is_to_char)
5080 	{
5081 		*Np->inout_p = '\0';
5082 		return Np->inout;
5083 	}
5084 	else
5085 	{
5086 		if (*(Np->number_p - 1) == '.')
5087 			*(Np->number_p - 1) = '\0';
5088 		else
5089 			*Np->number_p = '\0';
5090 
5091 		/*
5092 		 * Correction - precision of dec. number
5093 		 */
5094 		Np->Num->post = Np->read_post;
5095 
5096 #ifdef DEBUG_TO_FROM_CHAR
5097 		elog(DEBUG_elog_output, "TO_NUMBER (number): '%s'", Np->number);
5098 #endif
5099 		return Np->number;
5100 	}
5101 }
5102 
5103 /* ----------
5104  * MACRO: Start part of NUM - for all NUM's to_char variants
5105  *	(sorry, but I hate copy same code - macro is better..)
5106  * ----------
5107  */
5108 #define NUM_TOCHAR_prepare \
5109 do { \
5110 	int len = VARSIZE_ANY_EXHDR(fmt); \
5111 	if (len <= 0 || len >= (INT_MAX-VARHDRSZ)/NUM_MAX_ITEM_SIZ)		\
5112 		PG_RETURN_TEXT_P(cstring_to_text("")); \
5113 	result	= (text *) palloc0((len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ);	\
5114 	format	= NUM_cache(len, &Num, fmt, &shouldFree);		\
5115 } while (0)
5116 
5117 /* ----------
5118  * MACRO: Finish part of NUM
5119  * ----------
5120  */
5121 #define NUM_TOCHAR_finish \
5122 do { \
5123 	int		len; \
5124 									\
5125 	NUM_processor(format, &Num, VARDATA(result), numstr, 0, out_pre_spaces, sign, true, PG_GET_COLLATION()); \
5126 									\
5127 	if (shouldFree)					\
5128 		pfree(format);				\
5129 									\
5130 	/*								\
5131 	 * Convert null-terminated representation of result to standard text. \
5132 	 * The result is usually much bigger than it needs to be, but there \
5133 	 * seems little point in realloc'ing it smaller. \
5134 	 */								\
5135 	len = strlen(VARDATA(result));	\
5136 	SET_VARSIZE(result, len + VARHDRSZ); \
5137 } while (0)
5138 
5139 /* -------------------
5140  * NUMERIC to_number() (convert string to numeric)
5141  * -------------------
5142  */
5143 Datum
numeric_to_number(PG_FUNCTION_ARGS)5144 numeric_to_number(PG_FUNCTION_ARGS)
5145 {
5146 	text	   *value = PG_GETARG_TEXT_PP(0);
5147 	text	   *fmt = PG_GETARG_TEXT_PP(1);
5148 	NUMDesc		Num;
5149 	Datum		result;
5150 	FormatNode *format;
5151 	char	   *numstr;
5152 	bool		shouldFree;
5153 	int			len = 0;
5154 	int			scale,
5155 				precision;
5156 
5157 	len = VARSIZE_ANY_EXHDR(fmt);
5158 
5159 	if (len <= 0 || len >= INT_MAX / NUM_MAX_ITEM_SIZ)
5160 		PG_RETURN_NULL();
5161 
5162 	format = NUM_cache(len, &Num, fmt, &shouldFree);
5163 
5164 	numstr = (char *) palloc((len * NUM_MAX_ITEM_SIZ) + 1);
5165 
5166 	NUM_processor(format, &Num, VARDATA_ANY(value), numstr,
5167 				  VARSIZE_ANY_EXHDR(value), 0, 0, false, PG_GET_COLLATION());
5168 
5169 	scale = Num.post;
5170 	precision = Num.pre + Num.multi + scale;
5171 
5172 	if (shouldFree)
5173 		pfree(format);
5174 
5175 	result = DirectFunctionCall3(numeric_in,
5176 								 CStringGetDatum(numstr),
5177 								 ObjectIdGetDatum(InvalidOid),
5178 								 Int32GetDatum(((precision << 16) | scale) + VARHDRSZ));
5179 
5180 	if (IS_MULTI(&Num))
5181 	{
5182 		Numeric		x;
5183 		Numeric		a = DatumGetNumeric(DirectFunctionCall1(int4_numeric,
5184 															Int32GetDatum(10)));
5185 		Numeric		b = DatumGetNumeric(DirectFunctionCall1(int4_numeric,
5186 															Int32GetDatum(-Num.multi)));
5187 
5188 		x = DatumGetNumeric(DirectFunctionCall2(numeric_power,
5189 												NumericGetDatum(a),
5190 												NumericGetDatum(b)));
5191 		result = DirectFunctionCall2(numeric_mul,
5192 									 result,
5193 									 NumericGetDatum(x));
5194 	}
5195 
5196 	pfree(numstr);
5197 	return result;
5198 }
5199 
5200 /* ------------------
5201  * NUMERIC to_char()
5202  * ------------------
5203  */
5204 Datum
numeric_to_char(PG_FUNCTION_ARGS)5205 numeric_to_char(PG_FUNCTION_ARGS)
5206 {
5207 	Numeric		value = PG_GETARG_NUMERIC(0);
5208 	text	   *fmt = PG_GETARG_TEXT_PP(1);
5209 	NUMDesc		Num;
5210 	FormatNode *format;
5211 	text	   *result;
5212 	bool		shouldFree;
5213 	int			out_pre_spaces = 0,
5214 				sign = 0;
5215 	char	   *numstr,
5216 			   *orgnum,
5217 			   *p;
5218 	Numeric		x;
5219 
5220 	NUM_TOCHAR_prepare;
5221 
5222 	/*
5223 	 * On DateType depend part (numeric)
5224 	 */
5225 	if (IS_ROMAN(&Num))
5226 	{
5227 		x = DatumGetNumeric(DirectFunctionCall2(numeric_round,
5228 												NumericGetDatum(value),
5229 												Int32GetDatum(0)));
5230 		numstr = orgnum =
5231 			int_to_roman(DatumGetInt32(DirectFunctionCall1(numeric_int4,
5232 														   NumericGetDatum(x))));
5233 	}
5234 	else if (IS_EEEE(&Num))
5235 	{
5236 		orgnum = numeric_out_sci(value, Num.post);
5237 
5238 		/*
5239 		 * numeric_out_sci() does not emit a sign for positive numbers.  We
5240 		 * need to add a space in this case so that positive and negative
5241 		 * numbers are aligned.  We also have to do the right thing for NaN.
5242 		 */
5243 		if (strcmp(orgnum, "NaN") == 0)
5244 		{
5245 			/*
5246 			 * Allow 6 characters for the leading sign, the decimal point,
5247 			 * "e", the exponent's sign and two exponent digits.
5248 			 */
5249 			numstr = (char *) palloc(Num.pre + Num.post + 7);
5250 			fill_str(numstr, '#', Num.pre + Num.post + 6);
5251 			*numstr = ' ';
5252 			*(numstr + Num.pre + 1) = '.';
5253 		}
5254 		else if (*orgnum != '-')
5255 		{
5256 			numstr = (char *) palloc(strlen(orgnum) + 2);
5257 			*numstr = ' ';
5258 			strcpy(numstr + 1, orgnum);
5259 		}
5260 		else
5261 		{
5262 			numstr = orgnum;
5263 		}
5264 	}
5265 	else
5266 	{
5267 		int			numstr_pre_len;
5268 		Numeric		val = value;
5269 
5270 		if (IS_MULTI(&Num))
5271 		{
5272 			Numeric		a = DatumGetNumeric(DirectFunctionCall1(int4_numeric,
5273 																Int32GetDatum(10)));
5274 			Numeric		b = DatumGetNumeric(DirectFunctionCall1(int4_numeric,
5275 																Int32GetDatum(Num.multi)));
5276 
5277 			x = DatumGetNumeric(DirectFunctionCall2(numeric_power,
5278 													NumericGetDatum(a),
5279 													NumericGetDatum(b)));
5280 			val = DatumGetNumeric(DirectFunctionCall2(numeric_mul,
5281 													  NumericGetDatum(value),
5282 													  NumericGetDatum(x)));
5283 			Num.pre += Num.multi;
5284 		}
5285 
5286 		x = DatumGetNumeric(DirectFunctionCall2(numeric_round,
5287 												NumericGetDatum(val),
5288 												Int32GetDatum(Num.post)));
5289 		orgnum = DatumGetCString(DirectFunctionCall1(numeric_out,
5290 													 NumericGetDatum(x)));
5291 
5292 		if (*orgnum == '-')
5293 		{
5294 			sign = '-';
5295 			numstr = orgnum + 1;
5296 		}
5297 		else
5298 		{
5299 			sign = '+';
5300 			numstr = orgnum;
5301 		}
5302 
5303 		if ((p = strchr(numstr, '.')))
5304 			numstr_pre_len = p - numstr;
5305 		else
5306 			numstr_pre_len = strlen(numstr);
5307 
5308 		/* needs padding? */
5309 		if (numstr_pre_len < Num.pre)
5310 			out_pre_spaces = Num.pre - numstr_pre_len;
5311 		/* overflowed prefix digit format? */
5312 		else if (numstr_pre_len > Num.pre)
5313 		{
5314 			numstr = (char *) palloc(Num.pre + Num.post + 2);
5315 			fill_str(numstr, '#', Num.pre + Num.post + 1);
5316 			*(numstr + Num.pre) = '.';
5317 		}
5318 	}
5319 
5320 	NUM_TOCHAR_finish;
5321 	PG_RETURN_TEXT_P(result);
5322 }
5323 
5324 /* ---------------
5325  * INT4 to_char()
5326  * ---------------
5327  */
5328 Datum
int4_to_char(PG_FUNCTION_ARGS)5329 int4_to_char(PG_FUNCTION_ARGS)
5330 {
5331 	int32		value = PG_GETARG_INT32(0);
5332 	text	   *fmt = PG_GETARG_TEXT_PP(1);
5333 	NUMDesc		Num;
5334 	FormatNode *format;
5335 	text	   *result;
5336 	bool		shouldFree;
5337 	int			out_pre_spaces = 0,
5338 				sign = 0;
5339 	char	   *numstr,
5340 			   *orgnum;
5341 
5342 	NUM_TOCHAR_prepare;
5343 
5344 	/*
5345 	 * On DateType depend part (int32)
5346 	 */
5347 	if (IS_ROMAN(&Num))
5348 		numstr = orgnum = int_to_roman(value);
5349 	else if (IS_EEEE(&Num))
5350 	{
5351 		/* we can do it easily because float8 won't lose any precision */
5352 		float8		val = (float8) value;
5353 
5354 		orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
5355 		snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, val);
5356 
5357 		/*
5358 		 * Swap a leading positive sign for a space.
5359 		 */
5360 		if (*orgnum == '+')
5361 			*orgnum = ' ';
5362 
5363 		numstr = orgnum;
5364 	}
5365 	else
5366 	{
5367 		int			numstr_pre_len;
5368 
5369 		if (IS_MULTI(&Num))
5370 		{
5371 			orgnum = DatumGetCString(DirectFunctionCall1(int4out,
5372 														 Int32GetDatum(value * ((int32) pow((double) 10, (double) Num.multi)))));
5373 			Num.pre += Num.multi;
5374 		}
5375 		else
5376 		{
5377 			orgnum = DatumGetCString(DirectFunctionCall1(int4out,
5378 														 Int32GetDatum(value)));
5379 		}
5380 
5381 		if (*orgnum == '-')
5382 		{
5383 			sign = '-';
5384 			orgnum++;
5385 		}
5386 		else
5387 			sign = '+';
5388 
5389 		numstr_pre_len = strlen(orgnum);
5390 
5391 		/* post-decimal digits?  Pad out with zeros. */
5392 		if (Num.post)
5393 		{
5394 			numstr = (char *) palloc(numstr_pre_len + Num.post + 2);
5395 			strcpy(numstr, orgnum);
5396 			*(numstr + numstr_pre_len) = '.';
5397 			memset(numstr + numstr_pre_len + 1, '0', Num.post);
5398 			*(numstr + numstr_pre_len + Num.post + 1) = '\0';
5399 		}
5400 		else
5401 			numstr = orgnum;
5402 
5403 		/* needs padding? */
5404 		if (numstr_pre_len < Num.pre)
5405 			out_pre_spaces = Num.pre - numstr_pre_len;
5406 		/* overflowed prefix digit format? */
5407 		else if (numstr_pre_len > Num.pre)
5408 		{
5409 			numstr = (char *) palloc(Num.pre + Num.post + 2);
5410 			fill_str(numstr, '#', Num.pre + Num.post + 1);
5411 			*(numstr + Num.pre) = '.';
5412 		}
5413 	}
5414 
5415 	NUM_TOCHAR_finish;
5416 	PG_RETURN_TEXT_P(result);
5417 }
5418 
5419 /* ---------------
5420  * INT8 to_char()
5421  * ---------------
5422  */
5423 Datum
int8_to_char(PG_FUNCTION_ARGS)5424 int8_to_char(PG_FUNCTION_ARGS)
5425 {
5426 	int64		value = PG_GETARG_INT64(0);
5427 	text	   *fmt = PG_GETARG_TEXT_PP(1);
5428 	NUMDesc		Num;
5429 	FormatNode *format;
5430 	text	   *result;
5431 	bool		shouldFree;
5432 	int			out_pre_spaces = 0,
5433 				sign = 0;
5434 	char	   *numstr,
5435 			   *orgnum;
5436 
5437 	NUM_TOCHAR_prepare;
5438 
5439 	/*
5440 	 * On DateType depend part (int32)
5441 	 */
5442 	if (IS_ROMAN(&Num))
5443 	{
5444 		/* Currently don't support int8 conversion to roman... */
5445 		numstr = orgnum = int_to_roman(DatumGetInt32(
5446 													 DirectFunctionCall1(int84, Int64GetDatum(value))));
5447 	}
5448 	else if (IS_EEEE(&Num))
5449 	{
5450 		/* to avoid loss of precision, must go via numeric not float8 */
5451 		Numeric		val;
5452 
5453 		val = DatumGetNumeric(DirectFunctionCall1(int8_numeric,
5454 												  Int64GetDatum(value)));
5455 		orgnum = numeric_out_sci(val, Num.post);
5456 
5457 		/*
5458 		 * numeric_out_sci() does not emit a sign for positive numbers.  We
5459 		 * need to add a space in this case so that positive and negative
5460 		 * numbers are aligned.  We don't have to worry about NaN here.
5461 		 */
5462 		if (*orgnum != '-')
5463 		{
5464 			numstr = (char *) palloc(strlen(orgnum) + 2);
5465 			*numstr = ' ';
5466 			strcpy(numstr + 1, orgnum);
5467 		}
5468 		else
5469 		{
5470 			numstr = orgnum;
5471 		}
5472 	}
5473 	else
5474 	{
5475 		int			numstr_pre_len;
5476 
5477 		if (IS_MULTI(&Num))
5478 		{
5479 			double		multi = pow((double) 10, (double) Num.multi);
5480 
5481 			value = DatumGetInt64(DirectFunctionCall2(int8mul,
5482 													  Int64GetDatum(value),
5483 													  DirectFunctionCall1(dtoi8,
5484 																		  Float8GetDatum(multi))));
5485 			Num.pre += Num.multi;
5486 		}
5487 
5488 		orgnum = DatumGetCString(DirectFunctionCall1(int8out,
5489 													 Int64GetDatum(value)));
5490 
5491 		if (*orgnum == '-')
5492 		{
5493 			sign = '-';
5494 			orgnum++;
5495 		}
5496 		else
5497 			sign = '+';
5498 
5499 		numstr_pre_len = strlen(orgnum);
5500 
5501 		/* post-decimal digits?  Pad out with zeros. */
5502 		if (Num.post)
5503 		{
5504 			numstr = (char *) palloc(numstr_pre_len + Num.post + 2);
5505 			strcpy(numstr, orgnum);
5506 			*(numstr + numstr_pre_len) = '.';
5507 			memset(numstr + numstr_pre_len + 1, '0', Num.post);
5508 			*(numstr + numstr_pre_len + Num.post + 1) = '\0';
5509 		}
5510 		else
5511 			numstr = orgnum;
5512 
5513 		/* needs padding? */
5514 		if (numstr_pre_len < Num.pre)
5515 			out_pre_spaces = Num.pre - numstr_pre_len;
5516 		/* overflowed prefix digit format? */
5517 		else if (numstr_pre_len > Num.pre)
5518 		{
5519 			numstr = (char *) palloc(Num.pre + Num.post + 2);
5520 			fill_str(numstr, '#', Num.pre + Num.post + 1);
5521 			*(numstr + Num.pre) = '.';
5522 		}
5523 	}
5524 
5525 	NUM_TOCHAR_finish;
5526 	PG_RETURN_TEXT_P(result);
5527 }
5528 
5529 /* -----------------
5530  * FLOAT4 to_char()
5531  * -----------------
5532  */
5533 Datum
float4_to_char(PG_FUNCTION_ARGS)5534 float4_to_char(PG_FUNCTION_ARGS)
5535 {
5536 	float4		value = PG_GETARG_FLOAT4(0);
5537 	text	   *fmt = PG_GETARG_TEXT_PP(1);
5538 	NUMDesc		Num;
5539 	FormatNode *format;
5540 	text	   *result;
5541 	bool		shouldFree;
5542 	int			out_pre_spaces = 0,
5543 				sign = 0;
5544 	char	   *numstr,
5545 			   *orgnum,
5546 			   *p;
5547 
5548 	NUM_TOCHAR_prepare;
5549 
5550 	if (IS_ROMAN(&Num))
5551 		numstr = orgnum = int_to_roman((int) rint(value));
5552 	else if (IS_EEEE(&Num))
5553 	{
5554 		numstr = orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
5555 		if (isnan(value) || is_infinite(value))
5556 		{
5557 			/*
5558 			 * Allow 6 characters for the leading sign, the decimal point,
5559 			 * "e", the exponent's sign and two exponent digits.
5560 			 */
5561 			numstr = (char *) palloc(Num.pre + Num.post + 7);
5562 			fill_str(numstr, '#', Num.pre + Num.post + 6);
5563 			*numstr = ' ';
5564 			*(numstr + Num.pre + 1) = '.';
5565 		}
5566 		else
5567 		{
5568 			snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, value);
5569 
5570 			/*
5571 			 * Swap a leading positive sign for a space.
5572 			 */
5573 			if (*orgnum == '+')
5574 				*orgnum = ' ';
5575 
5576 			numstr = orgnum;
5577 		}
5578 	}
5579 	else
5580 	{
5581 		float4		val = value;
5582 		int			numstr_pre_len;
5583 
5584 		if (IS_MULTI(&Num))
5585 		{
5586 			float		multi = pow((double) 10, (double) Num.multi);
5587 
5588 			val = value * multi;
5589 			Num.pre += Num.multi;
5590 		}
5591 
5592 		orgnum = (char *) palloc(MAXFLOATWIDTH + 1);
5593 		snprintf(orgnum, MAXFLOATWIDTH + 1, "%.0f", fabs(val));
5594 		numstr_pre_len = strlen(orgnum);
5595 
5596 		/* adjust post digits to fit max float digits */
5597 		if (numstr_pre_len >= FLT_DIG)
5598 			Num.post = 0;
5599 		else if (numstr_pre_len + Num.post > FLT_DIG)
5600 			Num.post = FLT_DIG - numstr_pre_len;
5601 		snprintf(orgnum, MAXFLOATWIDTH + 1, "%.*f", Num.post, val);
5602 
5603 		if (*orgnum == '-')
5604 		{						/* < 0 */
5605 			sign = '-';
5606 			numstr = orgnum + 1;
5607 		}
5608 		else
5609 		{
5610 			sign = '+';
5611 			numstr = orgnum;
5612 		}
5613 
5614 		if ((p = strchr(numstr, '.')))
5615 			numstr_pre_len = p - numstr;
5616 		else
5617 			numstr_pre_len = strlen(numstr);
5618 
5619 		/* needs padding? */
5620 		if (numstr_pre_len < Num.pre)
5621 			out_pre_spaces = Num.pre - numstr_pre_len;
5622 		/* overflowed prefix digit format? */
5623 		else if (numstr_pre_len > Num.pre)
5624 		{
5625 			numstr = (char *) palloc(Num.pre + Num.post + 2);
5626 			fill_str(numstr, '#', Num.pre + Num.post + 1);
5627 			*(numstr + Num.pre) = '.';
5628 		}
5629 	}
5630 
5631 	NUM_TOCHAR_finish;
5632 	PG_RETURN_TEXT_P(result);
5633 }
5634 
5635 /* -----------------
5636  * FLOAT8 to_char()
5637  * -----------------
5638  */
5639 Datum
float8_to_char(PG_FUNCTION_ARGS)5640 float8_to_char(PG_FUNCTION_ARGS)
5641 {
5642 	float8		value = PG_GETARG_FLOAT8(0);
5643 	text	   *fmt = PG_GETARG_TEXT_PP(1);
5644 	NUMDesc		Num;
5645 	FormatNode *format;
5646 	text	   *result;
5647 	bool		shouldFree;
5648 	int			out_pre_spaces = 0,
5649 				sign = 0;
5650 	char	   *numstr,
5651 			   *orgnum,
5652 			   *p;
5653 
5654 	NUM_TOCHAR_prepare;
5655 
5656 	if (IS_ROMAN(&Num))
5657 		numstr = orgnum = int_to_roman((int) rint(value));
5658 	else if (IS_EEEE(&Num))
5659 	{
5660 		numstr = orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
5661 		if (isnan(value) || is_infinite(value))
5662 		{
5663 			/*
5664 			 * Allow 6 characters for the leading sign, the decimal point,
5665 			 * "e", the exponent's sign and two exponent digits.
5666 			 */
5667 			numstr = (char *) palloc(Num.pre + Num.post + 7);
5668 			fill_str(numstr, '#', Num.pre + Num.post + 6);
5669 			*numstr = ' ';
5670 			*(numstr + Num.pre + 1) = '.';
5671 		}
5672 		else
5673 		{
5674 			snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, value);
5675 
5676 			/*
5677 			 * Swap a leading positive sign for a space.
5678 			 */
5679 			if (*orgnum == '+')
5680 				*orgnum = ' ';
5681 
5682 			numstr = orgnum;
5683 		}
5684 	}
5685 	else
5686 	{
5687 		float8		val = value;
5688 		int			numstr_pre_len;
5689 
5690 		if (IS_MULTI(&Num))
5691 		{
5692 			double		multi = pow((double) 10, (double) Num.multi);
5693 
5694 			val = value * multi;
5695 			Num.pre += Num.multi;
5696 		}
5697 		orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
5698 		numstr_pre_len = snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%.0f", fabs(val));
5699 
5700 		/* adjust post digits to fit max double digits */
5701 		if (numstr_pre_len >= DBL_DIG)
5702 			Num.post = 0;
5703 		else if (numstr_pre_len + Num.post > DBL_DIG)
5704 			Num.post = DBL_DIG - numstr_pre_len;
5705 		snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%.*f", Num.post, val);
5706 
5707 		if (*orgnum == '-')
5708 		{						/* < 0 */
5709 			sign = '-';
5710 			numstr = orgnum + 1;
5711 		}
5712 		else
5713 		{
5714 			sign = '+';
5715 			numstr = orgnum;
5716 		}
5717 
5718 		if ((p = strchr(numstr, '.')))
5719 			numstr_pre_len = p - numstr;
5720 		else
5721 			numstr_pre_len = strlen(numstr);
5722 
5723 		/* needs padding? */
5724 		if (numstr_pre_len < Num.pre)
5725 			out_pre_spaces = Num.pre - numstr_pre_len;
5726 		/* overflowed prefix digit format? */
5727 		else if (numstr_pre_len > Num.pre)
5728 		{
5729 			numstr = (char *) palloc(Num.pre + Num.post + 2);
5730 			fill_str(numstr, '#', Num.pre + Num.post + 1);
5731 			*(numstr + Num.pre) = '.';
5732 		}
5733 	}
5734 
5735 	NUM_TOCHAR_finish;
5736 	PG_RETURN_TEXT_P(result);
5737 }
5738