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