Run the program, track the code, and see what happened here?
Find the main function in Lua. C and follow it in.
First, open several databases to determine whether the program has parameters during execution. If there are no parameters, that is, the command input is received from the command line. If there are parameters, each parameter is executed as a script file. The second method is to write the script program to a file and run it with the Lua interpreter. You can also test a short program or verify the usage of a database using command line Input. However, if the script is a little longer, it is easy to introduce the problem: branch, complete semantics must be ensured by yourself. Therefore, writing scripts to files can save a lot of unnecessary problems.
Let's take a look at what happened during the database opening process?
First, we can see that the first call to open the database is iolib_open (); to its definition. We can see that there are seven lua_register calls.
(Math is 14, STR is 5, and the system comes with 7
This is a total of 33 system functions. Are you familiar with this number? Yes, it's the one that prints the bytecode .)
We can see that lua_register is a macro defined in Lua. h:
#define lua_register(n,f) (lua_pushcfunction(f), lua_storeglobal(n))
Let's look at lua_pushcfunction and lua_storeglobal respectively,
Opcode. c file
/*** Push an object (tag=cfunction) to stack. Return 0 on success or 1 on error.*/int lua_pushcfunction (lua_CFunction fn){ if ((top-stack) >= MAXSTACK-1) { lua_error ("stack overflow"); return 1; } tag(top) = T_CFUNCTION; fvalue(top++) = fn; return 0;}
The lua_pushcfunction parameter is a function pointer. At the end of the call, the object type at the top of the stack is set to t_cfunction, and the value is set to the actual parameter of the passed function pointer. Here is io_readfrom.
The stack mentioned here is a bond between Lua and C calls each other. As a method implemented by C code, it is converted into an object of the t_cfunction type, this type can be identified by the Lua environment, so we will associate it with the global symbols of the symbol table.
Opcode. c file
/*** Store top of the stack at a global variable array field. ** Return 1 on error, 0 on success.*/int lua_storeglobal (char *name){ int n = lua_findsymbol (name); if (n < 0) return 1; if (tag(top-1) == T_MARK) return 1; s_object(n) = *(--top); return 0;}
Table. c file
/*** Given a name, search it at symbol table and return its index. If not** found, allocate at end of table, checking oveflow and return its index.** On error, return -1.*/int lua_findsymbol (char *s){ struct List *l, *p; for (p=NULL, l=searchlist; l!=NULL; p=l, l=l->next) if (streq(s,l->s->name)) { if (p!=NULL) { p->next = l->next; l->next = searchlist; searchlist = l; } return (l->s-lua_table); } if (lua_ntable >= MAXSYMBOL-1) { lua_error ("symbol table overflow"); return -1; } s_name(lua_ntable) = strdup(s); if (s_name(lua_ntable) == NULL) { lua_error ("not enough memory"); return -1; } s_tag(lua_ntable) = T_NIL; p = malloc(sizeof(*p)); p->s = lua_table+lua_ntable; p->next = searchlist; searchlist = p; return lua_ntable++;}
Lua_storeglobal stores global variables in the symbol table. A parameter is a string that is the name of a global variable. Set the symbol value to the object at the top of the current stack, which is the t_cfunction type object at the top of the stack as mentioned above. Lua_findsymbol searches for the string specified by the parameter in the symbol table. If it is found, return its index in the symbol table. Otherwise, create a new symbol at the end of the table and return its index in the table. Set this symbol to the header of the searchlist.
Let's take a look at the definition of the symbol:
typedef struct{ char *name; Object object;} Symbol;
It includes a symbolic name and a corresponding object type.
The symbol table initially has seven values, as shown below (in the Table. c file ):
static Symbol tablebuffer[MAXSYMBOL] = { {"type",{T_CFUNCTION,{lua_type}}}, {"tonumber",{T_CFUNCTION,{lua_obj2number}}}, {"next",{T_CFUNCTION,{lua_next}}}, {"nextvar",{T_CFUNCTION,{lua_nextvar}}}, {"print",{T_CFUNCTION,{lua_print}}}, {"dofile",{T_CFUNCTION,{lua_internaldofile}}}, {"dostring",{T_CFUNCTION,{lua_internaldostring}}} };Symbol *lua_table=tablebuffer;Word lua_ntable=7;struct List{ Symbol *s; struct List *next;};static struct List o6={ tablebuffer+6, 0};static struct List o5={ tablebuffer+5, &o6 };static struct List o4={ tablebuffer+4, &o5 };static struct List o3={ tablebuffer+3, &o4 };static struct List o2={ tablebuffer+2, &o3 };static struct List o1={ tablebuffer+1, &o2 };static struct List o0={ tablebuffer+0, &o1 };static struct List *searchlist=&o0;
Searchlist is a linked list. It can be seen from the name that it is used to search for symbols. It connects the items in the symbol table above and is only used in lua_findsymbol.
Call lua_findsymbol each time and place the searched result in the head of the linked list.
After the lua_findsymbol ends, the symbol name is already in the symbol table. If it is an added symbol, the corresponding object is not associated with the symbol name. This is what lua_storeglobal will do next.
After lua_storeglobal returns lua_findsymbol, it uses the returned index to find the corresponding symbol and set its obejct field.
At this point, the method registers lua_register ("readfrom", io_readfrom); the call is complete.
If (Tag (top-1) = t_mark) return 1; indicates that there is no corresponding object on the stack, and an error occurs.
Registration of other library functions is the same as registration.
iolib_open (); strlib_open (); mathlib_open ();
After the call of these open databases is completed, all system functions are registered.
Lua1.1 environment preparation