# Lua代码阅读(1)

lua源代码可以在这里在线阅读http://www.lua.org/source/5.1/，另外还有一个索引页面http://www.lua.org/source/5.1/idx.html也是非常有帮助。

———————————
lmathlib.c
———————————

#undef PI
#define PI (3.14159265358979323846)

static const luaL_Reg mathlib[] = {
{"abs",   math_abs},
{"acos",  math_acos},
{"asin",  math_asin},
{"atan2", math_atan2},
{"atan",  math_atan},
{"ceil",  math_ceil},
{"cosh",   math_cosh},
{"cos",   math_cos},
{"deg",   math_deg},
{"exp",   math_exp},
{"floor", math_floor},
{"fmod",   math_fmod},
{"frexp", math_frexp},
{"ldexp", math_ldexp},
{"log10", math_log10},
{"log",   math_log},
{"max",   math_max},
{"min",   math_min},
{"modf",   math_modf},
{"pow",   math_pow},
{"random",     math_random},
{"randomseed", math_randomseed},
{"sinh",   math_sinh},
{"sin",   math_sin},
{"sqrt",  math_sqrt},
{"tanh",   math_tanh},
{"tan",   math_tan},
{NULL, NULL}
};

/*
** Open math library
*/
LUALIB_API int luaopen_math (lua_State *L) {
luaL_register(L, LUA_MATHLIBNAME, mathlib);
lua_pushnumber(L, PI);
lua_setfield(L, -2, "pi");
lua_pushnumber(L, HUGE_VAL);
lua_setfield(L, -2, "huge");
return 1;
}

mathlib定义了一个名字（字符串）到函数的映射数组，然后在函数luaopen_math中，通过luaL_register注册这个映射数组，这样Lua就可以通过函数名来调用扩展函数。这实际上也是其他C语言扩展Lua最常用的步骤。

static int math_ceil (lua_State *L) {
lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
return 1;
}

static int math_floor (lua_State *L) {
lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
return 1;
}

static int math_fmod (lua_State *L) {
lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
return 1;
}

void lua_pushnil(lua_State * L);
void lua_pushboolean(lua_State * L, int bool);
void lua_pushnumber(lua_State * L, double n);
void lua_pushlstring(lua_State * L, const char * s, size_t length);
void lua_pushstring(lua_State * L, const char * s);

———————————————-

static int math_min (lua_State *L) {
int n = lua_gettop(L);  /* number of arguments */
lua_Number dmin = luaL_checknumber(L, 1);
int i;
for (i=2; i<=n; i++) {
lua_Number d = luaL_checknumber(L, i);
if (d < dmin)
dmin = d;
}
lua_pushnumber(L, dmin);
return 1;
}

———————————————-

static int math_random (lua_State *L) {
/* the `%’ avoids the (rare) case of r==1, and is needed also because on
some systems (SunOS!) `rand()’ may return a value larger than RAND_MAX */
lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
switch (lua_gettop(L)) {  /* check number of arguments */
case 0: {  /* no arguments */
lua_pushnumber(L, r);  /* Number between 0 and 1 */
break;
}
case 1: {  /* only upper limit */
int u = luaL_checkint(L, 1);
luaL_argcheck(L, 1<=u, 1, "interval is empty");
lua_pushnumber(L, floor(r*u)+1);  /* int between 1 and `u’ */
break;
}
case 2: {  /* lower and upper limits */
int l = luaL_checkint(L, 1);
int u = luaL_checkint(L, 2);
luaL_argcheck(L, l<=u, 2, "interval is empty");
lua_pushnumber(L, floor(r*(u-l+1))+l);  /* int between `l’ and `u’ */
break;
}
default: return luaL_error(L, "wrong number of arguments");
}
return 1;
}

static int math_randomseed (lua_State *L) {
srand(luaL_checkint(L, 1));
return 0;
}

———————————————-

———————————————-

static const luaL_Reg strlib[] = {
{"byte", str_byte},
{"char", str_char},
{"dump", str_dump},
{"find", str_find},
{"format", str_format},
{"gfind", gfind_nodef},
{"gmatch", gmatch},
{"gsub", str_gsub},
{"len", str_len},
{"lower", str_lower},
{"match", str_match},
{"rep", str_rep},
{"reverse", str_reverse},
{"sub", str_sub},
{"upper", str_upper},
{NULL, NULL}
};

LUALIB_API int luaopen_string (lua_State *L) {
luaL_register(L, LUA_STRLIBNAME, strlib);
createmetatable(L);
return 1;
}

static int str_len (lua_State *L) {
size_t l;
luaL_checklstring(L, 1, &l);
lua_pushinteger(L, l);
return 1;
}

LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {
const char *s = lua_tolstring(L, narg, len);
if (!s) tag_error(L, narg, LUA_TSTRING);
return s;
}

typedef union TString {
L_Umaxalign dummy;  /* ensures maximum alignment for strings */
struct {
lu_byte reserved;
unsigned int hash;
size_t len;
} tsv;
} TString;

#ifndef cast
#define cast(t, exp)    ((t)(exp))
#endif

#define getstr(ts)    cast(const char *, (ts) + 1)
#define svalue(o)       getstr(rawtsvalue(o))

———————————————-

static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {
/* relative string position: negative means back from end */
if (pos < 0) pos += (ptrdiff_t)len + 1;
return (pos >= 0) ? pos : 0;
}

