From d63c2da552bc89c6748c31af651699b77fc1efe6 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 14 Mar 2008 20:43:28 +0000 Subject: * fcntl.cc (fcntl_worker): Protect with a 'myfault'. * path.cc (normalize_posix_path): Treat X:/ as Win32 path, too. * smallprint.cc (__wrn): New static function. (__small_vswprintf): New function to generate WCHAR strings. (__small_swprintf): Ditto. * winsup.h (__small_swprintf): Declare. (__small_vswprintf): Declare. --- winsup/cygwin/smallprint.cc | 193 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) (limited to 'winsup/cygwin/smallprint.cc') diff --git a/winsup/cygwin/smallprint.cc b/winsup/cygwin/smallprint.cc index 2a7810c50..eead3716f 100644 --- a/winsup/cygwin/smallprint.cc +++ b/winsup/cygwin/smallprint.cc @@ -14,6 +14,8 @@ details. */ #include #include #include +#include +#include #include #define LLMASK (0xffffffffffffffffULL) @@ -286,3 +288,194 @@ console_printf (const char *fmt, ...) FlushFileBuffers (console_handle); } #endif + +#define wrnarg(dst, base, dosign, len, pad) __wrn ((dst), (base), (dosign), va_arg (ap, long), len, pad, LMASK) +#define wrnargLL(dst, base, dosign, len, pad) __wrn ((dst), (base), (dosign), va_arg (ap, unsigned long long), len, pad, LLMASK) + +static PWCHAR __fastcall +__wrn (PWCHAR dst, int base, int dosign, long long val, int len, int pad, unsigned long long mask) +{ + /* longest number is ULLONG_MAX, 18446744073709551615, 20 digits */ + unsigned long long uval = 0; + WCHAR res[20]; + static const WCHAR str[] = L"0123456789ABCDEF"; + int l = 0; + + if (dosign && val < 0) + { + *dst++ = L'-'; + uval = -val; + } + else if (dosign > 0 && val > 0) + { + *dst++ = L'+'; + uval = val; + } + else + uval = val; + + uval &= mask; + + do + { + res[l++] = str[uval % base]; + uval /= base; + } + while (uval); + + while (len-- > l) + *dst++ = pad; + + while (l > 0) + *dst++ = res[--l]; + + return dst; +} + +extern "C" int +__small_vswprintf (PWCHAR dst, const WCHAR *fmt, va_list ap) +{ + WCHAR tmp[NT_MAX_PATH]; + PWCHAR orig = dst; + const char *s; + PWCHAR w; + UNICODE_STRING uw, *us; + + DWORD err = GetLastError (); + + while (*fmt) + { + unsigned int n = 0x7fff; + if (*fmt != L'%') + *dst++ = *fmt++; + else + { + int len = 0; + WCHAR pad = L' '; + int addsign = -1; + + switch (*++fmt) + { + case L'+': + addsign = 1; + fmt++; + break; + case L'%': + *dst++ = *fmt++; + continue; + } + + for (;;) + { + char c = *fmt++; + switch (c) + { + case L'0': + if (len == 0) + { + pad = L'0'; + continue; + } + case L'1' ... L'9': + len = len * 10 + (c - L'0'); + continue; + case L'l': + continue; + case L'c': + case L'C': + { + unsigned int c = va_arg (ap, unsigned int); + if (c > L' ' && c <= 127) + *dst++ = c; + else + { + *dst++ = L'0'; + *dst++ = L'x'; + dst = __wrn (dst, 16, 0, c, len, pad, LMASK); + } + } + break; + case L'E': + wcscpy (dst, L"Win32 error "); + dst = __wrn (dst + sizeof ("Win32 error"), 10, 0, err, len, pad, LMASK); + break; + case L'd': + dst = wrnarg (dst, 10, addsign, len, pad); + break; + case L'D': + dst = wrnargLL (dst, 10, addsign, len, pad); + break; + case L'u': + dst = wrnarg (dst, 10, 0, len, pad); + break; + case L'U': + dst = wrnargLL (dst, 10, 0, len, pad); + break; + case L'o': + dst = wrnarg (dst, 8, 0, len, pad); + break; + case L'p': + *dst++ = L'0'; + *dst++ = L'x'; + /* fall through */ + case L'x': + dst = wrnarg (dst, 16, 0, len, pad); + break; + case L'X': + dst = wrnargLL (dst, 16, 0, len, pad); + break; + case L'P': + if (!GetModuleFileNameW (NULL, tmp, NT_MAX_PATH)) + RtlInitUnicodeString (us = &uw, L"cygwin program"); + else + RtlInitUnicodeString (us = &uw, tmp); + goto fillin; + case L'.': + n = wcstoul (fmt, (wchar_t **) &fmt, 10); + if (*fmt++ != L's') + goto endfor; + case L's': + s = va_arg (ap, char *); + if (s == NULL) + s = "(null)"; + sys_mbstowcs (tmp, NT_MAX_PATH, s, n); + RtlInitUnicodeString (us = &uw, tmp); + goto fillin; + break; + case L'W': + w = va_arg (ap, PWCHAR); + RtlInitUnicodeString (us = &uw, w); + goto fillin; + case L'S': + us = va_arg (ap, PUNICODE_STRING); + fillin: + if (us->Length / sizeof (WCHAR) < n) + n = us->Length / sizeof (WCHAR); + + for (unsigned int i = 0; i < n; i++) + *dst++ = *w++; + break; + default: + *dst++ = L'?'; + *dst++ = fmt[-1]; + } + endfor: + break; + } + } + } + *dst = L'\0'; + SetLastError (err); + return dst - orig; +} + +extern "C" int +__small_swprintf (PWCHAR dst, const WCHAR *fmt, ...) +{ + int r; + va_list ap; + va_start (ap, fmt); + r = __small_vswprintf (dst, fmt, ap); + va_end (ap); + return r; +} -- cgit v1.2.3