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

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

Temporary backup checkin.

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