6565 * causing nasty effects.
6666 **************************************************************/
6767
68- /*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.19 2005/03/12 04 :00:56 momjian Exp $";*/
68+ /*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.20 2005/03/16 06 :00:58 momjian Exp $";*/
6969
7070int pg_snprintf (char * str ,size_t count ,const char * fmt ,...);
7171int pg_vsnprintf (char * str ,size_t count ,const char * fmt ,va_list args );
@@ -151,20 +151,20 @@ static void dopr_outch(int c, char *end, char **output);
151151
152152#define FMTSTR 1
153153#define FMTNUM 2
154- #define FMTFLOAT 3
155- #define FMTCHAR 4
154+ #define FMTNUM_U 3
155+ #define FMTFLOAT 4
156+ #define FMTCHAR 5
157+ #define FMTWIDTH 6
158+ #define FMTLEN 7
156159
157160static void
158161dopr (char * buffer ,const char * format ,va_list args ,char * end )
159162{
160163int ch ;
161- int64 value ;
162- double fvalue ;
163164int longlongflag = 0 ;
164165int longflag = 0 ;
165166int pointflag = 0 ;
166167int maxwidth = 0 ;
167- char * strvalue ;
168168int ljust ;
169169int len ;
170170int zpad ;
@@ -173,6 +173,7 @@ dopr(char *buffer, const char *format, va_list args, char *end)
173173const char * fmtbegin ;
174174int fmtpos = 1 ;
175175int realpos = 0 ;
176+ int precision ;
176177int position ;
177178char * output ;
178179int percents = 1 ;
@@ -195,6 +196,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
195196int pointflag ;
196197char func ;
197198int realpos ;
199+ int longflag ;
200+ int longlongflag ;
198201}* fmtpar ,* * fmtparptr ;
199202
200203/* Create enough structures to hold all arguments */
@@ -229,12 +232,12 @@ dopr(char *buffer, const char *format, va_list args, char *end)
229232longflag = longlongflag = pointflag = 0 ;
230233fmtbegin = format - 1 ;
231234realpos = 0 ;
232- position = 0 ;
235+ position = precision = 0 ;
233236nextch :
234237ch = * format ++ ;
235238switch (ch )
236239{
237- case 0 :
240+ case '\0' :
238241gotoperformpr ;
239242case '-' :
240243ljust = 1 ;
@@ -251,24 +254,29 @@ dopr(char *buffer, const char *format, va_list args, char *end)
251254case '7' :
252255case '8' :
253256case '9' :
254- if (pointflag )
255- /* could also be precision */
256- maxwidth = maxwidth * 10 + ch - '0' ;
257- else
257+ if (!pointflag )
258258{
259259len = len * 10 + ch - '0' ;
260260position = position * 10 + ch - '0' ;
261261}
262+ else
263+ {
264+ maxwidth = maxwidth * 10 + ch - '0' ;
265+ precision = precision * 10 + ch - '0' ;
266+ }
262267gotonextch ;
263268case '$' :
264269realpos = position ;
265270len = 0 ;
266271gotonextch ;
267272case '*' :
268- if (pointflag )
269- maxwidth = va_arg (args ,int );
273+ MemSet (& fmtpar [fmtpos ],0 ,sizeof (fmtpar [fmtpos ]));
274+ if (!pointflag )
275+ fmtpar [fmtpos ].func = FMTLEN ;
270276else
271- len = va_arg (args ,int );
277+ fmtpar [fmtpos ].func = FMTWIDTH ;
278+ fmtpar [fmtpos ].realpos = realpos ?realpos :fmtpos ;
279+ fmtpos ++ ;
272280gotonextch ;
273281case '.' :
274282pointflag = 1 ;
@@ -301,68 +309,40 @@ dopr(char *buffer, const char *format, va_list args, char *end)
301309#endif
302310case 'u' :
303311case 'U' :
304- /* fmtnum(value,base,dosign,ljust,len,zpad,&output) */
305- if (longflag )
306- {
307- if (longlongflag )
308- value = va_arg (args ,uint64 );
309- else
310- value = va_arg (args ,unsigned long );
311- }
312- else
313- value = va_arg (args ,unsigned int );
312+ fmtpar [fmtpos ].longflag = longflag ;
313+ fmtpar [fmtpos ].longlongflag = longlongflag ;
314314fmtpar [fmtpos ].fmtbegin = fmtbegin ;
315315fmtpar [fmtpos ].fmtend = format ;
316- fmtpar [fmtpos ].numvalue = value ;
317316fmtpar [fmtpos ].base = 10 ;
318317fmtpar [fmtpos ].dosign = 0 ;
319318fmtpar [fmtpos ].ljust = ljust ;
320319fmtpar [fmtpos ].len = len ;
321320fmtpar [fmtpos ].zpad = zpad ;
322- fmtpar [fmtpos ].func = FMTNUM ;
321+ fmtpar [fmtpos ].func = FMTNUM_U ;
323322fmtpar [fmtpos ].realpos = realpos ?realpos :fmtpos ;
324323fmtpos ++ ;
325324break ;
326325case 'o' :
327326case 'O' :
328- /* fmtnum(value,base,dosign,ljust,len,zpad,&output) */
329- if (longflag )
330- {
331- if (longlongflag )
332- value = va_arg (args ,uint64 );
333- else
334- value = va_arg (args ,unsigned long );
335- }
336- else
337- value = va_arg (args ,unsigned int );
327+ fmtpar [fmtpos ].longflag = longflag ;
328+ fmtpar [fmtpos ].longlongflag = longlongflag ;
338329fmtpar [fmtpos ].fmtbegin = fmtbegin ;
339330fmtpar [fmtpos ].fmtend = format ;
340- fmtpar [fmtpos ].numvalue = value ;
341331fmtpar [fmtpos ].base = 8 ;
342332fmtpar [fmtpos ].dosign = 0 ;
343333fmtpar [fmtpos ].ljust = ljust ;
344334fmtpar [fmtpos ].len = len ;
345335fmtpar [fmtpos ].zpad = zpad ;
346- fmtpar [fmtpos ].func = FMTNUM ;
336+ fmtpar [fmtpos ].func = FMTNUM_U ;
347337fmtpar [fmtpos ].realpos = realpos ?realpos :fmtpos ;
348338fmtpos ++ ;
349339break ;
350340case 'd' :
351341case 'D' :
352- if (longflag )
353- {
354- if (longlongflag )
355- {
356- value = va_arg (args ,int64 );
357- }
358- else
359- value = va_arg (args ,long );
360- }
361- else
362- value = va_arg (args ,int );
342+ fmtpar [fmtpos ].longflag = longflag ;
343+ fmtpar [fmtpos ].longlongflag = longlongflag ;
363344fmtpar [fmtpos ].fmtbegin = fmtbegin ;
364345fmtpar [fmtpos ].fmtend = format ;
365- fmtpar [fmtpos ].numvalue = value ;
366346fmtpar [fmtpos ].base = 10 ;
367347fmtpar [fmtpos ].dosign = 1 ;
368348fmtpar [fmtpos ].ljust = ljust ;
@@ -373,72 +353,47 @@ dopr(char *buffer, const char *format, va_list args, char *end)
373353fmtpos ++ ;
374354break ;
375355case 'x' :
376- if (longflag )
377- {
378- if (longlongflag )
379- value = va_arg (args ,uint64 );
380- else
381- value = va_arg (args ,unsigned long );
382- }
383- else
384- value = va_arg (args ,unsigned int );
356+ fmtpar [fmtpos ].longflag = longflag ;
357+ fmtpar [fmtpos ].longlongflag = longlongflag ;
385358fmtpar [fmtpos ].fmtbegin = fmtbegin ;
386359fmtpar [fmtpos ].fmtend = format ;
387- fmtpar [fmtpos ].numvalue = value ;
388360fmtpar [fmtpos ].base = 16 ;
389361fmtpar [fmtpos ].dosign = 0 ;
390362fmtpar [fmtpos ].ljust = ljust ;
391363fmtpar [fmtpos ].len = len ;
392364fmtpar [fmtpos ].zpad = zpad ;
393- fmtpar [fmtpos ].func = FMTNUM ;
365+ fmtpar [fmtpos ].func = FMTNUM_U ;
394366fmtpar [fmtpos ].realpos = realpos ?realpos :fmtpos ;
395367fmtpos ++ ;
396368break ;
397369case 'X' :
398- if (longflag )
399- {
400- if (longlongflag )
401- value = va_arg (args ,uint64 );
402- else
403- value = va_arg (args ,unsigned long );
404- }
405- else
406- value = va_arg (args ,unsigned int );
370+ fmtpar [fmtpos ].longflag = longflag ;
371+ fmtpar [fmtpos ].longlongflag = longlongflag ;
407372fmtpar [fmtpos ].fmtbegin = fmtbegin ;
408373fmtpar [fmtpos ].fmtend = format ;
409- fmtpar [fmtpos ].numvalue = value ;
410374fmtpar [fmtpos ].base = -16 ;
411375fmtpar [fmtpos ].dosign = 1 ;
412376fmtpar [fmtpos ].ljust = ljust ;
413377fmtpar [fmtpos ].len = len ;
414378fmtpar [fmtpos ].zpad = zpad ;
415- fmtpar [fmtpos ].func = FMTNUM ;
379+ fmtpar [fmtpos ].func = FMTNUM_U ;
416380fmtpar [fmtpos ].realpos = realpos ?realpos :fmtpos ;
417381fmtpos ++ ;
418382break ;
419383case 's' :
420- strvalue = va_arg (args ,char * );
421- if (maxwidth > 0 || !pointflag )
422- {
423- if (pointflag && len > maxwidth )
424- len = maxwidth ;/* Adjust padding */
425- fmtpar [fmtpos ].fmtbegin = fmtbegin ;
426- fmtpar [fmtpos ].fmtend = format ;
427- fmtpar [fmtpos ].value = strvalue ;
428- fmtpar [fmtpos ].ljust = ljust ;
429- fmtpar [fmtpos ].len = len ;
430- fmtpar [fmtpos ].zpad = zpad ;
431- fmtpar [fmtpos ].maxwidth = maxwidth ;
432- fmtpar [fmtpos ].func = FMTSTR ;
433- fmtpar [fmtpos ].realpos = realpos ?realpos :fmtpos ;
434- fmtpos ++ ;
435- }
384+ fmtpar [fmtpos ].fmtbegin = fmtbegin ;
385+ fmtpar [fmtpos ].fmtend = format ;
386+ fmtpar [fmtpos ].ljust = ljust ;
387+ fmtpar [fmtpos ].len = len ;
388+ fmtpar [fmtpos ].zpad = zpad ;
389+ fmtpar [fmtpos ].maxwidth = maxwidth ;
390+ fmtpar [fmtpos ].func = FMTSTR ;
391+ fmtpar [fmtpos ].realpos = realpos ?realpos :fmtpos ;
392+ fmtpos ++ ;
436393break ;
437394case 'c' :
438- ch = va_arg (args ,int );
439395fmtpar [fmtpos ].fmtbegin = fmtbegin ;
440396fmtpar [fmtpos ].fmtend = format ;
441- fmtpar [fmtpos ].charvalue = ch ;
442397fmtpar [fmtpos ].func = FMTCHAR ;
443398fmtpar [fmtpos ].realpos = realpos ?realpos :fmtpos ;
444399fmtpos ++ ;
@@ -448,15 +403,13 @@ dopr(char *buffer, const char *format, va_list args, char *end)
448403case 'f' :
449404case 'g' :
450405case 'G' :
451- fvalue = va_arg (args ,double );
452406fmtpar [fmtpos ].fmtbegin = fmtbegin ;
453407fmtpar [fmtpos ].fmtend = format ;
454- fmtpar [fmtpos ].fvalue = fvalue ;
455408fmtpar [fmtpos ].type = ch ;
456409fmtpar [fmtpos ].ljust = ljust ;
457410fmtpar [fmtpos ].len = len ;
458411fmtpar [fmtpos ].maxwidth = maxwidth ;
459- fmtpar [fmtpos ].precision = position ;
412+ fmtpar [fmtpos ].precision = precision ;
460413fmtpar [fmtpos ].pointflag = pointflag ;
461414fmtpar [fmtpos ].func = FMTFLOAT ;
462415fmtpar [fmtpos ].realpos = realpos ?realpos :fmtpos ;
@@ -473,22 +426,74 @@ dopr(char *buffer, const char *format, va_list args, char *end)
473426break ;
474427}
475428}
429+
476430performpr :
477- /*shuffle pointers */
431+ /*reorder pointers */
478432for (i = 1 ;i < fmtpos ;i ++ )
479433fmtparptr [i ]= & fmtpar [fmtpar [i ].realpos ];
434+
435+ /* assign values */
436+ for (i = 1 ;i < fmtpos ;i ++ ){
437+ switch (fmtparptr [i ]-> func ){
438+ case FMTSTR :
439+ fmtparptr [i ]-> value = va_arg (args ,char * );
440+ break ;
441+ case FMTNUM :
442+ if (fmtparptr [i ]-> longflag )
443+ {
444+ if (fmtparptr [i ]-> longlongflag )
445+ fmtparptr [i ]-> numvalue = va_arg (args ,int64 );
446+ else
447+ fmtparptr [i ]-> numvalue = va_arg (args ,long );
448+ }
449+ else
450+ fmtparptr [i ]-> numvalue = va_arg (args ,int );
451+ break ;
452+ case FMTNUM_U :
453+ if (fmtparptr [i ]-> longflag )
454+ {
455+ if (fmtparptr [i ]-> longlongflag )
456+ fmtparptr [i ]-> numvalue = va_arg (args ,uint64 );
457+ else
458+ fmtparptr [i ]-> numvalue = va_arg (args ,unsigned long );
459+ }
460+ else
461+ fmtparptr [i ]-> numvalue = va_arg (args ,unsigned int );
462+ break ;
463+ case FMTFLOAT :
464+ fmtparptr [i ]-> fvalue = va_arg (args ,double );
465+ break ;
466+ case FMTCHAR :
467+ fmtparptr [i ]-> charvalue = va_arg (args ,int );
468+ break ;
469+ case FMTLEN :
470+ if (i + 1 < fmtpos && fmtpar [i + 1 ].func != FMTWIDTH )
471+ fmtpar [i + 1 ].len = va_arg (args ,int );
472+ /* For "%*.*f", use the second arg */
473+ if (i + 2 < fmtpos && fmtpar [i + 1 ].func == FMTWIDTH )
474+ fmtpar [i + 2 ].len = va_arg (args ,int );
475+ break ;
476+ case FMTWIDTH :
477+ if (i + 1 < fmtpos )
478+ fmtpar [i + 1 ].maxwidth = fmtpar [i + 1 ].precision =
479+ va_arg (args ,int );
480+ break ;
481+ }
482+ }
483+
484+ /* do the output */
480485output = buffer ;
481486format = format_save ;
482487while ((ch = * format ++ ))
483488{
484489for (i = 1 ;i < fmtpos ;i ++ )
485490{
486- if (ch == '%' && * format == '%' )
491+ if (ch == '%' && * format == '%' )
487492{
488493format ++ ;
489494continue ;
490495}
491- if (fmtpar [i ].fmtbegin == format - 1 )
496+ if (fmtpar [i ].fmtbegin == format - 1 )
492497{
493498switch (fmtparptr [i ]-> func ){
494499case FMTSTR :
@@ -497,6 +502,7 @@ dopr(char *buffer, const char *format, va_list args, char *end)
497502fmtparptr [i ]-> maxwidth ,end ,& output );
498503break ;
499504case FMTNUM :
505+ case FMTNUM_U :
500506fmtnum (fmtparptr [i ]-> numvalue ,fmtparptr [i ]-> base ,
501507fmtparptr [i ]-> dosign ,fmtparptr [i ]-> ljust ,
502508fmtparptr [i ]-> len ,fmtparptr [i ]-> zpad ,end ,& output );