Lua4.0 编译入口

解决上一篇的问题,上代码了。

C 语言程序的入口为 main 函数,Lua 编译器的入口为 luac.c 文件里的 main 函数。

先来看一下 main 函数:

int main(int argc, const char* argv[])
{
 Proto** P,*tf;
 int i=doargs(argc,argv);
 argc-=i; argv+=i;
 if (argc<=0) usage("no input files given",NULL);
 L=lua_open(0);
 P=luaM_newvector(L,argc,Proto*);
 for (i=0; i<argc; i++)
  P[i]=load(IS("-")? NULL : argv[i]);
 tf=combine(P,argc);
 if (dumping) luaU_optchunk(tf);
 if (listing) luaU_printchunk(tf);
 if (testing) luaU_testchunk(tf);
 if (dumping)
 {
  if (stripping) strip(tf);
  luaU_dumpchunk(tf,efopen(output,"wb"));
 }
 return 0;
}

程序上来先声明一个函数原型的二级指针 P(下面用的时候是把它做为函数原型的指针数组来用的),一个函数原型的指针 tf。

函数原型可以简单地认为是一个 lua 文件等价的编译后的东西。

每一个 lua 文件会生成一个函数原型,最后,所有的输入 lua 文件会拼成一个函数原型。

doargs 解析入参。主要是带中划线的那样的参数。就是一系列的 IS 宏调用的判断。这个函数的注释比较清楚。代码如下:

static int doargs(int argc, const char* argv[])
{
 int i;
 for (i=1; i<argc; i++)
 {
  if (*argv[i]!=‘-‘) /* end of options */
   break;
  else if (IS("-")) /* end of options; use stdin */
   return i;
  else if (IS("-l")) /* list */
   listing=1;
  else if (IS("-o")) /* output file */
  {
   output=argv[++i];
   if (output==NULL) usage(NULL,NULL);
  }
  else if (IS("-p")) /* parse only */
   dumping=0;
  else if (IS("-s")) /* strip debug information */
   stripping=1;
  else if (IS("-t")) /* test */
  {
   testing=1;
   dumping=0;
  }
  else if (IS("-v")) /* show version */
  {
   printf("%s  %s\n",LUA_VERSION,LUA_COPYRIGHT);
   if (argc==2) exit(0);
  }
  else /* unknown option */
   usage("unrecognized option `%s‘",argv[i]);
 }
 if (i==argc && (listing || testing))
 {
  dumping=0;
  argv[--i]=OUTPUT;
 }
 return i;
}

解析好的选项保存在相应的静态变量中。

如下所示:

static int listing=0;           /* list bytecodes? */
static int dumping=1;           /* dump bytecodes? */
static int stripping=0;         /* strip debug information? */
static int testing=0;           /* test integrity? */
static const char* output=OUTPUT;   /* output file name */

输出的文件名默认为 "luac.out",如果用户指定了,则用用户指定的名字。就是上面的 IS("-o") 这块儿。

如果出错,则调用 usage 提示用户。usage 中列出了各个参数的用户及意义。

参数解析完之后,如果还有剩余的命令行参数的话,都被当作输入的 lua 源代码文件。

新建一个 lua_state ,这就是 lua 中那个无处不在的 L 。

新建函数原型 Proto 指针数组。

为每一个命令行参数调用 load ,把它转化为一个函数原型。代码如下:

 for (i=0; i<argc; i++)
  P[i]=load(IS("-")? NULL : argv[i]);

把这个数组合并为一个函数原型。 tf=combine(P,argc);

最下面的几个 if 判断根据参数选项的不同,进行不同的操作。

dump 代码之前会先对函数原型进行优化。 if (dumping) luaU_optchunk(tf);

luaU_printchunk(tf); 打印函数原型内容。

luaU_dumpchunk : dump 函数原型。

这几个先列个问题,以后细说,虽说和主要的编译过程关系不是太大。

回到编译的问题上来,一个 lua 文件是如何转经为 Proto 的呢?

这里有一个 load 函数,就是做得这个事。

