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

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

Changes during Pe2Lx rewrite.

File size: 11.4 KB
Line 
1/* $Id: vprintf.c,v 1.1 1999-10-14 01:19:22 bird Exp $
2 *
3 * vprintf and printf
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 "vprintf.h"
39
40
41/*******************************************************************************
42* Internal Functions *
43*******************************************************************************/
44static int _atoi_skip(const char **ppsz);
45static unsigned _strnlen(const char *psz, unsigned cchMax);
46_Inline void chout(int ch);
47
48
49/**
50 * Read an integer (decimal) and update the string pointer while reading.
51 * Do not support sign values.
52 * @returns Integer value.
53 * @param ppsz Pointer to pointer to string. The string to be converted.
54 */
55static int _atoi_skip(const char **ppsz)
56{
57 int iValue = 0;
58
59 while (ISDIGIT(**ppsz))
60 {
61 iValue *= 10;
62 iValue += **ppsz - '0';
63 (*ppsz)++;
64 }
65
66 return iValue;
67}
68
69
70/**
71 * Finds the length of a string up to cchMax.
72 * @returns Length.
73 * @param psz Pointer to string.
74 * @param cchMax Max length.
75 */
76static unsigned _strnlen(const char *psz, unsigned cchMax)
77{
78 const char *pszC = psz;
79
80 while (*psz != '\0' && cchMax-- > 0)
81 psz++;
82
83 return psz - pszC;
84}
85
86
87/**
88 * Formats a number according to the parameters.
89 * @returns Pointer to next char. (after number)
90 * @param psz Pointer to output string.
91 * @param lValue Value
92 * @param uiBase Number representation base.
93 * @param cchWidth Width
94 * @param cchPrecision Precision.
95 * @param fFlags Flags (NTFS_*).
96 */
97static char * numtostr(long lValue, unsigned int uiBase,
98 signed int cchWidth, signed int cchPrecision,
99 unsigned int fFlags
100 )
101{
102 char * achDigits = "0123456789abcdef";
103 int cchValue;
104 unsigned long ul;
105 int i;
106 int j;
107
108#ifdef DEBUG
109 if (uiBase < 2 || uiBase > 16)
110 return NULL;
111#endif
112 if (fFlags & NTSF_CAPITAL)
113 achDigits = "0123456789ABCDEF";
114 if (fFlags & NTSF_LEFT)
115 fFlags &= ~NTSF_ZEROPAD;
116
117 /* determin value length */
118 cchValue = 0;
119 ul = (unsigned long)((fFlags & NTSF_VALSIGNED) && lValue < 0L ? -lValue : lValue);
120 do
121 {
122 cchValue++;
123 ul /= uiBase;
124 } while (ul > 0);
125
126 i = 0;
127 if (fFlags & NTSF_VALSIGNED)
128 {
129 if (lValue < 0)
130 {
131 lValue = -lValue;
132 chout('-');
133 i++;
134 }
135 else if (fFlags & (NTSF_PLUS | NTSF_BLANK))
136 {
137 chout(fFlags & NTSF_PLUS ? '+' : ' ');
138 i++;
139 }
140 }
141
142 if (fFlags & NTSF_SPECIAL && (uiBase % 8) == 0)
143 {
144 chout('0');
145 i++;
146 if (uiBase == 16)
147 {
148 chout(fFlags & NTSF_CAPITAL ? 'X' : 'x');
149 i++;
150 }
151 }
152
153
154 /* width - only if ZEROPAD */
155 cchWidth -= i + cchValue;
156 if (fFlags & NTSF_ZEROPAD)
157 while (--cchWidth >= 0)
158 {
159 chout('0');
160 cchPrecision--;
161 }
162 #if 0
163 else if (!(fFlags & NTSF_LEFT) && cchWidth > 0)
164 { /* not supported! */
165 /*
166 for (j = i-1; j >= 0; j--)
167 psz[cchWidth + j] = psz[j];
168 for (j = 0; j < cchWidth; j++)
169 psz[j] = ' ';
170 i += cchWidth;
171 */
172 }
173 #endif
174
175 /* percision */
176 while (--cchPrecision >= cchValue)
177 chout('0');
178
179 ul = 1;
180 for (i = 1; i < cchValue; i++)
181 ul *= uiBase;
182 for (i = 0; i < cchValue; i++)
183 {
184 chout(achDigits[lValue / ul]);
185 lValue %= ul;
186 ul /= uiBase;
187 }
188
189 /* width if NTSF_LEFT */
190 if (fFlags & NTSF_LEFT)
191 while (--cchWidth >= 0)
192 chout(' ');
193
194
195 return NULL;
196}
197
198
199#pragma info(notrd)
200/**
201 * Partial vprintf implementation.
202 * @returns number of
203 * @param pszBuffer Output buffer.
204 * @param pszFormat Format string.
205 * @param args Argument list.
206 */
207int vprintf(const char *pszFormat, va_list args)
208{
209 while (*pszFormat != '\0')
210 {
211 if (*pszFormat == '%')
212 {
213 pszFormat++; /* skip '%' */
214 if (*pszFormat == '%') /* '%%'-> '%' */
215 chout(*pszFormat++);
216 else
217 {
218 long lValue;
219 unsigned int fFlags = 0;
220 int cchWidth = -1;
221 int cchPrecision = -1;
222 unsigned int uiBase = 10;
223 char chArgSize;
224
225 /* flags */
226 #pragma info(none)
227 while (1)
228 #pragma info(restore)
229 {
230 switch (*pszFormat++)
231 {
232 case '#': fFlags |= NTSF_SPECIAL; continue;
233 case '-': fFlags |= NTSF_LEFT; continue;
234 case '+': fFlags |= NTSF_PLUS; continue;
235 case ' ': fFlags |= NTSF_BLANK; continue;
236 case '0': fFlags |= NTSF_ZEROPAD; continue;
237 }
238 pszFormat--;
239 break;
240 }
241 /* width */
242 if (ISDIGIT(*pszFormat))
243 cchWidth = _atoi_skip(SSToDS(&pszFormat));
244 else if (*pszFormat == '*')
245 {
246 pszFormat++;
247 cchWidth = va_arg(args, int);
248 if (cchWidth < 0)
249 {
250 cchWidth = -cchWidth;
251 fFlags |= NTSF_LEFT;
252 }
253 }
254
255 /* precision */
256 if (*pszFormat == '.')
257 {
258 pszFormat++;
259 if (ISDIGIT(*pszFormat))
260 cchPrecision = _atoi_skip(SSToDS(&pszFormat));
261 else if (*pszFormat == '*')
262 {
263 pszFormat++;
264 cchPrecision = va_arg(args, int);
265 }
266 if (cchPrecision < 0)
267 cchPrecision = 0;
268 }
269
270 /* argsize */
271 chArgSize = *pszFormat;
272 if (chArgSize != 'l' && chArgSize != 'L' && chArgSize != 'H')
273 chArgSize = 0;
274 else
275 pszFormat++;
276
277 /* type */
278 switch (*pszFormat++)
279 {
280 /* char */
281 case 'c':
282 if (!(fFlags & NTSF_LEFT))
283 while (--cchWidth > 0)
284 chout(' ');
285
286 chout(va_arg(args, int));
287
288 while (--cchWidth > 0)
289 chout(' ');
290 continue;
291
292 case 'd': /* signed decimal integer */
293 case 'i':
294 fFlags |= NTSF_VALSIGNED;
295 break;
296
297 case 'o':
298 uiBase = 8;
299 break;
300
301 case 'p':
302 fFlags |= NTSF_SPECIAL; /* Note not standard behaviour (but I like it this way!) */
303 uiBase = 16;
304 break;
305
306 case 's': /* string */
307 {
308 int i;
309 int cchStr;
310 char *pszStr = va_arg(args, char*);
311
312 if (pszStr < (char*)0x10000)
313 pszStr = "<NULL>";
314 cchStr = _strnlen(pszStr, (unsigned)cchPrecision);
315 if (!(fFlags & NTSF_LEFT))
316 while (--cchWidth >= cchStr)
317 chout(' ');
318 for (i = cchStr; i > 0; i--)
319 chout(*pszStr++);
320
321 while (--cchWidth >= cchStr)
322 chout(' ');
323 continue;
324 }
325
326 case 'u':
327 uiBase = 10;
328 break;
329
330 case 'x':
331 case 'X':
332 uiBase = 16;
333 break;
334
335 default:
336 continue;
337 }
338 /*-----------------*/
339 /* integer/pointer */
340 /*-----------------*/
341 /* get value */
342 if (pszFormat[-1] == 'p')
343 lValue = (signed long)va_arg(args, char *);
344 else if (chArgSize == 'l')
345 lValue = va_arg(args, signed long);
346 else if (chArgSize == 'h')
347 lValue = va_arg(args, signed short);
348 else
349 lValue = va_arg(args, signed int);
350 numtostr(lValue, uiBase, cchWidth, cchPrecision, fFlags);
351 }
352 }
353 else
354 chout(*pszFormat++);
355 }
356
357 return 0UL;
358}
359
360/* stub */
361int _vprintfieee(const char *pszFormat, va_list args)
362{
363 return vprintf(pszFormat, args);
364}
365
366
367/**
368 * printf - wraps arguments into a vprintf call.
369 * @returns number of bytes written.
370 * @param pszFormat Pointer to format string.
371 * @param ... Optional parameters.
372 */
373int printf(const char *pszFormat, ...)
374{
375 int cch;
376 va_list arguments;
377
378 va_start(arguments, pszFormat);
379 cch = vprintf(pszFormat, arguments);
380 va_end(arguments);
381
382 return cch;
383}
384
385
386/* stub */
387int _printfieee(const char *pszFormat, ...)
388{
389 int cch;
390 va_list arguments;
391
392 va_start(arguments, pszFormat);
393 cch = vprintf(pszFormat, arguments);
394 va_end(arguments);
395
396 return cch;
397}
398
399/* stub */
400int _printf_ansi(const char *pszFormat, ...)
401{
402 int cch;
403 va_list arguments;
404
405 va_start(arguments, pszFormat);
406 cch = vprintf(pszFormat, arguments);
407 va_end(arguments);
408
409 return cch;
410}
411
412
413
414
415/**
416 * Writes a char to output device.
417 * @param ch Char to write.
418 * @status completely
419 * @author knut st. osmundsen
420 */
421_Inline void chout(int ch)
422{
423 #ifdef RING0
424
425 #else
426 ULONG ulWrote;
427 #endif
428
429 if (ch != '\r')
430 {
431 if (ch == '\n')
432 {
433 static char chReturn = '\r';
434 #ifdef RING0
435
436 #else
437 DosWrite(1, (void*)&chReturn, 1, &ulWrote);
438 #endif
439 }
440 #ifdef RING0
441
442 #else
443 DosWrite(1, (void*)&ch, 1, &ulWrote);
444 #endif
445 }
446}
447
Note: See TracBrowser for help on using the repository browser.