Added macro 'luaL_pushfail'

The macro 'luaL_pushfail' documents all places in the standard libraries
that return nil to signal some kind of failure. It is defined as
'lua_pushnil'. The manual also got a notation (@fail) to document those
returns. The tests were changed to be agnostic regarding whether 'fail'
is 'nil' or 'false'.
This commit is contained in:
Roberto Ierusalimschy 2019-08-16 14:58:02 -03:00
parent ca13be9af7
commit b96b0b5abb
20 changed files with 176 additions and 154 deletions

View File

@ -249,7 +249,7 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
return 1;
}
else {
lua_pushnil(L);
luaL_pushfail(L);
if (fname)
lua_pushfstring(L, "%s: %s", fname, strerror(en));
else
@ -291,10 +291,10 @@ LUALIB_API int luaL_execresult (lua_State *L, int stat) {
if (*what == 'e' && stat == 0) /* successful termination? */
lua_pushboolean(L, 1);
else
lua_pushnil(L);
luaL_pushfail(L);
lua_pushstring(L, what);
lua_pushinteger(L, stat);
return 3; /* return true/nil,what,code */
return 3; /* return true/fail,what,code */
}
}

View File

@ -153,6 +153,10 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL)
/* push the value used to represent failure/error */
#define luaL_pushfail(L) lua_pushnil(L)
/*
** {======================================================
** Generic Buffer manipulation

View File

@ -106,7 +106,7 @@ static int luaB_tonumber (lua_State *L) {
return 1;
} /* else not a number */
} /* else not a number */
lua_pushnil(L); /* not a number */
luaL_pushfail(L); /* not a number */
return 1;
}
@ -308,9 +308,9 @@ static int load_aux (lua_State *L, int status, int envidx) {
return 1;
}
else { /* error (message is on top of the stack) */
lua_pushnil(L);
luaL_pushfail(L);
lua_insert(L, -2); /* put before error message */
return 2; /* return nil plus error message */
return 2; /* return fail plus error message */
}
}

View File

