VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/string/strformatrt.cpp@ 53401

Last change on this file since 53401 was 52331, checked in by vboxsync, 10 years ago

strformatrt.cpp: Don't translate cchPrecision=0 to 16 for %Rhx* format types, only values less than zero, otherwise we will mistake 0 specified by the user and read beyond heap allocation.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 52.0 KB
Line 
1/* $Id: strformatrt.cpp 52331 2014-08-09 12:05:21Z vboxsync $ */
2/** @file
3 * IPRT - IPRT String Formatter Extensions.
4 */
5
6/*
7 * Copyright (C) 2006-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#define LOG_GROUP RTLOGGROUP_STRING
32#include <iprt/string.h>
33#ifndef RT_NO_EXPORT_SYMBOL
34# define RT_NO_EXPORT_SYMBOL /* don't slurp <linux/module.h> which then again
35 slurps arch-specific headers defining symbols */
36#endif
37#include "internal/iprt.h"
38
39#include <iprt/log.h>
40#include <iprt/assert.h>
41#include <iprt/string.h>
42#include <iprt/stdarg.h>
43#ifdef IN_RING3
44# include <iprt/thread.h>
45# include <iprt/err.h>
46#endif
47#include <iprt/ctype.h>
48#include <iprt/time.h>
49#include <iprt/net.h>
50#include <iprt/path.h>
51#include <iprt/asm.h>
52#define STRFORMAT_WITH_X86
53#ifdef STRFORMAT_WITH_X86
54# include <iprt/x86.h>
55#endif
56#include "internal/string.h"
57
58
59/**
60 * Helper function to format IPv6 address according to RFC 5952.
61 *
62 * @returns The number of bytes formatted.
63 * @param pfnOutput Pointer to output function.
64 * @param pvArgOutput Argument for the output function.
65 * @param pIpv6Addr IPv6 address
66 */
67static size_t rtstrFormatIPv6(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, PCRTNETADDRIPV6 pIpv6Addr)
68{
69 size_t cch = 0; /* result */
70
71 bool fEmbeddedIpv4;
72 size_t cwHexPart;
73 size_t cwZeroRun, cwLongestZeroRun;
74 size_t iZeroStart, iLongestZeroStart;
75 size_t idx;
76
77 Assert(pIpv6Addr != NULL);
78
79 /*
80 * Check for embedded IPv4 address.
81 *
82 * IPv4-compatible - ::11.22.33.44 (obsolete)
83 * IPv4-mapped - ::ffff:11.22.33.44
84 * IPv4-translated - ::ffff:0:11.22.33.44 (RFC 2765)
85 */
86 fEmbeddedIpv4 = false;
87 cwHexPart = RT_ELEMENTS(pIpv6Addr->au16);
88 if (pIpv6Addr->au64[0] == 0
89 && ( (pIpv6Addr->au32[2] == 0
90 && ( pIpv6Addr->au32[3] != 0
91 && pIpv6Addr->au32[3] != RT_H2BE_U32_C(1)))
92 || pIpv6Addr->au32[2] == RT_H2BE_U32_C(0x0000ffff)
93 || pIpv6Addr->au32[2] == RT_H2BE_U32_C(0xffff0000)))
94 {
95 fEmbeddedIpv4 = true;
96 cwHexPart -= 2;
97 }
98
99 cwZeroRun = cwLongestZeroRun = 0;
100 iZeroStart = iLongestZeroStart = -1;
101 for (idx = 0; idx <= cwHexPart; ++idx)
102 {
103 if (idx < cwHexPart && pIpv6Addr->au16[idx] == 0)
104 {
105 if (cwZeroRun == 0)
106 {
107 cwZeroRun = 1;
108 iZeroStart = idx;
109 }
110 else
111 ++cwZeroRun;
112 }
113 else
114 {
115 if (cwZeroRun != 0)
116 {
117 if (cwZeroRun > 1 && cwZeroRun > cwLongestZeroRun)
118 {
119 cwLongestZeroRun = cwZeroRun;
120 iLongestZeroStart = iZeroStart;
121 }
122 cwZeroRun = 0;
123 iZeroStart = -1;
124 }
125 }
126 }
127
128 if (cwLongestZeroRun == 0)
129 {
130 for (idx = 0; idx < cwHexPart; ++idx)
131 cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
132 "%s%x",
133 idx == 0 ? "" : ":",
134 RT_BE2H_U16(pIpv6Addr->au16[idx]));
135
136 if (fEmbeddedIpv4)
137 cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, ":");
138 }
139 else
140 {
141 const size_t iLongestZeroEnd = iLongestZeroStart + cwLongestZeroRun;
142
143 if (iLongestZeroStart == 0)
144 cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, ":");
145 else
146 for (idx = 0; idx < iLongestZeroStart; ++idx)
147 cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
148 "%x:", RT_BE2H_U16(pIpv6Addr->au16[idx]));
149
150 if (iLongestZeroEnd == cwHexPart)
151 cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, ":");
152 else
153 {
154 for (idx = iLongestZeroEnd; idx < cwHexPart; ++idx)
155 cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
156 ":%x", RT_BE2H_U16(pIpv6Addr->au16[idx]));
157
158 if (fEmbeddedIpv4)
159 cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, ":");
160 }
161 }
162
163 if (fEmbeddedIpv4)
164 cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
165 "%u.%u.%u.%u",
166 pIpv6Addr->au8[12],
167 pIpv6Addr->au8[13],
168 pIpv6Addr->au8[14],
169 pIpv6Addr->au8[15]);
170
171 return cch;
172}
173
174
175/**
176 * Callback to format iprt formatting extentions.
177 * See @ref pg_rt_str_format for a reference on the format types.
178 *
179 * @returns The number of bytes formatted.
180 * @param pfnOutput Pointer to output function.
181 * @param pvArgOutput Argument for the output function.
182 * @param ppszFormat Pointer to the format string pointer. Advance this till the char
183 * after the format specifier.
184 * @param pArgs Pointer to the argument list. Use this to fetch the arguments.
185 * @param cchWidth Format Width. -1 if not specified.
186 * @param cchPrecision Format Precision. -1 if not specified.
187 * @param fFlags Flags (RTSTR_NTFS_*).
188 * @param chArgSize The argument size specifier, 'l' or 'L'.
189 */
190DECLHIDDEN(size_t) rtstrFormatRt(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, const char **ppszFormat, va_list *pArgs,
191 int cchWidth, int cchPrecision, unsigned fFlags, char chArgSize)
192{
193 const char *pszFormatOrg = *ppszFormat;
194 char ch = *(*ppszFormat)++;
195 size_t cch;
196 char szBuf[80];
197
198 if (ch == 'R')
199 {
200 ch = *(*ppszFormat)++;
201 switch (ch)
202 {
203 /*
204 * Groups 1 and 2.
205 */
206 case 'T':
207 case 'G':
208 case 'H':
209 case 'R':
210 case 'C':
211 case 'I':
212 case 'X':
213 case 'U':
214 {
215 /*
216 * Interpret the type.
217 */
218 typedef enum
219 {
220 RTSF_INT,
221 RTSF_INTW,
222 RTSF_BOOL,
223 RTSF_FP16,
224 RTSF_FP32,
225 RTSF_FP64,
226 RTSF_IPV4,
227 RTSF_IPV6,
228 RTSF_MAC,
229 RTSF_NETADDR,
230 RTSF_UUID
231 } RTSF;
232 static const struct
233 {
234 uint8_t cch; /**< the length of the string. */
235 char sz[10]; /**< the part following 'R'. */
236 uint8_t cb; /**< the size of the type. */
237 uint8_t u8Base; /**< the size of the type. */
238 RTSF enmFormat; /**< The way to format it. */
239 uint16_t fFlags; /**< additional RTSTR_F_* flags. */
240 }
241 /** Sorted array of types, looked up using binary search! */
242 s_aTypes[] =
243 {
244#define STRMEM(str) sizeof(str) - 1, str
245 { STRMEM("Ci"), sizeof(RTINT), 10, RTSF_INT, RTSTR_F_VALSIGNED },
246 { STRMEM("Cp"), sizeof(RTCCPHYS), 16, RTSF_INTW, 0 },
247 { STRMEM("Cr"), sizeof(RTCCUINTREG), 16, RTSF_INTW, 0 },
248 { STRMEM("Cu"), sizeof(RTUINT), 10, RTSF_INT, 0 },
249 { STRMEM("Cv"), sizeof(void *), 16, RTSF_INTW, 0 },
250 { STRMEM("Cx"), sizeof(RTUINT), 16, RTSF_INT, 0 },
251 { STRMEM("Gi"), sizeof(RTGCINT), 10, RTSF_INT, RTSTR_F_VALSIGNED },
252 { STRMEM("Gp"), sizeof(RTGCPHYS), 16, RTSF_INTW, 0 },
253 { STRMEM("Gr"), sizeof(RTGCUINTREG), 16, RTSF_INTW, 0 },
254 { STRMEM("Gu"), sizeof(RTGCUINT), 10, RTSF_INT, 0 },
255 { STRMEM("Gv"), sizeof(RTGCPTR), 16, RTSF_INTW, 0 },
256 { STRMEM("Gx"), sizeof(RTGCUINT), 16, RTSF_INT, 0 },
257 { STRMEM("Hi"), sizeof(RTHCINT), 10, RTSF_INT, RTSTR_F_VALSIGNED },
258 { STRMEM("Hp"), sizeof(RTHCPHYS), 16, RTSF_INTW, 0 },
259 { STRMEM("Hr"), sizeof(RTHCUINTREG), 16, RTSF_INTW, 0 },
260 { STRMEM("Hu"), sizeof(RTHCUINT), 10, RTSF_INT, 0 },
261 { STRMEM("Hv"), sizeof(RTHCPTR), 16, RTSF_INTW, 0 },
262 { STRMEM("Hx"), sizeof(RTHCUINT), 16, RTSF_INT, 0 },
263 { STRMEM("I16"), sizeof(int16_t), 10, RTSF_INT, RTSTR_F_VALSIGNED },
264 { STRMEM("I32"), sizeof(int32_t), 10, RTSF_INT, RTSTR_F_VALSIGNED },
265 { STRMEM("I64"), sizeof(int64_t), 10, RTSF_INT, RTSTR_F_VALSIGNED },
266 { STRMEM("I8"), sizeof(int8_t), 10, RTSF_INT, RTSTR_F_VALSIGNED },
267 { STRMEM("Rv"), sizeof(RTRCPTR), 16, RTSF_INTW, 0 },
268 { STRMEM("Tbool"), sizeof(bool), 10, RTSF_BOOL, 0 },
269 { STRMEM("Tfile"), sizeof(RTFILE), 10, RTSF_INT, 0 },
270 { STRMEM("Tfmode"), sizeof(RTFMODE), 16, RTSF_INTW, 0 },
271 { STRMEM("Tfoff"), sizeof(RTFOFF), 10, RTSF_INT, RTSTR_F_VALSIGNED },
272 { STRMEM("Tfp16"), sizeof(RTFAR16), 16, RTSF_FP16, RTSTR_F_ZEROPAD },
273 { STRMEM("Tfp32"), sizeof(RTFAR32), 16, RTSF_FP32, RTSTR_F_ZEROPAD },
274 { STRMEM("Tfp64"), sizeof(RTFAR64), 16, RTSF_FP64, RTSTR_F_ZEROPAD },
275 { STRMEM("Tgid"), sizeof(RTGID), 10, RTSF_INT, RTSTR_F_VALSIGNED },
276 { STRMEM("Tino"), sizeof(RTINODE), 16, RTSF_INTW, 0 },
277 { STRMEM("Tint"), sizeof(RTINT), 10, RTSF_INT, RTSTR_F_VALSIGNED },
278 { STRMEM("Tiop"), sizeof(RTIOPORT), 16, RTSF_INTW, 0 },
279 { STRMEM("Tldrm"), sizeof(RTLDRMOD), 16, RTSF_INTW, 0 },
280 { STRMEM("Tmac"), sizeof(PCRTMAC), 16, RTSF_MAC, 0 },
281 { STRMEM("Tnaddr"), sizeof(PCRTNETADDR), 10, RTSF_NETADDR,0 },
282 { STRMEM("Tnaipv4"), sizeof(RTNETADDRIPV4), 10, RTSF_IPV4, 0 },
283 { STRMEM("Tnaipv6"), sizeof(PCRTNETADDRIPV6),16, RTSF_IPV6, 0 },
284 { STRMEM("Tnthrd"), sizeof(RTNATIVETHREAD), 16, RTSF_INTW, 0 },
285 { STRMEM("Tproc"), sizeof(RTPROCESS), 16, RTSF_INTW, 0 },
286 { STRMEM("Tptr"), sizeof(RTUINTPTR), 16, RTSF_INTW, 0 },
287 { STRMEM("Treg"), sizeof(RTCCUINTREG), 16, RTSF_INTW, 0 },
288 { STRMEM("Tsel"), sizeof(RTSEL), 16, RTSF_INTW, 0 },
289 { STRMEM("Tsem"), sizeof(RTSEMEVENT), 16, RTSF_INTW, 0 },
290 { STRMEM("Tsock"), sizeof(RTSOCKET), 10, RTSF_INT, 0 },
291 { STRMEM("Tthrd"), sizeof(RTTHREAD), 16, RTSF_INTW, 0 },
292 { STRMEM("Tuid"), sizeof(RTUID), 10, RTSF_INT, RTSTR_F_VALSIGNED },
293 { STRMEM("Tuint"), sizeof(RTUINT), 10, RTSF_INT, 0 },
294 { STRMEM("Tunicp"), sizeof(RTUNICP), 16, RTSF_INTW, RTSTR_F_ZEROPAD },
295 { STRMEM("Tutf16"), sizeof(RTUTF16), 16, RTSF_INTW, RTSTR_F_ZEROPAD },
296 { STRMEM("Tuuid"), sizeof(PCRTUUID), 16, RTSF_UUID, 0 },
297 { STRMEM("Txint"), sizeof(RTUINT), 16, RTSF_INT, 0 },
298 { STRMEM("U16"), sizeof(uint16_t), 10, RTSF_INT, 0 },
299 { STRMEM("U32"), sizeof(uint32_t), 10, RTSF_INT, 0 },
300 { STRMEM("U64"), sizeof(uint64_t), 10, RTSF_INT, 0 },
301 { STRMEM("U8"), sizeof(uint8_t), 10, RTSF_INT, 0 },
302 { STRMEM("X16"), sizeof(uint16_t), 16, RTSF_INT, 0 },
303 { STRMEM("X32"), sizeof(uint32_t), 16, RTSF_INT, 0 },
304 { STRMEM("X64"), sizeof(uint64_t), 16, RTSF_INT, 0 },
305 { STRMEM("X8"), sizeof(uint8_t), 16, RTSF_INT, 0 },
306#undef STRMEM
307 };
308 static const char s_szNull[] = "<NULL>";
309
310 const char *pszType = *ppszFormat - 1;
311 int iStart = 0;
312 int iEnd = RT_ELEMENTS(s_aTypes) - 1;
313 int i = RT_ELEMENTS(s_aTypes) / 2;
314
315 union
316 {
317 uint8_t u8;
318 uint16_t u16;
319 uint32_t u32;
320 uint64_t u64;
321 int8_t i8;
322 int16_t i16;
323 int32_t i32;
324 int64_t i64;
325 RTFAR16 fp16;
326 RTFAR32 fp32;
327 RTFAR64 fp64;
328 bool fBool;
329 PCRTMAC pMac;
330 RTNETADDRIPV4 Ipv4Addr;
331 PCRTNETADDRIPV6 pIpv6Addr;
332 PCRTNETADDR pNetAddr;
333 PCRTUUID pUuid;
334 } u;
335
336 AssertMsg(!chArgSize, ("Not argument size '%c' for RT types! '%.10s'\n", chArgSize, pszFormatOrg));
337
338 /*
339 * Lookup the type - binary search.
340 */
341 for (;;)
342 {
343 int iDiff = strncmp(pszType, s_aTypes[i].sz, s_aTypes[i].cch);
344 if (!iDiff)
345 break;
346 if (iEnd == iStart)
347 {
348 AssertMsgFailed(("Invalid format type '%.10s'!\n", pszFormatOrg));
349 return 0;
350 }
351 if (iDiff < 0)
352 iEnd = i - 1;
353 else
354 iStart = i + 1;
355 if (iEnd < iStart)
356 {
357 AssertMsgFailed(("Invalid format type '%.10s'!\n", pszFormatOrg));
358 return 0;
359 }
360 i = iStart + (iEnd - iStart) / 2;
361 }
362
363 /*
364 * Advance the format string and merge flags.
365 */
366 *ppszFormat += s_aTypes[i].cch - 1;
367 fFlags |= s_aTypes[i].fFlags;
368
369 /*
370 * Fetch the argument.
371 * It's important that a signed value gets sign-extended up to 64-bit.
372 */
373 RT_ZERO(u);
374 if (fFlags & RTSTR_F_VALSIGNED)
375 {
376 switch (s_aTypes[i].cb)
377 {
378 case sizeof(int8_t):
379 u.i64 = va_arg(*pArgs, /*int8_t*/int);
380 fFlags |= RTSTR_F_8BIT;
381 break;
382 case sizeof(int16_t):
383 u.i64 = va_arg(*pArgs, /*int16_t*/int);
384 fFlags |= RTSTR_F_16BIT;
385 break;
386 case sizeof(int32_t):
387 u.i64 = va_arg(*pArgs, int32_t);
388 fFlags |= RTSTR_F_32BIT;
389 break;
390 case sizeof(int64_t):
391 u.i64 = va_arg(*pArgs, int64_t);
392 fFlags |= RTSTR_F_64BIT;
393 break;
394 default:
395 AssertMsgFailed(("Invalid format error, size %d'!\n", s_aTypes[i].cb));
396 break;
397 }
398 }
399 else
400 {
401 switch (s_aTypes[i].cb)
402 {
403 case sizeof(uint8_t):
404 u.u8 = va_arg(*pArgs, /*uint8_t*/unsigned);
405 fFlags |= RTSTR_F_8BIT;
406 break;
407 case sizeof(uint16_t):
408 u.u16 = va_arg(*pArgs, /*uint16_t*/unsigned);
409 fFlags |= RTSTR_F_16BIT;
410 break;
411 case sizeof(uint32_t):
412 u.u32 = va_arg(*pArgs, uint32_t);
413 fFlags |= RTSTR_F_32BIT;
414 break;
415 case sizeof(uint64_t):
416 u.u64 = va_arg(*pArgs, uint64_t);
417 fFlags |= RTSTR_F_64BIT;
418 break;
419 case sizeof(RTFAR32):
420 u.fp32 = va_arg(*pArgs, RTFAR32);
421 break;
422 case sizeof(RTFAR64):
423 u.fp64 = va_arg(*pArgs, RTFAR64);
424 break;
425 default:
426 AssertMsgFailed(("Invalid format error, size %d'!\n", s_aTypes[i].cb));
427 break;
428 }
429 }
430
431 /*
432 * Format the output.
433 */
434 switch (s_aTypes[i].enmFormat)
435 {
436 case RTSF_INT:
437 {
438 cch = RTStrFormatNumber(szBuf, u.u64, s_aTypes[i].u8Base, cchWidth, cchPrecision, fFlags);
439 break;
440 }
441
442 /* hex which defaults to max width. */
443 case RTSF_INTW:
444 {
445 Assert(s_aTypes[i].u8Base == 16);
446 if (cchWidth < 0)
447 {
448 cchWidth = s_aTypes[i].cb * 2 + (fFlags & RTSTR_F_SPECIAL ? 2 : 0);
449 fFlags |= RTSTR_F_ZEROPAD;
450 }
451 cch = RTStrFormatNumber(szBuf, u.u64, s_aTypes[i].u8Base, cchWidth, cchPrecision, fFlags);
452 break;
453 }
454
455 case RTSF_BOOL:
456 {
457 static const char s_szTrue[] = "true ";
458 static const char s_szFalse[] = "false";
459 if (u.u64 == 1)
460 return pfnOutput(pvArgOutput, s_szTrue, sizeof(s_szTrue) - 1);
461 if (u.u64 == 0)
462 return pfnOutput(pvArgOutput, s_szFalse, sizeof(s_szFalse) - 1);
463 /* invalid boolean value */
464 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "!%lld!", u.u64);
465 }
466
467 case RTSF_FP16:
468 {
469 fFlags &= ~(RTSTR_F_VALSIGNED | RTSTR_F_BIT_MASK | RTSTR_F_WIDTH | RTSTR_F_PRECISION | RTSTR_F_THOUSAND_SEP);
470 cch = RTStrFormatNumber(&szBuf[0], u.fp16.sel, 16, 4, -1, fFlags | RTSTR_F_16BIT);
471 Assert(cch == 4);
472 szBuf[4] = ':';
473 cch = RTStrFormatNumber(&szBuf[5], u.fp16.off, 16, 4, -1, fFlags | RTSTR_F_16BIT);
474 Assert(cch == 4);
475 cch = 4 + 1 + 4;
476 break;
477 }
478 case RTSF_FP32:
479 {
480 fFlags &= ~(RTSTR_F_VALSIGNED | RTSTR_F_BIT_MASK | RTSTR_F_WIDTH | RTSTR_F_PRECISION | RTSTR_F_THOUSAND_SEP);
481 cch = RTStrFormatNumber(&szBuf[0], u.fp32.sel, 16, 4, -1, fFlags | RTSTR_F_16BIT);
482 Assert(cch == 4);
483 szBuf[4] = ':';
484 cch = RTStrFormatNumber(&szBuf[5], u.fp32.off, 16, 8, -1, fFlags | RTSTR_F_32BIT);
485 Assert(cch == 8);
486 cch = 4 + 1 + 8;
487 break;
488 }
489 case RTSF_FP64:
490 {
491 fFlags &= ~(RTSTR_F_VALSIGNED | RTSTR_F_BIT_MASK | RTSTR_F_WIDTH | RTSTR_F_PRECISION | RTSTR_F_THOUSAND_SEP);
492 cch = RTStrFormatNumber(&szBuf[0], u.fp64.sel, 16, 4, -1, fFlags | RTSTR_F_16BIT);
493 Assert(cch == 4);
494 szBuf[4] = ':';
495 cch = RTStrFormatNumber(&szBuf[5], u.fp64.off, 16, 16, -1, fFlags | RTSTR_F_64BIT);
496 Assert(cch == 16);
497 cch = 4 + 1 + 16;
498 break;
499 }
500
501 case RTSF_IPV4:
502 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
503 "%u.%u.%u.%u",
504 u.Ipv4Addr.au8[0],
505 u.Ipv4Addr.au8[1],
506 u.Ipv4Addr.au8[2],
507 u.Ipv4Addr.au8[3]);
508
509 case RTSF_IPV6:
510 {
511 if (VALID_PTR(u.pIpv6Addr))
512 return rtstrFormatIPv6(pfnOutput, pvArgOutput, u.pIpv6Addr);
513 return pfnOutput(pvArgOutput, s_szNull, sizeof(s_szNull) - 1);
514 }
515
516 case RTSF_MAC:
517 {
518 if (VALID_PTR(u.pMac))
519 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
520 "%02x:%02x:%02x:%02x:%02x:%02x",
521 u.pMac->au8[0],
522 u.pMac->au8[1],
523 u.pMac->au8[2],
524 u.pMac->au8[3],
525 u.pMac->au8[4],
526 u.pMac->au8[5]);
527 return pfnOutput(pvArgOutput, s_szNull, sizeof(s_szNull) - 1);
528 }
529
530 case RTSF_NETADDR:
531 {
532 if (VALID_PTR(u.pNetAddr))
533 {
534 switch (u.pNetAddr->enmType)
535 {
536 case RTNETADDRTYPE_IPV4:
537 if (u.pNetAddr->uPort == RTNETADDR_PORT_NA)
538 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
539 "%u.%u.%u.%u",
540 u.pNetAddr->uAddr.IPv4.au8[0],
541 u.pNetAddr->uAddr.IPv4.au8[1],
542 u.pNetAddr->uAddr.IPv4.au8[2],
543 u.pNetAddr->uAddr.IPv4.au8[3]);
544 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
545 "%u.%u.%u.%u:%u",
546 u.pNetAddr->uAddr.IPv4.au8[0],
547 u.pNetAddr->uAddr.IPv4.au8[1],
548 u.pNetAddr->uAddr.IPv4.au8[2],
549 u.pNetAddr->uAddr.IPv4.au8[3],
550 u.pNetAddr->uPort);
551
552 case RTNETADDRTYPE_IPV6:
553 if (u.pNetAddr->uPort == RTNETADDR_PORT_NA)
554 return rtstrFormatIPv6(pfnOutput, pvArgOutput, &u.pNetAddr->uAddr.IPv6);
555
556 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
557 "[%RTnaipv6]:%u",
558 &u.pNetAddr->uAddr.IPv6,
559 u.pNetAddr->uPort);
560
561 case RTNETADDRTYPE_MAC:
562 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
563 "%02x:%02x:%02x:%02x:%02x:%02x",
564 u.pNetAddr->uAddr.Mac.au8[0],
565 u.pNetAddr->uAddr.Mac.au8[1],
566 u.pNetAddr->uAddr.Mac.au8[2],
567 u.pNetAddr->uAddr.Mac.au8[3],
568 u.pNetAddr->uAddr.Mac.au8[4],
569 u.pNetAddr->uAddr.Mac.au8[5]);
570
571 default:
572 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
573 "unsupported-netaddr-type=%u", u.pNetAddr->enmType);
574
575 }
576 }
577 return pfnOutput(pvArgOutput, s_szNull, sizeof(s_szNull) - 1);
578 }
579
580 case RTSF_UUID:
581 {
582 if (VALID_PTR(u.pUuid))
583 {
584 /* cannot call RTUuidToStr because of GC/R0. */
585 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
586 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
587 RT_H2LE_U32(u.pUuid->Gen.u32TimeLow),
588 RT_H2LE_U16(u.pUuid->Gen.u16TimeMid),
589 RT_H2LE_U16(u.pUuid->Gen.u16TimeHiAndVersion),
590 u.pUuid->Gen.u8ClockSeqHiAndReserved,
591 u.pUuid->Gen.u8ClockSeqLow,
592 u.pUuid->Gen.au8Node[0],
593 u.pUuid->Gen.au8Node[1],
594 u.pUuid->Gen.au8Node[2],
595 u.pUuid->Gen.au8Node[3],
596 u.pUuid->Gen.au8Node[4],
597 u.pUuid->Gen.au8Node[5]);
598 }
599 return pfnOutput(pvArgOutput, s_szNull, sizeof(s_szNull) - 1);
600 }
601
602 default:
603 AssertMsgFailed(("Internal error %d\n", s_aTypes[i].enmFormat));
604 return 0;
605 }
606
607 /*
608 * Finally, output the formatted string and return.
609 */
610 return pfnOutput(pvArgOutput, szBuf, cch);
611 }
612
613
614 /* Group 3 */
615
616 /*
617 * Base name printing.
618 */
619 case 'b':
620 {
621 switch (*(*ppszFormat)++)
622 {
623 case 'n':
624 {
625 const char *pszLastSep;
626 const char *psz = pszLastSep = va_arg(*pArgs, const char *);
627 if (!VALID_PTR(psz))
628 return pfnOutput(pvArgOutput, RT_STR_TUPLE("<null>"));
629
630 while ((ch = *psz) != '\0')
631 {
632 if (RTPATH_IS_SEP(ch))
633 {
634 do
635 psz++;
636 while ((ch = *psz) != '\0' && RTPATH_IS_SEP(ch));
637 if (!ch)
638 break;
639 pszLastSep = psz;
640 }
641 psz++;
642 }
643
644 return pfnOutput(pvArgOutput, pszLastSep, psz - pszLastSep);
645 }
646
647 default:
648 AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
649 break;
650 }
651 break;
652 }
653
654
655 /*
656 * Pretty function / method name printing.
657 */
658 case 'f':
659 {
660 switch (*(*ppszFormat)++)
661 {
662 /*
663 * Pretty function / method name printing.
664 * This isn't 100% right (see classic signal prototype) and it assumes
665 * standardized names, but it'll do for today.
666 */
667 case 'n':
668 {
669 const char *pszStart;
670 const char *psz = pszStart = va_arg(*pArgs, const char *);
671 if (!VALID_PTR(psz))
672 return pfnOutput(pvArgOutput, RT_STR_TUPLE("<null>"));
673
674 while ((ch = *psz) != '\0' && ch != '(')
675 {
676 if (RT_C_IS_BLANK(ch))
677 {
678 psz++;
679 while ((ch = *psz) != '\0' && (RT_C_IS_BLANK(ch) || ch == '('))
680 psz++;
681 if (ch)
682 pszStart = psz;
683 }
684 else if (ch == '(')
685 break;
686 else
687 psz++;
688 }
689
690 return pfnOutput(pvArgOutput, pszStart, psz - pszStart);
691 }
692
693 default:
694 AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
695 break;
696 }
697 break;
698 }
699
700
701 /*
702 * hex dumping and COM/XPCOM.
703 */
704 case 'h':
705 {
706 switch (*(*ppszFormat)++)
707 {
708 /*
709 * Hex stuff.
710 */
711 case 'x':
712 {
713 uint8_t *pu8 = va_arg(*pArgs, uint8_t *);
714 if (cchPrecision < 0)
715 cchPrecision = 16;
716 if (pu8)
717 {
718 switch (*(*ppszFormat)++)
719 {
720 /*
721 * Regular hex dump.
722 */
723 case 'd':
724 {
725 int off = 0;
726 cch = 0;
727
728 if (cchWidth <= 0)
729 cchWidth = 16;
730
731 while (off < cchPrecision)
732 {
733 int i;
734 cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%s%0*p %04x:", off ? "\n" : "", sizeof(pu8) * 2, (uintptr_t)pu8, off);
735 for (i = 0; i < cchWidth && off + i < cchPrecision ; i++)
736 cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
737 off + i < cchPrecision ? !(i & 7) && i ? "-%02x" : " %02x" : " ", pu8[i]);
738 while (i++ < cchWidth)
739 cch += pfnOutput(pvArgOutput, " ", 3);
740
741 cch += pfnOutput(pvArgOutput, " ", 1);
742
743 for (i = 0; i < cchWidth && off + i < cchPrecision; i++)
744 {
745 uint8_t u8 = pu8[i];
746 cch += pfnOutput(pvArgOutput, u8 < 127 && u8 >= 32 ? (const char *)&u8 : ".", 1);
747 }
748
749 /* next */
750 pu8 += cchWidth;
751 off += cchWidth;
752 }
753 return cch;
754 }
755
756 /*
757 * Hex string.
758 */
759 case 's':
760 {
761 if (cchPrecision-- > 0)
762 {
763 cch = RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%02x", *pu8++);
764 for (; cchPrecision > 0; cchPrecision--, pu8++)
765 cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, " %02x", *pu8);
766 return cch;
767 }
768 break;
769 }
770
771 default:
772 AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
773 break;
774 }
775 }
776 else
777 return pfnOutput(pvArgOutput, RT_STR_TUPLE("<null>"));
778 break;
779 }
780
781
782#ifdef IN_RING3
783 /*
784 * XPCOM / COM status code: %Rhrc, %Rhrf, %Rhra
785 * ASSUMES: If Windows Then COM else XPCOM.
786 */
787 case 'r':
788 {
789 uint32_t hrc = va_arg(*pArgs, uint32_t);
790 PCRTCOMERRMSG pMsg = RTErrCOMGet(hrc);
791 switch (*(*ppszFormat)++)
792 {
793 case 'c':
794 return pfnOutput(pvArgOutput, pMsg->pszDefine, strlen(pMsg->pszDefine));
795 case 'f':
796 return pfnOutput(pvArgOutput, pMsg->pszMsgFull,strlen(pMsg->pszMsgFull));
797 case 'a':
798 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%s (0x%08X) - %s", pMsg->pszDefine, hrc, pMsg->pszMsgFull);
799 default:
800 AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
801 return 0;
802 }
803 break;
804 }
805#endif /* IN_RING3 */
806
807 default:
808 AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
809 return 0;
810
811 }
812 break;
813 }
814
815 /*
816 * iprt status code: %Rrc, %Rrs, %Rrf, %Rra.
817 */
818 case 'r':
819 {
820 int rc = va_arg(*pArgs, int);
821#ifdef IN_RING3 /* we don't want this anywhere else yet. */
822 PCRTSTATUSMSG pMsg = RTErrGet(rc);
823 switch (*(*ppszFormat)++)
824 {
825 case 'c':
826 return pfnOutput(pvArgOutput, pMsg->pszDefine, strlen(pMsg->pszDefine));
827 case 's':
828 return pfnOutput(pvArgOutput, pMsg->pszMsgShort, strlen(pMsg->pszMsgShort));
829 case 'f':
830 return pfnOutput(pvArgOutput, pMsg->pszMsgFull, strlen(pMsg->pszMsgFull));
831 case 'a':
832 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%s (%d) - %s", pMsg->pszDefine, rc, pMsg->pszMsgFull);
833 default:
834 AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
835 return 0;
836 }
837#else /* !IN_RING3 */
838 switch (*(*ppszFormat)++)
839 {
840 case 'c':
841 case 's':
842 case 'f':
843 case 'a':
844 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%d", rc);
845 default:
846 AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
847 return 0;
848 }
849#endif /* !IN_RING3 */
850 break;
851 }
852
853#if defined(IN_RING3)
854 /*
855 * Windows status code: %Rwc, %Rwf, %Rwa
856 */
857 case 'w':
858 {
859 long rc = va_arg(*pArgs, long);
860# if defined(RT_OS_WINDOWS)
861 PCRTWINERRMSG pMsg = RTErrWinGet(rc);
862# endif
863 switch (*(*ppszFormat)++)
864 {
865# if defined(RT_OS_WINDOWS)
866 case 'c':
867 return pfnOutput(pvArgOutput, pMsg->pszDefine, strlen(pMsg->pszDefine));
868 case 'f':
869 return pfnOutput(pvArgOutput, pMsg->pszMsgFull,strlen(pMsg->pszMsgFull));
870 case 'a':
871 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%s (0x%08X) - %s", pMsg->pszDefine, rc, pMsg->pszMsgFull);
872# else
873 case 'c':
874 case 'f':
875 case 'a':
876 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "0x%08X", rc);
877# endif
878 default:
879 AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
880 return 0;
881 }
882 break;
883 }
884#endif /* IN_RING3 */
885
886 /*
887 * Group 4, structure dumpers.
888 */
889 case 'D':
890 {
891 /*
892 * Interpret the type.
893 */
894 typedef enum
895 {
896 RTST_TIMESPEC
897 } RTST;
898/** Set if it's a pointer */
899#define RTST_FLAGS_POINTER RT_BIT(0)
900 static const struct
901 {
902 uint8_t cch; /**< the length of the string. */
903 char sz[16-2]; /**< the part following 'R'. */
904 uint8_t cb; /**< the size of the argument. */
905 uint8_t fFlags; /**< RTST_FLAGS_* */
906 RTST enmType; /**< The structure type. */
907 }
908 /** Sorted array of types, looked up using binary search! */
909 s_aTypes[] =
910 {
911#define STRMEM(str) sizeof(str) - 1, str
912 { STRMEM("Dtimespec"), sizeof(PCRTTIMESPEC), RTST_FLAGS_POINTER, RTST_TIMESPEC},
913#undef STRMEM
914 };
915 const char *pszType = *ppszFormat - 1;
916 int iStart = 0;
917 int iEnd = RT_ELEMENTS(s_aTypes) - 1;
918 int i = RT_ELEMENTS(s_aTypes) / 2;
919
920 union
921 {
922 const void *pv;
923 uint64_t u64;
924 PCRTTIMESPEC pTimeSpec;
925 } u;
926
927 AssertMsg(!chArgSize, ("Not argument size '%c' for RT types! '%.10s'\n", chArgSize, pszFormatOrg));
928
929 /*
930 * Lookup the type - binary search.
931 */
932 for (;;)
933 {
934 int iDiff = strncmp(pszType, s_aTypes[i].sz, s_aTypes[i].cch);
935 if (!iDiff)
936 break;
937 if (iEnd == iStart)
938 {
939 AssertMsgFailed(("Invalid format type '%.10s'!\n", pszFormatOrg));
940 return 0;
941 }
942 if (iDiff < 0)
943 iEnd = i - 1;
944 else
945 iStart = i + 1;
946 if (iEnd < iStart)
947 {
948 AssertMsgFailed(("Invalid format type '%.10s'!\n", pszFormatOrg));
949 return 0;
950 }
951 i = iStart + (iEnd - iStart) / 2;
952 }
953 *ppszFormat += s_aTypes[i].cch - 1;
954
955 /*
956 * Fetch the argument.
957 */
958 u.u64 = 0;
959 switch (s_aTypes[i].cb)
960 {
961 case sizeof(const void *):
962 u.pv = va_arg(*pArgs, const void *);
963 break;
964 default:
965 AssertMsgFailed(("Invalid format error, size %d'!\n", s_aTypes[i].cb));
966 break;
967 }
968
969 /*
970 * If it's a pointer, we'll check if it's valid before going on.
971 */
972 if ((s_aTypes[i].fFlags & RTST_FLAGS_POINTER) && !VALID_PTR(u.pv))
973 return pfnOutput(pvArgOutput, RT_STR_TUPLE("<null>"));
974
975 /*
976 * Format the output.
977 */
978 switch (s_aTypes[i].enmType)
979 {
980 case RTST_TIMESPEC:
981 return RTStrFormat(pfnOutput, pvArgOutput, NULL, NULL, "%'lld ns", RTTimeSpecGetNano(u.pTimeSpec));
982
983 default:
984 AssertMsgFailed(("Invalid/unhandled enmType=%d\n", s_aTypes[i].enmType));
985 break;
986 }
987 break;
988 }
989
990#ifdef IN_RING3
991 /*
992 * Group 5, XML / HTML escapers.
993 */
994 case 'M':
995 {
996 char chWhat = (*ppszFormat)[0];
997 bool fAttr = chWhat == 'a';
998 char chType = (*ppszFormat)[1];
999 AssertMsgBreak(chWhat == 'a' || chWhat == 'e', ("Invalid IPRT format type '%.10s'!\n", pszFormatOrg));
1000 *ppszFormat += 2;
1001 switch (chType)
1002 {
1003 case 's':
1004 {
1005 static const char s_szElemEscape[] = "<>&\"'";
1006 static const char s_szAttrEscape[] = "<>&\"\n\r"; /* more? */
1007 const char * const pszEscape = fAttr ? s_szAttrEscape : s_szElemEscape;
1008 size_t const cchEscape = (fAttr ? RT_ELEMENTS(s_szAttrEscape) : RT_ELEMENTS(s_szElemEscape)) - 1;
1009 size_t cchOutput = 0;
1010 const char *pszStr = va_arg(*pArgs, char *);
1011 ssize_t cchStr;
1012 ssize_t offCur;
1013 ssize_t offLast;
1014
1015 if (!VALID_PTR(pszStr))
1016 pszStr = "<NULL>";
1017 cchStr = RTStrNLen(pszStr, (unsigned)cchPrecision);
1018
1019 if (fAttr)
1020 cchOutput += pfnOutput(pvArgOutput, "\"", 1);
1021 if (!(fFlags & RTSTR_F_LEFT))
1022 while (--cchWidth >= cchStr)
1023 cchOutput += pfnOutput(pvArgOutput, " ", 1);
1024
1025 offLast = offCur = 0;
1026 while (offCur < cchStr)
1027 {
1028 if (memchr(pszEscape, pszStr[offCur], cchEscape))
1029 {
1030 if (offLast < offCur)
1031 cchOutput += pfnOutput(pvArgOutput, &pszStr[offLast], offCur - offLast);
1032 switch (pszStr[offCur])
1033 {
1034 case '<': cchOutput += pfnOutput(pvArgOutput, "&lt;", 4); break;
1035 case '>': cchOutput += pfnOutput(pvArgOutput, "&gt;", 4); break;
1036 case '&': cchOutput += pfnOutput(pvArgOutput, "&amp;", 5); break;
1037 case '\'': cchOutput += pfnOutput(pvArgOutput, "&apos;", 6); break;
1038 case '"': cchOutput += pfnOutput(pvArgOutput, "&quot;", 6); break;
1039 case '\n': cchOutput += pfnOutput(pvArgOutput, "&#xA;", 5); break;
1040 case '\r': cchOutput += pfnOutput(pvArgOutput, "&#xD;", 5); break;
1041 default:
1042 AssertFailed();
1043 }
1044 offLast = offCur + 1;
1045 }
1046 offCur++;
1047 }
1048 if (offLast < offCur)
1049 cchOutput += pfnOutput(pvArgOutput, &pszStr[offLast], offCur - offLast);
1050
1051 while (--cchWidth >= cchStr)
1052 cchOutput += pfnOutput(pvArgOutput, " ", 1);
1053 if (fAttr)
1054 cchOutput += pfnOutput(pvArgOutput, "\"", 1);
1055 return cchOutput;
1056 }
1057
1058 default:
1059 AssertMsgFailed(("Invalid IPRT format type '%.10s'!\n", pszFormatOrg));
1060 }
1061 break;
1062 }
1063#endif /* IN_RING3 */
1064
1065
1066 /*
1067 * Groups 6 - CPU Architecture Register Formatters.
1068 * "%RAarch[reg]"
1069 */
1070 case 'A':
1071 {
1072 char const * const pszArch = *ppszFormat;
1073 const char *pszReg = pszArch;
1074 size_t cchOutput = 0;
1075 int cPrinted = 0;
1076 size_t cchReg;
1077
1078 /* Parse out the */
1079 while ((ch = *pszReg++) && ch != '[')
1080 { /* nothing */ }
1081 AssertMsgBreak(ch == '[', ("Malformed IPRT architecture register format type '%.10s'!\n", pszFormatOrg));
1082
1083 cchReg = 0;
1084 while ((ch = pszReg[cchReg]) && ch != ']')
1085 cchReg++;
1086 AssertMsgBreak(ch == ']', ("Malformed IPRT architecture register format type '%.10s'!\n", pszFormatOrg));
1087
1088 *ppszFormat = &pszReg[cchReg + 1];
1089
1090
1091#define REG_EQUALS(a_szReg) (sizeof(a_szReg) - 1 == cchReg && !strncmp(a_szReg, pszReg, sizeof(a_szReg) - 1))
1092#define REG_OUT_BIT(a_uVal, a_fBitMask, a_szName) \
1093 do { \
1094 if ((a_uVal) & (a_fBitMask)) \
1095 { \
1096 if (!cPrinted++) \
1097 cchOutput += pfnOutput(pvArgOutput, "{" a_szName, sizeof(a_szName)); \
1098 else \
1099 cchOutput += pfnOutput(pvArgOutput, "," a_szName, sizeof(a_szName)); \
1100 (a_uVal) &= ~(a_fBitMask); \
1101 } \
1102 } while (0)
1103#define REG_OUT_CLOSE(a_uVal) \
1104 do { \
1105 if ((a_uVal)) \
1106 { \
1107 cchOutput += pfnOutput(pvArgOutput, !cPrinted ? "{unkn=" : ",unkn=", 6); \
1108 cch = RTStrFormatNumber(&szBuf[0], (a_uVal), 16, 1, -1, fFlags); \
1109 cchOutput += pfnOutput(pvArgOutput, szBuf, cch); \
1110 cPrinted++; \
1111 } \
1112 if (cPrinted) \
1113 cchOutput += pfnOutput(pvArgOutput, "}", 1); \
1114 } while (0)
1115
1116
1117 if (0)
1118 { /* dummy */ }
1119#ifdef STRFORMAT_WITH_X86
1120 /*
1121 * X86 & AMD64.
1122 */
1123 else if ( pszReg - pszArch == 3 + 1
1124 && pszArch[0] == 'x'
1125 && pszArch[1] == '8'
1126 && pszArch[2] == '6')
1127 {
1128 if (REG_EQUALS("cr0"))
1129 {
1130 uint64_t cr0 = va_arg(*pArgs, uint64_t);
1131 fFlags |= RTSTR_F_64BIT;
1132 cch = RTStrFormatNumber(&szBuf[0], cr0, 16, 8, -1, fFlags | RTSTR_F_ZEROPAD);
1133 cchOutput += pfnOutput(pvArgOutput, szBuf, cch);
1134 REG_OUT_BIT(cr0, X86_CR0_PE, "PE");
1135 REG_OUT_BIT(cr0, X86_CR0_MP, "MP");
1136 REG_OUT_BIT(cr0, X86_CR0_EM, "EM");
1137 REG_OUT_BIT(cr0, X86_CR0_TS, "DE");
1138 REG_OUT_BIT(cr0, X86_CR0_ET, "ET");
1139 REG_OUT_BIT(cr0, X86_CR0_NE, "NE");
1140 REG_OUT_BIT(cr0, X86_CR0_WP, "WP");
1141 REG_OUT_BIT(cr0, X86_CR0_AM, "AM");
1142 REG_OUT_BIT(cr0, X86_CR0_NW, "NW");
1143 REG_OUT_BIT(cr0, X86_CR0_CD, "CD");
1144 REG_OUT_BIT(cr0, X86_CR0_PG, "PG");
1145 REG_OUT_CLOSE(cr0);
1146 }
1147 else if (REG_EQUALS("cr4"))
1148 {
1149 uint64_t cr4 = va_arg(*pArgs, uint64_t);
1150 fFlags |= RTSTR_F_64BIT;
1151 cch = RTStrFormatNumber(&szBuf[0], cr4, 16, 8, -1, fFlags | RTSTR_F_ZEROPAD);
1152 cchOutput += pfnOutput(pvArgOutput, szBuf, cch);
1153 REG_OUT_BIT(cr4, X86_CR4_VME, "VME");
1154 REG_OUT_BIT(cr4, X86_CR4_PVI, "PVI");
1155 REG_OUT_BIT(cr4, X86_CR4_TSD, "TSD");
1156 REG_OUT_BIT(cr4, X86_CR4_DE, "DE");
1157 REG_OUT_BIT(cr4, X86_CR4_PSE, "PSE");
1158 REG_OUT_BIT(cr4, X86_CR4_PAE, "PAE");
1159 REG_OUT_BIT(cr4, X86_CR4_MCE, "MCE");
1160 REG_OUT_BIT(cr4, X86_CR4_PGE, "PGE");
1161 REG_OUT_BIT(cr4, X86_CR4_PCE, "PCE");
1162 REG_OUT_BIT(cr4, X86_CR4_OSFSXR, "OSFSXR");
1163 REG_OUT_BIT(cr4, X86_CR4_OSXMMEEXCPT, "OSXMMEEXCPT");
1164 REG_OUT_BIT(cr4, X86_CR4_VMXE, "VMXE");
1165 REG_OUT_BIT(cr4, X86_CR4_SMXE, "SMXE");
1166 REG_OUT_BIT(cr4, X86_CR4_PCIDE, "PCIDE");
1167 REG_OUT_BIT(cr4, X86_CR4_OSXSAVE, "OSXSAVE");
1168 REG_OUT_BIT(cr4, X86_CR4_SMEP, "SMEP");
1169 REG_OUT_BIT(cr4, X86_CR4_SMAP, "SMAP");
1170 REG_OUT_CLOSE(cr4);
1171 }
1172 else
1173 AssertMsgFailed(("Unknown x86 register specified in '%.10s'!\n", pszFormatOrg));
1174 }
1175#endif
1176 else
1177 AssertMsgFailed(("Unknown architecture specified in '%.10s'!\n", pszFormatOrg));
1178#undef REG_OUT_BIT
1179#undef REG_OUT_CLOSE
1180#undef REG_EQUALS
1181 return cchOutput;
1182 }
1183
1184 /*
1185 * Invalid/Unknown. Bitch about it.
1186 */
1187 default:
1188 AssertMsgFailed(("Invalid IPRT format type '%.10s'!\n", pszFormatOrg));
1189 break;
1190 }
1191 }
1192 else
1193 AssertMsgFailed(("Invalid IPRT format type '%.10s'!\n", pszFormatOrg));
1194
1195 NOREF(pszFormatOrg);
1196 return 0;
1197}
1198
Note: See TracBrowser for help on using the repository browser.

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