home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff319.lzh / CNewsSrc / uupc.lzh / vsprintf.c < prev   
C/C++ Source or Header  |  1990-02-06  |  4KB  |  187 lines

  1. /* Portable vsprintf  by Robert A. Larson <blarson@skat.usc.edu> */
  2.  
  3. /* Copyright 1989 Robert A. Larson.
  4.  * Distribution in any form is allowed as long as the author
  5.  * retains credit, changes are noted by their author, and the
  6.  * copyright message remains intact.  This program comes as-is
  7.  * with no warranty of fitness for any purpose.
  8.  *
  9.  * Thanks to Doug Gwen, Chris Torek, and others who helped clarify
  10.  * the ANSI printf specs.
  11.  *
  12.  * Please send any bug fixes and improvements to blarson@skat.usc.edu .
  13.  * The use of goto is NOT a bug.
  14.  */
  15.  
  16. /* Feb    7, 1989        blarson        First usenet release */
  17.  
  18. /* This code implements the vsprintf function, without relying on
  19.  * the existance of _doprnt or other system specific code.
  20.  *
  21.  * Define NOVOID if void * is not a supported type.
  22.  *
  23.  * Two compile options are available for efficiency:
  24.  *    INTSPRINTF    should be defined if sprintf is int and returns
  25.  *                the number of chacters formatted.
  26.  *    LONGINT        should be defined if sizeof(long) == sizeof(int)
  27.  *
  28.  * They only make the code smaller and faster, they need not be defined.
  29.  *
  30.  * UNSIGNEDSPECIAL should be defined if unsigned is treated differently
  31.  * than int in argument passing.  If this is defined, and LONGINT is not,
  32.  * the compiler must support the type unsingned long.
  33.  *
  34.  * NOVOID should be defined if the compiler does not allow the "void *"
  35.  * datatype.  "char*" will be used instead.
  36.  *
  37.  * Most quirks and bugs of the available sprintf fuction are duplicated,
  38.  * however "*" in the width and precision fields will work correctly
  39.  * even if sprintf does not support this, as will the %n format.
  40.  *
  41.  * Bad format strings, or those with very long width and precision
  42.  * fields (including expanded * fields) will cause undesired results.
  43.  */
  44.  
  45. #define ULONG    unsigned long
  46.  
  47. #ifdef OSK        /* os9/68k can take advantage of both */
  48. #  undef  ULONG
  49. #  define ULONG    unsigned int
  50. #  define LONGINT
  51. #  define INTSPRINTF
  52. #endif /* OSK */
  53.  
  54. #ifdef MCH_AMIGA
  55. #  define INTSPRINTF
  56. #  if sizeof(long) == sizeof(int)
  57. #    define LONGINT
  58. #  endif
  59. #else
  60. # ifdef AMIGA        /* Lattice can take advantage of both */
  61. #  define INTSPRINTF
  62. #  define LONGINT
  63. # endif /* AMIGA */
  64. #endif /* !MCH_AMIGA */
  65.  
  66. #ifdef NOVOID
  67. typedef char *pointer;
  68. #else
  69. typedef void *pointer;
  70. #endif /* NOVOID */
  71.  
  72. #ifdef    INTSPRINTF
  73. #  define Sprintf(string,format,arg)    (sprintf((string),(format),(arg)))
  74. #else
  75. #  define Sprintf(string,format,arg)    (\
  76.     sprintf((string),(format),(arg)),\
  77.     strlen(string)\
  78. )
  79. #endif /* INTSPRINTF */
  80.  
  81. #ifdef __STDC__
  82. #  include <stdarg.h>
  83. #else
  84. #  include "varargs.h"
  85. #endif /* __STDC__ */
  86.  
  87. typedef int *intp;
  88.  
  89. int vsprintf(dest, format, va_alist)
  90. char *dest;
  91. register char *format;
  92. va_dcl
  93. {
  94. #ifndef LONGINT
  95.     char longflag = 0;
  96. #endif /* !LONGINT */
  97.     register va_list args;
  98.     register char *dp = dest;
  99.     register char c;
  100.     register char *tp;
  101.     char tempfmt[64];
  102.  
  103.     va_start(args);            /* args = (char *) &va_alist; */
  104.     tempfmt[0] = '%';
  105.     while (c = *format++) {
  106.         if (c=='%') {
  107.             tp = &tempfmt[1];
  108. continue_format:
  109.             switch(c = *format++) {
  110.             case 's':
  111.                 *tp++ = c;
  112.                 *tp = '\0';
  113.                 dp += Sprintf(dp, tempfmt, va_arg(args, char *));
  114.                 break;
  115.             case 'u':
  116.             case 'x':
  117.             case 'o':
  118.             case 'X':
  119.             case 'd':
  120.             case 'c':
  121.             case 'i':
  122.                 *tp++ = c;
  123.                 *tp = '\0';
  124. #ifndef LONGINT
  125.                 if (longflag) {
  126.                     dp += Sprintf(dp, tempfmt, va_arg(args, ULONG));
  127.                     longflag = 0;
  128.                 } else
  129. #endif /* !LONGINT */
  130.                     dp += Sprintf(dp, tempfmt, va_arg(args, int));
  131.                 break;
  132.             case 'f':
  133.             case 'e':
  134.             case 'E':
  135.             case 'g':
  136.             case 'G':
  137.                 *tp++ = c;
  138.                 *tp = '\0';
  139.                 dp += Sprintf(dp, tempfmt, va_arg(args, double));
  140.                 break;
  141.             case 'p':
  142.                 *tp++ = c;
  143.                 *tp = '\0';
  144.                 dp += Sprintf(dp, tempfmt, va_arg(args, pointer));
  145.                 break;
  146.             case '-':
  147.             case '+':
  148.             case '0':
  149.             case '1':
  150.             case '2':
  151.             case '3':
  152.             case '4':
  153.             case '5':
  154.             case '6':
  155.             case '7':
  156.             case '8':
  157.             case '9':
  158.             case '.':
  159.             case ' ':
  160.             case '#':
  161.             case 'h':
  162.                 *tp++ = c;
  163.                 goto continue_format;
  164.             case 'l':
  165. #ifndef LONGINT
  166.                 longflag = 1;
  167.                 *tp++ = c;
  168. #endif /* !LONGINT */
  169.                 goto continue_format;
  170.             case '*':
  171.                 tp += Sprintf(tp, "%d", va_arg(args, int));
  172.                 goto continue_format;
  173.             case 'n':
  174.                 *va_arg(args, intp) = dp - dest;
  175.                 break;
  176.             case '%':
  177.             default:
  178.                 *dp++ = c;
  179.                 break;
  180.             }
  181.         } else
  182.             *dp++ = c;
  183.     }
  184.     *dp = '\0';
  185.     return( dp - dest );
  186. }
  187.