PostgreSQL Source Code  git master
snprintf.c File Reference
#include "c.h"
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include <sys/ioctl.h>
#include <sys/param.h>
Include dependency graph for snprintf.c:

Go to the source code of this file.

Data Structures

struct  PrintfTarget
 
union  PrintfArgValue
 

Macros

#define NL_ARGMAX   16
 

Enumerations

enum  PrintfArgType {
  ATYPE_NONE = 0, ATYPE_INT, ATYPE_LONG, ATYPE_LONGLONG,
  ATYPE_DOUBLE, ATYPE_CHARPTR
}
 

Functions

static void flushbuffer (PrintfTarget *target)
 
static void dopr (PrintfTarget *target, const char *format, va_list args)
 
int pg_vsnprintf (char *str, size_t count, const char *fmt, va_list args)
 
int pg_snprintf (char *str, size_t count, const char *fmt,...)
 
static int pg_vsprintf (char *str, const char *fmt, va_list args)
 
int pg_sprintf (char *str, const char *fmt,...)
 
int pg_vfprintf (FILE *stream, const char *fmt, va_list args)
 
int pg_fprintf (FILE *stream, const char *fmt,...)
 
int pg_printf (const char *fmt,...)
 
static void fmtstr (char *value, int leftjust, int minlen, int maxwidth, int pointflag, PrintfTarget *target)
 
static void fmtptr (void *value, PrintfTarget *target)
 
static void fmtint (int64 value, char type, int forcesign, int leftjust, int minlen, int zpad, int precision, int pointflag, PrintfTarget *target)
 
static void fmtchar (int value, int leftjust, int minlen, PrintfTarget *target)
 
static void fmtfloat (double value, char type, int forcesign, int leftjust, int minlen, int zpad, int precision, int pointflag, PrintfTarget *target)
 
static void dostr (const char *str, int slen, PrintfTarget *target)
 
static void dopr_outch (int c, PrintfTarget *target)
 
static int adjust_sign (int is_negative, int forcesign, int *signvalue)
 
static void adjust_padlen (int minlen, int vallen, int leftjust, int *padlen)
 
static void leading_pad (int zpad, int *signvalue, int *padlen, PrintfTarget *target)
 
static void trailing_pad (int *padlen, PrintfTarget *target)
 

Macro Definition Documentation

◆ NL_ARGMAX

#define NL_ARGMAX   16

Definition at line 47 of file snprintf.c.

Referenced by dopr().

Enumeration Type Documentation

◆ PrintfArgType

Enumerator
ATYPE_NONE 
ATYPE_INT 
ATYPE_LONG 
ATYPE_LONGLONG 
ATYPE_DOUBLE 
ATYPE_CHARPTR 

Definition at line 125 of file snprintf.c.

Function Documentation

◆ adjust_padlen()

static void adjust_padlen ( int  minlen,
int  vallen,
int  leftjust,
int *  padlen 
)
static

Definition at line 1082 of file snprintf.c.

Referenced by flushbuffer(), fmtchar(), fmtfloat(), fmtint(), and fmtstr().

1083 {
1084  *padlen = minlen - vallen;
1085  if (*padlen < 0)
1086  *padlen = 0;
1087  if (leftjust)
1088  *padlen = -(*padlen);
1089 }

◆ adjust_sign()

static int adjust_sign ( int  is_negative,
int  forcesign,
int *  signvalue 
)
static

Definition at line 1068 of file snprintf.c.

Referenced by flushbuffer(), fmtfloat(), and fmtint().

1069 {
1070  if (is_negative)
1071  {
1072  *signvalue = '-';
1073  return true;
1074  }
1075  else if (forcesign)
1076  *signvalue = '+';
1077  return false;
1078 }

◆ dopr()

static void dopr ( PrintfTarget target,
const char *  format,
va_list  args 
)
static

Definition at line 298 of file snprintf.c.

References Assert, ATYPE_CHARPTR, ATYPE_DOUBLE, ATYPE_INT, ATYPE_LONG, ATYPE_LONGLONG, ATYPE_NONE, PrintfArgValue::cptr, PrintfArgValue::d, dopr_outch(), PrintfTarget::failed, fmtchar(), fmtfloat(), fmtint(), fmtptr(), fmtstr(), format, i, PrintfArgValue::i, PrintfArgValue::l, PrintfArgValue::ll, Max, MemSet, and NL_ARGMAX.

Referenced by pg_vfprintf(), pg_vsnprintf(), and pg_vsprintf().

