aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lauxlib.c34
-rw-r--r--lbaselib.c4
-rw-r--r--ltests.c64
-rw-r--r--lua.c36
-rw-r--r--manual/manual.of29
-rw-r--r--testes/all.lua4
-rw-r--r--testes/api.lua2
-rw-r--r--testes/gc.lua8
-rw-r--r--testes/main.lua29
9 files changed, 161 insertions, 49 deletions
diff --git a/lauxlib.c b/lauxlib.c
index e3a7a577..ba1980b7 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -1002,29 +1002,43 @@ static int panic (lua_State *L) {
1002 1002
1003 1003
1004/* 1004/*
1005** Emit a warning. '*previoustocont' signals whether previous message 1005** Emit a warning. '*warnstate' means:
1006** was to be continued by the current one. 1006** 0 - warning system is off;
1007** 1 - ready to start a new message;
1008** 2 - previous message is to be continued.
1007*/ 1009*/
1008static void warnf (void *ud, const char *message, int tocont) { 1010static void warnf (void *ud, const char *message, int tocont) {
1009 int *previoustocont = (int *)ud; 1011 int *warnstate = (int *)ud;
1010 if (!*previoustocont) /* previous message was the last? */ 1012 if (*warnstate != 2 && !tocont && *message == '@') { /* control message? */
1013 if (strcmp(message + 1, "off") == 0)
1014 *warnstate = 0;
1015 else if (strcmp(message + 1, "on") == 0)
1016 *warnstate = 1;
1017 return;
1018 }
1019 else if (*warnstate == 0) /* warnings off? */
1020 return;
1021 if (*warnstate == 1) /* previous message was the last? */
1011 lua_writestringerror("%s", "Lua warning: "); /* start a new warning */ 1022 lua_writestringerror("%s", "Lua warning: "); /* start a new warning */
1012 lua_writestringerror("%s", message); /* write message */ 1023 lua_writestringerror("%s", message); /* write message */
1013 if (!tocont) /* is this the last part? */ 1024 if (tocont) /* not the last part? */
1025 *warnstate = 2; /* to be continued */
1026 else { /* last part */
1014 lua_writestringerror("%s", "\n"); /* finish message with end-of-line */ 1027 lua_writestringerror("%s", "\n"); /* finish message with end-of-line */
1015 *previoustocont = tocont; 1028 *warnstate = 1; /* ready to start a new message */
1029 }
1016} 1030}
1017 1031
1018 1032
1019LUALIB_API lua_State *luaL_newstate (void) { 1033LUALIB_API lua_State *luaL_newstate (void) {
1020 lua_State *L = lua_newstate(l_alloc, NULL); 1034 lua_State *L = lua_newstate(l_alloc, NULL);
1021 if (L) { 1035 if (L) {
1022 int *previoustocont; /* space for warning state */ 1036 int *warnstate; /* space for warning state */
1023 lua_atpanic(L, &panic); 1037 lua_atpanic(L, &panic);
1024 previoustocont = (int *)lua_newuserdatauv(L, sizeof(int), 0); 1038 warnstate = (int *)lua_newuserdatauv(L, sizeof(int), 0);
1025 luaL_ref(L, LUA_REGISTRYINDEX); /* make sure it won't be collected */ 1039 luaL_ref(L, LUA_REGISTRYINDEX); /* make sure it won't be collected */
1026 *previoustocont = 0; /* next message starts a new warning */ 1040 *warnstate = 1; /* next message starts a new warning */
1027 lua_setwarnf(L, warnf, previoustocont); 1041 lua_setwarnf(L, warnf, warnstate);
1028 } 1042 }
1029 return L; 1043 return L;
1030} 1044}
diff --git a/lbaselib.c b/lbaselib.c
index 4724e759..c68e6d38 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -48,9 +48,9 @@ static int luaB_warn (lua_State *L) {
48 luaL_checkstring(L, 1); /* at least one argument */ 48 luaL_checkstring(L, 1); /* at least one argument */
49 for (i = 2; i <= n; i++) 49 for (i = 2; i <= n; i++)
50 luaL_checkstring(L, i); /* make sure all arguments are strings */ 50 luaL_checkstring(L, i); /* make sure all arguments are strings */
51 for (i = 1; i <= n; i++) /* compose warning */ 51 for (i = 1; i < n; i++) /* compose warning */
52 lua_warning(L, lua_tostring(L, i), 1); 52 lua_warning(L, lua_tostring(L, i), 1);
53 lua_warning(L, "", 0); /* close warning */ 53 lua_warning(L, lua_tostring(L, n), 0); /* close warning */
54 return 0; 54 return 0;
55} 55}
56 56
diff --git a/ltests.c b/ltests.c
index 21273ea9..fd55fc31 100644
--- a/ltests.c
+++ b/ltests.c
@@ -79,32 +79,62 @@ static int tpanic (lua_State *L) {
79 79
80/* 80/*
81** Warning function for tests. Fist, it concatenates all parts of 81** Warning function for tests. Fist, it concatenates all parts of
82** a warning in buffer 'buff'. Then: 82** a warning in buffer 'buff'. Then, it has three modes:
83** - messages starting with '#' are shown on standard output (used to 83** - 0.normal: messages starting with '#' are shown on standard output;
84** test explicit warnings);
85** - messages containing '@' are stored in global '_WARN' (used to test
86** errors that generate warnings);
87** - other messages abort the tests (they represent real warning 84** - other messages abort the tests (they represent real warning
88** conditions; the standard tests should not generate these conditions 85** conditions; the standard tests should not generate these conditions
89** unexpectedly). 86** unexpectedly);
87** - 1.allow: all messages are shown;
88** - 2.store: all warnings go to the global '_WARN';
90*/ 89*/
91static void warnf (void *ud, const char *msg, int tocont) { 90static void warnf (void *ud, const char *msg, int tocont) {
92 static char buff[200] = ""; /* should be enough for tests... */ 91 static char buff[200] = ""; /* should be enough for tests... */
92 static int onoff = 1;
93 static int mode = 0; /* start in normal mode */
94 static int lasttocont = 0;
95 if (!lasttocont && !tocont && *msg == '@') { /* control message? */
96 if (buff[0] != '\0')
97 badexit("Control warning during warning: %s\naborting...\n", msg);
98 if (strcmp(msg + 1, "off") == 0)
99 onoff = 0;
100 else if (strcmp(msg + 1, "on") == 0)
101 onoff = 1;
102 else if (strcmp(msg + 1, "normal") == 0)
103 mode = 0;
104 else if (strcmp(msg + 1, "allow") == 0)
105 mode = 1;
106 else if (strcmp(msg + 1, "store") == 0)
107 mode = 2;
108 else
109 badexit("Invalid control warning in test mode: %s\naborting...\n", msg);
110 return;
111 }
112 lasttocont = tocont;
93 if (strlen(msg) >= sizeof(buff) - strlen(buff)) 113 if (strlen(msg) >= sizeof(buff) - strlen(buff))
94 badexit("%s", "warnf-buffer overflow"); 114 badexit("%s", "warnf-buffer overflow");
95 strcat(buff, msg); /* add new message to current warning */ 115 strcat(buff, msg); /* add new message to current warning */
96 if (!tocont) { /* message finished? */ 116 if (!tocont) { /* message finished? */
97 if (buff[0] == '#') /* expected warning? */ 117 switch (mode) {
98 printf("Expected Lua warning: %s\n", buff); /* print it */ 118 case 0: { /* normal */
99 else if (strchr(buff, '@') != NULL) { /* warning for test purposes? */ 119 if (buff[0] != '#' && onoff) /* unexpected warning? */
100 lua_State *L = cast(lua_State *, ud); 120 badexit("Unexpected warning in test mode: %s\naborting...\n", buff);
101 lua_unlock(L); 121 /* else */ /* FALLTHROUGH */
102 lua_pushstring(L, buff); 122 }
103 lua_setglobal(L, "_WARN"); /* assign message to global '_WARN' */ 123 case 1: { /* allow */
104 lua_lock(L); 124 if (onoff)
105 } 125 fprintf(stderr, "Lua warning: %s\n", buff); /* print warning */
106 else /* a real warning; should not happen during tests */ 126 break;
107 badexit("Unexpected warning in test mode: %s\naborting...\n", buff); 127 }
128 case 2: { /* store */
129 lua_State *L = cast(lua_State *, ud);
130 lua_unlock(L);
131 lua_pushstring(L, buff);
132 lua_setglobal(L, "_WARN"); /* assign message to global '_WARN' */
133 lua_lock(L);
134 buff[0] = '\0'; /* prepare buffer for next warning */
135 break;
136 }
137 }
108 buff[0] = '\0'; /* prepare buffer for next warning */ 138 buff[0] = '\0'; /* prepare buffer for next warning */
109 } 139 }
110} 140}
diff --git a/lua.c b/lua.c
index fa534ba2..d13e203b 100644
--- a/lua.c
+++ b/lua.c
@@ -73,6 +73,7 @@ static void print_usage (const char *badoption) {
73 " -l name require library 'name' into global 'name'\n" 73 " -l name require library 'name' into global 'name'\n"
74 " -v show version information\n" 74 " -v show version information\n"
75 " -E ignore environment variables\n" 75 " -E ignore environment variables\n"
76 " -q turn warnings off\n"
76 " -- stop handling options\n" 77 " -- stop handling options\n"
77 " - stop handling options and execute stdin\n" 78 " - stop handling options and execute stdin\n"
78 , 79 ,
@@ -259,14 +260,18 @@ static int collectargs (char **argv, int *first) {
259 case '\0': /* '-' */ 260 case '\0': /* '-' */
260 return args; /* script "name" is '-' */ 261 return args; /* script "name" is '-' */
261 case 'E': 262 case 'E':
262 if (argv[i][2] != '\0') /* extra characters after 1st? */ 263 if (argv[i][2] != '\0') /* extra characters? */
263 return has_error; /* invalid option */ 264 return has_error; /* invalid option */
264 args |= has_E; 265 args |= has_E;
265 break; 266 break;
267 case 'q':
268 if (argv[i][2] != '\0') /* extra characters? */
269 return has_error; /* invalid option */
270 break;
266 case 'i': 271 case 'i':
267 args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */ 272 args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */
268 case 'v': 273 case 'v':
269 if (argv[i][2] != '\0') /* extra characters after 1st? */ 274 if (argv[i][2] != '\0') /* extra characters? */
270 return has_error; /* invalid option */ 275 return has_error; /* invalid option */
271 args |= has_v; 276 args |= has_v;
272 break; 277 break;
@@ -289,7 +294,8 @@ static int collectargs (char **argv, int *first) {
289 294
290 295
291/* 296/*
292** Processes options 'e' and 'l', which involve running Lua code. 297** Processes options 'e' and 'l', which involve running Lua code, and
298** 'q', which also affects the state.
293** Returns 0 if some code raises an error. 299** Returns 0 if some code raises an error.
294*/ 300*/
295static int runargs (lua_State *L, char **argv, int n) { 301static int runargs (lua_State *L, char **argv, int n) {
@@ -297,15 +303,21 @@ static int runargs (lua_State *L, char **argv, int n) {
297 for (i = 1; i < n; i++) { 303 for (i = 1; i < n; i++) {
298 int option = argv[i][1]; 304 int option = argv[i][1];
299 lua_assert(argv[i][0] == '-'); /* already checked */ 305 lua_assert(argv[i][0] == '-'); /* already checked */
300 if (option == 'e' || option == 'l') { 306 switch (option) {
301 int status; 307 case 'e': case 'l': {
302 const char *extra = argv[i] + 2; /* both options need an argument */ 308 int status;
303 if (*extra == '\0') extra = argv[++i]; 309 const char *extra = argv[i] + 2; /* both options need an argument */
304 lua_assert(extra != NULL); 310 if (*extra == '\0') extra = argv[++i];
305 status = (option == 'e') 311 lua_assert(extra != NULL);
306 ? dostring(L, extra, "=(command line)") 312 status = (option == 'e')
307 : dolibrary(L, extra); 313 ? dostring(L, extra, "=(command line)")
308 if (status != LUA_OK) return 0; 314 : dolibrary(L, extra);
315 if (status != LUA_OK) return 0;
316 break;
317 }
318 case 'q':
319 lua_warning(L, "@off", 0); /* no warnings */
320 break;
309 } 321 }
310 } 322 }
311 return 1; 323 return 1;
diff --git a/manual/manual.of b/manual/manual.of
index ff27a7d4..8c71c613 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -4370,6 +4370,8 @@ The third parameter is a boolean that
4370indicates whether the message is 4370indicates whether the message is
4371to be continued by the message in the next call. 4371to be continued by the message in the next call.
4372 4372
4373See @Lid{warn} for more details about warnings.
4374
4373} 4375}
4374 4376
4375@APIEntry{ 4377@APIEntry{
@@ -4380,6 +4382,8 @@ Emits a warning with the given message.
4380A message in a call with @id{tocont} true should be 4382A message in a call with @id{tocont} true should be
4381continued in another call to this function. 4383continued in another call to this function.
4382 4384
4385See @Lid{warn} for more details about warnings.
4386
4383} 4387}
4384 4388
4385@APIEntry{ 4389@APIEntry{
@@ -6355,6 +6359,16 @@ The current value of this variable is @St{Lua 5.4}.
6355Emits a warning with a message composed by the concatenation 6359Emits a warning with a message composed by the concatenation
6356of all its arguments (which should be strings). 6360of all its arguments (which should be strings).
6357 6361
6362By convention,
6363a one-piece message starting with @Char{@At}
6364is intended to be a @emph{control message},
6365which is a message to the warning system itself.
6366In particular, the standard warning function in Lua
6367recognizes the control messages @St{@At{}off},
6368to stop the emission of warnings,
6369and @St{@At{}on}, to (re)start the emission;
6370it ignores unknown control messages.
6371
6358} 6372}
6359 6373
6360@LibEntry{xpcall (f, msgh [, arg1, @Cdots])| 6374@LibEntry{xpcall (f, msgh [, arg1, @Cdots])|
@@ -7293,7 +7307,7 @@ stored as the first capture, and therefore has @N{number 1};
7293the character matching @St{.} is captured with @N{number 2}, 7307the character matching @St{.} is captured with @N{number 2},
7294and the part matching @St{%s*} has @N{number 3}. 7308and the part matching @St{%s*} has @N{number 3}.
7295 7309
7296As a special case, the empty capture @T{()} captures 7310As a special case, the capture @T{()} captures
7297the current string position (a number). 7311the current string position (a number).
7298For instance, if we apply the pattern @T{"()aa()"} on the 7312For instance, if we apply the pattern @T{"()aa()"} on the
7299string @T{"flaaap"}, there will be two captures: @N{3 and 5}. 7313string @T{"flaaap"}, there will be two captures: @N{3 and 5}.
@@ -7858,7 +7872,6 @@ they are compared as @x{unsigned integers}.
7858 7872
7859} 7873}
7860 7874
7861
7862@sect2{iolib| @title{Input and Output Facilities} 7875@sect2{iolib| @title{Input and Output Facilities}
7863 7876
7864The I/O library provides two different styles for file manipulation. 7877The I/O library provides two different styles for file manipulation.
@@ -8150,7 +8163,6 @@ There are three available modes:
8150@item{@St{line}| line buffering.} 8163@item{@St{line}| line buffering.}
8151} 8164}
8152 8165
8153}
8154For the last two cases, 8166For the last two cases,
8155@id{size} is a hint for the size of the buffer, in bytes. 8167@id{size} is a hint for the size of the buffer, in bytes.
8156The default is an appropriate size. 8168The default is an appropriate size.
@@ -8708,6 +8720,7 @@ The options are:
8708@item{@T{-i}| enters interactive mode after running @rep{script};} 8720@item{@T{-i}| enters interactive mode after running @rep{script};}
8709@item{@T{-v}| prints version information;} 8721@item{@T{-v}| prints version information;}
8710@item{@T{-E}| ignores environment variables;} 8722@item{@T{-E}| ignores environment variables;}
8723@item{@T{-q}| turn warnings off;}
8711@item{@T{--}| stops handling options;} 8724@item{@T{--}| stops handling options;}
8712@item{@T{-}| executes @id{stdin} as a file and stops handling options.} 8725@item{@T{-}| executes @id{stdin} as a file and stops handling options.}
8713} 8726}
@@ -8733,12 +8746,13 @@ setting the values of
8733@Lid{package.path} and @Lid{package.cpath} 8746@Lid{package.path} and @Lid{package.cpath}
8734with the default paths defined in @id{luaconf.h}. 8747with the default paths defined in @id{luaconf.h}.
8735 8748
8736All options are handled in order, except @T{-i} and @T{-E}. 8749The options @T{-e}, @T{-l}, and @T{-q} are handled in
8750the order they appear.
8737For instance, an invocation like 8751For instance, an invocation like
8738@verbatim{ 8752@verbatim{
8739$ lua -e'a=1' -e 'print(a)' script.lua 8753$ lua -e 'a=1' -llib1 script.lua
8740} 8754}
8741will first set @id{a} to 1, then print the value of @id{a}, 8755will first set @id{a} to 1, then require the library @id{lib1},
8742and finally run the file @id{script.lua} with no arguments. 8756and finally run the file @id{script.lua} with no arguments.
8743(Here @T{$} is the shell prompt. Your prompt may be different.) 8757(Here @T{$} is the shell prompt. Your prompt may be different.)
8744 8758
@@ -8798,7 +8812,8 @@ has a metamethod @idx{__tostring},
8798the interpreter calls this metamethod to produce the final message. 8812the interpreter calls this metamethod to produce the final message.
8799Otherwise, the interpreter converts the error object to a string 8813Otherwise, the interpreter converts the error object to a string
8800and adds a stack traceback to it. 8814and adds a stack traceback to it.
8801Warnings are simply printed in the standard error output. 8815When warnings are on,
8816they are simply printed in the standard error output.
8802 8817
8803When finishing normally, 8818When finishing normally,
8804the interpreter closes its main Lua state 8819the interpreter closes its main Lua state
diff --git a/testes/all.lua b/testes/all.lua
index bf27f106..5d698d4b 100644
--- a/testes/all.lua
+++ b/testes/all.lua
@@ -209,6 +209,10 @@ if #msgs > 0 then
209 warn("#tests not performed:\n ", m, "\n") 209 warn("#tests not performed:\n ", m, "\n")
210end 210end
211 211
212warn("@off")
213warn("******** THIS WARNING SHOULD NOT APPEAR **********")
214warn("******** THIS WARNING ALSO SHOULD NOT APPEAR **********")
215warn("@on")
212print("(there should be two warnings now)") 216print("(there should be two warnings now)")
213warn("#This is ", "an expected", " warning") 217warn("#This is ", "an expected", " warning")
214warn("#This is", " another one") 218warn("#This is", " another one")
diff --git a/testes/api.lua b/testes/api.lua
index f6915c3e..4f9d6717 100644
--- a/testes/api.lua
+++ b/testes/api.lua
@@ -977,6 +977,7 @@ assert(t[7] == nil)
977 977
978------------------------------------------------------------------------- 978-------------------------------------------------------------------------
979do -- testing errors during GC 979do -- testing errors during GC
980 warn("@off")
980 collectgarbage("stop") 981 collectgarbage("stop")
981 local a = {} 982 local a = {}
982 for i=1,20 do 983 for i=1,20 do
@@ -994,6 +995,7 @@ do -- testing errors during GC
994 collectgarbage() 995 collectgarbage()
995 assert(A == 10) -- number of normal collections 996 assert(A == 10) -- number of normal collections
996 collectgarbage("restart") 997 collectgarbage("restart")
998 warn("@on")
997end 999end
998------------------------------------------------------------------------- 1000-------------------------------------------------------------------------
999-- test for userdata vals 1001-- test for userdata vals
diff --git a/testes/gc.lua b/testes/gc.lua
index 9ea054c1..6bdc98ca 100644
--- a/testes/gc.lua
+++ b/testes/gc.lua
@@ -369,6 +369,7 @@ if T then
369 s[n] = i 369 s[n] = i
370 end 370 end
371 371
372 warn("@store")
372 collectgarbage() 373 collectgarbage()
373 assert(string.find(_WARN, "error in __gc metamethod")) 374 assert(string.find(_WARN, "error in __gc metamethod"))
374 assert(string.match(_WARN, "@(.-)@") == "expected") 375 assert(string.match(_WARN, "@(.-)@") == "expected")
@@ -383,6 +384,7 @@ if T then
383 for i = 1, 10 do assert(s[i]) end 384 for i = 1, 10 do assert(s[i]) end
384 385
385 getmetatable(u).__gc = nil 386 getmetatable(u).__gc = nil
387 warn("@normal")
386 388
387end 389end
388print '+' 390print '+'
@@ -475,9 +477,11 @@ end
475 477
476-- errors during collection 478-- errors during collection
477if T then 479if T then
480 warn("@store")
478 u = setmetatable({}, {__gc = function () error "@expected error" end}) 481 u = setmetatable({}, {__gc = function () error "@expected error" end})
479 u = nil 482 u = nil
480 collectgarbage() 483 collectgarbage()
484 warn("@normal")
481end 485end
482 486
483 487
@@ -645,7 +649,7 @@ end
645 649
646-- create several objects to raise errors when collected while closing state 650-- create several objects to raise errors when collected while closing state
647if T then 651if T then
648 local error, assert, find = error, assert, string.find 652 local error, assert, find, warn = error, assert, string.find, warn
649 local n = 0 653 local n = 0
650 local lastmsg 654 local lastmsg
651 local mt = {__gc = function (o) 655 local mt = {__gc = function (o)
@@ -659,7 +663,9 @@ if T then
659 else 663 else
660 assert(lastmsg == _WARN) -- subsequent error messages are equal 664 assert(lastmsg == _WARN) -- subsequent error messages are equal
661 end 665 end
666 warn("@store")
662 error"@expected warning" 667 error"@expected warning"
668 warn("@normal")
663 end} 669 end}
664 for i = 10, 1, -1 do 670 for i = 10, 1, -1 do
665 -- create object and preserve it until the end 671 -- create object and preserve it until the end
diff --git a/testes/main.lua b/testes/main.lua
index b224b54e..0ef4822d 100644
--- a/testes/main.lua
+++ b/testes/main.lua
@@ -221,6 +221,28 @@ assert(string.find(getoutput(), "error calling 'print'"))
221RUN('echo "io.stderr:write(1000)\ncont" | lua -e "require\'debug\'.debug()" 2> %s', out) 221RUN('echo "io.stderr:write(1000)\ncont" | lua -e "require\'debug\'.debug()" 2> %s', out)
222checkout("lua_debug> 1000lua_debug> ") 222checkout("lua_debug> 1000lua_debug> ")
223 223
224-- test warnings
225RUN('echo "io.stderr:write(1); warn[[XXX]]" | lua -q 2> %s', out)
226checkout("1")
227
228prepfile[[
229warn("@allow") -- unknown control, ignored
230warn("@off", "XXX", "@off") -- these are not control messages
231warn("@off") -- this one is
232warn("@on", "YYY", "@on") -- not control, but warn is off
233warn("@off") -- keep it off
234warn("@on") -- restart warnings
235warn("", "@on") -- again, no control, real warning
236warn("@on") -- keep it "started"
237warn("Z", "Z", "Z") -- common warning
238]]
239RUN('lua %s 2> %s', prog, out)
240checkout[[
241Lua warning: @offXXX@off
242Lua warning: @on
243Lua warning: ZZZ
244]]
245
224-- test many arguments 246-- test many arguments
225prepfile[[print(({...})[30])]] 247prepfile[[print(({...})[30])]]
226RUN('lua %s %s > %s', prog, string.rep(" a", 30), out) 248RUN('lua %s %s > %s', prog, string.rep(" a", 30), out)
@@ -355,8 +377,15 @@ if T then -- test library?
355 NoRun("not enough memory", "env MEMLIMIT=100 lua") 377 NoRun("not enough memory", "env MEMLIMIT=100 lua")
356 378
357 -- testing 'warn' 379 -- testing 'warn'
380 warn("@store")
358 warn("@123", "456", "789") 381 warn("@123", "456", "789")
359 assert(_WARN == "@123456789") 382 assert(_WARN == "@123456789")
383
384 warn("zip", "", " ", "zap")
385 assert(_WARN == "zip zap")
386 warn("ZIP", "", " ", "ZAP")
387 assert(_WARN == "ZIP ZAP")
388 warn("@normal")
360end 389end
361 390
362do 391do