source: trunk/src/win32k/misc/vsprintf.c@ 1271

Last change on this file since 1271 was 1271, checked in by bird, 26 years ago

Changes during Pe2Lx rewrite.

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