missing/vsnprintf.c


DEFINITIONS

This source file includes following functions.
  1. BSD__sfvwrite
  2. BSD__sprint
  3. BSD__sbprintf
  4. BSD__ultoa
  5. BSD_vfprintf
  6. cvt
  7. exponent
  8. vsnprintf
  9. snprintf


   1  /*-
   2   * Copyright (c) 1990, 1993
   3   *      The Regents of the University of California.  All rights reserved.
   4   *
   5   * This code is derived from software contributed to Berkeley by
   6   * Chris Torek.
   7   *
   8   * Redistribution and use in source and binary forms, with or without
   9   * modification, are permitted provided that the following conditions
  10   * are met:
  11   * 1. Redistributions of source code must retain the above copyright
  12   *    notice, this list of conditions and the following disclaimer.
  13   * 2. Redistributions in binary form must reproduce the above copyright
  14   *    notice, this list of conditions and the following disclaimer in the
  15   *    documentation and/or other materials provided with the distribution.
  16   * 3. All advertising materials mentioning features or use of this software
  17   *    must display the following acknowledgement:
  18   *      This product includes software developed by the University of
  19   *      California, Berkeley and its contributors.
  20   * 4. Neither the name of the University nor the names of its contributors
  21   *    may be used to endorse or promote products derived from this software
  22   *    without specific prior written permission.
  23   *
  24   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27   * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34   * SUCH DAMAGE.
  35   */
  36  
  37  /*
  38   * IMPORTANT NOTE:
  39   * --------------
  40   * From ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
  41   * paragraph 3 above is now null and void.
  42   */
  43  
  44  /* SNPRINTF.C  
  45   * fjc 7-31-97 Modified by Mib Software to be a standalone snprintf.c module.
  46   *      http://www.mibsoftware.com
  47   * Mib Software does not warrant this software any differently than the
  48   * University of California, Berkeley as described above.  All warranties
  49   * are disclaimed.  Use this software at your own risk.
  50   *
  51   *      All code referencing FILE * functions was eliminated, since it could
  52   *      never be called.  All header files and necessary files are collapsed
  53   *      into one file, internal functions are declared static.  This should
  54   *      allow inclusion into libraries with less chance of namespace collisions.
  55   *
  56   *      snprintf should be the only externally visible item.
  57   *     
  58   *      As of 7-31-97 FLOATING_POINT is NOT provided.  The code is somewhat
  59   *        non-portable, so it is disabled.
  60   */
  61  
  62  /* Define FLOATING_POINT to get floating point. */
  63  /*
  64  #define FLOATING_POINT
  65  */
  66  
  67  #include <sys/types.h>
  68  #define u_long unsigned long
  69  #define u_short unsigned short
  70  #define u_int unsigned int
  71  
  72  #undef __P
  73  #if defined(__STDC__)
  74  # include <stdarg.h>
  75  # if !defined(__P)
  76  #  define __P(x) x
  77  # endif
  78  #else
  79  # define __P(x) ()
  80  # if !defined(const)
  81  #  define const
  82  # endif
  83  # include <varargs.h>
  84  #endif
  85  #ifndef _BSD_VA_LIST_ 
  86  #define _BSD_VA_LIST_ va_list
  87  #endif
  88  
  89  #ifdef __STDC__
  90  # include <limits.h>
  91  #else
  92  # ifndef LONG_MAX
  93  #  ifdef HAVE_LIMITS_H
  94  #   include <limits.h>
  95  #  else
  96      /* assuming 32bit(2's compliment) long */
  97  #   define LONG_MAX 2147483647
  98  #  endif
  99  # endif
 100  #endif
 101  
 102  #if defined(__hpux) && !defined(__GNUC__)
 103  #define const
 104  #endif
 105  
 106  #if defined(sgi)
 107  #undef __const
 108  #define __const
 109  #endif /* People who don't like const sys_error */
 110  
 111  #include <stddef.h>
 112  
 113  #ifndef NULL
 114  #define NULL    0
 115  #endif
 116  
 117  /*
 118   * NB: to fit things in six character monocase externals, the stdio
 119   * code uses the prefix `__s' for stdio objects, typically followed
 120   * by a three-character attempt at a mnemonic.
 121   */
 122  
 123  /* stdio buffers */
 124  struct __sbuf {
 125          unsigned char *_base;
 126          int     _size;
 127  };
 128  
 129  
 130  /*
 131   * stdio state variables.
 132   *
 133   * The following always hold:
 134   *
 135   *      if (_flags&(__SLBF|__SWR)) == (__SLBF|__SWR),
 136   *              _lbfsize is -_bf._size, else _lbfsize is 0
 137   *      if _flags&__SRD, _w is 0
 138   *      if _flags&__SWR, _r is 0
 139   *
 140   * This ensures that the getc and putc macros (or inline functions) never
 141   * try to write or read from a file that is in `read' or `write' mode.
 142   * (Moreover, they can, and do, automatically switch from read mode to
 143   * write mode, and back, on "r+" and "w+" files.)
 144   *
 145   * _lbfsize is used only to make the inline line-buffered output stream
 146   * code as compact as possible.
 147   *
 148   * _ub, _up, and _ur are used when ungetc() pushes back more characters
 149   * than fit in the current _bf, or when ungetc() pushes back a character
 150   * that does not match the previous one in _bf.  When this happens,
 151   * _ub._base becomes non-nil (i.e., a stream has ungetc() data iff
 152   * _ub._base!=NULL) and _up and _ur save the current values of _p and _r.
 153   *
 154   * NB: see WARNING above before changing the layout of this structure!
 155   */
 156  typedef struct __sFILE {
 157          unsigned char *_p;      /* current position in (some) buffer */
 158          int     _r;             /* read space left for getc() */
 159          int     _w;             /* write space left for putc() */
 160          short   _flags;         /* flags, below; this FILE is free if 0 */
 161          short   _file;          /* fileno, if Unix descriptor, else -1 */
 162          struct  __sbuf _bf;     /* the buffer (at least 1 byte, if !NULL) */
 163          int     _lbfsize;       /* 0 or -_bf._size, for inline putc */
 164  } FILE;
 165  
 166  
 167  #define __SLBF  0x0001          /* line buffered */
 168  #define __SNBF  0x0002          /* unbuffered */
 169  #define __SRD   0x0004          /* OK to read */
 170  #define __SWR   0x0008          /* OK to write */
 171          /* RD and WR are never simultaneously asserted */
 172  #define __SRW   0x0010          /* open for reading & writing */
 173  #define __SEOF  0x0020          /* found EOF */
 174  #define __SERR  0x0040          /* found error */
 175  #define __SMBF  0x0080          /* _buf is from malloc */
 176  #define __SAPP  0x0100          /* fdopen()ed in append mode */
 177  #define __SSTR  0x0200          /* this is an sprintf/snprintf string */
 178  #define __SOPT  0x0400          /* do fseek() optimisation */
 179  #define __SNPT  0x0800          /* do not do fseek() optimisation */
 180  #define __SOFF  0x1000          /* set iff _offset is in fact correct */
 181  #define __SMOD  0x2000          /* true => fgetln modified _p text */
 182  
 183  
 184  #define EOF     (-1)
 185  
 186  
 187  #define __sfeof(p)      (((p)->_flags & __SEOF) != 0)
 188  #define __sferror(p)    (((p)->_flags & __SERR) != 0)
 189  #define __sclearerr(p)  ((void)((p)->_flags &= ~(__SERR|__SEOF)))
 190  #define __sfileno(p)    ((p)->_file)
 191  
 192  #define feof(p)         __sfeof(p)
 193  #define ferror(p)       __sferror(p)
 194  #define clearerr(p)     __sclearerr(p)
 195  
 196  #ifndef _ANSI_SOURCE
 197  #define fileno(p)       __sfileno(p)
 198  #endif
 199  
 200  
 201  #if defined(__hpux) && !defined(__GNUC__) || defined(__DECC)
 202  #include <string.h>
 203  #endif
 204  
 205  /*
 206   * I/O descriptors for __sfvwrite().
 207   */
 208  struct __siov {
 209          void    *iov_base;
 210          size_t  iov_len;
 211  };
 212  struct __suio {
 213          struct  __siov *uio_iov;
 214          int     uio_iovcnt;
 215          int     uio_resid;
 216  };
 217  
 218  /*
 219   * Write some memory regions.  Return zero on success, EOF on error.
 220   *
 221   * This routine is large and unsightly, but most of the ugliness due
 222   * to the three different kinds of output buffering is handled here.
 223   */
 224  static BSD__sfvwrite(fp, uio)
 225          register FILE *fp;
 226          register struct __suio *uio;
 227  {
 228          register size_t len;
 229          register char *p;
 230          register struct __siov *iov;
 231          register int w;
 232  
 233          if ((len = uio->uio_resid) == 0)
 234                  return (0);
 235  #ifndef __hpux
 236  #define MIN(a, b) ((a) < (b) ? (a) : (b))
 237  #endif
 238  #define COPY(n)   (void)memcpy((void *)fp->_p, (void *)p, (size_t)(n))
 239  
 240          iov = uio->uio_iov;
 241          p = iov->iov_base;
 242          len = iov->iov_len;
 243          iov++;
 244  #define GETIOV(extra_work) \
 245          while (len == 0) { \
 246                  extra_work; \
 247                  p = iov->iov_base; \
 248                  len = iov->iov_len; \
 249                  iov++; \
 250          }
 251          if (fp->_flags & __SNBF) {
 252          /* fjc 7-31-97 Will never happen.  We are working with
 253                                             strings only
 254          */
 255          } else if ((fp->_flags & __SLBF) == 0) {
 256          /*
 257                   * Fully buffered: fill partially full buffer, if any,
 258                   * and then flush.  If there is no partial buffer, write
 259                   * one _bf._size byte chunk directly (without copying).
 260                   *
 261                   * String output is a special case: write as many bytes
 262                   * as fit, but pretend we wrote everything.  This makes
 263                   * snprintf() return the number of bytes needed, rather
 264                   * than the number used, and avoids its write function
 265                   * (so that the write function can be invalid).
 266                   */
 267                  do {
 268                          GETIOV(;);
 269                          w = fp->_w;
 270                          if (fp->_flags & __SSTR) {
 271                                  if (len < w)
 272                                          w = len;
 273                                  COPY(w);        /* copy MIN(fp->_w,len), */
 274                                  fp->_w -= w;
 275                                  fp->_p += w;
 276                                  w = len;        /* but pretend copied all */
 277                          } else {
 278                                  /* fjc 7-31-97 Will never happen.  We are working with
 279                                                                     strings only
 280                                  */
 281                          }
 282                          p += w;
 283                          len -= w;
 284                  } while ((uio->uio_resid -= w) != 0);
 285          } else {
 286                  /* fjc 7-31-97 Will never happen.  We are working with
 287                                                     strings only
 288                  */
 289          }
 290          return (0);
 291  
 292  err:
 293          fp->_flags |= __SERR;
 294          return (EOF);
 295  }
 296  
 297  /*
 298   * Actual printf innards.
 299   *
 300   * This code is large and complicated...
 301   */
 302  
 303  #if !defined(__CYGWIN32__) && defined(__hpux) && !defined(__GNUC__)
 304  #include <stdlib.h>
 305  #endif
 306  
 307  /*
 308   * Flush out all the vectors defined by the given uio,
 309   * then reset it so that it can be reused.
 310   */
 311  static int
 312  BSD__sprint(fp, uio)
 313          FILE *fp;
 314          register struct __suio *uio;
 315  {
 316          register int err;
 317  
 318          if (uio->uio_resid == 0) {
 319                  uio->uio_iovcnt = 0;
 320                  return (0);
 321          }
 322          err = BSD__sfvwrite(fp, uio);
 323          uio->uio_resid = 0;
 324          uio->uio_iovcnt = 0;
 325          return (err);
 326  }
 327  
 328  
 329  /*
 330   * Helper function for `fprintf to unbuffered unix file': creates a
 331   * temporary buffer.  We only work on write-only files; this avoids
 332   * worries about ungetc buffers and so forth.
 333   */
 334  static int
 335  BSD__sbprintf(fp, fmt, ap)
 336          register FILE *fp;
 337          const char *fmt;
 338          va_list ap;
 339  {
 340  /* We don't support files. */
 341          return 0;
 342  }
 343  
 344  
 345  /*
 346   * Macros for converting digits to letters and vice versa
 347   */
 348  #define to_digit(c)     ((c) - '0')
 349  #define is_digit(c)     ((unsigned)to_digit(c) <= 9)
 350  #define to_char(n)      ((n) + '0')
 351  
 352  /*
 353   * Convert an unsigned long to ASCII for printf purposes, returning
 354   * a pointer to the first character of the string representation.
 355   * Octal numbers can be forced to have a leading zero; hex numbers
 356   * use the given digits.
 357   */
 358  static char *
 359  BSD__ultoa(val, endp, base, octzero, xdigs)
 360          register u_long val;
 361          char *endp;
 362          int base, octzero;
 363          char *xdigs;
 364  {
 365          register char *cp = endp;
 366          register long sval;
 367  
 368          /*
 369           * Handle the three cases separately, in the hope of getting
 370           * better/faster code.
 371           */
 372          switch (base) {
 373          case 10:
 374                  if (val < 10) { /* many numbers are 1 digit */
 375                          *--cp = to_char(val);
 376                          return (cp);
 377                  }
 378                  /*
 379                   * On many machines, unsigned arithmetic is harder than
 380                   * signed arithmetic, so we do at most one unsigned mod and
 381                   * divide; this is sufficient to reduce the range of
 382                   * the incoming value to where signed arithmetic works.
 383                   */
 384                  if (val > LONG_MAX) {
 385                          *--cp = to_char(val % 10);
 386                          sval = val / 10;
 387                  } else
 388                          sval = val;
 389                  do {
 390                          *--cp = to_char(sval % 10);
 391                          sval /= 10;
 392                  } while (sval != 0);
 393                  break;
 394  
 395          case 8:
 396                  do {
 397                          *--cp = to_char(val & 7);
 398                          val >>= 3;
 399                  } while (val);
 400                  if (octzero && *cp != '0')
 401                          *--cp = '0';
 402                  break;
 403  
 404          case 16:
 405                  do {
 406                          *--cp = xdigs[val & 15];
 407                          val >>= 4;
 408                  } while (val);
 409                  break;
 410  
 411          default:                        /* oops */
 412                  /* 
 413                  abort();
 414                  */
 415                  break;  /* fjc 7-31-97.  Don't reference abort() here */
 416          }
 417          return (cp);
 418  }
 419  
 420  #ifdef FLOATING_POINT
 421  #include <math.h>
 422  /* #include "floatio.h" */
 423  
 424  #ifndef MAXEXP
 425  # define MAXEXP 1024
 426  #endif
 427  
 428  #ifndef MAXFRACT
 429  # define MAXFRACT 64
 430  #endif
 431  
 432  #define BUF             (MAXEXP+MAXFRACT+1)     /* + decimal point */
 433  #define DEFPREC         6
 434  
 435  static char *cvt __P((double, int, int, char *, int *, int, int *));
 436  static int exponent __P((char *, int, int));
 437  
 438  #else /* no FLOATING_POINT */
 439  
 440  #define BUF             68
 441  
 442  #endif /* FLOATING_POINT */
 443  
 444  
 445  /*
 446   * Flags used during conversion.
 447   */
 448  #define ALT             0x001           /* alternate form */
 449  #define HEXPREFIX       0x002           /* add 0x or 0X prefix */
 450  #define LADJUST         0x004           /* left adjustment */
 451  #define LONGDBL         0x008           /* long double; unimplemented */
 452  #define LONGINT         0x010           /* long integer */
 453  
 454  #ifdef _HAVE_SANE_QUAD_
 455  #define QUADINT         0x020           /* quad integer */
 456  #endif /* _HAVE_SANE_QUAD_ */
 457  
 458  #define SHORTINT        0x040           /* short integer */
 459  #define ZEROPAD         0x080           /* zero (as opposed to blank) pad */
 460  #define FPT             0x100           /* Floating point number */
 461  static int
 462  BSD_vfprintf(fp, fmt0, ap)
 463          FILE *fp;
 464          const char *fmt0;
 465          va_list ap;
 466  {
 467          register char *fmt;     /* format string */
 468          register int ch;        /* character from fmt */
 469          register int n;         /* handy integer (short term usage) */
 470          register char *cp;      /* handy char pointer (short term usage) */
 471          register struct __siov *iovp;/* for PRINT macro */
 472          register int flags;     /* flags as above */
 473          int ret;                /* return value accumulator */
 474          int width;              /* width from format (%8d), or 0 */
 475          int prec;               /* precision from format (%.3d), or -1 */
 476          char sign;              /* sign prefix (' ', '+', '-', or \0) */
 477  #ifdef FLOATING_POINT
 478          char softsign;          /* temporary negative sign for floats */
 479          double _double;         /* double precision arguments %[eEfgG] */
 480          int expt;               /* integer value of exponent */
 481          int expsize;            /* character count for expstr */
 482          int ndig;               /* actual number of digits returned by cvt */
 483          char expstr[7];         /* buffer for exponent string */
 484  #endif
 485          u_long  ulval;          /* integer arguments %[diouxX] */
 486  #ifdef _HAVE_SANE_QUAD_
 487          u_quad_t uqval;         /* %q integers */
 488  #endif /* _HAVE_SANE_QUAD_ */
 489          int base;               /* base for [diouxX] conversion */
 490          int dprec;              /* a copy of prec if [diouxX], 0 otherwise */
 491          int fieldsz;            /* field size expanded by sign, etc */
 492          int realsz;             /* field size expanded by dprec */
 493          int size;               /* size of converted field or string */
 494          char *xdigs;            /* digits for [xX] conversion */
 495  #define NIOV 8
 496          struct __suio uio;      /* output information: summary */
 497          struct __siov iov[NIOV];/* ... and individual io vectors */
 498          char buf[BUF];          /* space for %c, %[diouxX], %[eEfgG] */
 499          char ox[2];             /* space for 0x hex-prefix */
 500  
 501          /*
 502           * Choose PADSIZE to trade efficiency vs. size.  If larger printf
 503           * fields occur frequently, increase PADSIZE and make the initialisers
 504           * below longer.
 505           */
 506  #define PADSIZE 16              /* pad chunk size */
 507          static char blanks[PADSIZE] =
 508           {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
 509          static char zeroes[PADSIZE] =
 510           {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
 511  
 512          /*
 513           * BEWARE, these `goto error' on error, and PAD uses `n'.
 514           */
 515  #define PRINT(ptr, len) { \
 516          iovp->iov_base = (ptr); \
 517          iovp->iov_len = (len); \
 518          uio.uio_resid += (len); \
 519          iovp++; \
 520          if (++uio.uio_iovcnt >= NIOV) { \
 521                  if (BSD__sprint(fp, &uio)) \
 522                          goto error; \
 523                  iovp = iov; \
 524          } \
 525  }
 526  #define PAD(howmany, with) { \
 527          if ((n = (howmany)) > 0) { \
 528                  while (n > PADSIZE) { \
 529                          PRINT(with, PADSIZE); \
 530                          n -= PADSIZE; \
 531                  } \
 532                  PRINT(with, n); \
 533          } \
 534  }
 535  #define FLUSH() { \
 536          if (uio.uio_resid && BSD__sprint(fp, &uio)) \
 537                  goto error; \
 538          uio.uio_iovcnt = 0; \
 539          iovp = iov; \
 540  }
 541  
 542          /*
 543           * To extend shorts properly, we need both signed and unsigned
 544           * argument extraction methods.
 545           */
 546  #define SARG() \
 547          (flags&LONGINT ? va_arg(ap, long) : \
 548              flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
 549              (long)va_arg(ap, int))
 550  #define UARG() \
 551          (flags&LONGINT ? va_arg(ap, u_long) : \
 552              flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \
 553              (u_long)va_arg(ap, u_int))
 554  
 555          /* optimise fprintf(stderr) (and other unbuffered Unix files) */
 556          if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
 557              fp->_file >= 0)
 558                  return (BSD__sbprintf(fp, fmt0, ap));
 559  
 560          fmt = (char *)fmt0;
 561          uio.uio_iov = iovp = iov;
 562          uio.uio_resid = 0;
 563          uio.uio_iovcnt = 0;
 564          ret = 0;
 565  
 566          /*
 567           * Scan the format for conversions (`%' character).
 568           */
 569          for (;;) {
 570                  for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
 571                          /* void */;
 572                  if ((n = fmt - cp) != 0) {
 573                          PRINT(cp, n);
 574                          ret += n;
 575                  }
 576                  if (ch == '\0')
 577                          goto done;
 578                  fmt++;          /* skip over '%' */
 579  
 580                  flags = 0;
 581                  dprec = 0;
 582                  width = 0;
 583                  prec = -1;
 584                  sign = '\0';
 585  
 586  rflag:          ch = *fmt++;
 587  reswitch:       switch (ch) {
 588                  case ' ':
 589                          /*
 590                           * ``If the space and + flags both appear, the space
 591                           * flag will be ignored.''
 592                           *      -- ANSI X3J11
 593                           */
 594                          if (!sign)
 595                                  sign = ' ';
 596                          goto rflag;
 597                  case '#':
 598                          flags |= ALT;
 599                          goto rflag;
 600                  case '*':
 601                          /*
 602                           * ``A negative field width argument is taken as a
 603                           * - flag followed by a positive field width.''
 604                           *      -- ANSI X3J11
 605                           * They don't exclude field widths read from args.
 606                           */
 607                          if ((width = va_arg(ap, int)) >= 0)
 608                                  goto rflag;
 609                          width = -width;
 610                          /* FALLTHROUGH */
 611                  case '-':
 612                          flags |= LADJUST;
 613                          goto rflag;
 614                  case '+':
 615                          sign = '+';
 616                          goto rflag;
 617                  case '.':
 618                          if ((ch = *fmt++) == '*') {
 619                                  n = va_arg(ap, int);
 620                                  prec = n < 0 ? -1 : n;
 621                                  goto rflag;
 622                          }
 623                          n = 0;
 624                          while (is_digit(ch)) {
 625                                  n = 10 * n + to_digit(ch);
 626                                  ch = *fmt++;
 627                          }
 628                          prec = n < 0 ? -1 : n;
 629                          goto reswitch;
 630                  case '0':
 631                          /*
 632                           * ``Note that 0 is taken as a flag, not as the
 633                           * beginning of a field width.''
 634                           *      -- ANSI X3J11
 635                           */
 636                          flags |= ZEROPAD;
 637                          goto rflag;
 638                  case '1': case '2': case '3': case '4':
 639                  case '5': case '6': case '7': case '8': case '9':
 640                          n = 0;
 641                          do {
 642                                  n = 10 * n + to_digit(ch);
 643                                  ch = *fmt++;
 644                          } while (is_digit(ch));
 645                          width = n;
 646                          goto reswitch;
 647  #ifdef FLOATING_POINT
 648                  case 'L':
 649                          flags |= LONGDBL;
 650                          goto rflag;
 651  #endif
 652                  case 'h':
 653                          flags |= SHORTINT;
 654                          goto rflag;
 655                  case 'l':
 656                          flags |= LONGINT;
 657                          goto rflag;
 658  #ifdef _HAVE_SANE_QUAD_
 659                  case 'q':
 660                          flags |= QUADINT;
 661                          goto rflag;
 662  #endif /* _HAVE_SANE_QUAD_ */
 663                  case 'c':
 664                          *(cp = buf) = va_arg(ap, int);
 665                          size = 1;
 666                          sign = '\0';
 667                          break;
 668                  case 'D':
 669                          flags |= LONGINT;
 670                          /*FALLTHROUGH*/
 671                  case 'd':
 672                  case 'i':
 673  #ifdef _HAVE_SANE_QUAD_
 674                          if (flags & QUADINT) {
 675                                  uqval = va_arg(ap, quad_t);
 676                                  if ((quad_t)uqval < 0) {
 677                                          uqval = -uqval;
 678                                          sign = '-';
 679                                  }
 680                          } else {
 681  #else /* _HAVE_SANE_QUAD_ */
 682                          {
 683  #endif /* _HAVE_SANE_QUAD_ */
 684                                  ulval = SARG();
 685                                  if ((long)ulval < 0) {
 686                                          ulval = -ulval;
 687                                          sign = '-';
 688                                  }
 689                          }
 690                          base = 10;
 691                          goto number;
 692  #ifdef FLOATING_POINT
 693                  case 'e':               /* anomalous precision */
 694                  case 'E':
 695                          prec = (prec == -1) ?
 696                                  DEFPREC + 1 : prec + 1;
 697                          /* FALLTHROUGH */
 698                          goto fp_begin;
 699                  case 'f':               /* always print trailing zeroes */
 700                          if (prec != 0)
 701                                  flags |= ALT;
 702                  case 'g':
 703                  case 'G':
 704                          if (prec == -1)
 705                                  prec = DEFPREC;
 706  fp_begin:               _double = va_arg(ap, double);
 707                          /* do this before tricky precision changes */
 708                          if (isinf(_double)) {
 709                                  if (_double < 0)
 710                                          sign = '-';
 711                                  cp = "Inf";
 712                                  size = 3;
 713                                  break;
 714                          }
 715                          if (isnan(_double)) {
 716                                  cp = "NaN";
 717                                  size = 3;
 718                                  break;
 719                          }
 720                          flags |= FPT;
 721                          cp = cvt(_double, prec, flags, &softsign,
 722                                  &expt, ch, &ndig);
 723                          if (ch == 'g' || ch == 'G') {
 724                                  if (expt <= -4 || expt > prec)
 725                                          ch = (ch == 'g') ? 'e' : 'E';
 726                                  else
 727                                          ch = 'g';
 728                          } 
 729                          if (ch <= 'e') {        /* 'e' or 'E' fmt */
 730                                  --expt;
 731                                  expsize = exponent(expstr, expt, ch);
 732                                  size = expsize + ndig;
 733                                  if (ndig > 1 || flags & ALT)
 734                                          ++size;
 735                          } else if (ch == 'f') {         /* f fmt */
 736                                  if (expt > 0) {
 737                                          size = expt;
 738                                          if (prec || flags & ALT)
 739                                                  size += prec + 1;
 740                                  } else  /* "0.X" */
 741                                          size = prec + 2;
 742                          } else if (expt >= ndig) {      /* fixed g fmt */
 743                                  size = expt;
 744                                  if (flags & ALT)
 745                                          ++size;
 746                          } else
 747                                  size = ndig + (expt > 0 ?
 748                                          1 : 2 - expt);
 749  
 750                          if (softsign)
 751                                  sign = '-';
 752                          break;
 753  #endif /* FLOATING_POINT */
 754                  case 'n':
 755  #ifdef _HAVE_SANE_QUAD_
 756                          if (flags & QUADINT)
 757                                  *va_arg(ap, quad_t *) = ret;
 758                          else if (flags & LONGINT)
 759  #else /* _HAVE_SANE_QUAD_ */
 760                          if (flags & LONGINT)
 761  #endif /* _HAVE_SANE_QUAD_ */
 762                                  *va_arg(ap, long *) = ret;
 763                          else if (flags & SHORTINT)
 764                                  *va_arg(ap, short *) = ret;
 765                          else
 766                                  *va_arg(ap, int *) = ret;
 767                          continue;       /* no output */
 768                  case 'O':
 769                          flags |= LONGINT;
 770                          /*FALLTHROUGH*/
 771                  case 'o':
 772  #ifdef _HAVE_SANE_QUAD_
 773                          if (flags & QUADINT)
 774                                  uqval = va_arg(ap, u_quad_t);
 775                          else
 776  #endif /* _HAVE_SANE_QUAD_ */
 777                                  ulval = UARG();
 778                          base = 8;
 779                          goto nosign;
 780                  case 'p':
 781                          /*
 782                           * ``The argument shall be a pointer to void.  The
 783                           * value of the pointer is converted to a sequence
 784                           * of printable characters, in an implementation-
 785                           * defined manner.''
 786                           *      -- ANSI X3J11
 787                           */
 788                          ulval = (u_long)va_arg(ap, void *);
 789                          base = 16;
 790                          xdigs = "0123456789abcdef";
 791  #ifdef _HAVE_SANE_QUAD_
 792                          flags = (flags & ~QUADINT) | HEXPREFIX;
 793  #else /* _HAVE_SANE_QUAD_ */
 794                          flags = (flags) | HEXPREFIX;
 795  #endif /* _HAVE_SANE_QUAD_ */
 796                          ch = 'x';
 797                          goto nosign;
 798                  case 's':
 799                          if ((cp = va_arg(ap, char *)) == NULL)
 800                                  cp = "(null)";
 801                          if (prec >= 0) {
 802                                  /*
 803                                   * can't use strlen; can only look for the
 804                                   * NUL in the first `prec' characters, and
 805                                   * strlen() will go further.
 806                                   */
 807                                  char *p = (char *)memchr(cp, 0, prec);
 808  
 809                                  if (p != NULL) {
 810                                          size = p - cp;
 811                                          if (size > prec)
 812                                                  size = prec;
 813                                  } else
 814                                          size = prec;
 815                          } else
 816                                  size = strlen(cp);
 817                          sign = '\0';
 818                          break;
 819                  case 'U':
 820                          flags |= LONGINT;
 821                          /*FALLTHROUGH*/
 822                  case 'u':
 823  #ifdef _HAVE_SANE_QUAD_
 824                          if (flags & QUADINT)
 825                                  uqval = va_arg(ap, u_quad_t);
 826                          else
 827  #endif /* _HAVE_SANE_QUAD_ */
 828                                  ulval = UARG();
 829                          base = 10;
 830                          goto nosign;
 831                  case 'X':
 832                          xdigs = "0123456789ABCDEF";
 833                          goto hex;
 834                  case 'x':
 835                          xdigs = "0123456789abcdef";
 836  hex:
 837  #ifdef _HAVE_SANE_QUAD_
 838                          if (flags & QUADINT)
 839                                  uqval = va_arg(ap, u_quad_t);
 840                          else
 841  #endif /* _HAVE_SANE_QUAD_ */
 842                                  ulval = UARG();
 843                          base = 16;
 844                          /* leading 0x/X only if non-zero */
 845                          if (flags & ALT &&
 846  #ifdef _HAVE_SANE_QUAD_
 847                              (flags & QUADINT ? uqval != 0 : ulval != 0))
 848  #else /* _HAVE_SANE_QUAD_ */
 849                              ulval != 0)
 850  #endif /* _HAVE_SANE_QUAD_ */
 851                                  flags |= HEXPREFIX;
 852  
 853                          /* unsigned conversions */
 854  nosign:                 sign = '\0';
 855                          /*
 856                           * ``... diouXx conversions ... if a precision is
 857                           * specified, the 0 flag will be ignored.''
 858                           *      -- ANSI X3J11
 859                           */
 860  number:                 if ((dprec = prec) >= 0)
 861                                  flags &= ~ZEROPAD;
 862  
 863                          /*
 864                           * ``The result of converting a zero value with an
 865                           * explicit precision of zero is no characters.''
 866                           *      -- ANSI X3J11
 867                           */
 868                          cp = buf + BUF;
 869  #ifdef _HAVE_SANE_QUAD_
 870                          if (flags & QUADINT) {
 871                                  if (uqval != 0 || prec != 0)
 872                                          cp = __uqtoa(uqval, cp, base,
 873                                              flags & ALT, xdigs);
 874                          } else {
 875  #else /* _HAVE_SANE_QUAD_ */
 876                          {
 877  #endif /* _HAVE_SANE_QUAD_ */
 878                                  if (ulval != 0 || prec != 0)
 879                                          cp = BSD__ultoa(ulval, cp, base,
 880                                              flags & ALT, xdigs);
 881                          }
 882                          size = buf + BUF - cp;
 883                          break;
 884                  default:        /* "%?" prints ?, unless ? is NUL */
 885                          if (ch == '\0')
 886                                  goto done;
 887                          /* pretend it was %c with argument ch */
 888                          cp = buf;
 889                          *cp = ch;
 890                          size = 1;
 891                          sign = '\0';
 892                          break;
 893                  }
 894  
 895                  /*
 896                   * All reasonable formats wind up here.  At this point, `cp'
 897                   * points to a string which (if not flags&LADJUST) should be
 898                   * padded out to `width' places.  If flags&ZEROPAD, it should
 899                   * first be prefixed by any sign or other prefix; otherwise,
 900                   * it should be blank padded before the prefix is emitted.
 901                   * After any left-hand padding and prefixing, emit zeroes
 902                   * required by a decimal [diouxX] precision, then print the
 903                   * string proper, then emit zeroes required by any leftover
 904                   * floating precision; finally, if LADJUST, pad with blanks.
 905                   *
 906                   * Compute actual size, so we know how much to pad.
 907                   * fieldsz excludes decimal prec; realsz includes it.
 908                   */
 909                  fieldsz = size;
 910                  if (sign)
 911                          fieldsz++;
 912                  else if (flags & HEXPREFIX)
 913                          fieldsz += 2;
 914                  realsz = dprec > fieldsz ? dprec : fieldsz;
 915  
 916                  /* right-adjusting blank padding */
 917                  if ((flags & (LADJUST|ZEROPAD)) == 0)
 918                          PAD(width - realsz, blanks);
 919  
 920                  /* prefix */
 921                  if (sign) {
 922                          PRINT(&sign, 1);
 923                  } else if (flags & HEXPREFIX) {
 924                          ox[0] = '0';
 925                          ox[1] = ch;
 926                          PRINT(ox, 2);
 927                  }
 928  
 929                  /* right-adjusting zero padding */
 930                  if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
 931                          PAD(width - realsz, zeroes);
 932  
 933                  /* leading zeroes from decimal precision */
 934                  PAD(dprec - fieldsz, zeroes);
 935  
 936                  /* the string or number proper */
 937  #ifdef FLOATING_POINT
 938                  if ((flags & FPT) == 0) {
 939                          PRINT(cp, size);
 940                  } else {        /* glue together f_p fragments */
 941                          if (ch >= 'f') {        /* 'f' or 'g' */
 942                                  if (_double == 0) {
 943                                  /* kludge for __dtoa irregularity */
 944                                          if (prec == 0 ||
 945                                              (flags & ALT) == 0) {
 946                                                  PRINT("0", 1);
 947                                          } else {
 948                                                  PRINT("0.", 2);
 949                                                  PAD(ndig - 1, zeroes);
 950                                          }
 951                                  } else if (expt <= 0) {
 952                                          PRINT("0.", 2);
 953                                          PAD(-expt, zeroes);
 954                                          PRINT(cp, ndig);
 955                                  } else if (expt >= ndig) {
 956                                          PRINT(cp, ndig);
 957                                          PAD(expt - ndig, zeroes);
 958                                          if (flags & ALT)
 959                                                  PRINT(".", 1);
 960                                  } else {
 961                                          PRINT(cp, expt);
 962                                          cp += expt;
 963                                          PRINT(".", 1);
 964                                          PRINT(cp, ndig-expt);
 965                                  }
 966                          } else {        /* 'e' or 'E' */
 967                                  if (ndig > 1 || flags & ALT) {
 968                                          ox[0] = *cp++;
 969                                          ox[1] = '.';
 970                                          PRINT(ox, 2);
 971                                          if (_double || flags & ALT == 0) {
 972                                                  PRINT(cp, ndig-1);
 973                                          } else  /* 0.[0..] */
 974                                                  /* __dtoa irregularity */
 975                                                  PAD(ndig - 1, zeroes);
 976                                  } else  /* XeYYY */
 977                                          PRINT(cp, 1);
 978                                  PRINT(expstr, expsize);
 979                          }
 980                  }
 981  #else
 982                  PRINT(cp, size);
 983  #endif
 984                  /* left-adjusting padding (always blank) */
 985                  if (flags & LADJUST)
 986                          PAD(width - realsz, blanks);
 987  
 988                  /* finally, adjust ret */
 989                  ret += width > realsz ? width : realsz;
 990  
 991                  FLUSH();        /* copy out the I/O vectors */
 992          }
 993  done:
 994          FLUSH();
 995  error:
 996          return (__sferror(fp) ? EOF : ret);
 997          /* NOTREACHED */
 998  }
 999  
