lua源码编译linux,LUA源码之luaconf.h

Luaconf.h是配置的总集, 定义了平台相关的设置,是所有文件都包含的,即Rootly

Included。

0. 前言

开始关注Lua也是06年六月的事情,《程序员》的2006年第六期中,我独独看中了Lua,而不是当时我已经

比较熟悉的Python和Ruby,即使它们我都关注了好几年,但是都没有Lua给我的震撼大。于是那个夏天,

稍微地尝试读了Lua的代码。

开学后,我突然觉得自己有点受唆使,轻信了动态的福音,对Lisp系以及脚本系关注太多,有点不务正业

,于是回到了C,并且在年底投入了C++。C++的模板实在是让我爱不释手,于是寒假的时候写了一个内存

分配器,用了很多模板技巧,于是渐渐地对C++也熟悉了。

到了下学期,也就是现在,经历了一个小项目之后,在放弃C++/CLI的福音转向C#后,在.NET的信仰下,

在对DLR的期待中,决心写一个Lua的DLR实现,于是我回来了。

1. 基础设施代码解读

这部分包括基本数据结构,内存管理等部分,是重头戏。

1.1. 基本数据结构

正如Brooks所说“给我看你的流程图而藏起你的表,我将仍然莫名其妙。如果给我看你的表,那么我将不

再要你的流程图,因为它们太明显了。”不理解Lua最基本的数据结构,想要理解Lua是完全不可能的。

我们从包含的Root项,即Luaconf.h开始,它给出了最基本的信息。它是基于编译器和平台,对Lua进行最

基本的设置,是程序的元数据区。

第一段,平台选择:

#if defined(__STRICT_ANSI__)

#define LUA_ANSI

#endif

#if !defined(LUA_ANSI) &&

defined(_WIN32)

#define LUA_WIN

#endif

#if defined(LUA_USE_LINUX)

#define LUA_USE_POSIX

#define LUA_USE_DLOPEN #define LUA_USE_READLINE #endif

#if defined(LUA_USE_MACOSX)

#define LUA_USE_POSIX

#define LUA_DL_DYLD #endif

显然对于LUA_WIN来说,w32平台的确是用Unicode的,也就是非LUA_ANSI的。当定义了LUA_USE_LINUX和

LUA_USE_MACOSX后,需要POSIX标准以及定义相应的打开动态链接库的方法。这里可以看出Linux和BSD系

在打开动态库时的差别。

这里是POSIX的相关定义:

#if defined(LUA_USE_POSIX)

#define LUA_USE_MKSTEMP

#define LUA_USE_ISATTY

#define LUA_USE_POPEN

#define LUA_USE_ULONGJMP

#endif

这个是环境变量相关的:

#define

LUA_PATH "LUA_PATH"

#define

LUA_CPATH "LUA_CPATH"

#define LUA_INIT "LUA_INIT"

具体路径自己定。

于是这一段也很好理解了:

#if defined(_WIN32)

#define LUA_LDIR "!\\lua\\"

#define LUA_CDIR "!\\"

#define LUA_PATH_DEFAULT \

".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \

LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua"

#define LUA_CPATH_DEFAULT \

".\\?.dll;" LUA_CDIR"?.dll;"

LUA_CDIR"loadall.dll"

#else

#define LUA_ROOT "/usr/local/"

#define LUA_LDIR LUA_ROOT "share/lua/5.1/"

#define LUA_CDIR LUA_ROOT "lib/lua/5.1/"

#define LUA_PATH_DEFAULT \

"./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \

LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua"

#define LUA_CPATH_DEFAULT \

"./?.so;" LUA_CDIR"?.so;"

LUA_CDIR"loadall.so"

#endif

好了,接下来是Lua中特别指明的平台相关部分,库的加载:

#if defined(LUA_BUILD_AS_DLL)

#if defined(LUA_CORE) || defined(LUA_LIB)

#define LUA_API __declspec(dllexport)

#else

#define LUA_API __declspec(dllimport)

#endif

#else

#define LUA_API extern

#endif

#define LUALIB_API LUA_API

这里的LUA_BUILD_AS_DLL就是在编译的时候提交给编译器的一个选项。下面是另外一些自定义关键字。

#if defined(luaall_c)

#define LUAI_FUNC static

#define LUAI_DATA

#elif defined(__GNUC__) &&

((__GNUC__*100 + __GNUC_MINOR__) >= 302)

&& \

defined(__ELF__)

#define

LUAI_FUNC __attribute__((visibility("hidden")))

extern

#define LUAI_DATA LUAI_FUNC

#else

#define LUAI_FUNC extern

