开始看 Lua 源码也有段时间了,由于尝试用各种方式切入,效果均不是很理想,应该是个人内功不做所致。加上先阶段个人时间有限,现记录下断点,待到来日能力足够有兴趣时再来看。
初期探索:
0、由于第一次尝试读源码,开始时竟将源码按大小顺序排列,从小文件看起。
1、尝试从数据结构看起,看完了 Lua 的数据结构后对 Lua 的数据结构还是有种朦胧的感觉。然后尝试看 Lua 的 GC 终止。
2、尝试把 Lua 当作一个程序来看,从 main 函数开始读,函数调用层层深入下去。。。作为一个菜鸟,这注定是失败的尝试。
3、从网络中找各种源码分析的文章看,源码分析看看看去也就几块,有一个人分析过了后就有一批人跟着转载,不够系统,不能随心。
4、看到了云风的 Lua 源码欣赏中关于源码的阅读顺序的合理方式,觉得可行,又一次尝试。
试读准备:
1、个人机器为 Win7 使用的源码编译工具为 minGW ,minGW 下载链接:http://sourceforge.net/projects/mingw/?source=typ_redirect。
可以使用 mingw32-make Makefile 编译 Lua 源码(说明:个人用的 Lua 源码为 5.1.4 编译出来的 dll 文件 163 kb, 然后总觉得 luaforWindows 里的 dll 要好些,就索性把 luaforWindows 的目录下的 include 文件夹和 lib 文件夹下的文件拷贝出来放在测试文件夹下不要自己编译的了)。
2、编写简单批处理生成动态链接库(make.bat)。


@echo offset curdir=%~dp0 pushd %curdir%set CFN=%1REM remove the last build (del /q %CFN%.dll) 2>nulREM get file name except extension if "%CFN:~-2%" == ".c" set CFN=%CFN:~0,-2%gcc -shared -o %CFN%.dll %CFN%.c -B %curdir% -llua5.1popd echo on
3、提取源码测试(LuaStr.c)。