299 {
300  const char *format_start = format;
301  int ch;
302  bool have_dollar;
303  bool have_non_dollar;
304  bool have_star;
305  bool afterstar;
306  int accum;
307  int longlongflag;
308  int longflag;
309  int pointflag;
310  int leftjust;
311  int fieldwidth;
312  int precision;
313  int zpad;
314  int forcesign;
315  int last_dollar;
316  int fmtpos;
317  int cvalue;
318  int64 numvalue;
319  double fvalue;
320  char *strvalue;
321  int i;
322  PrintfArgType argtypes[NL_ARGMAX + 1];
323  PrintfArgValue argvalues[NL_ARGMAX + 1];
324 
325  /*
326  * Parse the format string to determine whether there are %n$ format
327  * specs, and identify the types and order of the format parameters.
328  */
329  have_dollar = have_non_dollar = false;
330  last_dollar = 0;
331  MemSet(argtypes, 0, sizeof(argtypes));
332 
333  while ((ch = *format++) != '\0')
334  {
335  if (ch != '%')
336  continue;
337  longflag = longlongflag = pointflag = 0;
338  fmtpos = accum = 0;
339  afterstar = false;
340 nextch1:
341  ch = *format++;
342  if (ch == '\0')
343  break; /* illegal, but we don't complain */
344  switch (ch)
345  {
346  case '-':
347  case '+':
348  goto nextch1;
349  case '0':
350  case '1':
351  case '2':
352  case '3':
353  case '4':
354  case '5':
355  case '6':
356  case '7':
357  case '8':
358  case '9':
359  accum = accum * 10 + (ch - '0');
360  goto nextch1;
361  case '.':
362  pointflag = 1;
363  accum = 0;
364  goto nextch1;
365  case '*':
366  if (afterstar)
367  have_non_dollar = true; /* multiple stars */
368  afterstar = true;
369  accum = 0;
370  goto nextch1;
371  case '$':
372  have_dollar = true;
373  if (accum <= 0 || accum > NL_ARGMAX)
374  goto bad_format;
375  if (afterstar)
376  {
377  if (argtypes[accum] &&
378  argtypes[accum] != ATYPE_INT)
379  goto bad_format;
380  argtypes[accum] = ATYPE_INT;
381  last_dollar = Max(last_dollar, accum);
382  afterstar = false;
383  }
384  else
385  fmtpos = accum;
386  accum = 0;
387  goto nextch1;
388  case 'l':
389  if (longflag)
390  longlongflag = 1;
391  else
392  longflag = 1;
393  goto nextch1;
394  case 'z':
395 #if SIZEOF_SIZE_T == 8
396 #ifdef HAVE_LONG_INT_64
397  longflag = 1;
398 #elif defined(HAVE_LONG_LONG_INT_64)
399  longlongflag = 1;
400 #else
401 #error "Don't know how to print 64bit integers"
402 #endif
403 #else
404  /* assume size_t is same size as int */
405 #endif
406  goto nextch1;
407  case 'h':
408  case '\'':
409  /* ignore these */
410  goto nextch1;
411  case 'd':
412  case 'i':
413  case 'o':
414  case 'u':
415  case 'x':
416  case 'X':
417  if (fmtpos)
418  {
419  PrintfArgType atype;
420 
421  if (longlongflag)
422  atype = ATYPE_LONGLONG;
423  else if (longflag)
424  atype = ATYPE_LONG;
425  else
426  atype = ATYPE_INT;
427  if (argtypes[fmtpos] &&
428  argtypes[fmtpos] != atype)
429  goto bad_format;
430  argtypes[fmtpos] = atype;
431  last_dollar = Max(last_dollar, fmtpos);
432  }
433  else
434  have_non_dollar = true;
435  break;
436  case 'c':
437  if (fmtpos)
438  {
439  if (argtypes[fmtpos] &&
440  argtypes[fmtpos] != ATYPE_INT)
441  goto bad_format;
442  argtypes[fmtpos] = ATYPE_INT;
443  last_dollar = Max(last_dollar, fmtpos);
444  }
445  else
446  have_non_dollar = true;
447  break;
448  case 's':
449  case 'p':
450  if (fmtpos)
451  {
452  if (argtypes[fmtpos] &&
453  argtypes[fmtpos] != ATYPE_CHARPTR)
454  goto bad_format;
455  argtypes[fmtpos] = ATYPE_CHARPTR;
456  last_dollar = Max(last_dollar, fmtpos);
457  }
458  else
459  have_non_dollar = true;
460  break;
461  case 'e':
462  case 'E':
463  case 'f':
464  case 'g':
465  case 'G':
466  if (fmtpos)
467  {
468  if (argtypes[fmtpos] &&
469  argtypes[fmtpos] != ATYPE_DOUBLE)
470  goto bad_format;
471  argtypes[fmtpos] = ATYPE_DOUBLE;
472  last_dollar = Max(last_dollar, fmtpos);
473  }
474  else
475  have_non_dollar = true;
476  break;
477  case '%':
478  break;
479  }
480 
481  /*
482  * If we finish the spec with afterstar still set, there's a
483  * non-dollar star in there.
484  */
485  if (afterstar)
486  have_non_dollar = true;
487  }
488 
489  /* Per spec, you use either all dollar or all not. */
490  if (have_dollar && have_non_dollar)
491  goto bad_format;
492 
493  /*
494  * In dollar mode, collect the arguments in physical order.
495  */
496  for (i = 1; i <= last_dollar; i++)
497  {
498  switch (argtypes[i])
499  {
500  case ATYPE_NONE:
501  goto bad_format;
502  case ATYPE_INT:
503  argvalues[i].i = va_arg(args, int);
504  break;
505  case ATYPE_LONG:
506  argvalues[i].l = va_arg(args, long);
507  break;
508  case ATYPE_LONGLONG:
509  argvalues[i].ll = va_arg(args, int64);
510  break;
511  case ATYPE_DOUBLE:
512  argvalues[i].d = va_arg(args, double);
513  break;
514  case ATYPE_CHARPTR:
515  argvalues[i].cptr = va_arg(args, char *);
516  break;
517  }
518  }
519 
520  /*
521  * At last we can parse the format for real.
522  */
523  format = format_start;
524  while ((ch = *format++) != '\0')
525  {
526  if (target->failed)
527  break;
528 
529  if (ch != '%')
530  {
531  dopr_outch(ch, target);
532  continue;
533  }
534  fieldwidth = precision = zpad = leftjust = forcesign = 0;
535  longflag = longlongflag = pointflag = 0;
536  fmtpos = accum = 0;
537  have_star = afterstar = false;
538 nextch2:
539  ch = *format++;
540  if (ch == '\0')
541  break; /* illegal, but we don't complain */
542  switch (ch)
543  {
544  case '-':
545  leftjust = 1;
546  goto nextch2;
547  case '+':
548  forcesign = 1;
549  goto nextch2;
550  case '0':
551  /* set zero padding if no nonzero digits yet */
552  if (accum == 0 && !pointflag)
553  zpad = '0';
554  /* FALL THRU */
555  case '1':
556  case '2':
557  case '3':
558  case '4':
559  case '5':
560  case '6':
561  case '7':
562  case '8':
563  case '9':
564  accum = accum * 10 + (ch - '0');
565  goto nextch2;
566  case '.':
567  if (have_star)
568  have_star = false;
569  else
570  fieldwidth = accum;
571  pointflag = 1;
572  accum = 0;
573  goto nextch2;
574  case '*':
575  if (have_dollar)
576  {
577  /* process value after reading n$ */
578  afterstar = true;
579  }
580  else
581  {
582  /* fetch and process value now */
583  int starval = va_arg(args, int);
584 
585  if (pointflag)
586  {
587  precision = starval;
588  if (precision < 0)
589  {
590  precision = 0;
591  pointflag = 0;
592  }
593  }
594  else
595  {
596  fieldwidth = starval;
597  if (fieldwidth < 0)
598  {
599  leftjust = 1;
600  fieldwidth = -fieldwidth;
601  }
602  }
603  }
604  have_star = true;
605  accum = 0;
606  goto nextch2;
607  case '$':
608  if (afterstar)
609  {
610  /* fetch and process star value */
611  int starval = argvalues[accum].i;
612 
613  if (pointflag)
614  {
615  precision = starval;
616  if (precision < 0)
617  {
618  precision = 0;
619  pointflag = 0;
620  }
621  }
622  else
623  {
624  fieldwidth = starval;
625  if (fieldwidth < 0)
626  {
627  leftjust = 1;
628  fieldwidth = -fieldwidth;
629  }
630  }
631  afterstar = false;
632  }
633  else
634  fmtpos = accum;
635  accum = 0;
636  goto nextch2;
637  case 'l':
638  if (longflag)
639  longlongflag = 1;
640  else
641  longflag = 1;
642  goto nextch2;
643  case 'z':
644 #if SIZEOF_SIZE_T == 8
645 #ifdef HAVE_LONG_INT_64
646  longflag = 1;
647 #elif defined(HAVE_LONG_LONG_INT_64)
648  longlongflag = 1;
649 #else
650 #error "Don't know how to print 64bit integers"
651 #endif
652 #else
653  /* assume size_t is same size as int */
654 #endif
655  goto nextch2;
656  case 'h':
657  case '\'':
658  /* ignore these */
659  goto nextch2;
660  case 'd':
661  case 'i':
662  if (!have_star)
663  {
664  if (pointflag)
665  precision = accum;
666  else
667  fieldwidth = accum;
668  }
669  if (have_dollar)
670  {
671  if (longlongflag)
672  numvalue = argvalues[fmtpos].ll;
673  else if (longflag)
674  numvalue = argvalues[fmtpos].l;
675  else
676  numvalue = argvalues[fmtpos].i;
677  }
678  else
679  {
680  if (longlongflag)
681  numvalue = va_arg(args, int64);
682  else if (longflag)
683  numvalue = va_arg(args, long);
684  else
685  numvalue = va_arg(args, int);
686  }
687  fmtint(numvalue, ch, forcesign, leftjust, fieldwidth, zpad,
688  precision, pointflag, target);
689  break;
690  case 'o':
691  case 'u':
692  case 'x':
693  case 'X':
694  if (!have_star)
695  {
696  if (pointflag)
697  precision = accum;
698  else
699  fieldwidth = accum;
700  }
701  if (have_dollar)
702  {
703  if (longlongflag)
704  numvalue = (uint64) argvalues[fmtpos].ll;
705  else if (longflag)
706  numvalue = (unsigned long) argvalues[fmtpos].l;
707  else
708  numvalue = (unsigned int) argvalues[fmtpos].i;
709  }
710  else
711  {
712  if (longlongflag)
713  numvalue = (uint64) va_arg(args, int64);
714  else if (longflag)
715  numvalue = (unsigned long) va_arg(args, long);
716  else
717  numvalue = (unsigned int) va_arg(args, int);
718  }
719  fmtint(numvalue, ch, forcesign, leftjust, fieldwidth, zpad,
720  precision, pointflag, target);
721  break;
722  case 'c':
723  if (!have_star)
724  {
725  if (pointflag)
726  precision = accum;
727  else
728  fieldwidth = accum;
729  }
730  if (have_dollar)
731  cvalue = (unsigned char) argvalues[fmtpos].i;
732  else
733  cvalue = (unsigned char) va_arg(args, int);
734  fmtchar(cvalue, leftjust, fieldwidth, target);
735  break;
736  case 's':
737  if (!have_star)
738  {
739  if (pointflag)
740  precision = accum;
741  else
742  fieldwidth = accum;
743  }
744  if (have_dollar)
745  strvalue = argvalues[fmtpos].cptr;
746  else
747  strvalue = va_arg(args, char *);
748  /* Whine if someone tries to print a NULL string */
749  Assert(strvalue != NULL);
750  fmtstr(strvalue, leftjust, fieldwidth, precision, pointflag,
751  target);
752  break;
753  case 'p':
754  /* fieldwidth/leftjust are ignored ... */
755  if (have_dollar)
756  strvalue = argvalues[fmtpos].cptr;
757  else
758  strvalue = va_arg(args, char *);
759  fmtptr((void *) strvalue, target);
760  break;
761  case 'e':
762  case 'E':
763  case 'f':
764  case 'g':
765  case 'G':
766  if (!have_star)
767  {
768  if (pointflag)
769  precision = accum;
770  else
771  fieldwidth = accum;
772  }
773  if (have_dollar)
774  fvalue = argvalues[fmtpos].d;
775  else
776  fvalue = va_arg(args, double);
777  fmtfloat(fvalue, ch, forcesign, leftjust,
778  fieldwidth, zpad,
779  precision, pointflag,
780  target);
781  break;
782  case '%':
783  dopr_outch('%', target);
784  break;
785  }
786  }
787 
788  return;
789 
790 bad_format:
791  errno = EINVAL;
792  target->failed = true;
793 }
static void dopr_outch(int c, PrintfTarget *target)
Definition: snprintf.c:1054
static void fmtptr(void *value, PrintfTarget *target)
Definition: snprintf.c:825
static void fmtint(int64 value, char type, int forcesign, int leftjust, int minlen, int zpad, int precision, int pointflag, PrintfTarget *target)
Definition: snprintf.c:839
static void fmtchar(int value, int leftjust, int minlen, PrintfTarget *target)
Definition: snprintf.c:918
#define MemSet(start, val, len)
Definition: c.h:908
char * cptr
Definition: snprintf.c:141
bool failed
Definition: snprintf.c:116
static void fmtstr(char *value, int leftjust, int minlen, int maxwidth, int pointflag, PrintfTarget *target)
Definition: snprintf.c:796
#define Max(x, y)
Definition: c.h:851
PrintfArgType
Definition: snprintf.c:125
#define Assert(condition)
Definition: c.h:699
#define NL_ARGMAX
Definition: snprintf.c:47
int i
static char format
Definition: pg_basebackup.c:83
static void fmtfloat(double value, char type, int forcesign, int leftjust, int minlen, int zpad, int precision, int pointflag, PrintfTarget *target)
Definition: snprintf.c:936

