aboutsummaryrefslogtreecommitdiff
path: root/src/lua/lauxlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lua/lauxlib.c')
-rw-r--r--src/lua/lauxlib.c96
1 files changed, 66 insertions, 30 deletions
diff --git a/src/lua/lauxlib.c b/src/lua/lauxlib.c
index cbe9ed3..074ff08 100644
--- a/src/lua/lauxlib.c
+++ b/src/lua/lauxlib.c
@@ -283,10 +283,10 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
283 283
284 284
285LUALIB_API int luaL_execresult (lua_State *L, int stat) { 285LUALIB_API int luaL_execresult (lua_State *L, int stat) {
286 const char *what = "exit"; /* type of termination */
287 if (stat != 0 && errno != 0) /* error with an 'errno'? */ 286 if (stat != 0 && errno != 0) /* error with an 'errno'? */
288 return luaL_fileresult(L, 0, NULL); 287 return luaL_fileresult(L, 0, NULL);
289 else { 288 else {
289 const char *what = "exit"; /* type of termination */
290 l_inspectstat(stat, what); /* interpret result */ 290 l_inspectstat(stat, what); /* interpret result */
291 if (*what == 'e' && stat == 0) /* successful termination? */ 291 if (*what == 'e' && stat == 0) /* successful termination? */
292 lua_pushboolean(L, 1); 292 lua_pushboolean(L, 1);
@@ -639,10 +639,14 @@ LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) {
639** ======================================================= 639** =======================================================
640*/ 640*/
641 641
642/* index of free-list header */ 642/* index of free-list header (after the predefined values) */
643#define freelist 0 643#define freelist (LUA_RIDX_LAST + 1)
644
645 644
645/*
646** The previously freed references form a linked list:
647** t[freelist] is the index of a first free index, or zero if list is
648** empty; t[t[freelist]] is the index of the second element; etc.
649*/
646LUALIB_API int luaL_ref (lua_State *L, int t) { 650LUALIB_API int luaL_ref (lua_State *L, int t) {
647 int ref; 651 int ref;
648 if (lua_isnil(L, -1)) { 652 if (lua_isnil(L, -1)) {
@@ -650,9 +654,16 @@ LUALIB_API int luaL_ref (lua_State *L, int t) {
650 return LUA_REFNIL; /* 'nil' has a unique fixed reference */ 654 return LUA_REFNIL; /* 'nil' has a unique fixed reference */
651 } 655 }
652 t = lua_absindex(L, t); 656 t = lua_absindex(L, t);
653 lua_rawgeti(L, t, freelist); /* get first free element */ 657 if (lua_rawgeti(L, t, freelist) == LUA_TNIL) { /* first access? */
654 ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ 658 ref = 0; /* list is empty */
655 lua_pop(L, 1); /* remove it from stack */ 659 lua_pushinteger(L, 0); /* initialize as an empty list */
660 lua_rawseti(L, t, freelist); /* ref = t[freelist] = 0 */
661 }
662 else { /* already initialized */
663 lua_assert(lua_isinteger(L, -1));
664 ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */
665 }
666 lua_pop(L, 1); /* remove element from stack */
656 if (ref != 0) { /* any free element? */ 667 if (ref != 0) { /* any free element? */
657 lua_rawgeti(L, t, ref); /* remove it from list */ 668 lua_rawgeti(L, t, ref); /* remove it from list */
658 lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ 669 lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */
@@ -668,6 +679,7 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
668 if (ref >= 0) { 679 if (ref >= 0) {
669 t = lua_absindex(L, t); 680 t = lua_absindex(L, t);
670 lua_rawgeti(L, t, freelist); 681 lua_rawgeti(L, t, freelist);
682 lua_assert(lua_isinteger(L, -1));
671 lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ 683 lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */
672 lua_pushinteger(L, ref); 684 lua_pushinteger(L, ref);
673 lua_rawseti(L, t, freelist); /* t[freelist] = ref */ 685 lua_rawseti(L, t, freelist); /* t[freelist] = ref */
@@ -1006,43 +1018,67 @@ static int panic (lua_State *L) {
1006 1018
1007 1019
1008/* 1020/*
1009** Emit a warning. '*warnstate' means: 1021** Warning functions:
1010** 0 - warning system is off; 1022** warnfoff: warning system is off
1011** 1 - ready to start a new message; 1023** warnfon: ready to start a new message
1012** 2 - previous message is to be continued. 1024** warnfcont: previous message is to be continued
1013*/ 1025*/
1014static void warnf (void *ud, const char *message, int tocont) { 1026static void warnfoff (void *ud, const char *message, int tocont);
1015 int *warnstate = (int *)ud; 1027static void warnfon (void *ud, const char *message, int tocont);
1016 if (*warnstate != 2 && !tocont && *message == '@') { /* control message? */ 1028static void warnfcont (void *ud, const char *message, int tocont);
1017 if (strcmp(message, "@off") == 0) 1029
1018 *warnstate = 0; 1030
1019 else if (strcmp(message, "@on") == 0) 1031/*
1020 *warnstate = 1; 1032** Check whether message is a control message. If so, execute the
1021 return; 1033** control or ignore it if unknown.
1034*/
1035static int checkcontrol (lua_State *L, const char *message, int tocont) {
1036 if (tocont || *(message++) != '@') /* not a control message? */
1037 return 0;
1038 else {
1039 if (strcmp(message, "off") == 0)
1040 lua_setwarnf(L, warnfoff, L); /* turn warnings off */
1041 else if (strcmp(message, "on") == 0)
1042 lua_setwarnf(L, warnfon, L); /* turn warnings on */
1043 return 1; /* it was a control message */
1022 } 1044 }
1023 else if (*warnstate == 0) /* warnings off? */ 1045}
1024 return; 1046
1025 if (*warnstate == 1) /* previous message was the last? */ 1047
1026 lua_writestringerror("%s", "Lua warning: "); /* start a new warning */ 1048static void warnfoff (void *ud, const char *message, int tocont) {
1049 checkcontrol((lua_State *)ud, message, tocont);
1050}
1051
1052
1053/*
1054** Writes the message and handle 'tocont', finishing the message
1055** if needed and setting the next warn function.
1056*/
1057static void warnfcont (void *ud, const char *message, int tocont) {
1058 lua_State *L = (lua_State *)ud;
1027 lua_writestringerror("%s", message); /* write message */ 1059 lua_writestringerror("%s", message); /* write message */
1028 if (tocont) /* not the last part? */ 1060 if (tocont) /* not the last part? */
1029 *warnstate = 2; /* to be continued */ 1061 lua_setwarnf(L, warnfcont, L); /* to be continued */
1030 else { /* last part */ 1062 else { /* last part */
1031 lua_writestringerror("%s", "\n"); /* finish message with end-of-line */ 1063 lua_writestringerror("%s", "\n"); /* finish message with end-of-line */
1032 *warnstate = 1; /* ready to start a new message */ 1064 lua_setwarnf(L, warnfon, L); /* next call is a new message */
1033 } 1065 }
1034} 1066}
1035 1067
1036 1068
1069static void warnfon (void *ud, const char *message, int tocont) {
1070 if (checkcontrol((lua_State *)ud, message, tocont)) /* control message? */
1071 return; /* nothing else to be done */
1072 lua_writestringerror("%s", "Lua warning: "); /* start a new warning */
1073 warnfcont(ud, message, tocont); /* finish processing */
1074}
1075
1076
1037LUALIB_API lua_State *luaL_newstate (void) { 1077LUALIB_API lua_State *luaL_newstate (void) {
1038 lua_State *L = lua_newstate(l_alloc, NULL); 1078 lua_State *L = lua_newstate(l_alloc, NULL);
1039 if (L) { 1079 if (L) {
1040 int *warnstate; /* space for warning state */
1041 lua_atpanic(L, &panic); 1080 lua_atpanic(L, &panic);
1042 warnstate = (int *)lua_newuserdatauv(L, sizeof(int), 0); 1081 lua_setwarnf(L, warnfoff, L); /* default is warnings off */
1043 luaL_ref(L, LUA_REGISTRYINDEX); /* make sure it won't be collected */
1044 *warnstate = 0; /* default is warnings off */
1045 lua_setwarnf(L, warnf, warnstate);
1046 } 1082 }
1047 return L; 1083 return L;
1048} 1084}