home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / lang / c / 11571 < prev    next >
Encoding:
Text File  |  1992-07-25  |  4.8 KB  |  127 lines

  1. Newsgroups: comp.lang.c
  2. Path: sparky!uunet!snorkelwacker.mit.edu!thunder.mcrcim.mcgill.edu!sobeco!ozrout!stirling
  3. From: stirling@ozrout.uucp (Stirling Westrup)
  4. Subject: Re: (Help) dynamic use of sprintf ?
  5. Organization: Andre P. Ozrout
  6. Date: Fri, 24 Jul 1992 16:45:18 GMT
  7. Message-ID: <1992Jul24.164518.27683@ozrout.uucp>
  8. References: <1992Jul21.201712.20985@BitBlocks.COM>
  9. Lines: 116
  10.  
  11. bvs@BitBlocks.COM (Bakul Shah) writes:
  12. >
  13. >I have a vfprintf like function, called `vfnprintf' that takes a
  14. >_function pointer_ instead of a FILE *.  vfnprintf calls this
  15. >function, possibly multiple times, to drain already formatted
  16. >characters.  _You_ supply the function.  Here is an example use.
  17.  
  18. [Some code deleted...]
  19.  
  20. >  /* typedef for a function ptr */
  21. >  typedef int (*_vfn_t)(void * st, const char * string, unsigned int count);
  22. >
  23. >  int vfnprintf(_vfn_t fn, void * st, const char * format, va_list args);
  24.  
  25. [More code deleted...]
  26.  
  27. >  int snprintf(char * str, int size, const char * fmt, ...) {
  28. >      int count;
  29. >      va_list args;
  30. >      struct snstate snstate;
  31. >      snstate.size = size;
  32. >      snstate.offset = 0;
  33. >      snstate.buffer = str;
  34. >
  35. >      va_start(args, fmt);
  36. >      count = vfnprintf((_vfn_t)sndrain, &snstate, fmt, args);
  37. >      va_end(args);
  38. >      return count;
  39. >  }
  40. >
  41.  
  42. The above aproach is very similar to the one I took when I needed to
  43. provide flexible handling of format strings (even to the fact that I also
  44. did not bother with the floating point formats).  There is one major
  45. difference between our ways of doing things.  My function (called 'fmt')
  46. accepts two void pointers, and returns a void pointer.  The intent was to
  47. allow for a printf-type function to return something other than an integer
  48. count.  For instance, my implementation of saprintf returns a pointer to 
  49. the newly allocated string.  This does make for some added complexity for
  50. simple cases like the above though, and I'm not entirely sure its worth it.
  51.  
  52. The basic idea is that one of the void pointers passed to the function is
  53. for state information, and the other is for some sort of accumulating
  54. result.  The ancillary function (called 'sndrain' in the above code) 
  55. would use the result from the previous invocation of itself to compute the
  56. result for this invocation.  This may be clearer if I include the
  57. definition of snprintf from my own library.  I think most of the types
  58. should be clear from context, except perhaps for Nat which is an unsigned
  59. int.  Oh, the Vpl... stuff is just an alias for the va_... stuff from ANSI.
  60. I use my own names due to certain bugs I've had to work around in various
  61. compilers.
  62.  
  63.  
  64. Struct StrLen StrLen;
  65.  
  66. Struct StrLen                   /* String/Length pair for snput */
  67.   { Char *str;                    /* string to write into */
  68.     Nat len;                      /* max characters to put in string */
  69.   };
  70.  
  71. Static Void *snput              /* put a chunk of text into a string */
  72.   ( Const Char *txt,              /* pointer to thte *
  73.     Nat len,                      /* length of the text */
  74.     Void *ctx,                    /* context (StrLen pointer) */
  75.     Void *rsl                     /* result (pointer to a character counter) */
  76.   )
  77.   { Register Struct StrLen sl = x;      /* recover type of StrLen pointer */
  78.     Register Nat idx = 0;               /* We need an index, why not a reg? */
  79.     Nat *num = rsl;                     /* recover type of counter pointer */
  80.  
  81.     while( len && sl->len )             /* while text, and a place for it... */
  82.       {
  83.         *(sl->str++) = txt[idx++];      /* Copy a char into the string */
  84.         len--;                          /* one less char to copy */
  85.         sl->len--;                      /* one less space ithe string */
  86.       }
  87.     *(sl->str) = 0;                     /* null terminate the string */
  88.     (*num) += idx;                      /* and bump counter by chars moved */
  89.     return rsl;                         /* return our result pointer */
  90.   }
  91.  
  92. /*
  93.   snprintf - printf'er to a string, with size maximum 
  94.   Takes a pointer to a buffer, the size of the buffer (including space for the
  95.   trailing 0), a printf format string, and a variable parameter list.
  96.   The function stores the formatted string in the buffer, or as much as will
  97.   fit.  The buffer will be null tminated.
  98.   The function returns the number of characters actually stored.
  99. */
  100.  
  101. Nat snprintf
  102.   ( Char *buf,
  103.     Nat len,
  104.     Const Char *str,
  105.     ...
  106.   )
  107.   { StrLen sl;
  108.     Nat num = 0;
  109.     Vpl args;
  110.  
  111.     if( !buf || len < 2 )
  112.       return 0;
  113.     sl.str = buf;
  114.     sl.len = len-1;
  115.     vplBeg(args,str);
  116.     fmt(snput, &sl, &num, str, args);
  117.     vplEnd(args);
  118.     return num;
  119.   }
  120.  
  121.  
  122. -- 
  123. ||    BUNGEE SIDEWAYS!                              o   )))
  124. ||                                                 /-- ///
  125. |P~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\_  \\\      __ -_
  126. ||    stirling@ozrout.uucp                                 ((( (_)T(_)
  127.