// File: /workspace/github_c_makefile_star2_O3/gplessis[P]dotdeb-redis/src/scripting.c
// Function: evalGenericCommand
void evalGenericCommand(client *c, int evalsha) {
    lua_State *lua = server.lua;
    char funcname[43];
    long long numkeys;
    int delhook = 0, err;

    /* When we replicate whole scripts, we want the same PRNG sequence at
     * every call so that our PRNG is not affected by external state. */
    redisSrand48(0);

    /* We set this flag to zero to remember that so far no random command
     * was called. This way we can allow the user to call commands like
     * SRANDMEMBER or RANDOMKEY from Lua scripts as far as no write command
     * is called (otherwise the replication and AOF would end with non
     * deterministic sequences).
     *
     * Thanks to this flag we'll raise an error every time a write command
     * is called after a random command was used. */
    server.lua_random_dirty = 0;
    server.lua_write_dirty = 0;
    server.lua_replicate_commands = server.lua_always_replicate_commands;
    server.lua_multi_emitted = 0;
    server.lua_repl = PROPAGATE_AOF|PROPAGATE_REPL;

    /* Get the number of arguments that are keys */
    if (getLongLongFromObjectOrReply(c,c->argv[2],&numkeys,NULL) != C_OK)
        return;
    if (numkeys > (c->argc - 3)) {
        addReplyError(c,"Number of keys can't be greater than number of args");
        return;
    } else if (numkeys < 0) {
        addReplyError(c,"Number of keys can't be negative");
        return;
    }

    /* We obtain the script SHA1, then check if this function is already
     * defined into the Lua state */
    funcname[0] = 'f';
    funcname[1] = '_';
    if (!evalsha) {
        /* Hash the code if this is an EVAL call */
        sha1hex(funcname+2,c->argv[1]->ptr,sdslen(c->argv[1]->ptr));
    } else {
        /* We already have the SHA if it is a EVALSHA */
        int j;
        char *sha = c->argv[1]->ptr;

        /* Convert to lowercase. We don't use tolower since the function
         * managed to always show up in the profiler output consuming
         * a non trivial amount of time. */
        for (j = 0; j < 40; j++)
            funcname[j+2] = (sha[j] >= 'A' && sha[j] <= 'Z') ?
                sha[j]+('a'-'A') : sha[j];
        funcname[42] = '\0';
    }

    /* Push the pcall error handler function on the stack. */
    lua_getglobal(lua, "__redis__err__handler");

    /* Try to lookup the Lua function */
    lua_getglobal(lua, funcname);
    if (lua_isnil(lua,-1)) {
        lua_pop(lua,1); /* remove the nil from the stack */
        /* Function not defined... let's define it if we have the
         * body of the function. If this is an EVALSHA call we can just
         * return an error. */
        if (evalsha) {
            lua_pop(lua,1); /* remove the error handler from the stack. */
            addReply(c, shared.noscripterr);
            return;
        }
        if (luaCreateFunction(c,lua,funcname,c->argv[1]) == C_ERR) {
            lua_pop(lua,1); /* remove the error handler from the stack. */
            /* The error is sent to the client by luaCreateFunction()
             * itself when it returns C_ERR. */
            return;
        }
        /* Now the following is guaranteed to return non nil */
        lua_getglobal(lua, funcname);
        serverAssert(!lua_isnil(lua,-1));
    }

    /* Populate the argv and keys table accordingly to the arguments that
     * EVAL received. */
    luaSetGlobalArray(lua,"KEYS",c->argv+3,numkeys);
    luaSetGlobalArray(lua,"ARGV",c->argv+3+numkeys,c->argc-3-numkeys);

    /* Select the right DB in the context of the Lua client */
    selectDb(server.lua_client,c->db->id);

    /* Set a hook in order to be able to stop the script execution if it
     * is running for too much time.
     * We set the hook only if the time limit is enabled as the hook will
     * make the Lua script execution slower.
     *
     * If we are debugging, we set instead a "line" hook so that the
     * debugger is call-back at every line executed by the script. */
    server.lua_caller = c;
    server.lua_time_start = mstime();
    server.lua_kill = 0;
    if (server.lua_time_limit > 0 && server.masterhost == NULL &&
        ldb.active == 0)
    {
        lua_sethook(lua,luaMaskCountHook,LUA_MASKCOUNT,100000);
        delhook = 1;
    } else if (ldb.active) {
        lua_sethook(server.lua,luaLdbLineHook,LUA_MASKLINE|LUA_MASKCOUNT,100000);
        delhook = 1;
    }

    /* At this point whether this script was never seen before or if it was
     * already defined, we can call it. We have zero arguments and expect
     * a single return value. */
    err = lua_pcall(lua,0,1,-2);

    /* Perform some cleanup that we need to do both on error and success. */
    if (delhook) lua_sethook(lua,NULL,0,0); /* Disable hook */
    if (server.lua_timedout) {
        server.lua_timedout = 0;
        /* Restore the readable handler that was unregistered when the
         * script timeout was detected. */
        aeCreateFileEvent(server.el,c->fd,AE_READABLE,
                          readQueryFromClient,c);
    }
    server.lua_caller = NULL;

    /* Call the Lua garbage collector from time to time to avoid a
     * full cycle performed by Lua, which adds too latency.
     *
     * The call is performed every LUA_GC_CYCLE_PERIOD executed commands
     * (and for LUA_GC_CYCLE_PERIOD collection steps) because calling it
     * for every command uses too much CPU. */
    #define LUA_GC_CYCLE_PERIOD 50
    {
        static long gc_count = 0;

        gc_count++;
        if (gc_count == LUA_GC_CYCLE_PERIOD) {
            lua_gc(lua,LUA_GCSTEP,LUA_GC_CYCLE_PERIOD);
            gc_count = 0;
        }
    }

    if (err) {
        addReplyErrorFormat(c,"Error running script (call to %s): %s\n",
            funcname, lua_tostring(lua,-1));
        lua_pop(lua,2); /* Consume the Lua reply and remove error handler. */
    } else {
        /* On success convert the Lua return value into Redis protocol, and
         * send it to * the client. */
        luaReplyToRedisReply(c,lua); /* Convert and consume the reply. */
        lua_pop(lua,1); /* Remove the error handler. */
    }

    /* If we are using single commands replication, emit EXEC if there
     * was at least a write. */
    if (server.lua_replicate_commands) {
        preventCommandPropagation(c);
        if (server.lua_multi_emitted) {
            robj *propargv[1];
            propargv[0] = createStringObject("EXEC",4);
            alsoPropagate(server.execCommand,c->db->id,propargv,1,
                PROPAGATE_AOF|PROPAGATE_REPL);
            decrRefCount(propargv[0]);
        }
    }

    /* EVALSHA should be propagated to Slave and AOF file as full EVAL, unless
     * we are sure that the script was already in the context of all the
     * attached slaves *and* the current AOF file if enabled.
     *
     * To do so we use a cache of SHA1s of scripts that we already propagated
     * as full EVAL, that's called the Replication Script Cache.
     *
     * For repliation, everytime a new slave attaches to the master, we need to
     * flush our cache of scripts that can be replicated as EVALSHA, while
     * for AOF we need to do so every time we rewrite the AOF file. */
    if (evalsha && !server.lua_replicate_commands) {
        if (!replicationScriptCacheExists(c->argv[1]->ptr)) {
            /* This script is not in our script cache, replicate it as
             * EVAL, then add it into the script cache, as from now on
             * slaves and AOF know about it. */
            robj *script = dictFetchValue(server.lua_scripts,c->argv[1]->ptr);

            replicationScriptCacheAdd(c->argv[1]->ptr);
            serverAssertWithInfo(c,NULL,script != NULL);
            rewriteClientCommandArgument(c,0,
                resetRefCount(createStringObject("EVAL",4)));
            rewriteClientCommandArgument(c,1,script);
            forceCommandPropagation(c,PROPAGATE_REPL|PROPAGATE_AOF);
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x50, %rsp
movl %esi, %ebp
movq %rdi, %rbx
leaq 0x9210f(%rip), %r12     # 0x1018a8
movq 0x9c8(%r12), %r14
xorl %edi, %edi
callq 0x72dcf
movq $0x0, 0x9f8(%r12)
movl 0xa14(%r12), %eax
movl %eax, 0xa00(%r12)
movabsq $0x300000000, %rax      # imm = 0x300000000
movq %rax, 0xa04(%r12)
movq 0x40(%rbx), %rax
movq 0x10(%rax), %rsi
leaq 0x8(%rsp), %rdx
movq %rbx, %rdi
xorl %ecx, %ecx
callq 0x416bb
testl %eax, %eax
jne 0x6f863
movq 0x8(%rsp), %rax
movslq 0x38(%rbx), %rcx
addq $-0x3, %rcx
cmpq %rcx, %rax
jle 0x6f80c
leaq 0x5ab6b(%rip), %rsi     # 0xca375
jmp 0x6f85b
testq %rax, %rax
js 0x6f854
movw $0x5f66, 0x10(%rsp)     # imm = 0x5F66
testl %ebp, %ebp
je 0x6f870
movq 0x40(%rbx), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %rax
xorl %ecx, %ecx
movzbl (%rax,%rcx), %edx
leal -0x41(%rdx), %esi
leal 0x20(%rdx), %edi
cmpb $0x1a, %sil
movzbl %dil, %esi
cmovael %edx, %esi
movb %sil, 0x12(%rsp,%rcx)
incq %rcx
cmpq $0x28, %rcx
jne 0x6f82a
movb $0x0, 0x3a(%rsp)
jmp 0x6f8c2
leaq 0x5ab4e(%rip), %rsi     # 0xca3a9
movq %rbx, %rdi
callq 0x3cc06
addq $0x50, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
leaq 0x12(%rsp), %rdi
movq 0x40(%rbx), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %rsi
movzbl -0x1(%rsi), %edx
movl %edx, %eax
andl $0x7, %eax
cmpl $0x4, %eax
ja 0x6f8bb
leaq 0x59eea(%rip), %rcx     # 0xc9780
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
shrl $0x3, %edx
jmp 0x6f8bd
movq -0x11(%rsi), %rdx
jmp 0x6f8bd
movzwl -0x5(%rsi), %edx
jmp 0x6f8bd
movl -0x9(%rsi), %edx
jmp 0x6f8bd
movzbl -0x3(%rsi), %edx
jmp 0x6f8bd
xorl %edx, %edx
callq 0x6d614
leaq 0x5ab01(%rip), %rdx     # 0xca3ca
movq %r14, %rdi
movl $0xffffd8ee, %esi       # imm = 0xFFFFD8EE
callq 0x8675f
leaq 0x10(%rsp), %rdx
movq %r14, %rdi
movl $0xffffd8ee, %esi       # imm = 0xFFFFD8EE
callq 0x8675f
movq %r14, %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x860ba
testl %eax, %eax
je 0x6f9b6
movq 0x40(%rbx), %rdx
addq $0x18, %rdx
movl 0x8(%rsp), %ecx
leaq 0x5aae3(%rip), %rsi     # 0xca3f3
movq %r14, %rdi
callq 0x6f405
movq 0x40(%rbx), %rax
movq 0x8(%rsp), %rsi
leaq (%rax,%rsi,8), %rdx
addq $0x18, %rdx
movl 0x38(%rbx), %ecx
subl %esi, %ecx
addl $-0x3, %ecx
leaq 0x5aac0(%rip), %rsi     # 0xca3f8
movq %r14, %rdi
callq 0x6f405
movq 0x9d0(%r12), %rdi
movq 0x10(%rbx), %rax
movl 0x30(%rax), %esi
callq 0x420b7
movq %rbx, 0x9d8(%r12)
callq 0x2ffce
movq %rax, 0x9f0(%r12)
movl $0x0, 0xa10(%r12)
cmpq $0x0, 0x9e8(%r12)
setg %cl
cmpq $0x0, 0x828(%r12)
sete %dl
movl 0xa68d1(%rip), %eax     # 0x116264
testl %eax, %eax
sete %sil
andb %dl, %sil
andb %cl, %sil
cmpb $0x1, %sil
jne 0x6f9f3
leaq -0x2f1(%rip), %rsi      # 0x6f6bb
movq %r14, %rdi
movl $0x8, %edx
jmp 0x6fa0f
movq %r14, %rdi
movl $0xfffffffe, %esi       # imm = 0xFFFFFFFE
callq 0x85d59
testl %ebp, %ebp
je 0x6fc0c
movq %r14, %rdi
movl $0xfffffffe, %esi       # imm = 0xFFFFFFFE
callq 0x85d59
leaq 0x92931(%rip), %rax     # 0x102310
movq 0x98(%rax), %rsi
movq %rbx, %rdi
callq 0x3c854
jmp 0x6f863
testl %eax, %eax
je 0x6fc6a
movq 0x9c8(%r12), %rdi
leaq 0x2b6(%rip), %rsi       # 0x6fcc0
movl $0xc, %edx
movl $0x186a0, %ecx          # imm = 0x186A0
callq 0x8708c
movq %r14, %rdi
xorl %esi, %esi
movl $0x1, %edx
movl $0xfffffffe, %ecx       # imm = 0xFFFFFFFE
callq 0x86bad
movl %eax, %r15d
movq %r14, %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x8708c
cmpl $0x0, 0xa0c(%r12)
je 0x6fa71
movl $0x0, 0xa0c(%r12)
movq 0x40(%r12), %rdi
movl 0x8(%rbx), %esi
leaq -0x33a9b(%rip), %rcx    # 0x3bfc9
movl $0x1, %edx
movq %rbx, %r8
callq 0x2ce46
movq $0x0, 0x9d8(%r12)
movq 0xa6b54(%rip), %rax     # 0x1165d8
incq %rax
movq %rax, 0xa6b4a(%rip)     # 0x1165d8
cmpq $0x32, %rax
jne 0x6fab1
movq %r14, %rdi
movl $0x5, %esi
movl $0x32, %edx
callq 0x86d60
movq $0x0, 0xa6b27(%rip) # 0x1165d8
testl %r15d, %r15d
je 0x6fae5
movq %r14, %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
xorl %edx, %edx
callq 0x862f8
leaq 0x5a931(%rip), %rsi     # 0xca3fd
leaq 0x10(%rsp), %rdx
movq %rbx, %rdi
movq %rax, %rcx
xorl %eax, %eax
callq 0x3cc2d
movl $0xfffffffd, %esi       # imm = 0xFFFFFFFD
jmp 0x6faf5
movq %rbx, %rdi
movq %r14, %rsi
callq 0x6db15
movl $0xfffffffe, %esi       # imm = 0xFFFFFFFE
movq %r14, %rdi
callq 0x85d59
cmpl $0x0, 0xa00(%r12)
je 0x6fb5e
movq %rbx, %rdi
callq 0x32ea2
cmpl $0x0, 0xa04(%r12)
je 0x6fb5e
leaq 0x5a902(%rip), %rdi     # 0xca424
movl $0x4, %esi
callq 0x40744
leaq 0x48(%rsp), %r14
movq %rax, (%r14)
movq 0x370(%r12), %rdi
movq 0x10(%rbx), %rax
movl 0x30(%rax), %esi
movq %r14, %rdx
movl $0x1, %ecx
movl $0x3, %r8d
callq 0x32dcf
movq (%r14), %rdi
callq 0x40c8f
testl %ebp, %ebp
je 0x6f863
cmpl $0x0, 0xa00(%r12)
jne 0x6f863
movq 0x40(%rbx), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %rdi
callq 0x4729d
testl %eax, %eax
jne 0x6f863
movq 0x9e0(%r12), %rdi
movq 0x40(%rbx), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %rsi
callq 0x2ef19
movq %rax, %r14
movq 0x40(%rbx), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %rdi
callq 0x471e4
testq %r14, %r14
je 0x6fc98
leaq 0x5a86d(%rip), %rdi     # 0xca438
movl $0x4, %esi
callq 0x40744
movq %rax, %rdi
callq 0x40d3c
movq %rbx, %rdi
xorl %esi, %esi
movq %rax, %rdx
callq 0x3f7dc
movq %rbx, %rdi
movl $0x1, %esi
movq %r14, %rdx
callq 0x3f7dc
movq %rbx, %rdi
movl $0x3, %esi
callq 0x32e87
jmp 0x6f863
movq 0x40(%rbx), %rax
movq 0x8(%rax), %rcx
leaq 0x10(%rsp), %rdx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x6f4b1
cmpl $-0x1, %eax
je 0x6fc86
leaq 0x10(%rsp), %rdx
movq %r14, %rdi
movl $0xffffd8ee, %esi       # imm = 0xFFFFD8EE
callq 0x8675f
movq %r14, %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x860ba
testl %eax, %eax
jne 0x6f8fd
leaq 0x5a789(%rip), %rdi     # 0xca3e0
leaq 0x5a631(%rip), %rsi     # 0xca28f
movl $0x505, %edx            # imm = 0x505
callq 0x61908
jmp 0x6fcb6
movq %r14, %rdi
xorl %esi, %esi
movl $0x1, %edx
movl $0xfffffffe, %ecx       # imm = 0xFFFFFFFE
callq 0x86bad
movl %eax, %r15d
jmp 0x6fa3e
movq %r14, %rdi
movl $0xfffffffe, %esi       # imm = 0xFFFFFFFE
callq 0x85d59
jmp 0x6f863
leaq 0x5a78a(%rip), %rdx     # 0xca429
leaq 0x5a5e9(%rip), %rcx     # 0xca28f
movq %rbx, %rdi
xorl %esi, %esi
movl $0x56f, %r8d            # imm = 0x56F
callq 0x627c3
movl $0x1, %edi
callq 0x263c0