w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

snprintf.c
Go to the documentation of this file.
1 /*
2  * snprintf.c
3  * ripped from rsync sources by pts@inf.bme.hu at Thu Mar 7 18:16:00 CET 2002
4  * ripped from reTCP sources by pts@fazekas.hu at Tue Jun 11 14:47:01 CEST 2002
5  *
6  * Why does this .c file rock?
7  *
8  * -- minimal dependencies: only <stdarg.h> is included
9  * -- minimal dependencies: not even -lm is required
10  * -- can print floating point numbers
11  * -- can print `long long' and `long double'
12  * -- C99 semantics (NULL arg for vsnprintf OK, always returns the length
13  * that would have been printed)
14  * -- provides all vsnprintf(), snprintf(), vasprintf(), asprintf()
15  */
16 
17 /**** pts: sam2p-specific defines ****/
18 #include "snprintf.h"
19 /* #include <stdarg.h> -- from snprintf.h */
20 #define P_CONST PTS_const
21 #ifdef NULL /* as on Mac OS/X 10.5.7 <stdlib.h> */
22 # undef NULL
23 #endif
24 #define NULL ((void*)0)
25 #ifdef __cplusplus
26 # define malloc ::operator new
27 #else
28 # include <stdlib.h> /* malloc() */
29 #endif
30 #define size_t slen_t /* normally defined in <sys/types.h> */
31 #define sizeret_t slen_t /* normally: int, unsigned */
32 #undef HAVE_LONG_DOUBLE
33 #undef HAVE_LONG_LONG
34 #undef HAVE_C99_VSNPRINTF /* force local implementation */
35 #undef HAVE_ASPRINTF
36 #undef HAVE_VASPRINTF
37 #undef TEST_SNPRINTF
38 #undef DEBUG_SNPRINTF
39 #define NEED_SPRINTF 1
40 #define vsnprintf fixup_vsnprintf
41 #define snprintf fixup_snprintf
42 #define vasprintf fixup_vasprintf
43 #define asprintf fixup_asprintf
44 #define sprintf fixup_sprintf
45 typedef slen_t ret_t;
46 
47 /* vvv repeat prototypes in snprintf.h */
49 EXTERN_C sizeret_t fixup_snprintf(char *str,size_t count,P_CONST char *fmt,...);
53 
54 /*
55  * Copyright Patrick Powell 1995
56  * This code is based on code written by Patrick Powell (papowell@astart.com)
57  * It may be used for any purpose as long as this notice remains intact
58  * on all source code distributions
59  */
60 
61 /**************************************************************
62  * Original:
63  * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
64  * A bombproof version of doprnt (dopr) included.
65  * Sigh. This sort of thing is always nasty do deal with. Note that
66  * the version here does not include floating point...
67  *
68  * snprintf() is used instead of sprintf() as it does limit checks
69  * for string length. This covers a nasty loophole.
70  *
71  * The other functions are there to prevent NULL pointers from
72  * causing nast effects.
73  *
74  * More Recently:
75  * Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
76  * This was ugly. It is still ugly. I opted out of floating point
77  * numbers, but the formatter understands just about everything
78  * from the normal C string format, at least as far as I can tell from
79  * the Solaris 2.5 printf(3S) man page.
80  *
81  * Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
82  * Ok, added some minimal floating point support, which means this
83  * probably requires libm on most operating systems. Don't yet
84  * support the exponent (e,E) and sigfig (g,G). Also, fmtint()
85  * was pretty badly broken, it just wasn't being exercised in ways
86  * which showed it, so that's been fixed. Also, formated the code
87  * to mutt conventions, and removed dead code left over from the
88  * original. Also, there is now a builtin-test, just compile with:
89  * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
90  * and run snprintf for results.
91  *
92  * Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
93  * The PGP code was using unsigned hexadecimal formats.
94  * Unfortunately, unsigned formats simply didn't work.
95  *
96  * Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
97  * The original code assumed that both snprintf() and vsnprintf() were
98  * missing. Some systems only have snprintf() but not vsnprintf(), so
99  * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
100  *
101  * Andrew Tridgell (tridge@samba.org) Oct 1998
102  * fixed handling of %.0f
103  * added test for HAVE_LONG_DOUBLE
104  *
105  * tridge@samba.org, idra@samba.org, April 2001
106  * got rid of fcvt code (twas buggy and made testing harder)
107  * added C99 semantics
108  *
109  **************************************************************/
110 
111 
112 #if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF)
113 /* only include stdio.h if we are not re-defining snprintf or vsnprintf */
114 #include <stdio.h>
115  /* make the compiler happy with an empty file */
116  void dummy_snprintf(void) {}
117 #else
118 
119 #if HAVE_LONG_DOUBLE && NEED_LONG_DOUBLE
120 #define LDOUBLE long double
121 #else
122 #define LDOUBLE double
123 #endif
124 
125 #if HAVE_LONG_LONG && NEED_LONG_LONG
126 #define LLONG long long
127 #else
128 #define LLONG long
129 #endif
130 
131 static size_t dopr(char *buffer, size_t maxlen, P_CONST char *format,
132  va_list args);
133 static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
134  char *value, int flags, int min, int max);
135 static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
136  long value, int base, int min, int max, int flags);
137 static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
138  LDOUBLE fvalue, int min, int max, int flags);
139 static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
140 
141 /*
142  * dopr(): poor man's version of doprintf
143  */
144 
145 /* format read states */
146 #define DP_S_DEFAULT 0
147 #define DP_S_FLAGS 1
148 #define DP_S_MIN 2
149 #define DP_S_DOT 3
150 #define DP_S_MAX 4
151 #define DP_S_MOD 5
152 #define DP_S_CONV 6
153 #define DP_S_DONE 7
154 
155 /* format flags - Bits */
156 #define DP_F_MINUS (1 << 0)
157 #define DP_F_PLUS (1 << 1)
158 #define DP_F_SPACE (1 << 2)
159 #define DP_F_NUM (1 << 3)
160 #define DP_F_ZERO (1 << 4)
161 #define DP_F_UP (1 << 5)
162 #define DP_F_UNSIGNED (1 << 6)
163 
164 /* Conversion Flags */
165 #define DP_C_SHORT 1
166 #define DP_C_LONG 2
167 #define DP_C_LDOUBLE 3
168 #define DP_C_LLONG 4
169 
170 #define char_to_int(p) ((p)- '0')
171 #ifndef MAX
172 #define MAX(p,q) (((p) >= (q)) ? (p) : (q))
173 #endif
174 
175 /**** pts ****/
176 #undef isdigit
177 #define isdigit(c) ((unsigned char)((c)-'0')<=(unsigned char)('9'-'0'))
178 
179 static size_t dopr(char *buffer, size_t maxlen, P_CONST char *format, va_list args)
180 {
181  char ch;
182  LLONG value;
183  LDOUBLE fvalue;
184  char *strvalue;
185  int min;
186  int max;
187  int state;
188  int flags;
189  int cflags;
190  size_t currlen;
191 
193  currlen = flags = cflags = min = 0;
194  max = -1;
195  ch = *format++;
196 
197  while (state != DP_S_DONE) {
198  if (ch == '\0')
199  state = DP_S_DONE;
200 
201  switch(state) {
202  case DP_S_DEFAULT:
203  if (ch == '%')
204  state = DP_S_FLAGS;
205  else
206  dopr_outch (buffer, &currlen, maxlen, ch);
207  ch = *format++;
208  break;
209  case DP_S_FLAGS:
210  switch (ch) {
211  case '-':
212  flags |= DP_F_MINUS;
213  ch = *format++;
214  break;
215  case '+':
216  flags |= DP_F_PLUS;
217  ch = *format++;
218  break;
219  case ' ':
220  flags |= DP_F_SPACE;
221  ch = *format++;
222  break;
223  case '#':
224  flags |= DP_F_NUM;
225  ch = *format++;
226  break;
227  case '0':
228  flags |= DP_F_ZERO;
229  ch = *format++;
230  break;
231  default:
232  state = DP_S_MIN;
233  break;
234  }
235  break;
236  case DP_S_MIN:
237  if (isdigit((unsigned char)ch)) {
238  min = 10*min + char_to_int (ch);
239  ch = *format++;
240  } else if (ch == '*') {
241  min = va_arg (args, int);
242  ch = *format++;
243  state = DP_S_DOT;
244  } else {
245  state = DP_S_DOT;
246  }
247  break;
248  case DP_S_DOT:
249  if (ch == '.') {
250  state = DP_S_MAX;
251  ch = *format++;
252  } else {
253  state = DP_S_MOD;
254  }
255  break;
256  case DP_S_MAX:
257  if (isdigit((unsigned char)ch)) {
258  if (max < 0)
259  max = 0;
260  max = 10*max + char_to_int (ch);
261  ch = *format++;
262  } else if (ch == '*') {
263  max = va_arg (args, int);
264  ch = *format++;
265  state = DP_S_MOD;
266  } else {
267  state = DP_S_MOD;
268  }
269  break;
270  case DP_S_MOD:
271  switch (ch) {
272  case 'h':
273  cflags = DP_C_SHORT;
274  ch = *format++;
275  break;
276  case 'l':
277  cflags = DP_C_LONG;
278  ch = *format++;
279  if (ch == 'l') { /* It's a long long */
280  cflags = DP_C_LLONG;
281  ch = *format++;
282  }
283  break;
284  case 'L':
285  cflags = DP_C_LDOUBLE;
286  ch = *format++;
287  break;
288  default:
289  break;
290  }
291  state = DP_S_CONV;
292  break;
293  case DP_S_CONV:
294  switch (ch) {
295  case 'd':
296  case 'i':
297  if (cflags == DP_C_SHORT)
298  value = va_arg (args, int);
299  else if (cflags == DP_C_LONG)
300  value = va_arg (args, long int);
301  else if (cflags == DP_C_LLONG)
302  value = va_arg (args, LLONG);
303  else
304  value = va_arg (args, int);
305  fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
306  break;
307  case 'o':
308  flags |= DP_F_UNSIGNED;
309  if (cflags == DP_C_SHORT)
310  value = va_arg (args, unsigned int);
311  else if (cflags == DP_C_LONG)
312  value = (long)va_arg (args, unsigned long int);
313  else if (cflags == DP_C_LLONG)
314  value = (long)va_arg (args, unsigned LLONG);
315  else
316  value = (long)va_arg (args, unsigned int);
317  fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
318  break;
319  case 'u':
320  flags |= DP_F_UNSIGNED;
321  if (cflags == DP_C_SHORT)
322  value = va_arg (args, unsigned int);
323  else if (cflags == DP_C_LONG)
324  value = (long)va_arg (args, unsigned long int);
325  else if (cflags == DP_C_LLONG)
326  value = (LLONG)va_arg (args, unsigned LLONG);
327  else
328  value = (long)va_arg (args, unsigned int);
329  fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
330  break;
331  case 'X':
332  flags |= DP_F_UP;
333  case 'x':
334  flags |= DP_F_UNSIGNED;
335  if (cflags == DP_C_SHORT)
336  value = va_arg (args, unsigned int);
337  else if (cflags == DP_C_LONG)
338  value = (long)va_arg (args, unsigned long int);
339  else if (cflags == DP_C_LLONG)
340  value = (LLONG)va_arg (args, unsigned LLONG);
341  else
342  value = (long)va_arg (args, unsigned int);
343  fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
344  break;
345  case 'f':
346  if (cflags == DP_C_LDOUBLE)
347  fvalue = va_arg (args, LDOUBLE);
348  else
349  fvalue = va_arg (args, double);
350  /* um, floating point? */
351  fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
352  break;
353  case 'E':
354  flags |= DP_F_UP;
355  case 'e':
356  if (cflags == DP_C_LDOUBLE)
357  fvalue = va_arg (args, LDOUBLE);
358  else
359  fvalue = va_arg (args, double);
360  break;
361  case 'G':
362  flags |= DP_F_UP;
363  case 'g':
364  if (cflags == DP_C_LDOUBLE)
365  fvalue = va_arg (args, LDOUBLE);
366  else
367  fvalue = va_arg (args, double);
368  break;
369  case 'c':
370  dopr_outch (buffer, &currlen, maxlen, (char)va_arg (args, int));
371  break;
372  case 's':
373  strvalue = va_arg (args, char *);
374  if (max == -1) {
375  /**** pts ****/
376  for (max = 0; strvalue[max]; ++max); /* strlen */
377  }
378  if (min > 0 && max >= 0 && min > max) max = min;
379  fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
380  break;
381  case 'p':
382  strvalue = (char*)(va_arg (args, void *));
383  fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
384  break;
385  case 'n':
386  if (cflags == DP_C_SHORT) {
387  short int *num;
388  num = va_arg (args, short int *);
389  *num = currlen;
390  } else if (cflags == DP_C_LONG) {
391  long int *num;
392  num = va_arg (args, long int *);
393  *num = (long int)currlen;
394  } else if (cflags == DP_C_LLONG) {
395  LLONG *num;
396  num = va_arg (args, LLONG *);
397  *num = (LLONG)currlen;
398  } else {
399  int *num;
400  num = va_arg (args, int *);
401  *num = currlen;
402  }
403  break;
404  case '%':
405  dopr_outch (buffer, &currlen, maxlen, ch);
406  break;
407  case 'w':
408  /* not supported yet, treat as next char */
409  ch = *format++;
410  break;
411  default:
412  /* Unknown, skip */
413  break;
414  }
415  ch = *format++;
417  flags = cflags = min = 0;
418  max = -1;
419  break;
420  case DP_S_DONE:
421  break;
422  default:
423  /* hmm? */
424  break; /* some picky compilers need this */
425  }
426  }
427  if (maxlen != 0) {
428  if (currlen < maxlen - 1)
429  buffer[currlen] = '\0';
430  else if (maxlen > 0)
431  buffer[maxlen - 1] = '\0';
432  }
433 
434  return currlen;
435 }
436 
437 static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
438  char *value, int flags, int min, int max)
439 {
440  int padlen, strln; /* amount to pad */
441  int cnt = 0;
442 
443 #ifdef DEBUG_SNPRINTF
444  printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value);
445 #endif
446  if (value == 0) {
447  value = (char*)"<NULL>";
448  }
449 
450  for (strln = 0; value[strln]; ++strln); /* strlen */
451  padlen = min - strln;
452  if (padlen < 0)
453  padlen = 0;
454  if (flags & DP_F_MINUS)
455  padlen = -padlen; /* Left Justify */
456 
457  while ((padlen > 0) && (cnt < max)) {
458  dopr_outch (buffer, currlen, maxlen, ' ');
459  --padlen;
460  ++cnt;
461  }
462  while (*value && (cnt < max)) {
463  dopr_outch (buffer, currlen, maxlen, *value++);
464  ++cnt;
465  }
466  while ((padlen < 0) && (cnt < max)) {
467  dopr_outch (buffer, currlen, maxlen, ' ');
468  ++padlen;
469  ++cnt;
470  }
471 }
472 
473 /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
474 
475 static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
476  long value, int base, int min, int max, int flags)
477 {
478  int signvalue = 0;
479  unsigned long uvalue;
480  char convert[20];
481  int place = 0;
482  int spadlen = 0; /* amount to space pad */
483  int zpadlen = 0; /* amount to zero pad */
484  int caps = 0;
485 
486  if (max < 0)
487  max = 0;
488 
489  uvalue = value;
490 
491  if(!(flags & DP_F_UNSIGNED)) {
492  if( value < 0 ) {
493  signvalue = '-';
494  uvalue = -value;
495  } else {
496  if (flags & DP_F_PLUS) /* Do a sign (+/i) */
497  signvalue = '+';
498  else if (flags & DP_F_SPACE)
499  signvalue = ' ';
500  }
501  }
502 
503  if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
504 
505  do {
506  convert[place++] =
507  (caps? "0123456789ABCDEF":"0123456789abcdef")
508  [uvalue % (unsigned)base ];
509  uvalue = (uvalue / (unsigned)base );
510  } while(uvalue && (place < 20));
511  if (place == 20) place--;
512  convert[place] = 0;
513 
514  zpadlen = max - place;
515  spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
516  if (zpadlen < 0) zpadlen = 0;
517  if (spadlen < 0) spadlen = 0;
518  if (flags & DP_F_ZERO) {
519  zpadlen = MAX(zpadlen, spadlen);
520  spadlen = 0;
521  }
522  if (flags & DP_F_MINUS)
523  spadlen = -spadlen; /* Left Justifty */
524 
525 #ifdef DEBUG_SNPRINTF
526  printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
527  zpadlen, spadlen, min, max, place);
528 #endif
529 
530  /* Spaces */
531  while (spadlen > 0) {
532  dopr_outch (buffer, currlen, maxlen, ' ');
533  --spadlen;
534  }
535 
536  /* Sign */
537  if (signvalue)
538  dopr_outch (buffer, currlen, maxlen, (char)signvalue); /* pacify VC6.0 */
539 
540  /* Zeros */
541  if (zpadlen > 0) {
542  while (zpadlen > 0) {
543  dopr_outch (buffer, currlen, maxlen, '0');
544  --zpadlen;
545  }
546  }
547 
548  /* Digits */
549  while (place > 0)
550  dopr_outch (buffer, currlen, maxlen, convert[--place]);
551 
552  /* Left Justified spaces */
553  while (spadlen < 0) {
554  dopr_outch (buffer, currlen, maxlen, ' ');
555  ++spadlen;
556  }
557 }
558 
560 {
561  LDOUBLE result = value;
562 
563  if (value < 0)
564  result = -value;
565 
566  return result;
567 }
568 
569 static LDOUBLE POW10(int exp)
570 {
571  LDOUBLE result = 1;
572 
573  while (exp) {
574  result *= 10;
575  exp--;
576  }
577 
578  return result;
579 }
580 
582 {
583  LLONG intpart;
584 
585  intpart = (LLONG)value;
586  value = value - intpart;
587  if (value >= 0.5) intpart++;
588 
589  return intpart;
590 }
591 
592 /* a replacement for modf that doesn't need the math library. Should
593  be portable, but slow */
594 static double my_modf(double x0, double *iptr)
595 {
596  int i;
597  long l=0;
598  double x = x0;
599  double f = 1.0;
600 
601  for (i=0;i<100;i++) {
602  l = (long)x;
603  if (l <= (x+1) && l >= (x-1)) break;
604  x *= 0.1;
605  f *= 10.0;
606  }
607 
608  if (i == 100) {
609  /* yikes! the number is beyond what we can handle. What do we do? */
610  (*iptr) = 0;
611  return 0;
612  }
613 
614  if (i != 0) {
615  double i2;
616  double ret;
617 
618  ret = my_modf(x0-l*f, &i2);
619  (*iptr) = l*f + i2;
620  return ret;
621  }
622 
623  (*iptr) = l;
624  return x - (*iptr);
625 }
626 
627 
628 static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
629  LDOUBLE fvalue, int min, int max, int flags)
630 {
631  int signvalue = 0;
632  double ufvalue;
633  char iconvert[311];
634  char fconvert[311];
635  int iplace = 0;
636  int fplace = 0;
637  int padlen = 0; /* amount to pad */
638  int zpadlen = 0;
639  int caps = 0;
640  int index;
641  double intpart;
642  double fracpart;
643  double temp;
644 
645  /*
646  * AIX manpage says the default is 0, but Solaris says the default
647  * is 6, and sprintf on AIX defaults to 6
648  */
649  if (max < 0)
650  max = 6;
651 
652  ufvalue = abs_val (fvalue);
653 
654  if (fvalue < 0) {
655  signvalue = '-';
656  } else {
657  if (flags & DP_F_PLUS) { /* Do a sign (+/i) */
658  signvalue = '+';
659  } else {
660  if (flags & DP_F_SPACE)
661  signvalue = ' ';
662  }
663  }
664 
665 #if 0
666  if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
667 #endif
668 
669 #if 0
670  if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */
671 #endif
672 
673  /*
674  * Sorry, we only support 16 digits past the decimal because of our
675  * conversion method
676  */
677  if (max > 16)
678  max = 16;
679 
680  /* We "cheat" by converting the fractional part to integer by
681  * multiplying by a factor of 10
682  */
683 
684  temp = ufvalue;
685  my_modf(temp, &intpart);
686 
687  fracpart = ROUND((POW10(max)) * (ufvalue - intpart));
688 
689  if (fracpart >= POW10(max)) {
690  intpart++;
691  fracpart -= POW10(max);
692  }
693 
694 
695  /* Convert integer part */
696  do {
697  temp = intpart;
698  my_modf(intpart*0.1, &intpart);
699  temp = temp*0.1;
700  index = (int) ((temp -intpart +0.05)* 10.0);
701  /* index = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
702  /* printf ("%llf, %f, %x\n", temp, intpart, index); */
703  iconvert[iplace++] =
704  (caps? "0123456789ABCDEF":"0123456789abcdef")[index];
705  } while (intpart && (iplace < 311));
706  if (iplace == 311) iplace--;
707  iconvert[iplace] = 0;
708 
709  /* Convert fractional part */
710  if (fracpart)
711  {
712  do {
713  temp = fracpart;
714  my_modf(fracpart*0.1, &fracpart);
715  temp = temp*0.1;
716  index = (int) ((temp -fracpart +0.05)* 10.0);
717  /* index = (int) ((((temp/10) -fracpart) +0.05) *10); */
718  /* printf ("%lf, %lf, %ld\n", temp, fracpart, index); */
719  fconvert[fplace++] =
720  (caps? "0123456789ABCDEF":"0123456789abcdef")[index];
721  } while(fracpart && (fplace < 311));
722  if (fplace == 311) fplace--;
723  }
724  fconvert[fplace] = 0;
725 
726  /* -1 for decimal point, another -1 if we are printing a sign */
727  padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
728  zpadlen = max - fplace;
729  if (zpadlen < 0) zpadlen = 0;
730  if (padlen < 0)
731  padlen = 0;
732  if (flags & DP_F_MINUS)
733  padlen = -padlen; /* Left Justifty */
734 
735  if ((flags & DP_F_ZERO) && (padlen > 0)) {
736  if (signvalue) {
737  dopr_outch (buffer, currlen, maxlen, (char)signvalue);
738  --padlen;
739  signvalue = 0;
740  }
741  while (padlen > 0) {
742  dopr_outch (buffer, currlen, maxlen, '0');
743  --padlen;
744  }
745  }
746  while (padlen > 0) {
747  dopr_outch (buffer, currlen, maxlen, ' ');
748  --padlen;
749  }
750  if (signvalue)
751  dopr_outch (buffer, currlen, maxlen, (char)signvalue);
752 
753  while (iplace > 0)
754  dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
755 
756 #ifdef DEBUG_SNPRINTF
757  printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
758 #endif
759 
760  /*
761  * Decimal point. This should probably use locale to find the correct
762  * char to print out.
763  */
764  if (max > 0) {
765  dopr_outch (buffer, currlen, maxlen, '.');
766 
767  while (fplace > 0)
768  dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
769  }
770 
771  while (zpadlen > 0) {
772  dopr_outch (buffer, currlen, maxlen, '0');
773  --zpadlen;
774  }
775 
776  while (padlen < 0) {
777  dopr_outch (buffer, currlen, maxlen, ' ');
778  ++padlen;
779  }
780 }
781 
782 static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
783 {
784  if (*currlen < maxlen) {
785  buffer[(*currlen)] = c;
786  }
787  (*currlen)++;
788 }
789 
790 #if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
791  sizeret_t vsnprintf (char *str, size_t count, P_CONST char *fmt, va_list args)
792 {
793  return dopr(str, count, fmt, args);
794 }
795 #endif
796 
797 #if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
798  sizeret_t snprintf(char *str,size_t count,P_CONST char *fmt,...)
799 {
800  size_t ret;
801  va_list ap;
802 
803  PTS_va_start(ap, fmt);
804  ret = vsnprintf(str, count, fmt, ap);
805  va_end(ap);
806  return ret;
807 }
808 #endif
809 
810 #endif
811 
812 #ifndef HAVE_VASPRINTF
814 {
815  size_t ret;
816 
817  ret = vsnprintf((char*)NULL, 0, format, ap);
818  if (ret+1 <= 1) return ret; /* pts: bit of old unsigned trick... */
819 
820  if (NULLP==(*ptr = (char *)malloc(ret+1))) return (sizeret_t)-1;
821  ret = vsnprintf(*ptr, ret+1, format, ap);
822 
823  return ret;
824 }
825 #endif
826 
827 
828 #ifndef HAVE_ASPRINTF
829  sizeret_t asprintf(char **ptr, P_CONST char *format, ...)
830 {
831  va_list ap;
832  sizeret_t ret;
833 
835  ret = vasprintf(ptr, format, ap);
836  va_end(ap);
837 
838  return ret;
839 }
840 #endif
841 
842 /**** pts ****/
843 #ifdef NEED_SPRINTF
844  sizeret_t sprintf(char *ptr, P_CONST char *format, ...)
845 {
846  va_list ap;
847  sizeret_t ret;
848 
850 #if 0
851  ret = vsnprintf(NULL, 0, format, ap);
852  if (ret+1 <= 1) return ret;
853  ret = vsnprintf(ptr, ret, format, ap);
854 #else
855  ret = vsnprintf(ptr, (slen_t)-1, format, ap);
856 #endif
857  va_end(ap);
858 
859  return ret;
860 }
861 #endif
862 
863 #ifdef TEST_SNPRINTF
864 
865  sizeret_t sprintf(char *str,P_CONST char *fmt,...);
866 
867  int main (void)
868 {
869  char buf1[1024];
870  char buf2[1024];
871  char *fp_fmt[] = {
872  "%1.1f",
873  "%-1.5f",
874  "%1.5f",
875  "%123.9f",
876  "%10.5f",
877  "% 10.5f",
878  "%+22.9f",
879  "%+4.9f",
880  "%01.3f",
881  "%4f",
882  "%3.1f",
883  "%3.2f",
884  "%.0f",
885  "%f",
886  "-16.16f",
887  NULL
888  };
889  double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
890  0.9996, 1.996, 4.136, 0};
891  char *int_fmt[] = {
892  "%-1.5d",
893  "%1.5d",
894  "%123.9d",
895  "%5.5d",
896  "%10.5d",
897  "% 10.5d",
898  "%+22.33d",
899  "%01.3d",
900  "%4d",
901  "%d",
902  NULL
903  };
904  long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
905  char *str_fmt[] = {
906  "10.5s",
907  "5.10s",
908  "10.1s",
909  "0.10s",
910  "10.0s",
911  "1.10s",
912  "%s",
913  "%.1s",
914  "%.10s",
915  "%10s",
916  NULL
917  };
918  char *str_vals[] = {"hello", "a", "", "a longer string", NULL};
919  int x, y;
920  int fail = 0;
921  int num = 0;
922 
923  printf ("Testing snprintf format codes against system sprintf...\n");
924 
925  for (x = 0; fp_fmt[x] ; x++) {
926  for (y = 0; fp_nums[y] != 0 ; y++) {
927  int l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]);
928  int l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]);
929  sprintf (buf2, fp_fmt[x], fp_nums[y]);
930  if (strcmp (buf1, buf2)) {
931  printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
932  fp_fmt[x], buf1, buf2);
933  fail++;
934  }
935  if (l1 != l2) {
936  printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, fp_fmt[x]);
937  fail++;
938  }
939  num++;
940  }
941  }
942 
943  for (x = 0; int_fmt[x] ; x++) {
944  for (y = 0; int_nums[y] != 0 ; y++) {
945  int l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]);
946  int l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]);
947  sprintf (buf2, int_fmt[x], int_nums[y]);
948  if (strcmp (buf1, buf2)) {
949  printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
950  int_fmt[x], buf1, buf2);
951  fail++;
952  }
953  if (l1 != l2) {
954  printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, int_fmt[x]);
955  fail++;
956  }
957  num++;
958  }
959  }
960 
961  for (x = 0; str_fmt[x] ; x++) {
962  for (y = 0; str_vals[y] != 0 ; y++) {
963  int l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]);
964  int l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]);
965  sprintf (buf2, str_fmt[x], str_vals[y]);
966  if (strcmp (buf1, buf2)) {
967  printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
968  str_fmt[x], buf1, buf2);
969  fail++;
970  }
971  if (l1 != l2) {
972  printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, str_fmt[x]);
973  fail++;
974  }
975  num++;
976  }
977  }
978 
979  printf ("%d tests failed out of %d.\n", fail, num);
980 
981  printf("seeing how many digits we support\n");
982  {
983  double v0 = 0.12345678901234567890123456789012345678901;
984  for (x=0; x<100; x++) {
985  snprintf(buf1, sizeof(buf1), "%1.1f", v0*pow(10, x));
986  sprintf(buf2, "%1.1f", v0*pow(10, x));
987  if (strcmp(buf1, buf2)) {
988  printf("we seem to support %d digits\n", x-1);
989  break;
990  }
991  }
992  }
993 
994  return 0;
995 }
996 #endif /* SNPRINTF_TEST */
double __cdecl exp(double _X)
double __cdecl pow(double _X, double _Y)
#define state
Definition: aptex-macros.h:996
#define convert
Definition: aptex-macros.h:489
#define count(a)
Definition: aptex-macros.h:781
#define x0
#define EXTERN_C
Definition: cgif.c:44
#define PTS_va_start(ap, fmt)
Definition: config2.h:119
unsigned int slen_t
Definition: config2.h:37
#define NULLP
Definition: config2.h:66
#define ap
int strcmp()
Definition: coll.cpp:143
int printf()
char * temp
Definition: dvidvi.c:137
mpz_t * f
Definition: gen-fib.c:34
#define v0
#define c(n)
Definition: gpos-common.c:150
int base
Definition: gsftopk.c:1502
small capitals from c petite p scientific i
Definition: afcover.h:80
kerning y
Definition: ttdriver.c:212
int num
Definition: disdvi.c:621
static int ret
Definition: convert.c:72
#define malloc
Definition: alloca.c:91
#define vsnprintf
Definition: snprintf.c:40
#define DP_S_DEFAULT
Definition: snprintf.c:146
#define NULL
Definition: snprintf.c:24
slen_t fixup_snprintf(char *str, slen_t count, const char *fmt,...)
Definition: snprintf.c:798
#define DP_C_LDOUBLE
Definition: snprintf.c:167
static void fmtint(char *buffer, slen_t *currlen, slen_t maxlen, long value, int base, int min, int max, int flags)
Definition: snprintf.c:475
#define DP_C_LLONG
Definition: snprintf.c:168
#define DP_S_DOT
Definition: snprintf.c:149
slen_t fixup_vsnprintf(char *str, slen_t count, const char *fmt, va_list args)
Definition: snprintf.c:791
#define MAX(p, q)
Definition: snprintf.c:172
#define DP_F_MINUS
Definition: snprintf.c:156
#define sprintf
Definition: snprintf.c:44
#define DP_F_UNSIGNED
Definition: snprintf.c:162
#define DP_S_CONV
Definition: snprintf.c:152
#define asprintf
Definition: snprintf.c:43
slen_t fixup_sprintf(char *ptr, const char *format,...)
Definition: snprintf.c:844
static long ROUND(double value)
Definition: snprintf.c:581
#define DP_F_PLUS
Definition: snprintf.c:157
static double POW10(int exp)
Definition: snprintf.c:569
#define LDOUBLE
Definition: snprintf.c:122
#define DP_F_SPACE
Definition: snprintf.c:158
#define isdigit(c)
Definition: snprintf.c:177
#define DP_S_MIN
Definition: snprintf.c:148
static double abs_val(double value)
Definition: snprintf.c:559
#define DP_S_MAX
Definition: snprintf.c:150
#define DP_C_SHORT
Definition: snprintf.c:165
#define snprintf
Definition: snprintf.c:41
#define DP_S_DONE
Definition: snprintf.c:153
slen_t ret_t
Definition: snprintf.c:45
#define DP_S_MOD
Definition: snprintf.c:151
#define sizeret_t
Definition: snprintf.c:31
#define DP_S_FLAGS
Definition: snprintf.c:147
#define char_to_int(p)
Definition: snprintf.c:170
static slen_t dopr(char *buffer, slen_t maxlen, const char *format, va_list args)
Definition: snprintf.c:179
slen_t fixup_vasprintf(char **ptr, const char *format, va_list ap)
Definition: snprintf.c:813
static void fmtstr(char *buffer, slen_t *currlen, slen_t maxlen, char *value, int flags, int min, int max)
Definition: snprintf.c:437
static void dopr_outch(char *buffer, slen_t *currlen, slen_t maxlen, char c)
Definition: snprintf.c:782
#define P_CONST
Definition: snprintf.c:20
#define DP_C_LONG
Definition: snprintf.c:166
#define vasprintf
Definition: snprintf.c:42
#define DP_F_ZERO
Definition: snprintf.c:160
#define DP_F_UP
Definition: snprintf.c:161
#define LLONG
Definition: snprintf.c:128
static void fmtfp(char *buffer, slen_t *currlen, slen_t maxlen, double fvalue, int min, int max, int flags)
Definition: snprintf.c:628
slen_t fixup_asprintf(char **ptr, const char *format,...)
Definition: snprintf.c:829
#define DP_F_NUM
Definition: snprintf.c:159
static double my_modf(double x0, double *iptr)
Definition: snprintf.c:594
float x
Definition: cordic.py:15
union value value
Definition: obx.h:44
static int format
Definition: pbmclean.c:15
#define min(a, b)
Definition: pbmplus.h:223
#define max(a, b)
Definition: pbmto4425.c:11
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst op &r &cond WK op &r &cond WK op &r &cond WK else op &m &cond &ia op &r &cond WK else op &m &cond &ia elseif elseif else error unsupported base if elseif elseif else error unsupported unaligned pixldst unaligned endm macro pixst base base else pixldst base endif endm macro PF ptr
static int cnt
Definition: pkout.c:166
#define index(s, c)
Definition: plain2.h:351
#define flags
static const char * caps[]
Definition: sfd.c:39
#define uvalue(o)
Definition: lobject.h:170
#define fvalue(o)
Definition: lobject.h:174
#define str(s)
Definition: sh6.c:399
Definition: usprintf.c:39
Definition: utils.c:300
Definition: mendex.h:20
ch
Definition: t4ht.c:1443
char fmt[256]
Definition: tex4ht.c:3925
return() int(((double) *(font_tbl[cur_fnt].wtbl+(int)(*(font_tbl[cur_fnt].char_wi+(int)(ch - font_tbl[cur_fnt].char_f)% 256)))/(double)(1L<< 20)) *(double) font_tbl[cur_fnt].scale)
Definition: obx.h:51
#define va_arg(pvar, type)
Definition: varargs.h:35
#define va_end(pvar)
Definition: varargs.h:38
char * va_list
Definition: varargs.h:22
#define main
Definition: xmain.c:31