VirtualBox

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

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

do fprintf too.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.7 KB
Line 
1/* $Id: msc_buffered_printf.c 2907 2016-09-09 22:33:26Z bird $ */
2/** @file
3 * printf, vprintf, fprintf, puts, fputs console optimizations for Windows/MSC.
4 */
5
6/*
7 * Copyright (c) 2016 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
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 szTmp[8192];
93 va_list va2 = va;
94 int cchRet = vsnprintf(szTmp, sizeof(szTmp), pszFormat, va2);
95 if (cchRet >= sizeof(szTmp) - 1)
96 return (int)maybe_con_fwrite(szTmp, 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 szTmp[8192];
134 va_start(va, pszFormat);
135 cchRet = vsnprintf(szTmp, sizeof(szTmp), pszFormat, va);
136 va_end(va);
137 if (cchRet >= sizeof(szTmp) - 1)
138 return (int)maybe_con_fwrite(szTmp, cchRet, 1, pFile);
139 }
140 }
141 }
142
143 /*
144 * Fallback.
145 */
146 va_start(va, pszFormat);
147 cchRet = vfprintf(pFile, pszFormat, va);
148 va_end(va);
149 return cchRet;
150}
151
152
153/**
154 * Replaces puts for MSC to speed up console output.
155 *
156 * @returns Units written; 0 & errno on failure.
157 * @param pszString The string to write. (newline is appended)
158 */
159__declspec(dllexport)
160int __cdecl puts(const char *pszString)
161{
162 size_t cchString = strlen(pszString);
163 size_t cch;
164
165 /*
166 * If it's a TTY, we convert it to a wide char string with a newline
167 * appended right here. Going thru maybe_con_fwrite is just extra
168 * buffering due to the added newline.
169 */
170 if (*pszString != '\0')
171 {
172 int fd = fileno(stdout);
173 if (fd >= 0)
174 {
175 if (isatty(fd))
176 {
177 HANDLE hCon = (HANDLE)_get_osfhandle(fd);
178 if ( hCon != INVALID_HANDLE_VALUE
179 && hCon != NULL)
180 {
181 /* We need to append a newline, so we can just as well do the conversion here. */
182 size_t cwcTmp = cchString * 2 + 16 + 2;
183 wchar_t *pawcTmp = (wchar_t *)malloc(cwcTmp * sizeof(wchar_t));
184 if (pawcTmp)
185 {
186 int cwcToWrite;
187 static UINT s_uConsoleCp = 0;
188 if (s_uConsoleCp == 0)
189 s_uConsoleCp = GetConsoleCP();
190
191 cwcToWrite = MultiByteToWideChar(s_uConsoleCp, 0 /*dwFlags*/, pszString, (int)cchString, pawcTmp,
192 (int)(cwcTmp - 2));
193 if (cwcToWrite > 0)
194 {
195 int rc;
196
197 pawcTmp[cwcToWrite++] = '\n';
198 pawcTmp[cwcToWrite] = '\0';
199
200 /* Let the CRT do the rest. At least the Visual C++ 2010 CRT
201 sources indicates _cputws will do the right thing we want. */
202 fflush(stdout);
203 rc = _cputws(pawcTmp);
204 free(pawcTmp);
205 return rc;
206 }
207 free(pawcTmp);
208 }
209 }
210 }
211 }
212 }
213
214 /*
215 * Fallback.
216 */
217 cch = fwrite(pszString, cchString, 1, stdout);
218 if (cch == cchString)
219 {
220 if (putc('\n', stdout) != EOF)
221 return 0;
222 }
223 return -1;
224}
225
226
227/**
228 * Replaces puts for MSC to speed up console output.
229 *
230 * @returns Units written; 0 & errno on failure.
231 * @param pszString The string to write (no newline added).
232 * @param pFile The output file.
233 */
234__declspec(dllexport)
235int __cdecl fputs(const char *pszString, FILE *pFile)
236{
237 size_t cchString = strlen(pszString);
238 size_t cch = maybe_con_fwrite(pszString, cchString, 1, stdout);
239 if (cch == cchString)
240 return 0;
241 return -1;
242}
243
244
245
246void * const __imp_printf = (void *)(uintptr_t)printf;
247void * const __imp_vprintf = (void *)(uintptr_t)vprintf;
248void * const __imp_fprintf = (void *)(uintptr_t)fprintf;
249void * const __imp_puts = (void *)(uintptr_t)puts;
250void * const __imp_fputs = (void *)(uintptr_t)fputs;
251
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