#define LUAI_DATA extern

#endif

显然,一般的编译器将会标记为static,而当编译器版本为GCC 3.2+或者是ELF时,就可以使用

__attribute__((visibility("hidden"))) extern了。

#define LUA_QL(x) "'" x "'"

#define LUA_QS LUA_QL("%s")

要理解这段代码其实也不难,随便找个程序,把这两个宏代入,比如,printf(LUA_QS, "hello world")

中,你可以得到'hello world'的输出。

#define LUA_IDSIZE 60

一下是Lua作为一个独立程序的设置:

#if defined(lua_c) || defined(luaall_c)

#if defined(LUA_USE_ISATTY)

#include

#define lua_stdin_is_tty() isatty(0)

#elif defined(LUA_WIN)

#include

#include

#define

lua_stdin_is_tty() _isatty(_fileno(stdin))

#else

#define

lua_stdin_is_tty() 1 #endif

这里有几种选择,如果定义了LUA_USE_ISATTY,那么则使用unistd.h(POSIX标准)并将tty定义为

isatty(0),否则,检查是否为w32环境,则定义_isatty(_fileno(stdin)),再不然,用传统的Unix的习

惯,stdin的文件号(即w32中的文件句柄)为1。

提示符部分:

#define

LUA_PROMPT ">

"

#define

LUA_PROMPT2 ">>

"

程序名称:

#define LUA_PROGNAME "lua"

#define LUA_MAXINPUT 512

#if defined(LUA_USE_READLINE)

#include

#include

#include

#define lua_readline(L,b,p) ((void)L,

((b)=readline(p)) != NULL)

#define lua_saveline(L,idx) \

if (lua_strlen(L,idx) >

0) \

add_history(lua_tostring(L,

idx)); #define lua_freeline(L,b) ((void)L, free(b))

#else

#define lua_readline(L,b,p) \

((void)L, fputs(p, stdout),

fflush(stdout), \

fgets(b, LUA_MAXINPUT, stdin) !=

NULL) #define lua_saveline(L,idx) { (void)L; (void)idx;

}

#define lua_freeline(L,b) { (void)L; (void)b;

}

#endif

#endif

但是不知道为什么,它要求了Lua_State的L,但是直接将之Discard了。

再往下就是GC相关Configurations了。

#define LUAI_GCPAUSE 200

#define LUAI_GCMUL 200

#undef LUA_COMPAT_GETN

#undef LUA_COMPAT_LOADLIB

#define LUA_COMPAT_VARARG

#define LUA_COMPAT_MOD

#define LUA_COMPAT_LSTR 1

#define LUA_COMPAT_GFIND

#define LUA_COMPAT_OPENLIB

#if defined(LUA_USE_APICHECK)

#include

#define luai_apicheck(L,o) { (void)L; assert(o);

}

#else

#define luai_apicheck(L,o) { (void)L; }

#endif

如果定义了这个宏,则用标准库的assert.h的assert来判断o,但是不知为什么还是抛弃了L。

#if INT_MAX-20 < 32760

#define LUAI_BITSINT 16

#elif INT_MAX > 2147483640L

#define LUAI_BITSINT 32

#else

#error "you must define LUA_BITSINT with number of bits in an

integer"

#endif

#if LUAI_BITSINT >= 32

#define LUAI_UINT32 unsigned int

#define LUAI_INT32 int

#define LUAI_MAXINT32 INT_MAX

#define LUAI_UMEM size_t

#define LUAI_MEM ptrdiff_t

#else

#define LUAI_UINT32 unsigned long

#define LUAI_INT32 long

#define LUAI_MAXINT32 LONG_MAX

#define LUAI_UMEM unsigned long

#define LUAI_MEM long

#endif

#define LUAI_MAXCALLS 20000

#define LUAI_MAXCSTACK 2048

#define LUAI_MAXCCALLS 200

#define LUAI_MAXVARS 200

#define LUAI_MAXUPVALUES 60

#define

LUAL_BUFFERSIZE BUFSIZ

#define LUA_NUMBER_DOUBLE

#define LUA_NUMBER double

#define LUAI_UACNUMBER double

#define

LUA_NUMBER_SCAN "%lf"

#define

LUA_NUMBER_FMT "%.14g"

#define lua_number2str(s,n) sprintf((s),

LUA_NUMBER_FMT, (n))

#define LUAI_MAXNUMBER2STR 32

#define lua_str2number(s,p) strtod((s), (p))

#if defined(LUA_CORE)

#include

#define luai_numadd(a,b) ((a)+(b))

#define luai_numsub(a,b) ((a)-(b))