◆ dopr_outch()

static void dopr_outch ( int  c,
PrintfTarget target 
)
static

Definition at line 1054 of file snprintf.c.

References PrintfTarget::bufend, PrintfTarget::bufptr, flushbuffer(), and PrintfTarget::stream.

Referenced by dopr(), flushbuffer(), fmtchar(), fmtfloat(), fmtint(), fmtstr(), leading_pad(), and trailing_pad().

1055 {
1056  if (target->bufend != NULL && target->bufptr >= target->bufend)
1057  {
1058  /* buffer full, can we dump to stream? */
1059  if (target->stream == NULL)
1060  return; /* no, lose the data */
1061  flushbuffer(target);
1062  }
1063  *(target->bufptr++) = c;
1064 }
char * bufend
Definition: snprintf.c:112
static void flushbuffer(PrintfTarget *target)
Definition: snprintf.c:258
char * c
FILE * stream
Definition: snprintf.c:114
char * bufptr
Definition: snprintf.c:110

◆ dostr()

static void dostr ( const char *  str,
int  slen,
PrintfTarget target 
)
static

Definition at line 1027 of file snprintf.c.

References PrintfTarget::bufend, PrintfTarget::bufptr, flushbuffer(), memmove, Min, and PrintfTarget::stream.

Referenced by flushbuffer(), fmtfloat(), fmtptr(), and fmtstr().

