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

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

Some bugsfixes - Yield is disabled.
Added parameters.
Correcte moduleheaders.
Introduced a new base class for virtual lx modules + some elf sketches.

File size: 15.0 KB
Line 
1/* $Id: vprintf.c,v 1.5 1999-11-10 01:45:37 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 if (!options.fLogging)
225 return 0;
226 return vprintf2(pszFormat, args);
227}
228
229#pragma info(notrd)
230/**
231 * Partial vprintf implementation.
232 * This function don't check the fLogging flag, and will therefore allways write.
233 * @returns number of
234 * @param pszFormat Format string.
235 * @param args Argument list.
236 */
237int vprintf2(const char *pszFormat, va_list args)
238{
239 #ifndef RING0
240 int cch = 0;
241 #endif
242
243 while (*pszFormat != '\0')
244 {
245 if (*pszFormat == '%')
246 {
247 #ifndef RING0
248 if (cch > 0)
249 {
250 strout((char*)(pszFormat - cch), cch);
251 cch = 0;
252 }
253 #endif
254
255 pszFormat++; /* skip '%' */
256 if (*pszFormat == '%') /* '%%'-> '%' */
257 chout(*pszFormat++);
258 else
259 {
260 long lValue;
261 unsigned int fFlags = 0;
262 int cchWidth = -1;
263 int cchPrecision = -1;
264 unsigned int uiBase = 10;
265 char chArgSize;
266
267 /* flags */
268 #pragma info(none)
269 while (1)
270 #pragma info(restore)
271 {
272 switch (*pszFormat++)
273 {
274 case '#': fFlags |= NTSF_SPECIAL; continue;
275 case '-': fFlags |= NTSF_LEFT; continue;
276 case '+': fFlags |= NTSF_PLUS; continue;
277 case ' ': fFlags |= NTSF_BLANK; continue;
278 case '0': fFlags |= NTSF_ZEROPAD; continue;
279 }
280 pszFormat--;
281 break;
282 }
283 /* width */
284 if (ISDIGIT(*pszFormat))
285 cchWidth = _atoi_skip(SSToDS(&pszFormat));
286 else if (*pszFormat == '*')
287 {
288 pszFormat++;
289 cchWidth = va_arg(args, int);
290 if (cchWidth < 0)
291 {
292 cchWidth = -cchWidth;
293 fFlags |= NTSF_LEFT;
294 }
295 }
296
297 /* precision */
298 if (*pszFormat == '.')
299 {
300 pszFormat++;
301 if (ISDIGIT(*pszFormat))
302 cchPrecision = _atoi_skip(SSToDS(&pszFormat));
303 else if (*pszFormat == '*')
304 {
305 pszFormat++;
306 cchPrecision = va_arg(args, int);
307 }
308 if (cchPrecision < 0)
309 cchPrecision = 0;
310 }
311
312 /* argsize */
313 chArgSize = *pszFormat;
314 if (chArgSize != 'l' && chArgSize != 'L' && chArgSize != 'H')
315 chArgSize = 0;
316 else
317 pszFormat++;
318
319 /* type */
320 switch (*pszFormat++)
321 {
322 /* char */
323 case 'c':
324 if (!(fFlags & NTSF_LEFT))
325 while (--cchWidth > 0)
326 chout(' ');
327
328 chout(va_arg(args, int));
329
330 while (--cchWidth > 0)
331 chout(' ');
332 continue;
333
334 case 'd': /* signed decimal integer */
335 case 'i':
336 fFlags |= NTSF_VALSIGNED;
337 break;
338
339 case 'o':
340 uiBase = 8;
341 break;
342
343 case 'p':
344 fFlags |= NTSF_SPECIAL; /* Note not standard behaviour (but I like it this way!) */
345 uiBase = 16;
346 break;
347
348 case 's': /* string */
349 {
350 int cchStr;
351 char *pszStr = va_arg(args, char*);
352
353 if (pszStr < (char*)0x10000)
354 pszStr = "<NULL>";
355 cchStr = _strnlen(pszStr, (unsigned)cchPrecision);
356 if (!(fFlags & NTSF_LEFT))
357 while (--cchWidth >= cchStr)
358 chout(' ');
359
360 pszStr = strout(pszStr, cchStr);
361
362 while (--cchWidth >= cchStr)
363 chout(' ');
364 continue;
365 }
366
367 case 'u':
368 uiBase = 10;
369 break;
370
371 case 'x':
372 case 'X':
373 uiBase = 16;
374 break;
375
376 default:
377 continue;
378 }
379 /*-----------------*/
380 /* integer/pointer */
381 /*-----------------*/
382 /* get value */
383 if (pszFormat[-1] == 'p')
384 lValue = (signed long)va_arg(args, char *);
385 else if (chArgSize == 'l')
386 lValue = va_arg(args, signed long);
387 else if (chArgSize == 'h')
388 lValue = va_arg(args, signed short);
389 else
390 lValue = va_arg(args, signed int);
391 numtostr(lValue, uiBase, cchWidth, cchPrecision, fFlags);
392 }
393 }
394 else
395 {
396 #ifdef RING0
397 chout(*pszFormat++);
398 #else
399 cch++;
400 pszFormat++;
401 #endif
402 }
403 }
404
405 #ifndef RING0
406 if (cch > 0)
407 {
408 strout((char*)(pszFormat - cch), cch);
409 cch = 0;
410 }
411 #endif
412
413 return 0UL;
414}
415
416/* stub */
417int _vprintfieee(const char *pszFormat, va_list args)
418{
419 return vprintf(pszFormat, args);
420}
421
422
423/**
424 * printf - wraps arguments into a vprintf call.
425 * @returns number of bytes written.
426 * @param pszFormat Pointer to format string.
427 * @param ... Optional parameters.
428 */
429int printf(const char *pszFormat, ...)
430{
431 int cch;
432 va_list arguments;
433
434 va_start(arguments, pszFormat);
435 cch = vprintf(pszFormat, arguments);
436 va_end(arguments);
437
438 return cch;
439}
440
441
442/* stub */
443int _printfieee(const char *pszFormat, ...)
444{
445 int cch;
446 va_list arguments;
447
448 va_start(arguments, pszFormat);
449 cch = vprintf(pszFormat, arguments);
450 va_end(arguments);
451
452 return cch;
453}
454
455/* stub */
456int _printf_ansi(const char *pszFormat, ...)
457{
458 int cch;
459 va_list arguments;
460
461 va_start(arguments, pszFormat);
462 cch = vprintf(pszFormat, arguments);
463 va_end(arguments);
464
465 return cch;
466}
467
468
469
470
471/**
472 * Writes a char to output device.
473 * @param ch Char to write.
474 * @status completely
475 * @author knut st. osmundsen
476 */
477static void chout(int ch)
478{
479 #ifndef RING0
480 ULONG ulWrote;
481 #endif
482
483 if (ch != '\r')
484 {
485 if (ch == '\n')
486 {
487 #ifdef RING0
488 while (!(_inp(options.usCom + 5) & 0x20)); /* Waits for the port to be ready. */
489 _outp(options.usCom, chReturn); /* Put the char. */
490 #else
491 DosWrite(1, (void*)&chReturn, 1, &ulWrote);
492 #endif
493 }
494 #ifdef RING0
495 while (!(_inp(options.usCom + 5) & 0x20)); /* Waits for the port to be ready. */
496 _outp(options.usCom, ch); /* Put the char. */
497 Yield();
498 #else
499 DosWrite(1, (void*)&ch, 1, &ulWrote);
500 #endif
501 }
502}
503
504
505/**
506 * Write a string to the output device.
507 * @returns pointer end of string.
508 * @param psz Pointer to the string to write.
509 * @param cchMax Max count of chars to write. (or until '\0')
510 * @status completely implemented.
511 * @author knut st. osmundsen
512 */
513static char *strout(char *psz, signed cchMax)
514{
515 int cchYield = 0;
516 while (cchMax > 0 && *psz != '\0')
517 {
518 ULONG cch = 0;
519 ULONG ul;
520
521 while (cchMax - cch > 0 && psz[cch] != '\0' && psz[cch] != '\r' && psz[cch] != '\n')
522 cch++;
523
524 /* write string part */
525 #ifdef RING0
526 for (ul = 0; ul < cch; ul++)
527 {
528 while (!(_inp(options.usCom + 5) & 0x20)); /* Waits for the port to be ready. */
529 _outp(options.usCom, psz[ul]); /* Put the char. */
530 }
531 #else
532 DosWrite(1, (void*)psz, cch, &ul);
533 #endif
534
535 /* cr and lf check + skip */
536 if (psz[cch] == '\n' || psz[cch] == '\r')
537 {
538 if (psz[cch] == '\n')
539 {
540 #ifdef RING0
541 while (!(_inp(options.usCom + 5) & 0x20)); /* Waits for the port to be ready. */
542 _outp(options.usCom, chReturn); /* Put the char. */
543 while (!(_inp(options.usCom + 5) & 0x20)); /* Waits for the port to be ready. */
544 _outp(options.usCom, chNewLine); /* Put the char. */
545 cchYield ++;
546 #else
547 DosWrite(1, (void*)&chReturn, 1, &ul);
548 DosWrite(1, (void*)&chNewLine, 1, &ul);
549 #endif
550
551 }
552
553 while (cchMax - cch > 0 && (psz[cch] == '\r' || psz[cch] == '\n'))
554 cch++;
555 }
556
557 /* next */
558 psz += cch;
559 cchMax -= cch;
560 cchYield += cch;
561 if (cchYield > 3)
562 if (Yield())
563 cchYield = 0;
564 }
565 return psz;
566}
567
Note: See TracBrowser for help on using the repository browser.