summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lapi.c4
-rw-r--r--lauxlib.c34
-rw-r--r--lbaselib.c2
-rw-r--r--lgc.c8
-rw-r--r--lstate.c4
-rw-r--r--lstate.h2
-rw-r--r--ltests.c60
-rw-r--r--lua.h4
-rw-r--r--manual/manual.of26
-rw-r--r--testes/all.lua10
-rw-r--r--testes/api.lua12
-rw-r--r--testes/gc.lua11
12 files changed, 79 insertions, 98 deletions
diff --git a/lapi.c b/lapi.c
index 66d75649..06396ad3 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1286,9 +1286,9 @@ void lua_setwarnf (lua_State *L, lua_WarnFunction f, void *ud) {
1286} 1286}
1287 1287
1288 1288
1289void lua_warning (lua_State *L, const char *msg) { 1289void lua_warning (lua_State *L, const char *msg, int tocont) {
1290 lua_lock(L); 1290 lua_lock(L);
1291 luaE_warning(L, msg); 1291 luaE_warning(L, msg, tocont);
1292 lua_unlock(L); 1292 lua_unlock(L);
1293} 1293}
1294 1294
diff --git a/lauxlib.c b/lauxlib.c
index abf923f8..e9c02d36 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -987,33 +987,29 @@ static int panic (lua_State *L) {
987 987
988 988
989/* 989/*
990** checks whether 'message' ends with end-of-line 990** Emit a warning. '*previoustocont' signals whether previous message
991** (and therefore is the last part of a warning) 991** was to be continued by the current one.
992*/ 992*/
993static int islast (const char *message) { 993static void warnf (void *ud, const char *message, int tocont) {
994 size_t len = strlen(message); 994 int *previoustocont = (int *)ud;
995 return (len > 0 && message[len - 1] == '\n'); 995 if (!*previoustocont) /* previous message was the last? */
996} 996 lua_writestringerror("%s", "Lua warning: "); /* start a new warning */
997 997 lua_writestringerror("%s", message); /* write message */
998 998 if (!tocont) /* is this the last part? */
999/* 999 lua_writestringerror("%s", "\n"); /* finish message with end-of-line */
1000** Emit a warning. If '*pud' is NULL, previous message was to be 1000 *previoustocont = tocont;
1001** continued by the current one.
1002*/
1003static void warnf (void **pud, const char *message) {
1004 if (*pud == NULL) /* previous message was not the last? */
1005 lua_writestringerror("%s", message);
1006 else /* start a new warning */
1007 lua_writestringerror("Lua warning: %s", message);
1008 *pud = (islast(message)) ? pud : NULL;
1009} 1001}
1010 1002
1011 1003
1012LUALIB_API lua_State *luaL_newstate (void) { 1004LUALIB_API lua_State *luaL_newstate (void) {
1013 lua_State *L = lua_newstate(l_alloc, NULL); 1005 lua_State *L = lua_newstate(l_alloc, NULL);
1014 if (L) { 1006 if (L) {
1007 int *previoustocont; /* space for warning state */
1015 lua_atpanic(L, &panic); 1008 lua_atpanic(L, &panic);
1016 lua_setwarnf(L, warnf, L); 1009 previoustocont = (int *)lua_newuserdatauv(L, sizeof(int), 0);
1010 luaL_ref(L, LUA_REGISTRYINDEX); /* make sure it won't be collected */
1011 *previoustocont = 0; /* next message starts a new warning */
1012 lua_setwarnf(L, warnf, previoustocont);
1017 } 1013 }
1018 return L; 1014 return L;
1019} 1015}
diff --git a/lbaselib.c b/lbaselib.c
index 26683a1d..d4b619a5 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -45,7 +45,7 @@ static int luaB_print (lua_State *L) {
45 45
46static int luaB_warn (lua_State *L) { 46static int luaB_warn (lua_State *L) {
47 const char *msg = luaL_checkstring(L, 1); 47 const char *msg = luaL_checkstring(L, 1);
48 lua_warning(L, msg); 48 lua_warning(L, msg, lua_toboolean(L, 2));
49 return 0; 49 return 0;
50} 50}
51 51
diff --git a/lgc.c b/lgc.c
index bf0460d5..c834319b 100644
--- a/lgc.c
+++ b/lgc.c
@@ -832,7 +832,7 @@ static void GCTM (lua_State *L) {
832 lua_assert(!g->gcemergency); 832 lua_assert(!g->gcemergency);
833 setgcovalue(L, &v, udata2finalize(g)); 833 setgcovalue(L, &v, udata2finalize(g));
834 tm = luaT_gettmbyobj(L, &v, TM_GC); 834 tm = luaT_gettmbyobj(L, &v, TM_GC);
835 if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ 835 if (ttisfunction(tm)) { /* is the finalizer a function? */
836 int status; 836 int status;
837 lu_byte oldah = L->allowhook; 837 lu_byte oldah = L->allowhook;
838 int running = g->gcrunning; 838 int running = g->gcrunning;
@@ -850,9 +850,9 @@ static void GCTM (lua_State *L) {
850 const char *msg = (ttisstring(s2v(L->top - 1))) 850 const char *msg = (ttisstring(s2v(L->top - 1)))
851 ? svalue(s2v(L->top - 1)) 851 ? svalue(s2v(L->top - 1))
852 : "error object is not a string"; 852 : "error object is not a string";
853 luaE_warning(L, "error in __gc metamethod ("); 853 luaE_warning(L, "error in __gc metamethod (", 1);
854 luaE_warning(L, msg); 854 luaE_warning(L, msg, 1);
855 luaE_warning(L, ")\n"); 855 luaE_warning(L, ")", 0);
856 } 856 }
857 } 857 }
858} 858}
diff --git a/lstate.c b/lstate.c
index 6c35ea1a..f5579a66 100644
--- a/lstate.c
+++ b/lstate.c
@@ -411,10 +411,10 @@ LUA_API void lua_close (lua_State *L) {
411} 411}
412 412
413 413
414void luaE_warning (lua_State *L, const char *msg) { 414void luaE_warning (lua_State *L, const char *msg, int tocont) {
415 lua_WarnFunction wf = G(L)->warnf; 415 lua_WarnFunction wf = G(L)->warnf;
416 if (wf != NULL) 416 if (wf != NULL)
417 wf(&G(L)->ud_warn, msg); 417 wf(G(L)->ud_warn, msg, tocont);
418} 418}
419 419
420 420
diff --git a/lstate.h b/lstate.h
index 11bf18fd..e35f8962 100644
--- a/lstate.h
+++ b/lstate.h
@@ -317,7 +317,7 @@ LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
317LUAI_FUNC void luaE_freeCI (lua_State *L); 317LUAI_FUNC void luaE_freeCI (lua_State *L);
318LUAI_FUNC void luaE_shrinkCI (lua_State *L); 318LUAI_FUNC void luaE_shrinkCI (lua_State *L);
319LUAI_FUNC void luaE_enterCcall (lua_State *L); 319LUAI_FUNC void luaE_enterCcall (lua_State *L);
320LUAI_FUNC void luaE_warning (lua_State *L, const char *msg); 320LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont);
321 321
322 322
323#define luaE_exitCcall(L) ((L)->nCcalls--) 323#define luaE_exitCcall(L) ((L)->nCcalls--)
diff --git a/ltests.c b/ltests.c
index 23375382..40de2292 100644
--- a/ltests.c
+++ b/ltests.c
@@ -63,11 +63,8 @@ static void pushobject (lua_State *L, const TValue *o) {
63} 63}
64 64
65 65
66static void badexit (const char *fmt, ...) { 66static void badexit (const char *fmt, const char *s) {
67 va_list argp; 67 fprintf(stderr, fmt, s);
68 va_start(argp, fmt);
69 vfprintf(stderr, fmt, argp);
70 va_end(argp);
71 /* avoid assertion failures when exiting */ 68 /* avoid assertion failures when exiting */
72 l_memcontrol.numblocks = l_memcontrol.total = 0; 69 l_memcontrol.numblocks = l_memcontrol.total = 0;
73 exit(EXIT_FAILURE); 70 exit(EXIT_FAILURE);
@@ -81,52 +78,35 @@ static int tpanic (lua_State *L) {
81} 78}
82 79
83 80
84static int islast (const char *message) {
85 size_t len = strlen(message);
86 return (len > 0 && message[len - 1] == '\n');
87}
88
89
90/* 81/*
91** Warning function for tests. Fist, it concatenates all parts of 82** Warning function for tests. Fist, it concatenates all parts of
92** a warning in buffer 'buff'. Then: 83** a warning in buffer 'buff'. Then:
93** messages starting with '#' are shown on standard output (used to 84** - messages starting with '#' are shown on standard output (used to
94** test explicit warnings); 85** test explicit warnings);
95** messages containing '@' are stored in global '_WARN' (used to test 86** - messages containing '@' are stored in global '_WARN' (used to test
96** errors that generate warnings); 87** errors that generate warnings);
97** other messages abort the tests (they represent real warning conditions; 88** - other messages abort the tests (they represent real warning
98** the standard tests should not generate these conditions unexpectedly). 89** conditions; the standard tests should not generate these conditions
90** unexpectedly).
99*/ 91*/
100static void warnf (void **pud, const char *msg) { 92static void warnf (void *ud, const char *msg, int tocont) {
101 static char buff[200]; /* should be enough for tests... */ 93 static char buff[200] = ""; /* should be enough for tests... */
102 static int cont = 0; /* message to be continued */ 94 if (strlen(msg) >= sizeof(buff) - strlen(buff))
103 if (cont) { /* continuation? */ 95 badexit("%s", "warnf-buffer overflow");
104 if (strlen(msg) >= sizeof(buff) - strlen(buff)) 96 strcat(buff, msg); /* add new message to current warning */
105 badexit("warnf-buffer overflow"); 97 if (!tocont) { /* message finished? */
106 strcat(buff, msg); /* add new message to current warning */
107 }
108 else { /* new warning */
109 if (strlen(msg) >= sizeof(buff))
110 badexit("warnf-buffer overflow");
111 strcpy(buff, msg); /* start a new warning */
112 }
113 if (!islast(msg)) /* message not finished yet? */
114 cont = 1; /* wait for more */
115 else { /* handle message */
116 cont = 0; /* prepare for next message */
117 if (buff[0] == '#') /* expected warning? */ 98 if (buff[0] == '#') /* expected warning? */
118 printf("Expected Lua warning: %s", buff); /* print it */ 99 printf("Expected Lua warning: %s\n", buff); /* print it */
119 else if (strchr(buff, '@') != NULL) { /* warning for test purposes? */ 100 else if (strchr(buff, '@') != NULL) { /* warning for test purposes? */
120 lua_State *L = cast(lua_State *, *pud); 101 lua_State *L = cast(lua_State *, ud);
121 lua_unlock(L); 102 lua_unlock(L);
122 lua_pushstring(L, buff); 103 lua_pushstring(L, buff);
123 lua_setglobal(L, "_WARN"); /* assign message to global '_WARN' */ 104 lua_setglobal(L, "_WARN"); /* assign message to global '_WARN' */
124 lua_lock(L); 105 lua_lock(L);
125 return;
126 } 106 }
127 else { /* a real warning; should not happen during tests */ 107 else /* a real warning; should not happen during tests */
128 badexit("Unexpected warning in test mode: %s\naborting...\n", buff); 108 badexit("Unexpected warning in test mode: %s\naborting...\n", buff);
129 } 109 buff[0] = '\0'; /* prepare buffer for next warning */
130 } 110 }
131} 111}
132 112
@@ -1466,9 +1446,13 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) {
1466 const char *msg = getstring; 1446 const char *msg = getstring;
1467 printf("%s\n", msg); 1447 printf("%s\n", msg);
1468 } 1448 }
1449 else if EQ("warningC") {
1450 const char *msg = getstring;
1451 lua_warning(L1, msg, 1);
1452 }
1469 else if EQ("warning") { 1453 else if EQ("warning") {
1470 const char *msg = getstring; 1454 const char *msg = getstring;
1471 lua_warning(L1, msg); 1455 lua_warning(L1, msg, 0);
1472 } 1456 }
1473 else if EQ("pushbool") { 1457 else if EQ("pushbool") {
1474 lua_pushboolean(L1, getnum); 1458 lua_pushboolean(L1, getnum);
diff --git a/lua.h b/lua.h
index b777624e..09611db5 100644
--- a/lua.h
+++ b/lua.h
@@ -128,7 +128,7 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
128/* 128/*
129** Type for warning functions 129** Type for warning functions
130*/ 130*/
131typedef void (*lua_WarnFunction) (void **pud, const char *msg); 131typedef void (*lua_WarnFunction) (void *ud, const char *msg, int tocont);
132 132
133 133
134 134
@@ -309,7 +309,7 @@ LUA_API int (lua_isyieldable) (lua_State *L);
309** Warning-related functions 309** Warning-related functions
310*/ 310*/
311LUA_API void (lua_setwarnf) (lua_State *L, lua_WarnFunction f, void *ud); 311LUA_API void (lua_setwarnf) (lua_State *L, lua_WarnFunction f, void *ud);
312LUA_API void (lua_warning) (lua_State *L, const char *msg); 312LUA_API void (lua_warning) (lua_State *L, const char *msg, int tocont);
313 313
314 314
315/* 315/*
diff --git a/manual/manual.of b/manual/manual.of
index b47fd865..63e78f95 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -4061,7 +4061,7 @@ If @id{index} @N{is 0}, then all stack elements are removed.
4061 4061
4062Sets the @x{warning function} to be used by Lua to emit warnings 4062Sets the @x{warning function} to be used by Lua to emit warnings
4063@see{lua_WarnFunction}. 4063@see{lua_WarnFunction}.
4064The @id{ud} parameter initializes the slot @id{pud} passed to 4064The @id{ud} parameter sets the value @id{ud} passed to
4065the warning function. 4065the warning function.
4066 4066
4067} 4067}
@@ -4325,25 +4325,24 @@ Returns the version number of this core.
4325} 4325}
4326 4326
4327@APIEntry{ 4327@APIEntry{
4328typedef void (*lua_WarnFunction) (void **pud, const char *msg);| 4328typedef void (*lua_WarnFunction) (void *ud, const char *msg, int tocont);|
4329 4329
4330The type of @x{warning function}s, called by Lua to emit warnings. 4330The type of @x{warning function}s, called by Lua to emit warnings.
4331The first parameter is the address of a writable slot, 4331The first parameter is an opaque pointer
4332constant for a given Lua state and 4332set by @Lid{lua_setwarnf}.
4333initialized by @Lid{lua_setwarnf}.
4334The second parameter is the warning message. 4333The second parameter is the warning message.
4335This function should assume that 4334The third parameter is a boolean that
4336a message not ending with an end-of-line will be 4335indicates whether the message is
4337continued by the message in the next call. 4336to be continued by the message in the next call.
4338 4337
4339} 4338}
4340 4339
4341@APIEntry{ 4340@APIEntry{
4342void lua_warning (lua_State *L, const char *msg);| 4341void lua_warning (lua_State *L, const char *msg, int tocont);|
4343@apii{0,0,-} 4342@apii{0,0,-}
4344 4343
4345Emits a warning with the given message. 4344Emits a warning with the given message.
4346A message not ending with an end-of-line should be 4345A message in a call with @id{tocont} true should be
4347continued in another call to this function. 4346continued in another call to this function.
4348 4347
4349} 4348}
@@ -6275,11 +6274,12 @@ The current value of this variable is @St{Lua 5.4}.
6275 6274
6276} 6275}
6277 6276
6278@LibEntry{warn (message)| 6277@LibEntry{warn (message [, tocont])|
6279 6278
6280Emits a warning with the given message. 6279Emits a warning with the given message.
6281Note that messages not ending with an end-of-line 6280A message in a call with @id{tocont} true should be
6282are assumed to be continued by the message in the next call. 6281continued in another call to this function.
6282The default for @id{tocont} is false.
6283 6283
6284} 6284}
6285 6285
diff --git a/testes/all.lua b/testes/all.lua
index 506afad2..8d727b6b 100644
--- a/testes/all.lua
+++ b/testes/all.lua
@@ -6,7 +6,7 @@
6local version = "Lua 5.4" 6local version = "Lua 5.4"
7if _VERSION ~= version then 7if _VERSION ~= version then
8 warn(string.format( 8 warn(string.format(
9 "This test suite is for %s, not for %s\nExiting tests\n", version, _VERSION)) 9 "This test suite is for %s, not for %s\nExiting tests", version, _VERSION))
10 return 10 return
11end 11end
12 12
@@ -190,16 +190,16 @@ assert(dofile('verybig.lua', true) == 10); collectgarbage()
190dofile('files.lua') 190dofile('files.lua')
191 191
192if #msgs > 0 then 192if #msgs > 0 then
193 warn("#tests not performed:\n ") 193 warn("#tests not performed:", true)
194 for i=1,#msgs do 194 for i=1,#msgs do
195 warn(msgs[i]); warn("\n ") 195 warn("\n ", true); warn(msgs[i], true)
196 end 196 end
197 warn("\n") 197 warn("\n")
198end 198end
199 199
200print("(there should be two warnings now)") 200print("(there should be two warnings now)")
201warn("#This is "); warn("an expected"); warn(" warning\n") 201warn("#This is ", true); warn("an expected", true); warn(" warning")
202warn("#This is"); warn(" another one\n") 202warn("#This is", true); warn(" another one")
203 203
204-- no test module should define 'debug' 204-- no test module should define 'debug'
205assert(debug == nil) 205assert(debug == nil)
diff --git a/testes/api.lua b/testes/api.lua
index d034ea80..08672e8a 100644
--- a/testes/api.lua
+++ b/testes/api.lua
@@ -114,13 +114,11 @@ end
114 114
115-- testing warnings 115-- testing warnings
116T.testC([[ 116T.testC([[
117 warning "#This shold be a" 117 warningC "#This shold be a"
118 warning " single " 118 warningC " single "
119 warning "warning 119 warning "warning"
120" 120 warningC "#This should be "
121 warning "#This should be " 121 warning "another one"
122 warning "another one
123"
124]]) 122]])
125 123
126 124
diff --git a/testes/gc.lua b/testes/gc.lua
index 05bf564e..91e78a48 100644
--- a/testes/gc.lua
+++ b/testes/gc.lua
@@ -18,6 +18,8 @@ assert(collectgarbage("incremental") == "generational")
18assert(collectgarbage("incremental") == "incremental") 18assert(collectgarbage("incremental") == "incremental")
19 19
20 20
21local function nop () end
22
21local function gcinfo () 23local function gcinfo ()
22 return collectgarbage"count" * 1024 24 return collectgarbage"count" * 1024
23end 25end
@@ -388,7 +390,7 @@ if T then
388 collectgarbage() 390 collectgarbage()
389 for i = 1, 10 do assert(s[i]) end 391 for i = 1, 10 do assert(s[i]) end
390 392
391 getmetatable(u).__gc = false 393 getmetatable(u).__gc = nil
392 394
393end 395end
394print '+' 396print '+'
@@ -604,8 +606,8 @@ if T then
604 collectgarbage("stop") 606 collectgarbage("stop")
605 local x = T.newuserdata(0) 607 local x = T.newuserdata(0)
606 local y = T.newuserdata(0) 608 local y = T.newuserdata(0)
607 debug.setmetatable(y, {__gc = true}) -- bless the new udata before... 609 debug.setmetatable(y, {__gc = nop}) -- bless the new udata before...
608 debug.setmetatable(x, {__gc = true}) -- ...the old one 610 debug.setmetatable(x, {__gc = nop}) -- ...the old one
609 assert(T.gccolor(y) == "white") 611 assert(T.gccolor(y) == "white")
610 T.checkmemory() 612 T.checkmemory()
611 collectgarbage("restart") 613 collectgarbage("restart")
@@ -631,6 +633,7 @@ if T then
631 assert(T.totalmem("thread") == t + 1) 633 assert(T.totalmem("thread") == t + 1)
632end 634end
633 635
636
634-- create an object to be collected when state is closed 637-- create an object to be collected when state is closed
635do 638do
636 local setmetatable,assert,type,print,getmetatable = 639 local setmetatable,assert,type,print,getmetatable =
@@ -650,7 +653,7 @@ end
650 653
651-- create several objects to raise errors when collected while closing state 654-- create several objects to raise errors when collected while closing state
652if T then 655if T then
653 local error, assert, warn, find = error, assert, warn, string.find 656 local error, assert, find = error, assert, string.find
654 local n = 0 657 local n = 0
655 local lastmsg 658 local lastmsg
656 local mt = {__gc = function (o) 659 local mt = {__gc = function (o)