This first edition was written for Lua 5.0. While still largely relevant for later versions, there are some differences.
The fourth edition targets Lua 5.3 and is available at Amazon and other bookstores.
By buying the book, you also help to support the Lua project.


24.2.3 – Other Stack Operations

Besides the above functions, which interchange values between C and the stack, the API offers also the following operations for generic stack manipulation:

    int   lua_gettop (lua_State *L);
    void  lua_settop (lua_State *L, int index);
    void  lua_pushvalue (lua_State *L, int index);
    void  lua_remove (lua_State *L, int index);
    void  lua_insert (lua_State *L, int index);
    void  lua_replace (lua_State *L, int index);
The lua_gettop function returns the number of elements in the stack, which is also the index of the top element. Notice that a negative index -x is equivalent to the positive index gettop - x + 1.

lua_settop sets the top (that is, the number of elements in the stack) to a specific value. If the previous top was higher than the new one, the top values are discarded. Otherwise, the function pushes nils on the stack to get the given size. As a particular case, lua_settop(L, 0) empties the stack. You can also use negative indices with lua_settop; that will set the top element to the given index. Using this facility, the API offers the following macro, which pops n elements from the stack:

    #define lua_pop(L,n)  lua_settop(L, -(n)-1)

The lua_pushvalue function pushes on the top of the stack a copy of the element at the given index; lua_remove removes the element at the given index, shifting down all elements on top of that position to fill in the gap; lua_insert moves the top element into the given position, shifting up all elements on top of that position to open space; finally, lua_replace pops a value from the top and sets it as the value of the given index, without moving anything. Notice that the following operations have no effect on the stack:

    lua_settop(L, -1);  /* set top to its current value */
    lua_insert(L, -1);  /* move top element to the top */

To illustrate the use of those functions, here is a useful helper function that dumps the entire content of the stack:

    static void stackDump (lua_State *L) {
      int i;
      int top = lua_gettop(L);
      for (i = 1; i <= top; i++) {  /* repeat for each level */
        int t = lua_type(L, i);
        switch (t) {
    
          case LUA_TSTRING:  /* strings */
            printf("`%s'", lua_tostring(L, i));
            break;
    
          case LUA_TBOOLEAN:  /* booleans */
            printf(lua_toboolean(L, i) ? "true" : "false");
            break;
    
          case LUA_TNUMBER:  /* numbers */
            printf("%g", lua_tonumber(L, i));
            break;
    
          default:  /* other values */
            printf("%s", lua_typename(L, t));
            break;
    
        }
        printf("  ");  /* put a separator */
      }
      printf("\n");  /* end the listing */
    }
This function traverses the stack from bottom to top, printing each element according to its type. It prints strings between quotes; for numbers it uses a `%g´ format; for other values (tables, functions, etc.) it prints only their types (lua_typename converts a type code to a type name).

The following program uses stackDump to further illustrate the manipulation of the API stack:

    #include <stdio.h>
    #include <lua.h>
    
    static void stackDump (lua_State *L) {
      ...
    }
    
    int main (void) {
      lua_State *L = lua_open();
      lua_pushboolean(L, 1); lua_pushnumber(L, 10);
      lua_pushnil(L); lua_pushstring(L, "hello");
      stackDump(L);
                       /* true  10  nil  `hello'  */
    
      lua_pushvalue(L, -4); stackDump(L);
                       /* true  10  nil  `hello'  true  */
    
      lua_replace(L, 3); stackDump(L);
                       /* true  10  true  `hello'  */
    
      lua_settop(L, 6); stackDump(L);
                       /* true  10  true  `hello'  nil  nil  */
    
      lua_remove(L, -3); stackDump(L);
                       /* true  10  true  nil  nil  */
    
      lua_settop(L, -5); stackDump(L);
                       /* true  */
    
      lua_close(L);
      return 0;
    }