aboutsummaryrefslogtreecommitdiffstats
path: root/sprintf.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-07-23 01:02:18 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-07-23 01:02:18 +0000
commit6524f34a2688436249d111a3456a097c7111722c (patch)
treef9c83bf95a7873e01e38ff396a8bc5490b61162c /sprintf.c
parente6a02b93747266925fd536a30715352bf2c60c07 (diff)
downloadruby-6524f34a2688436249d111a3456a097c7111722c.tar.gz
* sprintf.c (rb_vsprintf, rb_sprintf): new functions return new String,
using missing/vsnprintf.c. [ruby-dev:26580] * missing/vsnprintf.c: made the output changeable. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8825 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'sprintf.c')
-rw-r--r--sprintf.c117
1 files changed, 109 insertions, 8 deletions
diff --git a/sprintf.c b/sprintf.c
index 59195450bc..bdb24c1da0 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -15,6 +15,13 @@
#include "ruby.h"
#include <ctype.h>
#include <math.h>
+#ifdef HAVE_STDARG_PROTOTYPES
+#include <stdarg.h>
+#define va_init_list(a,b) va_start(a,b)
+#else
+#include <varargs.h>
+#define va_init_list(a,b) va_start(a)
+#endif
#define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */
@@ -96,6 +103,12 @@ sign_bits(base, p)
blen += (l);\
} while (0)
+#define FILL(c, l) do { \
+ CHECK(l);\
+ memset(&buf[blen], c, l);\
+ blen += (l);\
+} while (0)
+
#define GETARG() (nextvalue != Qundef ? nextvalue : \
posarg < 0 ? \
(rb_raise(rb_eArgError, "unnumbered(%d) mixed with numbered", nextarg), 0) : \
@@ -230,9 +243,17 @@ sign_bits(base, p)
VALUE
rb_f_sprintf(argc, argv)
int argc;
- VALUE *argv;
+ const VALUE *argv;
{
+ return rb_str_format(argc - 1, argv + 1, GETNTHARG(0));
+}
+
+VALUE
+rb_str_format(argc, argv, fmt)
+ int argc;
+ const VALUE *argv;
VALUE fmt;
+{
const char *p, *end;
char *buf;
int blen, bsiz;
@@ -246,7 +267,8 @@ rb_f_sprintf(argc, argv)
VALUE tmp;
VALUE str;
- fmt = GETNTHARG(0);
+ ++argc;
+ --argv;
if (OBJ_TAINTED(fmt)) tainted = 1;
StringValue(fmt);
fmt = rb_str_new4(fmt);
@@ -380,13 +402,14 @@ rb_f_sprintf(argc, argv)
VALUE val = GETARG();
char c;
- if (!(flags & FMINUS))
- while (--width > 0)
- PUSH(" ", 1);
c = NUM2INT(val) & 0xff;
- PUSH(&c, 1);
- while (--width > 0)
- PUSH(" ", 1);
+ if (!(flags & FWIDTH)) {
+ PUSH(&c, 1);
+ }
+ else {
+ FILL(' ', width);
+ buf[blen - ((flags & FMINUS) ? width : 1)] = c;
+ }
}
break;
@@ -807,3 +830,81 @@ fmt_setup(buf, c, flags, width, prec)
*buf++ = c;
*buf = '\0';
}
+
+#undef FILE
+#define FILE rb_printf_buffer
+#define __sbuf rb_printf_sbuf
+#define __sFILE rb_printf_sfile
+#undef feof
+#undef ferror
+#undef fileno
+#include "missing/vsnprintf.c"
+
+static int
+ruby__sfvwrite(fp, uio)
+ register rb_printf_buffer *fp;
+ register struct __suio *uio;
+{
+ struct __siov *iov;
+ VALUE result = (VALUE)fp->_bf._base;
+ char *buf = fp->_p;
+ size_t len, n;
+ int blen = buf - RSTRING(result)->ptr, bsiz = fp->_w;
+
+ if (RBASIC(result)->klass) {
+ rb_raise(rb_eRuntimeError, "rb_vsprintf reentered");
+ }
+ if ((len = uio->uio_resid) == 0)
+ return 0;
+ CHECK(len);
+ fp->_w = bsiz;
+ for (iov = uio->uio_iov; len > 0; ++iov) {
+ MEMCPY(buf, iov->iov_base, char, n = iov->iov_len);
+ buf += n;
+ len -= n;
+ }
+ fp->_p = (unsigned char *)buf;
+ return 0;
+}
+
+VALUE
+rb_vsprintf(fmt, ap)
+ const char *fmt;
+ va_list ap;
+{
+ rb_printf_buffer f;
+ VALUE result;
+
+ f._flags = __SWR | __SSTR;
+ f._bf._size = 0;
+ f._w = 120;
+ result = rb_str_buf_new(f._w);
+ f._bf._base = (unsigned char *)result;
+ f._p = (unsigned char *)RSTRING(result)->ptr;
+ RBASIC(result)->klass = 0;
+ f.vwrite = ruby__sfvwrite;
+ BSD_vfprintf(&f, fmt, ap);
+ RBASIC(result)->klass = rb_cString;
+ rb_str_resize(result, (char *)f._p - RSTRING(result)->ptr);
+
+ return result;
+}
+
+VALUE
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_sprintf(const char *format, ...)
+#else
+ruby_sprintf(format, va_alist)
+ const char *format;
+ va_dcl
+#endif
+{
+ VALUE result;
+ va_list ap;
+
+ va_init_list(ap, format);
+ result = rb_vsprintf(format, ap);
+ va_end(ap);
+
+ return result;
+}