diff options
-rw-r--r-- | include/modes.h | 1 | ||||
-rw-r--r-- | mbbsd/bbslua.c | 146 | ||||
-rw-r--r-- | mbbsd/more.c | 5 | ||||
-rw-r--r-- | mbbsd/pmore.c | 6 |
4 files changed, 137 insertions, 21 deletions
diff --git a/include/modes.h b/include/modes.h index c56e6548..f5cd6b18 100644 --- a/include/modes.h +++ b/include/modes.h @@ -23,6 +23,7 @@ #define RET_DOQUERYINFO (997) #define RET_DOSYSOPEDIT (996) #define RET_DOCHESSREPLAY (995) +#define RET_DOBBSLUA (994) /* user 操作狀態與模式 */ #define IDLE 0 diff --git a/mbbsd/bbslua.c b/mbbsd/bbslua.c index 2a94ecd9..ddb4795c 100644 --- a/mbbsd/bbslua.c +++ b/mbbsd/bbslua.c @@ -22,8 +22,12 @@ // DEFINITION ////////////////////////////////////////////////////////////////////////// -#define BBSLUA_VERSION (1) -#define BBSLUA_VERSION_STR "1.0" +#define BBSLUA_VERSION_MAJOR (0) +#define BBSLUA_VERSION_MINOR (1) +#define BBSLUA_VERSION_STR "0.01" +#define BBSLUA_SIGNATURE "-- BBSLUA" +#define BBSLUA_EOFSIGNATURE "--\n" + #define BLAPI_PROTO int ////////////////////////////////////////////////////////////////////////// @@ -307,47 +311,147 @@ bbsluaHook(lua_State *L, lua_Debug* ar) lua_yield(L, 0); } +static char * +bbslua_mmap(const char *fpath, int *plen) +{ + struct stat st; + int fd = open(fpath, O_RDONLY, 0600); + char *buf = NULL; + + *plen = 0; + + if (fd < 0) return buf; + if (fstat(fd, &st) || ((*plen = st.st_size) < 1) || S_ISDIR(st.st_mode)) + { + close(fd); + return buf; + } + *plen = *plen +1; + + buf = mmap(NULL, *plen, PROT_READ, MAP_SHARED, fd, 0); + close(fd); + + if (buf == NULL || buf == MAP_FAILED) + { + *plen = 0; + return NULL; + } + + madvise(buf, *plen, MADV_SEQUENTIAL); + return buf; +} + +int +bbslua_detect_range(char **pbs, char **pbe) +{ + int szsig = strlen(BBSLUA_SIGNATURE), + szeofsig = strlen(BBSLUA_EOFSIGNATURE); + char *bs, *be, *ps, *pe; + + bs = ps = *pbs; + be = pe = *pbe; + + // find start + while (ps + szsig < pe) + { + if (strncmp(ps, BBSLUA_SIGNATURE, szsig) == 0) + break; + // else, skip to next line + while (ps + szsig < pe && *ps++ != '\n'); + } + + if (!(ps + szsig < pe)) + return 0; + + *pbs = ps; + *pbe = be; + + // find tail + pe = be - szeofsig-2; + while (pe > ps) + { + if (pe+2 + szeofsig < be && + strncmp(pe+2, BBSLUA_EOFSIGNATURE, szeofsig) == 0) + break; + while (pe > ps && *pe-- != '\n'); + } + if (pe > ps) + *pbe = pe+2; + return 1; +} + int bbslua(const char *fpath) { int r = 0; lua_State *L = lua_open(); + char *bs, *ps, *pe; + int sz = 0; + + // detect file + bs = bbslua_mmap(fpath, &sz); + if (!bs) + return 0; + ps = bs; + pe = ps + sz; + + if(!bbslua_detect_range(&ps, &pe)) + { + // not detected + munmap(bs, sz); + return 0; + } + // load file abortBBSLua = 0; myluaL_openlibs(L); luaL_openlib(L, "bbs", lib_bbslua, 0); bbsluaRegConst(L, "bbs"); + r = luaL_loadbuffer(L, ps, pe-ps, "BBS-Lua"); + + // unmap + munmap(bs, sz); + + if (r != 0) + { + vmsg("BBS-Lua 錯誤: 請修正程式碼。"); + return 0; + } + // prompt user grayout(0, b_lines, GRAYOUT_DARK); - move(b_lines, 0); clrtoeol(); - outs("Loading BBS-Lua " BBSLUA_VERSION_STR " ..."); refresh(); + move(b_lines-2, 0); clrtobot(); + outs("\n"ANSI_COLOR(1;33;41) + "請按任意鍵開始執行 BBS-Lua 程式。 執行中您可隨時按下 Ctrl-C 強制中斷。" + ANSI_RESET); + + vmsg(" BBS-Lua " BBSLUA_VERSION_STR ); - if ((r = luaL_loadfile(L, fpath)) == 0) + // ready for running + lua_sethook(L, bbsluaHook, LUA_MASKCOUNT, 100 ); + clear(); + + while (!abortBBSLua && lua_resume(L, 0) == LUA_YIELD) { - // ready for running - lua_sethook(L, bbsluaHook, LUA_MASKCOUNT, 100 ); + if (input_isfull()) + drop_input(); + + refresh(); - while (!abortBBSLua && lua_resume(L, 0) == LUA_YIELD) + // check if input key is system break key. + if (peek_input(0.1, Ctrl('C'))) { - if (input_isfull()) - drop_input(); - - refresh(); - - // check if input key is system break key. - if (peek_input(0.1, Ctrl('C'))) - { - drop_input(); - abortBBSLua = 1; - break; - } + drop_input(); + abortBBSLua = 1; + break; } } lua_close(L); grayout(0, b_lines, GRAYOUT_DARK); move(b_lines, 0); clrtoeol(); - vmsgf("BBS-Lua: %s", abortBBSLua ? "USER ABORT" : r ? "FAILED" : "OK"); + vmsgf("BBS-Lua 執行結束%s。", + abortBBSLua ? " (使用者中斷)" : r ? " (程式錯誤)" : ""); clear(); return 0; diff --git a/mbbsd/more.c b/mbbsd/more.c index 252e9d02..2d4fec8d 100644 --- a/mbbsd/more.c +++ b/mbbsd/more.c @@ -31,6 +31,11 @@ int more(char *fpath, int promptend) r = FULLUPDATE; ChessReplayGame(fpath); break; + + case RET_DOBBSLUA: + r = FULLUPDATE; + bbslua(fpath); + break; } return r; diff --git a/mbbsd/pmore.c b/mbbsd/pmore.c index d82c721f..9d82838a 100644 --- a/mbbsd/pmore.c +++ b/mbbsd/pmore.c @@ -2368,6 +2368,12 @@ pmore(char *fpath, int promptend) MFDISP_DIRTY(); break; +#if defined(USE_BBSLUA) && defined(RET_DOBBSLUA) + case 'P': + flExit = 1, retval = RET_DOBBSLUA; + break; +#endif + #ifdef PMORE_USE_ASCII_MOVIE case 'p': /* play ascii movie again |