25#include "internal/error.h"
30#include "internal/symbol.h"
35#define BIT_DIGITS(N) (((N)*146)/485 + 1)
37static char *fmt_setup(
char*,
size_t,
int,
int,
int,
int);
38static char *ruby_ultoa(
unsigned long val,
char *endp,
int base,
int octzero);
41sign_bits(
int base,
const char *p)
47 if (*p ==
'X') c =
'F';
69 int cr = ENC_CODERANGE(result);\
70 while ((l) >= bsiz - blen) {\
72 if (bsiz<0) rb_raise(rb_eArgError, "too big specifier");\
74 rb_str_resize(result, bsiz);\
75 ENC_CODERANGE_SET(result, cr);\
76 buf = RSTRING_PTR(result);\
79#define PUSH(s, l) do { \
84#define PUSH_(s, l) do { \
85 memcpy(&buf[blen], (s), (l));\
89#define FILL(c, l) do { \
95#define FILL_(c, l) do { \
96 memset(&buf[blen], (c), (l));\
100#define GETARG() (nextvalue != Qundef ? nextvalue : \
103#define GETNEXTARG() ( \
104 check_next_arg(posarg, nextarg), \
105 (posarg = nextarg++, GETNTHARG(posarg)))
107#define GETPOSARG(n) ( \
108 check_pos_arg(posarg, (n)), \
109 (posarg = -1, GETNTHARG(n)))
111#define GETNTHARG(nth) \
112 (((nth) >= argc) ? (rb_raise(rb_eArgError, "too few arguments"), 0) : argv[(nth)])
114#define CHECKNAMEARG(name, len, enc) ( \
115 check_name_arg(posarg, name, len, enc), \
118#define GETNUM(n, val) \
119 (!(p = get_num(p, end, enc, &(n))) ? \
120 rb_raise(rb_eArgError, #val " too big") : (void)0)
122#define GETASTER(val) do { \
127 tmp = GETPOSARG(n); \
130 tmp = GETNEXTARG(); \
133 (val) = NUM2INT(tmp); \
144 if (INT_MAX - (*p -
'0') < next_n)
156check_next_arg(
int posarg,
int nextarg)
167check_pos_arg(
int posarg,
int n)
196 if (*hash !=
Qundef)
return *hash;
204 return (*hash = tmp);
216 enum {default_float_precision = 6};
225 int width, prec, flags =
FNONE;
234#define CHECK_FOR_WIDTH(f) \
235 if ((f) & FWIDTH) { \
236 rb_raise(rb_eArgError, "width given twice"); \
238 if ((f) & FPREC0) { \
239 rb_raise(rb_eArgError, "width after precision"); \
241#define CHECK_FOR_FLAGS(f) \
242 if ((f) & FWIDTH) { \
243 rb_raise(rb_eArgError, "flag after width"); \
245 if ((f) & FPREC0) { \
246 rb_raise(rb_eArgError, "flag after precision"); \
262 memset(
buf, 0, bsiz);
265 for (; p < end; p++) {
270 for (
t = p;
t < end && *
t !=
'%';
t++) ;
326 case '1':
case '2':
case '3':
case '4':
327 case '5':
case '6':
case '7':
case '8':
case '9':
331 if (nextvalue !=
Qundef) {
346 const char *start = p;
347 char term = (*p ==
'<') ?
'>' :
'}';
350 for (; p < end && *p !=
term; ) {
356#if SIZEOF_INT < SIZEOF_SIZE_T
357 if ((
size_t)(p - start) >= INT_MAX) {
358 const int message_limit = 20;
361 "too long name (%"PRIuSIZE" bytes) - %.*s...%c",
362 (
size_t)(p - start - 2),
len, start,
term);
365 len = (
int)(p - start + 1);
376 if (nextvalue ==
Qundef) {
383 if (
NIL_P(nextvalue)) {
387 if (
term ==
'}')
goto format_s;
429 if (flags !=
FNONE) {
462 else if ((flags &
FMINUS)) {
466 if (width > 1)
FILL(
' ', width-1);
469 if (width > 1)
FILL(
' ', width-1);
505 if ((flags&
FPREC) && (prec < slen)) {
512 if ((flags&
FWIDTH) && (width > slen)) {
548 int sign = 0, dots = 0;
551 int base, bignum = 0;
624 int numbits =
ffs(base)-1;
628 if (INT_MAX-1 < numdigits)
643 else if (flags &
FPLUS) {
647 else if (flags &
FSPACE) {
662 if (numdigits == 0 ||
663 ((abs_nlz_bits != (
size_t)(numbits-1) ||
665 (!bignum ? v < 0 : BIGNUM_NEGATIVE_P(val))))
685 else if (flags &
FPLUS) {
689 else if (flags &
FSPACE) {
693 s = ruby_ultoa((
unsigned long)v, nbuf +
sizeof(nbuf), 10, 0);
694 len = (
int)(nbuf +
sizeof(nbuf) - s);
706 else if (flags &
FPLUS) {
710 else if (flags &
FSPACE) {
725 while ((c = (
int)(
unsigned char)*pp) != 0) {
734 else if (
len == 1 && *s ==
'0') {
736 if (flags &
FPREC) prec--;
738 else if ((flags &
FPREC) && (prec >
len)) {
742 else if (
len == 1 && *s ==
'0') {
754 if (!
prefix && prec == 0 &&
len == 1 && *s ==
'0')
len = 0;
763 if (sc)
PUSH(&sc, 1);
768 if (dots)
PUSH(
"..", 2);
771 if (!sign && valsign < 0) {
772 char c = sign_bits(base, p);
788 int sign = (flags&
FPLUS) ? 1 : 0, zero = 0;
802 if (!(flags&
FPREC)) prec = default_float_precision;
810 else if (BIGNUM_NEGATIVE_P(
num)) {
819 else if (prec >= 0) {
824 if (prec >=
len)
len = prec + 1;
827 fill = width >
len ? width -
len : 0;
832 if (sign || (flags&
FSPACE)) {
833 buf[blen++] = sign > 0 ?
'+' : sign < 0 ?
'-' :
' ';
852 else if (prec >
len) {
859 if (fill && (flags&
FMINUS)) {
892 if (!
isnan(fval) && fval < 0.0)
895 sign = (flags &
FPLUS) ?
'+' :
' ';
898 if ((flags &
FWIDTH) && need < width)
904 buf[blen - need--] = sign;
909 buf[blen - elen - 1] = sign;
917 char *fmt = fmt_setup(fbuf,
sizeof(fbuf), *p, flags, width, prec);
934 if (posarg >= 0 && nextarg <
argc) {
935 const char *mesg =
"too many arguments for format string";
945fmt_setup(
char *
buf,
size_t size,
int c,
int flags,
int width,
int prec)
952 buf = ruby_ultoa(prec,
buf, 10, 0);
957 buf = ruby_ultoa(width,
buf, 10, 0);
970#define FILE rb_printf_buffer
971#define __sbuf rb_printf_sbuf
972#define __sFILE rb_printf_sfile
977#if SIZEOF_LONG < SIZEOF_VOIDP
978# if SIZEOF_LONG_LONG == SIZEOF_VOIDP
979# define _HAVE_SANE_QUAD_
981# define quad_t LONG_LONG
982# define u_quad_t unsigned LONG_LONG
984#elif SIZEOF_LONG != SIZEOF_LONG_LONG && SIZEOF_LONG_LONG == 8
985# define _HAVE_SANE_QUAD_
986# define quad_t LONG_LONG
987# define u_quad_t unsigned LONG_LONG
989#define FLOATING_POINT 1
990#define BSD__dtoa ruby_dtoa
991#define BSD__hdtoa ruby_hdtoa
992#ifdef RUBY_PRI_VALUE_MARK
993# define PRI_EXTRA_MARK RUBY_PRI_VALUE_MARK
995#define lower_hexdigits (ruby_hexdigits+0)
996#define upper_hexdigits (ruby_hexdigits+16)
1000ruby_ultoa(
unsigned long val,
char *endp,
int base,
int flags)
1003 int octzero = flags &
FSHARP;
1004 return BSD__ultoa(val, endp, base, octzero, xdigs);
1007static int ruby_do_vsnprintf(
char *
str,
size_t n,
const char *fmt, va_list ap);
1012 if (
str && (ssize_t)n < 1)
1014 return ruby_do_vsnprintf(
str, n, fmt, ap);
1018ruby_do_vsnprintf(
char *
str,
size_t n,
const char *fmt, va_list ap)
1024 f._bf._base =
f._p = (
unsigned char *)
str;
1025 f._bf._size =
f._w =
str ? (n - 1) : 0;
1026 f.vwrite = BSD__sfvwrite;
1028 ret = BSD_vfprintf(&
f, fmt, ap);
1030#if SIZEOF_SIZE_T > SIZEOF_INT
1031 if (n > INT_MAX)
return INT_MAX;
1042 if (
str && (ssize_t)n < 1)
1046 ret = ruby_do_vsnprintf(
str, n, fmt, ap);
1057ruby__sfvwrite(
register rb_printf_buffer *fp,
register struct __suio *uio)
1061 char *
buf = (
char*)fp->_p;
1065 if (
RBASIC(result)->klass) {
1070#if SIZE_MAX > LONG_MAX
1083 fp->_p = (
unsigned char *)
buf;
1089ruby__sfvextra(rb_printf_buffer *fp,
size_t valsize,
void *valp,
long *sz,
int sign)
1095 if (valsize !=
sizeof(
VALUE))
return 0;
1096 value = *(
VALUE *)valp;
1097 if (
RBASIC(result)->klass) {
1101 if (RB_TYPE_P(value,
T_CLASS)) {
1102# define LITERAL(str) (*sz = rb_strlen_lit(str), str)
1131 if (sign ==
' ') value = QUOTE(value);
1142 *(
volatile VALUE *)valp = value;
1154#define f buffer.base
1169 f._bf._base = (
unsigned char *)result;
1171 RBASIC_CLEAR_CLASS(result);
1172 f.vwrite = ruby__sfvwrite;
1173 f.vextra = ruby__sfvextra;
1175 BSD_vfprintf(&
f, fmt, ap);
1189 va_start(ap, format);
1208 va_start(ap, format);
1219#define f buffer.base
1227 f._bf._base = (
unsigned char *)
str;
1228 f._p = (
unsigned char *)RSTRING_END(
str);
1230 RBASIC_CLEAR_CLASS(
str);
1231 f.vwrite = ruby__sfvwrite;
1232 f.vextra = ruby__sfvextra;
1234 BSD_vfprintf(&
f, fmt, ap);
1235 RBASIC_SET_CLASS_RAW(
str, klass);
1247 va_start(ap, format);
int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
VALUE rb_str_to_inum(VALUE str, int base, int badcheck)
size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
int rb_absint_singlebit_p(VALUE val)
VALUE rb_big2str(VALUE x, int base)
VALUE rb_dbl2big(double d)
const char ruby_digitmap[]
VALUE rb_big_uminus(VALUE x)
#define MUL_OVERFLOW_INT_P(a, b)
VALUE rb_int_positive_pow(long x, unsigned long y)
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
unsigned int rb_enc_codepoint_len(const char *p, const char *e, int *len_p, rb_encoding *enc)
rb_encoding * rb_enc_get(VALUE obj)
rb_encoding * rb_enc_check(VALUE str1, VALUE str2)
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
rb_encoding * rb_enc_compatible(VALUE str1, VALUE str2)
int rb_enc_toupper(int c, rb_encoding *enc)
int rb_enc_codelen(int c, rb_encoding *enc)
char str[HTML_ESCAPE_MAX_LEN+1]
#define RSTRING_LEN(string)
#define RSTRING_PTR(string)
void rb_raise(VALUE exc, const char *fmt,...)
void rb_warn(const char *fmt,...)
VALUE rb_Float(VALUE)
Equivalent to Kernel#Float in Ruby.
VALUE rb_cNilClass
NilClass class.
VALUE rb_Integer(VALUE)
Equivalent to Kernel#Integer in Ruby.
VALUE rb_cFalseClass
FalseClass class.
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
VALUE rb_cTrueClass
TrueClass class.
unsigned short prefix[65536]
VALUE rb_hash_default_value(VALUE hash, VALUE key)
VALUE rb_check_hash_type(VALUE hash)
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
#define ENC_CODERANGE_7BIT
#define rb_enc_mbcput(c, buf, enc)
#define ECONV_UNDEF_REPLACE
#define ENC_CODERANGE(obj)
#define ENC_CODERANGE_UNKNOWN
VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts)
#define ECONV_INVALID_REPLACE
#define rb_enc_isdigit(c, enc)
#define rb_enc_isprint(c, enc)
#define rb_enc_mbminlen(enc)
VALUE rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc)
long rb_enc_strlen(const char *, const char *, rb_encoding *)
#define ENC_CODERANGE_BROKEN
long rb_str_coderange_scan_restartable(const char *, const char *, rb_encoding *, int *)
#define rb_enc_right_char_head(s, p, e, enc)
#define ENC_CODERANGE_SET(obj, cr)
char * rb_enc_nth(const char *, const char *, long, rb_encoding *)
Thin wrapper to ruby/config.h.
#define INTEGER_PACK_BIG_ENDIAN
#define INTEGER_PACK_2COMP
VALUE rb_rational_num(VALUE rat)
VALUE rb_rational_den(VALUE rat)
VALUE rb_str_resize(VALUE, long)
#define rb_str_new(str, len)
void rb_str_set_len(VALUE, long)
void rb_str_modify(VALUE)
VALUE rb_str_buf_new(long)
VALUE rb_check_string_type(VALUE)
VALUE rb_str_inspect(VALUE)
VALUE rb_obj_as_string(VALUE)
size_t rb_str_capacity(VALUE)
Internal header for Hash.
Internal header for Numeric.
VALUE rb_int2str(VALUE num, int base)
VALUE rb_int_idiv(VALUE x, VALUE y)
VALUE rb_int_plus(VALUE x, VALUE y)
VALUE rb_int_mul(VALUE x, VALUE y)
Internal header for Object.
int rb_str_symname_p(VALUE)
VALUE rb_str_tmp_frozen_acquire(VALUE str)
void rb_str_tmp_frozen_release(VALUE str, VALUE tmp)
VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc)
Internal header corresponding util.c.
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
Internal header for Math.
#define MEMCPY(p1, p2, type, n)
#define RSTRING_GETMEM(str, ptrvar, lenvar)
#define StringValueCStr(v)
#define RB_INTEGER_TYPE_P(obj)
Internal header for ASAN / MSAN / etc.
VALUE rb_str_catf(VALUE str, const char *format,...)
VALUE rb_sprintf(const char *format,...)
VALUE rb_str_format(int argc, const VALUE *argv, VALUE fmt)
VALUE rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
VALUE rb_f_sprintf(int argc, const VALUE *argv)
VALUE rb_enc_sprintf(rb_encoding *enc, const char *format,...)
#define CHECK_FOR_FLAGS(f)
VALUE rb_str_vcatf(VALUE str, const char *fmt, va_list ap)
int ruby_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
VALUE rb_vsprintf(const char *fmt, va_list ap)
#define CHECK_FOR_WIDTH(f)
#define CHECKNAMEARG(name, len, enc)
int ruby_snprintf(char *str, size_t n, char const *fmt,...)
size_t strlen(const char *)
if((ID)(DISPID) nameid !=nameid)