1028 {
1029  while (slen > 0)
1030  {
1031  int avail;
1032 
1033  if (target->bufend != NULL)
1034  avail = target->bufend - target->bufptr;
1035  else
1036  avail = slen;
1037  if (avail <= 0)
1038  {
1039  /* buffer full, can we dump to stream? */
1040  if (target->stream == NULL)
1041  return; /* no, lose the data */
1042  flushbuffer(target);
1043  continue;
1044  }
1045  avail = Min(avail, slen);
1046  memmove(target->bufptr, str, avail);
1047  target->bufptr += avail;
1048  str += avail;
1049  slen -= avail;
1050  }
1051 }
char * bufend
Definition: snprintf.c:112
#define Min(x, y)
Definition: c.h:857
static void flushbuffer(PrintfTarget *target)
Definition: snprintf.c:258
#define memmove(d, s, c)
Definition: c.h:1135
FILE * stream
Definition: snprintf.c:114
char * bufptr
Definition: snprintf.c:110

◆ flushbuffer()

static void flushbuffer ( PrintfTarget target)
static

Definition at line 258 of file snprintf.c.

References adjust_padlen(), adjust_sign(), PrintfTarget::bufptr, PrintfTarget::bufstart, dopr_outch(), dostr(), PrintfTarget::failed, fmtchar(), fmtfloat(), fmtint(), fmtptr(), fmtstr(), leading_pad(), PrintfTarget::nchars, generate_unaccent_rules::str, PrintfTarget::stream, trailing_pad(), generate_unaccent_rules::type, and value.

