From faf05c3a13e3b9b37a128a589a0b780a5fb7720e Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Tue, 2 Oct 2012 11:59:32 +0200 Subject: [PATCH] From Lua 5.2: '%s' option to string.format() behaves like tostring(). --- src/Makefile.dep | 4 ++-- src/lib_string.c | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/Makefile.dep b/src/Makefile.dep index b2d6b6a7..cab23b79 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -32,8 +32,8 @@ lib_package.o: lib_package.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h lib_string.o: lib_string.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h \ - lj_state.h lj_ff.h lj_ffdef.h lj_bcdump.h lj_lex.h lj_char.h lj_lib.h \ - lj_libdef.h + lj_meta.h lj_state.h lj_ff.h lj_ffdef.h lj_bcdump.h lj_lex.h lj_char.h \ + lj_lib.h lj_libdef.h lib_table.o: lib_table.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_lib.h \ lj_libdef.h diff --git a/src/lib_string.c b/src/lib_string.c index 9c4cee8b..b36fcd6d 100644 --- a/src/lib_string.c +++ b/src/lib_string.c @@ -20,6 +20,7 @@ #include "lj_err.h" #include "lj_str.h" #include "lj_tab.h" +#include "lj_meta.h" #include "lj_state.h" #include "lj_ff.h" #include "lj_bcdump.h" @@ -772,6 +773,41 @@ static unsigned LUA_INTFRM_T num2uintfrm(lua_State *L, int arg) } } +static GCstr *meta_tostring(lua_State *L, int arg) +{ + TValue *o = L->base+arg-1; + cTValue *mo; + lua_assert(o < L->top); /* Caller already checks for existence. */ + if (LJ_LIKELY(tvisstr(o))) + return strV(o); + if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) { + copyTV(L, L->top++, mo); + copyTV(L, L->top++, o); + lua_call(L, 1, 1); + L->top--; + if (tvisstr(L->top)) + return strV(L->top); + o = L->base+arg-1; + copyTV(L, o, L->top); + } + if (tvisnumber(o)) { + return lj_str_fromnumber(L, o); + } else if (tvisnil(o)) { + return lj_str_newlit(L, "nil"); + } else if (tvisfalse(o)) { + return lj_str_newlit(L, "false"); + } else if (tvistrue(o)) { + return lj_str_newlit(L, "true"); + } else { + if (tvisfunc(o) && isffunc(funcV(o))) + lj_str_pushf(L, "function: builtin#%d", funcV(o)->c.ffid); + else + lj_str_pushf(L, "%s: %p", lj_typename(o), lua_topointer(L, arg)); + L->top--; + return strV(L->top); + } +} + LJLIB_CF(string_format) { int arg = 1, top = (int)(L->top - L->base); @@ -832,7 +868,7 @@ LJLIB_CF(string_format) luaL_addvalue(&b); continue; case 's': { - GCstr *str = lj_lib_checkstr(L, arg); + GCstr *str = meta_tostring(L, arg); if (!strchr(form, '.') && str->len >= 100) { /* no precision and string is too long to be formatted; keep original string */