Lua4.0 lua_dofile,lua_dostring

这两个函数的定义都位于 ldo.c 中,看看这两个函数都做了什么事儿?

先来看一下 lua_dofile 执行文件

LUA_API int lua_dofile (lua_State *L, const char *filename) {
  int status = parse_file(L, filename);
  if (status == 0)  /* parse OK? */
    status = lua_call(L, 0, LUA_MULTRET);  /* call main */
  return status;
}

先解析文件,如果解析无误,则调用。

由函数名字及下面的调用我们可以猜出,parse_file 应该是做的语法解析。

static int parse_file (lua_State *L, const char *filename) {
  ZIO z;
  int status;
  int bin;  /* flag for file mode */
  int c;    /* look ahead char */
  FILE *f = (filename == NULL) ? stdin : fopen(filename, "r");
  if (f == NULL) return LUA_ERRFILE;  /* unable to open file */
  c = fgetc(f);
  ungetc(c, f);
  bin = (c == ID_CHUNK);
  if (bin && f != stdin) {
    f = freopen(filename, "rb", f);  /* set binary mode */
    if (f == NULL) return LUA_ERRFILE;  /* unable to reopen file */
  }
  lua_pushstring(L, "@");
  lua_pushstring(L, (filename == NULL) ? "(stdin)" : filename);
  lua_concat(L, 2);
  c = lua_gettop(L);
  filename = lua_tostring(L, c);  /* filename = ‘@‘..filename */
  luaZ_Fopen(&z, f, filename);
  status = protectedparser(L, &z, bin);
  lua_remove(L, c);  /* remove `filename‘ from the stack */
  if (f != stdin)
    fclose(f);
  return status;
}

先根据文件名来判断输入的是什么?

如果文件名为空,则从标准输入读取。

否则从文件名读取。

取得文件的第一个字符,如果是 ID_CHUNK 的话,表示文件是一个已经编译好的 Lua 字节码文件。

bin 标志位就是用来标识这个文件是否为 Lua 字节码文件。

后面对 filename 进行编码,前面添加 ‘@‘ 符号。

luaZ_Fopen 打开缓冲区。

protectedparser 解析。

先不看 protectedparser 里做什么了。

先看下 lua_dostring,因为最后也是调到了 protectedparser 身上。

LUA_API int lua_dostring (lua_State *L, const char *str) {
  return lua_dobuffer(L, str, strlen(str), str);
}

lua_dostring 内部调用 lua_dobuffer 来实现。

可以看出这里调用 lua_dobuffer 时 str 即当 buff 参数,又当 name 参数。

LUA_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, const char *name) {
  int status = parse_buffer(L, buff, size, name);
  if (status == 0)  /* parse OK? */
    status = lua_call(L, 0, LUA_MULTRET);  /* call main */
  return status;
}

同样,和文件类型,也是先语法解析。

解析无误,则调用。

static int parse_buffer (lua_State *L, const char *buff, size_t size,
                         const char *name) {
  ZIO z;
  if (!name) name = "?";
  luaZ_mopen(&z, buff, size, name);
  return protectedparser(L, &z, buff[0]==ID_CHUNK);
}

可以看到,在解析字符串 buffer 时,最后也是调到了 protectedparser 身上。

到 protectedparser 时,由于缓冲区 ZIO 的作用,已经没有文件或者字符串的区别了。

很不错的设计思想!

这时候,再来看看 protectedparser 。

static int protectedparser (lua_State *L, ZIO *z, int bin) {
  struct ParserS p;
  unsigned long old_blocks;
  int status;
  p.z = z; p.bin = bin;
  /* before parsing, give a (good) chance to GC */
  if (L->nblocks/8 >= L->GCthreshold/10)
    luaC_collectgarbage(L);
  old_blocks = L->nblocks;
  status = luaD_runprotected(L, f_parser, &p);
  if (status == 0) {
    /* add new memory to threshold (as it probably will stay) */
    L->GCthreshold += (L->nblocks - old_blocks);
  }
  else if (status == LUA_ERRRUN)  /* an error occurred: correct error code */
    status = LUA_ERRSYNTAX;
  return status;
}

可以看到它里面调用了 f_parser 。

static void f_parser (lua_State *L, void *ud) {
  struct ParserS *p = (struct ParserS *)ud;
  Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z);
  luaV_Lclosure(L, tf, 0);
}

f_parser 里调用 luaY_parser 来做具体的语法解析。

如果已经是字节码的文件,就不用语法解析了,直接 luaU_undump 字节码就好。

到这里,就差 lua_call 的执行了。

LUA_API int lua_call (lua_State *L, int nargs, int nresults) {
  StkId func = L->top - (nargs+1);  /* function to be called */
  struct CallS c;
  int status;
  c.func = func; c.nresults = nresults;
  status = luaD_runprotected(L, f_call, &c);
  if (status != 0)  /* an error occurred? */
    L->top = func;  /* remove parameters from the stack */
  return status;
}

lua_call 里调用 f_call

static void f_call (lua_State *L, void *ud) {
  struct CallS *c = (struct CallS *)ud;
  luaD_call(L, c->func, c->nresults);
}

f_call 里调用 luaD_call。

然后是 luaV_execute(L, cl, func+1));

这个就是虚拟机执行字节码指令了。

luaV_execute 就是个大大的 switch case,不贴代码了。

