Details
Several small improvements (code style, warnings, comments, more tests),
in particular:
- 'lua_topointer' extended to handle strings
- raises an error in 'string.format("%10q")' ('%q' with modifiers)
- in the manual for 'string.format', the term "option" replaced by
"conversion specifier" (the term used by the C standard)
This commit is contained in:
31
lapi.c
31
lapi.c
@@ -414,8 +414,7 @@ LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LUA_API void *lua_touserdata (lua_State *L, int idx) {
|
static void *touserdata (const TValue *o) {
|
||||||
const TValue *o = index2value(L, idx);
|
|
||||||
switch (ttype(o)) {
|
switch (ttype(o)) {
|
||||||
case LUA_TUSERDATA: return getudatamem(uvalue(o));
|
case LUA_TUSERDATA: return getudatamem(uvalue(o));
|
||||||
case LUA_TLIGHTUSERDATA: return pvalue(o);
|
case LUA_TLIGHTUSERDATA: return pvalue(o);
|
||||||
@@ -424,23 +423,37 @@ LUA_API void *lua_touserdata (lua_State *L, int idx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LUA_API void *lua_touserdata (lua_State *L, int idx) {
|
||||||
|
const TValue *o = index2value(L, idx);
|
||||||
|
return touserdata(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
|
LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
|
||||||
const TValue *o = index2value(L, idx);
|
const TValue *o = index2value(L, idx);
|
||||||
return (!ttisthread(o)) ? NULL : thvalue(o);
|
return (!ttisthread(o)) ? NULL : thvalue(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Returns a pointer to the internal representation of an object.
|
||||||
|
** Note that ANSI C does not allow the conversion of a pointer to
|
||||||
|
** function to a 'void*', so the conversion here goes through
|
||||||
|
** a 'size_t'. (As the returned pointer is only informative, this
|
||||||
|
** conversion should not be a problem.)
|
||||||
|
*/
|
||||||
LUA_API const void *lua_topointer (lua_State *L, int idx) {
|
LUA_API const void *lua_topointer (lua_State *L, int idx) {
|
||||||
const TValue *o = index2value(L, idx);
|
const TValue *o = index2value(L, idx);
|
||||||
switch (ttypetag(o)) {
|
switch (ttypetag(o)) {
|
||||||
case LUA_TTABLE: return hvalue(o);
|
|
||||||
case LUA_TLCL: return clLvalue(o);
|
|
||||||
case LUA_TCCL: return clCvalue(o);
|
|
||||||
case LUA_TLCF: return cast_voidp(cast_sizet(fvalue(o)));
|
case LUA_TLCF: return cast_voidp(cast_sizet(fvalue(o)));
|
||||||
case LUA_TTHREAD: return thvalue(o);
|
case LUA_TUSERDATA: case LUA_TLIGHTUSERDATA:
|
||||||
case LUA_TUSERDATA: return getudatamem(uvalue(o));
|
return touserdata(o);
|
||||||
case LUA_TLIGHTUSERDATA: return pvalue(o);
|
default: {
|
||||||
default: return NULL;
|
if (iscollectable(o))
|
||||||
|
return gcvalue(o);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
3
lfunc.c
3
lfunc.c
@@ -138,7 +138,8 @@ static int callclosemth (lua_State *L, TValue *uv, StkId level, int status) {
|
|||||||
if (prepclosingmethod(L, uv, &G(L)->nilvalue)) /* something to call? */
|
if (prepclosingmethod(L, uv, &G(L)->nilvalue)) /* something to call? */
|
||||||
callclose(L, NULL); /* call closing method */
|
callclose(L, NULL); /* call closing method */
|
||||||
else if (!ttisnil(uv)) { /* non-closable non-nil value? */
|
else if (!ttisnil(uv)) { /* non-closable non-nil value? */
|
||||||
const char *vname = luaG_findlocal(L, L->ci, level - L->ci->func, NULL);
|
int idx = cast_int(level - L->ci->func);
|
||||||
|
const char *vname = luaG_findlocal(L, L->ci, idx, NULL);
|
||||||
if (vname == NULL) vname = "?";
|
if (vname == NULL) vname = "?";
|
||||||
luaG_runerror(L, "attempt to close non-closable variable '%s'", vname);
|
luaG_runerror(L, "attempt to close non-closable variable '%s'", vname);
|
||||||
}
|
}
|
||||||
|
|||||||
15
lopcodes.h
15
lopcodes.h
@@ -90,7 +90,6 @@ enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */
|
|||||||
#define MAXARG_B ((1<<SIZE_B)-1)
|
#define MAXARG_B ((1<<SIZE_B)-1)
|
||||||
#define MAXARG_C ((1<<SIZE_C)-1)
|
#define MAXARG_C ((1<<SIZE_C)-1)
|
||||||
#define OFFSET_sC (MAXARG_C >> 1)
|
#define OFFSET_sC (MAXARG_C >> 1)
|
||||||
#define MAXARG_Cx ((1<<(SIZE_C + 1))-1)
|
|
||||||
|
|
||||||
|
|
||||||
/* creates a mask with 'n' 1 bits at position 'p' */
|
/* creates a mask with 'n' 1 bits at position 'p' */
|
||||||
@@ -233,8 +232,8 @@ OP_BANDK,/* A B C R(A) := R(B) & K(C):integer */
|
|||||||
OP_BORK,/* A B C R(A) := R(B) | K(C):integer */
|
OP_BORK,/* A B C R(A) := R(B) | K(C):integer */
|
||||||
OP_BXORK,/* A B C R(A) := R(B) ~ K(C):integer */
|
OP_BXORK,/* A B C R(A) := R(B) ~ K(C):integer */
|
||||||
|
|
||||||
OP_SHRI,/* A B C R(A) := R(B) >> C */
|
OP_SHRI,/* A B sC R(A) := R(B) >> C */
|
||||||
OP_SHLI,/* A B C R(A) := C << R(B) */
|
OP_SHLI,/* A B sC R(A) := C << R(B) */
|
||||||
|
|
||||||
OP_ADD,/* A B C R(A) := R(B) + R(C) */
|
OP_ADD,/* A B C R(A) := R(B) + R(C) */
|
||||||
OP_SUB,/* A B C R(A) := R(B) - R(C) */
|
OP_SUB,/* A B C R(A) := R(B) - R(C) */
|
||||||
@@ -272,7 +271,7 @@ OP_GTI,/* A sB if ((R(A) > sB) ~= k) then pc++ */
|
|||||||
OP_GEI,/* A sB if ((R(A) >= sB) ~= k) then pc++ */
|
OP_GEI,/* A sB if ((R(A) >= sB) ~= k) then pc++ */
|
||||||
|
|
||||||
OP_TEST,/* A if (not R(A) == k) then pc++ */
|
OP_TEST,/* A if (not R(A) == k) then pc++ */
|
||||||
OP_TESTSET,/* A B if (not R(B) == k) then R(A) := R(B) else pc++ */
|
OP_TESTSET,/* A B if (not R(B) == k) then pc++ else R(A) := R(B) */
|
||||||
|
|
||||||
OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
|
OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
|
||||||
OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
|
OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
|
||||||
@@ -305,15 +304,15 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
|
|||||||
} OpCode;
|
} OpCode;
|
||||||
|
|
||||||
|
|
||||||
#define NUM_OPCODES (cast_int(OP_EXTRAARG) + 1)
|
#define NUM_OPCODES ((int)(OP_EXTRAARG) + 1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================
|
/*===========================================================================
|
||||||
Notes:
|
Notes:
|
||||||
(*) In OP_CALL, if (B == 0) then B = top. If (C == 0), then 'top' is
|
(*) In OP_CALL, if (B == 0) then B = top - A. If (C == 0), then
|
||||||
set to last_result+1, so next open instruction (OP_CALL, OP_RETURN*,
|
'top' is set to last_result+1, so next open instruction (OP_CALL,
|
||||||
OP_SETLIST) may use 'top'.
|
OP_RETURN*, OP_SETLIST) may use 'top'.
|
||||||
|
|
||||||
(*) In OP_VARARG, if (C == 0) then use actual number of varargs and
|
(*) In OP_VARARG, if (C == 0) then use actual number of varargs and
|
||||||
set top (like in OP_CALL with C == 0).
|
set top (like in OP_CALL with C == 0).
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ static int str_byte (lua_State *L) {
|
|||||||
size_t pose = getendpos(L, 3, pi, l);
|
size_t pose = getendpos(L, 3, pi, l);
|
||||||
int n, i;
|
int n, i;
|
||||||
if (posi > pose) return 0; /* empty interval; return no values */
|
if (posi > pose) return 0; /* empty interval; return no values */
|
||||||
if (pose - posi >= INT_MAX) /* arithmetic overflow? */
|
if (pose - posi >= (size_t)INT_MAX) /* arithmetic overflow? */
|
||||||
return luaL_error(L, "string slice too long");
|
return luaL_error(L, "string slice too long");
|
||||||
n = (int)(pose - posi) + 1;
|
n = (int)(pose - posi) + 1;
|
||||||
luaL_checkstack(L, n, "string slice too long");
|
luaL_checkstack(L, n, "string slice too long");
|
||||||
@@ -1159,7 +1159,7 @@ static int str_format (lua_State *L) {
|
|||||||
char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */
|
char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */
|
||||||
int nb = 0; /* number of bytes in added item */
|
int nb = 0; /* number of bytes in added item */
|
||||||
if (++arg > top)
|
if (++arg > top)
|
||||||
luaL_argerror(L, arg, "no value");
|
return luaL_argerror(L, arg, "no value");
|
||||||
strfrmt = scanformat(L, strfrmt, form);
|
strfrmt = scanformat(L, strfrmt, form);
|
||||||
switch (*strfrmt++) {
|
switch (*strfrmt++) {
|
||||||
case 'c': {
|
case 'c': {
|
||||||
@@ -1186,6 +1186,8 @@ static int str_format (lua_State *L) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'q': {
|
case 'q': {
|
||||||
|
if (form[2] != '\0') /* modifiers? */
|
||||||
|
return luaL_error(L, "specifier '%%q' cannot have modifiers");
|
||||||
addliteral(L, &b, arg);
|
addliteral(L, &b, arg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
7
ltests.c
7
ltests.c
@@ -164,7 +164,7 @@ typedef union Header {
|
|||||||
|
|
||||||
|
|
||||||
Memcontrol l_memcontrol =
|
Memcontrol l_memcontrol =
|
||||||
{0L, 0L, 0L, 0L, (~0L), {0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L}};
|
{0UL, 0UL, 0UL, 0UL, (~0UL), {0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL}};
|
||||||
|
|
||||||
|
|
||||||
static void freeblock (Memcontrol *mc, Header *block) {
|
static void freeblock (Memcontrol *mc, Header *block) {
|
||||||
@@ -1596,7 +1596,10 @@ static struct X { int x; } x;
|
|||||||
lua_pushnumber(L1, lua_tonumber(L1, getindex));
|
lua_pushnumber(L1, lua_tonumber(L1, getindex));
|
||||||
}
|
}
|
||||||
else if EQ("topointer") {
|
else if EQ("topointer") {
|
||||||
lua_pushnumber(L1, cast_sizet(lua_topointer(L1, getindex)));
|
lua_pushlightuserdata(L1, cast_voidp(lua_topointer(L1, getindex)));
|
||||||
|
}
|
||||||
|
else if EQ("touserdata") {
|
||||||
|
lua_pushlightuserdata(L1, lua_touserdata(L1, getindex));
|
||||||
}
|
}
|
||||||
else if EQ("tostring") {
|
else if EQ("tostring") {
|
||||||
const char *s = lua_tostring(L1, getindex);
|
const char *s = lua_tostring(L1, getindex);
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ that is, @x{arrays} that can have as indices not only numbers,
|
|||||||
but any Lua value except @nil and @x{NaN}.
|
but any Lua value except @nil and @x{NaN}.
|
||||||
(@emphx{Not a Number} is a special floating-point value
|
(@emphx{Not a Number} is a special floating-point value
|
||||||
used by the @x{IEEE 754} standard to represent
|
used by the @x{IEEE 754} standard to represent
|
||||||
undefined or unrepresentable numerical results, such as @T{0/0}.)
|
undefined numerical results, such as @T{0/0}.)
|
||||||
Tables can be @emph{heterogeneous};
|
Tables can be @emph{heterogeneous};
|
||||||
that is, they can contain values of all types (except @nil).
|
that is, they can contain values of all types (except @nil).
|
||||||
Any key with value @nil is not considered part of the table.
|
Any key with value @nil is not considered part of the table.
|
||||||
@@ -670,8 +670,8 @@ are called when the garbage collector detects that the
|
|||||||
corresponding table or userdata is unreachable.
|
corresponding table or userdata is unreachable.
|
||||||
Finalizers allow you to coordinate Lua's garbage collection
|
Finalizers allow you to coordinate Lua's garbage collection
|
||||||
with external resource management
|
with external resource management
|
||||||
(such as closing files, network or database connections,
|
such as closing files, network or database connections,
|
||||||
or freeing your own memory).
|
or freeing your own memory.
|
||||||
|
|
||||||
For an object (table or userdata) to be finalized when collected,
|
For an object (table or userdata) to be finalized when collected,
|
||||||
you must @emph{mark} it for finalization.
|
you must @emph{mark} it for finalization.
|
||||||
@@ -1323,11 +1323,12 @@ labels in Lua are considered statements too:
|
|||||||
}
|
}
|
||||||
|
|
||||||
A label is visible in the entire block where it is defined,
|
A label is visible in the entire block where it is defined,
|
||||||
except
|
except inside nested functions.
|
||||||
inside nested blocks where a label with the same name is defined and
|
|
||||||
inside nested functions.
|
|
||||||
A goto may jump to any visible label as long as it does not
|
A goto may jump to any visible label as long as it does not
|
||||||
enter into the scope of a local variable.
|
enter into the scope of a local variable.
|
||||||
|
A label should not be declared
|
||||||
|
where a label with the same name is visible,
|
||||||
|
even if this other label has been declared in an enclosing block.
|
||||||
|
|
||||||
Labels and empty statements are called @def{void statements},
|
Labels and empty statements are called @def{void statements},
|
||||||
as they perform no actions.
|
as they perform no actions.
|
||||||
@@ -1537,7 +1538,7 @@ goes out of scope, including normal block termination,
|
|||||||
exiting its block by @Rw{break}/@Rw{goto}/@Rw{return},
|
exiting its block by @Rw{break}/@Rw{goto}/@Rw{return},
|
||||||
or exiting by an error.
|
or exiting by an error.
|
||||||
|
|
||||||
Here, to \emph{close} a value means
|
Here, to @emph{close} a value means
|
||||||
to call its @idx{__close} metamethod.
|
to call its @idx{__close} metamethod.
|
||||||
If the value is @nil, it is ignored;
|
If the value is @nil, it is ignored;
|
||||||
otherwise,
|
otherwise,
|
||||||
@@ -4236,7 +4237,7 @@ indicates whether the operation succeeded.
|
|||||||
|
|
||||||
Converts the value at the given index to a generic
|
Converts the value at the given index to a generic
|
||||||
@N{C pointer} (@T{void*}).
|
@N{C pointer} (@T{void*}).
|
||||||
The value can be a userdata, a table, a thread, or a function;
|
The value can be a userdata, a table, a thread, a string, or a function;
|
||||||
otherwise, @id{lua_topointer} returns @id{NULL}.
|
otherwise, @id{lua_topointer} returns @id{NULL}.
|
||||||
Different objects will give different pointers.
|
Different objects will give different pointers.
|
||||||
There is no way to convert the pointer back to its original value.
|
There is no way to convert the pointer back to its original value.
|
||||||
@@ -6712,8 +6713,10 @@ to save space.
|
|||||||
|
|
||||||
Functions with upvalues have only their number of upvalues saved.
|
Functions with upvalues have only their number of upvalues saved.
|
||||||
When (re)loaded,
|
When (re)loaded,
|
||||||
those upvalues receive fresh instances containing @nil.
|
those upvalues receive fresh instances.
|
||||||
(You can use the debug library to serialize
|
(See the @Lid{load} function for details about
|
||||||
|
how these upvalues are initialized.
|
||||||
|
You can use the debug library to serialize
|
||||||
and reload the upvalues of a function
|
and reload the upvalues of a function
|
||||||
in a way adequate to your needs.)
|
in a way adequate to your needs.)
|
||||||
|
|
||||||
@@ -6747,12 +6750,12 @@ after the two indices.
|
|||||||
Returns a formatted version of its variable number of arguments
|
Returns a formatted version of its variable number of arguments
|
||||||
following the description given in its first argument (which must be a string).
|
following the description given in its first argument (which must be a string).
|
||||||
The format string follows the same rules as the @ANSI{sprintf}.
|
The format string follows the same rules as the @ANSI{sprintf}.
|
||||||
The only differences are that the options/modifiers
|
The only differences are that the conversion specifiers and modifiers
|
||||||
@T{*}, @id{h}, @id{L}, @id{l}, @id{n},
|
@T{*}, @id{h}, @id{L}, @id{l}, @id{n},
|
||||||
and @id{p} are not supported
|
and @id{p} are not supported
|
||||||
and that there is an extra option, @id{q}.
|
and that there is an extra specifier, @id{q}.
|
||||||
|
|
||||||
The @id{q} option formats booleans, nil, numbers, and strings
|
The specifier @id{q} formats booleans, nil, numbers, and strings
|
||||||
in a way that the result is a valid constant in Lua source code.
|
in a way that the result is a valid constant in Lua source code.
|
||||||
Booleans and nil are written in the obvious way
|
Booleans and nil are written in the obvious way
|
||||||
(@id{true}, @id{false}, @id{nil}).
|
(@id{true}, @id{false}, @id{nil}).
|
||||||
@@ -6770,22 +6773,23 @@ may produce the string:
|
|||||||
"a string with \"quotes\" and \
|
"a string with \"quotes\" and \
|
||||||
new line"
|
new line"
|
||||||
}
|
}
|
||||||
|
This specifier does not support modifiers (flags, width, length).
|
||||||
|
|
||||||
Options
|
The conversion specifiers
|
||||||
@id{A}, @id{a}, @id{E}, @id{e}, @id{f},
|
@id{A}, @id{a}, @id{E}, @id{e}, @id{f},
|
||||||
@id{G}, and @id{g} all expect a number as argument.
|
@id{G}, and @id{g} all expect a number as argument.
|
||||||
Options @id{c}, @id{d},
|
The specifiers @id{c}, @id{d},
|
||||||
@id{i}, @id{o}, @id{u}, @id{X}, and @id{x}
|
@id{i}, @id{o}, @id{u}, @id{X}, and @id{x}
|
||||||
expect an integer.
|
expect an integer.
|
||||||
When Lua is compiled with a C89 compiler,
|
When Lua is compiled with a C89 compiler,
|
||||||
options @id{A} and @id{a} (hexadecimal floats)
|
the specifiers @id{A} and @id{a} (hexadecimal floats)
|
||||||
do not support any modifier (flags, width, length).
|
do not support modifiers.
|
||||||
|
|
||||||
Option @id{s} expects a string;
|
The specifier @id{s} expects a string;
|
||||||
if its argument is not a string,
|
if its argument is not a string,
|
||||||
it is converted to one following the same rules of @Lid{tostring}.
|
it is converted to one following the same rules of @Lid{tostring}.
|
||||||
If the option has any modifier (flags, width, length),
|
If the specifier has any modifier,
|
||||||
the string argument should not contain @x{embedded zeros}.
|
the corresponding string argument should not contain @x{embedded zeros}.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8009,8 +8013,8 @@ or there is any input from some special files
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
For the last two cases, @id{size}
|
For the last two cases,
|
||||||
specifies the size of the buffer, in bytes.
|
@id{size} is a hint for the size of the buffer, in bytes.
|
||||||
The default is an appropriate size.
|
The default is an appropriate size.
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -8698,6 +8702,12 @@ When a coroutine finishes with an error,
|
|||||||
its stack is unwound (to run any pending closing methods).
|
its stack is unwound (to run any pending closing methods).
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@item{
|
||||||
|
A label for a @Rw{goto} cannot be declared where a label with the same
|
||||||
|
name is visible, even if this other label is declared in an enclosing
|
||||||
|
block.
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -332,6 +332,7 @@ function to (s, x, n)
|
|||||||
return T.testC(string.format("%s %d; return 1", s, n), x)
|
return T.testC(string.format("%s %d; return 1", s, n), x)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local null = T.pushuserdata(0)
|
||||||
local hfunc = string.gmatch("", "") -- a "heavy C function" (with upvalues)
|
local hfunc = string.gmatch("", "") -- a "heavy C function" (with upvalues)
|
||||||
assert(debug.getupvalue(hfunc, 1))
|
assert(debug.getupvalue(hfunc, 1))
|
||||||
assert(to("tostring", {}) == nil)
|
assert(to("tostring", {}) == nil)
|
||||||
@@ -349,13 +350,19 @@ assert(to("tonumber", {}) == 0)
|
|||||||
assert(to("tonumber", "12") == 12)
|
assert(to("tonumber", "12") == 12)
|
||||||
assert(to("tonumber", "s2") == 0)
|
assert(to("tonumber", "s2") == 0)
|
||||||
assert(to("tonumber", 1, 20) == 0)
|
assert(to("tonumber", 1, 20) == 0)
|
||||||
assert(to("topointer", 10) == 0)
|
assert(to("topointer", 10) == null)
|
||||||
assert(to("topointer", true) == 0)
|
assert(to("topointer", true) == null)
|
||||||
assert(to("topointer", T.pushuserdata(20)) == 20)
|
assert(to("topointer", nil) == null)
|
||||||
assert(to("topointer", io.read) ~= 0) -- light C function
|
assert(to("topointer", "abc") ~= null)
|
||||||
assert(to("topointer", hfunc) ~= 0) -- "heavy" C function
|
assert(to("topointer", string.rep("x", 10)) ==
|
||||||
assert(to("topointer", function () end) ~= 0) -- Lua function
|
to("topointer", string.rep("x", 10))) -- short strings
|
||||||
assert(to("topointer", io.stdin) ~= 0) -- full userdata
|
assert(to("topointer", string.rep("x", 300)) ~=
|
||||||
|
to("topointer", string.rep("x", 300))) -- long strings
|
||||||
|
assert(to("topointer", T.pushuserdata(20)) ~= null)
|
||||||
|
assert(to("topointer", io.read) ~= null) -- light C function
|
||||||
|
assert(to("topointer", hfunc) ~= null) -- "heavy" C function
|
||||||
|
assert(to("topointer", function () end) ~= null) -- Lua function
|
||||||
|
assert(to("topointer", io.stdin) ~= null) -- full userdata
|
||||||
assert(to("func2num", 20) == 0)
|
assert(to("func2num", 20) == 0)
|
||||||
assert(to("func2num", T.pushuserdata(10)) == 0)
|
assert(to("func2num", T.pushuserdata(10)) == 0)
|
||||||
assert(to("func2num", io.read) ~= 0) -- light C function
|
assert(to("func2num", io.read) ~= 0) -- light C function
|
||||||
|
|||||||
@@ -199,6 +199,7 @@ end
|
|||||||
|
|
||||||
assert(string.format("\0%s\0", "\0\0\1") == "\0\0\0\1\0")
|
assert(string.format("\0%s\0", "\0\0\1") == "\0\0\0\1\0")
|
||||||
checkerror("contains zeros", string.format, "%10s", "\0")
|
checkerror("contains zeros", string.format, "%10s", "\0")
|
||||||
|
checkerror("cannot have modifiers", string.format, "%10q", "1")
|
||||||
|
|
||||||
-- format x tostring
|
-- format x tostring
|
||||||
assert(string.format("%s %s", nil, true) == "nil true")
|
assert(string.format("%s %s", nil, true) == "nil true")
|
||||||
|
|||||||
Reference in New Issue
Block a user