@ -65,7 +65,7 @@ static int db_setmetatable (lua_State *L) {
static int db_getuservalue (lua_State *L) {
int n = (int)luaL_optinteger(L, 2, 1);
if (lua_type(L, 1) != LUA_TUSERDATA)
lua_pushnil(L);
luaL_pushfail(L);
else if (lua_getiuservalue(L, 1, n) != LUA_TNONE) {
lua_pushboolean(L, 1);
return 2;
@ -80,7 +80,7 @@ static int db_setuservalue (lua_State *L) {
luaL_checkany(L, 2);
lua_settop(L, 2);
if (!lua_setiuservalue(L, 1, n))
lua_pushnil(L);
luaL_pushfail(L);
return 1;
}
@ -159,7 +159,7 @@ static int db_getinfo (lua_State *L) {
}
else { /* stack level */
if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) {
lua_pushnil(L); /* level out of range */
luaL_pushfail(L); /* level out of range */
return 1;
}
}
@ -223,7 +223,7 @@ static int db_getlocal (lua_State *L) {
return 2;
}
else {
lua_pushnil(L); /* no name (nor value) */
luaL_pushfail(L); /* no name (nor value) */
return 1;
}
}
@ -389,8 +389,10 @@ static int db_gethook (lua_State *L) {
char buff[5];
int mask = lua_gethookmask(L1);
lua_Hook hook = lua_gethook(L1);
if (hook == NULL) /* no hook? */
lua_pushnil(L);
if (hook == NULL) { /* no hook? */
luaL_pushfail(L);
return 1;
}
else if (hook != hookf) /* external hook? */
lua_pushliteral(L, "external hook");
else { /* hook table must exist */

View File

@ -153,7 +153,7 @@ static int io_type (lua_State *L) {
luaL_checkany(L, 1);
p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
if (p == NULL)
lua_pushnil(L); /* not a file */
luaL_pushfail(L); /* not a file */
else if (isclosed(p))
lua_pushliteral(L, "closed file");
else
@ -593,7 +593,7 @@ static int g_read (lua_State *L, FILE *f, int first) {
return luaL_fileresult(L, 0, NULL);
if (!success) {
lua_pop(L, 1); /* remove last result */
lua_pushnil(L); /* push nil instead */
luaL_pushfail(L); /* push nil instead */
}
return n - first;
}
@ -624,9 +624,9 @@ static int io_readline (lua_State *L) {
lua_pushvalue(L, lua_upvalueindex(3 + i));
n = g_read(L, p->f, 2); /* 'n' is number of results */
lua_assert(n > 0); /* should return at least a nil */
if (!lua_isnil(L, -n)) /* read at least one value? */
if (lua_toboolean(L, -n)) /* read at least one value? */
return n; /* return them */
else { /* first result is nil: EOF or error */
else { /* first result is false: EOF or error */
if (n > 1) { /* is there error information? */
/* 2nd result is error message */
return luaL_error(L, "%s", lua_tostring(L, -n + 1));
@ -782,7 +782,7 @@ static void createmeta (lua_State *L) {
static int io_noclose (lua_State *L) {
LStream *p = tolstream(L);
p->closef = &io_noclose; /* keep file opened */
lua_pushnil(L);
luaL_pushfail(L);
lua_pushliteral(L, "cannot close standard file");
return 2;
}

View File

@ -77,7 +77,7 @@ static int math_toint (lua_State *L) {
lua_pushinteger(L, n);
else {
luaL_checkany(L, 1);
lua_pushnil(L); /* value is not convertible to integer */
luaL_pushfail(L); /* value is not convertible to integer */
}
return 1;
}
@ -235,7 +235,7 @@ static int math_type (lua_State *L) {
lua_pushstring(L, (lua_isinteger(L, 1)) ? "integer" : "float");
else {
luaL_checkany(L, 1);
lua_pushnil(L);
luaL_pushfail(L);
}
return 1;
}

View File

@ -408,10 +408,10 @@ static int ll_loadlib (lua_State *L) {
if (stat == 0) /* no errors? */
return 1; /* return the loaded function */
else { /* error; error message is on stack top */
lua_pushnil(L);
luaL_pushfail(L);
lua_insert(L, -2);
lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init");
return 3; /* return nil, error message, and where */
return 3; /* return fail, error message, and where */
}
}
@ -505,9 +505,9 @@ static int ll_searchpath (lua_State *L) {
luaL_optstring(L, 4, LUA_DIRSEP));
if (f != NULL) return 1;
else { /* error message is on top of the stack */
lua_pushnil(L);
luaL_pushfail(L);
lua_insert(L, -2);
return 2; /* return nil + error message */
return 2; /* return fail + error message */
}
}

View File

@ -744,7 +744,7 @@ static int str_find_aux (lua_State *L, int find) {
const char *p = luaL_checklstring(L, 2, &lp);
size_t init = posrelatI(luaL_optinteger(L, 3, 1), ls) - 1;
if (init > ls) { /* start after string's end? */
lua_pushnil(L); /* cannot find anything */
luaL_pushfail(L); /* cannot find anything */
return 1;
}
/* explicit request or no special characters? */
@ -779,7 +779,7 @@ static int str_find_aux (lua_State *L, int find) {
}
} while (s1++ < ms.src_end && !anchor);
}
lua_pushnil(L); /* not found */
luaL_pushfail(L); /* not found */
return 1;
}

View File

@ -103,7 +103,7 @@ static int utflen (lua_State *L) {
while (posi <= posj) {
const char *s1 = utf8_decode(s + posi, NULL, !lax);
if (s1 == NULL) { /* conversion error? */
lua_pushnil(L); /* return nil ... */
luaL_pushfail(L); /* return fail ... */
lua_pushinteger(L, posi + 1); /* ... and current position */
return 2;
}
@ -216,7 +216,7 @@ static int byteoffset (lua_State *L) {
if (n == 0) /* did it find given character? */
lua_pushinteger(L, posi + 1);
else /* no such character */
lua_pushnil(L);
luaL_pushfail(L);
return 1;
}

View File

@ -324,6 +324,7 @@ N = function (s) return (string.gsub(s, " ", "&nbsp;")) end,
NE = id, -- tag"foreignphrase",
num = id,
["nil"] = fixed(Tag.b"nil"),
fail = fixed(Tag.b"fail"),
Open = fixed"{",
part = section("h1", true),
Pat = compose(verbfixed, prepos("'", "'")),

View File

@ -4058,12 +4058,15 @@ Returns 0 if the userdata does not have that value.
}
@APIEntry{void lua_setmetatable (lua_State *L, int index);|
@APIEntry{int lua_setmetatable (lua_State *L, int index);|
@apii{1,0,-}
Pops a table from the stack and
sets it as the new metatable for the value at the given index.
(For historical reasons, this function returns an @id{int},
which now is always 1.)
}
@APIEntry{void lua_settable (lua_State *L, int index);|
@ -5782,7 +5785,7 @@ that will be called to close the stream
when the handle is closed or collected;
this function receives the file handle as its sole argument and
must return either @true, in case of success,
or @nil plus an error message, in case of error.
or a false value plus an error message, in case of error.
Once Lua calls this field,
it changes the field value to @id{NULL}
to signal that the handle is closed.
@ -5904,6 +5907,14 @@ to its expected parameters.
For instance, a function documented as @T{foo(arg)}
should not be called without an argument.
The notation @fail means a return value representing
some kind of failure or the absence of a better value to return.
Currently, @fail is equal to @nil,
but that may change in future versions.
The recommendation is to test the success of these functions
with @T{(not status)}, instead of @T{(status == nil)}.
Currently, Lua has the following standard libraries:
@itemize{
@ -6108,8 +6119,8 @@ with previous results.
A return of an empty string, @nil, or no value signals the end of the chunk.
If there are no syntactic errors,
returns the compiled chunk as a function;
otherwise, returns @nil plus the error message.
@id{load} returns the compiled chunk as a function;
otherwise, it returns @fail plus the error message.
When you load a main chunk,
the resulting function will always have exactly one upvalue,
@ -6301,7 +6312,7 @@ When called with no @id{base},
If the argument is already a number or
a string convertible to a number,
then @id{tonumber} returns this number;
otherwise, it returns @nil.
otherwise, it returns @fail.
The conversion of strings can result in integers or floats,
according to the lexical conventions of Lua @see{lexical}.
@ -6315,7 +6326,7 @@ In bases @N{above 10}, the letter @Char{A} (in either upper or lower case)
@N{represents 10}, @Char{B} @N{represents 11}, and so forth,
with @Char{Z} representing 35.
If the string @id{e} is not a valid numeral in the given base,
the function returns @nil.
the function returns @fail.
}
@ -6762,7 +6773,7 @@ will try to open the files
Returns the resulting name of the first file that it can
open in read mode (after closing the file),
or @nil plus an error message if none succeeds.
or @fail plus an error message if none succeeds.
(This error message lists all file names it tried to open.)
}
@ -6841,7 +6852,7 @@ Looks for the first match of
@id{pattern} @see{pm} in the string @id{s}.
If it finds a match, then @id{find} returns the indices @N{of @T{s}}
where this occurrence starts and ends;
otherwise, it returns @nil.
otherwise, it returns @fail.
A third, optional numeric argument @id{init} specifies
where to start the search;
its default value @N{is 1} and can be negative.
@ -7034,7 +7045,7 @@ Looks for the first @emph{match} of
the @id{pattern} @see{pm} in the string @id{s}.
If it finds one, then @id{match} returns
the captures from the pattern;
otherwise it returns @nil.
otherwise it returns @fail.
If @id{pattern} specifies no captures,
then the whole match is returned.
A third, optional numeric argument @id{init} specifies
@ -7499,7 +7510,7 @@ Returns the number of UTF-8 characters in string @id{s}
that start between positions @id{i} and @id{j} (both inclusive).
The default for @id{i} is @num{1} and for @id{j} is @num{-1}.
If it finds any invalid byte sequence,
returns a false value plus the position of the first invalid byte.
returns @fail plus the position of the first invalid byte.
}
@ -7515,7 +7526,7 @@ so that @T{utf8.offset(s, -n)} gets the offset of the
@id{n}-th character from the end of the string.
If the specified character is neither in the subject
nor right after its end,
the function returns @nil.
the function returns @fail.
As a special case,
when @id{n} is 0 the function returns the start of the encoding
@ -7850,7 +7861,7 @@ Returns the tangent of @id{x} (assumed to be in radians).
If the value @id{x} is convertible to an integer,
returns that integer.
Otherwise, returns @nil.
Otherwise, returns @fail.
}
@ -7858,7 +7869,7 @@ Otherwise, returns @nil.
Returns @St{integer} if @id{x} is an integer,
@St{float} if it is a float,
or @nil if @id{x} is not a number.
or @fail if @id{x} is not a number.
}
@ -7897,10 +7908,10 @@ three predefined file handles with their usual meanings from C:
The I/O library never closes these files.
Unless otherwise stated,
all I/O functions return @nil on failure,
all I/O functions return @fail on failure,
plus an error message as a second result and
a system-dependent error code as a third result,
and some value different from @nil on success.
and some non-false value on success.
On non-POSIX systems,
the computation of the error message and error code
in case of errors
@ -8021,7 +8032,7 @@ and it is automatically removed when the program ends.
Checks whether @id{obj} is a valid file handle.
Returns the string @T{"file"} if @id{obj} is an open file handle,
@T{"closed file"} if @id{obj} is a closed file handle,
or @nil if @id{obj} is not a file handle.
or @fail if @id{obj} is not a file handle.
}
@ -8075,7 +8086,7 @@ Reads the file @id{file},
according to the given formats, which specify what to read.
For each format,
the function returns a string or a number with the characters read,
or @nil if it cannot read data with the specified format.
or @fail if it cannot read data with the specified format.
(In this latter case,
the function does not read subsequent formats.)
When called without arguments,
@ -8094,31 +8105,32 @@ is a valid prefix for a numeral;
if that prefix does not form a valid numeral
(e.g., an empty string, @St{0x}, or @St{3.4e-})
or it is too long (more than 200 characters),
it is discarded and the format returns @nil.
it is discarded and the format returns @fail.
}
@item{@St{a}|
reads the whole file, starting at the current position.
On end of file, it returns the empty string.
On end of file, it returns the empty string;
this format never fails.
}
@item{@St{l}|
reads the next line skipping the end of line,
returning @nil on end of file.
returning @fail on end of file.
This is the default format.
}
@item{@St{L}|
reads the next line keeping the end-of-line character (if present),
returning @nil on end of file.
returning @fail on end of file.
}
@item{@emph{number}|
reads a string with up to this number of bytes,
returning @nil on end of file.
returning @fail on end of file.
If @id{number} is zero,
it reads nothing and returns an empty string,
or @nil on end of file.
or @fail on end of file.
}
}
@ -8139,7 +8151,7 @@ specified by the string @id{whence}, as follows:
}
In case of success, @id{seek} returns the final file position,
measured in bytes from the beginning of the file.
If @id{seek} fails, it returns @nil,
If @id{seek} fails, it returns @fail,
plus a string describing the error.
The default value for @id{whence} is @T{"cur"},
@ -8179,7 +8191,6 @@ Writes the value of each of its arguments to @id{file}.
The arguments must be strings or numbers.
In case of success, this function returns @id{file}.
Otherwise it returns @nil plus a string describing the error.
}
@ -8251,7 +8262,7 @@ This function is equivalent to the @ANSI{system}.
It passes @id{command} to be executed by an operating system shell.
Its first result is @true
if the command terminated successfully,
or @nil otherwise.
or @fail otherwise.
After this first result
the function returns a string plus a number,
as follows:
@ -8293,7 +8304,7 @@ closes the Lua state before exiting.
@LibEntry{os.getenv (varname)|
Returns the value of the process environment variable @id{varname},
or @nil if the variable is not defined.
or @fail if the variable is not defined.
}
@ -8301,7 +8312,7 @@ or @nil if the variable is not defined.
Deletes the file (or empty directory, on @x{POSIX} systems)
with the given name.
If this function fails, it returns @nil,
If this function fails, it returns @fail
plus a string describing the error and the error code.
Otherwise, it returns true.
@ -8310,7 +8321,7 @@ Otherwise, it returns true.
@LibEntry{os.rename (oldname, newname)|
Renames the file or directory named @id{oldname} to @id{newname}.
If this function fails, it returns @nil,
If this function fails, it returns @fail,
plus a string describing the error and the error code.
Otherwise, it returns true.
@ -8325,7 +8336,7 @@ Sets the current locale of the program.
@T{"monetary"}, @T{"numeric"}, or @T{"time"};
the default category is @T{"all"}.
The function returns the name of the new locale,
or @nil if the request cannot be honored.
or @fail if the request cannot be honored.
If @id{locale} is the empty string,
the current locale is set to an implementation-defined native locale.
@ -8444,6 +8455,8 @@ the current hook function, the current hook mask,
and the current hook count,
as set by the @Lid{debug.sethook} function.
Returns @fail if there is no active hook.
}
@LibEntry{debug.getinfo ([thread,] f [, what])|
@ -8458,7 +8471,7 @@ of the given thread:
(except for tail calls, which do not count on the stack);
and so on.
If @id{f} is a number greater than the number of active functions,
then @id{getinfo} returns @nil.
then @id{getinfo} returns @fail.
The returned table can contain all the fields returned by @Lid{lua_getinfo},
with the string @id{what} describing which fields to fill in.
@ -8496,7 +8509,8 @@ Compile-time constants may not appear in this listing,
if they were optimized away by the compiler.
Negative indices refer to vararg arguments;
@num{-1} is the first vararg argument.
The function returns @nil if there is no variable with the given index,
The function returns @fail
if there is no variable with the given index,
and raises an error when called with a level out of range.
(You can call @Lid{debug.getinfo} to check whether the level is valid.)
@ -8527,7 +8541,8 @@ Returns the registry table @see{registry}.
This function returns the name and the value of the upvalue
with index @id{up} of the function @id{f}.
The function returns @nil if there is no upvalue with the given index.
The function returns @fail
if there is no upvalue with the given index.
(For Lua functions,
upvalues are the external local variables that the function uses,
@ -8615,7 +8630,7 @@ and @N{level 1} is the hook function.)
This function assigns the value @id{value} to the local variable
with index @id{local} of the function at level @id{level} of the stack.
The function returns @nil if there is no local
The function returns @fail if there is no local
variable with the given index,
and raises an error when called with a @id{level} out of range.
(You can call @id{getinfo} to check whether the level is valid.)
@ -8638,7 +8653,7 @@ Returns @id{value}.
This function assigns the value @id{value} to the upvalue
with index @id{up} of the function @id{f}.
The function returns @nil if there is no upvalue
The function returns @fail if there is no upvalue
with the given index.
Otherwise, it returns the name of the upvalue.
@ -8653,7 +8668,7 @@ the @id{n}-th user value associated to the given @id{udata}.
@id{udata} must be a full userdata.
Returns @id{udata},
or @nil if the userdata does not have that value.
or @fail if the userdata does not have that value.
}

View File

@ -698,7 +698,7 @@ for k, v in ipairs(t) do
assert(v1 == v and p)
end
assert(debug.getuservalue(4) == nil)
assert(not debug.getuservalue(4))
debug.setuservalue(b, function () return 10 end, 10)
collectgarbage() -- function should not be collected

View File

@ -351,12 +351,12 @@ assert(g(0,0) == 30)
debug.sethook(nil);
assert(debug.gethook() == nil)
assert(not debug.gethook())
-- minimal tests for setuservalue/getuservalue
do
assert(debug.setuservalue(io.stdin, 10) == nil)
assert(not debug.setuservalue(io.stdin, 10))
local a, b = debug.getuservalue(io.stdin, 10)
assert(a == nil and not b)
end
@ -414,7 +414,7 @@ end, "c")
a:f(1,2,3,4,5)
assert(X.self == a and X.a == 1 and X.b == 2 and X.c == nil)
assert(XX == 12)
assert(debug.gethook() == nil)
assert(not debug.gethook())
-- testing access to local variables in return hook (bug in 5.2)

View File

@ -18,7 +18,7 @@ end
local function doit (s)
local f, msg = load(s)
if f == nil then return msg end
if not f then return msg end
local cond, msg = pcall(f)
return (not cond) and msg
end
@ -312,8 +312,8 @@ end
local function lineerror (s, l)
local err,msg = pcall(load(s))
local line = string.match(msg, ":(%d+):")
assert(tonumber(line) == l)
local line = tonumber(string.match(msg, ":(%d+):"))
assert(line == l or (not line and not l))
end
lineerror("local a\n for i=1,'a' do \n print(i) \n end", 2)
@ -359,7 +359,7 @@ local p = [[
g()
]]
X=3;lineerror((p), 3)
X=0;lineerror((p), nil)
X=0;lineerror((p), false)
X=1;lineerror((p), 2)
X=2;lineerror((p), 1)
@ -510,7 +510,7 @@ checksyntax("a\1a = 1", "", "<\\1>", 1)
checksyntax("\255a = 1", "", "<\\255>", 1)
doit('I = load("a=9+"); a=3')
assert(a==3 and I == nil)
assert(a==3 and not I)
print('+')
lim = 1000

