renamed moo_sprintfmtfromstack() to moo_strfmtcallstack().

refactored related functions
This commit is contained in:
hyunghwan.chung 2019-05-29 01:35:13 +00:00
parent 3f274d74b7
commit 054313b96c
8 changed files with 741 additions and 18 deletions

View File

@ -285,6 +285,7 @@ class(#character) String(Array)
method(#primitive) strlen.
method(#primitive,#variadic) strfmt().
method(#primitive,#variadic,#class) format(fmt).
}
## -------------------------------------------------------------------------------

View File

@ -3637,6 +3637,29 @@ static moo_pfrc_t pf_error_as_string (moo_t* moo, moo_mod_t* mod, moo_ooi_t narg
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_string_format (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
{
/* ignore the receiver. the first argument is the format string. */
/*moo_oop_t rcv;
rcv = MOO_STACK_GETRCV(moo, nargs);
MOO_PF_CHECK_RCV (moo, MOO_OBJ_IS_CHAR_POINTER(rcv));*/
if (moo_strfmtcallstack(moo, nargs, 0) <= -1)
{
MOO_STACK_SETRETTOERRNUM (moo, nargs);
}
else
{
moo_oop_t str;
str = moo_makestring(moo, moo->sprintf.xbuf.ptr, moo->sprintf.xbuf.len);
if (!str) return MOO_PF_FAILURE;
MOO_STACK_SETRET (moo, nargs, str);
}
return MOO_PF_SUCCESS;
}
static moo_pfrc_t pf_strfmt (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
{
moo_oop_t rcv;
@ -3644,7 +3667,7 @@ static moo_pfrc_t pf_strfmt (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs)
rcv = MOO_STACK_GETRCV(moo, nargs);
MOO_PF_CHECK_RCV (moo, MOO_OBJ_IS_CHAR_POINTER(rcv));
if (moo_sprintfmtst(moo, nargs) <= -1)
if (moo_strfmtcallstack(moo, nargs, 1) <= -1)
{
MOO_STACK_SETRETTOERRNUM (moo, nargs);
}
@ -3870,6 +3893,7 @@ static pf_t pftab[] =
{ "SmallPointer_putUint64", { moo_pf_smptr_put_uint64, 2, 2 } },
{ "SmallPointer_putUint8", { moo_pf_smptr_put_uint8, 2, 2 } },
{ "String_format", { pf_string_format, 1, MA } },
{ "String_strfmt", { pf_strfmt, 0, MA } },
{ "String_strlen", { pf_strlen, 0, 0 } },

View File

@ -1759,3 +1759,688 @@ moo_ooi_t moo_logufmt (moo_t* moo, moo_bitmask_t mask, const moo_uch_t* fmt, ...
}
return (x <= -1)? -1: fo.count;
}
/* --------------------------------------------------------------------------
* SUPPORT FOR FORMATTED OUTPUT TO BE USED BY BUILTIN PRIMITIVE FUNCTIONS
* -------------------------------------------------------------------------- */
static int sprint_bcs (moo_fmtout_t* fmtout, const moo_bch_t* ptr, moo_oow_t len)
{
moo_t* moo = (moo_t*)fmtout->ctx;
moo_oow_t unused, oolen, blen;
unused = moo->sprintf.xbuf.capa - moo->sprintf.xbuf.len;
#if defined(MOO_OOCH_IS_UCH)
blen = len;
moo_conv_bchars_to_uchars_with_cmgr (ptr, &blen, MOO_NULL, &oolen, moo->cmgr, 1);
#else
oolen = len;
#endif
if (oolen > unused)
{
moo_ooch_t* tmp;
moo_oow_t newcapa;
newcapa = moo->sprintf.xbuf.len + oolen + 1;
newcapa = MOO_ALIGN_POW2(newcapa, 256);
tmp = (moo_ooch_t*)moo_reallocmem(moo, moo->sprintf.xbuf.ptr, newcapa * MOO_SIZEOF(*tmp));
if (!tmp) return -1;
moo->sprintf.xbuf.ptr = tmp;
moo->sprintf.xbuf.capa = newcapa;
}
#if defined(MOO_OOCH_IS_UCH)
moo_conv_bchars_to_uchars_with_cmgr (ptr, &len, &moo->sprintf.xbuf.ptr[moo->sprintf.xbuf.len], &oolen, moo->cmgr, 1);
#else
MOO_MEMCPY (&moo->sprintf.xbuf.ptr[moo->sprintf.xbuf.len], ptr, len * MOO_SIZEOF(*ptr));
#endif
moo->sprintf.xbuf.len += oolen;
return 1; /* success */
}
static int sprint_ucs (moo_fmtout_t* fmtout, const moo_uch_t* ptr, moo_oow_t len)
{
moo_t* moo = (moo_t*)fmtout->ctx;
moo_oow_t unused, oolen, ulen;
unused = moo->sprintf.xbuf.capa - moo->sprintf.xbuf.len;
#if defined(MOO_OOCH_IS_UCH)
oolen = len;
#else
ulen = len;
moo_conv_uchars_to_bchars_with_cmgr (ptr, &ulen, MOO_NULL, &oolen, moo->cmgr);
#endif
if (oolen > unused)
{
moo_ooch_t* tmp;
moo_oow_t newcapa;
newcapa = moo->sprintf.xbuf.len + oolen + 1;
newcapa = MOO_ALIGN_POW2(newcapa, 256);
tmp = (moo_ooch_t*)moo_reallocmem(moo, moo->sprintf.xbuf.ptr, newcapa * MOO_SIZEOF(*tmp));
if (!tmp) return -1;
moo->sprintf.xbuf.ptr = tmp;
moo->sprintf.xbuf.capa = newcapa;
}
#if defined(MOO_OOCH_IS_UCH)
MOO_MEMCPY (&moo->sprintf.xbuf.ptr[moo->sprintf.xbuf.len], ptr, len * MOO_SIZEOF(*ptr));
#else
moo_conv_uchars_to_bchars_with_cmgr (ptr, &len, &moo->sprintf.xbuf.ptr[moo->sprintf.xbuf.len], &oolen, moo->cmgr);
#endif
moo->sprintf.xbuf.len += oolen;
return 1; /* success */
}
moo_ooi_t moo_sproutbfmt (moo_t* moo, moo_bitmask_t mask, const moo_bch_t* fmt, ...)
{
int x;
va_list ap;
moo_fmtout_t fo;
MOO_MEMSET (&fo, 0, MOO_SIZEOF(fo));
fo.fmt_type = MOO_FMTOUT_FMT_TYPE_BCH;
fo.fmt_str = fmt;
fo.mask = mask;
fo.putbcs = sprint_bcs;
fo.putucs = sprint_ucs;
fo.putobj = moo_fmt_object_;
va_start (ap, fmt);
x = fmt_outv(&fo, ap);
va_end (ap);
return (x <= -1)? -1: fo.count;
}
moo_ooi_t moo_sproutufmt (moo_t* moo, moo_bitmask_t mask, const moo_uch_t* fmt, ...)
{
int x;
va_list ap;
moo_fmtout_t fo;
MOO_MEMSET (&fo, 0, MOO_SIZEOF(fo));
fo.fmt_type = MOO_FMTOUT_FMT_TYPE_UCH;
fo.fmt_str = fmt;
fo.mask = mask;
fo.putbcs = sprint_bcs;
fo.putucs = sprint_ucs;
fo.putobj = moo_fmt_object_;
va_start (ap, fmt);
x = fmt_outv(&fo, ap);
va_end (ap);
return (x <= -1)? -1: fo.count;
}
#define GET_NEXT_ARG_TO(moo,nargs,arg_state,arg) do { \
if ((arg_state)->idx >= nargs) { (arg_state)->stop = 1; goto invalid_format; } \
arg = MOO_STACK_GETARG(moo, nargs, (arg_state)->idx); \
(arg_state)->idx++; \
} while(0)
#define GET_NEXT_CHAR_TO(moo,fmt,fmtend,ch) do { \
if (fmt >= fmtend) ch = MOO_OOCI_EOF; \
else { ch = *(fmt); (fmt)++; }\
} while(0)
static MOO_INLINE int format_stack_args (moo_fmtout_t* fmtout, moo_ooi_t nargs, int rcv_is_fmtstr)
{
moo_t* moo = (moo_t*)fmtout->ctx;
const moo_ooch_t* fmtptr, * fmtend;
const moo_ooch_t* checkpoint, * percent;
int n, radix, neg, sign, radix_flags;
moo_ooi_t extra, width, precision;
moo_ooch_t padc, ooch;
moo_ooci_t ch;
int flagc;
struct
{
moo_ooi_t idx;
int stop;
} arg_state;
moo_oop_t arg;
MOO_ASSERT (moo, fmtout->putobj != MOO_NULL);
fmtout->count = 0;
if (rcv_is_fmtstr)
{
arg = MOO_STACK_GETRCV(moo, nargs);
arg_state.idx = 0;
}
else
{
arg = MOO_STACK_GETARG(moo, nargs, 0);
arg_state.idx = 1;
}
if (!MOO_OOP_IS_POINTER(arg) || MOO_OBJ_GET_FLAGS_TYPE(arg) != MOO_OBJ_TYPE_CHAR)
{
moo_ooi_t i;
/* if the first argument is not a valid formatting string,
* print all arguments as objects */
if (fmtout->putobj(fmtout, arg) <= -1) goto oops;
for (i = arg_state.idx; i < nargs; i++)
{
arg = MOO_STACK_GETARG(moo, nargs, i);
if (fmtout->putobj(fmtout, arg) <= -1) goto oops;
}
return 0;
}
arg_state.stop = 0;
fmtptr = MOO_OBJ_GET_CHAR_SLOT(arg);
fmtend = fmtptr + MOO_OBJ_GET_SIZE(arg);
while (1)
{
checkpoint = fmtptr;
while (1)
{
GET_NEXT_CHAR_TO (moo, fmtptr, fmtend, ch);
if (ch == '%' && !arg_state.stop) break;
if (ch == MOO_OOCI_EOF)
{
/* fmt is not advanced when it is length-bounded.
* so not fmt - checkpoint - 1 */
PUT_OOCS (fmtout, checkpoint, fmtptr - checkpoint);
goto done;
}
}
PUT_OOCS (fmtout, checkpoint, fmtptr - checkpoint - 1);
percent = fmtptr - 1;
padc = ' ';
width = 0; precision = 0;
neg = 0; sign = 0;
flagc = 0;
radix_flags = MOO_INTTOSTR_NONEWOBJ;
reswitch:
GET_NEXT_CHAR_TO (moo, fmtptr, fmtend, ch);
switch (ch)
{
case '%': /* %% */
ooch = ch;
goto print_char;
/* flag characters */
case '.':
if (flagc & FLAGC_DOT) goto invalid_format;
flagc |= FLAGC_DOT;
goto reswitch;
case '#':
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
flagc |= FLAGC_SHARP;
goto reswitch;
case ' ':
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
flagc |= FLAGC_SPACE;
goto reswitch;
case '+': /* place sign for signed conversion */
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
flagc |= FLAGC_SIGN;
goto reswitch;
case '-': /* left adjusted */
if (flagc & (FLAGC_WIDTH | FLAGC_DOT | FLAGC_LENMOD)) goto invalid_format;
if (flagc & FLAGC_DOT)
{
goto invalid_format;
}
else
{
flagc |= FLAGC_LEFTADJ;
if (flagc & FLAGC_ZEROPAD)
{
padc = ' ';
flagc &= ~FLAGC_ZEROPAD;
}
}
goto reswitch;
case '*': /* take the length from the parameter */
if (flagc & FLAGC_DOT)
{
if (flagc & (FLAGC_STAR2 | FLAGC_PRECISION)) goto invalid_format;
flagc |= FLAGC_STAR2;
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
if (moo_inttoooi(moo, arg, &precision) <= -1) goto invalid_format;
if (precision < 0)
{
/* if precision is less than 0,
* treat it as if no .precision is specified */
flagc &= ~FLAGC_DOT;
precision = 0;
}
}
else
{
if (flagc & (FLAGC_STAR1 | FLAGC_WIDTH)) goto invalid_format;
flagc |= FLAGC_STAR1;
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
if (moo_inttoooi(moo, arg, &width) <= -1) goto invalid_format;
if (width < 0)
{
flagc |= FLAGC_LEFTADJ;
width = -width;
}
}
goto reswitch;
case '0': /* zero pad */
if (flagc & FLAGC_LENMOD) goto invalid_format;
if (!(flagc & (FLAGC_DOT | FLAGC_LEFTADJ)))
{
padc = '0';
flagc |= FLAGC_ZEROPAD;
goto reswitch;
}
/* end of flags characters */
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if (flagc & FLAGC_LENMOD) goto invalid_format;
for (n = 0;; ++fmtptr)
{
n = n * 10 + ch - '0';
ch = *fmtptr;
if (ch < '0' || ch > '9') break;
}
if (flagc & FLAGC_DOT)
{
if (flagc & FLAGC_STAR2) goto invalid_format;
precision = n;
flagc |= FLAGC_PRECISION;
}
else
{
if (flagc & FLAGC_STAR1) goto invalid_format;
width = n;
flagc |= FLAGC_WIDTH;
}
goto reswitch;
/* integer conversions */
case 'd':
case 'i': /* signed conversion */
radix = 10;
sign = 1;
goto print_integer;
case 'o':
radix = 8;
goto print_integer;
case 'u':
radix = 10;
goto print_integer;
case 'x':
radix_flags |= MOO_INTTOSTR_LOWERCASE;
case 'X':
radix = 16;
goto print_integer;
case 'b':
radix = 2;
goto print_integer;
/* end of integer conversions */
case 'f':
{
const moo_ooch_t* nsptr;
moo_oow_t nslen;
moo_oow_t scale = 0;
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
if (MOO_OOP_IS_CHAR(arg))
{
arg = MOO_SMOOI_TO_OOP(MOO_OOP_TO_CHAR(arg));
}
else if (MOO_OOP_IS_FPDEC(moo, arg))
{
moo_oop_fpdec_t fa = (moo_oop_fpdec_t)arg;
scale = MOO_OOP_TO_SMOOI(fa->scale);
arg = fa->value;
}
if (!moo_inttostr(moo, arg, 10 | MOO_INTTOSTR_NONEWOBJ))
{
MOO_LOG1 (moo, MOO_LOG_WARN | MOO_LOG_UNTYPED, "unable to convert %O to string \n", arg);
goto invalid_format;
}
nsptr = moo->inttostr.xbuf.ptr;
nslen = moo->inttostr.xbuf.len;
MOO_ASSERT (moo, nslen > 0);
if (nsptr[0] == '-')
{
MOO_ASSERT (moo, (MOO_OOP_IS_SMOOI(arg) && MOO_OOP_TO_SMOOI(arg) < 0) || MOO_OOP_IS_NBIGINT(moo,arg));
nsptr++;
nslen--;
neg = 1;
}
if (!(flagc & FLAGC_DOT))
{
precision = scale;
if (precision <= 0) precision = 1;
}
if ((flagc & FLAGC_DOT) && precision < scale)
{
moo_oow_t diff = scale - precision;
scale = precision;
nslen = (nslen < diff)? 0: (nslen - diff);
}
if (nslen < scale + 1)
{
extra = 1;
if (precision > 0) extra += 1 + scale;
}
else
{
extra = 0;
if (nslen > 0) extra += nslen - scale;
if (precision > 0)
{
extra += 1;
if (nslen > 0) extra += scale;
}
}
if (neg) extra++;
else if (flagc & FLAGC_SIGN) extra++;
else if (flagc & FLAGC_SPACE) extra++;
if ((flagc & FLAGC_DOT) && precision > scale)
{
/* trailing zeros in the fractional part */
extra += precision - scale;
}
if (!(flagc & FLAGC_LEFTADJ) && !(flagc & FLAGC_ZEROPAD) && width > extra)
{
width -= extra;
PUT_OOCH (fmtout, padc, width);
width = 0;
}
if (neg) PUT_OOCH (fmtout, '-', 1);
else if (flagc & FLAGC_SIGN) PUT_OOCH (fmtout, '+', 1);
else if (flagc & FLAGC_SPACE) PUT_OOCH (fmtout, ' ', 1);
if (!(flagc & FLAGC_LEFTADJ) && width > extra)
{
width -= extra;
PUT_OOCH (fmtout, padc, width);
}
if (nslen < scale + 1)
{
PUT_OOCH (fmtout, '0', 1);
if (precision > 0)
{
PUT_OOCH (fmtout, '.', 1);
PUT_OOCH (fmtout, '0', scale - nslen);
PUT_OOCS (fmtout, nsptr, nslen);
}
}
else
{
if (nslen > 0) PUT_OOCS (fmtout, nsptr, nslen - scale);
if (precision > 0)
{
PUT_OOCH (fmtout, '.', 1);
if (nslen > 0) PUT_OOCS (fmtout, &nsptr[nslen - scale], scale);
}
}
if (precision > scale)
{
/* trailing zeros in the fractional part */
PUT_OOCH (fmtout, '0', precision - scale);
}
if ((flagc & FLAGC_LEFTADJ) && width > extra)
{
width -= extra;
PUT_OOCH (fmtout, padc, width);
}
break;
}
case 'c':
case 'C':
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
if (MOO_OOP_IS_SMOOI(arg)) arg = MOO_CHAR_TO_OOP(MOO_OOP_TO_SMOOI(arg));
if (!MOO_OOP_IS_CHAR(arg)) goto invalid_format;
ooch = MOO_OOP_TO_CHAR(arg);
print_char:
/* zeropad must not take effect for 'c' */
if (flagc & FLAGC_ZEROPAD) padc = ' ';
/* precision 0 doesn't kill the letter */
width--;
if (!(flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (fmtout, padc, width);
PUT_OOCH (fmtout, ooch, 1);
if ((flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (fmtout, padc, width);
break;
case 's':
case 'S':
{
const moo_ooch_t* oosp;
moo_oow_t oosl;
/* zeropad must not take effect for 'S' */
if (flagc & FLAGC_ZEROPAD) padc = ' ';
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
if (!MOO_OOP_IS_POINTER(arg) || MOO_OBJ_GET_FLAGS_TYPE(arg) != MOO_OBJ_TYPE_CHAR) goto invalid_format;
oosp = MOO_OBJ_GET_CHAR_SLOT(arg);
oosl = MOO_OBJ_GET_SIZE(arg);
if (flagc & FLAGC_DOT)
{
if (oosl > precision) oosl = precision;
}
width -= oosl;
if (!(flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (fmtout, padc, width);
PUT_OOCS (fmtout, oosp, oosl);
if ((flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (fmtout, padc, width);
break;
}
case 'O': /* object - ignore precision, width, adjustment */
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
if (fmtout->putobj(fmtout, arg) <= -1) goto oops;
break;
print_integer:
{
const moo_ooch_t* nsptr;
moo_oow_t nslen;
GET_NEXT_ARG_TO (moo, nargs, &arg_state, arg);
if (MOO_OOP_IS_CHAR(arg))
{
arg = MOO_SMOOI_TO_OOP(MOO_OOP_TO_CHAR(arg));
}
else if (MOO_OOP_IS_FPDEC(moo, arg))
{
moo_oop_t nv;
moo_oop_fpdec_t fa = (moo_oop_fpdec_t)arg;
/* the given number for integer output is a fixed-point decimal.
* i will drop all digits after the fixed point */
moo_pushvolat (moo, &arg);
nv = moo_truncfpdecval(moo, fa->value, MOO_OOP_TO_SMOOI(fa->scale), 0);
moo_popvolat (moo);
if (!nv)
{
MOO_LOG1 (moo, MOO_LOG_WARN | MOO_LOG_UNTYPED, "unable to truncate a fixed-point number %O to an integer for output\n", arg);
goto invalid_format;
}
arg = nv;
}
if (!moo_inttostr(moo, arg, radix | radix_flags))
{
/*moo_seterrbfmt (moo, MOO_EINVAL, "not a valid number - %O", arg);
goto oops;*/
MOO_LOG1 (moo, MOO_LOG_WARN | MOO_LOG_UNTYPED, "unable to convert integer %O to string \n", arg);
goto invalid_format;
}
nsptr = moo->inttostr.xbuf.ptr;
nslen = moo->inttostr.xbuf.len;
MOO_ASSERT (moo, nslen > 0);
if (nsptr[0] == '-')
{
/* a negative number was given. i must skip the minus sign
* added by moo_inttostr() for a negative number. */
MOO_ASSERT (moo, (MOO_OOP_IS_SMOOI(arg) && MOO_OOP_TO_SMOOI(arg) < 0) || MOO_OOP_IS_NBIGINT(moo,arg));
nsptr++;
nslen--;
}
extra = nslen;
if (sign && ((MOO_OOP_IS_SMOOI(arg) && MOO_OOP_TO_SMOOI(arg) < 0) || MOO_OOP_IS_NBIGINT(moo,arg))) neg = 1;
if ((flagc & FLAGC_SHARP) && arg != MOO_SMOOI_TO_OOP(0))
{
if (radix == 2 || radix == 8 || radix == 16) extra += 2;
}
if (neg) extra++;
else if (flagc & FLAGC_SIGN) extra++;
else if (flagc & FLAGC_SPACE) extra++;
if ((flagc & FLAGC_DOT) && precision > nslen)
{
/* extra zeros for precision specified */
extra += (precision - nslen);
}
if (!(flagc & FLAGC_LEFTADJ) && !(flagc & FLAGC_ZEROPAD) && width > 0 && (width -= extra) > 0)
{
PUT_OOCH (fmtout, padc, width);
width = 0;
}
if (neg) PUT_OOCH (fmtout, '-', 1);
else if (flagc & FLAGC_SIGN) PUT_OOCH (fmtout, '+', 1);
else if (flagc & FLAGC_SPACE) PUT_OOCH (fmtout, ' ', 1);
if ((flagc & FLAGC_SHARP) && arg != MOO_SMOOI_TO_OOP(0))
{
if (radix == 2)
{
PUT_OOCH (fmtout, '2', 1);
PUT_OOCH (fmtout, 'r', 1);
}
if (radix == 8)
{
PUT_OOCH (fmtout, '8', 1);
PUT_OOCH (fmtout, 'r', 1);
}
else if (radix == 16)
{
PUT_OOCH (fmtout, '1', 1);
PUT_OOCH (fmtout, '6', 1);
PUT_OOCH (fmtout, 'r', 1);
}
}
if ((flagc & FLAGC_DOT) && precision > nslen)
{
/* extra zeros for precision specified */
PUT_OOCH (fmtout, '0', precision - nslen);
}
if (!(flagc & FLAGC_LEFTADJ) && width > 0 && (width -= extra) > 0)
{
PUT_OOCH (fmtout, padc, width);
}
PUT_OOCS (fmtout, nsptr, nslen);
if ((flagc & FLAGC_LEFTADJ) && width > 0 && (width -= extra) > 0)
{
PUT_OOCH (fmtout, padc, width);
}
break;
}
invalid_format:
PUT_OOCS (fmtout, percent, fmtptr - percent);
break;
default:
PUT_OOCS (fmtout, percent, fmtptr - percent);
/*
* Since we ignore an formatting argument it is no
* longer safe to obey the remaining formatting
* arguments as the arguments will no longer match
* the format specs.
*/
arg_state.stop = 1;
break;
}
}
done:
return 0;
oops:
return -1;
}
int moo_strfmtcallstack (moo_t* moo, moo_ooi_t nargs, int rcv_is_fmtstr)
{
/* format a string using the receiver and arguments on the stack */
moo_fmtout_t fo;
MOO_MEMSET (&fo, 0, MOO_SIZEOF(fo));
fo.ctx = moo;
fo.putbcs = sprint_bcs;
fo.putucs = sprint_ucs;
fo.putobj = moo_fmt_object_;
/* format_stack_args doesn't use fmt_str and fmt_type.
* it takes the format string from the stack. */
moo->sprintf.xbuf.len = 0;
return format_stack_args(&fo, nargs, rcv_is_fmtstr);
}

View File

@ -26,6 +26,8 @@
#include "moo-prv.h"
#if 0
/*#include <stdio.h>*/ /* for snrintf(). used for floating-point number formatting */
#if defined(_MSC_VER) || defined(__BORLANDC__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1200))
@ -729,7 +731,7 @@ moo_ooi_t moo_logufmt (moo_t* moo, moo_bitmask_t mask, const moo_uch_t* fmt, ...
else { ch = *(fmt); (fmt)++; }\
} while(0)
static MOO_INLINE int print_formatted (moo_t* moo, moo_ooi_t nargs, moo_fmtout_data_t* data, moo_outbfmt_t outbfmt, int ignore_rcv)
static MOO_INLINE int print_formatted (moo_t* moo, moo_ooi_t nargs, moo_fmtout_data_t* data, moo_outbfmt_t outbfmt, int rcv_is_fmtstr)
{
const moo_ooch_t* fmt, * fmtend;
const moo_ooch_t* checkpoint, * percent;
@ -747,16 +749,16 @@ static MOO_INLINE int print_formatted (moo_t* moo, moo_ooi_t nargs, moo_fmtout_d
} arg_state;
moo_oop_t arg;
if (ignore_rcv)
{
arg = MOO_STACK_GETARG(moo, nargs, 0);
arg_state.idx = 1;
}
else
if (rcv_is_fmtstr)
{
arg = MOO_STACK_GETRCV(moo, nargs);
arg_state.idx = 0;
}
else
{
arg = MOO_STACK_GETARG(moo, nargs, 0);
arg_state.idx = 1;
}
if (!MOO_OOP_IS_POINTER(arg) || MOO_OBJ_GET_FLAGS_TYPE(arg) != MOO_OBJ_TYPE_CHAR)
{
@ -1377,6 +1379,7 @@ static moo_ooi_t __sprbfmtv(moo_t* moo, moo_bitmask_t mask, const moo_bch_t* fmt
return fo.count;
}
#if 0
moo_ooi_t moo_sproutbfmt (moo_t* moo, moo_bitmask_t mask, const moo_bch_t* fmt, ...)
{
int x;
@ -1393,7 +1396,7 @@ moo_ooi_t moo_sproutbfmt (moo_t* moo, moo_bitmask_t mask, const moo_bch_t* fmt,
return (x <= -1)? -1: fo.count;
}
#endif
/*
moo_ooi_t moo_sproutufmt (moo_t* moo, moo_bitmask_t mask, const moo_uch_t* fmt, ...)
{
@ -1413,7 +1416,7 @@ moo_ooi_t moo_sproutufmt (moo_t* moo, moo_bitmask_t mask, const moo_uch_t* fmt,
}*/
int moo_sprintfmtst (moo_t* moo, moo_ooi_t nargs)
int moo_strfmtcallstack (moo_t* moo, moo_ooi_t nargs)
{
/* format a string using the receiver and arguments on the stack */
moo_fmtout_data_t fo;
@ -1421,5 +1424,7 @@ int moo_sprintfmtst (moo_t* moo, moo_ooi_t nargs)
fo.putch = put_sprch;
fo.putcs = put_sprcs;
moo->sprintf.xbuf.len = 0;
return print_formatted(moo, nargs, &fo, moo_sproutbfmt, 0);
return print_formatted(moo, nargs, &fo, moo_sproutbfmt, 1);
}
#endif

View File

@ -1501,9 +1501,10 @@ moo_ooi_t moo_sproutbfmt (
...
);
int moo_sprintfmtst (
int moo_strfmtcallstack (
moo_t* moo,
moo_ooi_t nargs
moo_ooi_t nargs,
int rcv_is_fmtstr
);
/* ========================================================================= */

View File

@ -381,10 +381,10 @@ MOO_EXPORT moo_oow_t moo_hash_bytes_ (
}
#else
# define moo_hash_bytes(ptr,len) moo_hash_bytes_(ptr, len)
# define moo_hash_bchars(ptr,len) moo_hash_bytes((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_bch_t))
# define moo_hash_uchars(ptr,len) moo_hash_bytes((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_uch_t))
# define moo_hash_words(ptr,len) moo_hash_bytes((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_oow_t))
# define moo_hash_halfwords(ptr,len) moo_hash_bytes((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_oohw_t))
# define moo_hash_bchars(ptr,len) moo_hash_bytes_((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_bch_t))
# define moo_hash_uchars(ptr,len) moo_hash_bytes_((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_uch_t))
# define moo_hash_words(ptr,len) moo_hash_bytes_((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_oow_t))
# define moo_hash_halfwords(ptr,len) moo_hash_bytes_((const moo_oob_t*)(ptr), (len) * MOO_SIZEOF(moo_oohw_t))
#endif
#if defined(MOO_OOCH_IS_UCH)

View File

@ -332,6 +332,7 @@ pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@

View File

@ -3,6 +3,7 @@
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
#include "t.h"
static int put_bcs (moo_fmtout_t* fmtout, const moo_bch_t* c, moo_oow_t len)
{
@ -59,6 +60,11 @@ int main ()
/* this unit is the number of characters written. but some are written as bch and some other as uch.
* if uch and bch data are mixed, the count returned doesn't really tell how many bytes or characters written */
cnt = bfmt_out ("wrote [%ld] units\n", cnt);
bfmt_out ("wrote [%ld] units\n", cnt);
T_ASSERT1 (cnt == 98, "bfmt_out test #1");
return 0;
oops:
return -1;
}