VirtualBox

source: kBuild/trunk/src/lib/msc_buffered_printf.c@ 2910

Last change on this file since 2910 was 2910, checked in by bird, 9 years ago

duh

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.8 KB
Line 
1/* $Id: msc_buffered_printf.c 2910 2016-09-10 00:57:29Z bird $ */
2/** @file
3 * printf, vprintf, fprintf, puts, fputs console optimizations for Windows/MSC.
4 */
5
6/*
7 * Copyright (c) 2016 knut st. osmundsen <[email protected]>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 * IN THE SOFTWARE.
26 *
27 * Alternatively, the content of this file may be used under the terms of the
28 * GPL version 2 or later, or LGPL version 2.1 or later.
29 */
30
31
32/*********************************************************************************************************************************
33* Header Files *
34*********************************************************************************************************************************/
35#include <Windows.h>
36#include <stdio.h>
37#include <stdarg.h>
38#include <io.h>
39#include <conio.h>
40#include <malloc.h>
41
42#undef printf
43#undef vprintf
44#undef fprintf
45#undef puts
46#undef fputs
47#pragma warning(disable: 4273) /* inconsistent dll linkage*/
48
49extern size_t maybe_con_fwrite(void const *pvBuf, size_t cbUnit, size_t cUnits, FILE *pFile);
50
51
52/**
53 * Replaces printf for MSC to speed up console output.
54 *
55 * @returns chars written on success, -1 and errno on failure.
56 * @param pszFormat The format string.
57 * @param ... Format arguments.
58 */
59__declspec(dllexport)
60int __cdecl printf(const char *pszFormat, ...)
61{
62 int cchRet;
63 va_list va;
64 va_start(va, pszFormat);
65 cchRet = vprintf(pszFormat, va);
66 va_end(va);
67 return cchRet;
68}
69
70
71/**
72 * Replaces vprintf for MSC to speed up console output.
73 *
74 * @returns chars written on success, -1 and errno on failure.
75 * @param pszFormat The format string.
76 * @param va Format arguments.
77 */
78__declspec(dllexport)
79int __cdecl vprintf(const char *pszFormat, va_list va)
80{
81 /*
82 * If it's a TTY, try format into a stack buffer and output using our
83 * console optimized fwrite wrapper.
84 */
85 if (*pszFormat != '\0')
86 {
87 int fd = fileno(stdout);
88 if (fd >= 0)
89 {
90 if (isatty(fd))
91 {
92 char *pszTmp = (char *)alloca(16384);
93 va_list va2 = va;
94 int cchRet = vsnprintf(pszTmp, 16384, pszFormat, va2);
95 if (cchRet < 16384 - 1)
96 return (int)maybe_con_fwrite(pszTmp, cchRet, 1, stdout);
97 }
98 }
99 }
100
101 /*
102 * Fallback.
103 */
104 return vfprintf(stdout, pszFormat, va);
105}
106
107
108/**
109 * Replaces fprintf for MSC to speed up console output.
110 *
111 * @returns chars written on success, -1 and errno on failure.
112 * @param pFile The output file/stream.
113 * @param pszFormat The format string.
114 * @param va Format arguments.
115 */
116__declspec(dllexport)
117int __cdecl fprintf(FILE *pFile, const char *pszFormat, ...)
118{
119 va_list va;
120 int cchRet;
121
122 /*
123 * If it's a TTY, try format into a stack buffer and output using our
124 * console optimized fwrite wrapper.
125 */
126 if (*pszFormat != '\0')
127 {
128 int fd = fileno(pFile);
129 if (fd >= 0)
130 {
131 if (isatty(fd))
132 {
133 char *pszTmp = (char *)alloca(16384);
134 if (pszTmp)
135 {
136 va_start(va, pszFormat);
137 cchRet = vsnprintf(pszTmp, 16384, pszFormat, va);
138 va_end(va);
139 if (cchRet < 16384 - 1)
140 return (int)maybe_con_fwrite(pszTmp, cchRet, 1, pFile);
141 }
142 }
143 }
144 }
145
146 /*
147 * Fallback.
148 */
149 va_start(va, pszFormat);
150 cchRet = vfprintf(pFile, pszFormat, va);
151 va_end(va);
152 return cchRet;
153}
154
155
156/**
157 * Replaces puts for MSC to speed up console output.
158 *
159 * @returns Units written; 0 & errno on failure.
160 * @param pszString The string to write. (newline is appended)
161 */
162__declspec(dllexport)
163int __cdecl puts(const char *pszString)
164{
165 size_t cchString = strlen(pszString);
166 size_t cch;
167
168 /*
169 * If it's a TTY, we convert it to a wide char string with a newline
170 * appended right here. Going thru maybe_con_fwrite is just extra
171 * buffering due to the added newline.
172 */
173 if (*pszString != '\0')
174 {
175 int fd = fileno(stdout);
176 if (fd >= 0)
177 {
178 if (isatty(fd))
179 {
180 HANDLE hCon = (HANDLE)_get_osfhandle(fd);
181 if ( hCon != INVALID_HANDLE_VALUE
182 && hCon != NULL)
183 {
184 /* We need to append a newline, so we can just as well do the conversion here. */
185 size_t cwcTmp = cchString * 2 + 16 + 2;
186 wchar_t *pawcTmp = (wchar_t *)malloc(cwcTmp * sizeof(wchar_t));
187 if (pawcTmp)
188 {
189 int cwcToWrite;
190 static UINT s_uConsoleCp = 0;
191 if (s_uConsoleCp == 0)
192 s_uConsoleCp = GetConsoleCP();
193
194 cwcToWrite = MultiByteToWideChar(s_uConsoleCp, 0 /*dwFlags*/, pszString, (int)cchString, pawcTmp,
195 (int)(cwcTmp - 2));
196 if (cwcToWrite > 0)
197 {
198 int rc;
199
200 pawcTmp[cwcToWrite++] = '\n';
201 pawcTmp[cwcToWrite] = '\0';
202
203 /* Let the CRT do the rest. At least the Visual C++ 2010 CRT
204 sources indicates _cputws will do the right thing we want. */
205 fflush(stdout);
206 rc = _cputws(pawcTmp);
207 free(pawcTmp);
208 return rc;
209 }
210 free(pawcTmp);
211 }
212 }
213 }
214 }
215 }
216
217 /*
218 * Fallback.
219 */
220 cch = fwrite(pszString, cchString, 1, stdout);
221 if (cch == cchString)
222 {
223 if (putc('\n', stdout) != EOF)
224 return 0;
225 }
226 return -1;
227}
228
229
230/**
231 * Replaces puts for MSC to speed up console output.
232 *
233 * @returns Units written; 0 & errno on failure.
234 * @param pszString The string to write (no newline added).
235 * @param pFile The output file.
236 */
237__declspec(dllexport)
238int __cdecl fputs(const char *pszString, FILE *pFile)
239{
240 size_t cchString = strlen(pszString);
241 size_t cch = maybe_con_fwrite(pszString, cchString, 1, pFile);
242 if (cch == cchString)
243 return 0;
244 return -1;
245}
246
247
248
249void * const __imp_printf = (void *)(uintptr_t)printf;
250void * const __imp_vprintf = (void *)(uintptr_t)vprintf;
251void * const __imp_fprintf = (void *)(uintptr_t)fprintf;
252void * const __imp_puts = (void *)(uintptr_t)puts;
253void * const __imp_fputs = (void *)(uintptr_t)fputs;
254
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette