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") |
