1
/* **********************************************************
2
* Copyright 2007 VMware, Inc. All rights reserved.
3
* **********************************************************/
6
* Copyright (c) 1990, 1993
7
* The Regents of the University of California. All rights reserved.
9
* This code is derived from software contributed to Berkeley by
12
* Redistribution and use in source and binary forms, with or without
13
* modification, are permitted provided that the following conditions
15
* 1. Redistributions of source code must retain the above copyright
16
* notice, this list of conditions and the following disclaimer.
17
* 2. Redistributions in binary form must reproduce the above copyright
18
* notice, this list of conditions and the following disclaimer in the
19
* documentation and/or other materials provided with the distribution.
20
* 4. Neither the name of the University nor the names of its contributors
21
* may be used to endorse or promote products derived from this software
22
* without specific prior written permission.
24
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40
* MsgFmt: format messages for the Msg module
54
#if defined(__FreeBSD__)
55
#include <sys/param.h>
57
#if !defined(_WIN32) && !defined(SOL9) && \
58
(!defined(__FreeBSD__) || __FreeBSD_version >= 500029)
61
#if !defined(__FreeBSD__) || __FreeBSD_version >= 400017
79
* Older versions of FreeBSD don't have C99 support (stdint), and also
80
* do not have wide character support. Re-implement the stuff we need
84
#if defined(__FreeBSD__) && __FreeBSD_version <= 320001
85
static INLINE const wchar_t *
86
wmemchr(const wchar_t *s, wchar_t c, size_t n)
89
for (i = 0; i < n; i++) {
99
wcslen(const wchar_t *s)
103
for (i = 0; s[i]; i++);
110
* The vmkernel doesn't have the Str module, malloc(), or
111
* some of the standard C string functions.
112
* The only ones we really need are Str_Vsnprintf() and memchr().
117
typedef int32 wchar_t;
118
typedef int32 wint_t;
119
typedef int64 intmax_t;
120
typedef size_t ptrdiff_t;
122
#define STUB(t, f, a) \
123
static INLINE t f a { NOT_IMPLEMENTED(); return (t) 0;}
124
#define VSTUB(f, a) \
125
static INLINE void f a { NOT_IMPLEMENTED(); }
126
STUB(char *, Str_Vasprintf, (char **b, const char *f, va_list a))
127
STUB(void *, malloc, (size_t s))
128
STUB(void *, realloc, (void *p, size_t s))
129
STUB(wchar_t *, wmemchr, (const wchar_t *s, wchar_t c, size_t n))
130
STUB(size_t, wcslen, (const wchar_t *s))
131
STUB(char *, strdup, (const char *s))
132
VSTUB(free, (void *p))
136
typedef int Err_Number;
137
#define ERR_INVALID (-1)
138
static INLINE Err_Number
139
Err_String2Errno(const char *string)
145
static INLINE Err_Number
146
Err_String2ErrnoDebug(const char *string)
153
Str_Vsnprintf(char *str, size_t size, const char *format, va_list ap) {
154
int n = vsnprintf(str, size, format, ap);
157
str[size - 1] = '\0';
163
static INLINE const void *
164
memchr(const void *s, int c, size_t n)
167
const uint8 *e = p + n;
183
typedef struct MsgFmtParseState {
190
* Allocator state for caller-supplied buffer.
198
/* d, i, o, u, x, X, e, E, f, F, g, G, a, A, c, s, C, S, p, and n --hpreg */
199
static int const isSpecifier[] = {
200
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
201
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
202
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
203
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
204
0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
205
0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
206
0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1,
207
1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
208
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
209
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
210
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
211
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
212
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
213
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
214
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
215
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
223
static MsgFmt_SpecFunc MsgFmtGetArg1;
224
static int MsgFmtAToI(char const **start, char const *end);
225
static void MsgFmtError(MsgFmtParseState *state, const char *fmt, ...);
227
static void MsgFmtAllocInit(MsgFmtParseState *state, void *buf, size_t size);
228
static void *MsgFmtAlloc(MsgFmtParseState *state, size_t size);
229
static Bool MsgFmtAllocArgs(MsgFmtParseState *state, int n);
230
static char *MsgFmtVasprintf(MsgFmtParseState *state,
231
const char *fmt, va_list args);
232
static void MsgFmtFreeAll(MsgFmtParseState *state);
233
static size_t MsgFmtBufUsed(MsgFmtParseState *state);
234
#ifdef HAS_BSD_PRINTF
235
static int MsgFmtSnprintfWork(char **outbuf, size_t bufSize, const char *fmt0,
236
const struct MsgFmt_Arg *args, int numArgs);
241
*-----------------------------------------------------------------------------
243
* MsgFmt_ParseWin32 --
245
* Convert the Win32 representation of a format string into another
246
* representation --hpreg
248
* XXX I haven't implemented %0 and %n, because they suck:
249
* . they mix content and presentation
250
* . they have nothing to do with parameters and hence have no
251
* equivalent in other systems
255
* -1 on failure: out of memory
256
* -2 on failure: invalid 'in'
261
*-----------------------------------------------------------------------------
265
MsgFmt_ParseWin32(MsgFmt_LitFunc *litFunc, // IN
266
MsgFmt_SpecFunc *specFunc, // IN
267
void *clientData, // IN
268
char const *in) // IN
270
char const *startUnescaped;
272
char const *pos = 0 /* Compiler warning --hpreg */;
273
char const *type = 0 /* Compiler warning --hpreg */;
279
for (; *in != '\0'; in++) {
280
/* Unsigned does matter --hpreg */
285
case 2: /* Found %<1-9>...<byte> --hpreg */
286
if (ubyte >= '0' && ubyte <= '9') {
294
if ((status = (*litFunc)(clientData, startUnescaped,
295
pos - 1 - startUnescaped)) < 0 ||
296
(status = (*specFunc)(clientData, pos, in - pos, "s", 1)) < 0) {
301
/* Fall through --hpreg */
303
case 0: /* Found <byte> --hpreg */
310
case 1: /* Found %<byte> --hpreg */
311
if (ubyte >= '1' && ubyte <= '9') {
314
ASSERT_NOT_IMPLEMENTED(ubyte != '0' && ubyte != 'n');
315
status = (*litFunc)(clientData, startUnescaped,
316
in - 1 - startUnescaped);
325
case 3: /* Found %<1-9>...!...<byte> --hpreg */
327
if ( (status = (*litFunc)(clientData, startUnescaped,
328
pos - 1 - startUnescaped)) < 0
329
|| (status = (*specFunc)(clientData, pos, type - 1 - pos,
330
type, in - type)) < 0) {
333
startUnescaped = in + 1;
346
status = (*litFunc)(clientData, startUnescaped, in - startUnescaped);
353
if ( (status = (*litFunc)(clientData, startUnescaped,
354
pos - 1 - startUnescaped)) < 0
355
|| (status = (*specFunc)(clientData, pos, in - pos, "s", 1)) < 0) {
375
*-----------------------------------------------------------------------------
379
* Parse a message format.
383
* -1 on failure: out of memory
384
* -2 on failure: invalid 'in'
389
*-----------------------------------------------------------------------------
393
MsgFmt_Parse(MsgFmt_LitFunc *litFunc, // IN
394
MsgFmt_SpecFunc *specFunc, // IN
395
void *clientData, // IN
396
char const *in) // IN
398
char const *startUnescaped;
400
unsigned int counter;
402
char const *startEscaped = 0 /* Compiler warning --hpreg */;
403
char const *type = 0 /* Compiler warning --hpreg */;
404
Bool usePos = FALSE /* Compiler warning --hpreg */;
410
for (; *in != '\0'; in++) {
411
/* Unsigned does matter --hpreg */
416
case 0: /* Found <byte> --hpreg */
422
case 1: /* Found %<byte> --hpreg */
424
if (litFunc != NULL &&
425
(status = (*litFunc)(clientData, startUnescaped,
426
in - 1 - startUnescaped)) < 0) {
435
if (ubyte >= '1' && ubyte <= '9') {
440
/* Fall through --hpreg */
442
case 3: /* Found %<1-9>...$...<byte> or %...<byte> --hpreg */
444
if (isSpecifier[ubyte]) {
447
char posBuf[10 /* 32 bits unsigned in decimal --hpreg */];
450
if (usePos != (startEscaped != type)) {
454
usePos = (startEscaped != type);
465
current = posBuf + sizeof(posBuf);
471
ASSERT(current >= posBuf);
472
*current = '0' + value % 10;
478
if (litFunc != NULL &&
479
(status = (*litFunc)(clientData, startUnescaped,
480
startEscaped - 1 - startUnescaped)) < 0) {
483
if ((status = (*specFunc)(clientData, pos, posEnd - pos, type,
484
in + 1 - type)) < 0) {
487
startUnescaped = in + 1;
491
/* Digits for field width & precision, zero for leading zeroes,
492
and dot for separator between width and precision. */
493
if ((ubyte >= '0' && ubyte <= '9') || ubyte == '.') {
497
if (ubyte == '#' || ubyte == '-' || ubyte == ' ' || ubyte == '+' ||
501
/* Length modifiers */
502
if (ubyte == 'L' || ubyte == 'l' || ubyte == 'h' || ubyte == 'z' ||
503
ubyte == 'Z' || ubyte == 't' || ubyte == 'q' || ubyte == 'j' ||
509
case 2: /* Found %<1-9>...<byte> --hpreg */
510
if (ubyte >= '0' && ubyte <= '9') {
530
if (litFunc != NULL &&
531
(status = (*litFunc)(clientData, startUnescaped,
532
in - startUnescaped)) < 0) {
541
*-----------------------------------------------------------------------------
543
* MsgFmt_ParseSpec --
545
* Given a format specifier (the % stuff), return its contituent parts.
548
* 0 on success, -2 (bad format) on failure.
550
* Width and precision are -1 if not specified.
551
* Length modifier is '\0' if not specified.
552
* Length modifier of "ll", "I64", or "q" is returned as 'L'.
553
* (This means we freely allow %llf and %qf, which is not strictly
554
* correct. However, glibc printf allows them (as well as %Ld),
555
* and they mean the same thing.)
556
* Length modifier of "hh" is returned as 'H'.
557
* Length modifier of "Z" is returned as 'z', for compatibility
559
* On failure, some or all of the out parameters may be modified
560
* in an undefined manner.
565
*-----------------------------------------------------------------------------
569
MsgFmt_ParseSpec(char const *pos, // IN: n$ location
570
unsigned int posSize, // IN: n$ length
571
char const *type, // IN: specifier after position
572
unsigned int typeSize, // IN: size of above
573
int *position, // OUT: argument position
574
int *flags, // OUT: flags
575
int *width, // OUT: width
576
int *precision, // OUT: precision
577
char *lengthMod, // OUT: length modifier
578
char *conversion) // OUT: conversion specifier
580
char const *p = type;
581
char const *end = type + typeSize;
584
* Convert argument position to int.
585
* Fail if not a good decimal number greater than 0.
589
char const *posEnd = pos + posSize;
590
*position = MsgFmtAToI(&pos, posEnd);
591
if (*position <= 0 || pos != posEnd) {
597
* The format specifier is, in this order,
599
* an optional width (a decimal number or *)
600
* an optional precision (. followed by optional decimal number or *)
601
* an optional length modifier (l, L, ll, z, etc.)
602
* conversion specifier (a character)
604
* The rest of this module does not recognize * as width or precision,
605
* so we don't do it here either.
607
* glibc 2.2 supports the I flag, which we don't. Instead, we
608
* support the I, I32, and I64 length modifiers used by Microsoft.
616
for (; p < end; p++) {
619
*flags |= MSGFMT_FLAG_ALT;
622
*flags |= MSGFMT_FLAG_ZERO;
625
*flags |= MSGFMT_FLAG_MINUS;
628
*flags |= MSGFMT_FLAG_SPACE;
631
*flags |= MSGFMT_FLAG_PLUS;
634
*flags |= MSGFMT_FLAG_QUOTE;
647
if (p >= end || *p < '1' || *p > '9') {
650
*width = MsgFmtAToI(&p, end);
660
if (p >= end || *p != '.') {
664
*precision = MsgFmtAToI(&p, end);
665
if (*precision < 0) {
681
if (p >= end || *p != 'h') {
690
if (p >= end || *p != 'l') {
700
* I64 is 64-bit number. For us, the same as L.
701
* I32 is 32-bit number. For us, nothing.
704
if (p + 2 < end && p[1] == '6' && p[2] == '4') {
707
} else if (p + 2 < end && p[1] == '3' && p[2] == '2') {
731
* Conversion specifier
733
* Return false if no conversion specifier or not the last character.
736
if (p + 1 == end && isSpecifier[(unsigned char) *p]) {
745
*-----------------------------------------------------------------------------
749
* Convert numeric string to integer.
750
* The range is 0 to MAX_INT32 (nonnegative 32-bit signed int).
751
* Empty string or a string that does not begin with
752
* a digit is treated as 0.
755
* The number or -1 on overflow.
756
* Start pointer updated to point to first nonnumeric character.
757
* or first character before overflow.
762
*-----------------------------------------------------------------------------
766
MsgFmtAToI(char const **start, // IN/OUT: string pointer
767
char const *end) // IN: end of string
772
ASSERT_ON_COMPILE(sizeof (int) >= 4);
773
for (p = *start; p < end && *p >= '0' && *p <= '9'; p++) {
774
if (n > MAX_INT32 / 10) {
791
*-----------------------------------------------------------------------------
795
* Parse a format string and return the arguments implied by it.
800
* The array of MsgFmt_Arg structures.
801
* The number of arguments.
802
* An error string on failure.
805
* Memory is allocated.
807
*-----------------------------------------------------------------------------
811
MsgFmt_GetArgs(const char *fmt, // IN: format string
812
va_list va, // IN: the argument list
813
MsgFmt_Arg **args, // OUT: the returned arguments
814
int *numArgs, // OUT: number of returned arguments
815
char **error) // OUT: error string
817
return MsgFmt_GetArgsWithBuf(fmt, va, args, numArgs, error, NULL, NULL);
822
*-----------------------------------------------------------------------------
824
* MsgFmt_GetArgsWithBuf --
826
* Parse a format string and return the arguments implied by it.
828
* If buf is supplied, allocate memory there instead of with malloc().
833
* The array of MsgFmt_Arg structures.
834
* The number of arguments.
835
* An error string on failure.
836
* The amount of buf used (if caller supplied buf)
839
* Memory may be allocated.
841
*-----------------------------------------------------------------------------
845
MsgFmt_GetArgsWithBuf(const char *fmt, // IN: format string
846
va_list va, // IN: the argument list
847
MsgFmt_Arg **args, // OUT: the returned arguments
848
int *numArgs, // OUT: number of returned arguments
849
char **error, // OUT: error string
850
void *buf, // OUT: memory to store output
851
size_t *bufSize) // IN/OUT: size of buf /
852
// amount of buf used
854
MsgFmtParseState state;
858
memset(&state, 0, sizeof state);
860
ASSERT(bufSize != NULL);
861
MsgFmtAllocInit(&state, buf, *bufSize);
865
* First pass: parse format to get argument information
868
status = MsgFmt_Parse(NULL, MsgFmtGetArg1, &state, fmt);
874
* Second pass: get argument values
876
* While we can store most values directly in the MsgFmt_Arg
877
* structure, strings have to be copied into allocated space.
878
* When precision is specified (see comment about it in
879
* MsgFmtGetArg1()), we copy at most that many bytes because
880
* that's how many printf() looks at, and we must not touch
881
* memory beyond what printf() would.
884
for (i = 0; i < state.numArgs; i++) {
885
MsgFmt_Arg *a = state.args + i;
887
case MSGFMT_ARG_INVALID:
888
MsgFmtError(&state, "MsgFmt_GetArgs: gap in arguments at position %d",
893
case MSGFMT_ARG_INT32:
894
ASSERT_ON_COMPILE(sizeof (int) == sizeof (int32));
895
a->v.signed32 = va_arg(va, int);
897
case MSGFMT_ARG_INT64:
898
ASSERT_ON_COMPILE(sizeof (long long) == sizeof (int64));
899
a->v.signed64 = va_arg(va, long long);
902
case MSGFMT_ARG_PTR32:
903
// we can only handle this case if native pointer is 4 bytes
904
ASSERT(sizeof (void *) == sizeof (uint32));
905
a->v.unsigned32 = (uint32) (uintptr_t) va_arg(va, void *);
907
case MSGFMT_ARG_PTR64:
908
// we can only handle this case if native pointer is 8 bytes
909
ASSERT(sizeof (void *) == sizeof (uint64));
910
a->v.unsigned64 = (uint64) (uintptr_t) va_arg(va, void *);
913
case MSGFMT_ARG_FLOAT64:
914
ASSERT_ON_COMPILE(sizeof (double) == 8);
915
a->v.float64 = va_arg(va, double);
918
case MSGFMT_ARG_STRING8: {
919
const char *p = va_arg(va, char *);
921
Err_Number errorNumber;
922
ASSERT_ON_COMPILE(sizeof (char) == sizeof (int8));
923
ASSERT_ON_COMPILE(offsetof(MsgFmt_Arg, v.string8) ==
924
offsetof(MsgFmt_Arg, v.ptr));
928
if (a->p.precision < 0) {
933
q = memchr(p, '\0', n);
938
// yes, sizeof (int8) is 1.
939
a->v.string8 = MsgFmtAlloc(&state, n + 1);
940
if (a->v.string8 == NULL) {
944
memcpy(a->v.string8, p, n);
945
a->v.string8[n] = '\0';
947
errorNumber = Err_String2Errno(p);
949
if (errorNumber == ERR_INVALID && p != NULL) {
950
// p may not be null terminated, so use string8
951
errorNumber = Err_String2ErrnoDebug(a->v.string8char);
952
if (errorNumber != ERR_INVALID) {
953
// Err_String2ErrnoDebug already logged its info
954
Log("%s: failed to look up copied error string at %p.\n",
959
if (errorNumber != ERR_INVALID) {
960
ASSERT_NOT_IMPLEMENTED(MSGFMT_CURRENT_PLATFORM !=
961
MSGFMT_PLATFORM_UNKNOWN);
962
ASSERT_ON_COMPILE(sizeof errorNumber == sizeof a->e.number);
963
a->type = MSGFMT_ARG_ERRNO;
964
a->e.platform = MSGFMT_CURRENT_PLATFORM;
965
a->e.number = errorNumber;
970
case MSGFMT_ARG_STRING16:
971
case MSGFMT_ARG_STRING32: {
972
// we can only handle the case when native wchar_t matches
973
// the string char size
974
const wchar_t *p = va_arg(va, wchar_t *);
976
ASSERT(a->type == MSGFMT_ARG_STRING16 ?
977
sizeof (wchar_t) == sizeof (int16) :
978
sizeof (wchar_t) == sizeof (int32));
979
ASSERT_ON_COMPILE(offsetof(MsgFmt_Arg, v.string16) ==
980
offsetof(MsgFmt_Arg, v.ptr));
981
ASSERT_ON_COMPILE(offsetof(MsgFmt_Arg, v.string32) ==
982
offsetof(MsgFmt_Arg, v.ptr));
986
if ((n = a->p.precision) < 0) {
990
const wchar_t *q = wmemchr(p, 0, n);
996
// fix this when we get new compiler -- edward
997
const wchar_t *e = p + n;
999
for (q = p; q < e && *q != 0; q++) {
1004
a->v.ptr = MsgFmtAlloc(&state, sizeof (wchar_t) * (n + 1));
1005
if (a->v.ptr == NULL) {
1009
memcpy(a->v.ptr, p, sizeof (wchar_t) * n);
1010
((wchar_t *) a->v.ptr)[n] = 0;
1015
case MSGFMT_ARG_ERRNO: // there shouldn't be this case here
1020
// clear private data
1021
memset(&a->p, 0, sizeof a->p);
1029
MsgFmtFreeAll(&state);
1033
if (numArgs != NULL) {
1034
*numArgs = state.numArgs;
1036
if (bufSize != NULL) {
1037
*bufSize = MsgFmtBufUsed(&state);
1039
ASSERT(state.error == NULL);
1044
if (state.error == NULL) {
1047
MsgFmtError(&state, "MsgFmt_GetArgs: out of memory");
1050
MsgFmtError(&state, "MsgFmt_GetArgs: error in format string");
1053
MsgFmtError(&state, "MsgFmt_GetArgs: error %d", status);
1056
ASSERT(state.args == NULL); // MsgFmtError() frees args
1057
*error = state.error;
1063
*-----------------------------------------------------------------------------
1067
* Process one format specifier for MsgFmt_GetArgs().
1068
* Called by MsgFmt_Parse().
1072
* negative status on failure (see MsgFmt_Parse()).
1073
* error string in state.error on failure.
1076
* Memory is allocated.
1078
*-----------------------------------------------------------------------------
1082
MsgFmtGetArg1(void *clientData, // IN: state
1083
const char *pos, // IN: n$ location
1084
unsigned int posSize, // IN: n$ length
1085
char const *type, // IN: specifier after position
1086
unsigned int typeSize) // IN: size of above
1088
MsgFmtParseState *state = clientData;
1096
MsgFmt_ArgType argType = MSGFMT_ARG_INVALID;
1100
* Parse format specifier
1103
status = MsgFmt_ParseSpec(pos, posSize, type, typeSize,
1104
&position, &flags, &width, &precision,
1105
&lengthMod, &conversion);
1108
"MsgFmtGetArg1: bad specifier, "
1109
"status %d, pos \"%.*s\", type \"%.*s\"",
1110
status, posSize, pos, typeSize, type);
1115
* Make room in argument array if necessary.
1118
if (position > state->numArgs) {
1119
if (!MsgFmtAllocArgs(state, position)) {
1120
MsgFmtError(state, "MsgFmtGetArg1: out of memory at arg %d",
1124
state->numArgs = position;
1128
* Fill in argument structure based on the format specifier.
1130
* For strings, the precision argument is the maximum length
1131
* to print. We need to keep track of it so MsgFmt_GetArgs()
1132
* can know how many characters to squirrel away, in case
1133
* the string isn't null terminated, is very long, or falls off
1134
* the end of the world.
1136
* In all other cases, the precision is unimportant to us
1137
* and we don't keep it around.
1140
a = state->args + position - 1;
1142
switch (conversion) {
1149
switch (lengthMod) {
1150
// all of these take an int argument, they just print differently
1154
ASSERT_ON_COMPILE(sizeof (int) == sizeof (int32));
1155
argType = MSGFMT_ARG_INT32;
1159
ASSERT_ON_COMPILE(sizeof (long) == sizeof (int32) ||
1160
sizeof (long) == sizeof (int64));
1161
if (sizeof (long) == sizeof (int32)) {
1162
argType = MSGFMT_ARG_INT32;
1164
argType = MSGFMT_ARG_INT64;
1169
#ifndef _WIN32 // no intmax_t, bsd_vsnprintf() uses 64 bits
1170
ASSERT_ON_COMPILE(sizeof (intmax_t) == sizeof (int64));
1173
ASSERT_ON_COMPILE(sizeof (long long) == sizeof (int64));
1174
argType = MSGFMT_ARG_INT64;
1178
ASSERT_ON_COMPILE(sizeof (ptrdiff_t) == sizeof (size_t));
1180
ASSERT_ON_COMPILE(sizeof (size_t) == sizeof (int32) ||
1181
sizeof (size_t) == sizeof (int64));
1182
if (sizeof (size_t) == sizeof (int32)) {
1183
argType = MSGFMT_ARG_INT32;
1185
argType = MSGFMT_ARG_INT64;
1201
switch (lengthMod) {
1202
// l h hh t z are not defined by man page, but allowed by glibc
1209
ASSERT_ON_COMPILE(sizeof (double) == 8);
1210
argType = MSGFMT_ARG_FLOAT64;
1212
// j is not defined by man page, but allowed by glibc
1216
* We don't do %Lf because it's not that useful to us, and
1217
* long double has a number of implementations. For example,
1218
* on Win32 it's the same as double, and it would have a hard
1219
* time dealing with a bigger one passed to it.
1220
* We can just coerce it down to a double at the source,
1221
* but then why bother?
1224
"MsgFmtGetArg1: %%%c%c not supported, "
1225
"pos \"%.*s\", type \"%.*s\"",
1226
lengthMod, conversion, posSize, pos, typeSize, type);
1234
switch (lengthMod) {
1235
// h hh t z not defined by man page, but allowed by glibc
1241
ASSERT_ON_COMPILE(sizeof (int) == sizeof (int32));
1242
argType = MSGFMT_ARG_INT32;
1244
// j ll L not defined by man page nor actually supported
1256
// man page says it's a wint_t argument, but we assume promotion to int
1257
ASSERT_ON_COMPILE(sizeof (wint_t) <= sizeof (int) &&
1258
sizeof (int) == sizeof (int32));
1259
argType = MSGFMT_ARG_INT32;
1263
// we interpret the length modifier like we do for %c
1264
switch (lengthMod) {
1270
ASSERT_ON_COMPILE(sizeof (char) == sizeof (int8));
1271
argType = MSGFMT_ARG_STRING8;
1280
// keep track of maximum string length, see block comment above
1281
a->p.precision = precision;
1282
ASSERT(a->v.ptr == NULL);
1288
#if defined __ANDROID__
1289
ASSERT_ON_COMPILE(sizeof (wchar_t) == sizeof (int16) ||
1290
sizeof (wchar_t) == sizeof (int32) ||
1291
sizeof (wchar_t) == sizeof (int8));
1293
ASSERT_ON_COMPILE(sizeof (wchar_t) == sizeof (int16) ||
1294
sizeof (wchar_t) == sizeof (int32));
1297
if (sizeof (wchar_t) == sizeof (int16)) {
1298
argType = MSGFMT_ARG_STRING16;
1299
#if defined __ANDROID__
1300
} else if (sizeof (wchar_t) == sizeof (int8)) {
1301
argType = MSGFMT_ARG_STRING8;
1304
argType = MSGFMT_ARG_STRING32;
1306
// keep track of maximum string length, see block comment above
1307
a->p.precision = precision;
1308
ASSERT(a->v.ptr == NULL);
1312
ASSERT_ON_COMPILE(sizeof (void *) == sizeof (int32) ||
1313
sizeof (void *) == sizeof (int64));
1314
if (sizeof (void *) == sizeof (int32)) {
1315
argType = MSGFMT_ARG_PTR32;
1317
argType = MSGFMT_ARG_PTR64;
1323
"MsgFmtGetArg1: %%n not supported, "
1324
"pos \"%.*s\", type \"%.*s\"",
1325
posSize, pos, typeSize, type);
1328
// MsgFmt_ParseSpec() doesn't do %m, and we don't see %%
1331
"MsgFmtGetArg1: %%%c not understood, "
1332
"pos \"%.*s\", type \"%.*s\"",
1333
conversion, posSize, pos, typeSize, type);
1337
ASSERT(argType != MSGFMT_ARG_INVALID);
1338
if (a->type != MSGFMT_ARG_INVALID && a->type != argType) {
1340
"MsgFmtGetArg1: incompatible specifiers for argument %d, "
1341
"old type %d, new type %d, pos \"%.*s\", type \"%.*s\"",
1342
position, a->type, argType, posSize, pos, typeSize, type);
1352
*-----------------------------------------------------------------------------
1356
* Format an error string and squirrel it away.
1359
* Error string returned in state variable.
1362
* Memory may be allocated.
1364
*-----------------------------------------------------------------------------
1368
MsgFmtError(MsgFmtParseState *state, // IN/OUT: state structure
1369
const char *fmt, // IN: error format
1370
...) // IN: error args
1374
ASSERT(state->error == NULL);
1375
// free up space (in call-supplied buffer) for error string
1376
MsgFmtFreeAll(state);
1377
va_start(args, fmt);
1378
state->error = MsgFmtVasprintf(state, fmt, args);
1384
*-----------------------------------------------------------------------------
1386
* MsgFmt_FreeArgs --
1388
* Free an array of MsgFmt_Arg structures.
1389
* Do not call this on an array in a caller-supplied
1390
* buffer from MsgFmt_GetArgsWithBuf().
1398
*-----------------------------------------------------------------------------
1402
MsgFmt_FreeArgs(MsgFmt_Arg *args, // IN/OUT: arguments to free
1403
int numArgs) // IN: number of arguments
1407
for (i = 0; i < numArgs; i++) {
1408
switch (args[i].type) {
1409
case MSGFMT_ARG_STRING8:
1410
case MSGFMT_ARG_STRING16:
1411
case MSGFMT_ARG_STRING32:
1412
case MSGFMT_ARG_ERRNO:
1413
free(args[i].v.ptr);
1424
*-----------------------------------------------------------------------------
1426
* MsgFmtAllocInit --
1428
* Initialize allocator for caller-supplied buffer.
1436
*-----------------------------------------------------------------------------
1440
MsgFmtAllocInit(MsgFmtParseState *state, // IN/OUT: state structure
1441
void *buf, // IN: buffer
1442
size_t size) // IN: size to allocate
1444
state->bufp = state->buf = buf;
1445
state->bufe = state->bufp + size;
1450
*-----------------------------------------------------------------------------
1454
* Allocate memory from malloc() or from supplied buffer.
1457
* Pointer or NULL on failure.
1460
* Memory allocated or state updated.
1462
*-----------------------------------------------------------------------------
1466
MsgFmtAlloc(MsgFmtParseState *state, // IN/OUT: state structure
1467
size_t size) // IN: size to allocate
1471
if (state->buf == NULL) {
1474
if (state->bufe - state->bufp < size) {
1478
state->bufp += size;
1485
*-----------------------------------------------------------------------------
1487
* MsgFmtAllocArgs --
1489
* Grow MsgFmt_Arg array to accomodate new entry.
1496
* Memory may be allocated.
1498
*-----------------------------------------------------------------------------
1502
MsgFmtAllocArgs(MsgFmtParseState *state, // IN/OUT: state structure
1503
int n) // IN: 1-based argument number
1505
if (n <= state->maxArgs) {
1510
* If using malloc, then reallocate() the array with some slack.
1511
* If using our own buffer, just grow it exactly.
1514
if (state->buf == NULL) {
1516
n = MAX(4, n + state->maxArgs);
1517
p = realloc(state->args, n * sizeof *state->args);
1523
if (state->args == NULL) {
1525
state->args = (void *) state->bufp;
1527
// growing: there must be nothing after the args array
1528
ASSERT((void *) state->bufp == state->args + state->maxArgs);
1530
if ((char *) (state->args + n) > state->bufe) {
1533
state->bufp = (char *) (state->args + n);
1535
memset(state->args + state->maxArgs, 0,
1536
sizeof *state->args * (n - state->maxArgs));
1543
*-----------------------------------------------------------------------------
1545
* MsgFmtVasprintf --
1547
* Format a string in allocated space.
1553
* Memory allocated or state updated.
1554
* Panic if can't allocate.
1556
*-----------------------------------------------------------------------------
1560
MsgFmtVasprintf(MsgFmtParseState *state, // IN/OUT: state structure
1561
const char *fmt, // IN: error format
1562
va_list args) // IN: error args
1566
ASSERT(state->error == NULL);
1567
if (state->buf == NULL) {
1568
p = Str_Vasprintf(NULL, fmt, args);
1569
ASSERT_MEM_ALLOC(p != NULL);
1573
// Str_Vsnprintf() may truncate
1574
n = Str_Vsnprintf(p, (char *)state->bufe - p, fmt, args);
1575
state->bufp = (n < 0) ? state->bufe : state->bufp + n + 1;
1582
*-----------------------------------------------------------------------------
1586
* Free all memory associated with current MsgFmt_Arg array.
1592
* Memory may be freed.
1594
*-----------------------------------------------------------------------------
1598
MsgFmtFreeAll(MsgFmtParseState *state) // IN/OUT: state structure
1600
if (state->args == NULL)
1603
if (state->buf == NULL) {
1604
MsgFmt_FreeArgs(state->args, state->numArgs);
1606
state->bufp = state->buf;
1608
state->numArgs = state->maxArgs = 0;
1614
*-----------------------------------------------------------------------------
1618
* Return the amount of space used in the caller supplied buffer.
1626
*-----------------------------------------------------------------------------
1630
MsgFmtBufUsed(MsgFmtParseState *state) // IN: state structure
1632
if (state->buf == NULL) {
1635
return state->bufp - (char *)state->buf;
1641
*-----------------------------------------------------------------------------
1643
* MsgFmt_SwizzleArgs --
1645
* Pointer swizzling. Flattens pointers in the MsgFmt_Arg array by
1646
* converting them to offsets relative to the start of the args array.
1647
* This should only be invoked if the MsgFmt_Arg array was allocated
1648
* from a caller-supplied buffer from MsgFmt_GetArgsWithBuf.
1654
* For all i such that args[i] is a string parameter,
1655
* args[i].v.offset is set to the offset from args to the start
1656
* of the string, or to 0 if the string was NULL.
1658
*-----------------------------------------------------------------------------
1662
MsgFmt_SwizzleArgs(MsgFmt_Arg *args,
1666
int8* bufStart = (int8*)args;
1668
for (i = 0; i < numArgs; i++) {
1670
switch (args[i].type) {
1671
case MSGFMT_ARG_STRING8:
1672
case MSGFMT_ARG_STRING16:
1673
case MSGFMT_ARG_STRING32:
1674
if (args[i].v.ptr == NULL) {
1675
// offset is never 0 otherwise
1676
args[i].v.offset = 0;
1678
args[i].v.offset = (int8*)args[i].v.ptr - bufStart;
1689
*-----------------------------------------------------------------------------
1691
* MsgFmt_GetSwizzledString --
1693
* Helper for pointer un-swizzling. Obtains the pointer encoded
1694
* by a swizzled argument, if it is a string and the pointer is
1695
* within the proper bounds.
1698
* NULL and a non-zero return value if the given argument is not
1699
* a string, or the pointer is out of bounds (below the end of
1700
* the args array or above the end of the buffer), or the string
1701
* is not null-terminated within the buffer.
1703
* Exception to the above: an offset of 0 is used to encode the
1704
* NULL pointer. In this case, yields NULL and returns zero.
1706
* Otherwise, yields a pointer to the string and returns zero.
1711
*-----------------------------------------------------------------------------
1715
MsgFmt_GetSwizzledString(const MsgFmt_Arg *args, // IN: argument array
1716
int numArgs, // IN: size of the array
1717
int i, // IN: index into the array
1718
const void *bufEnd, // IN: string space bound
1719
const int8 **str) // OUT: the string
1721
const int8 *bufStart = (const int8*)args;
1722
const int8 *strStart = (const int8*)(args + numArgs);
1723
const int8 *strEnd = bufEnd;
1725
switch(args[i].type) {
1726
case MSGFMT_ARG_STRING8:
1727
case MSGFMT_ARG_STRING16:
1728
case MSGFMT_ARG_STRING32:
1729
if (args[i].v.offset == 0) {
1730
// offset is never 0 otherwise
1734
const int8 *ptr = args[i].v.offset + bufStart;
1736
if (ptr < strStart || ptr >= strEnd
1737
|| memchr(ptr, '\0', strEnd - ptr) == NULL) {
1755
*-----------------------------------------------------------------------------
1757
* MsgFmt_UnswizzleArgs --
1759
* Pointer un-swizzling. Re-instates the pointers in the arg array.
1760
* This should only be invoked if the MsgFmt_Arg array was previously
1761
* swizzled using MsgFmt_SwizzleArgs.
1763
* If a reconstituted pointer would be out of range -- i.e.,
1764
* before the end of the args array or after the provided
1765
* end-of-buffer pointer -- it is replaced with NULL and an error
1766
* is returned. This is also done if the resulting string is not
1767
* null-terminated within the provided bound.
1770
* 0 on success; -1 in case of bad pointer.
1773
* For all i such that args[i] is a string parameter, sets
1774
* args[i].v.ptr to the string previously encoded as an offset,
1775
* or to NULL if the offset was 0, or to NULL in case of error.
1777
*-----------------------------------------------------------------------------
1781
MsgFmt_UnswizzleArgs(MsgFmt_Arg *args, // IN/OUT: the arguments (+ strings)
1782
int numArgs, // IN: number of arguments
1783
void *bufEnd) // IN: string space bound
1788
for (i = 0; i < numArgs; i++) {
1789
switch (args[i].type) {
1790
case MSGFMT_ARG_STRING8:
1791
case MSGFMT_ARG_STRING16:
1792
case MSGFMT_ARG_STRING32:
1793
if (MsgFmt_GetSwizzledString(args, numArgs, i, bufEnd,
1794
(const int8**)&args[i].v.ptr) != 0) {
1802
return failures > 0 ? -1 : 0;
1807
*-----------------------------------------------------------------------------
1809
* MsgFmt_CopyArgs --
1811
* Copy all args from the given 'copyArgs' array.
1814
* Pointer to copied args array.
1817
* Allocates memory for new args array.
1819
*-----------------------------------------------------------------------------
1823
MsgFmt_CopyArgs(MsgFmt_Arg* copyArgs, // IN: Args to be copied
1824
int numArgs) // IN: number of args
1829
args = malloc(numArgs * sizeof(MsgFmt_Arg));
1834
memcpy(args, copyArgs, numArgs * sizeof(MsgFmt_Arg));
1836
for (i = 0; i < numArgs; i++) {
1837
switch (args[i].type) {
1838
case MSGFMT_ARG_STRING8:
1839
case MSGFMT_ARG_ERRNO:
1840
if (args[i].v.string8 != NULL) {
1841
args[i].v.string8char = strdup(copyArgs[i].v.string8char);
1842
if (args[i].v.string8 == NULL) {
1843
MsgFmt_FreeArgs(args, i);
1848
case MSGFMT_ARG_STRING16:
1849
case MSGFMT_ARG_STRING32:
1851
* We don't care about these types.
1864
#ifdef HAS_BSD_PRINTF // {
1867
*-----------------------------------------------------------------------------
1869
* MsgFmt_Snprintf --
1871
* MsgFmt_Arg version of Str_Vsnprintf().
1874
* Number of character written, not including null termination,
1875
* or number of characters would have been written on overflow.
1876
* (This is exactly the same as vsnprintf(), but different
1877
* from Str_Vsnprintf().)
1878
* String is always null terminated, even on overflow.
1883
*-----------------------------------------------------------------------------
1887
MsgFmt_Snprintf(char *buf, // OUT: formatted string
1888
size_t size, // IN: size of buffer
1889
const char *format, // IN: format
1890
const MsgFmt_Arg *args, // IN: message arguments
1891
int numArgs) // IN: number of arguments
1893
return MsgFmtSnprintfWork(&buf, size, format, args, numArgs);
1898
*-----------------------------------------------------------------------------
1900
* MsgFmt_Asprintf --
1902
* MsgFmt_Arg version of Str_Vasprintf().
1905
* Allocated string on success.
1907
* Length of returned string (not including null termination)
1908
* in *length (if length != NULL).
1913
*-----------------------------------------------------------------------------
1917
MsgFmt_Asprintf(size_t *length, // OUT: length of returned string
1918
const char *format, // IN: format
1919
const MsgFmt_Arg *args, // IN: message arguments
1920
int numArgs) // IN: number of arguments
1923
int n = MsgFmtSnprintfWork(&p, 0, format, args, numArgs);
1928
if (length != NULL) {
1935
MsgFmtSnprintfWork(char **outbuf, size_t bufSize, const char *fmt0,
1936
const MsgFmt_Arg *args, int numArgs)
1938
char *fmt; /* format string */
1939
int ch; /* character from fmt */
1940
int n; /* handy integer (short term usage) */
1941
char *cp; /* handy char pointer (short term usage) */
1942
BSDFmt_IOV *iovp; /* for PRINT macro */
1943
int flags; /* flags as above */
1944
int ret; /* return value accumulator */
1945
int width; /* width from format (%8d), or 0 */
1946
int prec; /* precision from format; <0 for N/A */
1947
char sign; /* sign prefix (' ', '+', '-', or \0) */
1948
char thousands_sep; /* locale specific thousands separator */
1949
const char *grouping; /* locale specific numeric grouping rules */
1951
#ifndef NO_FLOATING_POINT
1953
* We can decompose the printed representation of floating
1954
* point numbers into several parts, some of which may be empty:
1956
* [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
1959
* A: 'sign' holds this value if present; '\0' otherwise
1960
* B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
1961
* C: cp points to the string MMMNNN. Leading and trailing
1962
* zeros are not in the string and must be added.
1963
* D: expchar holds this character; '\0' if no exponent, e.g. %f
1964
* F: at least two digits for decimal, at least one digit for hex
1966
char *decimal_point; /* locale specific decimal point */
1967
#if defined __ANDROID__
1968
static const char dp = '.';
1970
int signflag; /* true if float is negative */
1971
union { /* floating point arguments %[aAeEfFgG] */
1975
int expt; /* integer value of exponent */
1976
char expchar; /* exponent character: [eEpP\0] */
1977
char *dtoaend; /* pointer to end of converted digits */
1978
int expsize; /* character count for expstr */
1979
int lead; /* sig figs before decimal or group sep */
1980
int ndig; /* actual number of digits returned by dtoa */
1981
char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
1982
char *dtoaresult; /* buffer allocated by dtoa */
1983
int nseps; /* number of group separators with ' */
1984
int nrepeats; /* number of repeats of the last group */
1986
uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
1987
int base; /* base for [diouxX] conversion */
1988
int dprec; /* a copy of prec if [diouxX], 0 otherwise */
1989
int realsz; /* field size expanded by dprec, sign, etc */
1990
int size; /* size of converted field or string */
1991
int prsize; /* max size of printed field */
1992
const char *xdigs; /* digits for %[xX] conversion */
1993
BSDFmt_UIO uio; /* output information: summary */
1994
BSDFmt_IOV iov[BSDFMT_NIOV]; /* ... and individual io vectors */
1995
char buf[INT_CONV_BUF];/* buffer with space for digits of uintmax_t */
1996
char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */
1997
int nextarg; /* 1-based argument index */
1998
const MsgFmt_Arg *a;
1999
char *convbuf; /* wide to multibyte conversion result */
2003
* BEWARE, these `goto error' on error, and PAD uses `n'.
2005
#define PRINT(ptr, len) { \
2006
iovp->iov_base = (ptr); \
2007
iovp->iov_len = (len); \
2008
uio.uio_resid += (len); \
2010
if (++uio.uio_iovcnt >= BSDFMT_NIOV) { \
2011
if (BSDFmt_SPrint(&sbuf, &uio)) \
2016
#define PAD(howmany, with) { \
2017
if ((n = (howmany)) > 0) { \
2018
while (n > PADSIZE) { \
2019
PRINT(with, PADSIZE); \
2025
#define PRINTANDPAD(p, ep, len, with) do { \
2026
int n2 = (ep) - (p); \
2031
PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
2034
if (uio.uio_resid && BSDFmt_SPrint(&sbuf, &uio)) \
2036
uio.uio_iovcnt = 0; \
2040
#define FETCHARG(a, i) do { \
2042
if (ii >= numArgs) { \
2043
sbuf.error = TRUE; \
2050
* Get * arguments, including the form *nn$.
2052
#define GETASTER(val) do { \
2055
const MsgFmt_Arg *a; \
2056
while (is_digit(*cp)) { \
2057
n2 = 10 * n2 + to_digit(*cp); \
2064
FETCHARG(a, nextarg++); \
2066
if (a->type != MSGFMT_ARG_INT32) { \
2067
sbuf.error = TRUE; \
2070
val = a->v.signed32; \
2073
xdigs = xdigs_lower;
2074
thousands_sep = '\0';
2077
#ifndef NO_FLOATING_POINT
2079
#if defined __ANDROID__
2081
* Struct lconv is not working! For decimal_point,
2082
* using '.' instead is a workaround.
2085
decimal_point = &dp;
2087
decimal_point = localeconv()->decimal_point;
2093
uio.uio_iov = iovp = iov;
2099
* Set up output string buffer structure.
2102
sbuf.alloc = *outbuf == NULL;
2105
sbuf.size = bufSize;
2109
* If asprintf(), allocate initial buffer based on format length.
2110
* Empty format only needs one byte.
2111
* Otherwise, round up to multiple of 64.
2115
size_t n = strlen(fmt0) + 1; // +1 for \0
2119
if ((sbuf.buf = malloc(n * sizeof (char))) == NULL) {
2127
#ifndef NO_FLOATING_POINT
2140
* Scan the format for conversions (`%' character).
2143
for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
2145
if ((n = fmt - cp) != 0) {
2146
if ((unsigned)ret + n > INT_MAX) {
2155
fmt++; /* skip over '%' */
2165
reswitch: switch (ch) {
2168
* ``If the space and + flags both appear, the space
2169
* flag will be ignored.''
2180
* ``A negative field width argument is taken as a
2181
* - flag followed by a positive field width.''
2183
* They don't exclude field widths read from args.
2198
#if defined __ANDROID__
2200
* Struct lconv is not working! The code below is a workaround.
2203
thousands_sep = ',';
2205
thousands_sep = *(localeconv()->thousands_sep);
2206
grouping = localeconv()->grouping;
2210
if ((ch = *fmt++) == '*') {
2215
while (is_digit(ch)) {
2216
prec = 10 * prec + to_digit(ch);
2222
* ``Note that 0 is taken as a flag, not as the
2223
* beginning of a field width.''
2228
case '1': case '2': case '3': case '4':
2229
case '5': case '6': case '7': case '8': case '9':
2232
n = 10 * n + to_digit(ch);
2234
} while (is_digit(ch));
2242
if (flags & SHORTINT) {
2252
/* could be I64 - long long int is 64bit */
2253
if (fmt[0] == '6' && fmt[1] == '4') {
2258
/* could be I32 - normal int is 32bit */
2259
if (fmt[0] == '3' && fmt[1] == '2') {
2261
/* flags |= normal integer - it is 32bit for all our targets */
2265
* I alone - use Microsoft's semantic as size_t modifier. We do
2266
* not support glibc's semantic to use alternative digits.
2271
if (flags & LONGINT) {
2279
flags |= LLONGINT; /* not necessarily */
2292
FETCHARG(a, nextarg++);
2293
if (a->type != MSGFMT_ARG_INT32) {
2297
if (flags & LONGINT) {
2298
static const mbstate_t initial;
2303
// XXX must deal with mismatch between wchar_t size
2304
mbseqlen = wcrtomb(cp = buf, (wchar_t)a->v.signed32, &mbs);
2305
if (mbseqlen == (size_t)-1) {
2309
size = (int)mbseqlen;
2311
*(cp = buf) = a->v.signed32;
2321
FETCHARG(a, nextarg++);
2322
if ((flags & (INTMAXT|LLONGINT)) != 0) {
2323
if (a->type == MSGFMT_ARG_INT64) {
2324
ujval = a->v.signed64;
2329
} else if ((flags & (SIZET|PTRDIFFT|LONGINT)) != 0) {
2330
if (a->type == MSGFMT_ARG_INT64) {
2331
ujval = a->v.signed64;
2332
} else if (a->type == MSGFMT_ARG_INT32) {
2333
ujval = (intmax_t) a->v.signed32;
2338
} else if ((flags & SHORTINT) != 0) {
2339
if (a->type == MSGFMT_ARG_INT32) {
2340
ujval = (intmax_t) (short) a->v.signed32;
2345
} else if ((flags & CHARINT) != 0) {
2346
if (a->type == MSGFMT_ARG_INT32) {
2347
ujval = (intmax_t) (signed char) a->v.signed32;
2353
if (a->type == MSGFMT_ARG_INT32) {
2354
ujval = (intmax_t) a->v.signed32;
2360
if ((intmax_t)ujval < 0) {
2366
#ifndef NO_FLOATING_POINT
2370
if (prec < 0) /* account for digit before decpt */
2381
expchar = ch - ('g' - 'e');
2385
if (flags & LLONGINT) {
2391
if (dtoaresult != NULL)
2392
freedtoa(dtoaresult);
2393
FETCHARG(a, nextarg++);
2394
if (a->type != MSGFMT_ARG_FLOAT64) {
2398
fparg.dbl = a->v.float64;
2400
dtoa(fparg.dbl, expchar ? 2 : 3, prec,
2401
&expt, &signflag, &dtoaend);
2406
if (expt == INT_MAX) { /* inf or nan */
2408
cp = (ch >= 'a') ? "nan" : "NAN";
2411
cp = (ch >= 'a') ? "inf" : "INF";
2416
ndig = dtoaend - cp;
2417
if (ch == 'g' || ch == 'G') {
2418
if (expt > -4 && expt <= prec) {
2419
/* Make %[gG] smell like %[fF] */
2429
* Make %[gG] smell like %[eE], but
2430
* trim trailing zeroes if no # flag.
2437
expsize = BSDFmt_Exponent(expstr, expt - 1, expchar);
2438
size = expsize + prec;
2439
if (prec > 1 || flags & ALT)
2442
/* space for digits before decimal point */
2447
/* space for decimal pt and following digits */
2448
if (prec || flags & ALT)
2450
if (grouping && expt > 0) {
2451
/* space for thousands' grouping */
2452
nseps = nrepeats = 0;
2454
while (*grouping != CHAR_MAX) {
2455
if (lead <= *grouping)
2458
if (*(grouping+1)) {
2464
size += nseps + nrepeats;
2469
#endif /* !NO_FLOATING_POINT */
2481
* ``The argument shall be a pointer to void. The
2482
* value of the pointer is converted to a sequence
2483
* of printable characters, in an implementation-
2487
FETCHARG(a, nextarg++);
2488
if (a->type == MSGFMT_ARG_PTR32) {
2489
ujval = a->v.unsigned32;
2490
} else if (a->type == MSGFMT_ARG_PTR64) {
2491
ujval = a->v.unsigned64;
2497
xdigs = xdigs_upper;
2498
flags = flags | INTMAXT;
2501
* VisualC sscanf doesn't grok '0x', so prefix zeroes.
2509
FETCHARG(a, nextarg++);
2510
if (flags & LONGINT) {
2512
#if defined __ANDROID__
2513
ASSERT_ON_COMPILE(sizeof (wchar_t) == sizeof (int16) ||
2514
sizeof (wchar_t) == sizeof (int32) ||
2515
sizeof (wchar_t) == sizeof (int8));
2516
if ((sizeof (wchar_t) == sizeof (int16) &&
2517
a->type != MSGFMT_ARG_STRING16) ||
2518
(sizeof (wchar_t) == sizeof (int32) &&
2519
a->type != MSGFMT_ARG_STRING32) ||
2520
(sizeof (wchar_t) == sizeof (int8) &&
2521
a->type != MSGFMT_ARG_STRING8)) {
2523
ASSERT_ON_COMPILE(sizeof (wchar_t) == 2 || sizeof (wchar_t) == 4);
2524
if (sizeof (wchar_t) == 2 ?
2525
a->type != MSGFMT_ARG_STRING16 :
2526
a->type != MSGFMT_ARG_STRING32) {
2531
if ((wcp = (wchar_t *) a->v.ptr) == NULL)
2534
if (convbuf != NULL)
2536
convbuf = BSDFmt_WCharToUTF8(wcp, prec);
2537
if (convbuf == NULL) {
2544
if (a->type != MSGFMT_ARG_STRING8 &&
2545
a->type != MSGFMT_ARG_ERRNO) {
2551
* Use localized string (in localString) if available.
2552
* Strip off Msg ID if unlocalized string has one.
2553
* Use (null) for null pointer.
2556
if (a->p.localString != NULL) {
2557
cp = a->p.localString;
2558
} else if (a->v.string8 != NULL) {
2559
cp = (char *) Msg_StripMSGID(a->v.string8char);
2566
* We can use strlen here because the string is always
2567
* terminated, unlike the string passed to MsgFmt_GetArgs.
2568
* However, it's somewhat faster to use memchr.
2570
char *p = memchr(cp, 0, prec);
2589
xdigs = xdigs_upper;
2592
xdigs = xdigs_lower;
2600
FETCHARG(a, nextarg++);
2601
if ((flags & (INTMAXT|LLONGINT)) != 0) {
2602
if (a->type == MSGFMT_ARG_INT64) {
2603
ujval = a->v.unsigned64;
2608
} else if ((flags & (SIZET|PTRDIFFT|LONGINT)) != 0) {
2609
if (a->type == MSGFMT_ARG_INT64) {
2610
ujval = a->v.unsigned64;
2611
} else if (a->type == MSGFMT_ARG_INT32) {
2612
ujval = (uintmax_t) a->v.unsigned32;
2617
} else if ((flags & SHORTINT) != 0) {
2618
if (a->type == MSGFMT_ARG_INT32) {
2619
ujval = (intmax_t) (unsigned short) a->v.unsigned32;
2624
} else if ((flags & CHARINT) != 0) {
2625
if (a->type == MSGFMT_ARG_INT32) {
2626
ujval = (intmax_t) (unsigned char) a->v.unsigned32;
2632
if (a->type == MSGFMT_ARG_INT32) {
2633
ujval = (intmax_t) a->v.unsigned32;
2639
if (ujval == 0) /* squash 0x/X if zero */
2642
/* unsigned conversions */
2646
* ``... diouXx conversions ... if a precision is
2647
* specified, the 0 flag will be ignored.''
2651
if ((dprec = prec) >= 0)
2655
* ``The result of converting a zero value with an
2656
* explicit precision of zero is no characters.''
2659
* ``The C Standard is clear enough as is. The call
2660
* printf("%#.0o", 0) should print 0.''
2661
* -- Defect Report #151
2663
cp = buf + INT_CONV_BUF;
2664
if (ujval != 0 || prec != 0 ||
2665
(flags & ALT && base == 8))
2666
cp = BSDFmt_UJToA(ujval, cp, base,
2668
flags & GROUPING, thousands_sep,
2670
size = buf + INT_CONV_BUF - cp;
2671
if (size > INT_CONV_BUF) /* should never happen */
2674
default: /* "%?" prints ?, unless ? is NUL */
2677
/* pretend it was %c with argument ch */
2686
* All reasonable formats wind up here. At this point, `cp'
2687
* points to a string which (if not flags&LADJUST) should be
2688
* padded out to `width' places. If flags&ZEROPAD, it should
2689
* first be prefixed by any sign or other prefix; otherwise,
2690
* it should be blank padded before the prefix is emitted.
2691
* After any left-hand padding and prefixing, emit zeroes
2692
* required by a decimal [diouxX] precision, then print the
2693
* string proper, then emit zeroes required by any leftover
2694
* floating precision; finally, if LADJUST, pad with blanks.
2696
* Compute actual size, so we know how much to pad.
2697
* size excludes decimal prec; realsz includes it.
2699
realsz = dprec > size ? dprec : size;
2705
prsize = width > realsz ? width : realsz;
2706
if ((unsigned)ret + prsize > INT_MAX) {
2711
/* right-adjusting blank padding */
2712
if ((flags & (LADJUST|ZEROPAD)) == 0)
2713
PAD(width - realsz, blanks);
2719
if (ox[1]) { /* ox[1] is either x, X, or \0 */
2724
/* right-adjusting zero padding */
2725
if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
2726
PAD(width - realsz, zeroes);
2728
/* leading zeroes from decimal precision */
2729
PAD(dprec - size, zeroes);
2731
/* the string or number proper */
2732
#ifndef NO_FLOATING_POINT
2733
if ((flags & FPT) == 0) {
2735
} else { /* glue together f_p fragments */
2736
if (!expchar) { /* %[fF] or sufficiently short %[gG] */
2739
if (prec || flags & ALT)
2740
PRINT(decimal_point, 1);
2742
/* already handled initial 0's */
2745
PRINTANDPAD(cp, dtoaend, lead, zeroes);
2748
while (nseps>0 || nrepeats>0) {
2755
PRINT(&thousands_sep,
2757
PRINTANDPAD(cp,dtoaend,
2764
if (prec || flags & ALT)
2765
PRINT(decimal_point,1);
2767
PRINTANDPAD(cp, dtoaend, prec, zeroes);
2768
} else { /* %[eE] or sufficiently long %[gG] */
2769
if (prec > 1 || flags & ALT) {
2771
buf[1] = *decimal_point;
2774
PAD(prec - ndig, zeroes);
2777
PRINT(expstr, expsize);
2783
/* left-adjusting padding (always blank) */
2784
if (flags & LADJUST)
2785
PAD(width - realsz, blanks);
2787
/* finally, adjust ret */
2790
FLUSH(); /* copy out the I/O vectors */
2796
* Always null terminate, unless buffer is size 0.
2799
ASSERT(!sbuf.error && ret >= 0);
2800
if (sbuf.size <= 0) {
2801
ASSERT(!sbuf.alloc);
2803
ASSERT(sbuf.index < sbuf.size);
2804
sbuf.buf[sbuf.index] = '\0';
2808
#ifndef NO_FLOATING_POINT
2809
if (dtoaresult != NULL)
2810
freedtoa(dtoaresult);
2812
if (convbuf != NULL)
2818
// return allocated buffer on success, free it on failure