Referenced by dopr_outch(), dostr(), and pg_vfprintf().

259 {
260  size_t nc = target->bufptr - target->bufstart;
261 
262  if (!target->failed && nc > 0)
263  {
264  size_t written;
265 
266  written = fwrite(target->bufstart, 1, nc, target->stream);
267  target->nchars += written;
268  if (written != nc)
269  target->failed = true;
270  }
271  target->bufptr = target->bufstart;
272 }
char * bufstart
Definition: snprintf.c:111
FILE * stream
Definition: snprintf.c:114
bool failed
Definition: snprintf.c:116
char * bufptr
Definition: snprintf.c:110

◆ fmtchar()

static void fmtchar ( int  value,
int  leftjust,
int  minlen,
PrintfTarget target 
)
static

Definition at line 918 of file snprintf.c.

References adjust_padlen(), dopr_outch(), and trailing_pad().

Referenced by dopr(), flushbuffer(), and rfmtlong().

919 {
920  int padlen = 0; /* amount to pad */
921 
922  adjust_padlen(minlen, 1, leftjust, &padlen);
923 
924  while (padlen > 0)
925  {
926  dopr_outch(' ', target);
927  --padlen;
928  }
929 
930  dopr_outch(value, target);
931 
932  trailing_pad(&padlen, target);
933 }
static void dopr_outch(int c, PrintfTarget *target)
Definition: snprintf.c:1054
static struct @131 value
static void adjust_padlen(int minlen, int vallen, int leftjust, int *padlen)
Definition: snprintf.c:1082
static void trailing_pad(int *padlen, PrintfTarget *target)
Definition: snprintf.c:1126

◆ fmtfloat()

static void fmtfloat ( double  value,
char  type,
int  forcesign,
int  leftjust,
int  minlen,
int  zpad,
int  precision,
int  pointflag,
PrintfTarget target 
)
static

Definition at line 936 of file snprintf.c.

References adjust_padlen(), adjust_sign(), convert(), dopr_outch(), dostr(), PrintfTarget::failed, leading_pad(), Min, trailing_pad(), and value.

Referenced by dopr(), and flushbuffer().