/*Time :2015-04-07 09:13:23Function :Lua 的正则匹配试读 ( 截取自 Lua 源码 )Creater :Lazy_Pupa */ /*输出说明 :_Fun_i_Step_k : Output Message -- i:功能代号, k:第几步。1: str_find_aux; 2: posrelat; 3: match; 4: start_capture; 5: end_capture; 6: capture_to_close; 7: matchbalance; 8: classend; 9: matchbracketclass; 10: match_capture; 11: singlematch; 12: max_expand; 13: min_expand; 14: push_captures; 15: push_onecapture; 16: match_class; 17: check_capture; 18: ; 19: ; 20: ; */#include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h>#include "lua.h"#include "lauxlib.h" #include "lualib.h"#define uchar(c) ((unsigned char)(c))#define CAP_UNFINISHED (-1) #define CAP_POSITION (-2)#define L_ESC '%' #define SPECIALS "^$*+?.([%-"int Step = 0;typedef struct MatchState{const char *str_init;const char *str_end;lua_State *L;int level;struct {const char *init;ptrdiff_t len;}capture[LUA_MAXCAPTURES]; }MatchState;/*function: calculate relate positionparameters: (pos, len)return: (-4, 2) -> 0; (-3, 2) -> 0; (-2, 2) -> 1; (-1, 2) -> 2; (0, 2) -> 0; (1, 2) -> 1; (2, 2) -> 2; (3, 2) -> 3; */ static ptrdiff_t posrelat(ptrdiff_t pos, size_t len) {printf("_Fun_%02d_Step_%3d : parameters %d, %d\n", 2, ++Step, pos, len);if(pos < 0) pos += (ptrdiff_t)len + 1;printf("_Fun_%02d_Step_%3d :return %d ? %d : 0\n", 2, ++Step, (pos >= 0), pos);return (pos >= 0) ? pos : 0; }static const char *classend(MatchState *ms, const char *p) { // find the %f[match] pattern ']'// ms: 查找状态; *p: 匹配字符串printf("_Fun_%02d_Step_%3d : parameters '%s'\n", 8, ++Step, p);switch(*p++){case L_ESC:{if (*p == '\0')luaL_error(ms->L, "malformed pattern (end with " LUA_QL("%%") ")");printf("_Fun_%02d_Step_%3d :case L_ESC return '%s'\n", 8, ++Step, p + 1);return p + 1;}case '[':{if(*p == '^') p++;do{if(*p == '\0')luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")");if(*(p++) == L_ESC && *p != '\0')p++;}while(*p != ']');printf("_Fun_%02d_Step_%3d :case '[' return '%s'\n", 8, ++Step, p + 1);return p + 1;}default:{printf("_Fun_%02d_Step_%3d :default return '%s'\n", 8, ++Step, p);return p;}} }static int match_class(int c, int cl) {printf("_Fun_%02d_Step_%3d : parameters %d, %d\n", 16, ++Step, c, cl);int res;switch (tolower(cl)){case 'a': res = isalpha(c); break;case 'c': res = iscntrl(c); break;case 'd': res = isdigit(c); break;case 'l': res = islower(c); break;case 'p': res = ispunct(c); break;case 's': res = isspace(c); break;case 'u': res = isupper(c); break;case 'w': res = isalnum(c); break;case 'x': res = isxdigit(c); break;case 'z': res = (c == 0); break;default: return (cl == c);}printf("_Fun_%02d_Step_%3d :return (%d ? %d : %d)\n", 16, ++Step, islower(cl), res, !res);return (islower(cl) ? res : !res); }static int matchbracketclass(int c, const char *p, const char *ec) { // 匹配模版类。// c: ; *p: 匹配字符串; *ec: 匹配结束位置。printf("_Fun_%02d_Step_%3d : parameters %c, '%s', '%s'\n", 9, ++Step, c, p, ec);int sig = 1;if (*(p+1) == '^') {sig = 0;p++;}while (++p < ec) {if (*p == L_ESC) {p++;if (match_class(c, uchar(*p))){printf("_Fun_%02d_Step_%3d :if return %d\n", 9, ++Step, sig);return sig;}}else if ((*(p+1) == '-') && (p+2 < ec)) {p += 2;if (uchar(*(p-2)) <= c && c <= uchar(*p)){printf("_Fun_%02d_Step_%3d :else if return %d\n", 9, ++Step, sig);return sig;}}else if (uchar(*p) == c){printf("_Fun_%02d_Step_%3d :else if 2 return %d\n", 9, ++Step, sig);return sig;}}printf("_Fun_%02d_Step_%3d :return %d\n", 9, ++Step, !sig);return !sig; }static int singlematch(int c, const char *p, const char *ep) {// c: source char; *p: pattern string; *ep: pattern endprintf("_Fun_%02d_Step_%3d : parameters %d, '%s', '%s'\n", 11, ++Step, c, p, ep);switch(*p){case '.': printf("_Fun_%02d_Step_%3d :return 1;\n", 11, ++Step);return 1;case L_ESC: printf("_Fun_%02d_Step_%3d :return match_class(c, uchar(*(p+1)));\n", 11, ++Step);return match_class(c, uchar(*(p+1)));case '[': printf("_Fun_%02d_Step_%3d :return matchbracketclass(c, p, ep-1);\n", 11, ++Step);return matchbracketclass(c, p, ep-1);default: printf("_Fun_%02d_Step_%3d :default return %d\n", 11, ++Step, (uchar(*p) == c));return (uchar(*p) == c);} }static const char *match(MatchState *ms, const char *s, const char *p);static const char *matchbalance(MatchState *ms, const char *s, const char *p) {// ms: 查找状态; *s: 源字符串; *p: 匹配字符串// printf("ms->str_end = '%s', *s = '%s', *p = '%s'\n", ms->str_end, s, p);printf("_Fun_%02d_Step_%3d : parameters '%s', '%s'\n", 7, ++Step, s, p);if(*p == 0 || *(p+1) == 0) // *p 以 %b"结尾。luaL_error(ms->L, "unbalanced pattern");if (*s != *p) {printf("_Fun_%02d_Step_%3d :if return NULL\n", 7, ++Step);return NULL;}else {int b = *p; // 开始int e = *(p+1); // 结束int cont = 1; // while (++s < ms->str_end) {// printf("*s = %d, b = %d, e = %d, cont = %d\n*s = '%s'\n", *s, b, e, cont, s);if (*s == e) {if (--cont == 0){printf("_Fun_%02d_Step_%3d :return '%s'\n", 7, ++Step, s+1);return s+1;}}else if (*s == b) cont++; // 支持嵌套 }}printf("_Fun_%02d_Step_%3d :return NULL\n", 7, ++Step);return NULL; }static const char *max_expand(MatchState *ms, const char *s, const char *p, const char *ep) {// ms: 查找状态; *s: 源字符串; *p: 匹配字符串; *ep: 匹配字符串结尾printf("_Fun_%02d_Step_%3d : parameters '%s', '%s', '%s'\n", 12, ++Step, s, p, ep);ptrdiff_t i = 0;while((s+i) < ms->str_end && singlematch(uchar(*(s+i)), p, ep)) // anchor the match taili++;while (i >= 0) {const char *res = match(ms, (s+i), ep+1); // if (res) {printf("_Fun_%02d_Step_%3d :return '%s'\n", 12, ++Step, res);return res;}i--;}printf("_Fun_%02d_Step_%3d :return NULL\n", 12, ++Step);return NULL; }static const char *min_expand(MatchState *ms, const char *s, const char *p, const char *ep) {printf("_Fun_%02d_Step_%3d : parameters '%s', '%s', '%s'\n", 13, ++Step, s, p, ep);for(;;) {const char *res = match(ms, s, ep+1);if (res != NULL){printf("_Fun_%02d_Step_%3d : return '%s'\n", 13, ++Step, res);return res;}else if (s<ms->str_end && singlematch(uchar(*s), p, ep))s++;else{printf("_Fun_%02d_Step_%3d : return NULL\n", 13, ++Step);return NULL;}} }static const char *start_capture(MatchState *ms, const char *s, const char *p, int what) {// ms: 查找状态; *s: 源字符串; *p: 匹配字符串; what: 标记捕获是否结束printf("_Fun_%02d_Step_%3d : parameters %d, '%s', '%s', %d\n", 4, ++Step, ms->level, s, p, what);const char *res;int level = ms->level; // 捕获个数if (level > LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures");ms->capture[level].init = s;ms->capture[level].len = what; // 捕获状态ms->level = level + 1; // 捕获加一。if ((res=match(ms, s, p)) == NULL)ms->level--;printf("_Fun_%02d_Step_%3d :return '%s'\n", 4, ++Step, res);return res; }// 嵌套捕获结束 如:src = "Lua Test String!"; matchString = "((%a+) %a+)"; return "Lua Test", "Lua"; static int capture_to_close(MatchState *ms) {// ms: 查找状态printf("_Fun_%02d_Step_%3d : parameters %d\n", 6, ++Step, ms->level);int level = ms->level; // 查找深度for(level--; level>=0; level--) // 查找该捕获的起始深度if(ms->capture[level].len == CAP_UNFINISHED){printf("_Fun_%02d_Step_%3d :return %d\n", 6, ++Step, level);return level;}printf("_Fun_%02d_Step_%3d :return error\n", 6, ++Step);return luaL_error(ms->L, "invalid pattern capture"); }static const char *end_capture(MatchState *ms, const char *s, const char *p) {// ms: 查找状态; *s: 源字符串; *p: 捕获之后的字符串printf("_Fun_%02d_Step_%3d : parameters '%s', '%s'\n", 5, ++Step, s, p);int l = capture_to_close(ms); // 匹配的左括号。printf("_Fun_%02d_Step_%3d : parameters '%s', '%s', '%s', %d\n", 5, ++Step, ms->capture[l].init, s, p, s - ms->capture[l].init);const char *res;ms->capture[l].len = s - ms->capture[l].init; // 记录捕获长度。if((res = match(ms, s, p)) == NULL) // 捕获结束,开始后续匹配。ms->capture[l].len = CAP_UNFINISHED; // UNKNOW... Um, just mark capture unfinished.printf("_Fun_%02d_Step_%3d :return '%s'\n", 5, ++Step, res);return res; }static int check_capture(MatchState *ms, int l) {// ms : 查找状态; l : 匹配字符。 printf("_Fun_%02d_Step_%3d : parameters %d, %d, %d\n", 17, ++Step, ms->level, ms->capture[l].len, l);l -= '1';if (l<0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)return luaL_error(ms->L, "invalid capture index");printf("_Fun_%02d_Step_%3d : parameters %d\n", 17, ++Step, l);return l; }static const char *match_capture(MatchState *ms, const char *s, int l) {// ms : 查找状态; *s : 查找源字符串; l : 匹配字符。 printf("_Fun_%02d_Step_%3d : parameters '%s', %d\n", 10, ++Step, s, l);size_t len;l = check_capture(ms, l);printf("_Fun_%02d_Step_%3d : parameters '%s', '%s', %d\n", 10, ++Step, ms->capture[l].init, s, l);len = ms->capture[l].len;printf("_Fun_%02d_Step_%3d : parameters '%s', '%s', %d, %d\n", 10, ++Step, ms->capture[l].init, s, l, s+len);if ((size_t)(s+len) >= len && memcmp(ms->capture[l].init, s, len) == 0){printf("_Fun_%02d_Step_%3d :return '%s'\n", 10, ++Step, s+len);return s+len;}else{printf("_Fun_%02d_Step_%3d :return NULL\n", 10, ++Step);return NULL;} }static const char *match(MatchState *ms, const char *s, const char *p) {// ms : 查找状态; *s : 查找源字符串; *p : 匹配字符串。 init:printf("_Fun_%02d_Step_%3d : parameters *ms, '%s', '%s'\n", 3, ++Step, s, p);switch(*p) {case '(':{if (*(p+1) == ')') // 空捕获返回捕获的起始位置。如 find('Lua', '()') -> 1, 0, 1; find('Lua', '%a()') -> 1, 1, 2; {printf("_Fun_%02d_Step_%3d :return start_capture(ms, s, p+2, CAP_POSITION)\n", 3, ++Step);return start_capture(ms, s, p+2, CAP_POSITION);}else{printf("_Fun_%02d_Step_%3d :return start_capture(ms, s, p+1, CAP_UNFINISHED)\n", 3, ++Step);return start_capture(ms, s, p+1, CAP_UNFINISHED);}}case ')':{printf("_Fun_%02d_Step_%3d :return end_capture(ms, s, p+1)\n", 3, ++Step);return end_capture(ms, s, p+1);}case L_ESC:{ // translate meaning charswitch(*(p+1)) {case 'b':{s = matchbalance(ms, s, p+2); // if (s == NULL){printf("_Fun_%02d_Step_%3d :case 'b' return NULL\n", 3, ++Step);return NULL;}p += 4;printf("_Fun_%02d_Step_%3d :case 'b' goto init\n", 3, ++Step);goto init;}case 'f':{ // {LuaStr.find("Lua Test String!", "(%f[%a+])") -> 1 0} 没懂这是干嘛的。。。。const char *ep;char previous;p += 2;if (*p != '[')luaL_error(ms->L, "missing" LUA_QL("[") " after " LUA_QL("%%f") " in pattern");ep = classend(ms, p); // anchor the %f[] end.previous = (s == ms->str_init) ? '\0' : *(s-1);if (matchbracketclass(uchar(previous), p, ep-1) || !matchbracketclass(uchar(*s), p, ep-1)){printf("_Fun_%02d_Step_%3d :case 'f' return NULL\n", 3, ++Step);return NULL;}p = ep;printf("_Fun_%02d_Step_%3d :case 'f' goto init\n", 3, ++Step);goto init;}default: {if (isdigit(uchar(*(p+1)))) {s = match_capture(ms, s, uchar(*(p+1))); // 源自符指针后移,至下一个匹配开始。if (s == NULL){printf("_Fun_%02d_Step_%3d :case L_ESC return NULL\n", 3, ++Step);return NULL;}p += 2;printf("_Fun_%02d_Step_%3d :default goto init\n", 3, ++Step);goto init;}printf("_Fun_%02d_Step_%3d :case L_ESC goto dflt\n", 3, ++Step);goto dflt;}}}case '\0':{printf("_Fun_%02d_Step_%3d :case '\\0' return '%s'\n", 3, ++Step, s);return s;}case '$':{if (*(p+1) == '\0') // 是否匹配结束位置。 {printf("_Fun_%02d_Step_%3d :case '$' return %d ? s : NULL\n", 3, ++Step, (s == ms->str_end));return (s == ms->str_end) ? s : NULL;}else{printf("_Fun_%02d_Step_%3d :case '\0' goto dflt\n", 3, ++Step); goto dflt;}}default: dflt: {const char *ep = classend(ms, p); // check single match, if true jump to '[match string]' end ,( ep: end of *p)int m = s<ms->str_end && singlematch(uchar(*s), p, ep); // 简单匹配标识。switch(*ep) {case '?':{ // 匹配 0 次或 1 次。const char *res;if (m && ((res = match(ms, s+1, ep+1)) != NULL)) // UNKNOW ... Um, like match a result. {printf("_Fun_%02d_Step_%3d :case '?' return '%s'\n", 3, ++Step, res);return res;}p=ep+1; // Don't match any result.printf("_Fun_%02d_Step_%3d :case '?' goto init\n", 3, ++Step); goto init;}case '*':{ // 匹配 0 次或多次。printf("_Fun_%02d_Step_%3d :return max_expand(ms, s, p, ep)\n", 3, ++Step);return max_expand(ms, s, p, ep);}case '+':{ // 匹配 1 次或多次。printf("_Fun_%02d_Step_%3d :return (m ? max_expand(ms, s+1, p, ep) : NULL)\n", 3, ++Step);return (m ? max_expand(ms, s+1, p, ep) : NULL);}case '-':{ // 匹配 0 次或多次。printf("_Fun_%02d_Step_%3d :return min_expand(ms, s, p, ep)\n", 3, ++Step);return min_expand(ms, s, p, ep);}default: {if (!m){printf("_Fun_%02d_Step_%3d :default: dflt: return NULL\n", 3, ++Step);return NULL;}s++;p=ep;printf("_Fun_%02d_Step_%3d :default: dflt goto init\n", 3, ++Step); goto init;}}}} }static const char * lmemfind(const char *s1, size_t l1, const char *s2, size_t l2) {return NULL; }static void push_onecapture(MatchState *ms, int i, const char *s, const char *e) {printf("_Fun_%02d_Step_%3d : parameters %d, '%s', '%s'\n", 15, ++Step, i, s, e);if (i>=ms->level) {if (i == 0)lua_pushlstring(ms->L, s, e - s);elseluaL_error(ms->L, "invalid capture index!");}else {ptrdiff_t l = ms->capture[i].len;if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");if (l == CAP_POSITION)lua_pushinteger(ms->L, ms->capture[i].init - ms->str_init +1);elselua_pushlstring(ms->L, ms->capture[i].init, l);} }static int push_captures(MatchState *ms, const char *s, const char *e) {printf("_Fun_%02d_Step_%3d : parameters %d, '%s', '%s'\n", 14, ++Step, ms->level, s, e);int i;int nlevels = (ms->level == 0 && s) ? 1 : ms->level;luaL_checkstack(ms->L, nlevels, "too many captures");for(i=0; i<nlevels; i++)push_onecapture(ms, i, s, e);printf("_Fun_%02d_Step_%3d :return %d\n", 14, ++Step, nlevels);return nlevels; }static int str_find_aux(lua_State *L, int find) {printf("_Fun_%02d_Step_%3d : parameters find = %d\n", 1, ++Step, find);size_t srcStrLen, matchStrLen;const char *srcStr = luaL_checklstring(L, 1, &srcStrLen);const char *matchStr = luaL_checklstring(L, 2, &matchStrLen);ptrdiff_t startFindPostion = posrelat(luaL_optinteger(L, 3, 1), srcStrLen) - 1;if(startFindPostion < 0) startFindPostion = 0;else if ((size_t)(startFindPostion) > srcStrLen) startFindPostion = (ptrdiff_t)srcStrLen;if (find && (lua_toboolean(L, 4) || strpbrk(matchStr, SPECIALS) == NULL)) {const char *s2 = lmemfind(srcStr+startFindPostion, srcStrLen-startFindPostion, matchStr, matchStrLen); // 常规匹配查找if (s2) {lua_pushinteger(L, s2-srcStr+1);lua_pushinteger(L, s2-srcStr+matchStrLen);printf("_Fun_%02d_Step_%3d :return 2.\n", 1, ++Step);return 2;}}else { // 正则匹配查找 MatchState ms;int anchor = (*matchStr == '^') ? (matchStr++, 1) : 0; // 是否定位头部const char *s1 = srcStr + startFindPostion; // 待查找的字符串ms.L = L; // 保存脚本上下文ms.str_init = srcStr; // 保存待查找的字符串ms.str_end = srcStr + srcStrLen; // 保存字符串结束位置do {const char *res;ms.level = 0; // 设置默认捕获的数量if ((res=match(&ms, s1, matchStr)) != NULL) { // 匹配主体部分if (find) { // 返回查找结果lua_pushinteger(L, s1-srcStr+1);lua_pushinteger(L, res-srcStr);printf("_Fun_%02d_Step_%3d :return push_captures(&ms, NULL, 0) + 2\n", 1, ++Step);return push_captures(&ms, NULL, 0) + 2;}else // 返回匹配结果 {printf("_Fun_%02d_Step_%3d :return push_captures(&ms, s1, res)\n", 1, ++Step);return push_captures(&ms, s1, res);}}}while (s1++ < ms.str_end && !anchor); // 一次匹配不成功且非从头部开始定位则继续。 }lua_pushnil(L); // 查找失败。printf("_Fun_%02d_Step_%3d :return 1.\n", 1, ++Step);return 1; }static int str_find(lua_State *L) {printf("=================================== Lua Find Test ===================================\n"" 1: str_find_aux ; 4: start_capture ; 5: end_capture; 2: posrelat; 3: match;\n"" 6: capture_to_close; 7: matchbalance ; 8: classend ; 9: matchbracketclass;\n""10: match_capture ; 11: singlematch ; 12: max_expand ; 13: min_expand;\n""14: push_captures ; 15: push_onecapture; 16: match_class; 17: check_capture;\n""=================================== Lua Find Test ===================================\n");return str_find_aux(L, 1); }static const luaL_Reg strlib[] = {{"find", str_find},{NULL, NULL} };// Open String Library extern int luaopen_LuaStr(lua_State *L) {const char *libraryName = "LuaStr";luaL_register(L, libraryName, strlib);return 1; }
4、编译测试代码 make LuaStr.c
5、测试源码
require "LuaStr"print(LuaStr.find("Lua Test String!", "(%f[%a+])"));
6、运行看结果


