// Helper function for `fprintf to unbuffered unix file': creates a // temporary buffer. We only work on write-only files; this avoids // worries about ungetc buffers and so forth. // // We prevent inlining because this massively increases the printf() // family's stack usage to support a rare case.
__attribute__((__noinline__)) staticint __sbprintf(FILE* fp, const CHAR_TYPE* fmt, va_list ap) {
FILE fake; struct __sfileext fakeext;
_FILEEXT_SETUP(&fake, &fakeext); /* copy the important variables */
fake._flags = fp->_flags & ~__SNBF;
fake._file = fp->_file;
fake._cookie = fp->_cookie;
fake._write = fp->_write;
/* set up the buffer */ unsignedchar buf[BUFSIZ] __attribute__((__uninitialized__));
fake._bf._base = fake._p = buf;
fake._bf._size = fake._w = sizeof(buf);
fake._lbfsize = 0; /* not actually used, but Just In Case */
/* do the work, then copy any error status */ int ret = FUNCTION_NAME(&fake, fmt, ap); if (ret >= 0 && __sflush(&fake)) ret = EOF; if (fake._flags & __SERR) fp->_flags |= __SERR; return ret;
}
// Append a digit to a value and check for overflow. #define APPEND_DIGIT(val, dig) \ do { \ if ((val) > INT_MAX / 10) goto overflow; \
(val) *= 10; \ if ((val) > INT_MAX - to_digit((dig))) goto overflow; \
(val) += to_digit((dig)); \
} while (0)
// Get * arguments, including the form *nn$. Preserve the nextarg // that the argument can be gotten once the type is determined. #define GETASTER(val) \
n2 = 0; \
cp = fmt; \ while (is_digit(*cp)) { \
APPEND_DIGIT(n2, *cp); \
cp++; \
} \ if (*cp == '$') { \ int hold = nextarg; \ if (argtable == NULL) { \
argtable = statargtable; \ if (__find_arguments(fmt0, orgap, &argtable, &argtablesiz) == -1) { \
ret = -1; \ goto error; \
} \
} \
nextarg = n2; \
val = GETARG(int); \
nextarg = hold; \
fmt = ++cp; \
} else { \
val = GETARG(int); \
}
// Get the argument indexed by nextarg. If the argument table is // built, use it to get the argument. If its not, get the next // argument (and arguments must be gotten sequentially). #define GETARG(type) \
((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : (nextarg++, va_arg(ap, type)))
/* *Findallargumentswhenapositionalparameterisencountered.Returnsa *table,indexedbyargumentnumber,ofpointerstoeacharguments.The *initialargumenttableshouldbeanarrayofSTATIC_ARG_TBL_SIZEentries. *Itwillbereplacedwithammap-edoneifitoverflows(malloccannotbe *usedsinceweareattemptingtomakesnprintfthreadsafe,andallocais *problematicsincewehavenestedfunctions..)
*/ staticint __find_arguments(const CHAR_TYPE* fmt0, va_list ap, union arg** argtable,
size_t* argtablesiz) { int ch; /* character from fmt */ int n, n2; /* handy integer (short term usage) */ int flags; /* flags as above */ unsignedchar* typetable; /* table of types */ unsignedchar stattypetable[STATIC_ARG_TBL_SIZE]; int tablesize; /* current size of type table */ int tablemax; /* largest used index in table */ int nextarg; /* 1-based argument index */ int ret = 0; /* return value */
struct helpers { // Flush out all the vectors defined by the given uio, // then reset it so that it can be reused. staticint sprint(FILE* fp, struct __suio* uio) { if (uio->uio_resid == 0) {
uio->uio_iovcnt = 0; return0;
} int result = __sfvwrite(fp, uio);
uio->uio_resid = 0;
uio->uio_iovcnt = 0; return result;
}
// Convert a wide character string argument for the %ls format to a multibyte // string representation. If not -1, prec specifies the maximum number of // bytes to output, and also means that we can't assume that the wide char // string is null-terminated. staticchar* wcsconv(wchar_t* wcsarg, int prec) {
mbstate_t mbs; char buf[MB_LEN_MAX]; wchar_t* p; char* convbuf;
size_t clen, nbytes;
// Allocate space for the maximum number of bytes we could output. if (prec < 0) {
memset(&mbs, 0, sizeof(mbs));
p = wcsarg;
nbytes = wcsrtombs(nullptr, (constwchar_t**)&p, 0, &mbs); if (nbytes == (size_t)-1) return nullptr;
} else { // Optimisation: if the output precision is small enough, // just allocate enough memory for the maximum instead of // scanning the string. if (prec < 128) {
nbytes = prec;
} else {
nbytes = 0;
p = wcsarg;
memset(&mbs, 0, sizeof(mbs)); for (;;) {
clen = wcrtomb(buf, *p++, &mbs); if (clen == 0 || clen == (size_t)-1 || nbytes + clen > (size_t)prec) break;
nbytes += clen;
} if (clen == (size_t)-1) return nullptr;
}
} if ((convbuf = static_cast<char*>(malloc(nbytes + 1))) == nullptr) return nullptr;
// Fill the output buffer.
p = wcsarg;
memset(&mbs, 0, sizeof(mbs)); if ((nbytes = wcsrtombs(convbuf, (constwchar_t**)&p, nbytes, &mbs)) == (size_t)-1) {
free(convbuf); return nullptr;
}
convbuf[nbytes] = '\0'; return convbuf;
}
// Like __fputwc_unlock, but handles fake string (__SSTR) files properly. // File must already be locked. static wint_t xfputwc(wchar_t wc, FILE* fp) { if ((fp->_flags & __SSTR) == 0) return __fputwc_unlock(wc, fp);
// Convert a multibyte character string argument for the %s format to a wide // string representation. ``prec'' specifies the maximum number of bytes // to output. If ``prec'' is greater than or equal to zero, we can't assume // that the multibyte character string ends in a null character. // // Returns NULL on failure. // To find out what happened check errno for ENOMEM, EILSEQ and EINVAL. staticwchar_t* mbsconv(constchar* mbsarg, int prec) {
mbstate_t mbs; constchar* p;
size_t insize, nchars, nconv;
if (mbsarg == nullptr) return nullptr;
// Supplied argument is a multibyte string; convert it to wide characters first. if (prec >= 0) { // String is not guaranteed to be NUL-terminated. Find the number of characters to print.
p = mbsarg;
insize = nchars = nconv = 0;
bzero(&mbs, sizeof(mbs)); while (nchars != (size_t)prec) {
nconv = mbrlen(p, MB_CUR_MAX, &mbs); if (nconv == (size_t)0 || nconv == (size_t)-1 || nconv == (size_t)-2) break;
p += nconv;
nchars++;
insize += nconv;
} if (nconv == (size_t)-1 || nconv == (size_t)-2) return (nullptr);
} else {
insize = strlen(mbsarg);
}
// Allocate buffer for the result and perform the conversion, // converting at most `size' bytes of the input multibyte string to // wide characters for printing. wchar_t* convbuf = static_cast<wchar_t*>(calloc(insize + 1, sizeof(*convbuf))); if (convbuf == nullptr) return nullptr; wchar_t* wcp = convbuf;
p = mbsarg;
bzero(&mbs, sizeof(mbs));
nconv = 0; while (insize != 0) {
nconv = mbrtowc(wcp, p, insize, &mbs); if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2) break;
wcp++;
p += nconv;
insize -= nconv;
} if (nconv == (size_t)-1 || nconv == (size_t)-2) {
free(convbuf); return nullptr;
}
*wcp = '\0';
return convbuf;
}
// Trasnlate a fixed size integer argument for the %w/%wf format to a // flag representation. Supported sizes are 8, 16, 32, and 64 so far. // See details in bionic/libc/include/stdint.h staticint w_to_flag(int size, bool fast) { static constexpr int fast_size = sizeof(void*) == 8 ? LLONGINT : 0; if (size == 8) return CHARINT; if (size == 16) return fast ? fast_size : SHORTINT; if (size == 32) return fast ? fast_size : 0; if (size == 64) return LLONGINT;
__fortify_fatal("%%w%s%d is unsupported", fast ? "f" : "", size);
}
};
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet am 2026-06-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.