939 {
940  int signvalue = 0;
941  int prec;
942  int vallen;
943  char fmt[32];
944  char convert[1024];
945  int zeropadlen = 0; /* amount to pad with zeroes */
946  int padlen = 0; /* amount to pad with spaces */
947 
948  /*
949  * We rely on the regular C library's sprintf to do the basic conversion,
950  * then handle padding considerations here.
951  *
952  * The dynamic range of "double" is about 1E+-308 for IEEE math, and not
953  * too wildly more than that with other hardware. In "f" format, sprintf
954  * could therefore generate at most 308 characters to the left of the
955  * decimal point; while we need to allow the precision to get as high as
956  * 308+17 to ensure that we don't truncate significant digits from very
957  * small values. To handle both these extremes, we use a buffer of 1024
958  * bytes and limit requested precision to 350 digits; this should prevent
959  * buffer overrun even with non-IEEE math. If the original precision
960  * request was more than 350, separately pad with zeroes.
961  */
962  if (precision < 0) /* cover possible overflow of "accum" */
963  precision = 0;
964  prec = Min(precision, 350);
965 
966  if (pointflag)
967  {
968  if (sprintf(fmt, "%%.%d%c", prec, type) < 0)
969  goto fail;
970  zeropadlen = precision - prec;
971  }
972  else if (sprintf(fmt, "%%%c", type) < 0)
973  goto fail;
974 
975  if (!isnan(value) && adjust_sign((value < 0), forcesign, &signvalue))
976  value = -value;
977 
978  vallen = sprintf(convert, fmt, value);
979  if (vallen < 0)
980  goto fail;
981 
982  /* If it's infinity or NaN, forget about doing any zero-padding */
983  if (zeropadlen > 0 && !isdigit((unsigned char) convert[vallen - 1]))
984  zeropadlen = 0;
985 
986  adjust_padlen(minlen, vallen + zeropadlen, leftjust, &padlen);
987 
988  leading_pad(zpad, &signvalue, &padlen, target);
989 
990  if (zeropadlen > 0)
991  {
992  /* If 'e' or 'E' format, inject zeroes before the exponent */
993  char *epos = strrchr(convert, 'e');
994 
995  if (!epos)
996  epos = strrchr(convert, 'E');
997  if (epos)
998  {
999  /* pad after exponent */
1000  dostr(convert, epos - convert, target);
1001  while (zeropadlen-- > 0)
1002  dopr_outch('0', target);
1003  dostr(epos, vallen - (epos - convert), target);
1004  }
1005  else
1006  {
1007  /* no exponent, pad after the digits */
1008  dostr(convert, vallen, target);
1009  while (zeropadlen-- > 0)
1010  dopr_outch('0', target);
1011  }
1012  }
1013  else
1014  {
1015  /* no zero padding, just emit the number as-is */
1016  dostr(convert, vallen, target);
1017  }
1018 
1019  trailing_pad(&padlen, target);
1020  return;
1021 
1022 fail:
1023  target->failed = true;
1024 }
static void dopr_outch(int c, PrintfTarget *target)
Definition: snprintf.c:1054
#define Min(x, y)
Definition: c.h:857
static void dostr(const char *str, int slen, PrintfTarget *target)
Definition: snprintf.c:1027
static void convert(const int32 val, char *const buf)
Definition: zic.c:1890
static int adjust_sign(int is_negative, int forcesign, int *signvalue)
Definition: snprintf.c:1068
static struct @131 value
bool failed
Definition: snprintf.c:116
static void leading_pad(int zpad, int *signvalue, int *padlen, PrintfTarget *target)
Definition: snprintf.c:1093
static void adjust_padlen(int minlen, int vallen, int leftjust, int *padlen)
Definition: snprintf.c:1082
static void trailing_pad(int *padlen, PrintfTarget *target)
Definition: snprintf.c:1126

◆ fmtint()

static void fmtint ( int64  value,
char  type,
int  forcesign,
int  leftjust,
int  minlen,
int  zpad,
int  precision,
int  pointflag,
PrintfTarget target 
)
static

Definition at line 839 of file snprintf.c.

References adjust_padlen(), adjust_sign(), convert(), dopr_outch(), leading_pad(), Max, trailing_pad(), and value.

Referenced by dopr(), and flushbuffer().

842 {
843  uint64 base;
844  int dosign;
845  const char *cvt = "0123456789abcdef";
846  int signvalue = 0;
847  char convert[64];
848  int vallen = 0;
849  int padlen = 0; /* amount to pad */
850  int zeropad; /* extra leading zeroes */
851 
852  switch (type)
853  {
854  case 'd':
855  case 'i':
856  base = 10;
857  dosign = 1;
858  break;
859  case 'o':
860  base = 8;
861  dosign = 0;
862  break;
863  case 'u':
864  base = 10;
865  dosign = 0;
866  break;
867  case 'x':
868  base = 16;
869  dosign = 0;
870  break;
871  case 'X':
872  cvt = "0123456789ABCDEF";
873  base = 16;
874  dosign = 0;
875  break;
876  default:
877  return; /* keep compiler quiet */
878  }
879 
880  /* Handle +/- */
881  if (dosign && adjust_sign((value < 0), forcesign, &signvalue))
882  value = -value;
883 
884  /*
885  * SUS: the result of converting 0 with an explicit precision of 0 is no
886  * characters
887  */
888  if (value == 0 && pointflag && precision == 0)
889  vallen = 0;
890  else
891  {
892  /* make integer string */
893  uint64 uvalue = (uint64) value;
894 
895  do
896  {
897  convert[vallen++] = cvt[uvalue % base];
898  uvalue = uvalue / base;
899  } while (uvalue);
900  }
901 
902  zeropad = Max(0, precision - vallen);
903 
904  adjust_padlen(minlen, vallen + zeropad, leftjust, &padlen);
905 
906  leading_pad(zpad, &signvalue, &padlen, target);
907 
908  while (zeropad-- > 0)
909  dopr_outch('0', target);
910 
911  while (vallen > 0)
912  dopr_outch(convert[--vallen], target);
913 
914  trailing_pad(&padlen, target);
915 }
static void dopr_outch(int c, PrintfTarget *target)
Definition: snprintf.c:1054
static void convert(const int32 val, char *const buf)
Definition: zic.c:1890
static int adjust_sign(int is_negative, int forcesign, int *signvalue)
Definition: snprintf.c:1068
static struct @131 value
#define Max(x, y)
Definition: c.h:851
static void leading_pad(int zpad, int *signvalue, int *padlen, PrintfTarget *target)
Definition: snprintf.c:1093
static void adjust_padlen(int minlen, int vallen, int leftjust, int *padlen)
Definition: snprintf.c:1082
static void trailing_pad(int *padlen, PrintfTarget *target)
Definition: snprintf.c:1126

