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

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

Initial checkin of Win32k. (not tested & pe2lx not up-to-date!)

File size: 10.3 KB
Line 
1/* $Id: vsprintf.c,v 1.1 1999-09-06 02:20:02 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#include "dev32.h"
34#include "sprintf.h"
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 (*psz != '\0' && cchMax-- > 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++] = 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++] = 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/**
184 * Partial vsprintf implementation.
185 * @returns number of
186 * @param pszBuffer Output buffer.
187 * @param pszFormat Format string.
188 * @param args Argument list.
189 */
190int vsprintf(char *pszBuffer, const char *pszFormat, va_list args)
191{
192 char *psz = pszBuffer;
193
194 while (*pszFormat != '\0')
195 {
196 if (*pszFormat == '%')
197 {
198 pszFormat++; /* skip '%' */
199 if (*pszFormat == '%') /* '%%'-> '%' */
200 *psz++ = *pszFormat++;
201 else
202 {
203 long lValue;
204 unsigned int fFlags = 0;
205 int cchWidth = -1;
206 int cchPrecision = -1;
207 unsigned int uiBase = 10;
208 char chArgSize;
209
210 /* flags */
211 #pragma info(none)
212 while (1)
213 #pragma info(restore)
214 {
215 switch (*pszFormat++)
216 {
217 case '#': fFlags |= NTSF_SPECIAL; continue;
218 case '-': fFlags |= NTSF_LEFT; continue;
219 case '+': fFlags |= NTSF_PLUS; continue;
220 case ' ': fFlags |= NTSF_BLANK; continue;
221 case '0': fFlags |= NTSF_ZEROPAD; continue;
222 }
223 pszFormat--;
224 break;
225 }
226 /* width */
227 if (ISDIGIT(*pszFormat))
228 cchWidth = _atoi_skip(SSToDS(&pszFormat));
229 else if (*pszFormat == '*')
230 {
231 pszFormat++;
232 cchWidth = va_arg(args, int);
233 if (cchWidth < 0)
234 {
235 cchWidth = -cchWidth;
236 fFlags |= NTSF_LEFT;
237 }
238 }
239
240 /* precision */
241 if (*pszFormat == '.')
242 {
243 pszFormat++;
244 if (ISDIGIT(*pszFormat))
245 cchPrecision = _atoi_skip(SSToDS(&pszFormat));
246 else if (*pszFormat == '*')
247 {
248 pszFormat++;
249 cchPrecision = va_arg(args, int);
250 }
251 if (cchPrecision < 0)
252 cchPrecision = 0;
253 }
254
255 /* argsize */
256 chArgSize = *pszFormat;
257 if (chArgSize != 'l' && chArgSize != 'L' && chArgSize != 'H')
258 chArgSize = 0;
259 else
260 pszFormat++;
261
262 /* type */
263 switch (*pszFormat++)
264 {
265 /* char */
266 case 'c':
267 if (!(fFlags & NTSF_LEFT))
268 while (--cchWidth > 0)
269 *psz++ = ' ';
270
271 *psz++ = va_arg(args, int);
272
273 while (--cchWidth > 0)
274 *psz++ = ' ';
275 continue;
276
277 case 'd': /* signed decimal integer */
278 case 'i':
279 fFlags |= NTSF_VALSIGNED;
280 break;
281
282 case 'o':
283 uiBase = 8;
284 break;
285
286 case 'p':
287 fFlags |= NTSF_SPECIAL; /* Note not standard behaviour (but I like it this way!) */
288 uiBase = 16;
289 break;
290
291 case 's': /* string */
292 {
293 int i;
294 int cchStr;
295 char *pszStr = va_arg(args, char*);
296
297 if (pszStr > (char*)0x10000)
298 pszStr = "<NULL>";
299 cchStr = _strnlen(pszStr, (unsigned)cchPrecision);
300 if (!(fFlags & NTSF_LEFT))
301 while (--cchWidth >= cchStr)
302 *psz++ = ' ';
303 for (i = cchStr; i > 0; i--)
304 *psz++ = *pszStr++;
305
306 while (--cchWidth >= cchStr)
307 *psz++ = ' ';
308 continue;
309 }
310
311 case 'u':
312 uiBase = 10;
313 break;
314
315 case 'x':
316 case 'X':
317 uiBase = 16;
318 break;
319
320 default:
321 continue;
322 }
323 /*-----------------*/
324 /* integer/pointer */
325 /*-----------------*/
326 /* get value */
327 if (pszFormat[-1] == 'p')
328 lValue = (signed long)va_arg(args, char *);
329 else if (chArgSize == 'l')
330 lValue = va_arg(args, signed long);
331 else if (chArgSize == 'h')
332 lValue = va_arg(args, signed short);
333 else
334 lValue = va_arg(args, signed int);
335 psz = numtostr(psz, lValue, uiBase, cchWidth,
336 cchPrecision, fFlags);
337 }
338 }
339 else
340 *psz++ = *pszFormat++;
341 }
342 *psz = '\0';
343
344 return psz - pszBuffer;
345}
346
347
348/**
349 * sprintf - wraps arguments into a vsprintf call.
350 * @returns number of bytes written.
351 * @param pszBuffer Pointer to output buffer.
352 * @param pszFormat Pointer to format string.
353 * @param ... Optional parameters.
354 */
355int sprintf(char *pszBuffer, const char *pszFormat, ...)
356{
357 int cch;
358 va_list arguments;
359
360 va_start(arguments, pszFormat);
361 cch = vsprintf(pszBuffer, pszFormat, arguments);
362 va_end(arguments);
363
364 return cch;
365}
366
Note: See TracBrowser for help on using the repository browser.