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

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

No PM apis needed!

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