source: GPL/branches/uniaud32-next/lib32/vsprintf.c@ 660

Last change on this file since 660 was 32, checked in by vladest, 20 years ago

initial import

File size: 10.8 KB
Line 
1/* $Id: vsprintf.c,v 1.1.1.1 2003/07/02 13:57:04 eleph Exp $
2 *
3 * vsprintf and sprintf
4 *
5 * Copyright (c) 1999 knut st. osmundsen
6 *
7 * Project Odin Software License can be found in LICENSE.TXT
8 *
9 */
10
11/*******************************************************************************
12* Defined Constants *
13*******************************************************************************/
14#define ISDIGIT(c) ((c) >= '0' && (c) <= '9')
15#define MAX(a, b) ((a) >= (b) ? (a) : (b))
16#define MIN(a, b) ((a) < (b) ? (a) : (b))
17
18#define NTSF_CAPITAL 0x0001
19#define NTSF_LEFT 0x0002
20#define NTSF_ZEROPAD 0x0004
21#define NTSF_SPECIAL 0x0008
22#define NTSF_VALSIGNED 0x0010
23#define NTSF_PLUS 0x0020
24#define NTSF_BLANK 0x0040
25
26#define INCL_NOAPI
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include <os2.h>
32
33#include <stdarg.h>
34
35
36
37/*******************************************************************************
38* Internal Functions *
39*******************************************************************************/
40static unsigned _strnlen(const char *psz, unsigned cchMax);
41static int _atoi_skip(const char **ppsz);
42
43
44/**
45 * Read an integer (decimal) and update the string pointer while reading.
46 * Do not support sign values.
47 * @returns Integer value.
48 * @param ppsz Pointer to pointer to string. The string to be converted.
49 */
50static int _atoi_skip(const char **ppsz)
51{
52 int iValue = 0;
53
54 while (ISDIGIT(**ppsz))
55 {
56 iValue *= 10;
57 iValue += **ppsz - '0';
58 (*ppsz)++;
59 }
60
61 return iValue;
62}
63
64
65/**
66 * Finds the length of a string up to cchMax.
67 * @returns Length.
68 * @param psz Pointer to string.
69 * @param cchMax Max length.
70 */
71static unsigned _strnlen(const char *psz, unsigned cchMax)
72{
73 const char *pszC = psz;
74
75 while (cchMax-- > 0 && *psz != '\0')
76 psz++;
77
78 return psz - pszC;
79}
80
81
82/**
83 * Formats a number according to the parameters.
84 * @returns Pointer to next char. (after number)
85 * @param psz Pointer to output string.
86 * @param lValue Value
87 * @param uiBase Number representation base.
88 * @param cchWidth Width
89 * @param cchPrecision Precision.
90 * @param fFlags Flags (NTFS_*).
91 */
92static char * numtostr(char *psz, long lValue, unsigned int uiBase,
93 signed int cchWidth, signed int cchPrecision,
94 unsigned int fFlags
95 )
96{
97 char * achDigits = "0123456789abcdef";
98 int cchValue;
99 unsigned long ul;
100 int i;
101 int j;
102
103#ifdef DEBUG
104 if (uiBase < 2 || uiBase > 16)
105 return NULL;
106#endif
107 if (fFlags & NTSF_CAPITAL)
108 achDigits = "0123456789ABCDEF";
109 if (fFlags & NTSF_LEFT)
110 fFlags &= ~NTSF_ZEROPAD;
111
112 /* determin value length */
113 cchValue = 0;
114 ul = (unsigned long)((fFlags & NTSF_VALSIGNED) && lValue < 0L ? -lValue : lValue);
115 do
116 {
117 cchValue++;
118 ul /= uiBase;
119 } while (ul > 0);
120
121 i = 0;
122 if (fFlags & NTSF_VALSIGNED)
123 {
124 if (lValue < 0)
125 {
126 lValue = -lValue;
127 psz[i++] = '-';
128 }
129 else if (fFlags & (NTSF_PLUS | NTSF_BLANK))
130 psz[i++] = (char)(fFlags & NTSF_PLUS ? '+' : ' ');
131 }
132
133 if (fFlags & NTSF_SPECIAL && (uiBase % 8) == 0)
134 {
135 psz[i++] = '0';
136 if (uiBase == 16)
137 psz[i++] = (char)(fFlags & NTSF_CAPITAL ? 'X' : 'x');
138 }
139
140
141 /* width - only if ZEROPAD */
142 cchWidth -= i + cchValue;
143 if (fFlags & NTSF_ZEROPAD)
144 while (--cchWidth >= 0)
145 {
146 psz[i++] = '0';
147 cchPrecision--;
148 }
149 else if (!(fFlags & NTSF_LEFT) && cchWidth > 0)
150 {
151 for (j = i-1; j >= 0; j--)
152 psz[cchWidth + j] = psz[j];
153 for (j = 0; j < cchWidth; j++)
154 psz[j] = ' ';
155 i += cchWidth;
156 }
157
158 psz += i;
159
160 /* percision */
161 while (--cchPrecision >= cchValue)
162 *psz++ = '0';
163
164 /* write number - not good enough but it works */
165 i = -1;
166 psz += cchValue;
167 do
168 {
169 psz[i--] = achDigits[lValue % uiBase];
170 lValue /= uiBase;
171 } while (lValue > 0);
172
173 /* width if NTSF_LEFT */
174 if (fFlags & NTSF_LEFT)
175 while (--cchWidth >= 0)
176 *psz++ = ' ';
177
178
179 return psz;
180}
181
182
183#pragma info(notrd)
184/**
185 * Partial vsprintf implementation.
186 * @returns number of
187 * @param pszBuffer Output buffer.
188 * @param pszFormat Format string.
189 * @param args Argument list.
190 */
191int vsprintf(char *pszBuffer, const char *pszFormat, va_list args)
192{
193 char *psz = pszBuffer;
194
195 while (*pszFormat != '\0')
196 {
197 if (*pszFormat == '%')
198 {
199 pszFormat++; /* skip '%' */
200 if (*pszFormat == '%') /* '%%'-> '%' */
201 *psz++ = *pszFormat++;
202 else
203 {
204 long lValue;
205 unsigned int fFlags = 0;
206 int cchWidth = -1;
207 int cchPrecision = -1;
208 unsigned int uiBase = 10;
209 char chArgSize;
210
211 /* flags */
212 #pragma info(none)
213 while (1)
214 #pragma info(restore)
215 {
216 switch (*pszFormat++)
217 {
218 case '#': fFlags |= NTSF_SPECIAL; continue;
219 case '-': fFlags |= NTSF_LEFT; continue;
220 case '+': fFlags |= NTSF_PLUS; continue;
221 case ' ': fFlags |= NTSF_BLANK; continue;
222 case '0': fFlags |= NTSF_ZEROPAD; continue;
223 }
224 pszFormat--;
225 break;
226 }
227 /* width */
228 if (ISDIGIT(*pszFormat))
229 cchWidth = _atoi_skip(&pszFormat);
230 else if (*pszFormat == '*')
231 {
232 pszFormat++;
233 cchWidth = va_arg(args, int);
234 if (cchWidth < 0)
235 {
236 cchWidth = -cchWidth;
237 fFlags |= NTSF_LEFT;
238 }
239 }
240
241 /* precision */
242 if (*pszFormat == '.')
243 {
244 pszFormat++;
245 if (ISDIGIT(*pszFormat))
246 cchPrecision = _atoi_skip(&pszFormat);
247 else if (*pszFormat == '*')
248 {
249 pszFormat++;
250 cchPrecision = va_arg(args, int);
251 }
252 if (cchPrecision < 0)
253 cchPrecision = 0;
254 }
255
256 /* argsize */
257 chArgSize = *pszFormat;
258 if (chArgSize != 'l' && chArgSize != 'L' && chArgSize != 'H')
259 chArgSize = 0;
260 else
261 pszFormat++;
262
263 /* type */
264 switch (*pszFormat++)
265 {
266 /* char */
267 case 'c':
268 if (!(fFlags & NTSF_LEFT))
269 while (--cchWidth > 0)
270 *psz++ = ' ';
271
272 *psz++ = va_arg(args, int);
273
274 while (--cchWidth > 0)
275 *psz++ = ' ';
276 continue;
277
278 case 'd': /* signed decimal integer */
279 case 'i':
280 fFlags |= NTSF_VALSIGNED;
281 break;
282
283 case 'o':
284 uiBase = 8;
285 break;
286
287 case 'p':
288 fFlags |= NTSF_SPECIAL; /* Note not standard behaviour (but I like it this way!) */
289 uiBase = 16;
290 break;
291
292 case 's': /* string */
293 {
294 int i;
295 int cchStr;
296 char *pszStr = va_arg(args, char*);
297
298 if (pszStr < (char*)0x10000)
299 pszStr = "<NULL>";
300 cchStr = _strnlen(pszStr, (unsigned)cchPrecision);
301 if (!(fFlags & NTSF_LEFT))
302 while (--cchWidth >= cchStr)
303 *psz++ = ' ';
304 for (i = cchStr; i > 0; i--)
305 *psz++ = *pszStr++;
306
307 while (--cchWidth >= cchStr)
308 *psz++ = ' ';
309 continue;
310 }
311
312 case 'u':
313 uiBase = 10;
314 break;
315
316 case 'x':
317 case 'X':
318 uiBase = 16;
319 break;
320
321 default:
322 continue;
323 }
324 /*-----------------*/
325 /* integer/pointer */
326 /*-----------------*/
327 /* get value */
328 if (pszFormat[-1] == 'p')
329 lValue = (signed long)va_arg(args, char *);
330 else if (chArgSize == 'l')
331 lValue = va_arg(args, signed long);
332 else if (chArgSize == 'h')
333 lValue = va_arg(args, signed short);
334 else
335 lValue = va_arg(args, signed int);
336 psz = numtostr(psz, lValue, uiBase, cchWidth,
337 cchPrecision, fFlags);
338 }
339 }
340 else
341 *psz++ = *pszFormat++;
342 }
343 *psz = '\0';
344
345 return psz - pszBuffer;
346}
347
348
349/**
350 * sprintf - wraps arguments into a vsprintf call.
351 * @returns number of bytes written.
352 * @param pszBuffer Pointer to output buffer.
353 * @param pszFormat Pointer to format string.
354 * @param ... Optional parameters.
355 */
356int sprintf(char *pszBuffer, const char *pszFormat, ...)
357{
358 int cch;
359 va_list arguments;
360
361 va_start(arguments, pszFormat);
362 cch = vsprintf(pszBuffer, pszFormat, arguments);
363 va_end(arguments);
364
365 return cch;
366}
367
Note: See TracBrowser for help on using the repository browser.