View File

@ -184,7 +184,7 @@ three
local f <close> = assert(io.open(file, "r"))
-- second item failing
l1, n1, n2, dummy = f:read("l", "n", "n", "l")
assert(l1 == "a line" and n1 == nil)
assert(l1 == "a line" and not n1)
end
assert(os.remove(file))
@ -228,7 +228,7 @@ assert(f:read("n") == 0Xdeadbeefdeadbeef); assert(f:read(2) == "x\n")
assert(f:read("n") == 0x1.13aP3); assert(f:read(1) == "e")
do -- attempt to read too long number
assert(f:read("n") == nil) -- fails
assert(not f:read("n")) -- fails
local s = f:read("L") -- read rest of line
assert(string.find(s, "^00*\n$")) -- lots of 0's left
end
@ -314,13 +314,13 @@ assert(io.read() == "fourth_line")
assert(io.read() == "") -- empty line
assert(io.read('n') == 3450)
assert(io.read(1) == '\n')
assert(io.read(0) == nil) -- end of file
assert(io.read(1) == nil) -- end of file
assert(io.read(30000) == nil) -- end of file
assert(not io.read(0)) -- end of file
assert(not io.read(1)) -- end of file
assert(not io.read(30000)) -- end of file
assert(({io.read(1)})[2] == undef)
assert(io.read() == nil) -- end of file
assert(not io.read()) -- end of file
assert(({io.read()})[2] == undef)
assert(io.read('n') == nil) -- end of file
assert(not io.read('n')) -- end of file
assert(({io.read('n')})[2] == undef)
assert(io.read('a') == '') -- end of file (OK for 'a')
assert(io.read('a') == '') -- end of file (OK for 'a')
@ -356,7 +356,7 @@ assert(io.read(string.len(t)) == t)
assert(io.read(1) == ' ')
assert(io.read(0))
assert(io.read('a') == ';end of file\n')
assert(io.read(0) == nil)
assert(not io.read(0))
assert(io.close(io.input()))
@ -364,7 +364,7 @@ assert(io.close(io.input()))
do
local function ismsg (m)
-- error message is not a code number
return (type(m) == "string" and tonumber(m) == nil)
return (type(m) == "string" and not tonumber(m))
end
-- read
@ -393,7 +393,7 @@ assert(io.read"L" == "\n")
assert(io.read"L" == "\n")
assert(io.read"L" == "line\n")
assert(io.read"L" == "other")
assert(io.read"L" == nil)
assert(not io.read"L")
io.input():close()
local f = assert(io.open(file))
@ -462,7 +462,7 @@ end
-- test for multipe arguments in 'lines'
io.output(file); io.write"0123456789\n":close()
for a,b in io.lines(file, 1, 1) do
if a == "\n" then assert(b == nil)
if a == "\n" then assert(not b)
else assert(tonumber(a) == tonumber(b) - 1)
end
end
@ -473,13 +473,13 @@ end
for a,b,c in io.lines(file, "a", 0, 1) do
if a == "" then break end
assert(a == "0123456789\n" and b == nil and c == nil)
assert(a == "0123456789\n" and not b and not c)
end
collectgarbage() -- to close file in previous iteration
io.output(file); io.write"00\n10\n20\n30\n40\n":close()
for a, b in io.lines(file, "n", "n") do
if a == 40 then assert(b == nil)
if a == 40 then assert(not b)
else assert(a == b - 10)
end
end
@ -654,7 +654,7 @@ and the rest of the file
io.input(file)
local _,a,b,c,d,e,h,__ = io.read(1, 'n', 'n', 'l', 'l', 'l', 'a', 10)
assert(io.close(io.input()))
assert(_ == ' ' and __ == nil)
assert(_ == ' ' and not __)
assert(type(a) == 'number' and a==123.4 and b==-56e-2)
assert(d=='second line' and e=='third line')
assert(h==[[
@ -706,7 +706,7 @@ if not _soft then
io.input():seek('set', 0)
y = io.read() -- huge line
assert(x == y..'\n'..io.read())
assert(io.read() == nil)
assert(not io.read())
io.close(io.input())
assert(os.remove(file))
x = nil; y = nil

View File

@ -281,7 +281,7 @@ if os.setlocale("pt_BR") or os.setlocale("ptb") then
assert(" 0x.1 " + " 0x,1" + "-0X.1\t" == 0x0.1)
assert(tonumber"inf" == nil and tonumber"NAN" == nil)
assert(not tonumber"inf" and not tonumber"NAN")
assert(assert(load(string.format("return %q", 4.51)))() == 4.51)

View File

@ -39,7 +39,7 @@ do
end
assert(math.type(0) == "integer" and math.type(0.0) == "float"
and math.type("10") == nil)
and not math.type("10"))
local function checkerror (msg, f, ...)
@ -381,17 +381,17 @@ assert(tonumber(1/0) == 1/0)
-- 'tonumber' with strings
assert(tonumber("0") == 0)
assert(tonumber("") == nil)
assert(tonumber(" ") == nil)
assert(tonumber("-") == nil)
assert(tonumber(" -0x ") == nil)
assert(tonumber{} == nil)
assert(not tonumber(""))
assert(not tonumber(" "))
assert(not tonumber("-"))
assert(not tonumber(" -0x "))
assert(not tonumber{})
assert(tonumber'+0.01' == 1/100 and tonumber'+.01' == 0.01 and
tonumber'.01' == 0.01 and tonumber'-1.' == -1 and
tonumber'+1.' == 1)
assert(tonumber'+ 0.01' == nil and tonumber'+.e1' == nil and
tonumber'1e' == nil and tonumber'1.0e+' == nil and
tonumber'.' == nil)
assert(not tonumber'+ 0.01' and not tonumber'+.e1' and
not tonumber'1e' and not tonumber'1.0e+' and
not tonumber'.')
assert(tonumber('-012') == -010-2)
assert(tonumber('-1.2e2') == - - -120)
@ -445,45 +445,45 @@ local function f (...)
end
end
assert(f(tonumber('fFfa', 15)) == nil)
assert(f(tonumber('099', 8)) == nil)
assert(f(tonumber('1\0', 2)) == nil)
assert(f(tonumber('', 8)) == nil)
assert(f(tonumber(' ', 9)) == nil)
assert(f(tonumber(' ', 9)) == nil)
assert(f(tonumber('0xf', 10)) == nil)
assert(not f(tonumber('fFfa', 15)))
assert(not f(tonumber('099', 8)))
assert(not f(tonumber('1\0', 2)))
assert(not f(tonumber('', 8)))
assert(not f(tonumber(' ', 9)))
assert(not f(tonumber(' ', 9)))
assert(not f(tonumber('0xf', 10)))
assert(f(tonumber('inf')) == nil)
assert(f(tonumber(' INF ')) == nil)
assert(f(tonumber('Nan')) == nil)
assert(f(tonumber('nan')) == nil)
assert(not f(tonumber('inf')))
assert(not f(tonumber(' INF ')))
assert(not f(tonumber('Nan')))
assert(not f(tonumber('nan')))
assert(f(tonumber(' ')) == nil)
assert(f(tonumber('')) == nil)
assert(f(tonumber('1 a')) == nil)
assert(f(tonumber('1 a', 2)) == nil)
assert(f(tonumber('1\0')) == nil)
assert(f(tonumber('1 \0')) == nil)
assert(f(tonumber('1\0 ')) == nil)
assert(f(tonumber('e1')) == nil)
assert(f(tonumber('e 1')) == nil)
assert(f(tonumber(' 3.4.5 ')) == nil)
assert(not f(tonumber(' ')))
assert(not f(tonumber('')))
assert(not f(tonumber('1 a')))
assert(not f(tonumber('1 a', 2)))
assert(not f(tonumber('1\0')))
assert(not f(tonumber('1 \0')))
assert(not f(tonumber('1\0 ')))
assert(not f(tonumber('e1')))
assert(not f(tonumber('e 1')))
assert(not f(tonumber(' 3.4.5 ')))
-- testing 'tonumber' for invalid hexadecimal formats
assert(tonumber('0x') == nil)
assert(tonumber('x') == nil)
assert(tonumber('x3') == nil)
assert(tonumber('0x3.3.3') == nil) -- two decimal points
assert(tonumber('00x2') == nil)
assert(tonumber('0x 2') == nil)
assert(tonumber('0 x2') == nil)
assert(tonumber('23x') == nil)
assert(tonumber('- 0xaa') == nil)
assert(tonumber('-0xaaP ') == nil) -- no exponent
assert(tonumber('0x0.51p') == nil)
assert(tonumber('0x5p+-2') == nil)
assert(not tonumber('0x'))
assert(not tonumber('x'))
assert(not tonumber('x3'))
assert(not tonumber('0x3.3.3')) -- two decimal points
assert(not tonumber('00x2'))
assert(not tonumber('0x 2'))
assert(not tonumber('0 x2'))
assert(not tonumber('23x'))
assert(not tonumber('- 0xaa'))
assert(not tonumber('-0xaaP ')) -- no exponent
assert(not tonumber('0x0.51p'))
assert(not tonumber('0x5p+-2'))
-- testing hexadecimal numerals
@ -705,19 +705,19 @@ do -- testing floor & ceil
assert(eqT(math.tointeger(maxint), maxint))
assert(eqT(math.tointeger(maxint .. ""), maxint))
assert(eqT(math.tointeger(minint + 0.0), minint))
assert(math.tointeger(0.0 - minint) == nil)
assert(math.tointeger(math.pi) == nil)
assert(math.tointeger(-math.pi) == nil)
assert(not math.tointeger(0.0 - minint))
assert(not math.tointeger(math.pi))
assert(not math.tointeger(-math.pi))
assert(math.floor(math.huge) == math.huge)
assert(math.ceil(math.huge) == math.huge)
assert(math.tointeger(math.huge) == nil)
assert(not math.tointeger(math.huge))
assert(math.floor(-math.huge) == -math.huge)
assert(math.ceil(-math.huge) == -math.huge)
assert(math.tointeger(-math.huge) == nil)
assert(not math.tointeger(-math.huge))
assert(math.tointeger("34.0") == 34)
assert(math.tointeger("34.3") == nil)
assert(math.tointeger({}) == nil)
assert(math.tointeger(0/0) == nil) -- NaN
assert(not math.tointeger("34.3"))
assert(not math.tointeger({}))
assert(not math.tointeger(0/0)) -- NaN
end

View File

@ -28,10 +28,10 @@ a,b = string.find('a\0a\0a\0a\0\0ab', '\0ab', 2); -- finds at the end
assert(a == 9 and b == 11);
a,b = string.find('a\0a\0a\0a\0\0ab', 'b') -- last position
assert(a == 11 and b == 11)
assert(string.find('a\0a\0a\0a\0\0ab', 'b\0') == nil) -- check ending
assert(string.find('', '\0') == nil)
assert(not string.find('a\0a\0a\0a\0\0ab', 'b\0')) -- check ending
assert(not string.find('', '\0'))
assert(string.find('alo123alo', '12') == 4)
assert(string.find('alo123alo', '^12') == nil)
assert(not string.find('alo123alo', '^12'))
assert(string.match("aaab", ".*b") == "aaab")
assert(string.match("aaa", ".*a") == "aaa")
@ -57,17 +57,17 @@ assert(f('aaa', 'ab*a') == 'aa')
assert(f('aba', 'ab*a') == 'aba')
assert(f('aaab', 'a+') == 'aaa')
assert(f('aaa', '^.+$') == 'aaa')
assert(f('aaa', 'b+') == nil)
assert(f('aaa', 'ab+a') == nil)
assert(not f('aaa', 'b+'))
assert(not f('aaa', 'ab+a'))
assert(f('aba', 'ab+a') == 'aba')
assert(f('a$a', '.$') == 'a')
assert(f('a$a', '.%$') == 'a$')
assert(f('a$a', '.$.') == 'a$a')
assert(f('a$a', '$$') == nil)
assert(f('a$b', 'a$') == nil)
assert(not f('a$a', '$$'))
assert(not f('a$b', 'a$'))
assert(f('a$a', '$') == '')
assert(f('', 'b*') == '')
assert(f('aaa', 'bb*') == nil)
assert(not f('aaa', 'bb*'))
assert(f('aaab', 'a-') == '')
assert(f('aaa', '^.-$') == 'aaa')
assert(f('aabaaabaaabaaaba', 'b.*b') == 'baaabaaabaaab')
@ -101,7 +101,7 @@ end
assert(f1('alo alx 123 b\0o b\0o', '(..*) %1') == "b\0o b\0o")
assert(f1('axz123= 4= 4 34', '(.+)=(.*)=%2 %1') == '3= 4= 4 3')
assert(f1('=======', '^(=*)=%1$') == '=======')
assert(string.match('==========', '^([=]*)=%1$') == nil)
assert(not string.match('==========', '^([=]*)=%1$'))
local function range (i, j)
if i <= j then
@ -135,7 +135,7 @@ print('+');
assert(string.match("alo xyzK", "(%w+)K") == "xyz")
assert(string.match("254 K", "(%d*)K") == "")
assert(string.match("alo ", "(%w*)$") == "")
assert(string.match("alo ", "(%w+)$") == nil)
assert(not string.match("alo ", "(%w+)$"))
assert(string.find("(álo)", "%(á") == 1)
local a, b, c, d, e = string.match("âlo alo", "^(((.).).* (%w*))$")
assert(a == 'âlo alo' and b == 'âl' and c == 'â' and d == 'alo' and e == nil)
@ -209,7 +209,7 @@ assert(s == r and t[1] == 1 and t[3] == 3 and t[7] == 4 and t[13] == 4)
function isbalanced (s)
return string.find(string.gsub(s, "%b()", ""), "[()]") == nil
return not string.find(string.gsub(s, "%b()", ""), "[()]")
end
assert(isbalanced("(9 ((8))(\0) 7) \0\0 a b ()(c)() a"))

View File

@ -56,13 +56,13 @@ a,b = string.find("123456789", "345")
assert(string.sub("123456789", a, b) == "345")
assert(string.find("1234567890123456789", "345", 3) == 3)
assert(string.find("1234567890123456789", "345", 4) == 13)
assert(string.find("1234567890123456789", "346", 4) == nil)
assert(not string.find("1234567890123456789", "346", 4))
assert(string.find("1234567890123456789", ".45", -9) == 13)
assert(string.find("abcdefg", "\0", 5, 1) == nil)
assert(not string.find("abcdefg", "\0", 5, 1))
assert(string.find("", "") == 1)
assert(string.find("", "", 1) == 1)
assert(not string.find("", "", 2))
assert(string.find('', 'aaa', 1) == nil)
assert(not string.find('', 'aaa', 1))
assert(('alo(.)alo'):find('(.)', 1, 1) == 4)
assert(string.len("") == 0)

View File

@ -30,8 +30,8 @@ local function checksyntax (s, t)
assert(assert(load(ts))() == s)
end
assert(utf8.offset("alo", 5) == nil)
assert(utf8.offset("alo", -4) == nil)
assert(not utf8.offset("alo", 5))
assert(not utf8.offset("alo", -4))
-- 'check' makes several tests over the validity of string 's'.
-- 't' is the list of codepoints of 's'.