source: trunk/src/win32k/dev16/vprntf16.c@ 2898

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

Symbol Database is implemented.
No scanning of the os2krnl file, the loaded image is now scaned to determin
which build, debug/retail and smp/uni.
And yet some more enhanchments like 16-bit logging.

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