◆ fmtptr()

static void fmtptr ( void *  value,
PrintfTarget target 
)
static

Definition at line 825 of file snprintf.c.

References convert(), dostr(), and PrintfTarget::failed.

Referenced by dopr(), and flushbuffer().

826 {
827  int vallen;
828  char convert[64];
829 
830  /* we rely on regular C library's sprintf to do the basic conversion */
831  vallen = sprintf(convert, "%p", value);
832  if (vallen < 0)
833  target->failed = true;
834  else
835  dostr(convert, vallen, target);
836 }
static void dostr(const char *str, int slen, PrintfTarget *target)
Definition: snprintf.c:1027
static void convert(const int32 val, char *const buf)
Definition: zic.c:1890
static struct @131 value
bool failed
Definition: snprintf.c:116

◆ fmtstr()

static void fmtstr ( char *  value,
int  leftjust,
int  minlen,
int  maxwidth,
int  pointflag,
PrintfTarget target 
)
static

Definition at line 796 of file snprintf.c.

References adjust_padlen(), dopr_outch(), dostr(), strnlen(), and trailing_pad().

Referenced by dopr(), dttofmtasc_replace(), and flushbuffer().

798 {
799  int padlen,
800  vallen; /* amount to pad */
801 
802  /*
803  * If a maxwidth (precision) is specified, we must not fetch more bytes
804  * than that.
805  */
806  if (pointflag)
807  vallen = strnlen(value, maxwidth);
808  else
809  vallen = strlen(value);
810 
811  adjust_padlen(minlen, vallen, leftjust, &padlen);
812 
813  while (padlen > 0)
814  {
815  dopr_outch(' ', target);
816  --padlen;
817  }
818 
819  dostr(value, vallen, target);
820 
821  trailing_pad(&padlen, target);
822 }
static void dopr_outch(int c, PrintfTarget *target)
Definition: snprintf.c:1054
static void dostr(const char *str, int slen, PrintfTarget *target)
Definition: snprintf.c:1027
static struct @131 value
size_t strnlen(const char *str, size_t maxlen)
Definition: strnlen.c:26
static void adjust_padlen(int minlen, int vallen, int leftjust, int *padlen)
Definition: snprintf.c:1082
static void trailing_pad(int *padlen, PrintfTarget *target)
Definition: snprintf.c:1126

◆ leading_pad()

static void leading_pad ( int  zpad,
int *  signvalue,
int *  padlen,
PrintfTarget target 
)
static

Definition at line 1093 of file snprintf.c.

References dopr_outch().

Referenced by flushbuffer(), fmtfloat(), and fmtint().

1094 {
1095  if (*padlen > 0 && zpad)
1096  {
1097  if (*signvalue)
1098  {
1099  dopr_outch(*signvalue, target);
1100  --(*padlen);
1101  *signvalue = 0;
1102  }
1103  while (*padlen > 0)
1104  {
1105  dopr_outch(zpad, target);
1106  --(*padlen);
1107  }
1108  }
1109  while (*padlen > (*signvalue != 0))
1110  {
1111  dopr_outch(' ', target);
1112  --(*padlen);
1113  }
1114  if (*signvalue)
1115  {
1116  dopr_outch(*signvalue, target);
1117  if (*padlen > 0)
1118  --(*padlen);
1119  else if (*padlen < 0)
1120  ++(*padlen);
1121  }
1122 }
static void dopr_outch(int c, PrintfTarget *target)
Definition: snprintf.c:1054

◆ pg_fprintf()

int pg_fprintf ( FILE *  stream,
const char *  fmt,
  ... 
)

Definition at line 230 of file snprintf.c.

References generate_unaccent_rules::args, and pg_vfprintf().

231 {
232  int len;
233  va_list args;
234 
235  va_start(args, fmt);
236  len = pg_vfprintf(stream, fmt, args);
237  va_end(args);
238  return len;
239 }
int pg_vfprintf(FILE *stream, const char *fmt, va_list args)
Definition: snprintf.c:208

◆ pg_printf()

int pg_printf ( const char *  fmt,
  ... 
)

Definition at line 242 of file snprintf.c.

References generate_unaccent_rules::args, and pg_vfprintf().

243 {
244  int len;
245  va_list args;
246 
247  va_start(args, fmt);
248  len = pg_vfprintf(stdout, fmt, args);
249  va_end(args);
250  return len;
251 }
int pg_vfprintf(FILE *stream, const char *fmt, va_list args)
Definition: snprintf.c:208

◆ pg_snprintf()

int pg_snprintf ( char *  str,
size_t  count,
const char *  fmt,
  ... 
)

Definition at line 167 of file snprintf.c.

References generate_unaccent_rules::args, and pg_vsnprintf().

