summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-05-24 14:36:54 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-05-24 14:36:54 +0000
commitce8e2d54049ddbe4947ed90295b1b4d11ebaaa52 (patch)
treeb06c84e6da75e1a9821f6decc192299e5be8101c
parent60e8cd2e686efd3a965cb43ae5963ce31fc90d71 (diff)
Feature #5896
* vsnprintf.c (BSD_vfprintf): [EXPERIMENTAL] object representation in rb_enc_vsprintf(). [Feature #5896] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35776 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog5
-rw-r--r--error.c4
-rw-r--r--include/ruby/ruby.h4
-rw-r--r--sprintf.c47
-rw-r--r--vm_insnhelper.c5
-rw-r--r--vsnprintf.c33
6 files changed, 88 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index a416473f4b..9b84740666 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Thu May 24 23:36:51 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * vsnprintf.c (BSD_vfprintf): [EXPERIMENTAL] object representation in
+ rb_enc_vsprintf(). [Feature #5896]
+
Thu May 24 15:33:01 2012 Koichi Sasada <ko1@atdot.net>
* vm_method.c (rb_method_defined_by): removed.
diff --git a/error.c b/error.c
index 88c4c226cd..2bca03f0da 100644
--- a/error.c
+++ b/error.c
@@ -1116,9 +1116,9 @@ nometh_err_args(VALUE self)
void
rb_invalid_str(const char *str, const char *type)
{
- volatile VALUE s = rb_str_inspect(rb_str_new2(str));
+ VALUE s = rb_str_inspect(rb_str_new2(str));
- rb_raise(rb_eArgError, "invalid value for %s: %s", type, RSTRING_PTR(s));
+ rb_raise(rb_eArgError, "invalid value for %s: %"PRIsVALUE, type, s);
}
/*
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 6909bf3d7a..06c2a7fdd4 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -120,18 +120,18 @@ typedef char ruby_check_sizeof_voidp[SIZEOF_VOIDP == sizeof(void*) ? 1 : -1];
#if defined PRIdPTR && !defined PRI_VALUE_PREFIX
#define PRIdVALUE PRIdPTR
-#define PRIiVALUE PRIiPTR
#define PRIoVALUE PRIoPTR
#define PRIuVALUE PRIuPTR
#define PRIxVALUE PRIxPTR
#define PRIXVALUE PRIXPTR
+#define PRIsVALUE PRIiPTR
#else
#define PRIdVALUE PRI_VALUE_PREFIX"d"
-#define PRIiVALUE PRI_VALUE_PREFIX"i"
#define PRIoVALUE PRI_VALUE_PREFIX"o"
#define PRIuVALUE PRI_VALUE_PREFIX"u"
#define PRIxVALUE PRI_VALUE_PREFIX"x"
#define PRIXVALUE PRI_VALUE_PREFIX"X"
+#define PRIsVALUE PRI_VALUE_PREFIX"i"
#endif
#ifndef PRI_VALUE_PREFIX
# define PRI_VALUE_PREFIX ""
diff --git a/sprintf.c b/sprintf.c
index 5927c252dd..d705566fdf 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -1146,6 +1146,11 @@ fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec)
#define BSD__hdtoa ruby_hdtoa
#include "vsnprintf.c"
+typedef struct {
+ rb_printf_buffer base;
+ volatile VALUE value;
+} rb_printf_buffer_extra;
+
static int
ruby__sfvwrite(register rb_printf_buffer *fp, register struct __suio *uio)
{
@@ -1172,10 +1177,41 @@ ruby__sfvwrite(register rb_printf_buffer *fp, register struct __suio *uio)
return 0;
}
+static char *
+ruby__sfvextra(rb_printf_buffer *fp, size_t valsize, void *valp, long *sz)
+{
+ VALUE value, result = (VALUE)fp->_bf._base;
+ rb_encoding *enc;
+ char *cp;
+
+ if (valsize != sizeof(VALUE)) return 0;
+ value = *(VALUE *)valp;
+ if (RBASIC(result)->klass) {
+ rb_raise(rb_eRuntimeError, "rb_vsprintf reentered");
+ }
+ value = rb_obj_as_string(value);
+ enc = rb_enc_compatible(result, value);
+ if (enc) {
+ rb_enc_associate(result, enc);
+ }
+ else {
+ enc = rb_enc_get(result);
+ value = rb_str_conv_enc_opts(value, rb_enc_get(value), enc,
+ ECONV_UNDEF_REPLACE|ECONV_INVALID_REPLACE,
+ Qnil);
+ *(volatile VALUE *)valp = value;
+ }
+ StringValueCStr(value);
+ RSTRING_GETMEM(value, cp, *sz);
+ ((rb_printf_buffer_extra *)fp)->value = value;
+ return cp;
+}
+
VALUE
rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
{
- rb_printf_buffer f;
+ rb_printf_buffer_extra buffer;
+#define f buffer.base
VALUE result;
f._flags = __SWR | __SSTR;
@@ -1194,9 +1230,12 @@ rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
f._p = (unsigned char *)RSTRING_PTR(result);
RBASIC(result)->klass = 0;
f.vwrite = ruby__sfvwrite;
+ f.vextra = ruby__sfvextra;
+ buffer.value = 0;
BSD_vfprintf(&f, fmt, ap);
RBASIC(result)->klass = rb_cString;
rb_str_resize(result, (char *)f._p - RSTRING_PTR(result));
+#undef f
return result;
}
@@ -1236,7 +1275,8 @@ rb_sprintf(const char *format, ...)
VALUE
rb_str_vcatf(VALUE str, const char *fmt, va_list ap)
{
- rb_printf_buffer f;
+ rb_printf_buffer_extra buffer;
+#define f buffer.base
VALUE klass;
StringValue(str);
@@ -1249,9 +1289,12 @@ rb_str_vcatf(VALUE str, const char *fmt, va_list ap)
klass = RBASIC(str)->klass;
RBASIC(str)->klass = 0;
f.vwrite = ruby__sfvwrite;
+ f.vextra = ruby__sfvextra;
+ buffer.value = 0;
BSD_vfprintf(&f, fmt, ap);
RBASIC(str)->klass = klass;
rb_str_resize(str, (char *)f._p - RSTRING_PTR(str));
+#undef f
return str;
}
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index e67e0b9cd4..8a21f21ec0 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -154,10 +154,9 @@ unknown_keyword_error(const rb_iseq_t *iseq, VALUE hash)
}
keys = rb_funcall(hash, rb_intern("keys"), 0, 0);
if (!RB_TYPE_P(keys, T_ARRAY)) rb_raise(rb_eArgError, "unknown keyword");
- msg = RARRAY_LEN(keys) == 1 ? "unknown keyword: %s" : "unknown keywords: %s";
+ msg = RARRAY_LEN(keys) == 1 ? "" : "s";
keys = rb_funcall(keys, rb_intern("join"), 1, sep);
- RB_GC_GUARD(keys);
- rb_raise(rb_eArgError, msg, RSTRING_PTR(keys));
+ rb_raise(rb_eArgError, "unknown keyword%s: %"PRIsVALUE, msg, keys);
}
void
diff --git a/vsnprintf.c b/vsnprintf.c
index 5df4ffae6d..bb6a0e139a 100644
--- a/vsnprintf.c
+++ b/vsnprintf.c
@@ -183,6 +183,7 @@ typedef struct __sFILE {
struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */
size_t _lbfsize; /* 0 or -_bf._size, for inline putc */
int (*vwrite)(/* struct __sFILE*, struct __suio * */);
+ char *(*vextra)(/* struct __sFILE*, size_t, void*, long* */);
} FILE;
@@ -793,11 +794,39 @@ reswitch: switch (ch) {
size = 1;
sign = '\0';
break;
+ case 'i':
+#ifdef _HAVE_SANE_QUAD_
+# define INTPTR_MASK (QUADINT|LONGINT|SHORTINT)
+#else
+# define INTPTR_MASK (LONGINT|SHORTINT)
+#endif
+#if defined _HAVE_SANE_QUAD_ && SIZEOF_VOIDP == SIZEOF_LONG_LONG
+# define INTPTR_FLAG QUADINT
+#elif SIZEOF_VOIDP == SIZEOF_LONG
+# define INTPTR_FLAG LONGINT
+#else
+# define INTPTR_FLAG 0
+#endif
+ if (fp->vextra && (flags & INTPTR_MASK) == INTPTR_FLAG) {
+ FLUSH();
+#if defined _HAVE_SANE_QUAD_ && SIZEOF_VOIDP == SIZEOF_LONG_LONG
+ uqval = va_arg(ap, u_quad_t);
+ cp = (*fp->vextra)(fp, sizeof(uqval), &uqval, &fieldsz);
+#else
+ ulval = va_arg(ap, u_long);
+ cp = (*fp->vextra)(fp, sizeof(ulval), &ulval, &fieldsz);
+#endif
+ if (!cp) goto error;
+ if (prec < 0) goto long_len;
+ size = fieldsz < prec ? (int)fieldsz : prec;
+ break;
+ }
+ goto decimal;
case 'D':
flags |= LONGINT;
/*FALLTHROUGH*/
case 'd':
- case 'i':
+ decimal:
#ifdef _HAVE_SANE_QUAD_
if (flags & QUADINT) {
uqval = va_arg(ap, quad_t);
@@ -1269,6 +1298,7 @@ ruby_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
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);
@@ -1289,6 +1319,7 @@ ruby_snprintf(char *str, size_t n, char const *fmt, ...)
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);