summaryrefslogtreecommitdiff
path: root/vsnprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'vsnprintf.c')
-rw-r--r--vsnprintf.c127
1 files changed, 46 insertions, 81 deletions
diff --git a/vsnprintf.c b/vsnprintf.c
index 929572a999..ecd5573dd5 100644
--- a/vsnprintf.c
+++ b/vsnprintf.c
@@ -95,29 +95,18 @@
# ifdef HAVE_LIMITS_H
# include <limits.h>
# else
- /* assuming 32bit(2's compliment) long */
+ /* assuming 32bit(2's complement) long */
# define LONG_MAX 2147483647
# endif
# endif
#endif
-#if defined(__hpux) && !defined(__GNUC__) && !defined(__STDC__)
-#define const
-#endif
-
#if defined(sgi)
#undef __const
#define __const
#endif /* People who don't like const sys_error */
#include <stddef.h>
-#if defined(__hpux) && !defined(__GNUC__) || defined(__DECC)
-#include <string.h>
-#endif
-
-#if !defined(__CYGWIN32__) && defined(__hpux) && !defined(__GNUC__)
-#include <stdlib.h>
-#endif
#ifndef NULL
#define NULL 0
@@ -127,12 +116,6 @@
# include <errno.h>
#endif
-#if __GNUC__ >= 3
-#define UNINITIALIZED_VAR(x) x = x
-#else
-#define UNINITIALIZED_VAR(x) x
-#endif
-
/*
* NB: to fit things in six character monocase externals, the stdio
* code uses the prefix `__s' for stdio objects, typically followed
@@ -167,11 +150,13 @@ struct __sbuf {
* _ub, _up, and _ur are used when ungetc() pushes back more characters
* than fit in the current _bf, or when ungetc() pushes back a character
* that does not match the previous one in _bf. When this happens,
- * _ub._base becomes non-nil (i.e., a stream has ungetc() data iff
+ * _ub._base becomes non-nil (i.e., a stream has ungetc() data if and only if
* _ub._base!=NULL) and _up and _ur save the current values of _p and _r.
*
* NB: see WARNING above before changing the layout of this structure!
*/
+struct __suio;
+
typedef struct __sFILE {
unsigned char *_p; /* current position in (some) buffer */
#if 0
@@ -181,9 +166,11 @@ typedef struct __sFILE {
short _flags; /* flags, below; this FILE is free if 0 */
short _file; /* fileno, if Unix descriptor, else -1 */
struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */
+#if 0
size_t _lbfsize; /* 0 or -_bf._size, for inline putc */
- int (*vwrite)(/* struct __sFILE*, struct __suio * */);
- char *(*vextra)(/* struct __sFILE*, size_t, void*, long*, int */);
+#endif
+ int (*vwrite)(struct __sFILE*, struct __suio *);
+ const char *(*vextra)(struct __sFILE*, size_t, void*, long*, int);
} FILE;
@@ -200,7 +187,7 @@ typedef struct __sFILE {
#define __SSTR 0x0200 /* this is an sprintf/snprintf string */
#define __SOPT 0x0400 /* do fseek() optimisation */
#define __SNPT 0x0800 /* do not do fseek() optimisation */
-#define __SOFF 0x1000 /* set iff _offset is in fact correct */
+#define __SOFF 0x1000 /* set if and only if _offset is in fact correct */
#define __SMOD 0x2000 /* true => fgetln modified _p text */
@@ -253,9 +240,7 @@ BSD__sfvwrite(register FILE *fp, register struct __suio *uio)
if ((len = uio->uio_resid) == 0)
return (0);
-#ifndef __hpux
#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#endif
#define COPY(n) (void)memcpy((void *)fp->_p, (void *)p, (size_t)(n))
iov = uio->uio_iov;
@@ -516,6 +501,12 @@ static int exponent(char *, int, int);
#endif /* FLOATING_POINT */
+#ifndef lower_hexdigits
+# define lower_hexdigits "0123456789abcdef"
+#endif
+#ifndef upper_hexdigits
+# define upper_hexdigits "0123456789ABCDEF"
+#endif
/*
* Flags used during conversion.
@@ -533,9 +524,13 @@ static int exponent(char *, int, int);
#define SHORTINT 0x040 /* short integer */
#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
#define FPT 0x100 /* Floating point number */
+ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(static ssize_t BSD_vfprintf(FILE *fp, const char *fmt0, va_list ap));
static ssize_t
BSD_vfprintf(FILE *fp, const char *fmt0, va_list ap)
{
+#ifdef PRI_EXTRA_MARK
+ const int PRI_EXTRA_MARK_LEN = rb_strlen_lit(PRI_EXTRA_MARK);
+#endif
register const char *fmt; /* format string */
register int ch; /* character from fmt */
register int n; /* handy integer (short term usage) */
@@ -555,9 +550,9 @@ BSD_vfprintf(FILE *fp, const char *fmt0, va_list ap)
int fprec = 0; /* floating point precision */
char expstr[7]; /* buffer for exponent string */
#endif
- u_long UNINITIALIZED_VAR(ulval); /* integer arguments %[diouxX] */
+ u_long MAYBE_UNUSED(ulval) = 0; /* integer arguments %[diouxX] */
#ifdef _HAVE_SANE_QUAD_
- u_quad_t UNINITIALIZED_VAR(uqval); /* %q integers */
+ u_quad_t MAYBE_UNUSED(uqval) = 0; /* %q integers */
#endif /* _HAVE_SANE_QUAD_ */
int base; /* base for [diouxX] conversion */
int dprec; /* a copy of prec if [diouxX], 0 otherwise */
@@ -642,7 +637,7 @@ BSD_vfprintf(FILE *fp, const char *fmt0, va_list ap)
flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \
(u_long)va_arg(ap, u_int))
- /* optimise fprintf(stderr) (and other unbuffered Unix files) */
+ /* optimize fprintf(stderr) (and other unbuffered Unix files) */
if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
fp->_file >= 0)
return (BSD__sbprintf(fp, fmt0, ap));
@@ -812,7 +807,20 @@ reswitch: switch (ch) {
#else
# define INTPTR_FLAG 0
#endif
- if (fp->vextra && (flags & INTPTR_MASK) == INTPTR_FLAG) {
+#ifdef PRI_EXTRA_MARK
+# define IS_PRI_EXTRA_MARK(s) \
+ (PRI_EXTRA_MARK_LEN < 1 || \
+ (*(s) == PRI_EXTRA_MARK[0] && \
+ (PRI_EXTRA_MARK_LEN == 1 || \
+ strncmp((s)+1, &PRI_EXTRA_MARK[1], \
+ PRI_EXTRA_MARK_LEN-1) == 0)))
+#else
+# define PRI_EXTRA_MARK_LEN 0
+# define IS_PRI_EXTRA_MARK(s) 1
+#endif
+ if (fp->vextra && (flags & INTPTR_MASK) == INTPTR_FLAG &&
+ IS_PRI_EXTRA_MARK(fmt)) {
+ fmt += PRI_EXTRA_MARK_LEN;
FLUSH();
#if defined _HAVE_SANE_QUAD_ && SIZEOF_VOIDP == SIZEOF_LONG_LONG
uqval = va_arg(ap, u_quad_t);
@@ -985,7 +993,7 @@ fp_begin: _double = va_arg(ap, double);
#endif /* _HAVE_SANE_QUAD_ */
#endif
base = 16;
- xdigs = "0123456789abcdef";
+ xdigs = lower_hexdigits;
ch = 'x';
goto nosign;
case 's':
@@ -1023,10 +1031,10 @@ fp_begin: _double = va_arg(ap, double);
base = 10;
goto nosign;
case 'X':
- xdigs = "0123456789ABCDEF";
+ xdigs = upper_hexdigits;
goto hex;
case 'x':
- xdigs = "0123456789abcdef";
+ xdigs = lower_hexdigits;
hex:
#ifdef _HAVE_SANE_QUAD_
if (flags & QUADINT)
@@ -1060,6 +1068,7 @@ number: if ((dprec = prec) >= 0)
* explicit precision of zero is no characters.''
* -- ANSI X3J11
*/
+ cp = ebuf;
#ifdef _HAVE_SANE_QUAD_
if (flags & QUADINT) {
if (uqval != 0 || prec != 0)
@@ -1102,11 +1111,11 @@ number: if ((dprec = prec) >= 0)
*/
fieldsz = size;
long_len:
+ realsz = dprec > fieldsz ? dprec : fieldsz;
if (sign)
- fieldsz++;
+ realsz++;
if (flags & HEXPREFIX)
- fieldsz += 2;
- realsz = dprec > fieldsz ? dprec : fieldsz;
+ realsz += 2;
/* right-adjusting blank padding */
if ((flags & (LADJUST|ZEROPAD)) == 0)
@@ -1128,10 +1137,6 @@ long_len:
/* leading zeroes from decimal precision */
PAD_L(dprec - fieldsz, zeroes);
- if (sign)
- fieldsz--;
- if (flags & HEXPREFIX)
- fieldsz -= 2;
/* the string or number proper */
#ifdef FLOATING_POINT
@@ -1235,14 +1240,14 @@ cvt(double value, int ndigits, int flags, char *sign, int *decpt, int ch, int *l
if (value < 0) {
value = -value;
*sign = '-';
- } else if (value == 0.0 && 1.0/value < 0) {
+ } else if (value == 0.0 && signbit(value)) {
*sign = '-';
} else {
*sign = '\000';
}
if (ch == 'a' || ch =='A') {
digits = BSD__hdtoa(value,
- ch == 'a' ? "0123456789abcdef" : "0123456789ABCDEF",
+ ch == 'a' ? lower_hexdigits : upper_hexdigits,
ndigits, decpt, &dsgn, &rve);
}
else {
@@ -1250,8 +1255,8 @@ cvt(double value, int ndigits, int flags, char *sign, int *decpt, int ch, int *l
}
buf[0] = 0; /* rve - digits may be 0 */
memcpy(buf, digits, rve - digits);
- xfree(digits);
rve = buf + (rve - digits);
+ free(digits);
digits = buf;
if (flags & ALT) { /* Print trailing zeros */
bp = digits + ndigits;
@@ -1296,43 +1301,3 @@ exponent(char *p0, int exp, int fmtch)
return (int)(p - p0);
}
#endif /* FLOATING_POINT */
-
-int
-ruby_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
-{
- int ret;
- FILE f;
-
- if ((int)n < 1)
- return (EOF);
- f._flags = __SWR | __SSTR;
- f._bf._base = f._p = (unsigned char *)str;
- f._bf._size = f._w = n - 1;
- f.vwrite = BSD__sfvwrite;
- f.vextra = 0;
- ret = (int)BSD_vfprintf(&f, fmt, ap);
- *f._p = 0;
- return (ret);
-}
-
-int
-ruby_snprintf(char *str, size_t n, char const *fmt, ...)
-{
- int ret;
- va_list ap;
- FILE f;
-
- if ((int)n < 1)
- return (EOF);
-
- va_start(ap, fmt);
- f._flags = __SWR | __SSTR;
- f._bf._base = f._p = (unsigned char *)str;
- f._bf._size = f._w = n - 1;
- f.vwrite = BSD__sfvwrite;
- f.vextra = 0;
- ret = (int)BSD_vfprintf(&f, fmt, ap);
- *f._p = 0;
- va_end(ap);
- return (ret);
-}