=================================== Lua Find Test ===================================1: str_find_aux ; 4: start_capture ; 5: end_capture; 2: posrelat; 3: match;6: capture_to_close; 7: matchbalance ; 8: classend ; 9: matchbracketclass; 10: match_capture ; 11: singlematch ; 12: max_expand ; 13: min_expand; 14: push_captures ; 15: push_onecapture; 16: match_class; 17: check_capture; =================================== Lua Find Test =================================== _Fun_01_Step_ 1 : parameters find = 1 _Fun_02_Step_ 2 : parameters 1, 16 _Fun_02_Step_ 3 :return 1 ? 1 : 0 _Fun_03_Step_ 4 : parameters *ms, 'Lua Test String!', '(%f[%a+])' _Fun_03_Step_ 5 :return start_capture(ms, s, p+1, CAP_UNFINISHED) _Fun_04_Step_ 6 : parameters 0, 'Lua Test String!', '%f[%a+])', -1 _Fun_03_Step_ 7 : parameters *ms, 'Lua Test String!', '%f[%a+])' _Fun_08_Step_ 8 : parameters '[%a+])' _Fun_08_Step_ 9 :case '[' return ')' _Fun_09_Step_ 10 : parameters , '[%a+])', '])' _Fun_16_Step_ 11 : parameters 0, 97 _Fun_16_Step_ 12 :return (2 ? 0 : 1) _Fun_09_Step_ 13 :return 0 _Fun_09_Step_ 14 : parameters L, '[%a+])', '])' _Fun_16_Step_ 15 : parameters 76, 97 _Fun_16_Step_ 16 :return (2 ? 1 : 0) _Fun_09_Step_ 17 :if return 1 _Fun_03_Step_ 18 :case 'f' goto init _Fun_03_Step_ 19 : parameters *ms, 'Lua Test String!', ')' _Fun_03_Step_ 20 :return end_capture(ms, s, p+1) _Fun_05_Step_ 21 : parameters 'Lua Test String!', '' _Fun_06_Step_ 22 : parameters 1 _Fun_06_Step_ 23 :return 0 _Fun_05_Step_ 24 : parameters 'Lua Test String!', 'Lua Test String!', '', 0 _Fun_03_Step_ 25 : parameters *ms, 'Lua Test String!', '' _Fun_03_Step_ 26 :case '\0' return 'Lua Test String!' _Fun_05_Step_ 27 :return 'Lua Test String!' _Fun_04_Step_ 28 :return 'Lua Test String!' _Fun_01_Step_ 29 :return push_captures(&ms, NULL, 0) + 2 _Fun_14_Step_ 30 : parameters 1, '(null)', '(null)' _Fun_15_Step_ 31 : parameters 0, '(null)', '(null)' _Fun_14_Step_ 32 :return 1 1 0
另外,需要 Lua 用户手册, 网址:http://www.lua.org/manual/5.1/