1 /* smallprint.cc: small print routines for WIN32
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
17 Meaning of format conversion specifiers. If 'l' isn't explicitely mentioned,
20 0 modifier: pad with zero instead of spaces
21 0-9 modifier: field length
22 + modifier: always add sign
23 l modifier to d, o, R, u, x, y: 4 byte on 32 bit, 8 byte on 64 bit
24 l modifier to s, S, W: non-ASCII tweaking
25 _ modifier: print lower case hex chars a-f instead of A-F
30 D signed long long, 8 byte
32 o octal unsigned int, 4 byte
33 O octal unsigned long long, 8 byte
36 R return value, 4 byte.
39 u unsigned int, 4 byte
40 U unsigned long long, 8 byte
42 x hex unsigned int, 4 byte
43 X hex unsigned long long, 8 byte
44 y 0x hex unsigned int, 4 byte
45 Y 0x hex unsigned long long, 8 byte
48 #define LLMASK (0xffffffffffffffffULL)
49 #define LMASK (0xffffffff)
51 #define rnarg(dst, base, dosign, len, pad) __rn ((dst), (base), (dosign), va_arg (ap, int32_t), len, pad, LMASK)
52 #define rnargLL(dst, base, dosign, len, pad) __rn ((dst), (base), (dosign), va_arg (ap, uint64_t), len, pad, LLMASK)
54 static const char hex_str_upper
[] = "0123456789ABCDEF";
55 static const char hex_str_lower
[] = "0123456789abcdef";
65 buf
= (PWCHAR
) HeapAlloc (GetProcessHeap (), 0,
66 NT_MAX_PATH
* sizeof (WCHAR
));
69 operator char * () { return (char *) ((WCHAR
*) *this); }
71 tmpbuf () : buf (NULL
) {}
75 HeapFree (GetProcessHeap (), 0, buf
);
80 __rn (char *dst
, int base
, int dosign
, long long val
, int len
, int pad
, unsigned long long mask
)
82 /* longest number is ULLONG_MAX, 18446744073709551615, 20 digits */
83 unsigned long long uval
= 0;
91 hex_str
= hex_str_lower
;
94 hex_str
= hex_str_upper
;
96 if (dosign
&& val
< 0)
101 else if (dosign
> 0 && val
> 0)
113 res
[l
++] = hex_str
[uval
% base
];
128 __small_vsprintf (char *dst
, const char *fmt
, va_list ap
)
134 UNICODE_STRING uw
, *us
;
137 DWORD err
= GetLastError ();
144 /* set to -1 on '_', indicates upper (1)/lower(-1) case */
146 const char *hex_str
= hex_str_upper
;
179 len
= len
* 10 + (c
- '0');
186 hex_str
= hex_str_lower
;
190 unsigned char c
= (va_arg (ap
, int) & 0xff);
191 if (isprint (c
) || pad
!= '0')
197 dst
= __rn (dst
, h_opt
* 16, 0, c
, len
, pad
, LMASK
);
203 WCHAR wc
= (WCHAR
) va_arg (ap
, int);
204 char buf
[MB_LEN_MAX
+1] = "", *c
;
205 sys_wcstombs (buf
, MB_LEN_MAX
+1, &wc
, 1);
206 for (c
= buf
; *c
; ++c
)
211 strcpy (dst
, "Win32 error ");
212 dst
= __rn (dst
+ sizeof ("Win32 error"), 10, 0, err
, len
, pad
, LMASK
);
217 Rval
= va_arg (ap
, int64_t);
219 Rval
= va_arg (ap
, int32_t);
220 dst
= __rn (dst
, 10, addsign
, Rval
, len
, pad
, LMASK
);
250 dst
= rnarg (dst
, h_opt
* base
, addsign
, len
, pad
);
271 dst
= rnargLL (dst
, h_opt
* base
, addsign
, len
, pad
);
276 dst
= rnargLL (dst
, h_opt
* 16, 0, len
, pad
);
279 n
= strtol (fmt
, (char **) &fmt
, 10);
284 s
= va_arg (ap
, char *);
288 for (i
= 0; *s
&& i
< n
; i
++)
289 if (l_opt
&& ((*(unsigned char *)s
<= 0x1f && *s
!= '\n')
290 || *(unsigned char *)s
>= 0x7f))
294 *dst
++ = hex_str
[*(unsigned char *)s
>> 4];
295 *dst
++ = hex_str
[*(unsigned char *)s
++ & 0xf];
301 RtlInitUnicodeString (us
= &uw
, global_progname
);
304 w
= va_arg (ap
, PWCHAR
);
305 RtlInitUnicodeString (us
= &uw
, w
?: L
"(null)");
308 us
= va_arg (ap
, PUNICODE_STRING
);
310 RtlInitUnicodeString (us
= &uw
, L
"(null)");
314 for (USHORT i
= 0; i
< us
->Length
/ sizeof (WCHAR
); ++i
)
316 WCHAR w
= us
->Buffer
[i
];
317 if ((w
<= 0x1f && w
!= '\n') || w
>= 0x7f)
321 *dst
++ = hex_str
[(w
>> 12) & 0xf];
322 *dst
++ = hex_str
[(w
>> 8) & 0xf];
323 *dst
++ = hex_str
[(w
>> 4) & 0xf];
324 *dst
++ = hex_str
[w
& 0xf];
330 else if (sys_wcstombs (tmp
, NT_MAX_PATH
, us
->Buffer
,
331 us
->Length
/ sizeof (WCHAR
)))
348 dst
= stpcpy (dst
, ", errno ");
349 dst
= __rn (dst
, 10, false, get_errno (), 0, 0, LMASK
);
357 __small_sprintf (char *dst
, const char *fmt
, ...)
362 r
= __small_vsprintf (dst
, fmt
, ap
);
368 small_printf (const char *fmt
, ...)
375 #if 0 /* Turn on to force console errors */
376 extern SECURITY_ATTRIBUTES sec_none
;
377 HANDLE h
= CreateFileA ("CONOUT$", GENERIC_READ
|GENERIC_WRITE
,
378 FILE_SHARE_WRITE
| FILE_SHARE_WRITE
, &sec_none
,
379 OPEN_EXISTING
, 0, 0);
381 SetStdHandle (STD_ERROR_HANDLE
, h
);
385 count
= __small_vsprintf (buf
, fmt
, ap
);
388 WriteFile (GetStdHandle (STD_ERROR_HANDLE
), buf
, count
, &done
, NULL
);
389 FlushFileBuffers (GetStdHandle (STD_ERROR_HANDLE
));
393 static HANDLE NO_COPY console_handle
= NULL
;
395 console_printf (const char *fmt
, ...)
403 console_handle
= CreateFileA ("CON", GENERIC_WRITE
,
404 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
405 NULL
, OPEN_EXISTING
, 0, 0);
407 if (console_handle
== INVALID_HANDLE_VALUE
)
408 console_handle
= GetStdHandle (STD_ERROR_HANDLE
);
411 count
= __small_vsprintf (buf
, fmt
, ap
);
414 WriteFile (console_handle
, buf
, count
, &done
, NULL
);
415 FlushFileBuffers (console_handle
);
419 #define wrnarg(dst, base, dosign, len, pad) __wrn ((dst), (base), (dosign), va_arg (ap, long), len, pad, LMASK)
420 #define wrnargLL(dst, base, dosign, len, pad) __wrn ((dst), (base), (dosign), va_arg (ap, unsigned long long), len, pad, LLMASK)
423 __wrn (PWCHAR dst
, int base
, int dosign
, long long val
, int len
, int pad
, unsigned long long mask
)
425 /* longest number is ULLONG_MAX, 18446744073709551615, 20 digits */
426 unsigned long long uval
= 0;
434 hex_str
= hex_str_lower
;
437 hex_str
= hex_str_upper
;
439 if (dosign
&& val
< 0)
444 else if (dosign
> 0 && val
> 0)
456 res
[l
++] = hex_str
[uval
% base
];
471 __small_vswprintf (PWCHAR dst
, const WCHAR
*fmt
, va_list ap
)
477 UNICODE_STRING uw
, *us
;
480 DWORD err
= GetLastError ();
485 unsigned int n
= 0x7fff;
487 /* set to -1 on '_', indicates upper (1)/lower(-1) case */
521 len
= len
* 10 + (c
- L
'0');
531 *dst
++ = va_arg (ap
, unsigned);
534 wcscpy (dst
, L
"Win32 error ");
535 dst
= __wrn (dst
+ sizeof ("Win32 error"), 10, 0, err
, len
, pad
, LMASK
);
540 Rval
= va_arg (ap
, int64_t);
542 Rval
= va_arg (ap
, int32_t);
543 dst
= __wrn (dst
, 10, addsign
, Rval
, len
, pad
, LMASK
);
573 dst
= wrnarg (dst
, h_opt
* base
, addsign
, len
, pad
);
594 dst
= wrnargLL (dst
, h_opt
* base
, addsign
, len
, pad
);
599 dst
= wrnargLL (dst
, h_opt
* 16, 0, len
, pad
);
602 RtlInitUnicodeString (us
= &uw
, global_progname
);
605 n
= wcstoul (fmt
, (wchar_t **) &fmt
, 10);
610 s
= va_arg (ap
, char *);
613 sys_mbstowcs (tmp
, NT_MAX_PATH
, s
, n
< 0x7fff ? (int) n
: -1);
614 RtlInitUnicodeString (us
= &uw
, tmp
);
618 w
= va_arg (ap
, PWCHAR
);
619 RtlInitUnicodeString (us
= &uw
, w
?: L
"(null)");
622 us
= va_arg (ap
, PUNICODE_STRING
);
624 RtlInitUnicodeString (us
= &uw
, L
"(null)");
626 if (us
->Length
/ sizeof (WCHAR
) < n
)
627 n
= us
->Length
/ sizeof (WCHAR
);
629 for (unsigned int i
= 0; i
< n
; i
++)
643 dst
= wcpcpy (dst
, L
", errno ");
644 dst
= __wrn (dst
, 10, false, get_errno (), 0, 0, LMASK
);
652 __small_swprintf (PWCHAR dst
, const WCHAR
*fmt
, ...)
657 r
= __small_vswprintf (dst
, fmt
, ap
);