static int str_sub (lua_State *L) {
size_t l;
const char *s = luaL_checklstring(L, 1, &l);
ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);
// luaL_optinteger(L, 3, -1)将会检查第三个参数，如果为none或者nil，那么就用-1来作为默认值。第一第二个值为必须，posrelate()会将-1这样的负索引转为正向索引。
ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);
// Lua中string的索引值也是从1开始
if (start < 1) start = 1;
if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;
// 如果索引开始值小于结束值，那么截取一段字符串，否则返回空字符串。
if (start <= end)
lua_pushlstring(L, s+start-1, end-start+1);
else lua_pushliteral(L, "");
return 1;
}

——————————————————–

static int str_reverse (lua_State *L) {
size_t l;
luaL_Buffer b;

const char *s = luaL_checklstring(L, 1, &l);
luaL_buffinit(L, &b);
luaL_pushresult(&b);
return 1;
}

typedef struct luaL_Buffer {
char *p;            /* current position in buffer */
int lvl;  /* number of strings in the stack (level) */
lua_State *L;
char buffer[LUAL_BUFFERSIZE];
} luaL_Buffer;

((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
(*(B)->p++ = (char)(c)))

static void luaL_addchar2(luaL_Buffer* pBuffer, char c)
{
if (pBuffer->p < (pBuffer->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(pBuffer))
{
*pBuffer->p = c;
*pBuffer->p++;
}
}

LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) {
if (emptybuffer(B))
return B->buffer;
}

static int emptybuffer (luaL_Buffer *B) {
size_t l = bufflen(B);
if (l == 0) return 0;  /* put nothing on stack */
else {
lua_pushlstring(B->L, B->buffer, l);
B->p = B->buffer;
B->lvl++;
return 1;
}
}

static void adjuststack (luaL_Buffer *B) {
if (B->lvl > 1) {
lua_State *L = B->L;
int toget = 1;  /* number of levels to concat */
size_t toplen = lua_strlen(L, -1);
do {
size_t l = lua_strlen(L, -(toget+1));
if (B->lvl – toget + 1 >= LIMIT || toplen > l) {
toplen += l;
toget++;
}
else break;
} while (toget < B->lvl);
lua_concat(L, toget);
B->lvl = B->lvl – toget + 1;
}
}

str_reverse最后会调用luaL_pushresult这个函数，将buffer中的字符串压入lua栈中，然后执行lua_concat操作，当然，只有当lvl大于2的时候，才会真正调用string的concat操作。

LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
emptybuffer(B);
lua_concat(B->L, B->lvl);
B->lvl = 1;
}

————————————————-

static int writer (lua_State *L, const void* b, size_t size, void* B) {
(void)L;
luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
return 0;
}

static int str_dump (lua_State *L) {
luaL_Buffer b;
luaL_checktype(L, 1, LUA_TFUNCTION);
lua_settop(L, 1);
luaL_buffinit(L,&b);
if (lua_dump(L, writer, &b) != 0)
luaL_error(L, "unable to dump given function");
luaL_pushresult(&b);
return 1;
}

typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);
typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);

——————————————————-

static int str_format (lua_State *L) {
int arg = 1;
size_t sfl;
// 返回输入的字符串。
const char *strfrmt = luaL_checklstring(L, arg, &sfl);
// 定义一个结尾标记指针
const char *strfrmt_end = strfrmt+sfl;
luaL_Buffer b;
// 初始化buffer。
luaL_buffinit(L, &b);

//如果没有到结尾，就处理字符串。
while (strfrmt < strfrmt_end) {
// 当前字符不是%，也就是一个正常字符串，把它加入buffer中，然后当前指针++后移。
if (*strfrmt != L_ESC)
// 当前指针是%而且下一个也是%，把%字符加入buffer。
else if (*++strfrmt == L_ESC)
// 当前指针指向format字符，通过scanformat读取。
else { /* format item */
char form[MAX_FORMAT];  /* to store the format (`%…’) */
char buff[MAX_ITEM];  /* to store the formatted item */
arg++;
strfrmt = scanformat(L, strfrmt, form);
switch (*strfrmt++) {
case ‘c’: {
sprintf(buff, form, (int)luaL_checknumber(L, arg));
break;
}
case ‘d’:  case ‘i’: {
sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
break;
}
case ‘o’:  case ‘u’:  case ‘x’:  case ‘X’: {
sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
break;
}
case ‘e’:  case ‘E’: case ‘f’:
case ‘g’: case ‘G’: {
sprintf(buff, form, (double)luaL_checknumber(L, arg));
break;
}
case ‘q’: {
continue;  /* skip the ‘addsize’ at the end */
}
case ‘s’: {
size_t l;
const char *s = luaL_checklstring(L, arg, &l);
if (!strchr(form, ‘.’) && l >= 100) {
/* no precision and string is too long to be formatted;
keep original string */
lua_pushvalue(L, arg);
continue;  /* skip the `addsize’ at the end */
}
else {
sprintf(buff, form, s);
break;
}
}
default: {  /* also treat cases `pnLlh’ */
return luaL_error(L, "invalid option " LUA_QL("%%%c") " to "
LUA_QL("format"), *(strfrmt – 1));
}
}
// 将buff压入字符串BUFFER中。
}
}
//将字符串BUFFER压入堆栈中。
luaL_pushresult(&b);
return 1;
}

—————————————————

static int match_class (int c, int 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);
}
return (islower(cl) ? res : !res);}