aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/gallium/auxiliary
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/gallium/auxiliary')
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_atomic.h701
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_debug.c61
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_debug_refcnt.c26
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_dump.h352
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_dump_state.c103
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format.csv3
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format.h7
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format_etc.c104
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format_etc.h46
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format_pack.py2
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_format_table.py1
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_math.h68
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_snprintf.c2986
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_vbuf.c2
14 files changed, 2248 insertions, 2214 deletions
diff --git a/mesalib/src/gallium/auxiliary/util/u_atomic.h b/mesalib/src/gallium/auxiliary/util/u_atomic.h
index e8c0fdf75..2f2b42b34 100644
--- a/mesalib/src/gallium/auxiliary/util/u_atomic.h
+++ b/mesalib/src/gallium/auxiliary/util/u_atomic.h
@@ -1,352 +1,349 @@
-/**
- * Many similar implementations exist. See for example libwsbm
- * or the linux kernel include/atomic.h
- *
- * No copyright claimed on this file.
- *
- */
-
-#ifndef U_ATOMIC_H
-#define U_ATOMIC_H
-
-#include "pipe/p_compiler.h"
-#include "pipe/p_defines.h"
-
-/* Favor OS-provided implementations.
- *
- * Where no OS-provided implementation is available, fall back to
- * locally coded assembly, compiler intrinsic or ultimately a
- * mutex-based implementation.
- */
-#if (defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || \
- defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT))
-#define PIPE_ATOMIC_OS_UNLOCKED
-#elif defined(PIPE_OS_SOLARIS)
-#define PIPE_ATOMIC_OS_SOLARIS
-#elif defined(PIPE_CC_MSVC)
-#define PIPE_ATOMIC_MSVC_INTRINSIC
-#elif (defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86))
-#define PIPE_ATOMIC_ASM_MSVC_X86
-#elif (defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86))
-#define PIPE_ATOMIC_ASM_GCC_X86
-#elif (defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86_64))
-#define PIPE_ATOMIC_ASM_GCC_X86_64
-#elif defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 401)
-#define PIPE_ATOMIC_GCC_INTRINSIC
-#else
-#error "Unsupported platform"
-#endif
-
-
-#if defined(PIPE_ATOMIC_ASM_GCC_X86_64)
-#define PIPE_ATOMIC "GCC x86_64 assembly"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define p_atomic_set(_v, _i) (*(_v) = (_i))
-#define p_atomic_read(_v) (*(_v))
-
-static INLINE boolean
-p_atomic_dec_zero(int32_t *v)
-{
- unsigned char c;
-
- __asm__ __volatile__("lock; decl %0; sete %1":"+m"(*v), "=qm"(c)
- ::"memory");
-
- return c != 0;
-}
-
-static INLINE void
-p_atomic_inc(int32_t *v)
-{
- __asm__ __volatile__("lock; incl %0":"+m"(*v));
-}
-
-static INLINE void
-p_atomic_dec(int32_t *v)
-{
- __asm__ __volatile__("lock; decl %0":"+m"(*v));
-}
-
-static INLINE int32_t
-p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
-{
- return __sync_val_compare_and_swap(v, old, _new);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* PIPE_ATOMIC_ASM_GCC_X86_64 */
-
-
-#if defined(PIPE_ATOMIC_ASM_GCC_X86)
-
-#define PIPE_ATOMIC "GCC x86 assembly"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define p_atomic_set(_v, _i) (*(_v) = (_i))
-#define p_atomic_read(_v) (*(_v))
-
-static INLINE boolean
-p_atomic_dec_zero(int32_t *v)
-{
- unsigned char c;
-
- __asm__ __volatile__("lock; decl %0; sete %1":"+m"(*v), "=qm"(c)
- ::"memory");
-
- return c != 0;
-}
-
-static INLINE void
-p_atomic_inc(int32_t *v)
-{
- __asm__ __volatile__("lock; incl %0":"+m"(*v));
-}
-
-static INLINE void
-p_atomic_dec(int32_t *v)
-{
- __asm__ __volatile__("lock; decl %0":"+m"(*v));
-}
-
-static INLINE int32_t
-p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
-{
- return __sync_val_compare_and_swap(v, old, _new);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-
-
-/* Implementation using GCC-provided synchronization intrinsics
- */
-#if defined(PIPE_ATOMIC_GCC_INTRINSIC)
-
-#define PIPE_ATOMIC "GCC Sync Intrinsics"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define p_atomic_set(_v, _i) (*(_v) = (_i))
-#define p_atomic_read(_v) (*(_v))
-
-static INLINE boolean
-p_atomic_dec_zero(int32_t *v)
-{
- return (__sync_sub_and_fetch(v, 1) == 0);
-}
-
-static INLINE void
-p_atomic_inc(int32_t *v)
-{
- (void) __sync_add_and_fetch(v, 1);
-}
-
-static INLINE void
-p_atomic_dec(int32_t *v)
-{
- (void) __sync_sub_and_fetch(v, 1);
-}
-
-static INLINE int32_t
-p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
-{
- return __sync_val_compare_and_swap(v, old, _new);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-
-
-/* Unlocked version for single threaded environments, such as some
- * windows kernel modules.
- */
-#if defined(PIPE_ATOMIC_OS_UNLOCKED)
-
-#define PIPE_ATOMIC "Unlocked"
-
-#define p_atomic_set(_v, _i) (*(_v) = (_i))
-#define p_atomic_read(_v) (*(_v))
-#define p_atomic_dec_zero(_v) ((boolean) --(*(_v)))
-#define p_atomic_inc(_v) ((void) (*(_v))++)
-#define p_atomic_dec(_v) ((void) (*(_v))--)
-#define p_atomic_cmpxchg(_v, old, _new) (*(_v) == old ? *(_v) = (_new) : *(_v))
-
-#endif
-
-
-/* Locally coded assembly for MSVC on x86:
- */
-#if defined(PIPE_ATOMIC_ASM_MSVC_X86)
-
-#define PIPE_ATOMIC "MSVC x86 assembly"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define p_atomic_set(_v, _i) (*(_v) = (_i))
-#define p_atomic_read(_v) (*(_v))
-
-static INLINE boolean
-p_atomic_dec_zero(int32_t *v)
-{
- unsigned char c;
-
- __asm {
- mov eax, [v]
- lock dec dword ptr [eax]
- sete byte ptr [c]
- }
-
- return c != 0;
-}
-
-static INLINE void
-p_atomic_inc(int32_t *v)
-{
- __asm {
- mov eax, [v]
- lock inc dword ptr [eax]
- }
-}
-
-static INLINE void
-p_atomic_dec(int32_t *v)
-{
- __asm {
- mov eax, [v]
- lock dec dword ptr [eax]
- }
-}
-
-static INLINE int32_t
-p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
-{
- int32_t orig;
-
- __asm {
- mov ecx, [v]
- mov eax, [old]
- mov edx, [_new]
- lock cmpxchg [ecx], edx
- mov [orig], eax
- }
-
- return orig;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-
-#if defined(PIPE_ATOMIC_MSVC_INTRINSIC)
-
-#define PIPE_ATOMIC "MSVC Intrinsics"
-
-#include <intrin.h>
-
-#pragma intrinsic(_InterlockedIncrement)
-#pragma intrinsic(_InterlockedDecrement)
-#pragma intrinsic(_InterlockedCompareExchange)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define p_atomic_set(_v, _i) (*(_v) = (_i))
-#define p_atomic_read(_v) (*(_v))
-
-static INLINE boolean
-p_atomic_dec_zero(int32_t *v)
-{
- return _InterlockedDecrement((long *)v) == 0;
-}
-
-static INLINE void
-p_atomic_inc(int32_t *v)
-{
- _InterlockedIncrement((long *)v);
-}
-
-static INLINE void
-p_atomic_dec(int32_t *v)
-{
- _InterlockedDecrement((long *)v);
-}
-
-static INLINE int32_t
-p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
-{
- return _InterlockedCompareExchange((long *)v, _new, old);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-#if defined(PIPE_ATOMIC_OS_SOLARIS)
-
-#define PIPE_ATOMIC "Solaris OS atomic functions"
-
-#include <atomic.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define p_atomic_set(_v, _i) (*(_v) = (_i))
-#define p_atomic_read(_v) (*(_v))
-
-static INLINE boolean
-p_atomic_dec_zero(int32_t *v)
-{
- uint32_t n = atomic_dec_32_nv((uint32_t *) v);
-
- return n != 0;
-}
-
-#define p_atomic_inc(_v) atomic_inc_32((uint32_t *) _v)
-#define p_atomic_dec(_v) atomic_dec_32((uint32_t *) _v)
-
-#define p_atomic_cmpxchg(_v, _old, _new) \
- atomic_cas_32( (uint32_t *) _v, (uint32_t) _old, (uint32_t) _new)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-
-#ifndef PIPE_ATOMIC
-#error "No pipe_atomic implementation selected"
-#endif
-
-
-
-#endif /* U_ATOMIC_H */
+/**
+ * Many similar implementations exist. See for example libwsbm
+ * or the linux kernel include/atomic.h
+ *
+ * No copyright claimed on this file.
+ *
+ */
+
+#ifndef U_ATOMIC_H
+#define U_ATOMIC_H
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_defines.h"
+
+/* Favor OS-provided implementations.
+ *
+ * Where no OS-provided implementation is available, fall back to
+ * locally coded assembly, compiler intrinsic or ultimately a
+ * mutex-based implementation.
+ */
+#if defined(PIPE_OS_SOLARIS)
+#define PIPE_ATOMIC_OS_SOLARIS
+#elif defined(PIPE_CC_MSVC)
+#define PIPE_ATOMIC_MSVC_INTRINSIC
+#elif (defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86))
+#define PIPE_ATOMIC_ASM_MSVC_X86
+#elif (defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86))
+#define PIPE_ATOMIC_ASM_GCC_X86
+#elif (defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86_64))
+#define PIPE_ATOMIC_ASM_GCC_X86_64
+#elif defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 401)
+#define PIPE_ATOMIC_GCC_INTRINSIC
+#else
+#error "Unsupported platform"
+#endif
+
+
+#if defined(PIPE_ATOMIC_ASM_GCC_X86_64)
+#define PIPE_ATOMIC "GCC x86_64 assembly"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define p_atomic_set(_v, _i) (*(_v) = (_i))
+#define p_atomic_read(_v) (*(_v))
+
+static INLINE boolean
+p_atomic_dec_zero(int32_t *v)
+{
+ unsigned char c;
+
+ __asm__ __volatile__("lock; decl %0; sete %1":"+m"(*v), "=qm"(c)
+ ::"memory");
+
+ return c != 0;
+}
+
+static INLINE void
+p_atomic_inc(int32_t *v)
+{
+ __asm__ __volatile__("lock; incl %0":"+m"(*v));
+}
+
+static INLINE void
+p_atomic_dec(int32_t *v)
+{
+ __asm__ __volatile__("lock; decl %0":"+m"(*v));
+}
+
+static INLINE int32_t
+p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
+{
+ return __sync_val_compare_and_swap(v, old, _new);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PIPE_ATOMIC_ASM_GCC_X86_64 */
+
+
+#if defined(PIPE_ATOMIC_ASM_GCC_X86)
+
+#define PIPE_ATOMIC "GCC x86 assembly"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define p_atomic_set(_v, _i) (*(_v) = (_i))
+#define p_atomic_read(_v) (*(_v))
+
+static INLINE boolean
+p_atomic_dec_zero(int32_t *v)
+{
+ unsigned char c;
+
+ __asm__ __volatile__("lock; decl %0; sete %1":"+m"(*v), "=qm"(c)
+ ::"memory");
+
+ return c != 0;
+}
+
+static INLINE void
+p_atomic_inc(int32_t *v)
+{
+ __asm__ __volatile__("lock; incl %0":"+m"(*v));
+}
+
+static INLINE void
+p_atomic_dec(int32_t *v)
+{
+ __asm__ __volatile__("lock; decl %0":"+m"(*v));
+}
+
+static INLINE int32_t
+p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
+{
+ return __sync_val_compare_and_swap(v, old, _new);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
+/* Implementation using GCC-provided synchronization intrinsics
+ */
+#if defined(PIPE_ATOMIC_GCC_INTRINSIC)
+
+#define PIPE_ATOMIC "GCC Sync Intrinsics"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define p_atomic_set(_v, _i) (*(_v) = (_i))
+#define p_atomic_read(_v) (*(_v))
+
+static INLINE boolean
+p_atomic_dec_zero(int32_t *v)
+{
+ return (__sync_sub_and_fetch(v, 1) == 0);
+}
+
+static INLINE void
+p_atomic_inc(int32_t *v)
+{
+ (void) __sync_add_and_fetch(v, 1);
+}
+
+static INLINE void
+p_atomic_dec(int32_t *v)
+{
+ (void) __sync_sub_and_fetch(v, 1);
+}
+
+static INLINE int32_t
+p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
+{
+ return __sync_val_compare_and_swap(v, old, _new);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
+/* Unlocked version for single threaded environments, such as some
+ * windows kernel modules.
+ */
+#if defined(PIPE_ATOMIC_OS_UNLOCKED)
+
+#define PIPE_ATOMIC "Unlocked"
+
+#define p_atomic_set(_v, _i) (*(_v) = (_i))
+#define p_atomic_read(_v) (*(_v))
+#define p_atomic_dec_zero(_v) ((boolean) --(*(_v)))
+#define p_atomic_inc(_v) ((void) (*(_v))++)
+#define p_atomic_dec(_v) ((void) (*(_v))--)
+#define p_atomic_cmpxchg(_v, old, _new) (*(_v) == old ? *(_v) = (_new) : *(_v))
+
+#endif
+
+
+/* Locally coded assembly for MSVC on x86:
+ */
+#if defined(PIPE_ATOMIC_ASM_MSVC_X86)
+
+#define PIPE_ATOMIC "MSVC x86 assembly"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define p_atomic_set(_v, _i) (*(_v) = (_i))
+#define p_atomic_read(_v) (*(_v))
+
+static INLINE boolean
+p_atomic_dec_zero(int32_t *v)
+{
+ unsigned char c;
+
+ __asm {
+ mov eax, [v]
+ lock dec dword ptr [eax]
+ sete byte ptr [c]
+ }
+
+ return c != 0;
+}
+
+static INLINE void
+p_atomic_inc(int32_t *v)
+{
+ __asm {
+ mov eax, [v]
+ lock inc dword ptr [eax]
+ }
+}
+
+static INLINE void
+p_atomic_dec(int32_t *v)
+{
+ __asm {
+ mov eax, [v]
+ lock dec dword ptr [eax]
+ }
+}
+
+static INLINE int32_t
+p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
+{
+ int32_t orig;
+
+ __asm {
+ mov ecx, [v]
+ mov eax, [old]
+ mov edx, [_new]
+ lock cmpxchg [ecx], edx
+ mov [orig], eax
+ }
+
+ return orig;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+#if defined(PIPE_ATOMIC_MSVC_INTRINSIC)
+
+#define PIPE_ATOMIC "MSVC Intrinsics"
+
+#include <intrin.h>
+
+#pragma intrinsic(_InterlockedIncrement)
+#pragma intrinsic(_InterlockedDecrement)
+#pragma intrinsic(_InterlockedCompareExchange)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define p_atomic_set(_v, _i) (*(_v) = (_i))
+#define p_atomic_read(_v) (*(_v))
+
+static INLINE boolean
+p_atomic_dec_zero(int32_t *v)
+{
+ return _InterlockedDecrement((long *)v) == 0;
+}
+
+static INLINE void
+p_atomic_inc(int32_t *v)
+{
+ _InterlockedIncrement((long *)v);
+}
+
+static INLINE void
+p_atomic_dec(int32_t *v)
+{
+ _InterlockedDecrement((long *)v);
+}
+
+static INLINE int32_t
+p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
+{
+ return _InterlockedCompareExchange((long *)v, _new, old);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#if defined(PIPE_ATOMIC_OS_SOLARIS)
+
+#define PIPE_ATOMIC "Solaris OS atomic functions"
+
+#include <atomic.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define p_atomic_set(_v, _i) (*(_v) = (_i))
+#define p_atomic_read(_v) (*(_v))
+
+static INLINE boolean
+p_atomic_dec_zero(int32_t *v)
+{
+ uint32_t n = atomic_dec_32_nv((uint32_t *) v);
+
+ return n != 0;
+}
+
+#define p_atomic_inc(_v) atomic_inc_32((uint32_t *) _v)
+#define p_atomic_dec(_v) atomic_dec_32((uint32_t *) _v)
+
+#define p_atomic_cmpxchg(_v, _old, _new) \
+ atomic_cas_32( (uint32_t *) _v, (uint32_t) _old, (uint32_t) _new)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+#ifndef PIPE_ATOMIC
+#error "No pipe_atomic implementation selected"
+#endif
+
+
+
+#endif /* U_ATOMIC_H */
diff --git a/mesalib/src/gallium/auxiliary/util/u_debug.c b/mesalib/src/gallium/auxiliary/util/u_debug.c
index 2d6193039..df1d8e68c 100644
--- a/mesalib/src/gallium/auxiliary/util/u_debug.c
+++ b/mesalib/src/gallium/auxiliary/util/u_debug.c
@@ -30,7 +30,6 @@
#include "pipe/p_config.h"
#include "pipe/p_compiler.h"
-#include "os/os_stream.h"
#include "util/u_debug.h"
#include "pipe/p_format.h"
#include "pipe/p_state.h"
@@ -43,6 +42,7 @@
#include "util/u_prim.h"
#include "util/u_surface.h"
+#include <stdio.h>
#include <limits.h> /* CHAR_BIT */
#include <ctype.h> /* isalnum */
@@ -274,11 +274,7 @@ void _debug_assert_fail(const char *expr,
const char *function)
{
_debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr);
-#if defined(PIPE_OS_WINDOWS) && !defined(PIPE_SUBSYSTEM_WINDOWS_USER)
- if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", FALSE))
-#else
if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", TRUE))
-#endif
os_abort();
else
_debug_printf("continuing...\n");
@@ -453,42 +449,6 @@ void debug_dump_image(const char *prefix,
unsigned stride,
const void *data)
{
-#ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
- static unsigned no = 0;
- char filename[256];
- WCHAR wfilename[sizeof(filename)];
- ULONG_PTR iFile = 0;
- struct {
- unsigned format;
- unsigned cpp;
- unsigned width;
- unsigned height;
- } header;
- unsigned char *pMap = NULL;
- unsigned i;
-
- util_snprintf(filename, sizeof(filename), "\\??\\c:\\%03u%s.raw", ++no, prefix);
- for(i = 0; i < sizeof(filename); ++i)
- wfilename[i] = (WCHAR)filename[i];
-
- pMap = (unsigned char *)EngMapFile(wfilename, sizeof(header) + height*width*cpp, &iFile);
- if(!pMap)
- return;
-
- header.format = format;
- header.cpp = cpp;
- header.width = width;
- header.height = height;
- memcpy(pMap, &header, sizeof(header));
- pMap += sizeof(header);
-
- for(i = 0; i < height; ++i) {
- memcpy(pMap, (unsigned char *)data + stride*i, cpp*width);
- pMap += cpp*width;
- }
-
- EngUnmapFile(iFile);
-#elif defined(PIPE_OS_UNIX)
/* write a ppm file */
char filename[256];
FILE *f;
@@ -534,7 +494,6 @@ void debug_dump_image(const char *prefix,
else {
fprintf(stderr, "Can't open %s for writing\n", filename);
}
-#endif
}
/* FIXME: dump resources, not surfaces... */
@@ -636,7 +595,6 @@ debug_dump_surface_bmp(struct pipe_context *pipe,
const char *filename,
struct pipe_surface *surface)
{
-#ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
struct pipe_transfer *transfer;
struct pipe_resource *texture = surface->texture;
@@ -647,7 +605,6 @@ debug_dump_surface_bmp(struct pipe_context *pipe,
debug_dump_transfer_bmp(pipe, filename, transfer);
pipe->transfer_destroy(pipe, transfer);
-#endif
}
void
@@ -655,7 +612,6 @@ debug_dump_transfer_bmp(struct pipe_context *pipe,
const char *filename,
struct pipe_transfer *transfer)
{
-#ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
float *rgba;
if (!transfer)
@@ -679,7 +635,6 @@ debug_dump_transfer_bmp(struct pipe_context *pipe,
FREE(rgba);
error1:
;
-#endif
}
void
@@ -687,8 +642,7 @@ debug_dump_float_rgba_bmp(const char *filename,
unsigned width, unsigned height,
float *rgba, unsigned stride)
{
-#ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT
- struct os_stream *stream;
+ FILE *stream;
struct bmp_file_header bmfh;
struct bmp_info_header bmih;
unsigned x, y;
@@ -714,12 +668,12 @@ debug_dump_float_rgba_bmp(const char *filename,
bmih.biClrUsed = 0;
bmih.biClrImportant = 0;
- stream = os_file_stream_create(filename);
+ stream = fopen(filename, "wb");
if(!stream)
goto error1;
- os_stream_write(stream, &bmfh, 14);
- os_stream_write(stream, &bmih, 40);
+ fwrite(&bmfh, 14, 1, stream);
+ fwrite(&bmih, 40, 1, stream);
y = height;
while(y--) {
@@ -731,14 +685,13 @@ debug_dump_float_rgba_bmp(const char *filename,
pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]);
pixel.rgbBlue = float_to_ubyte(ptr[x*4 + 2]);
pixel.rgbAlpha = float_to_ubyte(ptr[x*4 + 3]);
- os_stream_write(stream, &pixel, 4);
+ fwrite(&pixel, 1, 4, stream);
}
}
- os_stream_close(stream);
+ fclose(stream);
error1:
;
-#endif
}
#endif
diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_refcnt.c b/mesalib/src/gallium/auxiliary/util/u_debug_refcnt.c
index b3e389408..a51b4c55f 100644
--- a/mesalib/src/gallium/auxiliary/util/u_debug_refcnt.c
+++ b/mesalib/src/gallium/auxiliary/util/u_debug_refcnt.c
@@ -24,11 +24,14 @@
*
**************************************************************************/
-#if defined(DEBUG) && (!defined(PIPE_OS_WINDOWS) || defined(PIPE_SUBSYSTEM_WINDOWS_USER))
+#if defined(DEBUG)
/* see http://www.mozilla.org/performance/refcnt-balancer.html for what do with the output
* on Linux, use tools/addr2line.sh to postprocess it before anything else
**/
+
+#include <stdio.h>
+
#include "util/u_debug.h"
#include "util/u_debug_refcnt.h"
#include "util/u_debug_stack.h"
@@ -36,11 +39,10 @@
#include "util/u_string.h"
#include "util/u_hash_table.h"
#include "os/os_thread.h"
-#include "os/os_stream.h"
int debug_refcnt_state;
-struct os_stream* stream;
+FILE* stream;
/* TODO: maybe move this serial machinery to a stand-alone module and expose it? */
pipe_static_mutex(serials_mutex);
@@ -115,9 +117,9 @@ static void dump_stack(const char* symbols[STACK_LEN])
for(i = 0; i < STACK_LEN; ++i)
{
if(symbols[i])
- os_stream_printf(stream, "%s\n", symbols[i]);
+ fprintf(stream, "%s\n", symbols[i]);
}
- os_stream_write(stream, "\n", 1);
+ fprintf(stream, "\n");
}
void debug_reference_slowpath(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change)
@@ -129,7 +131,7 @@ void debug_reference_slowpath(const struct pipe_reference* p, debug_reference_de
{
const char* filename = debug_get_option("GALLIUM_REFCNT_LOG", NULL);
if(filename && filename[0])
- stream = os_file_stream_create(filename);
+ stream = fopen(filename, "wt");
if(stream)
debug_refcnt_state = 1;
@@ -161,31 +163,33 @@ void debug_reference_slowpath(const struct pipe_reference* p, debug_reference_de
if(!existing)
{
- os_stream_printf(stream, "<%s> %p %u Create\n", buf, p, serial);
+ fprintf(stream, "<%s> %p %u Create\n", buf, (void *) p, serial);
dump_stack(symbols);
/* this is there to provide a gradual change even if we don't see the initialization */
for(i = 1; i <= refcnt - change; ++i)
{
- os_stream_printf(stream, "<%s> %p %u AddRef %u\n", buf, p, serial, i);
+ fprintf(stream, "<%s> %p %u AddRef %u\n", buf, (void *) p,
+ serial, i);
dump_stack(symbols);
}
}
if(change)
{
- os_stream_printf(stream, "<%s> %p %u %s %u\n", buf, p, serial, change > 0 ? "AddRef" : "Release", refcnt);
+ fprintf(stream, "<%s> %p %u %s %u\n", buf, (void *) p, serial,
+ change > 0 ? "AddRef" : "Release", refcnt);
dump_stack(symbols);
}
if(!refcnt)
{
debug_serial_delete((void*)p);
- os_stream_printf(stream, "<%s> %p %u Destroy\n", buf, p, serial);
+ fprintf(stream, "<%s> %p %u Destroy\n", buf, (void *) p, serial);
dump_stack(symbols);
}
- os_stream_flush(stream);
+ fflush(stream);
}
}
#endif
diff --git a/mesalib/src/gallium/auxiliary/util/u_dump.h b/mesalib/src/gallium/auxiliary/util/u_dump.h
index 7d89db163..3890b3bdd 100644
--- a/mesalib/src/gallium/auxiliary/util/u_dump.h
+++ b/mesalib/src/gallium/auxiliary/util/u_dump.h
@@ -1,179 +1,173 @@
-/**************************************************************************
- *
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-/**
- * @file
- * Dump data in human/machine readable format.
- *
- * @author Jose Fonseca <jfonseca@vmware.com>
- */
-
-#ifndef U_DEBUG_DUMP_H_
-#define U_DEBUG_DUMP_H_
-
-
-#include "pipe/p_compiler.h"
-#include "pipe/p_state.h"
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#define UTIL_DUMP_INVALID_NAME "<invalid>"
-
-
-struct os_stream;
-
-
-/* Duplicated here for convenience */
-extern struct os_stream *
-os_log_stream;
-
-
-/*
- * p_defines.h
- *
- * XXX: These functions don't really dump anything -- just translate into
- * strings so a verb better than "dump" should be used instead, in order to
- * free up the namespace to the true dumper functions.
- */
-
-const char *
-util_dump_blend_factor(unsigned value, boolean shortened);
-
-const char *
-util_dump_blend_func(unsigned value, boolean shortened);
-
-const char *
-util_dump_logicop(unsigned value, boolean shortened);
-
-const char *
-util_dump_func(unsigned value, boolean shortened);
-
-const char *
-util_dump_stencil_op(unsigned value, boolean shortened);
-
-const char *
-util_dump_tex_target(unsigned value, boolean shortened);
-
-const char *
-util_dump_tex_wrap(unsigned value, boolean shortened);
-
-const char *
-util_dump_tex_mipfilter(unsigned value, boolean shortened);
-
-const char *
-util_dump_tex_filter(unsigned value, boolean shortened);
-
-
-/*
- * p_state.h, through an os_stream
- */
-
-void
-util_dump_template(struct os_stream *stream,
- const struct pipe_resource *templat);
-
-void
-util_dump_rasterizer_state(struct os_stream *stream,
- const struct pipe_rasterizer_state *state);
-
-void
-util_dump_poly_stipple(struct os_stream *stream,
- const struct pipe_poly_stipple *state);
-
-void
-util_dump_viewport_state(struct os_stream *stream,
- const struct pipe_viewport_state *state);
-
-void
-util_dump_scissor_state(struct os_stream *stream,
- const struct pipe_scissor_state *state);
-
-void
-util_dump_clip_state(struct os_stream *stream,
- const struct pipe_clip_state *state);
-
-void
-util_dump_shader_state(struct os_stream *stream,
- const struct pipe_shader_state *state);
-
-void
-util_dump_depth_stencil_alpha_state(struct os_stream *stream,
- const struct pipe_depth_stencil_alpha_state *state);
-
-void
-util_dump_rt_blend_state(struct os_stream *stream,
- const struct pipe_rt_blend_state *state);
-
-void
-util_dump_blend_state(struct os_stream *stream,
- const struct pipe_blend_state *state);
-
-void
-util_dump_blend_color(struct os_stream *stream,
- const struct pipe_blend_color *state);
-
-void
-util_dump_stencil_ref(struct os_stream *stream,
- const struct pipe_stencil_ref *state);
-
-void
-util_dump_framebuffer_state(struct os_stream *stream,
- const struct pipe_framebuffer_state *state);
-
-void
-util_dump_sampler_state(struct os_stream *stream,
- const struct pipe_sampler_state *state);
-
-void
-util_dump_surface(struct os_stream *stream,
- const struct pipe_surface *state);
-
-void
-util_dump_transfer(struct os_stream *stream,
- const struct pipe_transfer *state);
-
-void
-util_dump_vertex_buffer(struct os_stream *stream,
- const struct pipe_vertex_buffer *state);
-
-void
-util_dump_vertex_element(struct os_stream *stream,
- const struct pipe_vertex_element *state);
-
-
-/* FIXME: Move the other debug_dump_xxx functions out of u_debug.h into here. */
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* U_DEBUG_H_ */
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * @file
+ * Dump data in human/machine readable format.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+#ifndef U_DEBUG_DUMP_H_
+#define U_DEBUG_DUMP_H_
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_state.h"
+
+#include <stdio.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define UTIL_DUMP_INVALID_NAME "<invalid>"
+
+
+/*
+ * p_defines.h
+ *
+ * XXX: These functions don't really dump anything -- just translate into
+ * strings so a verb better than "dump" should be used instead, in order to
+ * free up the namespace to the true dumper functions.
+ */
+
+const char *
+util_dump_blend_factor(unsigned value, boolean shortened);
+
+const char *
+util_dump_blend_func(unsigned value, boolean shortened);
+
+const char *
+util_dump_logicop(unsigned value, boolean shortened);
+
+const char *
+util_dump_func(unsigned value, boolean shortened);
+
+const char *
+util_dump_stencil_op(unsigned value, boolean shortened);
+
+const char *
+util_dump_tex_target(unsigned value, boolean shortened);
+
+const char *
+util_dump_tex_wrap(unsigned value, boolean shortened);
+
+const char *
+util_dump_tex_mipfilter(unsigned value, boolean shortened);
+
+const char *
+util_dump_tex_filter(unsigned value, boolean shortened);
+
+
+/*
+ * p_state.h, through a FILE
+ */
+
+void
+util_dump_template(FILE *stream,
+ const struct pipe_resource *templat);
+
+void
+util_dump_rasterizer_state(FILE *stream,
+ const struct pipe_rasterizer_state *state);
+
+void
+util_dump_poly_stipple(FILE *stream,
+ const struct pipe_poly_stipple *state);
+
+void
+util_dump_viewport_state(FILE *stream,
+ const struct pipe_viewport_state *state);
+
+void
+util_dump_scissor_state(FILE *stream,
+ const struct pipe_scissor_state *state);
+
+void
+util_dump_clip_state(FILE *stream,
+ const struct pipe_clip_state *state);
+
+void
+util_dump_shader_state(FILE *stream,
+ const struct pipe_shader_state *state);
+
+void
+util_dump_depth_stencil_alpha_state(FILE *stream,
+ const struct pipe_depth_stencil_alpha_state *state);
+
+void
+util_dump_rt_blend_state(FILE *stream,
+ const struct pipe_rt_blend_state *state);
+
+void
+util_dump_blend_state(FILE *stream,
+ const struct pipe_blend_state *state);
+
+void
+util_dump_blend_color(FILE *stream,
+ const struct pipe_blend_color *state);
+
+void
+util_dump_stencil_ref(FILE *stream,
+ const struct pipe_stencil_ref *state);
+
+void
+util_dump_framebuffer_state(FILE *stream,
+ const struct pipe_framebuffer_state *state);
+
+void
+util_dump_sampler_state(FILE *stream,
+ const struct pipe_sampler_state *state);
+
+void
+util_dump_surface(FILE *stream,
+ const struct pipe_surface *state);
+
+void
+util_dump_transfer(FILE *stream,
+ const struct pipe_transfer *state);
+
+void
+util_dump_vertex_buffer(FILE *stream,
+ const struct pipe_vertex_buffer *state);
+
+void
+util_dump_vertex_element(FILE *stream,
+ const struct pipe_vertex_element *state);
+
+
+/* FIXME: Move the other debug_dump_xxx functions out of u_debug.h into here. */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_DEBUG_H_ */
diff --git a/mesalib/src/gallium/auxiliary/util/u_dump_state.c b/mesalib/src/gallium/auxiliary/util/u_dump_state.c
index 8a7ec5848..917d7cd35 100644
--- a/mesalib/src/gallium/auxiliary/util/u_dump_state.c
+++ b/mesalib/src/gallium/auxiliary/util/u_dump_state.c
@@ -27,7 +27,6 @@
#include "pipe/p_compiler.h"
-#include "os/os_stream.h"
#include "util/u_memory.h"
#include "util/u_string.h"
#include "util/u_format.h"
@@ -41,7 +40,7 @@
*/
static INLINE void
-util_stream_writef(struct os_stream *stream, const char *format, ...)
+util_stream_writef(FILE *stream, const char *format, ...)
{
static char buf[1024];
unsigned len;
@@ -49,102 +48,102 @@ util_stream_writef(struct os_stream *stream, const char *format, ...)
va_start(ap, format);
len = util_vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
- os_stream_write(stream, buf, len);
+ fwrite(buf, len, 1, stream);
}
static void
-util_dump_bool(struct os_stream *stream, int value)
+util_dump_bool(FILE *stream, int value)
{
util_stream_writef(stream, "%c", value ? '1' : '0');
}
static void
-util_dump_int(struct os_stream *stream, long long int value)
+util_dump_int(FILE *stream, long long int value)
{
util_stream_writef(stream, "%lli", value);
}
static void
-util_dump_uint(struct os_stream *stream, long long unsigned value)
+util_dump_uint(FILE *stream, long long unsigned value)
{
util_stream_writef(stream, "%llu", value);
}
static void
-util_dump_float(struct os_stream *stream, double value)
+util_dump_float(FILE *stream, double value)
{
util_stream_writef(stream, "%g", value);
}
static void
-util_dump_string(struct os_stream *stream, const char *str)
+util_dump_string(FILE *stream, const char *str)
{
- os_stream_write_str(stream, "\"");
- os_stream_write_str(stream, str);
- os_stream_write_str(stream, "\"");
+ fputs("\"", stream);
+ fputs(str, stream);
+ fputs("\"", stream);
}
static void
-util_dump_enum(struct os_stream *stream, const char *value)
+util_dump_enum(FILE *stream, const char *value)
{
- os_stream_write_str(stream, value);
+ fputs(value, stream);
}
static void
-util_dump_array_begin(struct os_stream *stream)
+util_dump_array_begin(FILE *stream)
{
- os_stream_write_str(stream, "{");
+ fputs("{", stream);
}
static void
-util_dump_array_end(struct os_stream *stream)
+util_dump_array_end(FILE *stream)
{
- os_stream_write_str(stream, "}");
+ fputs("}", stream);
}
static void
-util_dump_elem_begin(struct os_stream *stream)
+util_dump_elem_begin(FILE *stream)
{
}
static void
-util_dump_elem_end(struct os_stream *stream)
+util_dump_elem_end(FILE *stream)
{
- os_stream_write_str(stream, ", ");
+ fputs(", ", stream);
}
static void
-util_dump_struct_begin(struct os_stream *stream, const char *name)
+util_dump_struct_begin(FILE *stream, const char *name)
{
- os_stream_write_str(stream, "{");
+ fputs("{", stream);
}
static void
-util_dump_struct_end(struct os_stream *stream)
+util_dump_struct_end(FILE *stream)
{
- os_stream_write_str(stream, "}");
+ fputs("}", stream);
}
static void
-util_dump_member_begin(struct os_stream *stream, const char *name)
+util_dump_member_begin(FILE *stream, const char *name)
{
util_stream_writef(stream, "%s = ", name);
}
static void
-util_dump_member_end(struct os_stream *stream)
+util_dump_member_end(FILE *stream)
{
- os_stream_write_str(stream, ", ");
+ fputs(", ", stream);
}
static void
-util_dump_null(struct os_stream *stream)
+util_dump_null(FILE *stream)
{
- os_stream_write_str(stream, "NULL");
+ fputs("NULL", stream);
}
static void
-util_dump_ptr(struct os_stream *stream, const void *value)
+util_dump_ptr(FILE *stream, const void *value)
{
if(value)
util_stream_writef(stream, "0x%08lx", (unsigned long)(uintptr_t)value);
@@ -224,26 +223,26 @@ util_dump_ptr(struct os_stream *stream, const void *value)
static void
-util_dump_format(struct os_stream *stream, enum pipe_format format)
+util_dump_format(FILE *stream, enum pipe_format format)
{
util_dump_enum(stream, util_format_name(format));
}
static void
-util_dump_enum_blend_factor(struct os_stream *stream, unsigned value)
+util_dump_enum_blend_factor(FILE *stream, unsigned value)
{
util_dump_enum(stream, util_dump_blend_factor(value, TRUE));
}
static void
-util_dump_enum_blend_func(struct os_stream *stream, unsigned value)
+util_dump_enum_blend_func(FILE *stream, unsigned value)
{
util_dump_enum(stream, util_dump_blend_func(value, TRUE));
}
static void
-util_dump_enum_func(struct os_stream *stream, unsigned value)
+util_dump_enum_func(FILE *stream, unsigned value)
{
util_dump_enum(stream, util_dump_func(value, TRUE));
}
@@ -255,7 +254,7 @@ util_dump_enum_func(struct os_stream *stream, unsigned value)
void
-util_dump_template(struct os_stream *stream, const struct pipe_resource *templat)
+util_dump_template(FILE *stream, const struct pipe_resource *templat)
{
if(!templat) {
util_dump_null(stream);
@@ -293,7 +292,7 @@ util_dump_template(struct os_stream *stream, const struct pipe_resource *templat
void
-util_dump_rasterizer_state(struct os_stream *stream, const struct pipe_rasterizer_state *state)
+util_dump_rasterizer_state(FILE *stream, const struct pipe_rasterizer_state *state)
{
if(!state) {
util_dump_null(stream);
@@ -339,7 +338,7 @@ util_dump_rasterizer_state(struct os_stream *stream, const struct pipe_rasterize
void
-util_dump_poly_stipple(struct os_stream *stream, const struct pipe_poly_stipple *state)
+util_dump_poly_stipple(FILE *stream, const struct pipe_poly_stipple *state)
{
if(!state) {
util_dump_null(stream);
@@ -357,7 +356,7 @@ util_dump_poly_stipple(struct os_stream *stream, const struct pipe_poly_stipple
void
-util_dump_viewport_state(struct os_stream *stream, const struct pipe_viewport_state *state)
+util_dump_viewport_state(FILE *stream, const struct pipe_viewport_state *state)
{
if(!state) {
util_dump_null(stream);
@@ -374,7 +373,7 @@ util_dump_viewport_state(struct os_stream *stream, const struct pipe_viewport_st
void
-util_dump_scissor_state(struct os_stream *stream, const struct pipe_scissor_state *state)
+util_dump_scissor_state(FILE *stream, const struct pipe_scissor_state *state)
{
if(!state) {
util_dump_null(stream);
@@ -393,7 +392,7 @@ util_dump_scissor_state(struct os_stream *stream, const struct pipe_scissor_stat
void
-util_dump_clip_state(struct os_stream *stream, const struct pipe_clip_state *state)
+util_dump_clip_state(FILE *stream, const struct pipe_clip_state *state)
{
unsigned i;
@@ -421,7 +420,7 @@ util_dump_clip_state(struct os_stream *stream, const struct pipe_clip_state *sta
void
-util_dump_shader_state(struct os_stream *stream, const struct pipe_shader_state *state)
+util_dump_shader_state(FILE *stream, const struct pipe_shader_state *state)
{
char str[8192];
@@ -443,7 +442,7 @@ util_dump_shader_state(struct os_stream *stream, const struct pipe_shader_state
void
-util_dump_depth_stencil_alpha_state(struct os_stream *stream, const struct pipe_depth_stencil_alpha_state *state)
+util_dump_depth_stencil_alpha_state(FILE *stream, const struct pipe_depth_stencil_alpha_state *state)
{
unsigned i;
@@ -498,7 +497,7 @@ util_dump_depth_stencil_alpha_state(struct os_stream *stream, const struct pipe_
}
void
-util_dump_rt_blend_state(struct os_stream *stream, const struct pipe_rt_blend_state *state)
+util_dump_rt_blend_state(FILE *stream, const struct pipe_rt_blend_state *state)
{
util_dump_struct_begin(stream, "pipe_rt_blend_state");
@@ -519,7 +518,7 @@ util_dump_rt_blend_state(struct os_stream *stream, const struct pipe_rt_blend_st
}
void
-util_dump_blend_state(struct os_stream *stream, const struct pipe_blend_state *state)
+util_dump_blend_state(FILE *stream, const struct pipe_blend_state *state)
{
unsigned valid_entries = 1;
@@ -551,7 +550,7 @@ util_dump_blend_state(struct os_stream *stream, const struct pipe_blend_state *s
void
-util_dump_blend_color(struct os_stream *stream, const struct pipe_blend_color *state)
+util_dump_blend_color(FILE *stream, const struct pipe_blend_color *state)
{
if(!state) {
util_dump_null(stream);
@@ -566,7 +565,7 @@ util_dump_blend_color(struct os_stream *stream, const struct pipe_blend_color *s
}
void
-util_dump_stencil_ref(struct os_stream *stream, const struct pipe_stencil_ref *state)
+util_dump_stencil_ref(FILE *stream, const struct pipe_stencil_ref *state)
{
if(!state) {
util_dump_null(stream);
@@ -581,7 +580,7 @@ util_dump_stencil_ref(struct os_stream *stream, const struct pipe_stencil_ref *s
}
void
-util_dump_framebuffer_state(struct os_stream *stream, const struct pipe_framebuffer_state *state)
+util_dump_framebuffer_state(FILE *stream, const struct pipe_framebuffer_state *state)
{
util_dump_struct_begin(stream, "pipe_framebuffer_state");
@@ -596,7 +595,7 @@ util_dump_framebuffer_state(struct os_stream *stream, const struct pipe_framebuf
void
-util_dump_sampler_state(struct os_stream *stream, const struct pipe_sampler_state *state)
+util_dump_sampler_state(FILE *stream, const struct pipe_sampler_state *state)
{
if(!state) {
util_dump_null(stream);
@@ -625,7 +624,7 @@ util_dump_sampler_state(struct os_stream *stream, const struct pipe_sampler_stat
void
-util_dump_surface(struct os_stream *stream, const struct pipe_surface *state)
+util_dump_surface(FILE *stream, const struct pipe_surface *state)
{
if(!state) {
util_dump_null(stream);
@@ -650,7 +649,7 @@ util_dump_surface(struct os_stream *stream, const struct pipe_surface *state)
void
-util_dump_transfer(struct os_stream *stream, const struct pipe_transfer *state)
+util_dump_transfer(FILE *stream, const struct pipe_transfer *state)
{
if(!state) {
util_dump_null(stream);
@@ -672,7 +671,7 @@ util_dump_transfer(struct os_stream *stream, const struct pipe_transfer *state)
void
-util_dump_vertex_buffer(struct os_stream *stream, const struct pipe_vertex_buffer *state)
+util_dump_vertex_buffer(FILE *stream, const struct pipe_vertex_buffer *state)
{
if(!state) {
util_dump_null(stream);
@@ -690,7 +689,7 @@ util_dump_vertex_buffer(struct os_stream *stream, const struct pipe_vertex_buffe
void
-util_dump_vertex_element(struct os_stream *stream, const struct pipe_vertex_element *state)
+util_dump_vertex_element(FILE *stream, const struct pipe_vertex_element *state)
{
if(!state) {
util_dump_null(stream);
diff --git a/mesalib/src/gallium/auxiliary/util/u_format.csv b/mesalib/src/gallium/auxiliary/util/u_format.csv
index 4b6fc7536..345cc9d47 100644
--- a/mesalib/src/gallium/auxiliary/util/u_format.csv
+++ b/mesalib/src/gallium/auxiliary/util/u_format.csv
@@ -158,6 +158,7 @@ PIPE_FORMAT_R8G8Bx_SNORM , other, 1, 1, sn8 , sn8 , , , x
# - http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt
# - http://www.opengl.org/registry/specs/ARB/texture_compression_rgtc.txt
# - http://www.opengl.org/registry/specs/EXT/texture_compression_latc.txt
+# - http://www.khronos.org/registry/gles/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt
# - http://msdn.microsoft.com/en-us/library/bb694531.aspx
PIPE_FORMAT_DXT1_RGB , s3tc, 4, 4, x64 , , , , xyz1, rgb
PIPE_FORMAT_DXT1_RGBA , s3tc, 4, 4, x64 , , , , xyzw, rgb
@@ -178,6 +179,8 @@ PIPE_FORMAT_LATC1_SNORM , rgtc, 4, 4, x64, , , , xxx1, rg
PIPE_FORMAT_LATC2_UNORM , rgtc, 4, 4, x128, , , , xxxy, rgb
PIPE_FORMAT_LATC2_SNORM , rgtc, 4, 4, x128, , , , xxxy, rgb
+PIPE_FORMAT_ETC1_RGB8 , etc, 4, 4, x64, , , , xyz1, rgb
+
# Straightforward D3D10-like formats (also used for
# vertex buffer element description)
#
diff --git a/mesalib/src/gallium/auxiliary/util/u_format.h b/mesalib/src/gallium/auxiliary/util/u_format.h
index 99ee6767e..9694c9034 100644
--- a/mesalib/src/gallium/auxiliary/util/u_format.h
+++ b/mesalib/src/gallium/auxiliary/util/u_format.h
@@ -70,9 +70,14 @@ enum util_format_layout {
UTIL_FORMAT_LAYOUT_RGTC = 5,
/**
+ * Ericsson Texture Compression
+ */
+ UTIL_FORMAT_LAYOUT_ETC = 6,
+
+ /**
* Everything else that doesn't fit in any of the above layouts.
*/
- UTIL_FORMAT_LAYOUT_OTHER = 6
+ UTIL_FORMAT_LAYOUT_OTHER = 7
};
diff --git a/mesalib/src/gallium/auxiliary/util/u_format_etc.c b/mesalib/src/gallium/auxiliary/util/u_format_etc.c
new file mode 100644
index 000000000..7500e1ed6
--- /dev/null
+++ b/mesalib/src/gallium/auxiliary/util/u_format_etc.c
@@ -0,0 +1,104 @@
+#include "pipe/p_compiler.h"
+#include "util/u_debug.h"
+#include "util/u_math.h"
+#include "u_format_etc.h"
+
+/* define etc1_parse_block and etc. */
+#define UINT8_TYPE uint8_t
+#define TAG(x) x
+#include "../../../mesa/main/texcompress_etc_tmp.h"
+#undef TAG
+#undef UINT8_TYPE
+
+void
+util_format_etc1_rgb8_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
+{
+ const unsigned bw = 4, bh = 4, bs = 8, comps = 4;
+ struct etc1_block block;
+ unsigned x, y, i, j;
+
+ for (y = 0; y < height; y += bh) {
+ const uint8_t *src = src_row;
+
+ for (x = 0; x < width; x+= bw) {
+ etc1_parse_block(&block, src);
+
+ for (j = 0; j < bh; j++) {
+ uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
+ for (i = 0; i < bw; i++) {
+ etc1_fetch_texel(&block, i, j, dst);
+ dst[3] = 255;
+ dst += comps;
+ }
+ }
+
+ src += bs;
+ }
+
+ src_row += src_stride;
+ }
+}
+
+void
+util_format_etc1_rgb8_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
+{
+ assert(0);
+}
+
+void
+util_format_etc1_rgb8_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
+{
+ const unsigned bw = 4, bh = 4, bs = 8, comps = 4;
+ struct etc1_block block;
+ unsigned x, y, i, j;
+
+ for (y = 0; y < height; y += bh) {
+ const uint8_t *src = src_row;
+
+ for (x = 0; x < width; x+= bw) {
+ etc1_parse_block(&block, src);
+
+ for (j = 0; j < bh; j++) {
+ float *dst = dst_row + (y + j) * dst_stride / sizeof(*dst_row) + x * comps;
+ uint8_t tmp[3];
+
+ for (i = 0; i < bw; i++) {
+ etc1_fetch_texel(&block, i, j, tmp);
+ dst[0] = ubyte_to_float(tmp[0]);
+ dst[1] = ubyte_to_float(tmp[1]);
+ dst[2] = ubyte_to_float(tmp[2]);
+ dst[3] = 1.0f;
+ dst += comps;
+ }
+ }
+
+ src += bs;
+ }
+
+ src_row += src_stride;
+ }
+}
+
+void
+util_format_etc1_rgb8_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
+{
+ assert(0);
+}
+
+void
+util_format_etc1_rgb8_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
+{
+ const unsigned bw = 4, bh = 4;
+ struct etc1_block block;
+ uint8_t tmp[3];
+
+ assert(i < bw && j < bh);
+
+ etc1_parse_block(&block, src);
+ etc1_fetch_texel(&block, i, j, tmp);
+
+ dst[0] = ubyte_to_float(tmp[0]);
+ dst[1] = ubyte_to_float(tmp[1]);
+ dst[2] = ubyte_to_float(tmp[2]);
+ dst[3] = 1.0f;
+}
diff --git a/mesalib/src/gallium/auxiliary/util/u_format_etc.h b/mesalib/src/gallium/auxiliary/util/u_format_etc.h
new file mode 100644
index 000000000..30c3dcb92
--- /dev/null
+++ b/mesalib/src/gallium/auxiliary/util/u_format_etc.h
@@ -0,0 +1,46 @@
+/**************************************************************************
+ *
+ * Copyright 2011 LunarG, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ **************************************************************************/
+
+#ifndef U_FORMAT_ETC1_H_
+#define U_FORMAT_ETC1_H_
+
+void
+util_format_etc1_rgb8_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
+
+void
+util_format_etc1_rgb8_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
+
+void
+util_format_etc1_rgb8_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
+
+void
+util_format_etc1_rgb8_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
+
+void
+util_format_etc1_rgb8_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
+
+#endif /* U_FORMAT_ETC1_H_ */
diff --git a/mesalib/src/gallium/auxiliary/util/u_format_pack.py b/mesalib/src/gallium/auxiliary/util/u_format_pack.py
index 14a504944..fff409fb7 100644
--- a/mesalib/src/gallium/auxiliary/util/u_format_pack.py
+++ b/mesalib/src/gallium/auxiliary/util/u_format_pack.py
@@ -658,7 +658,7 @@ def generate_format_fetch(format, dst_channel, dst_native_type, dst_suffix):
def is_format_hand_written(format):
- return format.layout in ('s3tc', 'rgtc', 'subsampled', 'other') or format.colorspace == ZS
+ return format.layout in ('s3tc', 'rgtc', 'etc', 'subsampled', 'other') or format.colorspace == ZS
def generate(formats):
diff --git a/mesalib/src/gallium/auxiliary/util/u_format_table.py b/mesalib/src/gallium/auxiliary/util/u_format_table.py
index 703d99959..07beb3872 100644
--- a/mesalib/src/gallium/auxiliary/util/u_format_table.py
+++ b/mesalib/src/gallium/auxiliary/util/u_format_table.py
@@ -89,6 +89,7 @@ def write_format_table(formats):
print '#include "u_format_s3tc.h"'
print '#include "u_format_rgtc.h"'
print '#include "u_format_latc.h"'
+ print '#include "u_format_etc.h"'
print
u_format_pack.generate(formats)
diff --git a/mesalib/src/gallium/auxiliary/util/u_math.h b/mesalib/src/gallium/auxiliary/util/u_math.h
index 551463f75..f908341f6 100644
--- a/mesalib/src/gallium/auxiliary/util/u_math.h
+++ b/mesalib/src/gallium/auxiliary/util/u_math.h
@@ -48,74 +48,8 @@ extern "C" {
#endif
-#if defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
-__inline double ceil(double val)
-{
- double ceil_val;
-
- if ((val - (long) val) == 0) {
- ceil_val = val;
- }
- else {
- if (val > 0) {
- ceil_val = (long) val + 1;
- }
- else {
- ceil_val = (long) val;
- }
- }
-
- return ceil_val;
-}
-
-#ifndef PIPE_SUBSYSTEM_WINDOWS_CE_OGL
-__inline double floor(double val)
-{
- double floor_val;
-
- if ((val - (long) val) == 0) {
- floor_val = val;
- }
- else {
- if (val > 0) {
- floor_val = (long) val;
- }
- else {
- floor_val = (long) val - 1;
- }
- }
-
- return floor_val;
-}
-#endif
-
-#pragma function(pow)
-__inline double __cdecl pow(double val, double exponent)
-{
- /* XXX */
- assert(0);
- return 0;
-}
-
-#pragma function(log)
-__inline double __cdecl log(double val)
-{
- /* XXX */
- assert(0);
- return 0;
-}
-
-#pragma function(atan2)
-__inline double __cdecl atan2(double val)
-{
- /* XXX */
- assert(0);
- return 0;
-}
-#else
#include <math.h>
#include <stdarg.h>
-#endif
#ifndef M_SQRT2
@@ -125,7 +59,7 @@ __inline double __cdecl atan2(double val)
#if defined(_MSC_VER)
-#if _MSC_VER < 1400 && !defined(__cplusplus) || defined(PIPE_SUBSYSTEM_WINDOWS_CE)
+#if _MSC_VER < 1400 && !defined(__cplusplus)
static INLINE float cosf( float f )
{
diff --git a/mesalib/src/gallium/auxiliary/util/u_snprintf.c b/mesalib/src/gallium/auxiliary/util/u_snprintf.c
index a601df4e5..f0d53b3ce 100644
--- a/mesalib/src/gallium/auxiliary/util/u_snprintf.c
+++ b/mesalib/src/gallium/auxiliary/util/u_snprintf.c
@@ -1,1497 +1,1489 @@
-/*
- * Copyright (c) 1995 Patrick Powell.
- *
- * This code is based on code written by Patrick Powell <papowell@astart.com>.
- * It may be used for any purpose as long as this notice remains intact on all
- * source code distributions.
- */
-
-/*
- * Copyright (c) 2008 Holger Weiss.
- *
- * This version of the code is maintained by Holger Weiss <holger@jhweiss.de>.
- * My changes to the code may freely be used, modified and/or redistributed for
- * any purpose. It would be nice if additions and fixes to this file (including
- * trivial code cleanups) would be sent back in order to let me include them in
- * the version available at <http://www.jhweiss.de/software/snprintf.html>.
- * However, this is not a requirement for using or redistributing (possibly
- * modified) versions of this file, nor is leaving this notice intact mandatory.
- */
-
-/*
- * History
- *
- * 2008-01-20 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.1:
- *
- * Fixed the detection of infinite floating point values on IRIX (and
- * possibly other systems) and applied another few minor cleanups.
- *
- * 2008-01-06 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.0:
- *
- * Added a lot of new features, fixed many bugs, and incorporated various
- * improvements done by Andrew Tridgell <tridge@samba.org>, Russ Allbery
- * <rra@stanford.edu>, Hrvoje Niksic <hniksic@xemacs.org>, Damien Miller
- * <djm@mindrot.org>, and others for the Samba, INN, Wget, and OpenSSH
- * projects. The additions include: support the "e", "E", "g", "G", and
- * "F" conversion specifiers (and use conversion style "f" or "F" for the
- * still unsupported "a" and "A" specifiers); support the "hh", "ll", "j",
- * "t", and "z" length modifiers; support the "#" flag and the (non-C99)
- * "'" flag; use localeconv(3) (if available) to get both the current
- * locale's decimal point character and the separator between groups of
- * digits; fix the handling of various corner cases of field width and
- * precision specifications; fix various floating point conversion bugs;
- * handle infinite and NaN floating point values; don't attempt to write to
- * the output buffer (which may be NULL) if a size of zero was specified;
- * check for integer overflow of the field width, precision, and return
- * values and during the floating point conversion; use the OUTCHAR() macro
- * instead of a function for better performance; provide asprintf(3) and
- * vasprintf(3) functions; add new test cases. The replacement functions
- * have been renamed to use an "rpl_" prefix, the function calls in the
- * main project (and in this file) must be redefined accordingly for each
- * replacement function which is needed (by using Autoconf or other means).
- * Various other minor improvements have been applied and the coding style
- * was cleaned up for consistency.
- *
- * 2007-07-23 Holger Weiss <holger@jhweiss.de> for Mutt 1.5.13:
- *
- * C99 compliant snprintf(3) and vsnprintf(3) functions return the number
- * of characters that would have been written to a sufficiently sized
- * buffer (excluding the '\0'). The original code simply returned the
- * length of the resulting output string, so that's been fixed.
- *
- * 1998-03-05 Michael Elkins <me@mutt.org> for Mutt 0.90.8:
- *
- * The original code assumed that both snprintf(3) and vsnprintf(3) were
- * missing. Some systems only have snprintf(3) but not vsnprintf(3), so
- * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
- *
- * 1998-01-27 Thomas Roessler <roessler@does-not-exist.org> for Mutt 0.89i:
- *
- * The PGP code was using unsigned hexadecimal formats. Unfortunately,
- * unsigned formats simply didn't work.
- *
- * 1997-10-22 Brandon Long <blong@fiction.net> for Mutt 0.87.1:
- *
- * Ok, added some minimal floating point support, which means this probably
- * requires libm on most operating systems. Don't yet support the exponent
- * (e,E) and sigfig (g,G). Also, fmtint() was pretty badly broken, it just
- * wasn't being exercised in ways which showed it, so that's been fixed.
- * Also, formatted the code to Mutt conventions, and removed dead code left
- * over from the original. Also, there is now a builtin-test, run with:
- * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf
- *
- * 2996-09-15 Brandon Long <blong@fiction.net> for Mutt 0.43:
- *
- * This was ugly. It is still ugly. I opted out of floating point
- * numbers, but the formatter understands just about everything from the
- * normal C string format, at least as far as I can tell from the Solaris
- * 2.5 printf(3S) man page.
- */
-
-/*
- * ToDo
- *
- * - Add wide character support.
- * - Add support for "%a" and "%A" conversions.
- * - Create test routines which predefine the expected results. Our test cases
- * usually expose bugs in system implementations rather than in ours :-)
- */
-
-/*
- * Usage
- *
- * 1) The following preprocessor macros should be defined to 1 if the feature or
- * file in question is available on the target system (by using Autoconf or
- * other means), though basic functionality should be available as long as
- * HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly:
- *
- * HAVE_VSNPRINTF
- * HAVE_SNPRINTF
- * HAVE_VASPRINTF
- * HAVE_ASPRINTF
- * HAVE_STDARG_H
- * HAVE_STDDEF_H
- * HAVE_STDINT_H
- * HAVE_STDLIB_H
- * HAVE_INTTYPES_H
- * HAVE_LOCALE_H
- * HAVE_LOCALECONV
- * HAVE_LCONV_DECIMAL_POINT
- * HAVE_LCONV_THOUSANDS_SEP
- * HAVE_LONG_DOUBLE
- * HAVE_LONG_LONG_INT
- * HAVE_UNSIGNED_LONG_LONG_INT
- * HAVE_INTMAX_T
- * HAVE_UINTMAX_T
- * HAVE_UINTPTR_T
- * HAVE_PTRDIFF_T
- * HAVE_VA_COPY
- * HAVE___VA_COPY
- *
- * 2) The calls to the functions which should be replaced must be redefined
- * throughout the project files (by using Autoconf or other means):
- *
- * #define vsnprintf rpl_vsnprintf
- * #define snprintf rpl_snprintf
- * #define vasprintf rpl_vasprintf
- * #define asprintf rpl_asprintf
- *
- * 3) The required replacement functions should be declared in some header file
- * included throughout the project files:
- *
- * #if HAVE_CONFIG_H
- * #include <config.h>
- * #endif
- * #if HAVE_STDARG_H
- * #include <stdarg.h>
- * #if !HAVE_VSNPRINTF
- * int rpl_vsnprintf(char *, size_t, const char *, va_list);
- * #endif
- * #if !HAVE_SNPRINTF
- * int rpl_snprintf(char *, size_t, const char *, ...);
- * #endif
- * #if !HAVE_VASPRINTF
- * int rpl_vasprintf(char **, const char *, va_list);
- * #endif
- * #if !HAVE_ASPRINTF
- * int rpl_asprintf(char **, const char *, ...);
- * #endif
- * #endif
- *
- * Autoconf macros for handling step 1 and step 2 are available at
- * <http://www.jhweiss.de/software/snprintf.html>.
- */
-
-#include "pipe/p_config.h"
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#else
-#ifdef WIN32
-#define vsnprintf util_vsnprintf
-#define snprintf util_snprintf
-#define HAVE_VSNPRINTF 0
-#define HAVE_SNPRINTF 0
-#define HAVE_VASPRINTF 1 /* not needed */
-#define HAVE_ASPRINTF 1 /* not needed */
-#define HAVE_STDARG_H 1
-#define HAVE_STDDEF_H 1
-#define HAVE_STDINT_H 0
-#define HAVE_STDLIB_H 1
-#define HAVE_INTTYPES_H 0
-#define HAVE_LOCALE_H 0
-#define HAVE_LOCALECONV 0
-#define HAVE_LCONV_DECIMAL_POINT 0
-#define HAVE_LCONV_THOUSANDS_SEP 0
-#define HAVE_LONG_DOUBLE 0
-#define HAVE_LONG_LONG_INT 1
-#define HAVE_UNSIGNED_LONG_LONG_INT 1
-#define HAVE_INTMAX_T 0
-#define HAVE_UINTMAX_T 0
-#define HAVE_UINTPTR_T 1
-#define HAVE_PTRDIFF_T 1
-#define HAVE_VA_COPY 0
-#define HAVE___VA_COPY 0
-#else
-#define HAVE_VSNPRINTF 1
-#define HAVE_SNPRINTF 1
-#define HAVE_VASPRINTF 1
-#define HAVE_ASPRINTF 1
-#endif
-#endif /* HAVE_CONFIG_H */
-
-#if !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || !HAVE_VASPRINTF
-#include <stdio.h> /* For NULL, size_t, vsnprintf(3), and vasprintf(3). */
-#ifdef VA_START
-#undef VA_START
-#endif /* defined(VA_START) */
-#ifdef VA_SHIFT
-#undef VA_SHIFT
-#endif /* defined(VA_SHIFT) */
-#if HAVE_STDARG_H
-#include <stdarg.h>
-#define VA_START(ap, last) va_start(ap, last)
-#define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */
-#else /* Assume <varargs.h> is available. */
-#include <varargs.h>
-#define VA_START(ap, last) va_start(ap) /* "last" is ignored. */
-#define VA_SHIFT(ap, value, type) value = va_arg(ap, type)
-#endif /* HAVE_STDARG_H */
-
-#if !HAVE_VASPRINTF
-#if HAVE_STDLIB_H
-#include <stdlib.h> /* For malloc(3). */
-#endif /* HAVE_STDLIB_H */
-#ifdef VA_COPY
-#undef VA_COPY
-#endif /* defined(VA_COPY) */
-#ifdef VA_END_COPY
-#undef VA_END_COPY
-#endif /* defined(VA_END_COPY) */
-#if HAVE_VA_COPY
-#define VA_COPY(dest, src) va_copy(dest, src)
-#define VA_END_COPY(ap) va_end(ap)
-#elif HAVE___VA_COPY
-#define VA_COPY(dest, src) __va_copy(dest, src)
-#define VA_END_COPY(ap) va_end(ap)
-#else
-#define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list))
-#define VA_END_COPY(ap) /* No-op. */
-#define NEED_MYMEMCPY 1
-static void *mymemcpy(void *, void *, size_t);
-#endif /* HAVE_VA_COPY */
-#endif /* !HAVE_VASPRINTF */
-
-#if !HAVE_VSNPRINTF
-#include <limits.h> /* For *_MAX. */
-#if HAVE_INTTYPES_H
-#include <inttypes.h> /* For intmax_t (if not defined in <stdint.h>). */
-#endif /* HAVE_INTTYPES_H */
-#if HAVE_LOCALE_H
-#include <locale.h> /* For localeconv(3). */
-#endif /* HAVE_LOCALE_H */
-#if HAVE_STDDEF_H
-#include <stddef.h> /* For ptrdiff_t. */
-#endif /* HAVE_STDDEF_H */
-#if HAVE_STDINT_H
-#include <stdint.h> /* For intmax_t. */
-#endif /* HAVE_STDINT_H */
-
-/* Support for unsigned long long int. We may also need ULLONG_MAX. */
-#ifndef ULONG_MAX /* We may need ULONG_MAX as a fallback. */
-#ifdef UINT_MAX
-#define ULONG_MAX UINT_MAX
-#else
-#define ULONG_MAX INT_MAX
-#endif /* defined(UINT_MAX) */
-#endif /* !defined(ULONG_MAX) */
-#ifdef ULLONG
-#undef ULLONG
-#endif /* defined(ULLONG) */
-#if HAVE_UNSIGNED_LONG_LONG_INT
-#define ULLONG unsigned long long int
-#ifndef ULLONG_MAX
-#define ULLONG_MAX ULONG_MAX
-#endif /* !defined(ULLONG_MAX) */
-#else
-#define ULLONG unsigned long int
-#ifdef ULLONG_MAX
-#undef ULLONG_MAX
-#endif /* defined(ULLONG_MAX) */
-#define ULLONG_MAX ULONG_MAX
-#endif /* HAVE_LONG_LONG_INT */
-
-/* Support for uintmax_t. We also need UINTMAX_MAX. */
-#ifdef UINTMAX_T
-#undef UINTMAX_T
-#endif /* defined(UINTMAX_T) */
-#if HAVE_UINTMAX_T || defined(uintmax_t)
-#define UINTMAX_T uintmax_t
-#ifndef UINTMAX_MAX
-#define UINTMAX_MAX ULLONG_MAX
-#endif /* !defined(UINTMAX_MAX) */
-#else
-#define UINTMAX_T ULLONG
-#ifdef UINTMAX_MAX
-#undef UINTMAX_MAX
-#endif /* defined(UINTMAX_MAX) */
-#define UINTMAX_MAX ULLONG_MAX
-#endif /* HAVE_UINTMAX_T || defined(uintmax_t) */
-
-/* Support for long double. */
-#ifndef LDOUBLE
-#if HAVE_LONG_DOUBLE
-#define LDOUBLE long double
-#else
-#define LDOUBLE double
-#endif /* HAVE_LONG_DOUBLE */
-#endif /* !defined(LDOUBLE) */
-
-/* Support for long long int. */
-#ifndef LLONG
-#if HAVE_LONG_LONG_INT
-#define LLONG long long int
-#else
-#define LLONG long int
-#endif /* HAVE_LONG_LONG_INT */
-#endif /* !defined(LLONG) */
-
-/* Support for intmax_t. */
-#ifndef INTMAX_T
-#if HAVE_INTMAX_T || defined(intmax_t)
-#define INTMAX_T intmax_t
-#else
-#define INTMAX_T LLONG
-#endif /* HAVE_INTMAX_T || defined(intmax_t) */
-#endif /* !defined(INTMAX_T) */
-
-/* Support for uintptr_t. */
-#ifndef UINTPTR_T
-#if HAVE_UINTPTR_T || defined(uintptr_t)
-#define UINTPTR_T uintptr_t
-#else
-#define UINTPTR_T unsigned long int
-#endif /* HAVE_UINTPTR_T || defined(uintptr_t) */
-#endif /* !defined(UINTPTR_T) */
-
-/* WinCE5.0 does not have uintptr_t defined */
-#if (_WIN32_WCE < 600)
-#ifdef UINTPTR_T
-#undef UINTPTR_T
-#endif
-#define UINTPTR_T unsigned long int
-#endif
-
-
-/* Support for ptrdiff_t. */
-#ifndef PTRDIFF_T
-#if HAVE_PTRDIFF_T || defined(ptrdiff_t)
-#define PTRDIFF_T ptrdiff_t
-#else
-#define PTRDIFF_T long int
-#endif /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */
-#endif /* !defined(PTRDIFF_T) */
-
-/*
- * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99:
- * 7.19.6.1, 7). However, we'll simply use PTRDIFF_T and convert it to an
- * unsigned type if necessary. This should work just fine in practice.
- */
-#ifndef UPTRDIFF_T
-#define UPTRDIFF_T PTRDIFF_T
-#endif /* !defined(UPTRDIFF_T) */
-
-/*
- * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7).
- * However, we'll simply use size_t and convert it to a signed type if
- * necessary. This should work just fine in practice.
- */
-#ifndef SSIZE_T
-#define SSIZE_T size_t
-#endif /* !defined(SSIZE_T) */
-
-/* Either ERANGE or E2BIG should be available everywhere. */
-#ifndef ERANGE
-#define ERANGE E2BIG
-#endif /* !defined(ERANGE) */
-#ifndef EOVERFLOW
-#define EOVERFLOW ERANGE
-#endif /* !defined(EOVERFLOW) */
-
-/*
- * Buffer size to hold the octal string representation of UINT128_MAX without
- * nul-termination ("3777777777777777777777777777777777777777777").
- */
-#ifdef MAX_CONVERT_LENGTH
-#undef MAX_CONVERT_LENGTH
-#endif /* defined(MAX_CONVERT_LENGTH) */
-#define MAX_CONVERT_LENGTH 43
-
-/* Format read states. */
-#define PRINT_S_DEFAULT 0
-#define PRINT_S_FLAGS 1
-#define PRINT_S_WIDTH 2
-#define PRINT_S_DOT 3
-#define PRINT_S_PRECISION 4
-#define PRINT_S_MOD 5
-#define PRINT_S_CONV 6
-
-/* Format flags. */
-#define PRINT_F_MINUS (1 << 0)
-#define PRINT_F_PLUS (1 << 1)
-#define PRINT_F_SPACE (1 << 2)
-#define PRINT_F_NUM (1 << 3)
-#define PRINT_F_ZERO (1 << 4)
-#define PRINT_F_QUOTE (1 << 5)
-#define PRINT_F_UP (1 << 6)
-#define PRINT_F_UNSIGNED (1 << 7)
-#define PRINT_F_TYPE_G (1 << 8)
-#define PRINT_F_TYPE_E (1 << 9)
-
-/* Conversion flags. */
-#define PRINT_C_CHAR 1
-#define PRINT_C_SHORT 2
-#define PRINT_C_LONG 3
-#define PRINT_C_LLONG 4
-#define PRINT_C_LDOUBLE 5
-#define PRINT_C_SIZE 6
-#define PRINT_C_PTRDIFF 7
-#define PRINT_C_INTMAX 8
-
-#ifndef MAX
-#define MAX(x, y) ((x >= y) ? x : y)
-#endif /* !defined(MAX) */
-#ifndef CHARTOINT
-#define CHARTOINT(ch) (ch - '0')
-#endif /* !defined(CHARTOINT) */
-#ifndef ISDIGIT
-#define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9')
-#endif /* !defined(ISDIGIT) */
-#ifndef ISNAN
-#define ISNAN(x) (x != x)
-#endif /* !defined(ISNAN) */
-#ifndef ISINF
-#define ISINF(x) (x != 0.0 && x + x == x)
-#endif /* !defined(ISINF) */
-
-#ifdef OUTCHAR
-#undef OUTCHAR
-#endif /* defined(OUTCHAR) */
-#define OUTCHAR(str, len, size, ch) \
-do { \
- if (len + 1 < size) \
- str[len] = ch; \
- (len)++; \
-} while (/* CONSTCOND */ 0)
-
-static void fmtstr(char *, size_t *, size_t, const char *, int, int, int);
-static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int);
-static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *);
-static void printsep(char *, size_t *, size_t);
-static int getnumsep(int);
-static int getexponent(LDOUBLE);
-static int convert(UINTMAX_T, char *, size_t, int, int);
-static UINTMAX_T cast(LDOUBLE);
-static UINTMAX_T myround(LDOUBLE);
-static LDOUBLE mypow10(int);
-
-int
-util_vsnprintf(char *str, size_t size, const char *format, va_list args)
-{
- LDOUBLE fvalue;
- INTMAX_T value;
- unsigned char cvalue;
- const char *strvalue;
- INTMAX_T *intmaxptr;
- PTRDIFF_T *ptrdiffptr;
- SSIZE_T *sizeptr;
- LLONG *llongptr;
- long int *longptr;
- int *intptr;
- short int *shortptr;
- signed char *charptr;
- size_t len = 0;
- int overflow = 0;
- int base = 0;
- int cflags = 0;
- int flags = 0;
- int width = 0;
- int precision = -1;
- int state = PRINT_S_DEFAULT;
- char ch = *format++;
-
- /*
- * C99 says: "If `n' is zero, nothing is written, and `s' may be a null
- * pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer
- * even if a size larger than zero was specified. At least NetBSD's
- * snprintf(3) does the same, as well as other versions of this file.
- * (Though some of these versions will write to a non-NULL buffer even
- * if a size of zero was specified, which violates the standard.)
- */
- if (str == NULL && size != 0)
- size = 0;
-
- while (ch != '\0')
- switch (state) {
- case PRINT_S_DEFAULT:
- if (ch == '%')
- state = PRINT_S_FLAGS;
- else
- OUTCHAR(str, len, size, ch);
- ch = *format++;
- break;
- case PRINT_S_FLAGS:
- switch (ch) {
- case '-':
- flags |= PRINT_F_MINUS;
- ch = *format++;
- break;
- case '+':
- flags |= PRINT_F_PLUS;
- ch = *format++;
- break;
- case ' ':
- flags |= PRINT_F_SPACE;
- ch = *format++;
- break;
- case '#':
- flags |= PRINT_F_NUM;
- ch = *format++;
- break;
- case '0':
- flags |= PRINT_F_ZERO;
- ch = *format++;
- break;
- case '\'': /* SUSv2 flag (not in C99). */
- flags |= PRINT_F_QUOTE;
- ch = *format++;
- break;
- default:
- state = PRINT_S_WIDTH;
- break;
- }
- break;
- case PRINT_S_WIDTH:
- if (ISDIGIT(ch)) {
- ch = CHARTOINT(ch);
- if (width > (INT_MAX - ch) / 10) {
- overflow = 1;
- goto out;
- }
- width = 10 * width + ch;
- ch = *format++;
- } else if (ch == '*') {
- /*
- * C99 says: "A negative field width argument is
- * taken as a `-' flag followed by a positive
- * field width." (7.19.6.1, 5)
- */
- if ((width = va_arg(args, int)) < 0) {
- flags |= PRINT_F_MINUS;
- width = -width;
- }
- ch = *format++;
- state = PRINT_S_DOT;
- } else
- state = PRINT_S_DOT;
- break;
- case PRINT_S_DOT:
- if (ch == '.') {
- state = PRINT_S_PRECISION;
- ch = *format++;
- } else
- state = PRINT_S_MOD;
- break;
- case PRINT_S_PRECISION:
- if (precision == -1)
- precision = 0;
- if (ISDIGIT(ch)) {
- ch = CHARTOINT(ch);
- if (precision > (INT_MAX - ch) / 10) {
- overflow = 1;
- goto out;
- }
- precision = 10 * precision + ch;
- ch = *format++;
- } else if (ch == '*') {
- /*
- * C99 says: "A negative precision argument is
- * taken as if the precision were omitted."
- * (7.19.6.1, 5)
- */
- if ((precision = va_arg(args, int)) < 0)
- precision = -1;
- ch = *format++;
- state = PRINT_S_MOD;
- } else
- state = PRINT_S_MOD;
- break;
- case PRINT_S_MOD:
- switch (ch) {
- case 'h':
- ch = *format++;
- if (ch == 'h') { /* It's a char. */
- ch = *format++;
- cflags = PRINT_C_CHAR;
- } else
- cflags = PRINT_C_SHORT;
- break;
- case 'l':
- ch = *format++;
- if (ch == 'l') { /* It's a long long. */
- ch = *format++;
- cflags = PRINT_C_LLONG;
- } else
- cflags = PRINT_C_LONG;
- break;
- case 'L':
- cflags = PRINT_C_LDOUBLE;
- ch = *format++;
- break;
- case 'j':
- cflags = PRINT_C_INTMAX;
- ch = *format++;
- break;
- case 't':
- cflags = PRINT_C_PTRDIFF;
- ch = *format++;
- break;
- case 'z':
- cflags = PRINT_C_SIZE;
- ch = *format++;
- break;
- }
- state = PRINT_S_CONV;
- break;
- case PRINT_S_CONV:
- switch (ch) {
- case 'd':
- /* FALLTHROUGH */
- case 'i':
- switch (cflags) {
- case PRINT_C_CHAR:
- value = (signed char)va_arg(args, int);
- break;
- case PRINT_C_SHORT:
- value = (short int)va_arg(args, int);
- break;
- case PRINT_C_LONG:
- value = va_arg(args, long int);
- break;
- case PRINT_C_LLONG:
- value = va_arg(args, LLONG);
- break;
- case PRINT_C_SIZE:
- value = va_arg(args, SSIZE_T);
- break;
- case PRINT_C_INTMAX:
- value = va_arg(args, INTMAX_T);
- break;
- case PRINT_C_PTRDIFF:
- value = va_arg(args, PTRDIFF_T);
- break;
- default:
- value = va_arg(args, int);
- break;
- }
- fmtint(str, &len, size, value, 10, width,
- precision, flags);
- break;
- case 'X':
- flags |= PRINT_F_UP;
- /* FALLTHROUGH */
- case 'x':
- base = 16;
- /* FALLTHROUGH */
- case 'o':
- if (base == 0)
- base = 8;
- /* FALLTHROUGH */
- case 'u':
- if (base == 0)
- base = 10;
- flags |= PRINT_F_UNSIGNED;
- switch (cflags) {
- case PRINT_C_CHAR:
- value = (unsigned char)va_arg(args,
- unsigned int);
- break;
- case PRINT_C_SHORT:
- value = (unsigned short int)va_arg(args,
- unsigned int);
- break;
- case PRINT_C_LONG:
- value = va_arg(args, unsigned long int);
- break;
- case PRINT_C_LLONG:
- value = va_arg(args, ULLONG);
- break;
- case PRINT_C_SIZE:
- value = va_arg(args, size_t);
- break;
- case PRINT_C_INTMAX:
- value = va_arg(args, UINTMAX_T);
- break;
- case PRINT_C_PTRDIFF:
- value = va_arg(args, UPTRDIFF_T);
- break;
- default:
- value = va_arg(args, unsigned int);
- break;
- }
- fmtint(str, &len, size, value, base, width,
- precision, flags);
- break;
- case 'A':
- /* Not yet supported, we'll use "%F". */
- /* FALLTHROUGH */
- case 'F':
- flags |= PRINT_F_UP;
- case 'a':
- /* Not yet supported, we'll use "%f". */
- /* FALLTHROUGH */
- case 'f':
- if (cflags == PRINT_C_LDOUBLE)
- fvalue = va_arg(args, LDOUBLE);
- else
- fvalue = va_arg(args, double);
- fmtflt(str, &len, size, fvalue, width,
- precision, flags, &overflow);
- if (overflow)
- goto out;
- break;
- case 'E':
- flags |= PRINT_F_UP;
- /* FALLTHROUGH */
- case 'e':
- flags |= PRINT_F_TYPE_E;
- if (cflags == PRINT_C_LDOUBLE)
- fvalue = va_arg(args, LDOUBLE);
- else
- fvalue = va_arg(args, double);
- fmtflt(str, &len, size, fvalue, width,
- precision, flags, &overflow);
- if (overflow)
- goto out;
- break;
- case 'G':
- flags |= PRINT_F_UP;
- /* FALLTHROUGH */
- case 'g':
- flags |= PRINT_F_TYPE_G;
- if (cflags == PRINT_C_LDOUBLE)
- fvalue = va_arg(args, LDOUBLE);
- else
- fvalue = va_arg(args, double);
- /*
- * If the precision is zero, it is treated as
- * one (cf. C99: 7.19.6.1, 8).
- */
- if (precision == 0)
- precision = 1;
- fmtflt(str, &len, size, fvalue, width,
- precision, flags, &overflow);
- if (overflow)
- goto out;
- break;
- case 'c':
- cvalue = (unsigned char)va_arg(args, int);
- OUTCHAR(str, len, size, cvalue);
- break;
- case 's':
- strvalue = va_arg(args, char *);
- fmtstr(str, &len, size, strvalue, width,
- precision, flags);
- break;
- case 'p':
- /*
- * C99 says: "The value of the pointer is
- * converted to a sequence of printing
- * characters, in an implementation-defined
- * manner." (C99: 7.19.6.1, 8)
- */
- if ((strvalue = va_arg(args, void *)) == NULL)
- /*
- * We use the glibc format. BSD prints
- * "0x0", SysV "0".
- */
- fmtstr(str, &len, size, "(nil)", width,
- -1, flags);
- else {
- /*
- * We use the BSD/glibc format. SysV
- * omits the "0x" prefix (which we emit
- * using the PRINT_F_NUM flag).
- */
- flags |= PRINT_F_NUM;
- flags |= PRINT_F_UNSIGNED;
- fmtint(str, &len, size,
- (UINTPTR_T)strvalue, 16, width,
- precision, flags);
- }
- break;
- case 'n':
- switch (cflags) {
- case PRINT_C_CHAR:
- charptr = va_arg(args, signed char *);
- *charptr = (signed char)len;
- break;
- case PRINT_C_SHORT:
- shortptr = va_arg(args, short int *);
- *shortptr = (short int)len;
- break;
- case PRINT_C_LONG:
- longptr = va_arg(args, long int *);
- *longptr = (long int)len;
- break;
- case PRINT_C_LLONG:
- llongptr = va_arg(args, LLONG *);
- *llongptr = (LLONG)len;
- break;
- case PRINT_C_SIZE:
- /*
- * C99 says that with the "z" length
- * modifier, "a following `n' conversion
- * specifier applies to a pointer to a
- * signed integer type corresponding to
- * size_t argument." (7.19.6.1, 7)
- */
- sizeptr = va_arg(args, SSIZE_T *);
- *sizeptr = len;
- break;
- case PRINT_C_INTMAX:
- intmaxptr = va_arg(args, INTMAX_T *);
- *intmaxptr = len;
- break;
- case PRINT_C_PTRDIFF:
- ptrdiffptr = va_arg(args, PTRDIFF_T *);
- *ptrdiffptr = len;
- break;
- default:
- intptr = va_arg(args, int *);
- *intptr = (int)len;
- break;
- }
- break;
- case '%': /* Print a "%" character verbatim. */
- OUTCHAR(str, len, size, ch);
- break;
- default: /* Skip other characters. */
- break;
- }
- ch = *format++;
- state = PRINT_S_DEFAULT;
- base = cflags = flags = width = 0;
- precision = -1;
- break;
- }
-out:
- if (len < size)
- str[len] = '\0';
- else if (size > 0)
- str[size - 1] = '\0';
-
- if (overflow || len >= INT_MAX) {
- return -1;
- }
- return (int)len;
-}
-
-static void
-fmtstr(char *str, size_t *len, size_t size, const char *value, int width,
- int precision, int flags)
-{
- int padlen, strln; /* Amount to pad. */
- int noprecision = (precision == -1);
-
- if (value == NULL) /* We're forgiving. */
- value = "(null)";
-
- /* If a precision was specified, don't read the string past it. */
- for (strln = 0; value[strln] != '\0' &&
- (noprecision || strln < precision); strln++)
- continue;
-
- if ((padlen = width - strln) < 0)
- padlen = 0;
- if (flags & PRINT_F_MINUS) /* Left justify. */
- padlen = -padlen;
-
- while (padlen > 0) { /* Leading spaces. */
- OUTCHAR(str, *len, size, ' ');
- padlen--;
- }
- while (*value != '\0' && (noprecision || precision-- > 0)) {
- OUTCHAR(str, *len, size, *value);
- value++;
- }
- while (padlen < 0) { /* Trailing spaces. */
- OUTCHAR(str, *len, size, ' ');
- padlen++;
- }
-}
-
-static void
-fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width,
- int precision, int flags)
-{
- UINTMAX_T uvalue;
- char iconvert[MAX_CONVERT_LENGTH];
- char sign = 0;
- char hexprefix = 0;
- int spadlen = 0; /* Amount to space pad. */
- int zpadlen = 0; /* Amount to zero pad. */
- int pos;
- int separators = (flags & PRINT_F_QUOTE);
- int noprecision = (precision == -1);
-
- if (flags & PRINT_F_UNSIGNED)
- uvalue = value;
- else {
- uvalue = (value >= 0) ? value : -value;
- if (value < 0)
- sign = '-';
- else if (flags & PRINT_F_PLUS) /* Do a sign. */
- sign = '+';
- else if (flags & PRINT_F_SPACE)
- sign = ' ';
- }
-
- pos = convert(uvalue, iconvert, sizeof(iconvert), base,
- flags & PRINT_F_UP);
-
- if (flags & PRINT_F_NUM && uvalue != 0) {
- /*
- * C99 says: "The result is converted to an `alternative form'.
- * For `o' conversion, it increases the precision, if and only
- * if necessary, to force the first digit of the result to be a
- * zero (if the value and precision are both 0, a single 0 is
- * printed). For `x' (or `X') conversion, a nonzero result has
- * `0x' (or `0X') prefixed to it." (7.19.6.1, 6)
- */
- switch (base) {
- case 8:
- if (precision <= pos)
- precision = pos + 1;
- break;
- case 16:
- hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x';
- break;
- }
- }
-
- if (separators) /* Get the number of group separators we'll print. */
- separators = getnumsep(pos);
-
- zpadlen = precision - pos - separators;
- spadlen = width /* Minimum field width. */
- - separators /* Number of separators. */
- - MAX(precision, pos) /* Number of integer digits. */
- - ((sign != 0) ? 1 : 0) /* Will we print a sign? */
- - ((hexprefix != 0) ? 2 : 0); /* Will we print a prefix? */
-
- if (zpadlen < 0)
- zpadlen = 0;
- if (spadlen < 0)
- spadlen = 0;
-
- /*
- * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
- * ignored. For `d', `i', `o', `u', `x', and `X' conversions, if a
- * precision is specified, the `0' flag is ignored." (7.19.6.1, 6)
- */
- if (flags & PRINT_F_MINUS) /* Left justify. */
- spadlen = -spadlen;
- else if (flags & PRINT_F_ZERO && noprecision) {
- zpadlen += spadlen;
- spadlen = 0;
- }
- while (spadlen > 0) { /* Leading spaces. */
- OUTCHAR(str, *len, size, ' ');
- spadlen--;
- }
- if (sign != 0) /* Sign. */
- OUTCHAR(str, *len, size, sign);
- if (hexprefix != 0) { /* A "0x" or "0X" prefix. */
- OUTCHAR(str, *len, size, '0');
- OUTCHAR(str, *len, size, hexprefix);
- }
- while (zpadlen > 0) { /* Leading zeros. */
- OUTCHAR(str, *len, size, '0');
- zpadlen--;
- }
- while (pos > 0) { /* The actual digits. */
- pos--;
- OUTCHAR(str, *len, size, iconvert[pos]);
- if (separators > 0 && pos > 0 && pos % 3 == 0)
- printsep(str, len, size);
- }
- while (spadlen < 0) { /* Trailing spaces. */
- OUTCHAR(str, *len, size, ' ');
- spadlen++;
- }
-}
-
-static void
-fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width,
- int precision, int flags, int *overflow)
-{
- LDOUBLE ufvalue;
- UINTMAX_T intpart;
- UINTMAX_T fracpart;
- UINTMAX_T mask;
- const char *infnan = NULL;
- char iconvert[MAX_CONVERT_LENGTH];
- char fconvert[MAX_CONVERT_LENGTH];
- char econvert[4]; /* "e-12" (without nul-termination). */
- char esign = 0;
- char sign = 0;
- int leadfraczeros = 0;
- int exponent = 0;
- int emitpoint = 0;
- int omitzeros = 0;
- int omitcount = 0;
- int padlen = 0;
- int epos = 0;
- int fpos = 0;
- int ipos = 0;
- int separators = (flags & PRINT_F_QUOTE);
- int estyle = (flags & PRINT_F_TYPE_E);
-#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
- struct lconv *lc = localeconv();
-#endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
-
- /*
- * AIX' man page says the default is 0, but C99 and at least Solaris'
- * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX
- * defaults to 6.
- */
- if (precision == -1)
- precision = 6;
-
- if (fvalue < 0.0)
- sign = '-';
- else if (flags & PRINT_F_PLUS) /* Do a sign. */
- sign = '+';
- else if (flags & PRINT_F_SPACE)
- sign = ' ';
-
- if (ISNAN(fvalue))
- infnan = (flags & PRINT_F_UP) ? "NAN" : "nan";
- else if (ISINF(fvalue))
- infnan = (flags & PRINT_F_UP) ? "INF" : "inf";
-
- if (infnan != NULL) {
- if (sign != 0)
- iconvert[ipos++] = sign;
- while (*infnan != '\0')
- iconvert[ipos++] = *infnan++;
- fmtstr(str, len, size, iconvert, width, ipos, flags);
- return;
- }
-
- /* "%e" (or "%E") or "%g" (or "%G") conversion. */
- if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) {
- if (flags & PRINT_F_TYPE_G) {
- /*
- * For "%g" (and "%G") conversions, the precision
- * specifies the number of significant digits, which
- * includes the digits in the integer part. The
- * conversion will or will not be using "e-style" (like
- * "%e" or "%E" conversions) depending on the precision
- * and on the exponent. However, the exponent can be
- * affected by rounding the converted value, so we'll
- * leave this decision for later. Until then, we'll
- * assume that we're going to do an "e-style" conversion
- * (in order to get the exponent calculated). For
- * "e-style", the precision must be decremented by one.
- */
- precision--;
- /*
- * For "%g" (and "%G") conversions, trailing zeros are
- * removed from the fractional portion of the result
- * unless the "#" flag was specified.
- */
- if (!(flags & PRINT_F_NUM))
- omitzeros = 1;
- }
- exponent = getexponent(fvalue);
- estyle = 1;
- }
-
-again:
- /*
- * Sorry, we only support 9, 19, or 38 digits (that is, the number of
- * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value
- * minus one) past the decimal point due to our conversion method.
- */
- switch (sizeof(UINTMAX_T)) {
- case 16:
- if (precision > 38)
- precision = 38;
- break;
- case 8:
- if (precision > 19)
- precision = 19;
- break;
- default:
- if (precision > 9)
- precision = 9;
- break;
- }
-
- ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue;
- if (estyle) /* We want exactly one integer digit. */
- ufvalue /= mypow10(exponent);
-
- if ((intpart = cast(ufvalue)) == UINTMAX_MAX) {
- *overflow = 1;
- return;
- }
-
- /*
- * Factor of ten with the number of digits needed for the fractional
- * part. For example, if the precision is 3, the mask will be 1000.
- */
-#if defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
- mask = (unsigned long)mypow10(precision);
-#else
- mask = (UINTMAX_T)mypow10(precision);
-#endif
- /*
- * We "cheat" by converting the fractional part to integer by
- * multiplying by a factor of ten.
- */
- if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) {
- /*
- * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000
- * (because precision = 3). Now, myround(1000 * 0.99962) will
- * return 1000. So, the integer part must be incremented by one
- * and the fractional part must be set to zero.
- */
- intpart++;
- fracpart = 0;
- if (estyle && intpart == 10) {
- /*
- * The value was rounded up to ten, but we only want one
- * integer digit if using "e-style". So, the integer
- * part must be set to one and the exponent must be
- * incremented by one.
- */
- intpart = 1;
- exponent++;
- }
- }
-
- /*
- * Now that we know the real exponent, we can check whether or not to
- * use "e-style" for "%g" (and "%G") conversions. If we don't need
- * "e-style", the precision must be adjusted and the integer and
- * fractional parts must be recalculated from the original value.
- *
- * C99 says: "Let P equal the precision if nonzero, 6 if the precision
- * is omitted, or 1 if the precision is zero. Then, if a conversion
- * with style `E' would have an exponent of X:
- *
- * - if P > X >= -4, the conversion is with style `f' (or `F') and
- * precision P - (X + 1).
- *
- * - otherwise, the conversion is with style `e' (or `E') and precision
- * P - 1." (7.19.6.1, 8)
- *
- * Note that we had decremented the precision by one.
- */
- if (flags & PRINT_F_TYPE_G && estyle &&
- precision + 1 > exponent && exponent >= -4) {
- precision -= exponent;
- estyle = 0;
- goto again;
- }
-
- if (estyle) {
- if (exponent < 0) {
- exponent = -exponent;
- esign = '-';
- } else
- esign = '+';
-
- /*
- * Convert the exponent. The sizeof(econvert) is 4. So, the
- * econvert buffer can hold e.g. "e+99" and "e-99". We don't
- * support an exponent which contains more than two digits.
- * Therefore, the following stores are safe.
- */
- epos = convert(exponent, econvert, 2, 10, 0);
- /*
- * C99 says: "The exponent always contains at least two digits,
- * and only as many more digits as necessary to represent the
- * exponent." (7.19.6.1, 8)
- */
- if (epos == 1)
- econvert[epos++] = '0';
- econvert[epos++] = esign;
- econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e';
- }
-
- /* Convert the integer part and the fractional part. */
- ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0);
- if (fracpart != 0) /* convert() would return 1 if fracpart == 0. */
- fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0);
-
- leadfraczeros = precision - fpos;
-
- if (omitzeros) {
- if (fpos > 0) /* Omit trailing fractional part zeros. */
- while (omitcount < fpos && fconvert[omitcount] == '0')
- omitcount++;
- else { /* The fractional part is zero, omit it completely. */
- omitcount = precision;
- leadfraczeros = 0;
- }
- precision -= omitcount;
- }
-
- /*
- * Print a decimal point if either the fractional part is non-zero
- * and/or the "#" flag was specified.
- */
- if (precision > 0 || flags & PRINT_F_NUM)
- emitpoint = 1;
- if (separators) /* Get the number of group separators we'll print. */
- separators = getnumsep(ipos);
-
- padlen = width /* Minimum field width. */
- - ipos /* Number of integer digits. */
- - epos /* Number of exponent characters. */
- - precision /* Number of fractional digits. */
- - separators /* Number of group separators. */
- - (emitpoint ? 1 : 0) /* Will we print a decimal point? */
- - ((sign != 0) ? 1 : 0); /* Will we print a sign character? */
-
- if (padlen < 0)
- padlen = 0;
-
- /*
- * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
- * ignored." (7.19.6.1, 6)
- */
- if (flags & PRINT_F_MINUS) /* Left justifty. */
- padlen = -padlen;
- else if (flags & PRINT_F_ZERO && padlen > 0) {
- if (sign != 0) { /* Sign. */
- OUTCHAR(str, *len, size, sign);
- sign = 0;
- }
- while (padlen > 0) { /* Leading zeros. */
- OUTCHAR(str, *len, size, '0');
- padlen--;
- }
- }
- while (padlen > 0) { /* Leading spaces. */
- OUTCHAR(str, *len, size, ' ');
- padlen--;
- }
- if (sign != 0) /* Sign. */
- OUTCHAR(str, *len, size, sign);
- while (ipos > 0) { /* Integer part. */
- ipos--;
- OUTCHAR(str, *len, size, iconvert[ipos]);
- if (separators > 0 && ipos > 0 && ipos % 3 == 0)
- printsep(str, len, size);
- }
- if (emitpoint) { /* Decimal point. */
-#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
- if (lc->decimal_point != NULL && *lc->decimal_point != '\0')
- OUTCHAR(str, *len, size, *lc->decimal_point);
- else /* We'll always print some decimal point character. */
-#endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
- OUTCHAR(str, *len, size, '.');
- }
- while (leadfraczeros > 0) { /* Leading fractional part zeros. */
- OUTCHAR(str, *len, size, '0');
- leadfraczeros--;
- }
- while (fpos > omitcount) { /* The remaining fractional part. */
- fpos--;
- OUTCHAR(str, *len, size, fconvert[fpos]);
- }
- while (epos > 0) { /* Exponent. */
- epos--;
- OUTCHAR(str, *len, size, econvert[epos]);
- }
- while (padlen < 0) { /* Trailing spaces. */
- OUTCHAR(str, *len, size, ' ');
- padlen++;
- }
-}
-
-static void
-printsep(char *str, size_t *len, size_t size)
-{
-#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
- struct lconv *lc = localeconv();
- int i;
-
- if (lc->thousands_sep != NULL)
- for (i = 0; lc->thousands_sep[i] != '\0'; i++)
- OUTCHAR(str, *len, size, lc->thousands_sep[i]);
- else
-#endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
- OUTCHAR(str, *len, size, ',');
-}
-
-static int
-getnumsep(int digits)
-{
- int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3;
-#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
- int strln;
- struct lconv *lc = localeconv();
-
- /* We support an arbitrary separator length (including zero). */
- if (lc->thousands_sep != NULL) {
- for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++)
- continue;
- separators *= strln;
- }
-#endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
- return separators;
-}
-
-static int
-getexponent(LDOUBLE value)
-{
- LDOUBLE tmp = (value >= 0.0) ? value : -value;
- int exponent = 0;
-
- /*
- * We check for 99 > exponent > -99 in order to work around possible
- * endless loops which could happen (at least) in the second loop (at
- * least) if we're called with an infinite value. However, we checked
- * for infinity before calling this function using our ISINF() macro, so
- * this might be somewhat paranoid.
- */
- while (tmp < 1.0 && tmp > 0.0 && --exponent > -99)
- tmp *= 10;
- while (tmp >= 10.0 && ++exponent < 99)
- tmp /= 10;
-
- return exponent;
-}
-
-static int
-convert(UINTMAX_T value, char *buf, size_t size, int base, int caps)
-{
- const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef";
- size_t pos = 0;
-
- /* We return an unterminated buffer with the digits in reverse order. */
- do {
- buf[pos++] = digits[value % base];
- value /= base;
- } while (value != 0 && pos < size);
-
- return (int)pos;
-}
-
-static UINTMAX_T
-cast(LDOUBLE value)
-{
- UINTMAX_T result;
-
- /*
- * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be
- * represented exactly as an LDOUBLE value (but is less than LDBL_MAX),
- * it may be increased to the nearest higher representable value for the
- * comparison (cf. C99: 6.3.1.4, 2). It might then equal the LDOUBLE
- * value although converting the latter to UINTMAX_T would overflow.
- */
- if (value >= UINTMAX_MAX)
- return UINTMAX_MAX;
-
-#if defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
- result = (unsigned long)value;
-#else
- result = (UINTMAX_T)value;
-#endif
- /*
- * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to
- * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates
- * the standard). Sigh.
- */
- return (result <= value) ? result : result - 1;
-}
-
-static UINTMAX_T
-myround(LDOUBLE value)
-{
- UINTMAX_T intpart = cast(value);
-
- return ((value -= intpart) < 0.5) ? intpart : intpart + 1;
-}
-
-static LDOUBLE
-mypow10(int exponent)
-{
- LDOUBLE result = 1;
-
- while (exponent > 0) {
- result *= 10;
- exponent--;
- }
- while (exponent < 0) {
- result /= 10;
- exponent++;
- }
- return result;
-}
-#endif /* !HAVE_VSNPRINTF */
-
-#if !HAVE_VASPRINTF
-#if NEED_MYMEMCPY
-void *
-mymemcpy(void *dst, void *src, size_t len)
-{
- const char *from = src;
- char *to = dst;
-
- /* No need for optimization, we use this only to replace va_copy(3). */
- while (len-- > 0)
- *to++ = *from++;
- return dst;
-}
-#endif /* NEED_MYMEMCPY */
-
-int
-util_vasprintf(char **ret, const char *format, va_list ap)
-{
- size_t size;
- int len;
- va_list aq;
-
- VA_COPY(aq, ap);
- len = vsnprintf(NULL, 0, format, aq);
- VA_END_COPY(aq);
- if (len < 0 || (*ret = malloc(size = len + 1)) == NULL)
- return -1;
- return vsnprintf(*ret, size, format, ap);
-}
-#endif /* !HAVE_VASPRINTF */
-
-#if !HAVE_SNPRINTF
-#if HAVE_STDARG_H
-int
-util_snprintf(char *str, size_t size, const char *format, ...)
-#else
-int
-util_snprintf(va_alist) va_dcl
-#endif /* HAVE_STDARG_H */
-{
-#if !HAVE_STDARG_H
- char *str;
- size_t size;
- char *format;
-#endif /* HAVE_STDARG_H */
- va_list ap;
- int len;
-
- VA_START(ap, format);
- VA_SHIFT(ap, str, char *);
- VA_SHIFT(ap, size, size_t);
- VA_SHIFT(ap, format, const char *);
- len = vsnprintf(str, size, format, ap);
- va_end(ap);
- return len;
-}
-#endif /* !HAVE_SNPRINTF */
-
-#if !HAVE_ASPRINTF
-#if HAVE_STDARG_H
-int
-util_asprintf(char **ret, const char *format, ...)
-#else
-int
-util_asprintf(va_alist) va_dcl
-#endif /* HAVE_STDARG_H */
-{
-#if !HAVE_STDARG_H
- char **ret;
- char *format;
-#endif /* HAVE_STDARG_H */
- va_list ap;
- int len;
-
- VA_START(ap, format);
- VA_SHIFT(ap, ret, char **);
- VA_SHIFT(ap, format, const char *);
- len = vasprintf(ret, format, ap);
- va_end(ap);
- return len;
-}
-#endif /* !HAVE_ASPRINTF */
-#else /* Dummy declaration to avoid empty translation unit warnings. */
-int main(void);
-#endif /* !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || [...] */
-
-
-/* vim: set joinspaces textwidth=80: */
+/*
+ * Copyright (c) 1995 Patrick Powell.
+ *
+ * This code is based on code written by Patrick Powell <papowell@astart.com>.
+ * It may be used for any purpose as long as this notice remains intact on all
+ * source code distributions.
+ */
+
+/*
+ * Copyright (c) 2008 Holger Weiss.
+ *
+ * This version of the code is maintained by Holger Weiss <holger@jhweiss.de>.
+ * My changes to the code may freely be used, modified and/or redistributed for
+ * any purpose. It would be nice if additions and fixes to this file (including
+ * trivial code cleanups) would be sent back in order to let me include them in
+ * the version available at <http://www.jhweiss.de/software/snprintf.html>.
+ * However, this is not a requirement for using or redistributing (possibly
+ * modified) versions of this file, nor is leaving this notice intact mandatory.
+ */
+
+/*
+ * History
+ *
+ * 2008-01-20 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.1:
+ *
+ * Fixed the detection of infinite floating point values on IRIX (and
+ * possibly other systems) and applied another few minor cleanups.
+ *
+ * 2008-01-06 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.0:
+ *
+ * Added a lot of new features, fixed many bugs, and incorporated various
+ * improvements done by Andrew Tridgell <tridge@samba.org>, Russ Allbery
+ * <rra@stanford.edu>, Hrvoje Niksic <hniksic@xemacs.org>, Damien Miller
+ * <djm@mindrot.org>, and others for the Samba, INN, Wget, and OpenSSH
+ * projects. The additions include: support the "e", "E", "g", "G", and
+ * "F" conversion specifiers (and use conversion style "f" or "F" for the
+ * still unsupported "a" and "A" specifiers); support the "hh", "ll", "j",
+ * "t", and "z" length modifiers; support the "#" flag and the (non-C99)
+ * "'" flag; use localeconv(3) (if available) to get both the current
+ * locale's decimal point character and the separator between groups of
+ * digits; fix the handling of various corner cases of field width and
+ * precision specifications; fix various floating point conversion bugs;
+ * handle infinite and NaN floating point values; don't attempt to write to
+ * the output buffer (which may be NULL) if a size of zero was specified;
+ * check for integer overflow of the field width, precision, and return
+ * values and during the floating point conversion; use the OUTCHAR() macro
+ * instead of a function for better performance; provide asprintf(3) and
+ * vasprintf(3) functions; add new test cases. The replacement functions
+ * have been renamed to use an "rpl_" prefix, the function calls in the
+ * main project (and in this file) must be redefined accordingly for each
+ * replacement function which is needed (by using Autoconf or other means).
+ * Various other minor improvements have been applied and the coding style
+ * was cleaned up for consistency.
+ *
+ * 2007-07-23 Holger Weiss <holger@jhweiss.de> for Mutt 1.5.13:
+ *
+ * C99 compliant snprintf(3) and vsnprintf(3) functions return the number
+ * of characters that would have been written to a sufficiently sized
+ * buffer (excluding the '\0'). The original code simply returned the
+ * length of the resulting output string, so that's been fixed.
+ *
+ * 1998-03-05 Michael Elkins <me@mutt.org> for Mutt 0.90.8:
+ *
+ * The original code assumed that both snprintf(3) and vsnprintf(3) were
+ * missing. Some systems only have snprintf(3) but not vsnprintf(3), so
+ * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
+ *
+ * 1998-01-27 Thomas Roessler <roessler@does-not-exist.org> for Mutt 0.89i:
+ *
+ * The PGP code was using unsigned hexadecimal formats. Unfortunately,
+ * unsigned formats simply didn't work.
+ *
+ * 1997-10-22 Brandon Long <blong@fiction.net> for Mutt 0.87.1:
+ *
+ * Ok, added some minimal floating point support, which means this probably
+ * requires libm on most operating systems. Don't yet support the exponent
+ * (e,E) and sigfig (g,G). Also, fmtint() was pretty badly broken, it just
+ * wasn't being exercised in ways which showed it, so that's been fixed.
+ * Also, formatted the code to Mutt conventions, and removed dead code left
+ * over from the original. Also, there is now a builtin-test, run with:
+ * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf
+ *
+ * 2996-09-15 Brandon Long <blong@fiction.net> for Mutt 0.43:
+ *
+ * This was ugly. It is still ugly. I opted out of floating point
+ * numbers, but the formatter understands just about everything from the
+ * normal C string format, at least as far as I can tell from the Solaris
+ * 2.5 printf(3S) man page.
+ */
+
+/*
+ * ToDo
+ *
+ * - Add wide character support.
+ * - Add support for "%a" and "%A" conversions.
+ * - Create test routines which predefine the expected results. Our test cases
+ * usually expose bugs in system implementations rather than in ours :-)
+ */
+
+/*
+ * Usage
+ *
+ * 1) The following preprocessor macros should be defined to 1 if the feature or
+ * file in question is available on the target system (by using Autoconf or
+ * other means), though basic functionality should be available as long as
+ * HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly:
+ *
+ * HAVE_VSNPRINTF
+ * HAVE_SNPRINTF
+ * HAVE_VASPRINTF
+ * HAVE_ASPRINTF
+ * HAVE_STDARG_H
+ * HAVE_STDDEF_H
+ * HAVE_STDINT_H
+ * HAVE_STDLIB_H
+ * HAVE_INTTYPES_H
+ * HAVE_LOCALE_H
+ * HAVE_LOCALECONV
+ * HAVE_LCONV_DECIMAL_POINT
+ * HAVE_LCONV_THOUSANDS_SEP
+ * HAVE_LONG_DOUBLE
+ * HAVE_LONG_LONG_INT
+ * HAVE_UNSIGNED_LONG_LONG_INT
+ * HAVE_INTMAX_T
+ * HAVE_UINTMAX_T
+ * HAVE_UINTPTR_T
+ * HAVE_PTRDIFF_T
+ * HAVE_VA_COPY
+ * HAVE___VA_COPY
+ *
+ * 2) The calls to the functions which should be replaced must be redefined
+ * throughout the project files (by using Autoconf or other means):
+ *
+ * #define vsnprintf rpl_vsnprintf
+ * #define snprintf rpl_snprintf
+ * #define vasprintf rpl_vasprintf
+ * #define asprintf rpl_asprintf
+ *
+ * 3) The required replacement functions should be declared in some header file
+ * included throughout the project files:
+ *
+ * #if HAVE_CONFIG_H
+ * #include <config.h>
+ * #endif
+ * #if HAVE_STDARG_H
+ * #include <stdarg.h>
+ * #if !HAVE_VSNPRINTF
+ * int rpl_vsnprintf(char *, size_t, const char *, va_list);
+ * #endif
+ * #if !HAVE_SNPRINTF
+ * int rpl_snprintf(char *, size_t, const char *, ...);
+ * #endif
+ * #if !HAVE_VASPRINTF
+ * int rpl_vasprintf(char **, const char *, va_list);
+ * #endif
+ * #if !HAVE_ASPRINTF
+ * int rpl_asprintf(char **, const char *, ...);
+ * #endif
+ * #endif
+ *
+ * Autoconf macros for handling step 1 and step 2 are available at
+ * <http://www.jhweiss.de/software/snprintf.html>.
+ */
+
+#include "pipe/p_config.h"
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#else
+#ifdef WIN32
+#define vsnprintf util_vsnprintf
+#define snprintf util_snprintf
+#define HAVE_VSNPRINTF 0
+#define HAVE_SNPRINTF 0
+#define HAVE_VASPRINTF 1 /* not needed */
+#define HAVE_ASPRINTF 1 /* not needed */
+#define HAVE_STDARG_H 1
+#define HAVE_STDDEF_H 1
+#define HAVE_STDINT_H 0
+#define HAVE_STDLIB_H 1
+#define HAVE_INTTYPES_H 0
+#define HAVE_LOCALE_H 0
+#define HAVE_LOCALECONV 0
+#define HAVE_LCONV_DECIMAL_POINT 0
+#define HAVE_LCONV_THOUSANDS_SEP 0
+#define HAVE_LONG_DOUBLE 0
+#define HAVE_LONG_LONG_INT 1
+#define HAVE_UNSIGNED_LONG_LONG_INT 1
+#define HAVE_INTMAX_T 0
+#define HAVE_UINTMAX_T 0
+#define HAVE_UINTPTR_T 1
+#define HAVE_PTRDIFF_T 1
+#define HAVE_VA_COPY 0
+#define HAVE___VA_COPY 0
+#else
+#define HAVE_VSNPRINTF 1
+#define HAVE_SNPRINTF 1
+#define HAVE_VASPRINTF 1
+#define HAVE_ASPRINTF 1
+#endif
+#endif /* HAVE_CONFIG_H */
+
+#if !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || !HAVE_VASPRINTF
+#include <stdio.h> /* For NULL, size_t, vsnprintf(3), and vasprintf(3). */
+#ifdef VA_START
+#undef VA_START
+#endif /* defined(VA_START) */
+#ifdef VA_SHIFT
+#undef VA_SHIFT
+#endif /* defined(VA_SHIFT) */
+#if HAVE_STDARG_H
+#include <stdarg.h>
+#define VA_START(ap, last) va_start(ap, last)
+#define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */
+#else /* Assume <varargs.h> is available. */
+#include <varargs.h>
+#define VA_START(ap, last) va_start(ap) /* "last" is ignored. */
+#define VA_SHIFT(ap, value, type) value = va_arg(ap, type)
+#endif /* HAVE_STDARG_H */
+
+#if !HAVE_VASPRINTF
+#if HAVE_STDLIB_H
+#include <stdlib.h> /* For malloc(3). */
+#endif /* HAVE_STDLIB_H */
+#ifdef VA_COPY
+#undef VA_COPY
+#endif /* defined(VA_COPY) */
+#ifdef VA_END_COPY
+#undef VA_END_COPY
+#endif /* defined(VA_END_COPY) */
+#if HAVE_VA_COPY
+#define VA_COPY(dest, src) va_copy(dest, src)
+#define VA_END_COPY(ap) va_end(ap)
+#elif HAVE___VA_COPY
+#define VA_COPY(dest, src) __va_copy(dest, src)
+#define VA_END_COPY(ap) va_end(ap)
+#else
+#define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list))
+#define VA_END_COPY(ap) /* No-op. */
+#define NEED_MYMEMCPY 1
+static void *mymemcpy(void *, void *, size_t);
+#endif /* HAVE_VA_COPY */
+#endif /* !HAVE_VASPRINTF */
+
+#if !HAVE_VSNPRINTF
+#include <limits.h> /* For *_MAX. */
+#if HAVE_INTTYPES_H
+#include <inttypes.h> /* For intmax_t (if not defined in <stdint.h>). */
+#endif /* HAVE_INTTYPES_H */
+#if HAVE_LOCALE_H
+#include <locale.h> /* For localeconv(3). */
+#endif /* HAVE_LOCALE_H */
+#if HAVE_STDDEF_H
+#include <stddef.h> /* For ptrdiff_t. */
+#endif /* HAVE_STDDEF_H */
+#if HAVE_STDINT_H
+#include <stdint.h> /* For intmax_t. */
+#endif /* HAVE_STDINT_H */
+
+/* Support for unsigned long long int. We may also need ULLONG_MAX. */
+#ifndef ULONG_MAX /* We may need ULONG_MAX as a fallback. */
+#ifdef UINT_MAX
+#define ULONG_MAX UINT_MAX
+#else
+#define ULONG_MAX INT_MAX
+#endif /* defined(UINT_MAX) */
+#endif /* !defined(ULONG_MAX) */
+#ifdef ULLONG
+#undef ULLONG
+#endif /* defined(ULLONG) */
+#if HAVE_UNSIGNED_LONG_LONG_INT
+#define ULLONG unsigned long long int
+#ifndef ULLONG_MAX
+#define ULLONG_MAX ULONG_MAX
+#endif /* !defined(ULLONG_MAX) */
+#else
+#define ULLONG unsigned long int
+#ifdef ULLONG_MAX
+#undef ULLONG_MAX
+#endif /* defined(ULLONG_MAX) */
+#define ULLONG_MAX ULONG_MAX
+#endif /* HAVE_LONG_LONG_INT */
+
+/* Support for uintmax_t. We also need UINTMAX_MAX. */
+#ifdef UINTMAX_T
+#undef UINTMAX_T
+#endif /* defined(UINTMAX_T) */
+#if HAVE_UINTMAX_T || defined(uintmax_t)
+#define UINTMAX_T uintmax_t
+#ifndef UINTMAX_MAX
+#define UINTMAX_MAX ULLONG_MAX
+#endif /* !defined(UINTMAX_MAX) */
+#else
+#define UINTMAX_T ULLONG
+#ifdef UINTMAX_MAX
+#undef UINTMAX_MAX
+#endif /* defined(UINTMAX_MAX) */
+#define UINTMAX_MAX ULLONG_MAX
+#endif /* HAVE_UINTMAX_T || defined(uintmax_t) */
+
+/* Support for long double. */
+#ifndef LDOUBLE
+#if HAVE_LONG_DOUBLE
+#define LDOUBLE long double
+#else
+#define LDOUBLE double
+#endif /* HAVE_LONG_DOUBLE */
+#endif /* !defined(LDOUBLE) */
+
+/* Support for long long int. */
+#ifndef LLONG
+#if HAVE_LONG_LONG_INT
+#define LLONG long long int
+#else
+#define LLONG long int
+#endif /* HAVE_LONG_LONG_INT */
+#endif /* !defined(LLONG) */
+
+/* Support for intmax_t. */
+#ifndef INTMAX_T
+#if HAVE_INTMAX_T || defined(intmax_t)
+#define INTMAX_T intmax_t
+#else
+#define INTMAX_T LLONG
+#endif /* HAVE_INTMAX_T || defined(intmax_t) */
+#endif /* !defined(INTMAX_T) */
+
+/* Support for uintptr_t. */
+#ifndef UINTPTR_T
+#if HAVE_UINTPTR_T || defined(uintptr_t)
+#define UINTPTR_T uintptr_t
+#else
+#define UINTPTR_T unsigned long int
+#endif /* HAVE_UINTPTR_T || defined(uintptr_t) */
+#endif /* !defined(UINTPTR_T) */
+
+/* WinCE5.0 does not have uintptr_t defined */
+#if (_WIN32_WCE < 600)
+#ifdef UINTPTR_T
+#undef UINTPTR_T
+#endif
+#define UINTPTR_T unsigned long int
+#endif
+
+
+/* Support for ptrdiff_t. */
+#ifndef PTRDIFF_T
+#if HAVE_PTRDIFF_T || defined(ptrdiff_t)
+#define PTRDIFF_T ptrdiff_t
+#else
+#define PTRDIFF_T long int
+#endif /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */
+#endif /* !defined(PTRDIFF_T) */
+
+/*
+ * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99:
+ * 7.19.6.1, 7). However, we'll simply use PTRDIFF_T and convert it to an
+ * unsigned type if necessary. This should work just fine in practice.
+ */
+#ifndef UPTRDIFF_T
+#define UPTRDIFF_T PTRDIFF_T
+#endif /* !defined(UPTRDIFF_T) */
+
+/*
+ * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7).
+ * However, we'll simply use size_t and convert it to a signed type if
+ * necessary. This should work just fine in practice.
+ */
+#ifndef SSIZE_T
+#define SSIZE_T size_t
+#endif /* !defined(SSIZE_T) */
+
+/* Either ERANGE or E2BIG should be available everywhere. */
+#ifndef ERANGE
+#define ERANGE E2BIG
+#endif /* !defined(ERANGE) */
+#ifndef EOVERFLOW
+#define EOVERFLOW ERANGE
+#endif /* !defined(EOVERFLOW) */
+
+/*
+ * Buffer size to hold the octal string representation of UINT128_MAX without
+ * nul-termination ("3777777777777777777777777777777777777777777").
+ */
+#ifdef MAX_CONVERT_LENGTH
+#undef MAX_CONVERT_LENGTH
+#endif /* defined(MAX_CONVERT_LENGTH) */
+#define MAX_CONVERT_LENGTH 43
+
+/* Format read states. */
+#define PRINT_S_DEFAULT 0
+#define PRINT_S_FLAGS 1
+#define PRINT_S_WIDTH 2
+#define PRINT_S_DOT 3
+#define PRINT_S_PRECISION 4
+#define PRINT_S_MOD 5
+#define PRINT_S_CONV 6
+
+/* Format flags. */
+#define PRINT_F_MINUS (1 << 0)
+#define PRINT_F_PLUS (1 << 1)
+#define PRINT_F_SPACE (1 << 2)
+#define PRINT_F_NUM (1 << 3)
+#define PRINT_F_ZERO (1 << 4)
+#define PRINT_F_QUOTE (1 << 5)
+#define PRINT_F_UP (1 << 6)
+#define PRINT_F_UNSIGNED (1 << 7)
+#define PRINT_F_TYPE_G (1 << 8)
+#define PRINT_F_TYPE_E (1 << 9)
+
+/* Conversion flags. */
+#define PRINT_C_CHAR 1
+#define PRINT_C_SHORT 2
+#define PRINT_C_LONG 3
+#define PRINT_C_LLONG 4
+#define PRINT_C_LDOUBLE 5
+#define PRINT_C_SIZE 6
+#define PRINT_C_PTRDIFF 7
+#define PRINT_C_INTMAX 8
+
+#ifndef MAX
+#define MAX(x, y) ((x >= y) ? x : y)
+#endif /* !defined(MAX) */
+#ifndef CHARTOINT
+#define CHARTOINT(ch) (ch - '0')
+#endif /* !defined(CHARTOINT) */
+#ifndef ISDIGIT
+#define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9')
+#endif /* !defined(ISDIGIT) */
+#ifndef ISNAN
+#define ISNAN(x) (x != x)
+#endif /* !defined(ISNAN) */
+#ifndef ISINF
+#define ISINF(x) (x != 0.0 && x + x == x)
+#endif /* !defined(ISINF) */
+
+#ifdef OUTCHAR
+#undef OUTCHAR
+#endif /* defined(OUTCHAR) */
+#define OUTCHAR(str, len, size, ch) \
+do { \
+ if (len + 1 < size) \
+ str[len] = ch; \
+ (len)++; \
+} while (/* CONSTCOND */ 0)
+
+static void fmtstr(char *, size_t *, size_t, const char *, int, int, int);
+static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int);
+static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *);
+static void printsep(char *, size_t *, size_t);
+static int getnumsep(int);
+static int getexponent(LDOUBLE);
+static int convert(UINTMAX_T, char *, size_t, int, int);
+static UINTMAX_T cast(LDOUBLE);
+static UINTMAX_T myround(LDOUBLE);
+static LDOUBLE mypow10(int);
+
+int
+util_vsnprintf(char *str, size_t size, const char *format, va_list args)
+{
+ LDOUBLE fvalue;
+ INTMAX_T value;
+ unsigned char cvalue;
+ const char *strvalue;
+ INTMAX_T *intmaxptr;
+ PTRDIFF_T *ptrdiffptr;
+ SSIZE_T *sizeptr;
+ LLONG *llongptr;
+ long int *longptr;
+ int *intptr;
+ short int *shortptr;
+ signed char *charptr;
+ size_t len = 0;
+ int overflow = 0;
+ int base = 0;
+ int cflags = 0;
+ int flags = 0;
+ int width = 0;
+ int precision = -1;
+ int state = PRINT_S_DEFAULT;
+ char ch = *format++;
+
+ /*
+ * C99 says: "If `n' is zero, nothing is written, and `s' may be a null
+ * pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer
+ * even if a size larger than zero was specified. At least NetBSD's
+ * snprintf(3) does the same, as well as other versions of this file.
+ * (Though some of these versions will write to a non-NULL buffer even
+ * if a size of zero was specified, which violates the standard.)
+ */
+ if (str == NULL && size != 0)
+ size = 0;
+
+ while (ch != '\0')
+ switch (state) {
+ case PRINT_S_DEFAULT:
+ if (ch == '%')
+ state = PRINT_S_FLAGS;
+ else
+ OUTCHAR(str, len, size, ch);
+ ch = *format++;
+ break;
+ case PRINT_S_FLAGS:
+ switch (ch) {
+ case '-':
+ flags |= PRINT_F_MINUS;
+ ch = *format++;
+ break;
+ case '+':
+ flags |= PRINT_F_PLUS;
+ ch = *format++;
+ break;
+ case ' ':
+ flags |= PRINT_F_SPACE;
+ ch = *format++;
+ break;
+ case '#':
+ flags |= PRINT_F_NUM;
+ ch = *format++;
+ break;
+ case '0':
+ flags |= PRINT_F_ZERO;
+ ch = *format++;
+ break;
+ case '\'': /* SUSv2 flag (not in C99). */
+ flags |= PRINT_F_QUOTE;
+ ch = *format++;
+ break;
+ default:
+ state = PRINT_S_WIDTH;
+ break;
+ }
+ break;
+ case PRINT_S_WIDTH:
+ if (ISDIGIT(ch)) {
+ ch = CHARTOINT(ch);
+ if (width > (INT_MAX - ch) / 10) {
+ overflow = 1;
+ goto out;
+ }
+ width = 10 * width + ch;
+ ch = *format++;
+ } else if (ch == '*') {
+ /*
+ * C99 says: "A negative field width argument is
+ * taken as a `-' flag followed by a positive
+ * field width." (7.19.6.1, 5)
+ */
+ if ((width = va_arg(args, int)) < 0) {
+ flags |= PRINT_F_MINUS;
+ width = -width;
+ }
+ ch = *format++;
+ state = PRINT_S_DOT;
+ } else
+ state = PRINT_S_DOT;
+ break;
+ case PRINT_S_DOT:
+ if (ch == '.') {
+ state = PRINT_S_PRECISION;
+ ch = *format++;
+ } else
+ state = PRINT_S_MOD;
+ break;
+ case PRINT_S_PRECISION:
+ if (precision == -1)
+ precision = 0;
+ if (ISDIGIT(ch)) {
+ ch = CHARTOINT(ch);
+ if (precision > (INT_MAX - ch) / 10) {
+ overflow = 1;
+ goto out;
+ }
+ precision = 10 * precision + ch;
+ ch = *format++;
+ } else if (ch == '*') {
+ /*
+ * C99 says: "A negative precision argument is
+ * taken as if the precision were omitted."
+ * (7.19.6.1, 5)
+ */
+ if ((precision = va_arg(args, int)) < 0)
+ precision = -1;
+ ch = *format++;
+ state = PRINT_S_MOD;
+ } else
+ state = PRINT_S_MOD;
+ break;
+ case PRINT_S_MOD:
+ switch (ch) {
+ case 'h':
+ ch = *format++;
+ if (ch == 'h') { /* It's a char. */
+ ch = *format++;
+ cflags = PRINT_C_CHAR;
+ } else
+ cflags = PRINT_C_SHORT;
+ break;
+ case 'l':
+ ch = *format++;
+ if (ch == 'l') { /* It's a long long. */
+ ch = *format++;
+ cflags = PRINT_C_LLONG;
+ } else
+ cflags = PRINT_C_LONG;
+ break;
+ case 'L':
+ cflags = PRINT_C_LDOUBLE;
+ ch = *format++;
+ break;
+ case 'j':
+ cflags = PRINT_C_INTMAX;
+ ch = *format++;
+ break;
+ case 't':
+ cflags = PRINT_C_PTRDIFF;
+ ch = *format++;
+ break;
+ case 'z':
+ cflags = PRINT_C_SIZE;
+ ch = *format++;
+ break;
+ }
+ state = PRINT_S_CONV;
+ break;
+ case PRINT_S_CONV:
+ switch (ch) {
+ case 'd':
+ /* FALLTHROUGH */
+ case 'i':
+ switch (cflags) {
+ case PRINT_C_CHAR:
+ value = (signed char)va_arg(args, int);
+ break;
+ case PRINT_C_SHORT:
+ value = (short int)va_arg(args, int);
+ break;
+ case PRINT_C_LONG:
+ value = va_arg(args, long int);
+ break;
+ case PRINT_C_LLONG:
+ value = va_arg(args, LLONG);
+ break;
+ case PRINT_C_SIZE:
+ value = va_arg(args, SSIZE_T);
+ break;
+ case PRINT_C_INTMAX:
+ value = va_arg(args, INTMAX_T);
+ break;
+ case PRINT_C_PTRDIFF:
+ value = va_arg(args, PTRDIFF_T);
+ break;
+ default:
+ value = va_arg(args, int);
+ break;
+ }
+ fmtint(str, &len, size, value, 10, width,
+ precision, flags);
+ break;
+ case 'X':
+ flags |= PRINT_F_UP;
+ /* FALLTHROUGH */
+ case 'x':
+ base = 16;
+ /* FALLTHROUGH */
+ case 'o':
+ if (base == 0)
+ base = 8;
+ /* FALLTHROUGH */
+ case 'u':
+ if (base == 0)
+ base = 10;
+ flags |= PRINT_F_UNSIGNED;
+ switch (cflags) {
+ case PRINT_C_CHAR:
+ value = (unsigned char)va_arg(args,
+ unsigned int);
+ break;
+ case PRINT_C_SHORT:
+ value = (unsigned short int)va_arg(args,
+ unsigned int);
+ break;
+ case PRINT_C_LONG:
+ value = va_arg(args, unsigned long int);
+ break;
+ case PRINT_C_LLONG:
+ value = va_arg(args, ULLONG);
+ break;
+ case PRINT_C_SIZE:
+ value = va_arg(args, size_t);
+ break;
+ case PRINT_C_INTMAX:
+ value = va_arg(args, UINTMAX_T);
+ break;
+ case PRINT_C_PTRDIFF:
+ value = va_arg(args, UPTRDIFF_T);
+ break;
+ default:
+ value = va_arg(args, unsigned int);
+ break;
+ }
+ fmtint(str, &len, size, value, base, width,
+ precision, flags);
+ break;
+ case 'A':
+ /* Not yet supported, we'll use "%F". */
+ /* FALLTHROUGH */
+ case 'F':
+ flags |= PRINT_F_UP;
+ case 'a':
+ /* Not yet supported, we'll use "%f". */
+ /* FALLTHROUGH */
+ case 'f':
+ if (cflags == PRINT_C_LDOUBLE)
+ fvalue = va_arg(args, LDOUBLE);
+ else
+ fvalue = va_arg(args, double);
+ fmtflt(str, &len, size, fvalue, width,
+ precision, flags, &overflow);
+ if (overflow)
+ goto out;
+ break;
+ case 'E':
+ flags |= PRINT_F_UP;
+ /* FALLTHROUGH */
+ case 'e':
+ flags |= PRINT_F_TYPE_E;
+ if (cflags == PRINT_C_LDOUBLE)
+ fvalue = va_arg(args, LDOUBLE);
+ else
+ fvalue = va_arg(args, double);
+ fmtflt(str, &len, size, fvalue, width,
+ precision, flags, &overflow);
+ if (overflow)
+ goto out;
+ break;
+ case 'G':
+ flags |= PRINT_F_UP;
+ /* FALLTHROUGH */
+ case 'g':
+ flags |= PRINT_F_TYPE_G;
+ if (cflags == PRINT_C_LDOUBLE)
+ fvalue = va_arg(args, LDOUBLE);
+ else
+ fvalue = va_arg(args, double);
+ /*
+ * If the precision is zero, it is treated as
+ * one (cf. C99: 7.19.6.1, 8).
+ */
+ if (precision == 0)
+ precision = 1;
+ fmtflt(str, &len, size, fvalue, width,
+ precision, flags, &overflow);
+ if (overflow)
+ goto out;
+ break;
+ case 'c':
+ cvalue = (unsigned char)va_arg(args, int);
+ OUTCHAR(str, len, size, cvalue);
+ break;
+ case 's':
+ strvalue = va_arg(args, char *);
+ fmtstr(str, &len, size, strvalue, width,
+ precision, flags);
+ break;
+ case 'p':
+ /*
+ * C99 says: "The value of the pointer is
+ * converted to a sequence of printing
+ * characters, in an implementation-defined
+ * manner." (C99: 7.19.6.1, 8)
+ */
+ if ((strvalue = va_arg(args, void *)) == NULL)
+ /*
+ * We use the glibc format. BSD prints
+ * "0x0", SysV "0".
+ */
+ fmtstr(str, &len, size, "(nil)", width,
+ -1, flags);
+ else {
+ /*
+ * We use the BSD/glibc format. SysV
+ * omits the "0x" prefix (which we emit
+ * using the PRINT_F_NUM flag).
+ */
+ flags |= PRINT_F_NUM;
+ flags |= PRINT_F_UNSIGNED;
+ fmtint(str, &len, size,
+ (UINTPTR_T)strvalue, 16, width,
+ precision, flags);
+ }
+ break;
+ case 'n':
+ switch (cflags) {
+ case PRINT_C_CHAR:
+ charptr = va_arg(args, signed char *);
+ *charptr = (signed char)len;
+ break;
+ case PRINT_C_SHORT:
+ shortptr = va_arg(args, short int *);
+ *shortptr = (short int)len;
+ break;
+ case PRINT_C_LONG:
+ longptr = va_arg(args, long int *);
+ *longptr = (long int)len;
+ break;
+ case PRINT_C_LLONG:
+ llongptr = va_arg(args, LLONG *);
+ *llongptr = (LLONG)len;
+ break;
+ case PRINT_C_SIZE:
+ /*
+ * C99 says that with the "z" length
+ * modifier, "a following `n' conversion
+ * specifier applies to a pointer to a
+ * signed integer type corresponding to
+ * size_t argument." (7.19.6.1, 7)
+ */
+ sizeptr = va_arg(args, SSIZE_T *);
+ *sizeptr = len;
+ break;
+ case PRINT_C_INTMAX:
+ intmaxptr = va_arg(args, INTMAX_T *);
+ *intmaxptr = len;
+ break;
+ case PRINT_C_PTRDIFF:
+ ptrdiffptr = va_arg(args, PTRDIFF_T *);
+ *ptrdiffptr = len;
+ break;
+ default:
+ intptr = va_arg(args, int *);
+ *intptr = (int)len;
+ break;
+ }
+ break;
+ case '%': /* Print a "%" character verbatim. */
+ OUTCHAR(str, len, size, ch);
+ break;
+ default: /* Skip other characters. */
+ break;
+ }
+ ch = *format++;
+ state = PRINT_S_DEFAULT;
+ base = cflags = flags = width = 0;
+ precision = -1;
+ break;
+ }
+out:
+ if (len < size)
+ str[len] = '\0';
+ else if (size > 0)
+ str[size - 1] = '\0';
+
+ if (overflow || len >= INT_MAX) {
+ return -1;
+ }
+ return (int)len;
+}
+
+static void
+fmtstr(char *str, size_t *len, size_t size, const char *value, int width,
+ int precision, int flags)
+{
+ int padlen, strln; /* Amount to pad. */
+ int noprecision = (precision == -1);
+
+ if (value == NULL) /* We're forgiving. */
+ value = "(null)";
+
+ /* If a precision was specified, don't read the string past it. */
+ for (strln = 0; value[strln] != '\0' &&
+ (noprecision || strln < precision); strln++)
+ continue;
+
+ if ((padlen = width - strln) < 0)
+ padlen = 0;
+ if (flags & PRINT_F_MINUS) /* Left justify. */
+ padlen = -padlen;
+
+ while (padlen > 0) { /* Leading spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ padlen--;
+ }
+ while (*value != '\0' && (noprecision || precision-- > 0)) {
+ OUTCHAR(str, *len, size, *value);
+ value++;
+ }
+ while (padlen < 0) { /* Trailing spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ padlen++;
+ }
+}
+
+static void
+fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width,
+ int precision, int flags)
+{
+ UINTMAX_T uvalue;
+ char iconvert[MAX_CONVERT_LENGTH];
+ char sign = 0;
+ char hexprefix = 0;
+ int spadlen = 0; /* Amount to space pad. */
+ int zpadlen = 0; /* Amount to zero pad. */
+ int pos;
+ int separators = (flags & PRINT_F_QUOTE);
+ int noprecision = (precision == -1);
+
+ if (flags & PRINT_F_UNSIGNED)
+ uvalue = value;
+ else {
+ uvalue = (value >= 0) ? value : -value;
+ if (value < 0)
+ sign = '-';
+ else if (flags & PRINT_F_PLUS) /* Do a sign. */
+ sign = '+';
+ else if (flags & PRINT_F_SPACE)
+ sign = ' ';
+ }
+
+ pos = convert(uvalue, iconvert, sizeof(iconvert), base,
+ flags & PRINT_F_UP);
+
+ if (flags & PRINT_F_NUM && uvalue != 0) {
+ /*
+ * C99 says: "The result is converted to an `alternative form'.
+ * For `o' conversion, it increases the precision, if and only
+ * if necessary, to force the first digit of the result to be a
+ * zero (if the value and precision are both 0, a single 0 is
+ * printed). For `x' (or `X') conversion, a nonzero result has
+ * `0x' (or `0X') prefixed to it." (7.19.6.1, 6)
+ */
+ switch (base) {
+ case 8:
+ if (precision <= pos)
+ precision = pos + 1;
+ break;
+ case 16:
+ hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x';
+ break;
+ }
+ }
+
+ if (separators) /* Get the number of group separators we'll print. */
+ separators = getnumsep(pos);
+
+ zpadlen = precision - pos - separators;
+ spadlen = width /* Minimum field width. */
+ - separators /* Number of separators. */
+ - MAX(precision, pos) /* Number of integer digits. */
+ - ((sign != 0) ? 1 : 0) /* Will we print a sign? */
+ - ((hexprefix != 0) ? 2 : 0); /* Will we print a prefix? */
+
+ if (zpadlen < 0)
+ zpadlen = 0;
+ if (spadlen < 0)
+ spadlen = 0;
+
+ /*
+ * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
+ * ignored. For `d', `i', `o', `u', `x', and `X' conversions, if a
+ * precision is specified, the `0' flag is ignored." (7.19.6.1, 6)
+ */
+ if (flags & PRINT_F_MINUS) /* Left justify. */
+ spadlen = -spadlen;
+ else if (flags & PRINT_F_ZERO && noprecision) {
+ zpadlen += spadlen;
+ spadlen = 0;
+ }
+ while (spadlen > 0) { /* Leading spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ spadlen--;
+ }
+ if (sign != 0) /* Sign. */
+ OUTCHAR(str, *len, size, sign);
+ if (hexprefix != 0) { /* A "0x" or "0X" prefix. */
+ OUTCHAR(str, *len, size, '0');
+ OUTCHAR(str, *len, size, hexprefix);
+ }
+ while (zpadlen > 0) { /* Leading zeros. */
+ OUTCHAR(str, *len, size, '0');
+ zpadlen--;
+ }
+ while (pos > 0) { /* The actual digits. */
+ pos--;
+ OUTCHAR(str, *len, size, iconvert[pos]);
+ if (separators > 0 && pos > 0 && pos % 3 == 0)
+ printsep(str, len, size);
+ }
+ while (spadlen < 0) { /* Trailing spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ spadlen++;
+ }
+}
+
+static void
+fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width,
+ int precision, int flags, int *overflow)
+{
+ LDOUBLE ufvalue;
+ UINTMAX_T intpart;
+ UINTMAX_T fracpart;
+ UINTMAX_T mask;
+ const char *infnan = NULL;
+ char iconvert[MAX_CONVERT_LENGTH];
+ char fconvert[MAX_CONVERT_LENGTH];
+ char econvert[4]; /* "e-12" (without nul-termination). */
+ char esign = 0;
+ char sign = 0;
+ int leadfraczeros = 0;
+ int exponent = 0;
+ int emitpoint = 0;
+ int omitzeros = 0;
+ int omitcount = 0;
+ int padlen = 0;
+ int epos = 0;
+ int fpos = 0;
+ int ipos = 0;
+ int separators = (flags & PRINT_F_QUOTE);
+ int estyle = (flags & PRINT_F_TYPE_E);
+#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
+ struct lconv *lc = localeconv();
+#endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
+
+ /*
+ * AIX' man page says the default is 0, but C99 and at least Solaris'
+ * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX
+ * defaults to 6.
+ */
+ if (precision == -1)
+ precision = 6;
+
+ if (fvalue < 0.0)
+ sign = '-';
+ else if (flags & PRINT_F_PLUS) /* Do a sign. */
+ sign = '+';
+ else if (flags & PRINT_F_SPACE)
+ sign = ' ';
+
+ if (ISNAN(fvalue))
+ infnan = (flags & PRINT_F_UP) ? "NAN" : "nan";
+ else if (ISINF(fvalue))
+ infnan = (flags & PRINT_F_UP) ? "INF" : "inf";
+
+ if (infnan != NULL) {
+ if (sign != 0)
+ iconvert[ipos++] = sign;
+ while (*infnan != '\0')
+ iconvert[ipos++] = *infnan++;
+ fmtstr(str, len, size, iconvert, width, ipos, flags);
+ return;
+ }
+
+ /* "%e" (or "%E") or "%g" (or "%G") conversion. */
+ if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) {
+ if (flags & PRINT_F_TYPE_G) {
+ /*
+ * For "%g" (and "%G") conversions, the precision
+ * specifies the number of significant digits, which
+ * includes the digits in the integer part. The
+ * conversion will or will not be using "e-style" (like
+ * "%e" or "%E" conversions) depending on the precision
+ * and on the exponent. However, the exponent can be
+ * affected by rounding the converted value, so we'll
+ * leave this decision for later. Until then, we'll
+ * assume that we're going to do an "e-style" conversion
+ * (in order to get the exponent calculated). For
+ * "e-style", the precision must be decremented by one.
+ */
+ precision--;
+ /*
+ * For "%g" (and "%G") conversions, trailing zeros are
+ * removed from the fractional portion of the result
+ * unless the "#" flag was specified.
+ */
+ if (!(flags & PRINT_F_NUM))
+ omitzeros = 1;
+ }
+ exponent = getexponent(fvalue);
+ estyle = 1;
+ }
+
+again:
+ /*
+ * Sorry, we only support 9, 19, or 38 digits (that is, the number of
+ * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value
+ * minus one) past the decimal point due to our conversion method.
+ */
+ switch (sizeof(UINTMAX_T)) {
+ case 16:
+ if (precision > 38)
+ precision = 38;
+ break;
+ case 8:
+ if (precision > 19)
+ precision = 19;
+ break;
+ default:
+ if (precision > 9)
+ precision = 9;
+ break;
+ }
+
+ ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue;
+ if (estyle) /* We want exactly one integer digit. */
+ ufvalue /= mypow10(exponent);
+
+ if ((intpart = cast(ufvalue)) == UINTMAX_MAX) {
+ *overflow = 1;
+ return;
+ }
+
+ /*
+ * Factor of ten with the number of digits needed for the fractional
+ * part. For example, if the precision is 3, the mask will be 1000.
+ */
+ mask = (UINTMAX_T)mypow10(precision);
+ /*
+ * We "cheat" by converting the fractional part to integer by
+ * multiplying by a factor of ten.
+ */
+ if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) {
+ /*
+ * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000
+ * (because precision = 3). Now, myround(1000 * 0.99962) will
+ * return 1000. So, the integer part must be incremented by one
+ * and the fractional part must be set to zero.
+ */
+ intpart++;
+ fracpart = 0;
+ if (estyle && intpart == 10) {
+ /*
+ * The value was rounded up to ten, but we only want one
+ * integer digit if using "e-style". So, the integer
+ * part must be set to one and the exponent must be
+ * incremented by one.
+ */
+ intpart = 1;
+ exponent++;
+ }
+ }
+
+ /*
+ * Now that we know the real exponent, we can check whether or not to
+ * use "e-style" for "%g" (and "%G") conversions. If we don't need
+ * "e-style", the precision must be adjusted and the integer and
+ * fractional parts must be recalculated from the original value.
+ *
+ * C99 says: "Let P equal the precision if nonzero, 6 if the precision
+ * is omitted, or 1 if the precision is zero. Then, if a conversion
+ * with style `E' would have an exponent of X:
+ *
+ * - if P > X >= -4, the conversion is with style `f' (or `F') and
+ * precision P - (X + 1).
+ *
+ * - otherwise, the conversion is with style `e' (or `E') and precision
+ * P - 1." (7.19.6.1, 8)
+ *
+ * Note that we had decremented the precision by one.
+ */
+ if (flags & PRINT_F_TYPE_G && estyle &&
+ precision + 1 > exponent && exponent >= -4) {
+ precision -= exponent;
+ estyle = 0;
+ goto again;
+ }
+
+ if (estyle) {
+ if (exponent < 0) {
+ exponent = -exponent;
+ esign = '-';
+ } else
+ esign = '+';
+
+ /*
+ * Convert the exponent. The sizeof(econvert) is 4. So, the
+ * econvert buffer can hold e.g. "e+99" and "e-99". We don't
+ * support an exponent which contains more than two digits.
+ * Therefore, the following stores are safe.
+ */
+ epos = convert(exponent, econvert, 2, 10, 0);
+ /*
+ * C99 says: "The exponent always contains at least two digits,
+ * and only as many more digits as necessary to represent the
+ * exponent." (7.19.6.1, 8)
+ */
+ if (epos == 1)
+ econvert[epos++] = '0';
+ econvert[epos++] = esign;
+ econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e';
+ }
+
+ /* Convert the integer part and the fractional part. */
+ ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0);
+ if (fracpart != 0) /* convert() would return 1 if fracpart == 0. */
+ fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0);
+
+ leadfraczeros = precision - fpos;
+
+ if (omitzeros) {
+ if (fpos > 0) /* Omit trailing fractional part zeros. */
+ while (omitcount < fpos && fconvert[omitcount] == '0')
+ omitcount++;
+ else { /* The fractional part is zero, omit it completely. */
+ omitcount = precision;
+ leadfraczeros = 0;
+ }
+ precision -= omitcount;
+ }
+
+ /*
+ * Print a decimal point if either the fractional part is non-zero
+ * and/or the "#" flag was specified.
+ */
+ if (precision > 0 || flags & PRINT_F_NUM)
+ emitpoint = 1;
+ if (separators) /* Get the number of group separators we'll print. */
+ separators = getnumsep(ipos);
+
+ padlen = width /* Minimum field width. */
+ - ipos /* Number of integer digits. */
+ - epos /* Number of exponent characters. */
+ - precision /* Number of fractional digits. */
+ - separators /* Number of group separators. */
+ - (emitpoint ? 1 : 0) /* Will we print a decimal point? */
+ - ((sign != 0) ? 1 : 0); /* Will we print a sign character? */
+
+ if (padlen < 0)
+ padlen = 0;
+
+ /*
+ * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
+ * ignored." (7.19.6.1, 6)
+ */
+ if (flags & PRINT_F_MINUS) /* Left justifty. */
+ padlen = -padlen;
+ else if (flags & PRINT_F_ZERO && padlen > 0) {
+ if (sign != 0) { /* Sign. */
+ OUTCHAR(str, *len, size, sign);
+ sign = 0;
+ }
+ while (padlen > 0) { /* Leading zeros. */
+ OUTCHAR(str, *len, size, '0');
+ padlen--;
+ }
+ }
+ while (padlen > 0) { /* Leading spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ padlen--;
+ }
+ if (sign != 0) /* Sign. */
+ OUTCHAR(str, *len, size, sign);
+ while (ipos > 0) { /* Integer part. */
+ ipos--;
+ OUTCHAR(str, *len, size, iconvert[ipos]);
+ if (separators > 0 && ipos > 0 && ipos % 3 == 0)
+ printsep(str, len, size);
+ }
+ if (emitpoint) { /* Decimal point. */
+#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
+ if (lc->decimal_point != NULL && *lc->decimal_point != '\0')
+ OUTCHAR(str, *len, size, *lc->decimal_point);
+ else /* We'll always print some decimal point character. */
+#endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
+ OUTCHAR(str, *len, size, '.');
+ }
+ while (leadfraczeros > 0) { /* Leading fractional part zeros. */
+ OUTCHAR(str, *len, size, '0');
+ leadfraczeros--;
+ }
+ while (fpos > omitcount) { /* The remaining fractional part. */
+ fpos--;
+ OUTCHAR(str, *len, size, fconvert[fpos]);
+ }
+ while (epos > 0) { /* Exponent. */
+ epos--;
+ OUTCHAR(str, *len, size, econvert[epos]);
+ }
+ while (padlen < 0) { /* Trailing spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ padlen++;
+ }
+}
+
+static void
+printsep(char *str, size_t *len, size_t size)
+{
+#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
+ struct lconv *lc = localeconv();
+ int i;
+
+ if (lc->thousands_sep != NULL)
+ for (i = 0; lc->thousands_sep[i] != '\0'; i++)
+ OUTCHAR(str, *len, size, lc->thousands_sep[i]);
+ else
+#endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
+ OUTCHAR(str, *len, size, ',');
+}
+
+static int
+getnumsep(int digits)
+{
+ int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3;
+#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
+ int strln;
+ struct lconv *lc = localeconv();
+
+ /* We support an arbitrary separator length (including zero). */
+ if (lc->thousands_sep != NULL) {
+ for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++)
+ continue;
+ separators *= strln;
+ }
+#endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
+ return separators;
+}
+
+static int
+getexponent(LDOUBLE value)
+{
+ LDOUBLE tmp = (value >= 0.0) ? value : -value;
+ int exponent = 0;
+
+ /*
+ * We check for 99 > exponent > -99 in order to work around possible
+ * endless loops which could happen (at least) in the second loop (at
+ * least) if we're called with an infinite value. However, we checked
+ * for infinity before calling this function using our ISINF() macro, so
+ * this might be somewhat paranoid.
+ */
+ while (tmp < 1.0 && tmp > 0.0 && --exponent > -99)
+ tmp *= 10;
+ while (tmp >= 10.0 && ++exponent < 99)
+ tmp /= 10;
+
+ return exponent;
+}
+
+static int
+convert(UINTMAX_T value, char *buf, size_t size, int base, int caps)
+{
+ const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef";
+ size_t pos = 0;
+
+ /* We return an unterminated buffer with the digits in reverse order. */
+ do {
+ buf[pos++] = digits[value % base];
+ value /= base;
+ } while (value != 0 && pos < size);
+
+ return (int)pos;
+}
+
+static UINTMAX_T
+cast(LDOUBLE value)
+{
+ UINTMAX_T result;
+
+ /*
+ * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be
+ * represented exactly as an LDOUBLE value (but is less than LDBL_MAX),
+ * it may be increased to the nearest higher representable value for the
+ * comparison (cf. C99: 6.3.1.4, 2). It might then equal the LDOUBLE
+ * value although converting the latter to UINTMAX_T would overflow.
+ */
+ if (value >= UINTMAX_MAX)
+ return UINTMAX_MAX;
+
+ result = (UINTMAX_T)value;
+ /*
+ * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to
+ * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates
+ * the standard). Sigh.
+ */
+ return (result <= value) ? result : result - 1;
+}
+
+static UINTMAX_T
+myround(LDOUBLE value)
+{
+ UINTMAX_T intpart = cast(value);
+
+ return ((value -= intpart) < 0.5) ? intpart : intpart + 1;
+}
+
+static LDOUBLE
+mypow10(int exponent)
+{
+ LDOUBLE result = 1;
+
+ while (exponent > 0) {
+ result *= 10;
+ exponent--;
+ }
+ while (exponent < 0) {
+ result /= 10;
+ exponent++;
+ }
+ return result;
+}
+#endif /* !HAVE_VSNPRINTF */
+
+#if !HAVE_VASPRINTF
+#if NEED_MYMEMCPY
+void *
+mymemcpy(void *dst, void *src, size_t len)
+{
+ const char *from = src;
+ char *to = dst;
+
+ /* No need for optimization, we use this only to replace va_copy(3). */
+ while (len-- > 0)
+ *to++ = *from++;
+ return dst;
+}
+#endif /* NEED_MYMEMCPY */
+
+int
+util_vasprintf(char **ret, const char *format, va_list ap)
+{
+ size_t size;
+ int len;
+ va_list aq;
+
+ VA_COPY(aq, ap);
+ len = vsnprintf(NULL, 0, format, aq);
+ VA_END_COPY(aq);
+ if (len < 0 || (*ret = malloc(size = len + 1)) == NULL)
+ return -1;
+ return vsnprintf(*ret, size, format, ap);
+}
+#endif /* !HAVE_VASPRINTF */
+
+#if !HAVE_SNPRINTF
+#if HAVE_STDARG_H
+int
+util_snprintf(char *str, size_t size, const char *format, ...)
+#else
+int
+util_snprintf(va_alist) va_dcl
+#endif /* HAVE_STDARG_H */
+{
+#if !HAVE_STDARG_H
+ char *str;
+ size_t size;
+ char *format;
+#endif /* HAVE_STDARG_H */
+ va_list ap;
+ int len;
+
+ VA_START(ap, format);
+ VA_SHIFT(ap, str, char *);
+ VA_SHIFT(ap, size, size_t);
+ VA_SHIFT(ap, format, const char *);
+ len = vsnprintf(str, size, format, ap);
+ va_end(ap);
+ return len;
+}
+#endif /* !HAVE_SNPRINTF */
+
+#if !HAVE_ASPRINTF
+#if HAVE_STDARG_H
+int
+util_asprintf(char **ret, const char *format, ...)
+#else
+int
+util_asprintf(va_alist) va_dcl
+#endif /* HAVE_STDARG_H */
+{
+#if !HAVE_STDARG_H
+ char **ret;
+ char *format;
+#endif /* HAVE_STDARG_H */
+ va_list ap;
+ int len;
+
+ VA_START(ap, format);
+ VA_SHIFT(ap, ret, char **);
+ VA_SHIFT(ap, format, const char *);
+ len = vasprintf(ret, format, ap);
+ va_end(ap);
+ return len;
+}
+#endif /* !HAVE_ASPRINTF */
+#else /* Dummy declaration to avoid empty translation unit warnings. */
+int main(void);
+#endif /* !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || [...] */
+
+
+/* vim: set joinspaces textwidth=80: */
diff --git a/mesalib/src/gallium/auxiliary/util/u_vbuf.c b/mesalib/src/gallium/auxiliary/util/u_vbuf.c
index f6da91203..5b0e26e30 100644
--- a/mesalib/src/gallium/auxiliary/util/u_vbuf.c
+++ b/mesalib/src/gallium/auxiliary/util/u_vbuf.c
@@ -808,6 +808,8 @@ static void u_vbuf_get_minmax_index(struct pipe_context *pipe,
}
default:
assert(0);
+ *out_min_index = 0;
+ *out_max_index = 0;
}
if (transfer) {