#define luai_nummul(a,b) ((a)*(b))

#define luai_numdiv(a,b) ((a)/(b))

#define luai_nummod(a,b) ((a) -

floor((a)/(b))*(b))

#define luai_numpow(a,b) (pow(a,b))

#define

luai_numunm(a) (-(a))

#define

luai_numeq(a,b) ((a)==(b))

#define

luai_numlt(a,b) ((a)

#define

luai_numle(a,b) ((a)<=(b))

#define luai_numisnan(a) (!luai_numeq((a),

(a)))

#endif

#if defined(LUA_NUMBER_DOUBLE) &&

!defined(LUA_ANSI) &&

!defined(__SSE2__) && \

(defined(__i386) || defined (_M_IX86) || defined(__i386__))

#if defined(_MSC_VER)

#define lua_number2int(i,d) __asm fld d __asm fistp i

#define

lua_number2integer(i,n) lua_number2int(i,

n)

#else

union luai_Cast { double l_d; long l_l; };

#define lua_number2int(i,d) \

{ volatile union luai_Cast u; u.l_d = (d) +

6755399441055744.0; (i) = u.l_l; }

#define

lua_number2integer(i,n) lua_number2int(i,

n)

#endif

#else

#define lua_number2int(i,d) ((i)=(int)(d))

#define

lua_number2integer(i,d) ((i)=(lua_Integer)(d))

#endif

#define LUAI_USER_ALIGNMENT_T union { double u;

void *s; long l; }

#if defined(__cplusplus)

#define LUAI_THROW(L,c) throw(c)

#define LUAI_TRY(L,c,a) try { a } catch(...)

\

{ if ((c)->status == 0)

(c)->status = -1; }

#define luai_jmpbuf int

#elif defined(LUA_USE_ULONGJMP)

#define

LUAI_THROW(L,c) _longjmp((c)->b,

1)

#define LUAI_TRY(L,c,a) if

(_setjmp((c)->b) == 0) { a }

#define luai_jmpbuf jmp_buf

#else

#define

LUAI_THROW(L,c) longjmp((c)->b,

1)

#define LUAI_TRY(L,c,a) if

(setjmp((c)->b) == 0) { a }

#define luai_jmpbuf jmp_buf

#endif

这部分是源代码级的异常处理。Unix下用_longjmp/_setjmp效率更加高。

#define LUA_MAXCAPTURES 32

#if defined(loslib_c) || defined(luaall_c)

#if defined(LUA_USE_MKSTEMP)

#include

#define LUA_TMPNAMBUFSIZE 32

#define lua_tmpnam(b,e) { \

strcpy(b, "/tmp/lua_XXXXXX"); \

e = mkstemp(b); \

if (e != -1) close(e); \

e = (e == -1); }

#else

#define LUA_TMPNAMBUFSIZE L_tmpnam

#define lua_tmpnam(b,e) { e =

(tmpnam(b) == NULL); }

#endif

#endif

#if defined(LUA_USE_POPEN)

#define lua_popen(L,c,m) ((void)L,

popen(c,m))

#define lua_pclose(L,file) ((void)L, (pclose(file)

!= -1))

#elif defined(LUA_WIN)

#define lua_popen(L,c,m) ((void)L,

_popen(c,m))

#define lua_pclose(L,file) ((void)L,

(_pclose(file) != -1))

#else

#define lua_popen(L,c,m) ((void)((void)c,

m), \

luaL_error(L, LUA_QL("popen") "

not supported"), (FILE*)0)

#define

lua_pclose(L,file) ((void)((void)L,

file), 0)

#endif

#if defined(LUA_USE_DLOPEN)

#define LUA_DL_DLOPEN

#endif

#if defined(LUA_WIN)

#define LUA_DL_DLL

#endif

#define LUAI_EXTRASPACE 0

#define

luai_userstateopen(L) ((void)L)

#define

luai_userstateclose(L) ((void)L)

#define luai_userstatethread(L,L1) ((void)L)

#define

luai_userstatefree(L) ((void)L)

#define luai_userstateresume(L,n) ((void)L)

#define luai_userstateyield(L,n) ((void)L)

#if defined(LUA_USELONGLONG)

#define

LUA_INTFRMLEN "ll"

#define LUA_INTFRM_T long

long

#else

#define

LUA_INTFRMLEN "l"

#define LUA_INTFRM_T long

#endif

综上所述,这个文件定义的最重要的几个方面:动态库操作(重中之重,根据Programming in Lua的说法

,这方面是Lua中唯一依赖于平台的做法),异常及错误处理,打印数据格式,数字运算,C Stack,GC,

对齐等方面。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值