static Proto* load(const char* filename)
{
 Proto* tf;
 ZIO z;
 char source[512];
 FILE* f;
 int c,undump;
 if (filename==NULL)
 {
  f=stdin;
  filename="(stdin)";
 }
 else
  f=efopen(filename,"r");
 c=ungetc(fgetc(f),f);
 if (ferror(f))
 {
  fprintf(stderr,"luac: cannot read from ");
  perror(filename);
  exit(1);
 }
 undump=(c==ID_CHUNK);
 if (undump && f!=stdin)
 {
  fclose(f);
  f=efopen(filename,"rb");
 }
 sprintf(source,"@%.*s",Sizeof(source)-2,filename);
 luaZ_Fopen(&z,f,source);
 tf = undump ? luaU_undump(L,&z) : luaY_parser(L,&z);
 if (f!=stdin) fclose(f);
 return tf;
}

程序上来声明了一个 ZIO 变量,以后读源代码就从它读取了。

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

先读文件的第一个字符,如果是 ID_CHUNK 的话,则说明此时打开的文件是一个 lua 字节码文件。

最后根据打开的是否是 lua 字节码文件来决定是进行 undump 操作还是语法解释操作。

combine 把多个 Proto 拼成一个 Proto。

其中有一个需要注意的地方是,一个函数原型是一个 Closure。就是 for 循环里面的东西。

strip 把一些调试信息删掉。

这篇的内容先到这里,等后面几个相关的知识点说完这里自然就清楚了。

看下目前的问题列表,好像已经很多了。

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

到目前为止的问题:

> 函数原型优化 luaU_optchunk

> 打印函数原型 luaU_printchunk

> dump 函数原型 luaU_dumpchunk

> 内存分配 luaM_newvector

> ZIO 是什么

> 语法分析 luaY_parser

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

时间: 2024-08-26 15:47:09

Lua4.0 编译入口的相关文章

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 语法分析

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 是一个扩展编程语言,支持通用编程功能与数据描述功能.作为一个强大

hadoop-2.2.0编译

由于从官网下载的hadoop中依赖包 native hadoop library是基于32位版本的,在64位机器上安装,会出现以下错误: 2014-05-30 19:47:49,703 INFO org.apache.hadoop.hdfs.server.datanode.DataNode: registered UNIX signal handlers for [TERM, HUP, INT]2014-05-30 19:47:49,887 WARN org.apache.hadoop.hdfs

Centos 7.0 编译安装LAMP(Linxu+apache+mysql+php)之源码安装Mysql (二)

mysql 简介: MySQL是一个关系型数据库管理系统,关系数据库将数据保存在不同的表中,这样就增加了速度并提高了灵活性.目前其属于 Oracle 旗下产品.MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件.MySQL所使用的 SQL 语言是用于访问数据库的最常用标准化语言. 安装环境: 系统: centos 7.0 最小化安装 软件

Cocos2d-x 3.0 编译 eclipse+Win7+Android 篇

文档 Eclipse --> Windows--> Preferences ... 3. Set up Variables: 1. Path Variable `COCOS2DX`: * Eclipse->Preferences->General->Workspace->**Linked Resources** * Click **New** button to add a Path Variable `COCOS2DX` pointing to the root co

android7.0 编译问题及解决【转】

本文转载自:http://blog.csdn.net/zhangmingbao2016/article/details/52699182 注意:Linux操作系统上编译Android 7.0必须使用open-jdk,mac os才可以使用Oraclejdk,我的是ubuntu16.04,下面我将我遇到的问题及解决办法做一个陈述,仅供参考: 1.正常的编译三部曲: 1)source build/envsetup.sh 2)lunch 1 3)make -j32(-j32表示是开启32个线程同时编译

Centos 7.0 编译安装LNMP(Linxu+nginx+mysql+php)之源码安装nginx (一)

nginx简介:       Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器.Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日. 其将源代码以类BSD许可证的形式发布,因它的稳定性.丰富的功能集.示例配置文件和低系统资源的消耗而闻名.2011年6月1日,nginx 1.0.4发布. Nginx是一款轻量级的Web 服务器