翻了下之前的博客,最早的时候有一个虚拟机执行的分析。

这里就不再重复一次这种体力劳动了。

力气应该花在更有意义的地方!

----------------------------------------

到目前为止的问题:

> 无!

----------------------------------------

时间: 2024-11-12 18:34:09

Lua4.0 lua_dofile,lua_dostring的相关文章

Lua4.0 解释器入口

开始解释器了. 解释器的入口文件为 lua.c,在文件中找到 C 语言的 main. int main (int argc, char *argv[]) {   struct Options opt;   int status;   opt.toclose = 0;   getstacksize(argc, argv, &opt);  /* handle option `-s' */   L = lua_open(opt.stacksize);  /* create state */   use

Lua4.0 参考手册(六)5.8-5.14

(接上篇)-------------------5.8 执行 Lua 代码-------------------一个宿主程序可以执行写在文件中或在字符串中的 Lua 块,使用下面的函数:     int lua_dofile (lua_State *L, const char *filename);     int lua_dostring (lua_State *L, const char *string);     int lua_dobuffer (lua_State *L, const 

Lua4.0 语法分析

Lua 最初使用的是 Yacc 生成的语法分析器,后来改为手写的递归下降语法分析器(Recursive descent parser).因为一般在语言发展的早期,语言的语法还没有稳定下来,变动可能会比较多,用工具可以快速的验证自己的想法.当语法稳定下来之后,一般都会采用手写的语法分析器.因为这样程序员是调试可控的,并且一般也能有更好的性能表现.递归下降的语法分析对编程语言的语法有要求.因 Lua 的语法比较简单,是 LL(1) 文法.所以,手工编写语法分析也就是情理之中的事了. 关于递归下降的语

Lua4.0 开篇

标题说是 4.0,其实这里分析的是 4.0.1.不过按照 Lua 的版本号规则,小号只做 bug fix .所以,下面的所说的 4.0 指的就是 release 4.0.1(在不引起混淆的情况下). 4.0 发布于 2000 年 11 月,4.0.1 发布于 2002.7,我们看的上一个版本 2.4 则是发布于 1996 年 5 月,怎么说这个版本也是二十一世纪的了. 4.0 算是比较新的版本了,因为它有在线版的代码和文档.在线文档在 http://www.lua.org/manual/,其实从

Lua4.0 参考手册(一)1-3

说明:这个文档是 doc 目录里的 manual.html 文件.原文版权归原作者所有,这篇翻译只是作为学习之用.如果翻译有不当之处,请参考原文.-------------------以下是正文-------------------编程语言 Lua4.0 的参考手册--------------------------------------1 简介--------------------------------------Lua 是一个扩展编程语言,支持通用编程功能与数据描述功能.作为一个强大

题目一:一张纸的厚度大约是0.08mm,对折多少次之后能达到珠穆朗玛峰的高度(8848.13米)?

//一张纸的厚度大约是0.08mm,对折多少次之后能达到珠穆朗玛峰的高度(8848.13米 double a = 0.08; double h =0; int i=0; for(i=1;h<8848130;i++) { a=a*2; h=a+h; } System.out.println(i);

从零开始制作H5应用(2)——V2.0版,多页单张图片滑动,透明过渡及交互指示

上一次,我们制作了我们第一个H5场景应用的V1.0版,这次我们趁热打铁,在上一版的基础上对层序进行修改和扩展. 任务 1.页面数量由3张增加至9张: 2.每张页面中放入一张全屏自适应的图片: 3.修复页面过渡中的白场,并在过渡时加入页面的透明效果 4.给予用户"向上滑动"的交互提示: 分析 老规矩,拿到任务需求后,我们还是要先具体分析每一步的实现思路: 1.页面数量由3张增加至9张 这个太简单啦,就是再复制出来6个div,并给他们添加类名就可以啦:) 2.每张页面中放入一张全屏自适应的

[经典面试题][谷歌]一个大小为n的数组,里面的数都属于范围[0, n-1],有不确定的重复元素,找到至少一个重复元素

题目 一个大小为n的数组,里面的数都属于范围[0, n-1],有不确定的重复元素,找到至少一个重复元素,要求O(1)空间和O(n)时间. 思路一 寻找重复元素,很容易想到建立哈希表来完成,遍历一遍数组就可以将每个元素映射到哈希表中.如果哈希表中已经存在这个元素则说明这就是个重复元素.这种方法可以很方便的在O(n)时间内完成对重复元素的查找.可是题目要求在O(1)的空间.因此采用哈希表这种解法肯定在空间复杂度上是不符合要求的.题目中数组中所以数字都在[0, n-1]区间范围内,因此哈希表的大小为n

10.16输入一个字符串,内有数字和非数字字符,如: a123x456 17960? 302tab5876 将其中连续的数字作为一个整数,依次存放到一数组num中。例如123放在num[0]中,456放在num[1]中……统计共有多少个整数,并输出这些数。

10.16输入一个字符串,内有数字和非数字字符,如: a123x456 17960? 302tab5876 将其中连续的数字作为一个整数,依次存放到一数组num中.例如123放在num[0]中,456放在num[1]中--统计共有多少个整数,并输出这些数. #include <stdio.h> int main(){ void search(char * parr, int * pnum); char arr[100],* parr; int num[30],* pnum; parr=arr;