diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-03-13 13:16:53 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-03-13 13:16:53 -0300 |
commit | cf71a5ddc742692fad813f89f1c9ef53e1ffde0f (patch) | |
tree | df02305ff3cf05908f21829384e3a7f8699d2331 | |
parent | 2c32bff60987d38a60a58d4f0123f3783da60a63 (diff) | |
download | lua-cf71a5ddc742692fad813f89f1c9ef53e1ffde0f.tar.gz lua-cf71a5ddc742692fad813f89f1c9ef53e1ffde0f.tar.bz2 lua-cf71a5ddc742692fad813f89f1c9ef53e1ffde0f.zip |
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)
-rw-r--r-- | lapi.c | 31 | ||||
-rw-r--r-- | lfunc.c | 3 | ||||
-rw-r--r-- | lopcodes.h | 15 | ||||
-rw-r--r-- | lstrlib.c | 6 | ||||
-rw-r--r-- | ltests.c | 7 | ||||
-rw-r--r-- | manual/manual.of | 54 | ||||
-rw-r--r-- | testes/api.lua | 21 | ||||
-rw-r--r-- | testes/strings.lua | 1 |
8 files changed, 87 insertions, 51 deletions
@@ -414,8 +414,7 @@ LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { | |||
414 | } | 414 | } |
415 | 415 | ||
416 | 416 | ||
417 | LUA_API void *lua_touserdata (lua_State *L, int idx) { | 417 | static void *touserdata (const TValue *o) { |
418 | const TValue *o = index2value(L, idx); | ||
419 | switch (ttype(o)) { | 418 | switch (ttype(o)) { |
420 | case LUA_TUSERDATA: return getudatamem(uvalue(o)); | 419 | case LUA_TUSERDATA: return getudatamem(uvalue(o)); |
421 | case LUA_TLIGHTUSERDATA: return pvalue(o); | 420 | case LUA_TLIGHTUSERDATA: return pvalue(o); |
@@ -424,23 +423,37 @@ LUA_API void *lua_touserdata (lua_State *L, int idx) { | |||
424 | } | 423 | } |
425 | 424 | ||
426 | 425 | ||
426 | LUA_API void *lua_touserdata (lua_State *L, int idx) { | ||
427 | const TValue *o = index2value(L, idx); | ||
428 | return touserdata(o); | ||
429 | } | ||
430 | |||
431 | |||
427 | LUA_API lua_State *lua_tothread (lua_State *L, int idx) { | 432 | LUA_API lua_State *lua_tothread (lua_State *L, int idx) { |
428 | const TValue *o = index2value(L, idx); | 433 | const TValue *o = index2value(L, idx); |
429 | return (!ttisthread(o)) ? NULL : thvalue(o); | 434 | return (!ttisthread(o)) ? NULL : thvalue(o); |
430 | } | 435 | } |
431 | 436 | ||
432 | 437 | ||
438 | /* | ||
439 | ** Returns a pointer to the internal representation of an object. | ||
440 | ** Note that ANSI C does not allow the conversion of a pointer to | ||
441 | ** function to a 'void*', so the conversion here goes through | ||
442 | ** a 'size_t'. (As the returned pointer is only informative, this | ||
443 | ** conversion should not be a problem.) | ||
444 | */ | ||
433 | LUA_API const void *lua_topointer (lua_State *L, int idx) { | 445 | LUA_API const void *lua_topointer (lua_State *L, int idx) { |
434 | const TValue *o = index2value(L, idx); | 446 | const TValue *o = index2value(L, idx); |
435 | switch (ttypetag(o)) { | 447 | switch (ttypetag(o)) { |
436 | case LUA_TTABLE: return hvalue(o); | ||
437 | case LUA_TLCL: return clLvalue(o); | ||
438 | case LUA_TCCL: return clCvalue(o); | ||
439 | case LUA_TLCF: return cast_voidp(cast_sizet(fvalue(o))); | 448 | case LUA_TLCF: return cast_voidp(cast_sizet(fvalue(o))); |
440 | case LUA_TTHREAD: return thvalue(o); | 449 | case LUA_TUSERDATA: case LUA_TLIGHTUSERDATA: |
441 | case LUA_TUSERDATA: return getudatamem(uvalue(o)); | 450 | return touserdata(o); |
442 | case LUA_TLIGHTUSERDATA: return pvalue(o); | 451 | default: { |
443 | default: return NULL; | 452 | if (iscollectable(o)) |
453 | return gcvalue(o); | ||
454 | else | ||
455 | return NULL; | ||
456 | } | ||
444 | } | 457 | } |
445 | } | 458 | } |
446 | 459 | ||
@@ -138,7 +138,8 @@ static int callclosemth (lua_State *L, TValue *uv, StkId level, int status) { | |||
138 | if (prepclosingmethod(L, uv, &G(L)->nilvalue)) /* something to call? */ | 138 | if (prepclosingmethod(L, uv, &G(L)->nilvalue)) /* something to call? */ |
139 | callclose(L, NULL); /* call closing method */ | 139 | callclose(L, NULL); /* call closing method */ |
140 | else if (!ttisnil(uv)) { /* non-closable non-nil value? */ | 140 | else if (!ttisnil(uv)) { /* non-closable non-nil value? */ |
141 | const char *vname = luaG_findlocal(L, L->ci, level - L->ci->func, NULL); | 141 | int idx = cast_int(level - L->ci->func); |
142 | const char *vname = luaG_findlocal(L, L->ci, idx, NULL); | ||
142 | if (vname == NULL) vname = "?"; | 143 | if (vname == NULL) vname = "?"; |
143 | luaG_runerror(L, "attempt to close non-closable variable '%s'", vname); | 144 | luaG_runerror(L, "attempt to close non-closable variable '%s'", vname); |
144 | } | 145 | } |
@@ -90,7 +90,6 @@ enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */ | |||
90 | #define MAXARG_B ((1<<SIZE_B)-1) | 90 | #define MAXARG_B ((1<<SIZE_B)-1) |
91 | #define MAXARG_C ((1<<SIZE_C)-1) | 91 | #define MAXARG_C ((1<<SIZE_C)-1) |
92 | #define OFFSET_sC (MAXARG_C >> 1) | 92 | #define OFFSET_sC (MAXARG_C >> 1) |
93 | #define MAXARG_Cx ((1<<(SIZE_C + 1))-1) | ||
94 | 93 | ||
95 | 94 | ||
96 | /* creates a mask with 'n' 1 bits at position 'p' */ | 95 | /* 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 */ | |||
233 | OP_BORK,/* A B C R(A) := R(B) | K(C):integer */ | 232 | OP_BORK,/* A B C R(A) := R(B) | K(C):integer */ |
234 | OP_BXORK,/* A B C R(A) := R(B) ~ K(C):integer */ | 233 | OP_BXORK,/* A B C R(A) := R(B) ~ K(C):integer */ |
235 | 234 | ||
236 | OP_SHRI,/* A B C R(A) := R(B) >> C */ | 235 | OP_SHRI,/* A B sC R(A) := R(B) >> C */ |
237 | OP_SHLI,/* A B C R(A) := C << R(B) */ | 236 | OP_SHLI,/* A B sC R(A) := C << R(B) */ |
238 | 237 | ||
239 | OP_ADD,/* A B C R(A) := R(B) + R(C) */ | 238 | OP_ADD,/* A B C R(A) := R(B) + R(C) */ |
240 | OP_SUB,/* A B C R(A) := R(B) - R(C) */ | 239 | 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++ */ | |||
272 | OP_GEI,/* A sB if ((R(A) >= sB) ~= k) then pc++ */ | 271 | OP_GEI,/* A sB if ((R(A) >= sB) ~= k) then pc++ */ |
273 | 272 | ||
274 | OP_TEST,/* A if (not R(A) == k) then pc++ */ | 273 | OP_TEST,/* A if (not R(A) == k) then pc++ */ |
275 | OP_TESTSET,/* A B if (not R(B) == k) then R(A) := R(B) else pc++ */ | 274 | OP_TESTSET,/* A B if (not R(B) == k) then pc++ else R(A) := R(B) */ |
276 | 275 | ||
277 | OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ | 276 | OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ |
278 | OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ | 277 | 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 */ | |||
305 | } OpCode; | 304 | } OpCode; |
306 | 305 | ||
307 | 306 | ||
308 | #define NUM_OPCODES (cast_int(OP_EXTRAARG) + 1) | 307 | #define NUM_OPCODES ((int)(OP_EXTRAARG) + 1) |
309 | 308 | ||
310 | 309 | ||
311 | 310 | ||
312 | /*=========================================================================== | 311 | /*=========================================================================== |
313 | Notes: | 312 | Notes: |
314 | (*) In OP_CALL, if (B == 0) then B = top. If (C == 0), then 'top' is | 313 | (*) In OP_CALL, if (B == 0) then B = top - A. If (C == 0), then |
315 | set to last_result+1, so next open instruction (OP_CALL, OP_RETURN*, | 314 | 'top' is set to last_result+1, so next open instruction (OP_CALL, |
316 | OP_SETLIST) may use 'top'. | 315 | OP_RETURN*, OP_SETLIST) may use 'top'. |
317 | 316 | ||
318 | (*) In OP_VARARG, if (C == 0) then use actual number of varargs and | 317 | (*) In OP_VARARG, if (C == 0) then use actual number of varargs and |
319 | set top (like in OP_CALL with C == 0). | 318 | set top (like in OP_CALL with C == 0). |
@@ -181,7 +181,7 @@ static int str_byte (lua_State *L) { | |||
181 | size_t pose = getendpos(L, 3, pi, l); | 181 | size_t pose = getendpos(L, 3, pi, l); |
182 | int n, i; | 182 | int n, i; |
183 | if (posi > pose) return 0; /* empty interval; return no values */ | 183 | if (posi > pose) return 0; /* empty interval; return no values */ |
184 | if (pose - posi >= INT_MAX) /* arithmetic overflow? */ | 184 | if (pose - posi >= (size_t)INT_MAX) /* arithmetic overflow? */ |
185 | return luaL_error(L, "string slice too long"); | 185 | return luaL_error(L, "string slice too long"); |
186 | n = (int)(pose - posi) + 1; | 186 | n = (int)(pose - posi) + 1; |
187 | luaL_checkstack(L, n, "string slice too long"); | 187 | luaL_checkstack(L, n, "string slice too long"); |
@@ -1159,7 +1159,7 @@ static int str_format (lua_State *L) { | |||
1159 | char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ | 1159 | char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ |
1160 | int nb = 0; /* number of bytes in added item */ | 1160 | int nb = 0; /* number of bytes in added item */ |
1161 | if (++arg > top) | 1161 | if (++arg > top) |
1162 | luaL_argerror(L, arg, "no value"); | 1162 | return luaL_argerror(L, arg, "no value"); |
1163 | strfrmt = scanformat(L, strfrmt, form); | 1163 | strfrmt = scanformat(L, strfrmt, form); |
1164 | switch (*strfrmt++) { | 1164 | switch (*strfrmt++) { |
1165 | case 'c': { | 1165 | case 'c': { |
@@ -1186,6 +1186,8 @@ static int str_format (lua_State *L) { | |||
1186 | break; | 1186 | break; |
1187 | } | 1187 | } |
1188 | case 'q': { | 1188 | case 'q': { |
1189 | if (form[2] != '\0') /* modifiers? */ | ||
1190 | return luaL_error(L, "specifier '%%q' cannot have modifiers"); | ||
1189 | addliteral(L, &b, arg); | 1191 | addliteral(L, &b, arg); |
1190 | break; | 1192 | break; |
1191 | } | 1193 | } |
@@ -164,7 +164,7 @@ typedef union Header { | |||
164 | 164 | ||
165 | 165 | ||
166 | Memcontrol l_memcontrol = | 166 | Memcontrol l_memcontrol = |
167 | {0L, 0L, 0L, 0L, (~0L), {0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L}}; | 167 | {0UL, 0UL, 0UL, 0UL, (~0UL), {0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL}}; |
168 | 168 | ||
169 | 169 | ||
170 | static void freeblock (Memcontrol *mc, Header *block) { | 170 | static void freeblock (Memcontrol *mc, Header *block) { |
@@ -1596,7 +1596,10 @@ static struct X { int x; } x; | |||
1596 | lua_pushnumber(L1, lua_tonumber(L1, getindex)); | 1596 | lua_pushnumber(L1, lua_tonumber(L1, getindex)); |
1597 | } | 1597 | } |
1598 | else if EQ("topointer") { | 1598 | else if EQ("topointer") { |
1599 | lua_pushnumber(L1, cast_sizet(lua_topointer(L1, getindex))); | 1599 | lua_pushlightuserdata(L1, cast_voidp(lua_topointer(L1, getindex))); |
1600 | } | ||
1601 | else if EQ("touserdata") { | ||
1602 | lua_pushlightuserdata(L1, lua_touserdata(L1, getindex)); | ||
1600 | } | 1603 | } |
1601 | else if EQ("tostring") { | 1604 | else if EQ("tostring") { |
1602 | const char *s = lua_tostring(L1, getindex); | 1605 | const char *s = lua_tostring(L1, getindex); |
diff --git a/manual/manual.of b/manual/manual.of index 421d04de..9c8ab033 100644 --- a/manual/manual.of +++ b/manual/manual.of | |||
@@ -143,7 +143,7 @@ that is, @x{arrays} that can have as indices not only numbers, | |||
143 | but any Lua value except @nil and @x{NaN}. | 143 | but any Lua value except @nil and @x{NaN}. |
144 | (@emphx{Not a Number} is a special floating-point value | 144 | (@emphx{Not a Number} is a special floating-point value |
145 | used by the @x{IEEE 754} standard to represent | 145 | used by the @x{IEEE 754} standard to represent |
146 | undefined or unrepresentable numerical results, such as @T{0/0}.) | 146 | undefined numerical results, such as @T{0/0}.) |
147 | Tables can be @emph{heterogeneous}; | 147 | Tables can be @emph{heterogeneous}; |
148 | that is, they can contain values of all types (except @nil). | 148 | that is, they can contain values of all types (except @nil). |
149 | Any key with value @nil is not considered part of the table. | 149 | 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 | |||
670 | corresponding table or userdata is unreachable. | 670 | corresponding table or userdata is unreachable. |
671 | Finalizers allow you to coordinate Lua's garbage collection | 671 | Finalizers allow you to coordinate Lua's garbage collection |
672 | with external resource management | 672 | with external resource management |
673 | (such as closing files, network or database connections, | 673 | such as closing files, network or database connections, |
674 | or freeing your own memory). | 674 | or freeing your own memory. |
675 | 675 | ||
676 | For an object (table or userdata) to be finalized when collected, | 676 | For an object (table or userdata) to be finalized when collected, |
677 | you must @emph{mark} it for finalization. | 677 | you must @emph{mark} it for finalization. |
@@ -1323,11 +1323,12 @@ labels in Lua are considered statements too: | |||
1323 | } | 1323 | } |
1324 | 1324 | ||
1325 | A label is visible in the entire block where it is defined, | 1325 | A label is visible in the entire block where it is defined, |
1326 | except | 1326 | except inside nested functions. |
1327 | inside nested blocks where a label with the same name is defined and | ||
1328 | inside nested functions. | ||
1329 | A goto may jump to any visible label as long as it does not | 1327 | A goto may jump to any visible label as long as it does not |
1330 | enter into the scope of a local variable. | 1328 | enter into the scope of a local variable. |
1329 | A label should not be declared | ||
1330 | where a label with the same name is visible, | ||
1331 | even if this other label has been declared in an enclosing block. | ||
1331 | 1332 | ||
1332 | Labels and empty statements are called @def{void statements}, | 1333 | Labels and empty statements are called @def{void statements}, |
1333 | as they perform no actions. | 1334 | as they perform no actions. |
@@ -1537,7 +1538,7 @@ goes out of scope, including normal block termination, | |||
1537 | exiting its block by @Rw{break}/@Rw{goto}/@Rw{return}, | 1538 | exiting its block by @Rw{break}/@Rw{goto}/@Rw{return}, |
1538 | or exiting by an error. | 1539 | or exiting by an error. |
1539 | 1540 | ||
1540 | Here, to \emph{close} a value means | 1541 | Here, to @emph{close} a value means |
1541 | to call its @idx{__close} metamethod. | 1542 | to call its @idx{__close} metamethod. |
1542 | If the value is @nil, it is ignored; | 1543 | If the value is @nil, it is ignored; |
1543 | otherwise, | 1544 | otherwise, |
@@ -4236,7 +4237,7 @@ indicates whether the operation succeeded. | |||
4236 | 4237 | ||
4237 | Converts the value at the given index to a generic | 4238 | Converts the value at the given index to a generic |
4238 | @N{C pointer} (@T{void*}). | 4239 | @N{C pointer} (@T{void*}). |
4239 | The value can be a userdata, a table, a thread, or a function; | 4240 | The value can be a userdata, a table, a thread, a string, or a function; |
4240 | otherwise, @id{lua_topointer} returns @id{NULL}. | 4241 | otherwise, @id{lua_topointer} returns @id{NULL}. |
4241 | Different objects will give different pointers. | 4242 | Different objects will give different pointers. |
4242 | There is no way to convert the pointer back to its original value. | 4243 | There is no way to convert the pointer back to its original value. |
@@ -6712,8 +6713,10 @@ to save space. | |||
6712 | 6713 | ||
6713 | Functions with upvalues have only their number of upvalues saved. | 6714 | Functions with upvalues have only their number of upvalues saved. |
6714 | When (re)loaded, | 6715 | When (re)loaded, |
6715 | those upvalues receive fresh instances containing @nil. | 6716 | those upvalues receive fresh instances. |
6716 | (You can use the debug library to serialize | 6717 | (See the @Lid{load} function for details about |
6718 | how these upvalues are initialized. | ||
6719 | You can use the debug library to serialize | ||
6717 | and reload the upvalues of a function | 6720 | and reload the upvalues of a function |
6718 | in a way adequate to your needs.) | 6721 | in a way adequate to your needs.) |
6719 | 6722 | ||
@@ -6747,12 +6750,12 @@ after the two indices. | |||
6747 | Returns a formatted version of its variable number of arguments | 6750 | Returns a formatted version of its variable number of arguments |
6748 | following the description given in its first argument (which must be a string). | 6751 | following the description given in its first argument (which must be a string). |
6749 | The format string follows the same rules as the @ANSI{sprintf}. | 6752 | The format string follows the same rules as the @ANSI{sprintf}. |
6750 | The only differences are that the options/modifiers | 6753 | The only differences are that the conversion specifiers and modifiers |
6751 | @T{*}, @id{h}, @id{L}, @id{l}, @id{n}, | 6754 | @T{*}, @id{h}, @id{L}, @id{l}, @id{n}, |
6752 | and @id{p} are not supported | 6755 | and @id{p} are not supported |
6753 | and that there is an extra option, @id{q}. | 6756 | and that there is an extra specifier, @id{q}. |
6754 | 6757 | ||
6755 | The @id{q} option formats booleans, nil, numbers, and strings | 6758 | The specifier @id{q} formats booleans, nil, numbers, and strings |
6756 | in a way that the result is a valid constant in Lua source code. | 6759 | in a way that the result is a valid constant in Lua source code. |
6757 | Booleans and nil are written in the obvious way | 6760 | Booleans and nil are written in the obvious way |
6758 | (@id{true}, @id{false}, @id{nil}). | 6761 | (@id{true}, @id{false}, @id{nil}). |
@@ -6770,22 +6773,23 @@ may produce the string: | |||
6770 | "a string with \"quotes\" and \ | 6773 | "a string with \"quotes\" and \ |
6771 | new line" | 6774 | new line" |
6772 | } | 6775 | } |
6776 | This specifier does not support modifiers (flags, width, length). | ||
6773 | 6777 | ||
6774 | Options | 6778 | The conversion specifiers |
6775 | @id{A}, @id{a}, @id{E}, @id{e}, @id{f}, | 6779 | @id{A}, @id{a}, @id{E}, @id{e}, @id{f}, |
6776 | @id{G}, and @id{g} all expect a number as argument. | 6780 | @id{G}, and @id{g} all expect a number as argument. |
6777 | Options @id{c}, @id{d}, | 6781 | The specifiers @id{c}, @id{d}, |
6778 | @id{i}, @id{o}, @id{u}, @id{X}, and @id{x} | 6782 | @id{i}, @id{o}, @id{u}, @id{X}, and @id{x} |
6779 | expect an integer. | 6783 | expect an integer. |
6780 | When Lua is compiled with a C89 compiler, | 6784 | When Lua is compiled with a C89 compiler, |
6781 | options @id{A} and @id{a} (hexadecimal floats) | 6785 | the specifiers @id{A} and @id{a} (hexadecimal floats) |
6782 | do not support any modifier (flags, width, length). | 6786 | do not support modifiers. |
6783 | 6787 | ||
6784 | Option @id{s} expects a string; | 6788 | The specifier @id{s} expects a string; |
6785 | if its argument is not a string, | 6789 | if its argument is not a string, |
6786 | it is converted to one following the same rules of @Lid{tostring}. | 6790 | it is converted to one following the same rules of @Lid{tostring}. |
6787 | If the option has any modifier (flags, width, length), | 6791 | If the specifier has any modifier, |
6788 | the string argument should not contain @x{embedded zeros}. | 6792 | the corresponding string argument should not contain @x{embedded zeros}. |
6789 | 6793 | ||
6790 | } | 6794 | } |
6791 | 6795 | ||
@@ -8009,8 +8013,8 @@ or there is any input from some special files | |||
8009 | } | 8013 | } |
8010 | 8014 | ||
8011 | } | 8015 | } |
8012 | For the last two cases, @id{size} | 8016 | For the last two cases, |
8013 | specifies the size of the buffer, in bytes. | 8017 | @id{size} is a hint for the size of the buffer, in bytes. |
8014 | The default is an appropriate size. | 8018 | The default is an appropriate size. |
8015 | 8019 | ||
8016 | } | 8020 | } |
@@ -8698,6 +8702,12 @@ When a coroutine finishes with an error, | |||
8698 | its stack is unwound (to run any pending closing methods). | 8702 | its stack is unwound (to run any pending closing methods). |
8699 | } | 8703 | } |
8700 | 8704 | ||
8705 | @item{ | ||
8706 | A label for a @Rw{goto} cannot be declared where a label with the same | ||
8707 | name is visible, even if this other label is declared in an enclosing | ||
8708 | block. | ||
8709 | } | ||
8710 | |||
8701 | } | 8711 | } |
8702 | 8712 | ||
8703 | } | 8713 | } |
diff --git a/testes/api.lua b/testes/api.lua index 9904dadf..d034ea80 100644 --- a/testes/api.lua +++ b/testes/api.lua | |||
@@ -332,6 +332,7 @@ function to (s, x, n) | |||
332 | return T.testC(string.format("%s %d; return 1", s, n), x) | 332 | return T.testC(string.format("%s %d; return 1", s, n), x) |
333 | end | 333 | end |
334 | 334 | ||
335 | local null = T.pushuserdata(0) | ||
335 | local hfunc = string.gmatch("", "") -- a "heavy C function" (with upvalues) | 336 | local hfunc = string.gmatch("", "") -- a "heavy C function" (with upvalues) |
336 | assert(debug.getupvalue(hfunc, 1)) | 337 | assert(debug.getupvalue(hfunc, 1)) |
337 | assert(to("tostring", {}) == nil) | 338 | assert(to("tostring", {}) == nil) |
@@ -349,13 +350,19 @@ assert(to("tonumber", {}) == 0) | |||
349 | assert(to("tonumber", "12") == 12) | 350 | assert(to("tonumber", "12") == 12) |
350 | assert(to("tonumber", "s2") == 0) | 351 | assert(to("tonumber", "s2") == 0) |
351 | assert(to("tonumber", 1, 20) == 0) | 352 | assert(to("tonumber", 1, 20) == 0) |
352 | assert(to("topointer", 10) == 0) | 353 | assert(to("topointer", 10) == null) |
353 | assert(to("topointer", true) == 0) | 354 | assert(to("topointer", true) == null) |
354 | assert(to("topointer", T.pushuserdata(20)) == 20) | 355 | assert(to("topointer", nil) == null) |
355 | assert(to("topointer", io.read) ~= 0) -- light C function | 356 | assert(to("topointer", "abc") ~= null) |
356 | assert(to("topointer", hfunc) ~= 0) -- "heavy" C function | 357 | assert(to("topointer", string.rep("x", 10)) == |
357 | assert(to("topointer", function () end) ~= 0) -- Lua function | 358 | to("topointer", string.rep("x", 10))) -- short strings |
358 | assert(to("topointer", io.stdin) ~= 0) -- full userdata | 359 | assert(to("topointer", string.rep("x", 300)) ~= |
360 | to("topointer", string.rep("x", 300))) -- long strings | ||
361 | assert(to("topointer", T.pushuserdata(20)) ~= null) | ||
362 | assert(to("topointer", io.read) ~= null) -- light C function | ||
363 | assert(to("topointer", hfunc) ~= null) -- "heavy" C function | ||
364 | assert(to("topointer", function () end) ~= null) -- Lua function | ||
365 | assert(to("topointer", io.stdin) ~= null) -- full userdata | ||
359 | assert(to("func2num", 20) == 0) | 366 | assert(to("func2num", 20) == 0) |
360 | assert(to("func2num", T.pushuserdata(10)) == 0) | 367 | assert(to("func2num", T.pushuserdata(10)) == 0) |
361 | assert(to("func2num", io.read) ~= 0) -- light C function | 368 | assert(to("func2num", io.read) ~= 0) -- light C function |
diff --git a/testes/strings.lua b/testes/strings.lua index 88480924..da53a87e 100644 --- a/testes/strings.lua +++ b/testes/strings.lua | |||
@@ -199,6 +199,7 @@ end | |||
199 | 199 | ||
200 | assert(string.format("\0%s\0", "\0\0\1") == "\0\0\0\1\0") | 200 | assert(string.format("\0%s\0", "\0\0\1") == "\0\0\0\1\0") |
201 | checkerror("contains zeros", string.format, "%10s", "\0") | 201 | checkerror("contains zeros", string.format, "%10s", "\0") |
202 | checkerror("cannot have modifiers", string.format, "%10q", "1") | ||
202 | 203 | ||
203 | -- format x tostring | 204 | -- format x tostring |
204 | assert(string.format("%s %s", nil, true) == "nil true") | 205 | assert(string.format("%s %s", nil, true) == "nil true") |