source: trunk/src/win32k/misc/vprintf.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: 14.6 KB
Line 
1/* $Id: vprintf.c,v 1.2 1999-10-27 02:03:00 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#include "dev32.h"
34#include "vprintf.h"
35#ifdef RING0
36 #include <builtin.h>
37 #include "options.h"
38#endif
39
40
41/*******************************************************************************
42* Global Variables *
43*******************************************************************************/
44static char chNewLine = '\n';
45static char chReturn = '\r';
46
47/*******************************************************************************
48* Internal Functions *
49*******************************************************************************/
50static int _atoi_skip(const char **ppsz);
51static unsigned _strnlen(const char *psz, unsigned cchMax);
52static void chout(int ch);
53static char * strout(char *psz, signed cchMax);
54
55
56/**
57 * Read an integer (decimal) and update the string pointer while reading.
58 * Do not support sign values.
59 * @returns Integer value.
60 * @param ppsz Pointer to pointer to string. The string to be converted.
61 */
62static int _atoi_skip(const char **ppsz)
63{
64 int iValue = 0;
65
66 while (ISDIGIT(**ppsz))
67 {
68 iValue *= 10;
69 iValue += **ppsz - '0';
70 (*ppsz)++;
71 }
72
73 return iValue;
74}
75
76
77/**
78 * Finds the length of a string up to cchMax.
79 * @returns Length.
80 * @param psz Pointer to string.
81 * @param cchMax Max length.
82 */
83static unsigned _strnlen(const char *psz, unsigned cchMax)
84{
85 const char *pszC = psz;
86
87 while (*psz != '\0' && cchMax-- > 0)
88 psz++;
89
90 return psz - pszC;
91}
92
93
94/**
95 * Formats a number according to the parameters.
96 * @returns Pointer to next char. (after number)
97 * @param psz Pointer to output string.
98 * @param lValue Value
99 * @param uiBase Number representation base.
100 * @param cchWidth Width
101 * @param cchPrecision Precision.
102 * @param fFlags Flags (NTFS_*).
103 */
104static char * numtostr(long lValue, unsigned int uiBase,
105 signed int cchWidth, signed int cchPrecision,
106 unsigned int fFlags
107 )
108{
109 char * achDigits = "0123456789abcdef";
110 int cchValue;
111 unsigned long ul;
112 int i;
113 int j;
114
115#ifdef DEBUG
116 if (uiBase < 2 || uiBase > 16)
117 return NULL;
118#endif
119 if (fFlags & NTSF_CAPITAL)
120 achDigits = "0123456789ABCDEF";
121 if (fFlags & NTSF_LEFT)
122 fFlags &= ~NTSF_ZEROPAD;
123
124 /* determin value length */
125 cchValue = 0;
126 ul = (unsigned long)((fFlags & NTSF_VALSIGNED) && lValue < 0L ? -lValue : lValue);
127 do
128 {
129 cchValue++;
130 ul /= uiBase;
131 } while (ul > 0);
132
133 i = 0;
134 if (fFlags & NTSF_VALSIGNED)
135 {
136 if (lValue < 0)
137 {
138 lValue = -lValue;
139 chout('-');
140 i++;
141 }
142 else if (fFlags & (NTSF_PLUS | NTSF_BLANK))
143 {
144 chout(fFlags & NTSF_PLUS ? '+' : ' ');
145 i++;
146 }
147 }
148
149 if (fFlags & NTSF_SPECIAL && (uiBase % 8) == 0)
150 {
151 chout('0');
152 i++;
153 if (uiBase == 16)
154 {
155 chout(fFlags & NTSF_CAPITAL ? 'X' : 'x');
156 i++;
157 }
158 }
159
160
161 /* width - only if ZEROPAD */
162 cchWidth -= i + cchValue;
163 if (fFlags & NTSF_ZEROPAD)
164 while (--cchWidth >= 0)
165 {
166 chout('0');
167 cchPrecision--;
168 }
169 #if 0
170 else if (!(fFlags & NTSF_LEFT) && cchWidth > 0)
171 { /* not yet supported! */
172 /*
173 for (j = i-1; j >= 0; j--)
174 psz[cchWidth + j] = psz[j];
175 for (j = 0; j < cchWidth; j++)
176 psz[j] = ' ';
177 i += cchWidth;
178 */
179 }
180 #endif
181
182 /* percision */
183 while (--cchPrecision >= cchValue)
184 chout('0');
185
186 ul = 1;
187 for (i = 1; i < cchValue; i++)
188 ul *= uiBase;
189 for (i = 0; i < cchValue; i++)
190 {
191 chout(achDigits[lValue / ul]);
192 lValue %= ul;
193 ul /= uiBase;
194 }
195
196 /* width if NTSF_LEFT */
197 if (fFlags & NTSF_LEFT)
198 while (--cchWidth >= 0)
199 chout(' ');
200
201
202 return NULL;
203}
204
205
206#pragma info(notrd)
207/**
208 * Partial vprintf implementation.
209 * @returns number of
210 * @param pszBuffer Output buffer.
211 * @param pszFormat Format string.
212 * @param args Argument list.
213 */
214int vprintf(const char *pszFormat, va_list args)
215{
216 #ifdef RING0
217 if (options.fQuiet)
218 return 0;
219 #else
220 int cch = 0;
221 #endif
222
223 while (*pszFormat != '\0')
224 {
225 if (*pszFormat == '%')
226 {
227 #ifndef RING0
228 if (cch > 0)
229 {
230 strout((char*)(pszFormat - cch), cch);
231 cch = 0;
232 }
233 #endif
234
235 pszFormat++; /* skip '%' */
236 if (*pszFormat == '%') /* '%%'-> '%' */
237 chout(*pszFormat++);
238 else
239 {
240 long lValue;
241 unsigned int fFlags = 0;
242 int cchWidth = -1;
243 int cchPrecision = -1;
244 unsigned int uiBase = 10;
245 char chArgSize;
246
247 /* flags */
248 #pragma info(none)
249 while (1)
250 #pragma info(restore)
251 {
252 switch (*pszFormat++)
253 {
254 case '#': fFlags |= NTSF_SPECIAL; continue;
255 case '-': fFlags |= NTSF_LEFT; continue;
256 case '+': fFlags |= NTSF_PLUS; continue;
257 case ' ': fFlags |= NTSF_BLANK; continue;
258 case '0': fFlags |= NTSF_ZEROPAD; continue;
259 }
260 pszFormat--;
261 break;
262 }
263 /* width */
264 if (ISDIGIT(*pszFormat))
265 cchWidth = _atoi_skip(SSToDS(&pszFormat));
266 else if (*pszFormat == '*')
267 {
268 pszFormat++;
269 cchWidth = va_arg(args, int);
270 if (cchWidth < 0)
271 {
272 cchWidth = -cchWidth;
273 fFlags |= NTSF_LEFT;
274 }
275 }
276
277 /* precision */
278 if (*pszFormat == '.')
279 {
280 pszFormat++;
281 if (ISDIGIT(*pszFormat))
282 cchPrecision = _atoi_skip(SSToDS(&pszFormat));
283 else if (*pszFormat == '*')
284 {
285 pszFormat++;
286 cchPrecision = va_arg(args, int);
287 }
288 if (cchPrecision < 0)
289 cchPrecision = 0;
290 }
291
292 /* argsize */
293 chArgSize = *pszFormat;
294 if (chArgSize != 'l' && chArgSize != 'L' && chArgSize != 'H')
295 chArgSize = 0;
296 else
297 pszFormat++;
298
299 /* type */
300 switch (*pszFormat++)
301 {
302 /* char */
303 case 'c':
304 if (!(fFlags & NTSF_LEFT))
305 while (--cchWidth > 0)
306 chout(' ');
307
308 chout(va_arg(args, int));
309
310 while (--cchWidth > 0)
311 chout(' ');
312 continue;
313
314 case 'd': /* signed decimal integer */
315 case 'i':
316 fFlags |= NTSF_VALSIGNED;
317 break;
318
319 case 'o':
320 uiBase = 8;
321 break;
322
323 case 'p':
324 fFlags |= NTSF_SPECIAL; /* Note not standard behaviour (but I like it this way!) */
325 uiBase = 16;
326 break;
327
328 case 's': /* string */
329 {
330 int cchStr;
331 char *pszStr = va_arg(args, char*);
332
333 if (pszStr < (char*)0x10000)
334 pszStr = "<NULL>";
335 cchStr = _strnlen(pszStr, (unsigned)cchPrecision);
336 if (!(fFlags & NTSF_LEFT))
337 while (--cchWidth >= cchStr)
338 chout(' ');
339
340 pszStr = strout(pszStr, cchStr);
341
342 while (--cchWidth >= cchStr)
343 chout(' ');
344 continue;
345 }
346
347 case 'u':
348 uiBase = 10;
349 break;
350
351 case 'x':
352 case 'X':
353 uiBase = 16;
354 break;
355
356 default:
357 continue;
358 }
359 /*-----------------*/
360 /* integer/pointer */
361 /*-----------------*/
362 /* get value */
363 if (pszFormat[-1] == 'p')
364 lValue = (signed long)va_arg(args, char *);
365 else if (chArgSize == 'l')
366 lValue = va_arg(args, signed long);
367 else if (chArgSize == 'h')
368 lValue = va_arg(args, signed short);
369 else
370 lValue = va_arg(args, signed int);
371 numtostr(lValue, uiBase, cchWidth, cchPrecision, fFlags);
372 }
373 }
374 else
375 {
376 #ifdef RING0
377 chout(*pszFormat++);
378 #else
379 cch++;
380 pszFormat++;
381 #endif
382 }
383 }
384
385 #ifndef RING0
386 if (cch > 0)
387 {
388 strout((char*)(pszFormat - cch), cch);
389 cch = 0;
390 }
391 #endif
392
393 return 0UL;
394}
395
396/* stub */
397int _vprintfieee(const char *pszFormat, va_list args)
398{
399 return vprintf(pszFormat, args);
400}
401
402
403/**
404 * printf - wraps arguments into a vprintf call.
405 * @returns number of bytes written.
406 * @param pszFormat Pointer to format string.
407 * @param ... Optional parameters.
408 */
409int printf(const char *pszFormat, ...)
410{
411 int cch;
412 va_list arguments;
413
414 #ifdef RING0
415 if (options.fQuiet)
416 return 0;
417 #endif
418
419 va_start(arguments, pszFormat);
420 cch = vprintf(pszFormat, arguments);
421 va_end(arguments);
422
423 return cch;
424}
425
426
427/* stub */
428int _printfieee(const char *pszFormat, ...)
429{
430 int cch;
431 va_list arguments;
432
433 #ifdef RING0
434 if (options.fQuiet)
435 return 0;
436 #endif
437
438 va_start(arguments, pszFormat);
439 cch = vprintf(pszFormat, arguments);
440 va_end(arguments);
441
442 return cch;
443}
444
445/* stub */
446int _printf_ansi(const char *pszFormat, ...)
447{
448 int cch;
449 va_list arguments;
450
451 #ifdef RING0
452 if (options.fQuiet)
453 return 0;
454 #endif
455
456 va_start(arguments, pszFormat);
457 cch = vprintf(pszFormat, arguments);
458 va_end(arguments);
459
460 return cch;
461}
462
463
464
465
466/**
467 * Writes a char to output device.
468 * @param ch Char to write.
469 * @status completely
470 * @author knut st. osmundsen
471 */
472static void chout(int ch)
473{
474 #ifndef RING0
475 ULONG ulWrote;
476 #endif
477
478 if (ch != '\r')
479 {
480 if (ch == '\n')
481 {
482 #ifdef RING0
483 while (!(_inp(options.usCom + 5) & 0x20)); /* Waits for the port to be ready. */
484 _outp(options.usCom, chReturn); /* Put the char. */
485 #else
486 DosWrite(1, (void*)&chReturn, 1, &ulWrote);
487 #endif
488 }
489 #ifdef RING0
490 while (!(_inp(options.usCom + 5) & 0x20)); /* Waits for the port to be ready. */
491 _outp(options.usCom, ch); /* Put the char. */
492 #else
493 DosWrite(1, (void*)&ch, 1, &ulWrote);
494 #endif
495 }
496}
497
498
499/**
500 * Write a string to the output device.
501 * @returns pointer end of string.
502 * @param psz Pointer to the string to write.
503 * @param cchMax Max count of chars to write. (or until '\0')
504 * @status completely implemented.
505 * @author knut st. osmundsen
506 */
507static char *strout(char *psz, signed cchMax)
508{
509 while (cchMax > 0 && *psz != '\0')
510 {
511 ULONG cch = 0;
512 ULONG ul;
513
514 while (cchMax - cch > 0 && psz[cch] != '\0' && psz[cch] != '\r' && psz[cch] != '\n')
515 cch++;
516
517 /* write string part */
518 #ifdef RING0
519 for (ul = 0; ul < cch; ul++)
520 {
521 while (!(_inp(options.usCom + 5) & 0x20)); /* Waits for the port to be ready. */
522 _outp(options.usCom, psz[ul]); /* Put the char. */
523 }
524 #else
525 DosWrite(1, (void*)psz, cch, &ul);
526 #endif
527
528 /* cr and lf check + skip */
529 if (psz[cch] == '\n' || psz[cch] == '\r')
530 {
531 if (psz[cch] == '\n')
532 {
533 #ifdef RING0
534 while (!(_inp(options.usCom + 5) & 0x20)); /* Waits for the port to be ready. */
535 _outp(options.usCom, chReturn); /* Put the char. */
536 while (!(_inp(options.usCom + 5) & 0x20)); /* Waits for the port to be ready. */
537 _outp(options.usCom, chNewLine); /* Put the char. */
538 #else
539 DosWrite(1, (void*)&chReturn, 1, &ul);
540 DosWrite(1, (void*)&chNewLine, 1, &ul);
541 #endif
542
543 }
544
545 while (cchMax - cch > 0 && (psz[cch] == '\r' || psz[cch] == '\n'))
546 cch++;
547 }
548
549 /* next */
550 psz += cch;
551 cchMax -= cch;
552 }
553 return psz;
554}
555
Note: See TracBrowser for help on using the repository browser.