diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-05-24 14:36:54 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-05-24 14:36:54 +0000 |
commit | ce8e2d54049ddbe4947ed90295b1b4d11ebaaa52 (patch) | |
tree | b06c84e6da75e1a9821f6decc192299e5be8101c | |
parent | 60e8cd2e686efd3a965cb43ae5963ce31fc90d71 (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-- | ChangeLog | 5 | ||||
-rw-r--r-- | error.c | 4 | ||||
-rw-r--r-- | include/ruby/ruby.h | 4 | ||||
-rw-r--r-- | sprintf.c | 47 | ||||
-rw-r--r-- | vm_insnhelper.c | 5 | ||||
-rw-r--r-- | vsnprintf.c | 33 |
6 files changed, 88 insertions, 10 deletions
@@ -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. @@ -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 "" @@ -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); |