1000  #ifdef FLOATING_POINT
1001  
1002  extern char *BSD__dtoa __P((double, int, int, int *, int *, char **));
1003  
1004  static char *
1005  cvt(value, ndigits, flags, sign, decpt, ch, length)
1006          double value;
1007          int ndigits, flags, *decpt, ch, *length;
1008          char *sign;
1009  {
1010          int mode, dsgn;
1011          char *digits, *bp, *rve;
1012  
1013          if (ch == 'f')
1014                  mode = 3;
1015          else {
1016                  mode = 2;
1017          }
1018          if (value < 0) {
1019                  value = -value;
1020                  *sign = '-';
1021          } else if (value == 0.0 && 1.0/value < 0) {
1022              *sign = '-';
1023          } else {
1024              *sign = '\000';
1025          }
1026          digits = BSD__dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
1027          if (flags & ALT) {      /* Print trailing zeros */
1028                  bp = digits + ndigits;
1029                  if (ch == 'f') {
1030                          if (*digits == '0' && value)
1031                                  *decpt = -ndigits + 1;
1032                          bp += *decpt;
1033                  }
1034                  if (value == 0) /* kludge for __dtoa irregularity */
1035                          rve = bp;
1036                  while (rve < bp)
1037                          *rve++ = '0';
1038          }
1039          *length = rve - digits;
1040          return (digits);
1041  }
1042  
1043  static int
1044  exponent(p0, exp, fmtch)
1045          char *p0;
1046          int exp, fmtch;
1047  {
1048          register char *p, *t;
1049          char expbuf[MAXEXP];
1050  
1051          p = p0;
1052          *p++ = fmtch;
1053          if (exp < 0) {
1054                  exp = -exp;
1055                  *p++ = '-';
1056          }
1057          else
1058                  *p++ = '+';
1059          t = expbuf + MAXEXP;
1060          if (exp > 9) {
1061                  do {
1062                          *--t = to_char(exp % 10);
1063                  } while ((exp /= 10) > 9);
1064                  *--t = to_char(exp);
1065                  for (; t < expbuf + MAXEXP; *p++ = *t++);
1066          }
1067          else {
1068                  *p++ = '0';
1069                  *p++ = to_char(exp);
1070          }
1071          return (p - p0);
1072  }
1073  #endif /* FLOATING_POINT */
1074  
1075  int
1076  vsnprintf(str, n, fmt, ap)
1077          char *str;
1078          size_t n;
1079          const char *fmt;
1080          _BSD_VA_LIST_ ap;
1081  {
1082          int ret;
1083          FILE f;
1084  
1085          if ((int)n < 1)
1086                  return (EOF);
1087          f._flags = __SWR | __SSTR;
1088          f._bf._base = f._p = (unsigned char *)str;
1089          f._bf._size = f._w = n - 1;
1090          ret = BSD_vfprintf(&f, fmt, ap);
1091          *f._p = 0;
1092          return (ret);
1093  }
1094  
1095  #if defined(LIBC_SCCS) && !defined(lint)
1096  static char sccsid[] = "@(#)snprintf.c  8.1 (Berkeley) 6/4/93";
1097  #endif /* LIBC_SCCS and not lint */
1098  
1099  #if defined(__STDC__)
1100  # include <stdarg.h>
1101  #else
1102  # include <varargs.h>
1103  #endif
1104  
1105  int
1106  #if defined(__STDC__)
1107  snprintf(char *str, size_t n, char const *fmt, ...)
1108  #else
1109  snprintf(str, n, fmt, va_alist)
1110  char *str, *fmt;
1111  size_t n;
1112  va_dcl
1113  #endif
1114  {
1115          int ret;
1116          va_list ap;
1117          FILE f;
1118  
1119          if ((int)n < 1)
1120                  return (EOF);
1121  
1122  #if defined(__STDC__)
1123          va_start(ap, fmt);
1124  #else
1125          va_start(ap);
1126  #endif
1127          f._flags = __SWR | __SSTR;
1128          f._bf._base = f._p = (unsigned char *)str;
1129          f._bf._size = f._w = n - 1;
1130          ret = BSD_vfprintf(&f, fmt, ap);
1131          *f._p = 0;
1132          va_end(ap);
1133          return (ret);
1134  }