// File: /workspace/github_c_makefile_star2_O0/nilyang[P]redis-tdd-annotation/src/scripting.c
// Function: scriptingInit
void scriptingInit(void) {

    // 创建一个新的 lua 环境
    lua_State *lua = lua_open();

    // 载入内置函数库
    luaLoadLibraries(lua);

    // 屏蔽所有不想暴露给脚本环境的函数（目前只有 loadfile）
    luaRemoveUnsupportedFunctions(lua);

    /* Initialize a dictionary we use to map SHAs to scripts.
     *
     * 创建一个字典，用于将 SHA 校验码映射到脚本
     *
     * This is useful for replication, as we need to replicate EVALSHA
     * as EVAL, so we need to remember the associated script. 
     *
     * 因为 Redis 目前复制脚本的方法是将 EVALSHA 转换为 EVAL 来进行的，
     * 所以程序需要保存和 SHA 校验值相对应的脚本。
     */
    server.lua_scripts = dictCreate(&shaScriptObjectDictType,NULL);

    /* Register the redis commands table and fields */
    // 创建 lua 表，并以给定名称将 C 函数注册到表格上
    lua_newtable(lua);

    /* redis.call */
    /* 注册 redis.call */
    lua_pushstring(lua,"call");
    lua_pushcfunction(lua,luaRedisCallCommand);
    lua_settable(lua,-3);

    /* redis.pcall */
    /* 注册 redis.pcall */
    lua_pushstring(lua,"pcall");
    lua_pushcfunction(lua,luaRedisPCallCommand);
    lua_settable(lua,-3);

    /* redis.log and log levels. */
    /* 注册 redis.log 和 log levels. */
    lua_pushstring(lua,"log");
    lua_pushcfunction(lua,luaLogCommand);
    lua_settable(lua,-3);

    lua_pushstring(lua,"LOG_DEBUG");
    lua_pushnumber(lua,REDIS_DEBUG);
    lua_settable(lua,-3);

    lua_pushstring(lua,"LOG_VERBOSE");
    lua_pushnumber(lua,REDIS_VERBOSE);
    lua_settable(lua,-3);

    lua_pushstring(lua,"LOG_NOTICE");
    lua_pushnumber(lua,REDIS_NOTICE);
    lua_settable(lua,-3);

    lua_pushstring(lua,"LOG_WARNING");
    lua_pushnumber(lua,REDIS_WARNING);
    lua_settable(lua,-3);

    /* redis.sha1hex */
    /* 注册 redis.sha1hex */
    lua_pushstring(lua, "sha1hex");
    lua_pushcfunction(lua, luaRedisSha1hexCommand);
    lua_settable(lua, -3);

    /* redis.error_reply and redis.status_reply */
    /* 注册 redis.error_reply and redis.status_reply */
    lua_pushstring(lua, "error_reply");
    lua_pushcfunction(lua, luaRedisErrorReplyCommand);
    lua_settable(lua, -3);
    lua_pushstring(lua, "status_reply");
    lua_pushcfunction(lua, luaRedisStatusReplyCommand);
    lua_settable(lua, -3);

    /* Finally set the table as 'redis' global var. */
    // 将 table 设置为 redis 全局变量
    lua_setglobal(lua,"redis");

    /* Replace math.random and math.randomseed with our implementations. 
     *
     * 使用 Redis 自己的函数来替换 Lua 原来的 math.random 和 math.randomseed 实现
     *
     * 使得随机数的生成带有确定性：对于同一个 seed ，总是产生相同的随机数序列
     */
    lua_getglobal(lua,"math");

    lua_pushstring(lua,"random");
    lua_pushcfunction(lua,redis_math_random);
    lua_settable(lua,-3);

    lua_pushstring(lua,"randomseed");
    lua_pushcfunction(lua,redis_math_randomseed);
    lua_settable(lua,-3);

    lua_setglobal(lua,"math");

    /* Add a helper function that we use to sort the multi bulk output of non
     * deterministic commands, when containing 'false' elements. 
     *
     * 辅助函数，用于对带有不确定性的 multi bulk reply 进行排序
     */
    {
        char *compare_func =    "function __redis__compare_helper(a,b)\n"
                                "  if a == false then a = '' end\n"
                                "  if b == false then b = '' end\n"
                                "  return a<b\n"
                                "end\n";
        luaL_loadbuffer(lua,compare_func,strlen(compare_func),"@cmp_func_def");
        lua_pcall(lua,0,0,0);
    }

    /* Add a helper function we use for pcall error reporting.
     * Note that when the error is in the C function we want to report the
     * information about the caller, that's what makes sense from the point
     * of view of the user debugging a script. 
     *
     * 创建一个用于报告 pcall 错误的报告函数
     */
    {
        char *errh_func =       "function __redis__err__handler(err)\n"
                                "  local i = debug.getinfo(2,'nSl')\n"
                                "  if i and i.what == 'C' then\n"
                                "    i = debug.getinfo(3,'nSl')\n"
                                "  end\n"
                                "  if i then\n"
                                "    return i.source .. ':' .. i.currentline .. ': ' .. err\n"
                                "  else\n"
                                "    return err\n"
                                "  end\n"
                                "end\n";
        luaL_loadbuffer(lua,errh_func,strlen(errh_func),"@err_handler_def");
        lua_pcall(lua,0,0,0);
    }

    /* Create the (non connected) client that we use to execute Redis commands
     * inside the Lua interpreter.
     *
     * 因为 Redis 的命令只能通过客户端来执行，
     * 所以创建一个无网络链接的伪客户端来专门执行 Lua 脚本中的 Redis 命令。
     *
     * Note: there is no need to create it again when this function is called
     * by scriptingReset(). 
     *
     * 伪客户端只需要创建一次即可，因为这个函数会被 scriptingReset() 调用。
     */
    if (server.lua_client == NULL) {
        server.lua_client = createClient(-1);
        server.lua_client->flags |= REDIS_LUA_CLIENT;
    }

    /* Lua beginners ofter don't use "local", this is likely to introduce
     * subtle bugs in their code. To prevent problems we protect accesses
     * to global variables. 
     *
     * 为了避免全局变量被意外地修改，保护全局变量。
     */
    scriptingEnableGlobalsProtection(lua);

    // 将 Lua 环境赋值到服务器属性中
    server.lua = lua;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
callq 0xa0b80
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rdi
callq 0x73db0
movq -0x8(%rbp), %rdi
callq 0x73e80
leaq 0x9e6c6(%rip), %rdi     # 0x112910
xorl %eax, %eax
movl %eax, %esi
callq 0x231a0
movq %rax, %rcx
leaq 0x9f69b(%rip), %rax     # 0x1138f8
movq %rcx, 0x7f8(%rax)
movq -0x8(%rbp), %rdi
xorl %edx, %edx
movl %edx, %esi
callq 0x8cb60
movq -0x8(%rbp), %rdi
leaq 0x7741d(%rip), %rsi     # 0xeb699
callq 0x8c590
movq -0x8(%rbp), %rdi
leaq -0xa1c(%rip), %rsi      # 0x73870
xorl %edx, %edx
callq 0x8c720
movq -0x8(%rbp), %rdi
movl $0xfffffffd, %esi       # imm = 0xFFFFFFFD
callq 0x8cdc0
movq -0x8(%rbp), %rdi
leaq 0x777ff(%rip), %rsi     # 0xebaab
callq 0x8c590
movq -0x8(%rbp), %rdi
leaq -0xa2c(%rip), %rsi      # 0x73890
xorl %edx, %edx
callq 0x8c720
movq -0x8(%rbp), %rdi
movl $0xfffffffd, %esi       # imm = 0xFFFFFFFD
callq 0x8cdc0
movq -0x8(%rbp), %rdi
leaq 0x6f582(%rip), %rsi     # 0xe385e
callq 0x8c590
movq -0x8(%rbp), %rdi
leaq -0x7cc(%rip), %rsi      # 0x73b20
xorl %edx, %edx
callq 0x8c720
movq -0x8(%rbp), %rdi
movl $0xfffffffd, %esi       # imm = 0xFFFFFFFD
callq 0x8cdc0
movq -0x8(%rbp), %rdi
leaq 0x73884(%rip), %rsi     # 0xe7b90
callq 0x8c590
movq -0x8(%rbp), %rdi
xorps %xmm0, %xmm0
callq 0x8c470
movq -0x8(%rbp), %rdi
movl $0xfffffffd, %esi       # imm = 0xFFFFFFFD
callq 0x8cdc0
movq -0x8(%rbp), %rdi
leaq 0x73864(%rip), %rsi     # 0xe7b9a
callq 0x8c590
movq -0x8(%rbp), %rdi
movsd 0x69e91(%rip), %xmm0    # 0xde1d8
callq 0x8c470
movq -0x8(%rbp), %rdi
movl $0xfffffffd, %esi       # imm = 0xFFFFFFFD
callq 0x8cdc0
movq -0x8(%rbp), %rdi
leaq 0x73841(%rip), %rsi     # 0xe7ba6
callq 0x8c590
movq -0x8(%rbp), %rdi
movsd 0x7330a(%rip), %xmm0    # 0xe7680
callq 0x8c470
movq -0x8(%rbp), %rdi
movl $0xfffffffd, %esi       # imm = 0xFFFFFFFD
callq 0x8cdc0
movq -0x8(%rbp), %rdi
leaq 0x7381d(%rip), %rsi     # 0xe7bb1
callq 0x8c590
movq -0x8(%rbp), %rdi
movsd 0x732d3(%rip), %xmm0    # 0xe7678
callq 0x8c470
movq -0x8(%rbp), %rdi
movl $0xfffffffd, %esi       # imm = 0xFFFFFFFD
callq 0x8cdc0
movq -0x8(%rbp), %rdi
leaq 0x737fa(%rip), %rsi     # 0xe7bbd
callq 0x8c590
movq -0x8(%rbp), %rdi
leaq -0xb23(%rip), %rsi      # 0x738b0
xorl %edx, %edx
callq 0x8c720
movq -0x8(%rbp), %rdi
movl $0xfffffffd, %esi       # imm = 0xFFFFFFFD
callq 0x8cdc0
movq -0x8(%rbp), %rdi
leaq 0x737d2(%rip), %rsi     # 0xe7bc5
callq 0x8c590
movq -0x8(%rbp), %rdi
leaq -0x943(%rip), %rsi      # 0x73ac0
xorl %edx, %edx
callq 0x8c720
movq -0x8(%rbp), %rdi
movl $0xfffffffd, %esi       # imm = 0xFFFFFFFD
callq 0x8cdc0
movq -0x8(%rbp), %rdi
leaq 0x737ae(%rip), %rsi     # 0xe7bd1
callq 0x8c590
movq -0x8(%rbp), %rdi
leaq -0x943(%rip), %rsi      # 0x73af0
xorl %edx, %edx
callq 0x8c720
movq -0x8(%rbp), %rdi
movl $0xfffffffd, %esi       # imm = 0xFFFFFFFD
callq 0x8cdc0
movq -0x8(%rbp), %rdi
movl $0xffffd8ee, %esi       # imm = 0xFFFFD8EE
leaq 0x6a921(%rip), %rdx     # 0xded79
callq 0x8ce20
movq -0x8(%rbp), %rdi
movl $0xffffd8ee, %esi       # imm = 0xFFFFD8EE
leaq 0x734f7(%rip), %rdx     # 0xe7964
callq 0x8c9d0
movq -0x8(%rbp), %rdi
leaq 0x6f60d(%rip), %rsi     # 0xe3a8a
callq 0x8c590
movq -0x8(%rbp), %rdi
leaq 0x163(%rip), %rsi       # 0x745f0
xorl %edx, %edx
callq 0x8c720
movq -0x8(%rbp), %rdi
movl $0xfffffffd, %esi       # imm = 0xFFFFFFFD
callq 0x8cdc0
movq -0x8(%rbp), %rdi
leaq 0x73731(%rip), %rsi     # 0xe7bde
callq 0x8c590
movq -0x8(%rbp), %rdi
leaq 0x2f3(%rip), %rsi       # 0x747b0
xorl %edx, %edx
callq 0x8c720
movq -0x8(%rbp), %rdi
movl $0xfffffffd, %esi       # imm = 0xFFFFFFFD
callq 0x8cdc0
movq -0x8(%rbp), %rdi
movl $0xffffd8ee, %esi       # imm = 0xFFFFD8EE
leaq 0x73482(%rip), %rdx     # 0xe7964
callq 0x8ce20
leaq 0x736fb(%rip), %rax     # 0xe7be9
movq %rax, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rdi
callq 0x1f4d0
movq -0x38(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq %rax, %rdx
leaq 0x73744(%rip), %rcx     # 0xe7c61
callq 0xa0a80
movq -0x8(%rbp), %rdi
xorl %ecx, %ecx
movl %ecx, %esi
movl %ecx, %edx
callq 0x8d340
leaq 0x73737(%rip), %rax     # 0xe7c6f
movq %rax, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rdi
callq 0x1f4d0
movq -0x28(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq %rax, %rdx
leaq 0x737fa(%rip), %rcx     # 0xe7d61
callq 0xa0a80
movq -0x8(%rbp), %rdi
xorl %ecx, %ecx
movl %ecx, %esi
movl %ecx, %edx
callq 0x8d340
leaq 0x9f376(%rip), %rax     # 0x1138f8
cmpq $0x0, 0x7e8(%rax)
jne 0x745c7
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x34950
movq %rax, %rcx
leaq 0x9f358(%rip), %rax     # 0x1138f8
movq %rcx, 0x7e8(%rax)
leaq 0x9f34a(%rip), %rax     # 0x1138f8
movq 0x7e8(%rax), %rax
movl 0x90(%rax), %ecx
orl $0x100, %ecx            # imm = 0x100
movl %ecx, 0x90(%rax)
movq -0x8(%rbp), %rdi
callq 0x73eb0
movq -0x8(%rbp), %rcx
leaq 0x9f31d(%rip), %rax     # 0x1138f8
movq %rcx, 0x7e0(%rax)
addq $0x40, %rsp
popq %rbp
retq
nopl (%rax,%rax)