home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2374 / vprintf.c next >
C/C++ Source or Header  |  1990-12-28  |  6KB  |  302 lines

  1. #include <stdio.h>
  2.  
  3. /* Portable vfprintf  by Robert A. Larson <blarson@skat.usc.edu> */
  4.  
  5. /* Copyright 1989 Robert A. Larson.
  6.  * Distribution in any form is allowed as long as the author
  7.  * retains credit, changes are noted by their author and the
  8.  * copyright message remains intact.  This program comes as-is
  9.  * with no warentee of fitness for any purpouse.
  10.  *
  11.  * Thanks to Doug Gwen, Chris Torek, and others who helped clarify
  12.  * the ansi printf specs.
  13.  *
  14.  * Please send any bug fixes and improvments to blarson@skat.usc.edu .
  15.  * The use of goto is NOT a bug.
  16.  */
  17.  
  18. /* Feb    7, 1989        blarson        First usenet release */
  19.  
  20. /* This code implements the vsprintf function, without relying on
  21.  * the existance of _doprint or other system specific code.
  22.  *
  23.  * Define NOVOID if void * is not a supported type.
  24.  *
  25.  * Two compile options are available for efficency:
  26.  *    INTSPRINTF    should be defined if sprintf is int and returns
  27.  *            the number of chacters formated.
  28.  *    LONGINT        should be defined if sizeof(long) == sizeof(int)
  29.  *
  30.  *    They only make the code smaller and faster, they need not be
  31.  *    defined.
  32.  *
  33.  * UNSIGNEDSPECIAL should be defined if unsigned is treated differently
  34.  * than int in argument passing.  If this is definded, and LONGINT is not,
  35.  * the compiler must support the type unsingned long.
  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. #ifdef OSK        /* os9/68k can take advantage of both */
  46. #define LONGINT
  47. #define INTSPRINTF
  48. #endif
  49.  
  50. /* This must be a typedef not a #define! */
  51. #ifdef NOVOID
  52. typedef char *pointer;
  53. #else
  54. typedef void *pointer;
  55. #endif
  56.  
  57. #ifdef    INTSPRINTF
  58. #define Sprintf(string,format,arg)    (sprintf((string),(format),(arg)))
  59. #else
  60. #define Sprintf(string,format,arg)    (\
  61.     sprintf((string),(format),(arg)),\
  62.     strlen(string)\
  63. )
  64. #endif
  65.  
  66. #if defined(__STDC__) && !defined(NOSTDHDRS)
  67. #include <stdarg.h>
  68. #else
  69. #include <varargs.h>
  70. #endif
  71.  
  72. typedef int *intp;
  73.  
  74. int vsprintf(dest, format, args)
  75. char *dest;
  76. register char *format;
  77. va_list args;
  78. {
  79.     register char *dp = dest;
  80.     register char c;
  81.     register char *tp;
  82.     char tempfmt[64];
  83. #ifndef LONGINT
  84.     int longflag;
  85. #endif
  86.  
  87.     tempfmt[0] = '%';
  88.     while(c = *format++) {
  89.     if(c=='%') {
  90.         tp = &tempfmt[1];
  91. #ifndef LONGINT
  92.         longflag = 0;
  93. #endif
  94. continue_format:
  95.         switch(c = *format++) {
  96.         case 's':
  97.             *tp++ = c;
  98.             *tp = '\0';
  99.             dp += Sprintf(dp, tempfmt, va_arg(args, char *));
  100.             break;
  101.         case 'u':
  102.         case 'x':
  103.         case 'o':
  104.         case 'X':
  105. #ifdef UNSIGNEDSPECIAL
  106.             *tp++ = c;
  107.             *tp = '\0';
  108. #ifndef LONGINT
  109.             if(longflag)
  110.             dp += Sprintf(dp, tempfmt, va_arg(args, unsigned long));
  111.             else
  112. #endif
  113.             dp += Sprintf(dp, tempfmt, va_arg(args, unsigned));
  114.             break;
  115. #endif
  116.         case 'd':
  117.         case 'c':
  118.         case 'i':
  119.             *tp++ = c;
  120.             *tp = '\0';
  121. #ifndef LONGINT
  122.             if(longflag)
  123.             dp += Sprintf(dp, tempfmt, va_arg(args, long));
  124.             else
  125. #endif
  126.             dp += Sprintf(dp, tempfmt, va_arg(args, int));
  127.             break;
  128.         case 'f':
  129.         case 'e':
  130.         case 'E':
  131.         case 'g':
  132.         case 'G':
  133.             *tp++ = c;
  134.             *tp = '\0';
  135.             dp += Sprintf(dp, tempfmt, va_arg(args, double));
  136.             break;
  137.         case 'p':
  138.             *tp++ = c;
  139.             *tp = '\0';
  140.             dp += Sprintf(dp, tempfmt, va_arg(args, pointer));
  141.             break;
  142.         case '-':
  143.         case '+':
  144.         case '0':
  145.         case '1':
  146.         case '2':
  147.         case '3':
  148.         case '4':
  149.         case '5':
  150.         case '6':
  151.         case '7':
  152.         case '8':
  153.         case '9':
  154.         case '.':
  155.         case ' ':
  156.         case '#':
  157.         case 'h':
  158.             *tp++ = c;
  159.             goto continue_format;
  160.         case 'l':
  161. #ifndef LONGINT
  162.             longflag = 1;
  163.             *tp++ = c;
  164. #endif
  165.             goto continue_format;
  166.         case '*':
  167.             tp += Sprintf(tp, "%d", va_arg(args, int));
  168.             goto continue_format;
  169.         case 'n':
  170.             *va_arg(args, intp) = dp - dest;
  171.             break;
  172.         case '%':
  173.         default:
  174.             *dp++ = c;
  175.             break;
  176.         }
  177.     } else *dp++ = c;
  178.     }
  179.     *dp = '\0';
  180.     return dp - dest;
  181. }
  182.  
  183.  
  184. int vfprintf(dest, format, args)
  185. FILE *dest;
  186. register char *format;
  187. va_list args;
  188. {
  189.     register char c;
  190.     register char *tp;
  191.     register int count = 0;
  192.     char tempfmt[64];
  193. #ifndef LONGINT
  194.     int longflag;
  195. #endif
  196.  
  197.     tempfmt[0] = '%';
  198.     while(c = *format++) {
  199.     if(c=='%') {
  200.         tp = &tempfmt[1];
  201. #ifndef LONGINT
  202.         longflag = 0;
  203. #endif
  204. continue_format:
  205.         switch(c = *format++) {
  206.         case 's':
  207.             *tp++ = c;
  208.             *tp = '\0';
  209.             count += fprintf(dest, tempfmt, va_arg(args, char *));
  210.             break;
  211.         case 'u':
  212.         case 'x':
  213.         case 'o':
  214.         case 'X':
  215. #ifdef UNSIGNEDSPECIAL
  216.             *tp++ = c;
  217.             *tp = '\0';
  218. #ifndef LONGINT
  219.             if(longflag)
  220.             count += fprintf(dest, tempfmt, va_arg(args, unsigned long));
  221.             else
  222. #endif
  223.             count += fprintf(dest, tempfmt, va_arg(args, unsigned));
  224.             break;
  225. #endif
  226.         case 'd':
  227.         case 'c':
  228.         case 'i':
  229.             *tp++ = c;
  230.             *tp = '\0';
  231. #ifndef LONGINT
  232.             if(longflag)
  233.             count += fprintf(dest, tempfmt, va_arg(args, long));
  234.             else
  235. #endif
  236.             count += fprintf(dest, tempfmt, va_arg(args, int));
  237.             break;
  238.         case 'f':
  239.         case 'e':
  240.         case 'E':
  241.         case 'g':
  242.         case 'G':
  243.             *tp++ = c;
  244.             *tp = '\0';
  245.             count += fprintf(dest, tempfmt, va_arg(args, double));
  246.             break;
  247.         case 'p':
  248.             *tp++ = c;
  249.             *tp = '\0';
  250.             count += fprintf(dest, tempfmt, va_arg(args, pointer));
  251.             break;
  252.         case '-':
  253.         case '+':
  254.         case '0':
  255.         case '1':
  256.         case '2':
  257.         case '3':
  258.         case '4':
  259.         case '5':
  260.         case '6':
  261.         case '7':
  262.         case '8':
  263.         case '9':
  264.         case '.':
  265.         case ' ':
  266.         case '#':
  267.         case 'h':
  268.             *tp++ = c;
  269.             goto continue_format;
  270.         case 'l':
  271. #ifndef LONGINT
  272.             longflag = 1;
  273.             *tp++ = c;
  274. #endif
  275.             goto continue_format;
  276.         case '*':
  277.             tp += Sprintf(tp, "%d", va_arg(args, int));
  278.             goto continue_format;
  279.         case 'n':
  280.             *va_arg(args, intp) = count;
  281.             break;
  282.         case '%':
  283.         default:
  284.             putc(c, dest);
  285.             count++;
  286.             break;
  287.         }
  288.     } else {
  289.         putc(c, dest);
  290.         count++;
  291.     }
  292.     }
  293.     return count;
  294. }
  295.  
  296. vprintf(format, args)
  297. char *format;
  298. va_list args;
  299. {
  300.     return vfprintf(stdout, format, args);
  301. }
  302.