168 {
169  int len;
170  va_list args;
171 
172  va_start(args, fmt);
173  len = pg_vsnprintf(str, count, fmt, args);
174  va_end(args);
175  return len;
176 }
int pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
Definition: snprintf.c:150

◆ pg_sprintf()

int pg_sprintf ( char *  str,
const char *  fmt,
  ... 
)

Definition at line 196 of file snprintf.c.

References generate_unaccent_rules::args, and pg_vsprintf().

197 {
198  int len;
199  va_list args;
200 
201  va_start(args, fmt);
202  len = pg_vsprintf(str, fmt, args);
203  va_end(args);
204  return len;
205 }
static int pg_vsprintf(char *str, const char *fmt, va_list args)
Definition: snprintf.c:179

◆ pg_vfprintf()

int pg_vfprintf ( FILE *  stream,
const char *  fmt,
va_list  args 
)

Definition at line 208 of file snprintf.c.

References PrintfTarget::bufend, buffer, PrintfTarget::bufptr, PrintfTarget::bufstart, dopr(), PrintfTarget::failed, flushbuffer(), PrintfTarget::nchars, and PrintfTarget::stream.

Referenced by pg_fprintf(), and pg_printf().

209 {
210  PrintfTarget target;
211  char buffer[1024]; /* size is arbitrary */
212 
213  if (stream == NULL)
214  {
215  errno = EINVAL;
216  return -1;
217  }
218  target.bufstart = target.bufptr = buffer;
219  target.bufend = buffer + sizeof(buffer) - 1;
220  target.stream = stream;
221  target.nchars = 0;
222  target.failed = false;
223  dopr(&target, fmt, args);
224  /* dump any remaining buffer contents */
225  flushbuffer(&target);
226  return target.failed ? -1 : target.nchars;
227 }
char * bufend
Definition: snprintf.c:112
char * bufstart
Definition: snprintf.c:111
static void flushbuffer(PrintfTarget *target)
Definition: snprintf.c:258
FILE * stream
Definition: snprintf.c:114
bool failed
Definition: snprintf.c:116
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
static void dopr(PrintfTarget *target, const char *format, va_list args)
Definition: snprintf.c:298
char * bufptr
Definition: snprintf.c:110

◆ pg_vsnprintf()

int pg_vsnprintf ( char *  str,
size_t  count,
const char *  fmt,
va_list  args 
)

Definition at line 150 of file snprintf.c.

References PrintfTarget::bufend, PrintfTarget::bufptr, PrintfTarget::bufstart, dopr(), PrintfTarget::failed, generate_unaccent_rules::str, and PrintfTarget::stream.

Referenced by pg_snprintf().

151 {
152  PrintfTarget target;
153 
154  if (str == NULL || count == 0)
155  return 0;
156  target.bufstart = target.bufptr = str;
157  target.bufend = str + count - 1;
158  target.stream = NULL;
159  /* target.nchars is unused in this case */
160  target.failed = false;
161  dopr(&target, fmt, args);
162  *(target.bufptr) = '\0';
163  return target.failed ? -1 : (target.bufptr - target.bufstart);
164 }
char * bufend
Definition: snprintf.c:112
char * bufstart
Definition: snprintf.c:111
FILE * stream
Definition: snprintf.c:114
bool failed
Definition: snprintf.c:116
static void dopr(PrintfTarget *target, const char *format, va_list args)
Definition: snprintf.c:298
char * bufptr
Definition: snprintf.c:110

◆ pg_vsprintf()

static int pg_vsprintf ( char *  str,
const char *  fmt,
va_list  args 
)
static

Definition at line 179 of file snprintf.c.

References PrintfTarget::bufend, PrintfTarget::bufptr, PrintfTarget::bufstart, dopr(), PrintfTarget::failed, generate_unaccent_rules::str, and PrintfTarget::stream.

Referenced by pg_sprintf().

180 {
181  PrintfTarget target;
182 
183  if (str == NULL)
184  return 0;
185  target.bufstart = target.bufptr = str;
186  target.bufend = NULL;
187  target.stream = NULL;
188  /* target.nchars is unused in this case */
189  target.failed = false;
190  dopr(&target, fmt, args);
191  *(target.bufptr) = '\0';
192  return target.failed ? -1 : (target.bufptr - target.bufstart);
193 }
char * bufend
Definition: snprintf.c:112
char * bufstart
Definition: snprintf.c:111
FILE * stream
Definition: snprintf.c:114
bool failed
Definition: snprintf.c:116
static void dopr(PrintfTarget *target, const char *format, va_list args)
Definition: snprintf.c:298
char * bufptr
Definition: snprintf.c:110

◆ trailing_pad()

static void trailing_pad ( int *  padlen,
PrintfTarget target 
)
static

Definition at line 1126 of file snprintf.c.

References dopr_outch().

Referenced by flushbuffer(), fmtchar(), fmtfloat(), fmtint(), and fmtstr().

1127 {
1128  while (*padlen < 0)
1129  {
1130  dopr_outch(' ', target);
1131  ++(*padlen);
1132  }
1133 }
static void dopr_outch(int c, PrintfTarget *target)
Definition: snprintf.c:1054