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

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

Corrections to make win32k work.
(And now it does work, at least at my test machine...)

File size: 10.4 KB
Line 
1/* $Id: vsprintf.c,v 1.3 1999-10-27 02:03:00 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++] = (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(SSToDS(&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(SSToDS(&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.