Always exit D-lined clients with reason "D-lined" and K-lined clients with "K-lined".
[seven-1.x.git] / libseven / snprintf.c
blobfbceebd5b921e481311d445da00e044b2dc1b591
1 /*
2 * libString, Copyright (C) 1999 Patrick Alken
3 * This library comes with absolutely NO WARRANTY
5 * Should you choose to use and/or modify this source code, please
6 * do so under the terms of the GNU General Public License under which
7 * this library is distributed.
9 * $Id: snprintf.c 26 2006-09-20 18:02:06Z spb $
12 #include <stdio.h>
13 #include <stdarg.h>
14 #include <stdlib.h>
15 #include <sys/types.h>
16 #include <ctype.h>
17 #include "setup.h"
18 #include "sprintf_irc.h"
21 * This table is arranged in chronological order from 0-999,
22 * however the numbers are written backwards, so the number 100
23 * is expressed in this table as "001".
24 * It's purpose is to ensure fast conversions from integers to
25 * ASCII strings. When an integer variable is encountered, a
26 * simple hash algorithm is used to determine where to look
27 * in this array for the corresponding string.
28 * This outperforms continually dividing by 10 and using the
29 * digit obtained as a character, because we can now divide by
30 * 1000 and use the remainder directly, thus cutting down on
31 * the number of costly divisions needed. For an integer's worst
32 * case, 2 divisions are needed because it can only go up to
33 * 32767, so after 2 divisions by 1000, and some algebra, we will
34 * be left with 327 which we can get from this table. This is much
35 * better than the 5 divisions by 10 that we would need if we did
36 * it the conventional way. Of course, if we made this table go
37 * from 0-9999, only 1 division would be needed.
38 * Longs and unsigned ints of course, are another matter :-).
40 * Patrick Alken <wnder@underworld.net>
44 * Set this to the number of indices (numbers) in our table
46 #define TABLE_MAX 1000
48 static const char *IntTable[] = {
49 "000", "100", "200", "300", "400",
50 "500", "600", "700", "800", "900",
51 "010", "110", "210", "310", "410",
52 "510", "610", "710", "810", "910",
53 "020", "120", "220", "320", "420",
54 "520", "620", "720", "820", "920",
55 "030", "130", "230", "330", "430",
56 "530", "630", "730", "830", "930",
57 "040", "140", "240", "340", "440",
58 "540", "640", "740", "840", "940",
59 "050", "150", "250", "350", "450",
60 "550", "650", "750", "850", "950",
61 "060", "160", "260", "360", "460",
62 "560", "660", "760", "860", "960",
63 "070", "170", "270", "370", "470",
64 "570", "670", "770", "870", "970",
65 "080", "180", "280", "380", "480",
66 "580", "680", "780", "880", "980",
67 "090", "190", "290", "390", "490",
68 "590", "690", "790", "890", "990",
69 "001", "101", "201", "301", "401",
70 "501", "601", "701", "801", "901",
71 "011", "111", "211", "311", "411",
72 "511", "611", "711", "811", "911",
73 "021", "121", "221", "321", "421",
74 "521", "621", "721", "821", "921",
75 "031", "131", "231", "331", "431",
76 "531", "631", "731", "831", "931",
77 "041", "141", "241", "341", "441",
78 "541", "641", "741", "841", "941",
79 "051", "151", "251", "351", "451",
80 "551", "651", "751", "851", "951",
81 "061", "161", "261", "361", "461",
82 "561", "661", "761", "861", "961",
83 "071", "171", "271", "371", "471",
84 "571", "671", "771", "871", "971",
85 "081", "181", "281", "381", "481",
86 "581", "681", "781", "881", "981",
87 "091", "191", "291", "391", "491",
88 "591", "691", "791", "891", "991",
89 "002", "102", "202", "302", "402",
90 "502", "602", "702", "802", "902",
91 "012", "112", "212", "312", "412",
92 "512", "612", "712", "812", "912",
93 "022", "122", "222", "322", "422",
94 "522", "622", "722", "822", "922",
95 "032", "132", "232", "332", "432",
96 "532", "632", "732", "832", "932",
97 "042", "142", "242", "342", "442",
98 "542", "642", "742", "842", "942",
99 "052", "152", "252", "352", "452",
100 "552", "652", "752", "852", "952",
101 "062", "162", "262", "362", "462",
102 "562", "662", "762", "862", "962",
103 "072", "172", "272", "372", "472",
104 "572", "672", "772", "872", "972",
105 "082", "182", "282", "382", "482",
106 "582", "682", "782", "882", "982",
107 "092", "192", "292", "392", "492",
108 "592", "692", "792", "892", "992",
109 "003", "103", "203", "303", "403",
110 "503", "603", "703", "803", "903",
111 "013", "113", "213", "313", "413",
112 "513", "613", "713", "813", "913",
113 "023", "123", "223", "323", "423",
114 "523", "623", "723", "823", "923",
115 "033", "133", "233", "333", "433",
116 "533", "633", "733", "833", "933",
117 "043", "143", "243", "343", "443",
118 "543", "643", "743", "843", "943",
119 "053", "153", "253", "353", "453",
120 "553", "653", "753", "853", "953",
121 "063", "163", "263", "363", "463",
122 "563", "663", "763", "863", "963",
123 "073", "173", "273", "373", "473",
124 "573", "673", "773", "873", "973",
125 "083", "183", "283", "383", "483",
126 "583", "683", "783", "883", "983",
127 "093", "193", "293", "393", "493",
128 "593", "693", "793", "893", "993",
129 "004", "104", "204", "304", "404",
130 "504", "604", "704", "804", "904",
131 "014", "114", "214", "314", "414",
132 "514", "614", "714", "814", "914",
133 "024", "124", "224", "324", "424",
134 "524", "624", "724", "824", "924",
135 "034", "134", "234", "334", "434",
136 "534", "634", "734", "834", "934",
137 "044", "144", "244", "344", "444",
138 "544", "644", "744", "844", "944",
139 "054", "154", "254", "354", "454",
140 "554", "654", "754", "854", "954",
141 "064", "164", "264", "364", "464",
142 "564", "664", "764", "864", "964",
143 "074", "174", "274", "374", "474",
144 "574", "674", "774", "874", "974",
145 "084", "184", "284", "384", "484",
146 "584", "684", "784", "884", "984",
147 "094", "194", "294", "394", "494",
148 "594", "694", "794", "894", "994",
149 "005", "105", "205", "305", "405",
150 "505", "605", "705", "805", "905",
151 "015", "115", "215", "315", "415",
152 "515", "615", "715", "815", "915",
153 "025", "125", "225", "325", "425",
154 "525", "625", "725", "825", "925",
155 "035", "135", "235", "335", "435",
156 "535", "635", "735", "835", "935",
157 "045", "145", "245", "345", "445",
158 "545", "645", "745", "845", "945",
159 "055", "155", "255", "355", "455",
160 "555", "655", "755", "855", "955",
161 "065", "165", "265", "365", "465",
162 "565", "665", "765", "865", "965",
163 "075", "175", "275", "375", "475",
164 "575", "675", "775", "875", "975",
165 "085", "185", "285", "385", "485",
166 "585", "685", "785", "885", "985",
167 "095", "195", "295", "395", "495",
168 "595", "695", "795", "895", "995",
169 "006", "106", "206", "306", "406",
170 "506", "606", "706", "806", "906",
171 "016", "116", "216", "316", "416",
172 "516", "616", "716", "816", "916",
173 "026", "126", "226", "326", "426",
174 "526", "626", "726", "826", "926",
175 "036", "136", "236", "336", "436",
176 "536", "636", "736", "836", "936",
177 "046", "146", "246", "346", "446",
178 "546", "646", "746", "846", "946",
179 "056", "156", "256", "356", "456",
180 "556", "656", "756", "856", "956",
181 "066", "166", "266", "366", "466",
182 "566", "666", "766", "866", "966",
183 "076", "176", "276", "376", "476",
184 "576", "676", "776", "876", "976",
185 "086", "186", "286", "386", "486",
186 "586", "686", "786", "886", "986",
187 "096", "196", "296", "396", "496",
188 "596", "696", "796", "896", "996",
189 "007", "107", "207", "307", "407",
190 "507", "607", "707", "807", "907",
191 "017", "117", "217", "317", "417",
192 "517", "617", "717", "817", "917",
193 "027", "127", "227", "327", "427",
194 "527", "627", "727", "827", "927",
195 "037", "137", "237", "337", "437",
196 "537", "637", "737", "837", "937",
197 "047", "147", "247", "347", "447",
198 "547", "647", "747", "847", "947",
199 "057", "157", "257", "357", "457",
200 "557", "657", "757", "857", "957",
201 "067", "167", "267", "367", "467",
202 "567", "667", "767", "867", "967",
203 "077", "177", "277", "377", "477",
204 "577", "677", "777", "877", "977",
205 "087", "187", "287", "387", "487",
206 "587", "687", "787", "887", "987",
207 "097", "197", "297", "397", "497",
208 "597", "697", "797", "897", "997",
209 "008", "108", "208", "308", "408",
210 "508", "608", "708", "808", "908",
211 "018", "118", "218", "318", "418",
212 "518", "618", "718", "818", "918",
213 "028", "128", "228", "328", "428",
214 "528", "628", "728", "828", "928",
215 "038", "138", "238", "338", "438",
216 "538", "638", "738", "838", "938",
217 "048", "148", "248", "348", "448",
218 "548", "648", "748", "848", "948",
219 "058", "158", "258", "358", "458",
220 "558", "658", "758", "858", "958",
221 "068", "168", "268", "368", "468",
222 "568", "668", "768", "868", "968",
223 "078", "178", "278", "378", "478",
224 "578", "678", "778", "878", "978",
225 "088", "188", "288", "388", "488",
226 "588", "688", "788", "888", "988",
227 "098", "198", "298", "398", "498",
228 "598", "698", "798", "898", "998",
229 "009", "109", "209", "309", "409",
230 "509", "609", "709", "809", "909",
231 "019", "119", "219", "319", "419",
232 "519", "619", "719", "819", "919",
233 "029", "129", "229", "329", "429",
234 "529", "629", "729", "829", "929",
235 "039", "139", "239", "339", "439",
236 "539", "639", "739", "839", "939",
237 "049", "149", "249", "349", "449",
238 "549", "649", "749", "849", "949",
239 "059", "159", "259", "359", "459",
240 "559", "659", "759", "859", "959",
241 "069", "169", "269", "369", "469",
242 "569", "669", "769", "869", "969",
243 "079", "179", "279", "379", "479",
244 "579", "679", "779", "879", "979",
245 "089", "189", "289", "389", "489",
246 "589", "689", "789", "889", "989",
247 "099", "199", "299", "399", "499",
248 "599", "699", "799", "899", "999"
252 * Since we calculate the right-most digits for %d %u etc first,
253 * we need a temporary buffer to store them in until we get
254 * to the left-most digits
257 #define TEMPBUF_MAX 20
259 static char TempBuffer[TEMPBUF_MAX];
262 vSnprintf()
263 Backend to Snprintf() - performs the construction of 'dest'
264 using the string 'format' and the given arguments. Also makes sure
265 not more than 'bytes' characters are copied to 'dest'
267 We always allow room for a terminating \0 character, so at most,
268 bytes - 1 characters will be written to dest.
270 Return: Number of characters written, NOT including the terminating
271 \0 character which is *always* placed at the end of the string
273 NOTE: This function handles the following flags only:
274 %s %d %c %u %ld %lu
275 In addition, this function performs *NO* precision, padding,
276 or width formatting. If it receives an unknown % character,
277 it will call vsprintf() to complete the remainder of the
278 string.
282 ircvsnprintf(char *dest, const size_t bytes, const char *format, va_list args)
284 char ch;
285 int written = 0; /* bytes written so far */
286 int maxbytes = bytes - 1;
288 while ((ch = *format++) && (written < maxbytes))
290 if(ch == '%')
293 * Advance past the %
295 ch = *format++;
298 * Put the most common cases first - %s %d etc
301 if(ch == 's')
303 const char *str = va_arg(args, const char *);
305 while ((*dest = *str))
307 ++dest;
308 ++str;
310 if(++written >= maxbytes)
311 break;
314 continue;
317 if(ch == 'd')
319 int num = va_arg(args, int);
320 int quotient;
321 const char *str;
322 char *digitptr = TempBuffer;
325 * We have to special-case "0" unfortunately
327 if(num == 0)
329 *dest++ = '0';
330 ++written;
331 continue;
334 if(num < 0)
336 *dest++ = '-';
337 if(++written >= maxbytes)
338 continue;
340 num = -num;
345 quotient = num / TABLE_MAX;
348 * We'll start with the right-most digits of 'num'.
349 * Dividing by TABLE_MAX cuts off all but the X
350 * right-most digits, where X is such that:
352 * 10^X = TABLE_MAX
354 * For example, if num = 1200, and TABLE_MAX = 1000,
355 * quotient will be 1. Multiplying this by 1000 and
356 * subtracting from 1200 gives: 1200 - (1 * 1000) = 200.
357 * We then go right to slot 200 in our array and behold!
358 * The string "002" (200 backwards) is conveniently
359 * waiting for us. Then repeat the process with the
360 * digits left.
362 * The reason we need to have the integers written
363 * backwards, is because we don't know how many digits
364 * there are. If we want to express the number 12130
365 * for example, our first pass would leave us with 130,
366 * whose slot in the array yields "031", which we
367 * plug into our TempBuffer[]. The next pass gives us
368 * 12, whose slot yields "21" which we append to
369 * TempBuffer[], leaving us with "03121". This is the
370 * exact number we want, only backwards, so it is
371 * a simple matter to reverse the string. If we used
372 * straightfoward numbers, we would have a TempBuffer
373 * looking like this: "13012" which would be a nightmare
374 * to deal with.
377 str = IntTable[num - (quotient * TABLE_MAX)];
379 while ((*digitptr = *str))
381 ++digitptr;
382 ++str;
385 while ((num = quotient) != 0);
388 * If the last quotient was a 1 or 2 digit number, there
389 * will be one or more leading zeroes in TempBuffer[] -
390 * get rid of them.
392 while (*(digitptr - 1) == '0')
393 --digitptr;
395 while (digitptr != TempBuffer)
397 *dest++ = *--digitptr;
398 if(++written >= maxbytes)
399 break;
402 continue;
403 } /* if (ch == 'd') */
405 if(ch == 'c')
407 *dest++ = va_arg(args, int);
409 ++written;
411 continue;
412 } /* if (ch == 'c') */
414 if(ch == 'u')
416 unsigned int num = va_arg(args, unsigned int);
417 unsigned int quotient;
418 const char *str;
419 char *digitptr = TempBuffer;
421 if(num == 0)
423 *dest++ = '0';
424 ++written;
425 continue;
430 quotient = num / TABLE_MAX;
433 * Very similar to case 'd'
436 str = IntTable[num - (quotient * TABLE_MAX)];
438 while ((*digitptr = *str))
440 ++digitptr;
441 ++str;
444 while ((num = quotient) != 0);
446 while (*(digitptr - 1) == '0')
447 --digitptr;
449 while (digitptr != TempBuffer)
451 *dest++ = *--digitptr;
452 if(++written >= maxbytes)
453 break;
456 continue;
457 } /* if (ch == 'u') */
459 if(ch == 'l')
461 if(*format == 'u')
463 unsigned long num = va_arg(args, unsigned long);
464 unsigned long quotient;
465 const char *str;
466 char *digitptr = TempBuffer;
468 ++format;
470 if(num == 0)
472 *dest++ = '0';
473 ++written;
474 continue;
479 quotient = num / TABLE_MAX;
482 * Very similar to case 'u'
485 str = IntTable[num - (quotient * TABLE_MAX)];
487 while ((*digitptr = *str))
489 ++digitptr;
490 ++str;
493 while ((num = quotient) != 0);
495 while (*(digitptr - 1) == '0')
496 --digitptr;
498 while (digitptr != TempBuffer)
500 *dest++ = *--digitptr;
501 if(++written >= maxbytes)
502 break;
505 continue;
506 } else /* if (*format == 'u') */
508 if(*format == 'd')
510 long num = va_arg(args, long);
511 long quotient;
512 const char *str;
513 char *digitptr = TempBuffer;
515 ++format;
517 if(num == 0)
519 *dest++ = '0';
520 ++written;
521 continue;
524 if(num < 0)
526 *dest++ = '-';
527 if(++written >= maxbytes)
528 continue;
530 num = -num;
535 quotient = num / TABLE_MAX;
537 str = IntTable[num - (quotient * TABLE_MAX)];
539 while ((*digitptr = *str))
541 ++digitptr;
542 ++str;
545 while ((num = quotient) != 0);
547 while (*(digitptr - 1) == '0')
548 --digitptr;
550 while (digitptr != TempBuffer)
552 *dest++ = *--digitptr;
553 if(++written >= maxbytes)
554 break;
557 continue;
558 } else /* if (*format == 'd') */
560 int ret;
561 format -= 2;
562 #ifdef HAVE_VSNPRINTF
563 ret = vsnprintf(dest, maxbytes - written, format, args);
564 #else
565 ret = vsprintf(dest, format, args);
566 #endif
567 dest += ret;
568 written += ret;
569 break;
573 } /* if (ch == 'l') */
575 if(ch != '%')
577 int ret;
580 * The character might be invalid, or be a precision,
581 * padding, or width specification - call vsprintf()
582 * to finish off the string
585 format -= 2;
586 #ifdef HAVE_VSNPRINTF
587 ret = vsnprintf(dest, maxbytes - written, format, args);
588 #else
589 ret = vsprintf(dest, format, args);
590 #endif
591 dest += ret;
592 written += ret;
594 break;
595 } /* if (ch != '%') */
596 } /* if (ch == '%') */
598 *dest++ = ch;
599 ++written;
600 } /* while ((ch = *format++) && (written < maxbytes)) */
603 * Terminate the destination buffer with a \0
605 *dest = '\0';
607 return (written);
608 } /* vSnprintf() */
611 ircvsprintf()
612 Backend to Sprintf() - performs the construction of 'dest'
613 using the string 'format' and the given arguments.
615 We always place a \0 character onto the end of 'dest'.
617 Return: Number of characters written, NOT including the terminating
618 \0 character which is *always* placed at the end of the string
620 NOTE: This function handles the following flags only:
621 %s %d %c %u %ld %lu
622 In addition, this function performs *NO* precision, padding,
623 or width formatting. If it receives an unknown % character,
624 it will call vsprintf() to complete the remainder of the
625 string.
629 ircvsprintf(char *dest, const char *format, va_list args)
631 char ch;
632 int written = 0; /* bytes written so far */
634 while ((ch = *format++))
636 if(ch == '%')
639 * Advance past the %
641 ch = *format++;
644 * Put the most common cases first - %s %d etc
647 if(ch == 's')
649 const char *str = va_arg(args, const char *);
651 while ((*dest = *str))
653 ++dest;
654 ++str;
656 ++written;
659 continue;
660 } /* if (ch == 's') */
663 if(ch == 'd')
665 int num = va_arg(args, int);
666 int quotient;
667 const char *str;
668 char *digitptr = TempBuffer;
671 * We have to special-case "0" unfortunately
673 if(num == 0)
675 *dest++ = '0';
676 ++written;
677 continue;
680 if(num < 0)
682 *dest++ = '-';
683 ++written;
685 num = -num;
690 quotient = num / TABLE_MAX;
693 * We'll start with the right-most digits of 'num'.
694 * Dividing by TABLE_MAX cuts off all but the X
695 * right-most digits, where X is such that:
697 * 10^X = TABLE_MAX
699 * For example, if num = 1200, and TABLE_MAX = 1000,
700 * quotient will be 1. Multiplying this by 1000 and
701 * subtracting from 1200 gives: 1200 - (1 * 1000) = 200.
702 * We then go right to slot 200 in our array and behold!
703 * The string "002" (200 backwards) is conveniently
704 * waiting for us. Then repeat the process with the
705 * digits left.
707 * The reason we need to have the integers written
708 * backwards, is because we don't know how many digits
709 * there are. If we want to express the number 12130
710 * for example, our first pass would leave us with 130,
711 * whose slot in the array yields "031", which we
712 * plug into our TempBuffer[]. The next pass gives us
713 * 12, whose slot yields "21" which we append to
714 * TempBuffer[], leaving us with "03121". This is the
715 * exact number we want, only backwards, so it is
716 * a simple matter to reverse the string. If we used
717 * straightfoward numbers, we would have a TempBuffer
718 * looking like this: "13012" which would be a nightmare
719 * to deal with.
722 str = IntTable[num - (quotient * TABLE_MAX)];
724 while ((*digitptr = *str))
726 ++digitptr;
727 ++str;
730 while ((num = quotient) != 0);
733 * If the last quotient was a 1 or 2 digit number, there
734 * will be one or more leading zeroes in TempBuffer[] -
735 * get rid of them.
737 while (*(digitptr - 1) == '0')
738 --digitptr;
740 while (digitptr != TempBuffer)
742 *dest++ = *--digitptr;
743 ++written;
746 continue;
747 } /* if (ch == 'd') */
749 if(ch == 'c')
751 *dest++ = va_arg(args, int);
753 ++written;
755 continue;
756 } /* if (ch == 'c') */
758 if(ch == 'u')
760 unsigned int num = va_arg(args, unsigned int);
761 unsigned int quotient;
762 const char *str;
763 char *digitptr = TempBuffer;
765 if(num == 0)
767 *dest++ = '0';
768 ++written;
769 continue;
774 quotient = num / TABLE_MAX;
777 * Very similar to case 'd'
780 str = IntTable[num - (quotient * TABLE_MAX)];
782 while ((*digitptr = *str))
784 ++digitptr;
785 ++str;
788 while ((num = quotient) != 0);
790 while (*(digitptr - 1) == '0')
791 --digitptr;
793 while (digitptr != TempBuffer)
795 *dest++ = *--digitptr;
796 ++written;
799 continue;
800 } /* if (ch == 'u') */
802 if(ch == 'l')
804 if(*format == 'u')
806 unsigned long num = va_arg(args, unsigned long);
807 unsigned long quotient;
808 const char *str;
809 char *digitptr = TempBuffer;
811 ++format;
813 if(num == 0)
815 *dest++ = '0';
816 ++written;
817 continue;
822 quotient = num / TABLE_MAX;
825 * Very similar to case 'u'
828 str = IntTable[num - (quotient * TABLE_MAX)];
830 while ((*digitptr = *str))
832 ++digitptr;
833 ++str;
836 while ((num = quotient) != 0);
838 while (*(digitptr - 1) == '0')
839 --digitptr;
841 while (digitptr != TempBuffer)
843 *dest++ = *--digitptr;
844 ++written;
847 continue;
848 } /* if (*format == 'u') */
850 if(*format == 'd')
852 long num = va_arg(args, long);
853 long quotient;
854 const char *str;
855 char *digitptr = TempBuffer;
857 ++format;
859 if(num == 0)
861 *dest++ = '0';
862 ++written;
863 continue;
866 if(num < 0)
868 *dest++ = '-';
869 ++written;
871 num = -num;
876 quotient = num / TABLE_MAX;
878 str = IntTable[num - (quotient * TABLE_MAX)];
880 while ((*digitptr = *str))
882 ++digitptr;
883 ++str;
886 while ((num = quotient) != 0);
888 while (*(digitptr - 1) == '0')
889 --digitptr;
891 while (digitptr != TempBuffer)
893 *dest++ = *--digitptr;
894 ++written;
897 continue;
898 } /* if (*format == 'd') */
900 continue;
901 } /* if (ch == 'l') */
903 if(ch != '%')
905 int ret;
907 format -= 2;
908 ret = vsprintf(dest, format, args);
909 dest += ret;
910 written += ret;
912 break;
913 } /* if (ch != '%') */
914 } /* if (ch == '%') */
916 *dest++ = ch;
917 ++written;
918 } /* while ((ch = *format++)) */
921 * Terminate the destination buffer with a \0
923 *dest = '\0';
925 return (written);
926 } /* vSprintf() */
929 ircsnprintf()
930 Optimized version of snprintf().
932 Inputs: dest - destination string
933 bytes - number of bytes to copy
934 format - formatted string
935 args - args to 'format'
937 Return: number of characters copied, NOT including the terminating
938 NULL which is always placed at the end of the string
942 ircsnprintf(char *dest, const size_t bytes, const char *format, ...)
944 va_list args;
945 int count;
947 va_start(args, format);
949 count = ircvsnprintf(dest, bytes, format, args);
951 va_end(args);
953 return (count);
954 } /* Snprintf() */
957 ircsprintf()
958 Optimized version of sprintf()
960 Inputs: dest - destination string
961 format - formatted string
962 args - arguments to 'format'
964 Return: number of characters copied, NOT including the terminating
965 NULL which is always placed at the end of the string
969 ircsprintf(char *dest, const char *format, ...)
971 va_list args;
972 int count;
974 va_start(args, format);
976 count = ircvsprintf(dest, format, args);
978 va_end(args);
980 return (count);
981 } /* Sprintf() */