]>
Commit | Line | Data |
---|---|---|
dcd1ef45 CV |
1 | /* smallprint.c: small print routines for WIN32 |
2 | ||
3 | Copyright 1996, 1998, 2000, 2001, 2002, 2003, 2005, 2006 Red Hat, Inc. | |
4 | ||
5 | This file is part of Cygwin. | |
6 | ||
7 | This software is a copyrighted work licensed under the terms of the | |
8 | Cygwin license. Please consult the file "CYGWIN_LICENSE" for | |
9 | details. */ | |
10 | ||
11 | #include "winsup.h" | |
12 | #include <stdarg.h> | |
13 | #include <stdlib.h> | |
14 | #include <ctype.h> | |
15 | #define WIN32_LEAN_AND_MEAN | |
16 | #include <windows.h> | |
17 | ||
18 | int __small_sprintf (char *dst, const char *fmt, ...); | |
19 | int __small_vsprintf (char *dst, const char *fmt, va_list ap); | |
20 | ||
21 | #define LLMASK (0xffffffffffffffffULL) | |
22 | #define LMASK (0xffffffff) | |
23 | ||
24 | #define rnarg(dst, base, dosign, len, pad) __rn ((dst), (base), (dosign), va_arg (ap, long), len, pad, LMASK) | |
25 | #define rnargLL(dst, base, dosign, len, pad) __rn ((dst), (base), (dosign), va_arg (ap, unsigned long long), len, pad, LLMASK) | |
26 | ||
27 | static char __fastcall * | |
28 | __rn (char *dst, int base, int dosign, long long val, int len, int pad, unsigned long long mask) | |
29 | { | |
30 | /* longest number is ULLONG_MAX, 18446744073709551615, 20 digits */ | |
31 | unsigned long long uval = 0; | |
32 | char res[20]; | |
33 | static const char str[16] = "0123456789ABCDEF"; | |
34 | int l = 0; | |
35 | ||
36 | if (dosign && val < 0) | |
37 | { | |
38 | *dst++ = '-'; | |
39 | uval = -val; | |
40 | } | |
41 | else if (dosign > 0 && val > 0) | |
42 | { | |
43 | *dst++ = '+'; | |
44 | uval = val; | |
45 | } | |
46 | else | |
47 | uval = val; | |
48 | ||
49 | uval &= mask; | |
50 | ||
51 | do | |
52 | { | |
53 | res[l++] = str[uval % base]; | |
54 | uval /= base; | |
55 | } | |
56 | while (uval); | |
57 | ||
58 | while (len-- > l) | |
59 | *dst++ = pad; | |
60 | ||
61 | while (l > 0) | |
62 | *dst++ = res[--l]; | |
63 | ||
64 | return dst; | |
65 | } | |
66 | ||
67 | int | |
68 | __small_vsprintf (char *dst, const char *fmt, va_list ap) | |
69 | { | |
70 | char tmp[CYG_MAX_PATH + 1]; | |
71 | char *orig = dst; | |
72 | const char *s; | |
73 | ||
74 | DWORD err = GetLastError (); | |
75 | ||
76 | while (*fmt) | |
77 | { | |
78 | int i, n = 0x7fff; | |
79 | if (*fmt != '%') | |
80 | *dst++ = *fmt++; | |
81 | else | |
82 | { | |
83 | int len = 0; | |
84 | char pad = ' '; | |
85 | int addsign = -1; | |
86 | ||
87 | switch (*++fmt) | |
88 | { | |
89 | case '+': | |
90 | addsign = 1; | |
91 | fmt++; | |
92 | break; | |
93 | case '%': | |
94 | *dst++ = *fmt++; | |
95 | continue; | |
96 | } | |
97 | ||
98 | for (;;) | |
99 | { | |
100 | char c = *fmt++; | |
101 | switch (c) | |
102 | { | |
103 | case '0': | |
104 | if (len == 0) | |
105 | { | |
106 | pad = '0'; | |
107 | continue; | |
108 | } | |
109 | case '1': case '2': case '3': case '4': | |
110 | case '5': case '6': case '7': case '8': case '9': | |
111 | len = len * 10 + (c - '0'); | |
112 | continue; | |
113 | case 'l': | |
114 | continue; | |
115 | case 'c': | |
116 | { | |
117 | int c = va_arg (ap, int); | |
118 | if (c > ' ' && c <= 127) | |
119 | *dst++ = c; | |
120 | else | |
121 | { | |
122 | *dst++ = '0'; | |
123 | *dst++ = 'x'; | |
124 | dst = __rn (dst, 16, 0, c, len, pad, LMASK); | |
125 | } | |
126 | } | |
127 | break; | |
128 | case 'E': | |
129 | strcpy (dst, "Win32 error "); | |
130 | dst = __rn (dst + sizeof ("Win32 error"), 10, 0, err, len, pad, LMASK); | |
131 | break; | |
132 | case 'd': | |
133 | dst = rnarg (dst, 10, addsign, len, pad); | |
134 | break; | |
135 | case 'D': | |
136 | dst = rnargLL (dst, 10, addsign, len, pad); | |
137 | break; | |
138 | case 'u': | |
139 | dst = rnarg (dst, 10, 0, len, pad); | |
140 | break; | |
141 | case 'U': | |
142 | dst = rnargLL (dst, 10, 0, len, pad); | |
143 | break; | |
144 | case 'o': | |
145 | dst = rnarg (dst, 8, 0, len, pad); | |
146 | break; | |
147 | case 'p': | |
148 | *dst++ = '0'; | |
149 | *dst++ = 'x'; | |
150 | /* fall through */ | |
151 | case 'x': | |
152 | dst = rnarg (dst, 16, 0, len, pad); | |
153 | break; | |
154 | case 'X': | |
155 | dst = rnargLL (dst, 16, 0, len, pad); | |
156 | break; | |
157 | case 'P': | |
158 | if (!GetModuleFileName (NULL, tmp, CYG_MAX_PATH)) | |
159 | s = "cygwin program"; | |
160 | else | |
161 | s = tmp; | |
162 | goto fillin; | |
163 | case '.': | |
164 | n = strtol (fmt, (char **) &fmt, 10); | |
165 | if (*fmt++ != 's') | |
166 | goto endfor; | |
167 | case 's': | |
168 | s = va_arg (ap, char *); | |
169 | if (s == NULL) | |
170 | s = "(null)"; | |
171 | fillin: | |
172 | for (i = 0; *s && i < n; i++) | |
173 | *dst++ = *s++; | |
174 | break; | |
175 | default: | |
176 | *dst++ = '?'; | |
177 | *dst++ = fmt[-1]; | |
178 | } | |
179 | endfor: | |
180 | break; | |
181 | } | |
182 | } | |
183 | } | |
184 | *dst = 0; | |
185 | SetLastError (err); | |
186 | return dst - orig; | |
187 | } | |
188 | ||
189 | int | |
190 | __small_sprintf (char *dst, const char *fmt, ...) | |
191 | { | |
192 | int r; | |
193 | va_list ap; | |
194 | va_start (ap, fmt); | |
195 | r = __small_vsprintf (dst, fmt, ap); | |
196 | va_end (ap); | |
197 | return r; | |
198 | } | |
199 | ||
200 | void | |
201 | small_printf (const char *fmt, ...) | |
202 | { | |
203 | char buf[16384]; | |
204 | va_list ap; | |
205 | DWORD done; | |
206 | int count; | |
207 | ||
208 | #if 0 /* Turn on to force console errors */ | |
209 | extern SECURITY_ATTRIBUTES sec_none; | |
210 | HANDLE h = CreateFileA ("CONOUT$", GENERIC_READ|GENERIC_WRITE, | |
211 | FILE_SHARE_WRITE | FILE_SHARE_WRITE, &sec_none, | |
212 | OPEN_EXISTING, 0, 0); | |
213 | if (h) | |
214 | SetStdHandle (STD_ERROR_HANDLE, h); | |
215 | #endif | |
216 | ||
217 | va_start (ap, fmt); | |
218 | count = __small_vsprintf (buf, fmt, ap); | |
219 | va_end (ap); | |
220 | ||
221 | WriteFile (GetStdHandle (STD_ERROR_HANDLE), buf, count, &done, NULL); | |
222 | FlushFileBuffers (GetStdHandle (STD_ERROR_HANDLE)); | |
223 | } | |
224 | ||
225 | #ifdef DEBUGGING | |
226 | static HANDLE NO_COPY console_handle = NULL; | |
227 | void | |
228 | console_printf (const char *fmt, ...) | |
229 | { | |
230 | char buf[16384]; | |
231 | va_list ap; | |
232 | DWORD done; | |
233 | int count; | |
234 | ||
235 | if (!console_handle) | |
236 | console_handle = CreateFileA ("CON", GENERIC_WRITE, | |
237 | FILE_SHARE_READ | FILE_SHARE_WRITE, | |
238 | NULL, OPEN_EXISTING, 0, 0); | |
239 | ||
240 | if (console_handle == INVALID_HANDLE_VALUE) | |
241 | console_handle = GetStdHandle (STD_ERROR_HANDLE); | |
242 | ||
243 | va_start (ap, fmt); | |
244 | count = __small_vsprintf (buf, fmt, ap); | |
245 | va_end (ap); | |
246 | ||
247 | WriteFile (console_handle, buf, count, &done, NULL); | |
248 | FlushFileBuffers (console_handle); | |
249 | } | |
250 | #endif |