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 1080 of file snprintf.c.

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

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

◆ adjust_sign()

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

Definition at line 1066 of file snprintf.c.

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

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

◆ dopr()

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

Definition at line 298 of file snprintf.c.

References 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  fmtstr(strvalue, leftjust, fieldwidth, precision, pointflag,
749  target);
750  break;
751  case 'p':
752  /* fieldwidth/leftjust are ignored ... */
753  if (have_dollar)
754  strvalue = argvalues[fmtpos].cptr;
755  else
756  strvalue = va_arg(args, char *);
757  fmtptr((void *) strvalue, target);
758  break;
759  case 'e':
760  case 'E':
761  case 'f':
762  case 'g':
763  case 'G':
764  if (!have_star)
765  {
766  if (pointflag)
767  precision = accum;
768  else
769  fieldwidth = accum;
770  }
771  if (have_dollar)
772  fvalue = argvalues[fmtpos].d;
773  else
774  fvalue = va_arg(args, double);
775  fmtfloat(fvalue, ch, forcesign, leftjust,
776  fieldwidth, zpad,
777  precision, pointflag,
778  target);
779  break;
780  case '%':
781  dopr_outch('%', target);
782  break;
783  }
784  }
785 
786  return;
787 
788 bad_format:
789  errno = EINVAL;
790  target->failed = true;
791 }
static void dopr_outch(int c, PrintfTarget *target)
Definition: snprintf.c:1052
static void fmtptr(void *value, PrintfTarget *target)
Definition: snprintf.c:823
static void fmtint(int64 value, char type, int forcesign, int leftjust, int minlen, int zpad, int precision, int pointflag, PrintfTarget *target)
Definition: snprintf.c:837
static void fmtchar(int value, int leftjust, int minlen, PrintfTarget *target)
Definition: snprintf.c:916
#define MemSet(start, val, len)
Definition: c.h:863
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:794
#define Max(x, y)
Definition: c.h:806
PrintfArgType
Definition: snprintf.c:125
#define NL_ARGMAX
Definition: snprintf.c:47
int i
static char format
Definition: pg_basebackup.c:81
static void fmtfloat(double value, char type, int forcesign, int leftjust, int minlen, int zpad, int precision, int pointflag, PrintfTarget *target)
Definition: snprintf.c:934

◆ dopr_outch()

static void dopr_outch ( int  c,
PrintfTarget target 
)
static

Definition at line 1052 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().

1053 {
1054  if (target->bufend != NULL && target->bufptr >= target->bufend)
1055  {
1056  /* buffer full, can we dump to stream? */
1057  if (target->stream == NULL)
1058  return; /* no, lose the data */
1059  flushbuffer(target);
1060  }
1061  *(target->bufptr++) = c;
1062 }
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 1025 of file snprintf.c.

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

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

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

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

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

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

◆ 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 934 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().

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

◆ 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 837 of file snprintf.c.

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

Referenced by dopr(), and flushbuffer().

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

◆ fmtptr()

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

Definition at line 823 of file snprintf.c.

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

Referenced by dopr(), and flushbuffer().

824 {
825  int vallen;
826  char convert[64];
827 
828  /* we rely on regular C library's sprintf to do the basic conversion */
829  vallen = sprintf(convert, "%p", value);
830  if (vallen < 0)
831  target->failed = true;
832  else
833  dostr(convert, vallen, target);
834 }
static void dostr(const char *str, int slen, PrintfTarget *target)
Definition: snprintf.c:1025
static void convert(const int32 val, char *const buf)
Definition: zic.c:1812
static struct @121 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 794 of file snprintf.c.

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

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

796 {
797  int padlen,
798  vallen; /* amount to pad */
799 
800  /*
801  * If a maxwidth (precision) is specified, we must not fetch more bytes
802  * than that.
803  */
804  if (pointflag)
805  vallen = strnlen(value, maxwidth);
806  else
807  vallen = strlen(value);
808 
809  adjust_padlen(minlen, vallen, leftjust, &padlen);
810 
811  while (padlen > 0)
812  {
813  dopr_outch(' ', target);
814  --padlen;
815  }
816 
817  dostr(value, vallen, target);
818 
819  trailing_pad(&padlen, target);
820 }
static void dopr_outch(int c, PrintfTarget *target)
Definition: snprintf.c:1052
static void dostr(const char *str, int slen, PrintfTarget *target)
Definition: snprintf.c:1025
static struct @121 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:1080
static void trailing_pad(int *padlen, PrintfTarget *target)
Definition: snprintf.c:1124

◆ leading_pad()

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

Definition at line 1091 of file snprintf.c.

References dopr_outch().

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

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

◆ 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:214
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 1124 of file snprintf.c.

References dopr_outch().

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

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