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

Last change on this file since 10367 was 8703, checked in by bird, 23 years ago

removed the cause of warning.

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