daily pastebin goal
55%
SHARE
TWEET

Untitled

a guest Feb 16th, 2019 105 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * Copyright Patrick Powell 1995
  3.  * This code is based on code written by Patrick Powell (papowell@astart.com)
  4.  * It may be used for any purpose as long as this notice remains intact
  5.  * on all source code distributions
  6.  */
  7.  
  8. /**************************************************************
  9.  * Original:
  10.  * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
  11.  * A bombproof version of doprnt (dopr) included.
  12.  * Sigh.  This sort of thing is always nasty do deal with.  Note that
  13.  * the version here does not include floating point...
  14.  *
  15.  * snprintf() is used instead of sprintf() as it does limit checks
  16.  * for string length.  This covers a nasty loophole.
  17.  *
  18.  * The other functions are there to prevent NULL pointers from
  19.  * causing nast effects.
  20.  *
  21.  * More Recently:
  22.  *  Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
  23.  *  This was ugly.  It is still ugly.  I opted out of floating point
  24.  *  numbers, but the formatter understands just about everything
  25.  *  from the normal C string format, at least as far as I can tell from
  26.  *  the Solaris 2.5 printf(3S) man page.
  27.  *
  28.  *  Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
  29.  *    Ok, added some minimal floating point support, which means this
  30.  *    probably requires libm on most operating systems.  Don't yet
  31.  *    support the exponent (e,E) and sigfig (g,G).  Also, fmtint()
  32.  *    was pretty badly broken, it just wasn't being exercised in ways
  33.  *    which showed it, so that's been fixed.  Also, formated the code
  34.  *    to mutt conventions, and removed dead code left over from the
  35.  *    original.  Also, there is now a builtin-test, just compile with:
  36.  *           gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
  37.  *    and run snprintf for results.
  38.  *
  39.  *  Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
  40.  *    The PGP code was using unsigned hexadecimal formats.
  41.  *    Unfortunately, unsigned formats simply didn't work.
  42.  *
  43.  *  Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
  44.  *    The original code assumed that both snprintf() and vsnprintf() were
  45.  *    missing.  Some systems only have snprintf() but not vsnprintf(), so
  46.  *    the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
  47.  *
  48.  *  Andrew Tridgell (tridge@samba.org) Oct 1998
  49.  *    fixed handling of %.0f
  50.  *    added test for HAVE_LONG_DOUBLE
  51.  *
  52.  * tridge@samba.org, idra@samba.org, April 2001
  53.  *    got rid of fcvt code (twas buggy and made testing harder)
  54.  *    added C99 semantics
  55.  *
  56.  * date: 2002/12/19 19:56:31;  author: herb;  state: Exp;  lines: +2 -0
  57.  * actually print args for %g and %e
  58.  *
  59.  * date: 2002/06/03 13:37:52;  author: jmcd;  state: Exp;  lines: +8 -0
  60.  * Since includes.h isn't included here, VA_COPY has to be defined here.  I don't
  61.  * see any include file that is guaranteed to be here, so I'm defining it
  62.  * locally.  Fixes AIX and Solaris builds.
  63.  *
  64.  * date: 2002/06/03 03:07:24;  author: tridge;  state: Exp;  lines: +5 -13
  65.  * put the ifdef for HAVE_VA_COPY in one place rather than in lots of
  66.  * functions
  67.  *
  68.  * date: 2002/05/17 14:51:22;  author: jmcd;  state: Exp;  lines: +21 -4
  69.  * Fix usage of va_list passed as an arg.  Use __va_copy before using it
  70.  * when it exists.
  71.  *
  72.  * date: 2002/04/16 22:38:04;  author: idra;  state: Exp;  lines: +20 -14
  73.  * Fix incorrect zpadlen handling in fmtfp.
  74.  * Thanks to Ollie Oldham <ollie.oldham@metro-optix.com> for spotting it.
  75.  * few mods to make it easier to compile the tests.
  76.  * addedd the "Ollie" test to the floating point ones.
  77.  *
  78.  * Martin Pool (mbp@samba.org) April 2003
  79.  *    Remove NO_CONFIG_H so that the test case can be built within a source
  80.  *    tree with less trouble.
  81.  *    Remove unnecessary SAFE_FREE() definition.
  82.  *
  83.  * Martin Pool (mbp@samba.org) May 2003
  84.  *    Put in a prototype for dummy_snprintf() to quiet compiler warnings.
  85.  *
  86.  *    Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even
  87.  *    if the C library has some snprintf functions already.
  88.  *
  89.  * Damien Miller (djm@mindrot.org) Jan 2007
  90.  *    Fix integer overflows in return value.
  91.  *    Make formatting quite a bit faster by inlining dopr_outch()
  92.  *
  93.  **************************************************************/
  94.  
  95. #include "includes.h"
  96.  
  97. #if defined(BROKEN_SNPRINTF)        /* For those with broken snprintf() */
  98. # undef HAVE_SNPRINTF
  99. # undef HAVE_VSNPRINTF
  100. #endif
  101.  
  102. #ifndef VA_COPY
  103. # ifdef HAVE_VA_COPY
  104. #  define VA_COPY(dest, src) va_copy(dest, src)
  105. # else
  106. #  ifdef HAVE___VA_COPY
  107. #   define VA_COPY(dest, src) __va_copy(dest, src)
  108. #  else
  109. #   define VA_COPY(dest, src) (dest) = (src)
  110. #  endif
  111. # endif
  112. #endif
  113.  
  114. #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
  115.  
  116. #include <ctype.h>
  117. #include <stdarg.h>
  118. #include <stdlib.h>
  119. #include <string.h>
  120. #include <limits.h>
  121. #include <errno.h>
  122.  
  123. #ifdef HAVE_LONG_DOUBLE
  124. # define LDOUBLE long double
  125. #else
  126. # define LDOUBLE double
  127. #endif
  128.  
  129. #ifdef HAVE_LONG_LONG
  130. # define LLONG long long
  131. #else
  132. # define LLONG long
  133. #endif
  134.  
  135. /*
  136.  * dopr(): poor man's version of doprintf
  137.  */
  138.  
  139. /* format read states */
  140. #define DP_S_DEFAULT 0
  141. #define DP_S_FLAGS   1
  142. #define DP_S_MIN     2
  143. #define DP_S_DOT     3
  144. #define DP_S_MAX     4
  145. #define DP_S_MOD     5
  146. #define DP_S_CONV    6
  147. #define DP_S_DONE    7
  148.  
  149. /* format flags - Bits */
  150. #define DP_F_MINUS  (1 << 0)
  151. #define DP_F_PLUS   (1 << 1)
  152. #define DP_F_SPACE  (1 << 2)
  153. #define DP_F_NUM    (1 << 3)
  154. #define DP_F_ZERO   (1 << 4)
  155. #define DP_F_UP     (1 << 5)
  156. #define DP_F_UNSIGNED   (1 << 6)
  157.  
  158. /* Conversion Flags */
  159. #define DP_C_SHORT   1
  160. #define DP_C_LONG    2
  161. #define DP_C_LDOUBLE 3
  162. #define DP_C_LLONG   4
  163.  
  164. #define char_to_int(p) ((p)- '0')
  165. #ifndef MAX
  166. # define MAX(p,q) (((p) >= (q)) ? (p) : (q))
  167. #endif
  168.  
  169. #define DOPR_OUTCH(buf, pos, buflen, thechar) \
  170.     do { \
  171.         if (pos + 1 >= INT_MAX) { \
  172.             errno = ERANGE; \
  173.             return -1; \
  174.         } \
  175.         if (pos < buflen) \
  176.             buf[pos] = thechar; \
  177.         (pos)++; \
  178.     } while (0)
  179.  
  180. static int dopr(char *buffer, size_t maxlen, const char *format,
  181.     va_list args_in);
  182. static int fmtstr(char *buffer, size_t *currlen, size_t maxlen,
  183.     char *value, int flags, int min, int max);
  184. static int fmtint(char *buffer, size_t *currlen, size_t maxlen,
  185.     LLONG value, int base, int min, int max, int flags);
  186. static int fmtfp(char *buffer, size_t *currlen, size_t maxlen,
  187.     LDOUBLE fvalue, int min, int max, int flags);
  188.  
  189. static int
  190. dopr(char *buffer, size_t maxlen, const char *format, va_list args_in)
  191. {
  192.     char ch;
  193.     LLONG value;
  194.     LDOUBLE fvalue;
  195.     char *strvalue;
  196.     int min;
  197.     int max;
  198.     int state;
  199.     int flags;
  200.     int cflags;
  201.     size_t currlen;
  202.     va_list args;
  203.  
  204.     VA_COPY(args, args_in);
  205.    
  206.     state = DP_S_DEFAULT;
  207.     currlen = flags = cflags = min = 0;
  208.     max = -1;
  209.     ch = *format++;
  210.    
  211.     while (state != DP_S_DONE) {
  212.         if (ch == '\0')
  213.             state = DP_S_DONE;
  214.  
  215.         switch(state) {
  216.         case DP_S_DEFAULT:
  217.             if (ch == '%')
  218.                 state = DP_S_FLAGS;
  219.             else
  220.                 DOPR_OUTCH(buffer, currlen, maxlen, ch);
  221.             ch = *format++;
  222.             break;
  223.         case DP_S_FLAGS:
  224.             switch (ch) {
  225.             case '-':
  226.                 flags |= DP_F_MINUS;
  227.                 ch = *format++;
  228.                 break;
  229.             case '+':
  230.                 flags |= DP_F_PLUS;
  231.                 ch = *format++;
  232.                 break;
  233.             case ' ':
  234.                 flags |= DP_F_SPACE;
  235.                 ch = *format++;
  236.                 break;
  237.             case '#':
  238.                 flags |= DP_F_NUM;
  239.                 ch = *format++;
  240.                 break;
  241.             case '0':
  242.                 flags |= DP_F_ZERO;
  243.                 ch = *format++;
  244.                 break;
  245.             default:
  246.                 state = DP_S_MIN;
  247.                 break;
  248.             }
  249.             break;
  250.         case DP_S_MIN:
  251.             if (isdigit((unsigned char)ch)) {
  252.                 min = 10*min + char_to_int (ch);
  253.                 ch = *format++;
  254.             } else if (ch == '*') {
  255.                 min = va_arg (args, int);
  256.                 ch = *format++;
  257.                 state = DP_S_DOT;
  258.             } else {
  259.                 state = DP_S_DOT;
  260.             }
  261.             break;
  262.         case DP_S_DOT:
  263.             if (ch == '.') {
  264.                 state = DP_S_MAX;
  265.                 ch = *format++;
  266.             } else {
  267.                 state = DP_S_MOD;
  268.             }
  269.             break;
  270.         case DP_S_MAX:
  271.             if (isdigit((unsigned char)ch)) {
  272.                 if (max < 0)
  273.                     max = 0;
  274.                 max = 10*max + char_to_int (ch);
  275.                 ch = *format++;
  276.             } else if (ch == '*') {
  277.                 max = va_arg (args, int);
  278.                 ch = *format++;
  279.                 state = DP_S_MOD;
  280.             } else {
  281.                 state = DP_S_MOD;
  282.             }
  283.             break;
  284.         case DP_S_MOD:
  285.             switch (ch) {
  286.             case 'h':
  287.                 cflags = DP_C_SHORT;
  288.                 ch = *format++;
  289.                 break;
  290.             case 'l':
  291.                 cflags = DP_C_LONG;
  292.                 ch = *format++;
  293.                 if (ch == 'l') {    /* It's a long long */
  294.                     cflags = DP_C_LLONG;
  295.                     ch = *format++;
  296.                 }
  297.                 break;
  298.             case 'L':
  299.                 cflags = DP_C_LDOUBLE;
  300.                 ch = *format++;
  301.                 break;
  302.             default:
  303.                 break;
  304.             }
  305.             state = DP_S_CONV;
  306.             break;
  307.         case DP_S_CONV:
  308.             switch (ch) {
  309.             case 'd':
  310.             case 'i':
  311.                 if (cflags == DP_C_SHORT)
  312.                     value = va_arg (args, int);
  313.                 else if (cflags == DP_C_LONG)
  314.                     value = va_arg (args, long int);
  315.                 else if (cflags == DP_C_LLONG)
  316.                     value = va_arg (args, LLONG);
  317.                 else
  318.                     value = va_arg (args, int);
  319.                 if (fmtint(buffer, &currlen, maxlen,
  320.                     value, 10, min, max, flags) == -1)
  321.                     return -1;
  322.                 break;
  323.             case 'o':
  324.                 flags |= DP_F_UNSIGNED;
  325.                 if (cflags == DP_C_SHORT)
  326.                     value = va_arg (args, unsigned int);
  327.                 else if (cflags == DP_C_LONG)
  328.                     value = (long)va_arg (args, unsigned long int);
  329.                 else if (cflags == DP_C_LLONG)
  330.                     value = (long)va_arg (args, unsigned LLONG);
  331.                 else
  332.                     value = (long)va_arg (args, unsigned int);
  333.                 if (fmtint(buffer, &currlen, maxlen, value,
  334.                     8, min, max, flags) == -1)
  335.                     return -1;
  336.                 break;
  337.             case 'u':
  338.                 flags |= DP_F_UNSIGNED;
  339.                 if (cflags == DP_C_SHORT)
  340.                     value = va_arg (args, unsigned int);
  341.                 else if (cflags == DP_C_LONG)
  342.                     value = (long)va_arg (args, unsigned long int);
  343.                 else if (cflags == DP_C_LLONG)
  344.                     value = (LLONG)va_arg (args, unsigned LLONG);
  345.                 else
  346.                     value = (long)va_arg (args, unsigned int);
  347.                 if (fmtint(buffer, &currlen, maxlen, value,
  348.                     10, min, max, flags) == -1)
  349.                     return -1;
  350.                 break;
  351.             case 'X':
  352.                 flags |= DP_F_UP;
  353.             case 'x':
  354.                 flags |= DP_F_UNSIGNED;
  355.                 if (cflags == DP_C_SHORT)
  356.                     value = va_arg (args, unsigned int);
  357.                 else if (cflags == DP_C_LONG)
  358.                     value = (long)va_arg (args, unsigned long int);
  359.                 else if (cflags == DP_C_LLONG)
  360.                     value = (LLONG)va_arg (args, unsigned LLONG);
  361.                 else
  362.                     value = (long)va_arg (args, unsigned int);
  363.                 if (fmtint(buffer, &currlen, maxlen, value,
  364.                     16, min, max, flags) == -1)
  365.                     return -1;
  366.                 break;
  367.             case 'f':
  368.                 if (cflags == DP_C_LDOUBLE)
  369.                     fvalue = va_arg (args, LDOUBLE);
  370.                 else
  371.                     fvalue = va_arg (args, double);
  372.                 if (fmtfp(buffer, &currlen, maxlen, fvalue,
  373.                     min, max, flags) == -1)
  374.                     return -1;
  375.                 break;
  376.             case 'E':
  377.                 flags |= DP_F_UP;
  378.             case 'e':
  379.                 if (cflags == DP_C_LDOUBLE)
  380.                     fvalue = va_arg (args, LDOUBLE);
  381.                 else
  382.                     fvalue = va_arg (args, double);
  383.                 if (fmtfp(buffer, &currlen, maxlen, fvalue,
  384.                     min, max, flags) == -1)
  385.                     return -1;
  386.                 break;
  387.             case 'G':
  388.                 flags |= DP_F_UP;
  389.             case 'g':
  390.                 if (cflags == DP_C_LDOUBLE)
  391.                     fvalue = va_arg (args, LDOUBLE);
  392.                 else
  393.                     fvalue = va_arg (args, double);
  394.                 if (fmtfp(buffer, &currlen, maxlen, fvalue,
  395.                     min, max, flags) == -1)
  396.                     return -1;
  397.                 break;
  398.             case 'c':
  399.                 DOPR_OUTCH(buffer, currlen, maxlen,
  400.                     va_arg (args, int));
  401.                 break;
  402.             case 's':
  403.                 strvalue = va_arg (args, char *);
  404.                 if (!strvalue) strvalue = "(NULL)";
  405.                 if (max == -1) {
  406.                     max = strlen(strvalue);
  407.                 }
  408.                 if (min > 0 && max >= 0 && min > max) max = min;
  409.                 if (fmtstr(buffer, &currlen, maxlen,
  410.                     strvalue, flags, min, max) == -1)
  411.                     return -1;
  412.                 break;
  413.             case 'p':
  414.                 strvalue = va_arg (args, void *);
  415.                 if (fmtint(buffer, &currlen, maxlen,
  416.                     (long) strvalue, 16, min, max, flags) == -1)
  417.                     return -1;
  418.                 break;
  419.             case 'n':
  420.                 if (cflags == DP_C_SHORT) {
  421.                     short int *num;
  422.                     num = va_arg (args, short int *);
  423.                     *num = currlen;
  424.                 } else if (cflags == DP_C_LONG) {
  425.                     long int *num;
  426.                     num = va_arg (args, long int *);
  427.                     *num = (long int)currlen;
  428.                 } else if (cflags == DP_C_LLONG) {
  429.                     LLONG *num;
  430.                     num = va_arg (args, LLONG *);
  431.                     *num = (LLONG)currlen;
  432.                 } else {
  433.                     int *num;
  434.                     num = va_arg (args, int *);
  435.                     *num = currlen;
  436.                 }
  437.                 break;
  438.             case '%':
  439.                 DOPR_OUTCH(buffer, currlen, maxlen, ch);
  440.                 break;
  441.             case 'w':
  442.                 /* not supported yet, treat as next char */
  443.                 ch = *format++;
  444.                 break;
  445.             default:
  446.                 /* Unknown, skip */
  447.                 break;
  448.             }
  449.             ch = *format++;
  450.             state = DP_S_DEFAULT;
  451.             flags = cflags = min = 0;
  452.             max = -1;
  453.             break;
  454.         case DP_S_DONE:
  455.             break;
  456.         default:
  457.             /* hmm? */
  458.             break; /* some picky compilers need this */
  459.         }
  460.     }
  461.     if (maxlen != 0) {
  462.         if (currlen < maxlen - 1)
  463.             buffer[currlen] = '\0';
  464.         else if (maxlen > 0)
  465.             buffer[maxlen - 1] = '\0';
  466.     }
  467.    
  468.     return currlen < INT_MAX ? (int)currlen : -1;
  469. }
  470.  
  471. static int
  472. fmtstr(char *buffer, size_t *currlen, size_t maxlen,
  473.     char *value, int flags, int min, int max)
  474. {
  475.     int padlen, strln;     /* amount to pad */
  476.     int cnt = 0;
  477.  
  478. #ifdef DEBUG_SNPRINTF
  479.     printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value);
  480. #endif
  481.     if (value == 0) {
  482.         value = "<NULL>";
  483.     }
  484.  
  485.     for (strln = 0; strln < max && value[strln]; ++strln); /* strlen */
  486.     padlen = min - strln;
  487.     if (padlen < 0)
  488.         padlen = 0;
  489.     if (flags & DP_F_MINUS)
  490.         padlen = -padlen; /* Left Justify */
  491.    
  492.     while ((padlen > 0) && (cnt < max)) {
  493.         DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
  494.         --padlen;
  495.         ++cnt;
  496.     }
  497.     while (*value && (cnt < max)) {
  498.         DOPR_OUTCH(buffer, *currlen, maxlen, *value);
  499.         *value++;
  500.         ++cnt;
  501.     }
  502.     while ((padlen < 0) && (cnt < max)) {
  503.         DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
  504.         ++padlen;
  505.         ++cnt;
  506.     }
  507.     return 0;
  508. }
  509.  
  510. /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
  511.  
  512. static int
  513. fmtint(char *buffer, size_t *currlen, size_t maxlen,
  514.             LLONG value, int base, int min, int max, int flags)
  515. {
  516.     int signvalue = 0;
  517.     unsigned LLONG uvalue;
  518.     char convert[20];
  519.     int place = 0;
  520.     int spadlen = 0; /* amount to space pad */
  521.     int zpadlen = 0; /* amount to zero pad */
  522.     int caps = 0;
  523.    
  524.     if (max < 0)
  525.         max = 0;
  526.    
  527.     uvalue = value;
  528.    
  529.     if(!(flags & DP_F_UNSIGNED)) {
  530.         if( value < 0 ) {
  531.             signvalue = '-';
  532.             uvalue = -value;
  533.         } else {
  534.             if (flags & DP_F_PLUS)  /* Do a sign (+/i) */
  535.                 signvalue = '+';
  536.             else if (flags & DP_F_SPACE)
  537.                 signvalue = ' ';
  538.         }
  539.     }
  540.  
  541.     if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
  542.  
  543.     do {
  544.         convert[place++] =
  545.             (caps? "0123456789ABCDEF":"0123456789abcdef")
  546.             [uvalue % (unsigned)base  ];
  547.         uvalue = (uvalue / (unsigned)base );
  548.     } while(uvalue && (place < 20));
  549.     if (place == 20) place--;
  550.     convert[place] = 0;
  551.  
  552.     zpadlen = max - place;
  553.     spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
  554.     if (zpadlen < 0) zpadlen = 0;
  555.     if (spadlen < 0) spadlen = 0;
  556.     if (flags & DP_F_ZERO) {
  557.         zpadlen = MAX(zpadlen, spadlen);
  558.         spadlen = 0;
  559.     }
  560.     if (flags & DP_F_MINUS)
  561.         spadlen = -spadlen; /* Left Justifty */
  562.  
  563. #ifdef DEBUG_SNPRINTF
  564.     printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
  565.            zpadlen, spadlen, min, max, place);
  566. #endif
  567.  
  568.     /* Spaces */
  569.     while (spadlen > 0) {
  570.         DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
  571.         --spadlen;
  572.     }
  573.  
  574.     /* Sign */
  575.     if (signvalue)
  576.         DOPR_OUTCH(buffer, *currlen, maxlen, signvalue);
  577.  
  578.     /* Zeros */
  579.     if (zpadlen > 0) {
  580.         while (zpadlen > 0) {
  581.             DOPR_OUTCH(buffer, *currlen, maxlen, '0');
  582.             --zpadlen;
  583.         }
  584.     }
  585.  
  586.     /* Digits */
  587.     while (place > 0) {
  588.         --place;
  589.         DOPR_OUTCH(buffer, *currlen, maxlen, convert[place]);
  590.     }
  591.  
  592.     /* Left Justified spaces */
  593.     while (spadlen < 0) {
  594.         DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
  595.         ++spadlen;
  596.     }
  597.     return 0;
  598. }
  599.  
  600. static LDOUBLE abs_val(LDOUBLE value)
  601. {
  602.     LDOUBLE result = value;
  603.  
  604.     if (value < 0)
  605.         result = -value;
  606.    
  607.     return result;
  608. }
  609.  
  610. static LDOUBLE POW10(int val)
  611. {
  612.     LDOUBLE result = 1;
  613.    
  614.     while (val) {
  615.         result *= 10;
  616.         val--;
  617.     }
  618.  
  619.     return result;
  620. }
  621.  
  622. static LLONG ROUND(LDOUBLE value)
  623. {
  624.     LLONG intpart;
  625.  
  626.     intpart = (LLONG)value;
  627.     value = value - intpart;
  628.     if (value >= 0.5) intpart++;
  629.    
  630.     return intpart;
  631. }
  632.  
  633. /* a replacement for modf that doesn't need the math library. Should
  634.    be portable, but slow */
  635. static double my_modf(double x0, double *iptr)
  636. {
  637.     int i;
  638.     long l;
  639.     double x = x0;
  640.     double f = 1.0;
  641.  
  642.     for (i=0;i<100;i++) {
  643.         l = (long)x;
  644.         if (l <= (x+1) && l >= (x-1)) break;
  645.         x *= 0.1;
  646.         f *= 10.0;
  647.     }
  648.  
  649.     if (i == 100) {
  650.         /*
  651.          * yikes! the number is beyond what we can handle.
  652.          * What do we do?
  653.          */
  654.         (*iptr) = 0;
  655.         return 0;
  656.     }
  657.  
  658.     if (i != 0) {
  659.         double i2;
  660.         double ret;
  661.  
  662.         ret = my_modf(x0-l*f, &i2);
  663.         (*iptr) = l*f + i2;
  664.         return ret;
  665.     }
  666.  
  667.     (*iptr) = l;
  668.     return x - (*iptr);
  669. }
  670.  
  671.  
  672. static int
  673. fmtfp (char *buffer, size_t *currlen, size_t maxlen,
  674.     LDOUBLE fvalue, int min, int max, int flags)
  675. {
  676.     int signvalue = 0;
  677.     double ufvalue;
  678.     char iconvert[311];
  679.     char fconvert[311];
  680.     int iplace = 0;
  681.     int fplace = 0;
  682.     int padlen = 0; /* amount to pad */
  683.     int zpadlen = 0;
  684.     int caps = 0;
  685.     int idx;
  686.     double intpart;
  687.     double fracpart;
  688.     double temp;
  689.  
  690.     /*
  691.      * AIX manpage says the default is 0, but Solaris says the default
  692.      * is 6, and sprintf on AIX defaults to 6
  693.      */
  694.     if (max < 0)
  695.         max = 6;
  696.  
  697.     ufvalue = abs_val (fvalue);
  698.  
  699.     if (fvalue < 0) {
  700.         signvalue = '-';
  701.     } else {
  702.         if (flags & DP_F_PLUS) { /* Do a sign (+/i) */
  703.             signvalue = '+';
  704.         } else {
  705.             if (flags & DP_F_SPACE)
  706.                 signvalue = ' ';
  707.         }
  708.     }
  709.  
  710. #if 0
  711.     if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
  712. #endif
  713.  
  714. #if 0
  715.      if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */
  716. #endif
  717.  
  718.     /*
  719.      * Sorry, we only support 16 digits past the decimal because of our
  720.      * conversion method
  721.      */
  722.     if (max > 16)
  723.         max = 16;
  724.  
  725.     /* We "cheat" by converting the fractional part to integer by
  726.      * multiplying by a factor of 10
  727.      */
  728.  
  729.     temp = ufvalue;
  730.     my_modf(temp, &intpart);
  731.  
  732.     fracpart = ROUND((POW10(max)) * (ufvalue - intpart));
  733.    
  734.     if (fracpart >= POW10(max)) {
  735.         intpart++;
  736.         fracpart -= POW10(max);
  737.     }
  738.  
  739.     /* Convert integer part */
  740.     do {
  741.         temp = intpart*0.1;
  742.         my_modf(temp, &intpart);
  743.         idx = (int) ((temp -intpart +0.05)* 10.0);
  744.         /* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
  745.         /* printf ("%llf, %f, %x\n", temp, intpart, idx); */
  746.         iconvert[iplace++] =
  747.             (caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
  748.     } while (intpart && (iplace < 311));
  749.     if (iplace == 311) iplace--;
  750.     iconvert[iplace] = 0;
  751.  
  752.     /* Convert fractional part */
  753.     if (fracpart)
  754.     {
  755.         do {
  756.             temp = fracpart*0.1;
  757.             my_modf(temp, &fracpart);
  758.             idx = (int) ((temp -fracpart +0.05)* 10.0);
  759.             /* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */
  760.             /* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */
  761.             fconvert[fplace++] =
  762.             (caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
  763.         } while(fracpart && (fplace < 311));
  764.         if (fplace == 311) fplace--;
  765.     }
  766.     fconvert[fplace] = 0;
  767.  
  768.     /* -1 for decimal point, another -1 if we are printing a sign */
  769.     padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
  770.     zpadlen = max - fplace;
  771.     if (zpadlen < 0) zpadlen = 0;
  772.     if (padlen < 0)
  773.         padlen = 0;
  774.     if (flags & DP_F_MINUS)
  775.         padlen = -padlen; /* Left Justifty */
  776.    
  777.     if ((flags & DP_F_ZERO) && (padlen > 0)) {
  778.         if (signvalue) {
  779.             DOPR_OUTCH(buffer, *currlen, maxlen, signvalue);
  780.             --padlen;
  781.             signvalue = 0;
  782.         }
  783.         while (padlen > 0) {
  784.             DOPR_OUTCH(buffer, *currlen, maxlen, '0');
  785.             --padlen;
  786.         }
  787.     }
  788.     while (padlen > 0) {
  789.         DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
  790.         --padlen;
  791.     }
  792.     if (signvalue)
  793.         DOPR_OUTCH(buffer, *currlen, maxlen, signvalue);
  794.    
  795.     while (iplace > 0) {
  796.         --iplace;
  797.         DOPR_OUTCH(buffer, *currlen, maxlen, iconvert[iplace]);
  798.     }
  799.  
  800. #ifdef DEBUG_SNPRINTF
  801.     printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
  802. #endif
  803.  
  804.     /*
  805.      * Decimal point.  This should probably use locale to find the correct
  806.      * char to print out.
  807.      */
  808.     if (max > 0) {
  809.         DOPR_OUTCH(buffer, *currlen, maxlen, '.');
  810.        
  811.         while (zpadlen > 0) {
  812.             DOPR_OUTCH(buffer, *currlen, maxlen, '0');
  813.             --zpadlen;
  814.         }
  815.  
  816.         while (fplace > 0) {
  817.             --fplace;
  818.             DOPR_OUTCH(buffer, *currlen, maxlen, fconvert[fplace]);
  819.         }
  820.     }
  821.  
  822.     while (padlen < 0) {
  823.         DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
  824.         ++padlen;
  825.     }
  826.     return 0;
  827. }
  828. #endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
  829.  
  830. #if !defined(HAVE_VSNPRINTF)
  831. int
  832. vsnprintf (char *str, size_t count, const char *fmt, va_list args)
  833. {
  834.     return dopr(str, count, fmt, args);
  835. }
  836. #endif
  837.  
  838. #if !defined(HAVE_SNPRINTF)
  839. int
  840. snprintf(char *str, size_t count, SNPRINTF_CONST char *fmt, ...)
  841. {
  842.     size_t ret;
  843.     va_list ap;
  844.  
  845.     va_start(ap, fmt);
  846.     ret = vsnprintf(str, count, fmt, ap);
  847.     va_end(ap);
  848.     return ret;
  849. }
  850. #endif
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top