13 |
14 |
15 | #include "llimits.h"
16 | #include "lua.h"
17 |
18 |
19 | /* tags for values visible from Lua */
20 | #define LAST_TAG LUA_TTHREAD
21 |
22 | #define NUM_TAGS (LAST_TAG+1)
23 |
24 |
25 | /*
26 | ** Extra tags for non-values
27 | */
28 | #define LUA_TPROTO (LAST_TAG+1)
29 | #define LUA_TUPVAL (LAST_TAG+2)
30 | #define LUA_TDEADKEY (LAST_TAG+3)
31 |
32 |
33 | /*
34 | ** Union of all collectable objects
35 | */
36 | typedef union GCObject GCObject;
37 |
38 |
39 | /*
40 | ** Common Header for all collectable objects (in macro form, to be
41 | ** included in other objects)
42 | */
43 | #define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
44 |
45 |
46 | /*
47 | ** Common header in struct form
48 | */
49 | typedef struct GCheader {
50 | CommonHeader;
51 | } GCheader;
52 |
53 |
54 |
55 |
56 | /*
57 | ** Union of all Lua values
58 | */
59 | typedef union {
60 | GCObject *gc;
61 | void *p;
62 | lua_Number n;
63 | int b;
64 | } Value;
65 |
66 |
67 | /*
68 | ** Tagged Values
69 | */
70 |
71 | #define TValuefields Value value; int tt
72 |
73 | typedef struct lua_TValue {
74 | TValuefields;
75 | } TValue;
76 |
77 |
78 | /* Macros to test type */
79 | #define ttisnil(o) (ttype(o) == LUA_TNIL)
80 | #define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
81 | #define ttisstring(o) (ttype(o) == LUA_TSTRING)
82 | #define ttistable(o) (ttype(o) == LUA_TTABLE)
83 | #define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
84 | #define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
85 | #define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA)
86 | #define ttisthread(o) (ttype(o) == LUA_TTHREAD)
87 | #define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
88 |
89 | /* Macros to access values */
90 | #define ttype(o) ((o)->tt)
91 | #define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
92 | #define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
93 | #define nvalue(o) check_exp(ttisnumber(o), (o)->value.n)
94 | #define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
95 | #define tsvalue(o) (&rawtsvalue(o)->tsv)
96 | #define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u)
97 | #define uvalue(o) (&rawuvalue(o)->uv)
98 | #define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl)
99 | #define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h)
100 | #define bvalue(o) check_exp(ttisboolean(o), (o)->value.b)
101 | #define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th)
102 |
103 | #define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
104 |
105 | /*
106 | ** for internal debug only
107 | */
108 | #define checkconsistency(obj) \
109 | lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
110 |
111 | #define checkliveness(g,obj) \
112 | lua_assert(!iscollectable(obj) || \
113 | ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))
114 |
115 |
116 | /* Macros to set values */
117 | #define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
118 |
119 | #define setnvalue(obj,x) \
120 | { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }
121 |
122 | #define setpvalue(obj,x) \
123 | { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }
124 |
125 | #define setbvalue(obj,x) \
126 | { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; }
127 |
128 | #define setsvalue(L,obj,x) \
129 | { TValue *i_o=(obj); \
130 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \
131 | checkliveness(G(L),i_o); }
132 |
133 | #define setuvalue(L,obj,x) \
134 | { TValue *i_o=(obj); \
135 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \
136 | checkliveness(G(L),i_o); }
137 |
138 | #define setthvalue(L,obj,x) \
139 | { TValue *i_o=(obj); \
140 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \
141 | checkliveness(G(L),i_o); }
142 |
143 | #define setclvalue(L,obj,x) \
144 | { TValue *i_o=(obj); \
145 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \
146 | checkliveness(G(L),i_o); }
147 |
148 | #define sethvalue(L,obj,x) \
149 | { TValue *i_o=(obj); \
150 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \
151 | checkliveness(G(L),i_o); }
152 |
153 | #define setptvalue(L,obj,x) \
154 | { TValue *i_o=(obj); \
155 | i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \
156 | checkliveness(G(L),i_o); }
157 |
158 |
159 |
160 |
161 | #define setobj(L,obj1,obj2) \
162 | { const TValue *o2=(obj2); TValue *o1=(obj1); \
163 | o1->value = o2->value; o1->tt=o2->tt; \
164 | checkliveness(G(L),o1); }
165 |
166 |
167 | /*
168 | ** different types of sets, according to destination
169 | */
170 |
171 | /* from stack to (same) stack */
172 | #define setobjs2s setobj
173 | /* to stack (not from same stack) */
174 | #define setobj2s setobj
175 | #define setsvalue2s setsvalue
176 | #define sethvalue2s sethvalue
177 | #define setptvalue2s setptvalue
178 | /* from table to same table */
179 | #define setobjt2t setobj
180 | /* to table */
181 | #define setobj2t setobj
182 | /* to new object */
183 | #define setobj2n setobj
184 | #define setsvalue2n setsvalue
185 |
186 | #define setttype(obj, tt) (ttype(obj) = (tt))
187 |
188 | // 只有这些类型的数据 才是可回收的数据
189 | #define iscollectable(o) (ttype(o) >= LUA_TSTRING)
190 |
191 |
192 |
193 | typedef TValue *StkId; /* index to stack elements */
194 |
195 |
196 | /*
197 | ** String headers for string table
198 | */
199 | typedef union TString {
200 | L_Umaxalign dummy; /* ensures maximum alignment for strings */
201 | struct {
202 | CommonHeader;
203 | lu_byte reserved;
204 | unsigned int hash;
205 | size_t len;
206 | } tsv;
207 | } TString;
208 |
209 |
210 | #define getstr(ts) cast(const char *, (ts) + 1)
211 | #define svalue(o) getstr(rawtsvalue(o))
212 |
213 |
214 | // 这里为什么需要使用union类型?
215 | typedef union Udata {
216 | L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
217 | struct {
218 | CommonHeader;
219 | struct Table *metatable;
220 | struct Table *env;
221 | size_t len;
222 | } uv;
223 | } Udata;
224 |
225 |
226 |
227 |
228 | /*
229 | ** Function Prototypes
230 | */
231 | // 存放函数原型的数据结构
232 | typedef struct Proto {
233 | CommonHeader;
234 | TValue *k; /* constants used by the function */
235 | // 存放函数体的opcode
236 | Instruction *code;
237 | // 在这个函数中定义的函数
238 | struct Proto **p; /* functions defined inside the function */
239 | int *lineinfo; /* map from opcodes to source lines */
240 | // 存放局部变量的数组
241 | struct LocVar *locvars; /* information about local variables */
242 | TString **upvalues; /* upvalue names */
243 | TString *source;
244 | int sizeupvalues;
245 | int sizek; /* size of `k' */
246 | int sizecode;
247 | int sizelineinfo;
248 | int sizep; /* size of `p' */
249 | int sizelocvars;
250 | int linedefined;
251 | int lastlinedefined;
252 | GCObject *gclist;
253 | lu_byte nups; /* number of upvalues */
254 | lu_byte numparams;
255 | lu_byte is_vararg;
256 | lu_byte maxstacksize;
257 | } Proto;
258 |
259 |
260 | /* masks for new-style vararg */
261 | #define VARARG_HASARG 1
262 | #define VARARG_ISVARARG 2
263 | #define VARARG_NEEDSARG 4
264 |
265 | // 存放局部变量的结构体
266 | typedef struct LocVar {
267 | TString *varname;
268 | int startpc; /* first point where variable is active */
269 | int endpc; /* first point where variable is dead */
270 | } LocVar;
271 |
272 |
273 |
274 | /*
275 | ** Upvalues
276 | */
277 |
278 | typedef struct UpVal {
279 | CommonHeader;
280 | TValue *v; /* points to stack or to its own value */
281 | union {
282 | // 当这个upval被close时,保存upval的值,后面可能还会被引用到
283 | TValue value; /* the value (when closed) */
284 | // 当这个upval还在open状态时,以下链表串连在openupval链表中
285 | struct { /* double linked list (when open) */
286 | struct UpVal *prev;
287 | struct UpVal *next;
288 | } l;
289 | } u;
290 | } UpVal;
291 |
292 |
293 | /*
294 | ** Closures
295 | */
296 |
297 | #define ClosureHeader \
298 | CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \
299 | struct Table *env
300 |
301 | typedef struct CClosure {
302 | ClosureHeader;
303 | lua_CFunction f;
304 | TValue upvalue[1];
305 | } CClosure;
306 |
307 |
308 | typedef struct LClosure {
309 | ClosureHeader;
310 | struct Proto *p;
311 | UpVal *upvals[1];
312 | } LClosure;
313 |
314 |
315 | typedef union Closure {
316 | CClosure c;
317 | LClosure l;
318 | } Closure;
319 |
320 |
321 | #define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC)
322 | #define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC)
323 |
324 |
325 | /*
326 | ** Tables
327 | */
328 |
329 | typedef union TKey {
330 | struct {
331 | TValuefields;
332 | struct Node *next; /* for chaining */
333 | } nk;
334 | TValue tvk;
335 | } TKey;
336 |
337 | // 每个节点都有key和val
338 | typedef struct Node {
339 | TValue i_val;
340 | TKey i_key;
341 | } Node;
342 |
343 |
344 | typedef struct Table {
345 | CommonHeader;
346 | lu_byte flags; /* 1<lsizenode))
370 |
371 |
372 | #define luaO_nilobject (&luaO_nilobject_)
373 |
374 | LUAI_DATA const TValue luaO_nilobject_;
375 |
376 | #define ceillog2(x) (luaO_log2((x)-1) + 1)
377 |
378 | LUAI_FUNC int luaO_log2 (unsigned int x);
379 | LUAI_FUNC int luaO_int2fb (unsigned int x);
380 | LUAI_FUNC int luaO_fb2int (int x);
381 | LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);
382 | LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);
383 | LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
384 | va_list argp);
385 | LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
386 | LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);
387 |
388 |
389 | #endif
390 |
391 |
--------------------------------------------------------------------------------
/src/lopcodes.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $
3 | ** See Copyright Notice in lua.h
4 | */
5 |
6 |
7 | #define lopcodes_c
8 | #define LUA_CORE
9 |
10 |
11 | #include "lopcodes.h"
12 |
13 |
14 | /* ORDER OP */
15 |
16 | const char *const luaP_opnames[NUM_OPCODES+1] = {
17 | "MOVE",
18 | "LOADK",
19 | "LOADBOOL",
20 | "LOADNIL",
21 | "GETUPVAL",
22 | "GETGLOBAL",
23 | "GETTABLE",
24 | "SETGLOBAL",
25 | "SETUPVAL",
26 | "SETTABLE",
27 | "NEWTABLE",
28 | "SELF",
29 | "ADD",
30 | "SUB",
31 | "MUL",
32 | "DIV",
33 | "MOD",
34 | "POW",
35 | "UNM",
36 | "NOT",
37 | "LEN",
38 | "CONCAT",
39 | "JMP",
40 | "EQ",
41 | "LT",
42 | "LE",
43 | "TEST",
44 | "TESTSET",
45 | "CALL",
46 | "TAILCALL",
47 | "RETURN",
48 | "FORLOOP",
49 | "FORPREP",
50 | "TFORLOOP",
51 | "SETLIST",
52 | "CLOSE",
53 | "CLOSURE",
54 | "VARARG",
55 | NULL
56 | };
57 |
58 |
59 | #define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))
60 |
61 | // Tmode为1表示是逻辑测试类语句
62 | const lu_byte luaP_opmodes[NUM_OPCODES] = {
63 | /* T A B C mode opcode */
64 | opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */
65 | ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */
66 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */
67 | ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */
68 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */
69 | ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */
70 | ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */
71 | ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */
72 | ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */
73 | ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */
74 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */
75 | ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */
76 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */
77 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */
78 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */
79 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */
80 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */
81 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */
82 | ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */
83 | ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */
84 | ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */
85 | ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */
86 | ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */
87 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */
88 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */
89 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */
90 | ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */
91 | ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */
92 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */
93 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */
94 | ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */
95 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */
96 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */
97 | ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */
98 | ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */
99 | ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */
100 | ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */
101 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */
102 | };
103 |
104 |
--------------------------------------------------------------------------------
/src/lopcodes.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $
3 | ** Opcodes for Lua virtual machine
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 | #ifndef lopcodes_h
8 | #define lopcodes_h
9 |
10 | #include "llimits.h"
11 |
12 |
13 | /*===========================================================================
14 | We assume that instructions are unsigned numbers.
15 | All instructions have an opcode in the first 6 bits.
16 | Instructions can have the following fields:
17 | `A' : 8 bits
18 | `B' : 9 bits
19 | `C' : 9 bits
20 | `Bx' : 18 bits (`B' and `C' together)
21 | `sBx' : signed Bx
22 |
23 | A signed argument is represented in excess K; that is, the number
24 | value is the unsigned value minus K. K is exactly the maximum value
25 | for that argument (so that -max is represented by 0, and +max is
26 | represented by 2*max), which is half the maximum for the corresponding
27 | unsigned argument.
28 | ===========================================================================*/
29 |
30 |
31 | enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
32 |
33 |
34 | /*
35 | ** size and position of opcode arguments.
36 | */
37 | #define SIZE_C 9
38 | #define SIZE_B 9
39 | #define SIZE_Bx (SIZE_C + SIZE_B)
40 | #define SIZE_A 8
41 |
42 | #define SIZE_OP 6
43 |
44 | #define POS_OP 0
45 | #define POS_A (POS_OP + SIZE_OP)
46 | #define POS_C (POS_A + SIZE_A)
47 | #define POS_B (POS_C + SIZE_C)
48 | #define POS_Bx POS_C
49 |
50 |
51 | /*
52 | ** limits for opcode arguments.
53 | ** we use (signed) int to manipulate most arguments,
54 | ** so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
55 | */
56 | #if SIZE_Bx < LUAI_BITSINT-1
57 | #define MAXARG_Bx ((1<>1) /* `sBx' is signed */
59 | #else
60 | #define MAXARG_Bx MAX_INT
61 | #define MAXARG_sBx MAX_INT
62 | #endif
63 |
64 |
65 | #define MAXARG_A ((1<>POS_OP) & MASK1(SIZE_OP,0)))
81 | #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
82 | ((cast(Instruction, o)<>POS_A) & MASK1(SIZE_A,0)))
85 | #define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \
86 | ((cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0)))
89 | #define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \
90 | ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0)))
93 | #define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \
94 | ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0)))
97 | #define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \
98 | ((cast(Instruction, b)< C) then pc++ */
190 | OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
191 |
192 | OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
193 | OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
194 | OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */
195 |
196 | OP_FORLOOP,/* A sBx R(A)+=R(A+2);
197 | if R(A) = R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
198 | OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */
199 |
200 | OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
201 | if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */
202 | OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
203 |
204 | OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/
205 | OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
206 |
207 | OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
208 | } OpCode;
209 |
210 |
211 | #define NUM_OPCODES (cast(int, OP_VARARG) + 1)
212 |
213 |
214 |
215 | /*===========================================================================
216 | Notes:
217 | (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
218 | and can be 0: OP_CALL then sets `top' to last_result+1, so
219 | next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.
220 |
221 | (*) In OP_VARARG, if (B == 0) then use actual number of varargs and
222 | set top (like in OP_CALL with C == 0).
223 |
224 | (*) In OP_RETURN, if (B == 0) then return up to `top'
225 |
226 | (*) In OP_SETLIST, if (B == 0) then B = `top';
227 | if (C == 0) then next `instruction' is real C
228 |
229 | (*) For comparisons, A specifies what condition the test should accept
230 | (true or false).
231 |
232 | (*) All `skips' (pc++) assume that next instruction is a jump
233 | ===========================================================================*/
234 |
235 |
236 | /*
237 | ** masks for instruction properties. The format is:
238 | ** bits 0-1: op mode
239 | ** bits 2-3: C arg mode
240 | ** bits 4-5: B arg mode
241 | ** bit 6: instruction set register A
242 | ** bit 7: operator is a test
243 | */
244 |
245 | enum OpArgMask {
246 | OpArgN, /* argument is not used */
247 | OpArgU, /* argument is used */
248 | OpArgR, /* argument is a register or a jump offset */
249 | OpArgK /* argument is a constant or register/constant */
250 | };
251 |
252 | LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES];
253 |
254 | #define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3))
255 | #define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3))
256 | #define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3))
257 | #define testAMode(m) (luaP_opmodes[m] & (1 << 6))
258 | #define testTMode(m) (luaP_opmodes[m] & (1 << 7))
259 |
260 |
261 | LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */
262 |
263 |
264 | /* number of list items to accumulate before a SETLIST instruction */
265 | #define LFIELDS_PER_FLUSH 50
266 |
267 |
268 | #endif
269 |
--------------------------------------------------------------------------------
/src/loslib.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $
3 | ** Standard Operating System library
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | #define loslib_c
15 | #define LUA_LIB
16 |
17 | #include "lua.h"
18 |
19 | #include "lauxlib.h"
20 | #include "lualib.h"
21 |
22 |
23 | static int os_pushresult (lua_State *L, int i, const char *filename) {
24 | int en = errno; /* calls to Lua API may change this value */
25 | if (i) {
26 | lua_pushboolean(L, 1);
27 | return 1;
28 | }
29 | else {
30 | lua_pushnil(L);
31 | lua_pushfstring(L, "%s: %s", filename, strerror(en));
32 | lua_pushinteger(L, en);
33 | return 3;
34 | }
35 | }
36 |
37 |
38 | static int os_execute (lua_State *L) {
39 | lua_pushinteger(L, system(luaL_optstring(L, 1, NULL)));
40 | return 1;
41 | }
42 |
43 |
44 | static int os_remove (lua_State *L) {
45 | const char *filename = luaL_checkstring(L, 1);
46 | return os_pushresult(L, remove(filename) == 0, filename);
47 | }
48 |
49 |
50 | static int os_rename (lua_State *L) {
51 | const char *fromname = luaL_checkstring(L, 1);
52 | const char *toname = luaL_checkstring(L, 2);
53 | return os_pushresult(L, rename(fromname, toname) == 0, fromname);
54 | }
55 |
56 |
57 | static int os_tmpname (lua_State *L) {
58 | char buff[LUA_TMPNAMBUFSIZE];
59 | int err;
60 | lua_tmpnam(buff, err);
61 | if (err)
62 | return luaL_error(L, "unable to generate a unique filename");
63 | lua_pushstring(L, buff);
64 | return 1;
65 | }
66 |
67 |
68 | static int os_getenv (lua_State *L) {
69 | lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */
70 | return 1;
71 | }
72 |
73 |
74 | static int os_clock (lua_State *L) {
75 | lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);
76 | return 1;
77 | }
78 |
79 |
80 | /*
81 | ** {======================================================
82 | ** Time/Date operations
83 | ** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
84 | ** wday=%w+1, yday=%j, isdst=? }
85 | ** =======================================================
86 | */
87 |
88 | static void setfield (lua_State *L, const char *key, int value) {
89 | lua_pushinteger(L, value);
90 | lua_setfield(L, -2, key);
91 | }
92 |
93 | static void setboolfield (lua_State *L, const char *key, int value) {
94 | if (value < 0) /* undefined? */
95 | return; /* does not set field */
96 | lua_pushboolean(L, value);
97 | lua_setfield(L, -2, key);
98 | }
99 |
100 | static int getboolfield (lua_State *L, const char *key) {
101 | int res;
102 | lua_getfield(L, -1, key);
103 | res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
104 | lua_pop(L, 1);
105 | return res;
106 | }
107 |
108 |
109 | static int getfield (lua_State *L, const char *key, int d) {
110 | int res;
111 | lua_getfield(L, -1, key);
112 | if (lua_isnumber(L, -1))
113 | res = (int)lua_tointeger(L, -1);
114 | else {
115 | if (d < 0)
116 | return luaL_error(L, "field " LUA_QS " missing in date table", key);
117 | res = d;
118 | }
119 | lua_pop(L, 1);
120 | return res;
121 | }
122 |
123 |
124 | static int os_date (lua_State *L) {
125 | const char *s = luaL_optstring(L, 1, "%c");
126 | time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));
127 | struct tm *stm;
128 | if (*s == '!') { /* UTC? */
129 | stm = gmtime(&t);
130 | s++; /* skip `!' */
131 | }
132 | else
133 | stm = localtime(&t);
134 | if (stm == NULL) /* invalid date? */
135 | lua_pushnil(L);
136 | else if (strcmp(s, "*t") == 0) {
137 | lua_createtable(L, 0, 9); /* 9 = number of fields */
138 | setfield(L, "sec", stm->tm_sec);
139 | setfield(L, "min", stm->tm_min);
140 | setfield(L, "hour", stm->tm_hour);
141 | setfield(L, "day", stm->tm_mday);
142 | setfield(L, "month", stm->tm_mon+1);
143 | setfield(L, "year", stm->tm_year+1900);
144 | setfield(L, "wday", stm->tm_wday+1);
145 | setfield(L, "yday", stm->tm_yday+1);
146 | setboolfield(L, "isdst", stm->tm_isdst);
147 | }
148 | else {
149 | char cc[3];
150 | luaL_Buffer b;
151 | cc[0] = '%'; cc[2] = '\0';
152 | luaL_buffinit(L, &b);
153 | for (; *s; s++) {
154 | if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */
155 | luaL_addchar(&b, *s);
156 | else {
157 | size_t reslen;
158 | char buff[200]; /* should be big enough for any conversion result */
159 | cc[1] = *(++s);
160 | reslen = strftime(buff, sizeof(buff), cc, stm);
161 | luaL_addlstring(&b, buff, reslen);
162 | }
163 | }
164 | luaL_pushresult(&b);
165 | }
166 | return 1;
167 | }
168 |
169 |
170 | static int os_time (lua_State *L) {
171 | time_t t;
172 | if (lua_isnoneornil(L, 1)) /* called without args? */
173 | t = time(NULL); /* get current time */
174 | else {
175 | struct tm ts;
176 | luaL_checktype(L, 1, LUA_TTABLE);
177 | lua_settop(L, 1); /* make sure table is at the top */
178 | ts.tm_sec = getfield(L, "sec", 0);
179 | ts.tm_min = getfield(L, "min", 0);
180 | ts.tm_hour = getfield(L, "hour", 12);
181 | ts.tm_mday = getfield(L, "day", -1);
182 | ts.tm_mon = getfield(L, "month", -1) - 1;
183 | ts.tm_year = getfield(L, "year", -1) - 1900;
184 | ts.tm_isdst = getboolfield(L, "isdst");
185 | t = mktime(&ts);
186 | }
187 | if (t == (time_t)(-1))
188 | lua_pushnil(L);
189 | else
190 | lua_pushnumber(L, (lua_Number)t);
191 | return 1;
192 | }
193 |
194 |
195 | static int os_difftime (lua_State *L) {
196 | lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
197 | (time_t)(luaL_optnumber(L, 2, 0))));
198 | return 1;
199 | }
200 |
201 | /* }====================================================== */
202 |
203 |
204 | static int os_setlocale (lua_State *L) {
205 | static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
206 | LC_NUMERIC, LC_TIME};
207 | static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
208 | "numeric", "time", NULL};
209 | const char *l = luaL_optstring(L, 1, NULL);
210 | int op = luaL_checkoption(L, 2, "all", catnames);
211 | lua_pushstring(L, setlocale(cat[op], l));
212 | return 1;
213 | }
214 |
215 |
216 | static int os_exit (lua_State *L) {
217 | exit(luaL_optint(L, 1, EXIT_SUCCESS));
218 | }
219 |
220 | static const luaL_Reg syslib[] = {
221 | {"clock", os_clock},
222 | {"date", os_date},
223 | {"difftime", os_difftime},
224 | {"execute", os_execute},
225 | {"exit", os_exit},
226 | {"getenv", os_getenv},
227 | {"remove", os_remove},
228 | {"rename", os_rename},
229 | {"setlocale", os_setlocale},
230 | {"time", os_time},
231 | {"tmpname", os_tmpname},
232 | {NULL, NULL}
233 | };
234 |
235 | /* }====================================================== */
236 |
237 |
238 |
239 | LUALIB_API int luaopen_os (lua_State *L) {
240 | luaL_register(L, LUA_OSLIBNAME, syslib);
241 | return 1;
242 | }
243 |
244 |
--------------------------------------------------------------------------------
/src/lparser.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $
3 | ** Lua Parser
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 | #ifndef lparser_h
8 | #define lparser_h
9 |
10 | #include "llimits.h"
11 | #include "lobject.h"
12 | #include "lzio.h"
13 |
14 |
15 | /*
16 | ** Expression descriptor
17 | */
18 |
19 | typedef enum {
20 | VVOID, /* no value */
21 | VNIL,
22 | VTRUE,
23 | VFALSE,
24 | VK, /* info = index of constant in `k' */
25 | VKNUM, /* nval = numerical value */
26 | VLOCAL, /* info = local register */
27 | VUPVAL, /* info = index of upvalue in `upvalues' */
28 | VGLOBAL, /* info = index of table; aux = index of global name in `k' */
29 | VINDEXED, /* info = table register; aux = index register (or `k') */
30 | VJMP, /* info = instruction pc */
31 | VRELOCABLE, /* info = instruction pc */
32 | VNONRELOC, /* info = result register */
33 | VCALL, /* info = instruction pc */
34 | VVARARG /* info = instruction pc */
35 | } expkind;
36 |
37 | // 存放表达式的数据结构
38 | typedef struct expdesc {
39 | // 表达式类型
40 | expkind k;
41 | // 保存表达式信息的联合体
42 | union {
43 | struct { // info 和aux里面存储的数据信息,根据不同的表达式类型有区分,见前面expkind的注释
44 | int info,
45 | aux; } s;
46 | lua_Number nval; // 类型为数字的时候存储具体的数据
47 | } u;
48 | int t; /* patch list of `exit when true' */
49 | int f; /* patch list of `exit when false' */
50 | } expdesc;
51 |
52 |
53 | typedef struct upvaldesc {
54 | lu_byte k;
55 | lu_byte info;
56 | } upvaldesc;
57 |
58 |
59 | struct BlockCnt; /* defined in lparser.c */
60 |
61 |
62 | /* state needed to generate code for a given function */
63 | typedef struct FuncState {
64 | Proto *f; /* current function header */
65 | Table *h; /* table to find (and reuse) elements in `k' */
66 | struct FuncState *prev; /* enclosing function */
67 | struct LexState *ls; /* lexical state */
68 | struct lua_State *L; /* copy of the Lua state */
69 | struct BlockCnt *bl; /* chain of current blocks */
70 | int pc; /* next position to code (equivalent to `ncode') */
71 | int lasttarget; /* `pc' of last `jump target' */
72 | // 这里存放的是所有空悬,也就是没有确定好跳转位置的pc链表
73 | int jpc; /* list of pending jumps to `pc' */
74 | int freereg; /* first free register */
75 | int nk; /* number of elements in `k' */
76 | int np; /* number of elements in `p' */
77 | short nlocvars; /* number of elements in `locvars' */
78 | lu_byte nactvar; /* number of active local variables */
79 | upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */
80 | unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */
81 | } FuncState;
82 |
83 |
84 | LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
85 | const char *name);
86 |
87 |
88 | #endif
89 |
--------------------------------------------------------------------------------
/src/lstate.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $
3 | ** Global State
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 |
8 | #include
9 |
10 | #define lstate_c
11 | #define LUA_CORE
12 |
13 | #include "lua.h"
14 |
15 | #include "ldebug.h"
16 | #include "ldo.h"
17 | #include "lfunc.h"
18 | #include "lgc.h"
19 | #include "llex.h"
20 | #include "lmem.h"
21 | #include "lstate.h"
22 | #include "lstring.h"
23 | #include "ltable.h"
24 | #include "ltm.h"
25 |
26 |
27 | #define state_size(x) (sizeof(x) + LUAI_EXTRASPACE)
28 | #define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE)
29 | #define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE))
30 |
31 |
32 | /*
33 | ** Main thread combines a thread state and the global state
34 | */
35 | typedef struct LG {
36 | lua_State l;
37 | global_State g;
38 | } LG;
39 |
40 |
41 |
42 | static void stack_init (lua_State *L1, lua_State *L) {
43 | /* initialize CallInfo array */
44 | // 创建CallInfo数组
45 | L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
46 | L1->ci = L1->base_ci;
47 | L1->size_ci = BASIC_CI_SIZE;
48 | L1->end_ci = L1->base_ci + L1->size_ci - 1;
49 | /* initialize stack array */
50 | // 创建TValue数组
51 | L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue);
52 | L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
53 | L1->top = L1->stack;
54 | L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;
55 | /* initialize first ci */
56 | // 没看懂这个下面几句什么意思
57 | L1->ci->func = L1->top;
58 | // 这里的作用是把当前top所在区域的值set成nil,然后top++
59 | // 在top++之前,从上一句代码可以看出,top指向的位置是L1->ci->func,也就是把L1->ci->func set为nil
60 | setnilvalue(L1->top++); /* `function' entry for this `ci' */
61 | // 执行这句调用之后, base = top = stack + 1, 但是base是存放什么值的呢??
62 | L1->base = L1->ci->base = L1->top;
63 | // 这里的意思是,每个lua函数最开始预留LUA_MINSTACK个栈位置,不够的时候再增加,见luaD_checkstack函数
64 | L1->ci->top = L1->top + LUA_MINSTACK;
65 | }
66 |
67 |
68 | static void freestack (lua_State *L, lua_State *L1) {
69 | luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo);
70 | luaM_freearray(L, L1->stack, L1->stacksize, TValue);
71 | }
72 |
73 |
74 | /*
75 | ** open parts that may cause memory-allocation errors
76 | */
77 | static void f_luaopen (lua_State *L, void *ud) {
78 | global_State *g = G(L);
79 | UNUSED(ud);
80 | // 初始化堆栈
81 | stack_init(L, L); /* init stack */
82 | // 初始化全局表
83 | sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */
84 | // 初始化寄存器
85 | sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */
86 | luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
87 | luaT_init(L);
88 | luaX_init(L);
89 | // 初始化not enough memory这个字符串并且标记为不可回收
90 | luaS_fix(luaS_newliteral(L, MEMERRMSG));
91 | g->GCthreshold = 4*g->totalbytes;
92 | }
93 |
94 |
95 | static void preinit_state (lua_State *L, global_State *g) {
96 | G(L) = g;
97 | L->stack = NULL;
98 | L->stacksize = 0;
99 | L->errorJmp = NULL;
100 | L->hook = NULL;
101 | L->hookmask = 0;
102 | L->basehookcount = 0;
103 | L->allowhook = 1;
104 | resethookcount(L);
105 | L->openupval = NULL;
106 | L->size_ci = 0;
107 | L->nCcalls = L->baseCcalls = 0;
108 | L->status = 0;
109 | L->base_ci = L->ci = NULL;
110 | L->savedpc = NULL;
111 | L->errfunc = 0;
112 | setnilvalue(gt(L));
113 | }
114 |
115 |
116 | static void close_state (lua_State *L) {
117 | global_State *g = G(L);
118 | luaF_close(L, L->stack); /* close all upvalues for this thread */
119 | luaC_freeall(L); /* collect all objects */
120 | lua_assert(g->rootgc == obj2gco(L));
121 | lua_assert(g->strt.nuse == 0);
122 | luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
123 | luaZ_freebuffer(L, &g->buff);
124 | freestack(L, L);
125 | lua_assert(g->totalbytes == sizeof(LG));
126 | (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0);
127 | }
128 |
129 |
130 | lua_State *luaE_newthread (lua_State *L) {
131 | lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));
132 | luaC_link(L, obj2gco(L1), LUA_TTHREAD);
133 | preinit_state(L1, G(L));
134 | stack_init(L1, L); /* init stack */
135 | setobj2n(L, gt(L1), gt(L)); /* share table of globals */
136 | L1->hookmask = L->hookmask;
137 | L1->basehookcount = L->basehookcount;
138 | L1->hook = L->hook;
139 | resethookcount(L1);
140 | lua_assert(iswhite(obj2gco(L1)));
141 | return L1;
142 | }
143 |
144 |
145 | void luaE_freethread (lua_State *L, lua_State *L1) {
146 | luaF_close(L1, L1->stack); /* close all upvalues for this thread */
147 | lua_assert(L1->openupval == NULL);
148 | luai_userstatefree(L1);
149 | freestack(L, L1);
150 | luaM_freemem(L, fromstate(L1), state_size(lua_State));
151 | }
152 |
153 |
154 | LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
155 | int i;
156 | lua_State *L;
157 | global_State *g;
158 | void *l = (*f)(ud, NULL, 0, state_size(LG));
159 | if (l == NULL) return NULL;
160 | L = tostate(l);
161 | g = &((LG *)L)->g;
162 | L->next = NULL;
163 | L->tt = LUA_TTHREAD;
164 | g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
165 | L->marked = luaC_white(g);
166 | set2bits(L->marked, FIXEDBIT, SFIXEDBIT);
167 | preinit_state(L, g);
168 | g->frealloc = f;
169 | g->ud = ud;
170 | g->mainthread = L;
171 | g->uvhead.u.l.prev = &g->uvhead;
172 | g->uvhead.u.l.next = &g->uvhead;
173 | g->GCthreshold = 0; /* mark it as unfinished state */
174 | g->strt.size = 0;
175 | g->strt.nuse = 0;
176 | g->strt.hash = NULL;
177 | setnilvalue(registry(L));
178 | luaZ_initbuffer(L, &g->buff);
179 | g->panic = NULL;
180 | g->gcstate = GCSpause;
181 | g->rootgc = obj2gco(L);
182 | g->sweepstrgc = 0;
183 | g->sweepgc = &g->rootgc;
184 | g->gray = NULL;
185 | g->grayagain = NULL;
186 | g->weak = NULL;
187 | g->tmudata = NULL;
188 | g->totalbytes = sizeof(LG);
189 | g->gcpause = LUAI_GCPAUSE;
190 | g->gcstepmul = LUAI_GCMUL;
191 | g->gcdept = 0;
192 | for (i=0; imt[i] = NULL;
193 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
194 | /* memory allocation error: free partial state */
195 | close_state(L);
196 | L = NULL;
197 | }
198 | else
199 | luai_userstateopen(L);
200 | return L;
201 | }
202 |
203 |
204 | static void callallgcTM (lua_State *L, void *ud) {
205 | UNUSED(ud);
206 | luaC_callGCTM(L); /* call GC metamethods for all udata */
207 | }
208 |
209 |
210 | LUA_API void lua_close (lua_State *L) {
211 | L = G(L)->mainthread; /* only the main thread can be closed */
212 | lua_lock(L);
213 | luaF_close(L, L->stack); /* close all upvalues for this thread */
214 | luaC_separateudata(L, 1); /* separate udata that have GC metamethods */
215 | L->errfunc = 0; /* no error function during GC metamethods */
216 | do { /* repeat until no more errors */
217 | L->ci = L->base_ci;
218 | L->base = L->top = L->ci->base;
219 | L->nCcalls = L->baseCcalls = 0;
220 | } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);
221 | lua_assert(G(L)->tmudata == NULL);
222 | luai_userstateclose(L);
223 | close_state(L);
224 | }
225 |
226 |
--------------------------------------------------------------------------------
/src/lstate.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $
3 | ** Global State
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 | #ifndef lstate_h
8 | #define lstate_h
9 |
10 | #include "lua.h"
11 |
12 | #include "lobject.h"
13 | #include "ltm.h"
14 | #include "lzio.h"
15 |
16 |
17 |
18 | struct lua_longjmp; /* defined in ldo.c */
19 |
20 |
21 | /* table of globals */
22 | #define gt(L) (&L->l_gt)
23 |
24 | /* registry */
25 | #define registry(L) (&G(L)->l_registry)
26 |
27 |
28 | /* extra stack space to handle TM calls and some other extras */
29 | #define EXTRA_STACK 5
30 |
31 |
32 | #define BASIC_CI_SIZE 8
33 |
34 | #define BASIC_STACK_SIZE (2*LUA_MINSTACK)
35 |
36 |
37 |
38 | typedef struct stringtable {
39 | GCObject **hash;
40 | lu_int32 nuse; /* number of elements */
41 | int size; // hash桶数组大小
42 | } stringtable;
43 |
44 |
45 | /*
46 | ** informations about a call
47 | */
48 | typedef struct CallInfo {
49 | StkId base; /* base for this function */
50 | StkId func; /* function index in the stack */
51 | StkId top; /* top for this function */
52 | const Instruction *savedpc;
53 | int nresults; /* expected number of results from this function */
54 | int tailcalls; /* number of tail calls lost under this entry */
55 | } CallInfo;
56 |
57 |
58 |
59 | #define curr_func(L) (clvalue(L->ci->func))
60 | #define ci_func(ci) (clvalue((ci)->func))
61 | #define f_isLua(ci) (!ci_func(ci)->c.isC)
62 | #define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci))
63 |
64 |
65 | /*
66 | ** `global state', shared by all threads of this state
67 | */
68 | typedef struct global_State {
69 | stringtable strt; /* hash table for strings */
70 | lua_Alloc frealloc; /* function to reallocate memory */
71 | void *ud; /* auxiliary data to `frealloc' */
72 | lu_byte currentwhite;
73 | lu_byte gcstate; /* state of garbage collector */
74 | int sweepstrgc; /* position of sweep in `strt' */
75 | GCObject *rootgc; /* list of all collectable objects */
76 | GCObject **sweepgc; /* position of sweep in `rootgc' */
77 | GCObject *gray; /* list of gray objects */
78 | GCObject *grayagain; /* list of objects to be traversed atomically */
79 | GCObject *weak; /* list of weak tables (to be cleared) */
80 | // 所有有GC方法的udata都放在tmudata链表中
81 | GCObject *tmudata; /* last element of list of userdata to be GC */
82 | Mbuffer buff; /* temporary buffer for string concatentation */
83 | // 一个阈值,当这个totalbytes大于这个阈值时进行自动GC
84 | lu_mem GCthreshold;
85 | // 保存当前分配的总内存数量
86 | lu_mem totalbytes; /* number of bytes currently allocated */
87 | // 一个估算值,根据这个计算GCthreshold
88 | lu_mem estimate; /* an estimate of number of bytes actually in use */
89 | // 当前待GC的数据大小,其实就是累加totalbytes和GCthreshold的差值
90 | lu_mem gcdept; /* how much GC is `behind schedule' */
91 | // 可以配置的一个值,不是计算出来的,根据这个计算GCthreshold,以此来控制下一次GC触发的时间
92 | int gcpause; /* size of pause between successive GCs */
93 | // 每次进行GC操作回收的数据比例,见lgc.c/luaC_step函数
94 | int gcstepmul; /* GC `granularity' */
95 | lua_CFunction panic; /* to be called in unprotected errors */
96 | TValue l_registry;
97 | struct lua_State *mainthread;
98 | UpVal uvhead; /* head of double-linked list of all open upvalues */
99 | struct Table *mt[NUM_TAGS]; /* metatables for basic types */
100 | TString *tmname[TM_N]; /* array with tag-method names */
101 | } global_State;
102 |
103 |
104 | /*
105 | ** `per thread' state
106 | */
107 | struct lua_State {
108 | CommonHeader;
109 | lu_byte status;
110 | StkId top; /* first free slot in the stack */
111 | StkId base; /* base of current function */
112 | global_State *l_G;
113 | CallInfo *ci; /* call info for current function */
114 | const Instruction *savedpc; /* `savedpc' of current function */
115 | StkId stack_last; /* last free slot in the stack */
116 | StkId stack; /* stack base */
117 | CallInfo *end_ci; /* points after end of ci array*/
118 | CallInfo *base_ci; /* array of CallInfo's */
119 | int stacksize;
120 | int size_ci; /* size of array `base_ci' */
121 | unsigned short nCcalls; /* number of nested C calls */
122 | unsigned short baseCcalls; /* nested C calls when resuming coroutine */
123 | lu_byte hookmask;
124 | lu_byte allowhook;
125 | int basehookcount;
126 | int hookcount;
127 | lua_Hook hook;
128 | TValue l_gt; /* table of globals */
129 | TValue env; /* temporary place for environments */
130 | GCObject *openupval; /* list of open upvalues in this stack */
131 | GCObject *gclist;
132 | struct lua_longjmp *errorJmp; /* current error recover point */
133 | ptrdiff_t errfunc; /* current error handling function (stack index) */
134 | };
135 |
136 |
137 | #define G(L) (L->l_G)
138 |
139 |
140 | /*
141 | ** Union of all collectable objects
142 | */
143 | union GCObject {
144 | GCheader gch;
145 | union TString ts;
146 | union Udata u;
147 | union Closure cl;
148 | struct Table h;
149 | struct Proto p;
150 | struct UpVal uv;
151 | struct lua_State th; /* thread */
152 | };
153 |
154 |
155 | /* macros to convert a GCObject into a specific value */
156 | #define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))
157 | #define gco2ts(o) (&rawgco2ts(o)->tsv)
158 | #define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
159 | #define gco2u(o) (&rawgco2u(o)->uv)
160 | #define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))
161 | #define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
162 | #define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
163 | #define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
164 | #define ngcotouv(o) \
165 | check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv))
166 | #define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
167 |
168 | /* macro to convert any Lua object into a GCObject */
169 | #define obj2gco(v) (cast(GCObject *, (v)))
170 |
171 |
172 | LUAI_FUNC lua_State *luaE_newthread (lua_State *L);
173 | LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
174 |
175 | #endif
176 |
--------------------------------------------------------------------------------
/src/lstring.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
3 | ** String table (keeps all strings handled by Lua)
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 |
8 | #include
9 |
10 | #define lstring_c
11 | #define LUA_CORE
12 |
13 | #include "lua.h"
14 |
15 | #include "lmem.h"
16 | #include "lobject.h"
17 | #include "lstate.h"
18 | #include "lstring.h"
19 |
20 |
21 | // 对保存string的hash桶进行resize
22 | void luaS_resize (lua_State *L, int newsize) {
23 | GCObject **newhash;
24 | stringtable *tb;
25 | int i;
26 | if (G(L)->gcstate == GCSsweepstring)
27 | return; /* cannot resize during GC traverse */
28 | newhash = luaM_newvector(L, newsize, GCObject *);
29 | tb = &G(L)->strt;
30 | for (i=0; isize; i++) {
33 | GCObject *p = tb->hash[i];
34 | while (p) { /* for each node in the list */
35 | GCObject *next = p->gch.next; /* save next */
36 | unsigned int h = gco2ts(p)->hash;
37 | // 重新计算hash桶索引,这次需要mod新的hash桶大小
38 | int h1 = lmod(h, newsize); /* new position */
39 | lua_assert(cast_int(h%newsize) == lmod(h, newsize));
40 | p->gch.next = newhash[h1]; /* chain it */
41 | newhash[h1] = p;
42 | p = next;
43 | }
44 | }
45 | luaM_freearray(L, tb->hash, tb->size, TString *);
46 | tb->size = newsize;
47 | tb->hash = newhash;
48 | }
49 |
50 |
51 | static TString *newlstr (lua_State *L, const char *str, size_t l,
52 | unsigned int h) {
53 | TString *ts;
54 | stringtable *tb;
55 | if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
56 | luaM_toobig(L);
57 | ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString)));
58 | ts->tsv.len = l;
59 | ts->tsv.hash = h;
60 | ts->tsv.marked = luaC_white(G(L));
61 | ts->tsv.tt = LUA_TSTRING;
62 | ts->tsv.reserved = 0;
63 | memcpy(ts+1, str, l*sizeof(char));
64 | ((char *)(ts+1))[l] = '\0'; /* ending 0 */
65 | tb = &G(L)->strt;
66 | h = lmod(h, tb->size);
67 | ts->tsv.next = tb->hash[h]; /* chain new entry */
68 | tb->hash[h] = obj2gco(ts);
69 | tb->nuse++;
70 | // 在hash桶数组大小小于MAX_INT/2的情况下,
71 | // 只要字符串数量大于桶数组数量就开始成倍的扩充桶的容量
72 | if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
73 | luaS_resize(L, tb->size*2); /* too crowded */
74 | return ts;
75 | }
76 |
77 |
78 | TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
79 | GCObject *o;
80 | unsigned int h = cast(unsigned int, l); /* seed */
81 | size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */
82 | size_t l1;
83 | for (l1=l; l1>=step; l1-=step) /* compute hash */
84 | h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));
85 | for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
86 | o != NULL;
87 | o = o->gch.next) {
88 | TString *ts = rawgco2ts(o);
89 | if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {
90 | /* string may be dead */
91 | if (isdead(G(L), o)) changewhite(o);
92 | return ts;
93 | }
94 | }
95 | return newlstr(L, str, l, h); /* not found */
96 | }
97 |
98 |
99 | Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {
100 | Udata *u;
101 | if (s > MAX_SIZET - sizeof(Udata))
102 | luaM_toobig(L);
103 | u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata)));
104 | u->uv.marked = luaC_white(G(L)); /* is not finalized */
105 | u->uv.tt = LUA_TUSERDATA;
106 | u->uv.len = s;
107 | u->uv.metatable = NULL;
108 | u->uv.env = e;
109 | /* chain it on udata list (after main thread) */
110 | // 这样让udata链接在mainthread之后,一定是整个GC链表的最后
111 | u->uv.next = G(L)->mainthread->next;
112 | G(L)->mainthread->next = obj2gco(u);
113 | return u;
114 | }
115 |
116 |
--------------------------------------------------------------------------------
/src/lstring.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $
3 | ** String table (keep all strings handled by Lua)
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 | #ifndef lstring_h
8 | #define lstring_h
9 |
10 |
11 | #include "lgc.h"
12 | #include "lobject.h"
13 | #include "lstate.h"
14 |
15 |
16 | #define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char))
17 |
18 | #define sizeudata(u) (sizeof(union Udata)+(u)->len)
19 |
20 | #define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s)))
21 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
22 | (sizeof(s)/sizeof(char))-1))
23 |
24 | // 标记这个GC对象不可回收
25 | #define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT)
26 |
27 | LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
28 | LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
29 | LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
30 |
31 |
32 | #endif
33 |
--------------------------------------------------------------------------------
/src/ltable.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $
3 | ** Lua tables (hash)
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 | #ifndef ltable_h
8 | #define ltable_h
9 |
10 | #include "lobject.h"
11 |
12 |
13 | #define gnode(t,i) (&(t)->node[i])
14 | #define gkey(n) (&(n)->i_key.nk)
15 | #define gval(n) (&(n)->i_val)
16 | #define gnext(n) ((n)->i_key.nk.next)
17 |
18 | #define key2tval(n) (&(n)->i_key.tvk)
19 |
20 |
21 | LUAI_FUNC const TValue *luaH_getnum (Table *t, int key);
22 | LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);
23 | LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
24 | LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);
25 | LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
26 | LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);
27 | LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash);
28 | LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize);
29 | LUAI_FUNC void luaH_free (lua_State *L, Table *t);
30 | LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
31 | LUAI_FUNC int luaH_getn (Table *t);
32 |
33 |
34 | #if defined(LUA_DEBUG)
35 | LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);
36 | LUAI_FUNC int luaH_isdummy (Node *n);
37 | #endif
38 |
39 |
40 | #endif
41 |
--------------------------------------------------------------------------------
/src/ltablib.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $
3 | ** Library for Table Manipulation
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 |
8 | #include
9 |
10 | #define ltablib_c
11 | #define LUA_LIB
12 |
13 | #include "lua.h"
14 |
15 | #include "lauxlib.h"
16 | #include "lualib.h"
17 |
18 |
19 | #define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n))
20 |
21 |
22 | static int foreachi (lua_State *L) {
23 | int i;
24 | int n = aux_getn(L, 1);
25 | luaL_checktype(L, 2, LUA_TFUNCTION);
26 | for (i=1; i <= n; i++) {
27 | lua_pushvalue(L, 2); /* function */
28 | lua_pushinteger(L, i); /* 1st argument */
29 | lua_rawgeti(L, 1, i); /* 2nd argument */
30 | lua_call(L, 2, 1);
31 | if (!lua_isnil(L, -1))
32 | return 1;
33 | lua_pop(L, 1); /* remove nil result */
34 | }
35 | return 0;
36 | }
37 |
38 |
39 | static int foreach (lua_State *L) {
40 | luaL_checktype(L, 1, LUA_TTABLE);
41 | luaL_checktype(L, 2, LUA_TFUNCTION);
42 | lua_pushnil(L); /* first key */
43 | while (lua_next(L, 1)) {
44 | lua_pushvalue(L, 2); /* function */
45 | lua_pushvalue(L, -3); /* key */
46 | lua_pushvalue(L, -3); /* value */
47 | lua_call(L, 2, 1);
48 | if (!lua_isnil(L, -1))
49 | return 1;
50 | lua_pop(L, 2); /* remove value and result */
51 | }
52 | return 0;
53 | }
54 |
55 |
56 | static int maxn (lua_State *L) {
57 | lua_Number max = 0;
58 | luaL_checktype(L, 1, LUA_TTABLE);
59 | lua_pushnil(L); /* first key */
60 | while (lua_next(L, 1)) {
61 | lua_pop(L, 1); /* remove value */
62 | if (lua_type(L, -1) == LUA_TNUMBER) {
63 | lua_Number v = lua_tonumber(L, -1);
64 | if (v > max) max = v;
65 | }
66 | }
67 | lua_pushnumber(L, max);
68 | return 1;
69 | }
70 |
71 |
72 | static int getn (lua_State *L) {
73 | lua_pushinteger(L, aux_getn(L, 1));
74 | return 1;
75 | }
76 |
77 |
78 | static int setn (lua_State *L) {
79 | luaL_checktype(L, 1, LUA_TTABLE);
80 | #ifndef luaL_setn
81 | luaL_setn(L, 1, luaL_checkint(L, 2));
82 | #else
83 | luaL_error(L, LUA_QL("setn") " is obsolete");
84 | #endif
85 | lua_pushvalue(L, 1);
86 | return 1;
87 | }
88 |
89 |
90 | static int tinsert (lua_State *L) {
91 | int e = aux_getn(L, 1) + 1; /* first empty element */
92 | int pos; /* where to insert new element */
93 | switch (lua_gettop(L)) {
94 | case 2: { /* called with only 2 arguments */
95 | pos = e; /* insert new element at the end */
96 | break;
97 | }
98 | case 3: {
99 | int i;
100 | pos = luaL_checkint(L, 2); /* 2nd argument is the position */
101 | if (pos > e) e = pos; /* `grow' array if necessary */
102 | for (i = e; i > pos; i--) { /* move up elements */
103 | lua_rawgeti(L, 1, i-1);
104 | lua_rawseti(L, 1, i); /* t[i] = t[i-1] */
105 | }
106 | break;
107 | }
108 | default: {
109 | return luaL_error(L, "wrong number of arguments to " LUA_QL("insert"));
110 | }
111 | }
112 | luaL_setn(L, 1, e); /* new size */
113 | lua_rawseti(L, 1, pos); /* t[pos] = v */
114 | return 0;
115 | }
116 |
117 |
118 | static int tremove (lua_State *L) {
119 | int e = aux_getn(L, 1);
120 | int pos = luaL_optint(L, 2, e);
121 | if (!(1 <= pos && pos <= e)) /* position is outside bounds? */
122 | return 0; /* nothing to remove */
123 | luaL_setn(L, 1, e - 1); /* t.n = n-1 */
124 | lua_rawgeti(L, 1, pos); /* result = t[pos] */
125 | for ( ;pos= P */
226 | while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {
227 | if (i>u) luaL_error(L, "invalid order function for sorting");
228 | lua_pop(L, 1); /* remove a[i] */
229 | }
230 | /* repeat --j until a[j] <= P */
231 | while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {
232 | if (j
9 |
10 | #define ltm_c
11 | #define LUA_CORE
12 |
13 | #include "lua.h"
14 |
15 | #include "lobject.h"
16 | #include "lstate.h"
17 | #include "lstring.h"
18 | #include "ltable.h"
19 | #include "ltm.h"
20 |
21 |
22 |
23 | const char *const luaT_typenames[] = {
24 | "nil", "boolean", "userdata", "number",
25 | "string", "table", "function", "userdata", "thread",
26 | "proto", "upval"
27 | };
28 |
29 |
30 | void luaT_init (lua_State *L) {
31 | static const char *const luaT_eventname[] = { /* ORDER TM */
32 | "__index", "__newindex",
33 | "__gc", "__mode", "__eq",
34 | "__add", "__sub", "__mul", "__div", "__mod",
35 | "__pow", "__unm", "__len", "__lt", "__le",
36 | "__concat", "__call"
37 | };
38 | int i;
39 | // 初始化meta method
40 | for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]);
42 | luaS_fix(G(L)->tmname[i]); /* never collect these names */
43 | }
44 | }
45 |
46 |
47 | /*
48 | ** function to be used with macro "fasttm": optimized for absence of
49 | ** tag methods
50 | */
51 | const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
52 | const TValue *tm = luaH_getstr(events, ename);
53 | // 这里这个条件是什么原因??
54 | lua_assert(event <= TM_EQ);
55 | if (ttisnil(tm)) { /* no tag method? */
56 | // 如果没有这个meta method,那么标记上,避免下一次再次进入这个函数
57 | events->flags |= cast_byte(1u<metatable;
69 | break;
70 | case LUA_TUSERDATA:
71 | mt = uvalue(o)->metatable;
72 | break;
73 | default:
74 | mt = G(L)->mt[ttype(o)];
75 | }
76 | return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
77 | }
78 |
79 |
--------------------------------------------------------------------------------
/src/ltm.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $
3 | ** Tag methods
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 | #ifndef ltm_h
8 | #define ltm_h
9 |
10 |
11 | #include "lobject.h"
12 |
13 |
14 | /*
15 | * WARNING: if you change the order of this enumeration,
16 | * grep "ORDER TM"
17 | */
18 | typedef enum {
19 | TM_INDEX,
20 | TM_NEWINDEX,
21 | TM_GC,
22 | TM_MODE,
23 | TM_EQ, /* last tag method with `fast' access */
24 | TM_ADD,
25 | TM_SUB,
26 | TM_MUL,
27 | TM_DIV,
28 | TM_MOD,
29 | TM_POW,
30 | TM_UNM,
31 | TM_LEN,
32 | TM_LT,
33 | TM_LE,
34 | TM_CONCAT,
35 | TM_CALL,
36 | TM_N /* number of elements in the enum */
37 | } TMS;
38 |
39 |
40 |
41 | #define gfasttm(g,et,e) ((et) == NULL ? NULL : \
42 | ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
43 |
44 | #define fasttm(l,et,e) gfasttm(G(l), et, e)
45 |
46 | LUAI_DATA const char *const luaT_typenames[];
47 |
48 |
49 | LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);
50 | LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
51 | TMS event);
52 | LUAI_FUNC void luaT_init (lua_State *L);
53 |
54 | #endif
55 |
--------------------------------------------------------------------------------
/src/luac.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: luac.c,v 1.54 2006/06/02 17:37:11 lhf Exp $
3 | ** Lua compiler (saves bytecodes to files; also list bytecodes)
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #define luac_c
13 | #define LUA_CORE
14 |
15 | #include "lua.h"
16 | #include "lauxlib.h"
17 |
18 | #include "ldo.h"
19 | #include "lfunc.h"
20 | #include "lmem.h"
21 | #include "lobject.h"
22 | #include "lopcodes.h"
23 | #include "lstring.h"
24 | #include "lundump.h"
25 |
26 | #define PROGNAME "luac" /* default program name */
27 | #define OUTPUT PROGNAME ".out" /* default output file */
28 |
29 | static int listing=0; /* list bytecodes? */
30 | static int dumping=1; /* dump bytecodes? */
31 | static int stripping=0; /* strip debug information? */
32 | static char Output[]={ OUTPUT }; /* default output file name */
33 | static const char* output=Output; /* actual output file name */
34 | static const char* progname=PROGNAME; /* actual program name */
35 |
36 | static void fatal(const char* message)
37 | {
38 | fprintf(stderr,"%s: %s\n",progname,message);
39 | exit(EXIT_FAILURE);
40 | }
41 |
42 | static void cannot(const char* what)
43 | {
44 | fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno));
45 | exit(EXIT_FAILURE);
46 | }
47 |
48 | static void usage(const char* message)
49 | {
50 | if (*message=='-')
51 | fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message);
52 | else
53 | fprintf(stderr,"%s: %s\n",progname,message);
54 | fprintf(stderr,
55 | "usage: %s [options] [filenames].\n"
56 | "Available options are:\n"
57 | " - process stdin\n"
58 | " -l list\n"
59 | " -o name output to file " LUA_QL("name") " (default is \"%s\")\n"
60 | " -p parse only\n"
61 | " -s strip debug information\n"
62 | " -v show version information\n"
63 | " -- stop handling options\n",
64 | progname,Output);
65 | exit(EXIT_FAILURE);
66 | }
67 |
68 | #define IS(s) (strcmp(argv[i],s)==0)
69 |
70 | static int doargs(int argc, char* argv[])
71 | {
72 | int i;
73 | int version=0;
74 | if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0];
75 | for (i=1; itop+(i))->l.p)
118 |
119 | static const Proto* combine(lua_State* L, int n)
120 | {
121 | if (n==1)
122 | return toproto(L,-1);
123 | else
124 | {
125 | int i,pc;
126 | Proto* f=luaF_newproto(L);
127 | setptvalue2s(L,L->top,f); incr_top(L);
128 | f->source=luaS_newliteral(L,"=(" PROGNAME ")");
129 | f->maxstacksize=1;
130 | pc=2*n+1;
131 | f->code=luaM_newvector(L,pc,Instruction);
132 | f->sizecode=pc;
133 | f->p=luaM_newvector(L,n,Proto*);
134 | f->sizep=n;
135 | pc=0;
136 | for (i=0; ip[i]=toproto(L,i-n-1);
139 | f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i);
140 | f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1);
141 | }
142 | f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0);
143 | return f;
144 | }
145 | }
146 |
147 | static int writer(lua_State* L, const void* p, size_t size, void* u)
148 | {
149 | UNUSED(L);
150 | return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0);
151 | }
152 |
153 | struct Smain {
154 | int argc;
155 | char** argv;
156 | };
157 |
158 | static int pmain(lua_State* L)
159 | {
160 | struct Smain* s = (struct Smain*)lua_touserdata(L, 1);
161 | int argc=s->argc;
162 | char** argv=s->argv;
163 | const Proto* f;
164 | int i;
165 | if (!lua_checkstack(L,argc)) fatal("too many input files");
166 | for (i=0; i1);
173 | if (dumping)
174 | {
175 | FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
176 | if (D==NULL) cannot("open");
177 | lua_lock(L);
178 | luaU_dump(L,f,writer,D,stripping);
179 | lua_unlock(L);
180 | if (ferror(D)) cannot("write");
181 | if (fclose(D)) cannot("close");
182 | }
183 | return 0;
184 | }
185 |
186 | int main(int argc, char* argv[])
187 | {
188 | lua_State* L;
189 | struct Smain s;
190 | int i=doargs(argc,argv);
191 | argc-=i; argv+=i;
192 | if (argc<=0) usage("no input files given");
193 | L=lua_open();
194 | if (L==NULL) fatal("not enough memory for state");
195 | s.argc=argc;
196 | s.argv=argv;
197 | if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1));
198 | lua_close(L);
199 | return EXIT_SUCCESS;
200 | }
201 |
--------------------------------------------------------------------------------
/src/lualib.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $
3 | ** Lua standard libraries
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 |
8 | #ifndef lualib_h
9 | #define lualib_h
10 |
11 | #include "lua.h"
12 |
13 |
14 | /* Key to file-handle type */
15 | #define LUA_FILEHANDLE "FILE*"
16 |
17 |
18 | #define LUA_COLIBNAME "coroutine"
19 | LUALIB_API int (luaopen_base) (lua_State *L);
20 |
21 | #define LUA_TABLIBNAME "table"
22 | LUALIB_API int (luaopen_table) (lua_State *L);
23 |
24 | #define LUA_IOLIBNAME "io"
25 | LUALIB_API int (luaopen_io) (lua_State *L);
26 |
27 | #define LUA_OSLIBNAME "os"
28 | LUALIB_API int (luaopen_os) (lua_State *L);
29 |
30 | #define LUA_STRLIBNAME "string"
31 | LUALIB_API int (luaopen_string) (lua_State *L);
32 |
33 | #define LUA_MATHLIBNAME "math"
34 | LUALIB_API int (luaopen_math) (lua_State *L);
35 |
36 | #define LUA_DBLIBNAME "debug"
37 | LUALIB_API int (luaopen_debug) (lua_State *L);
38 |
39 | #define LUA_LOADLIBNAME "package"
40 | LUALIB_API int (luaopen_package) (lua_State *L);
41 |
42 |
43 | /* open all previous libraries */
44 | LUALIB_API void (luaL_openlibs) (lua_State *L);
45 |
46 |
47 |
48 | #ifndef lua_assert
49 | #define lua_assert(x) ((void)0)
50 | #endif
51 |
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/src/lundump.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $
3 | ** load precompiled Lua chunks
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 | #include
8 |
9 | #define lundump_c
10 | #define LUA_CORE
11 |
12 | #include "lua.h"
13 |
14 | #include "ldebug.h"
15 | #include "ldo.h"
16 | #include "lfunc.h"
17 | #include "lmem.h"
18 | #include "lobject.h"
19 | #include "lstring.h"
20 | #include "lundump.h"
21 | #include "lzio.h"
22 |
23 | typedef struct {
24 | lua_State* L;
25 | ZIO* Z;
26 | Mbuffer* b;
27 | const char* name;
28 | } LoadState;
29 |
30 | #ifdef LUAC_TRUST_BINARIES
31 | #define IF(c,s)
32 | #define error(S,s)
33 | #else
34 | #define IF(c,s) if (c) error(S,s)
35 |
36 | static void error(LoadState* S, const char* why)
37 | {
38 | luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why);
39 | luaD_throw(S->L,LUA_ERRSYNTAX);
40 | }
41 | #endif
42 |
43 | #define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
44 | #define LoadByte(S) (lu_byte)LoadChar(S)
45 | #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
46 | #define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
47 |
48 | static void LoadBlock(LoadState* S, void* b, size_t size)
49 | {
50 | size_t r=luaZ_read(S->Z,b,size);
51 | IF (r!=0, "unexpected end");
52 | }
53 |
54 | static int LoadChar(LoadState* S)
55 | {
56 | char x;
57 | LoadVar(S,x);
58 | return x;
59 | }
60 |
61 | static int LoadInt(LoadState* S)
62 | {
63 | int x;
64 | LoadVar(S,x);
65 | IF (x<0, "bad integer");
66 | return x;
67 | }
68 |
69 | static lua_Number LoadNumber(LoadState* S)
70 | {
71 | lua_Number x;
72 | LoadVar(S,x);
73 | return x;
74 | }
75 |
76 | static TString* LoadString(LoadState* S)
77 | {
78 | size_t size;
79 | LoadVar(S,size);
80 | if (size==0)
81 | return NULL;
82 | else
83 | {
84 | char* s=luaZ_openspace(S->L,S->b,size);
85 | LoadBlock(S,s,size);
86 | return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
87 | }
88 | }
89 |
90 | static void LoadCode(LoadState* S, Proto* f)
91 | {
92 | int n=LoadInt(S);
93 | f->code=luaM_newvector(S->L,n,Instruction);
94 | f->sizecode=n;
95 | LoadVector(S,f->code,n,sizeof(Instruction));
96 | }
97 |
98 | static Proto* LoadFunction(LoadState* S, TString* p);
99 |
100 | static void LoadConstants(LoadState* S, Proto* f)
101 | {
102 | int i,n;
103 | n=LoadInt(S);
104 | f->k=luaM_newvector(S->L,n,TValue);
105 | f->sizek=n;
106 | for (i=0; ik[i]);
107 | for (i=0; ik[i];
110 | int t=LoadChar(S);
111 | switch (t)
112 | {
113 | case LUA_TNIL:
114 | setnilvalue(o);
115 | break;
116 | case LUA_TBOOLEAN:
117 | setbvalue(o,LoadChar(S)!=0);
118 | break;
119 | case LUA_TNUMBER:
120 | setnvalue(o,LoadNumber(S));
121 | break;
122 | case LUA_TSTRING:
123 | setsvalue2n(S->L,o,LoadString(S));
124 | break;
125 | default:
126 | error(S,"bad constant");
127 | break;
128 | }
129 | }
130 | n=LoadInt(S);
131 | f->p=luaM_newvector(S->L,n,Proto*);
132 | f->sizep=n;
133 | for (i=0; ip[i]=NULL;
134 | for (i=0; ip[i]=LoadFunction(S,f->source);
135 | }
136 |
137 | static void LoadDebug(LoadState* S, Proto* f)
138 | {
139 | int i,n;
140 | n=LoadInt(S);
141 | f->lineinfo=luaM_newvector(S->L,n,int);
142 | f->sizelineinfo=n;
143 | LoadVector(S,f->lineinfo,n,sizeof(int));
144 | n=LoadInt(S);
145 | f->locvars=luaM_newvector(S->L,n,LocVar);
146 | f->sizelocvars=n;
147 | for (i=0; ilocvars[i].varname=NULL;
148 | for (i=0; ilocvars[i].varname=LoadString(S);
151 | f->locvars[i].startpc=LoadInt(S);
152 | f->locvars[i].endpc=LoadInt(S);
153 | }
154 | n=LoadInt(S);
155 | f->upvalues=luaM_newvector(S->L,n,TString*);
156 | f->sizeupvalues=n;
157 | for (i=0; iupvalues[i]=NULL;
158 | for (i=0; iupvalues[i]=LoadString(S);
159 | }
160 |
161 | static Proto* LoadFunction(LoadState* S, TString* p)
162 | {
163 | Proto* f;
164 | if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep");
165 | f=luaF_newproto(S->L);
166 | setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
167 | f->source=LoadString(S); if (f->source==NULL) f->source=p;
168 | f->linedefined=LoadInt(S);
169 | f->lastlinedefined=LoadInt(S);
170 | f->nups=LoadByte(S);
171 | f->numparams=LoadByte(S);
172 | f->is_vararg=LoadByte(S);
173 | f->maxstacksize=LoadByte(S);
174 | LoadCode(S,f);
175 | LoadConstants(S,f);
176 | LoadDebug(S,f);
177 | IF (!luaG_checkcode(f), "bad code");
178 | S->L->top--;
179 | S->L->nCcalls--;
180 | return f;
181 | }
182 |
183 | static void LoadHeader(LoadState* S)
184 | {
185 | char h[LUAC_HEADERSIZE];
186 | char s[LUAC_HEADERSIZE];
187 | luaU_header(h);
188 | LoadBlock(S,s,LUAC_HEADERSIZE);
189 | IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
190 | }
191 |
192 | /*
193 | ** load precompiled chunk
194 | */
195 | Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
196 | {
197 | LoadState S;
198 | if (*name=='@' || *name=='=')
199 | S.name=name+1;
200 | else if (*name==LUA_SIGNATURE[0])
201 | S.name="binary string";
202 | else
203 | S.name=name;
204 | S.L=L;
205 | S.Z=Z;
206 | S.b=buff;
207 | LoadHeader(&S);
208 | return LoadFunction(&S,luaS_newliteral(L,"=?"));
209 | }
210 |
211 | /*
212 | * make header
213 | */
214 | void luaU_header (char* h)
215 | {
216 | int x=1;
217 | memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);
218 | h+=sizeof(LUA_SIGNATURE)-1;
219 | *h++=(char)LUAC_VERSION;
220 | *h++=(char)LUAC_FORMAT;
221 | *h++=(char)*(char*)&x; /* endianness */
222 | *h++=(char)sizeof(int);
223 | *h++=(char)sizeof(size_t);
224 | *h++=(char)sizeof(Instruction);
225 | *h++=(char)sizeof(lua_Number);
226 | *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */
227 | }
228 |
--------------------------------------------------------------------------------
/src/lundump.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $
3 | ** load precompiled Lua chunks
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 | #ifndef lundump_h
8 | #define lundump_h
9 |
10 | #include "lobject.h"
11 | #include "lzio.h"
12 |
13 | /* load one chunk; from lundump.c */
14 | LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);
15 |
16 | /* make header; from lundump.c */
17 | LUAI_FUNC void luaU_header (char* h);
18 |
19 | /* dump one chunk; from ldump.c */
20 | LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
21 |
22 | #ifdef luac_c
23 | /* print one chunk; from print.c */
24 | LUAI_FUNC void luaU_print (const Proto* f, int full);
25 | #endif
26 |
27 | /* for header of binary files -- this is Lua 5.1 */
28 | #define LUAC_VERSION 0x51
29 |
30 | /* for header of binary files -- this is the official format */
31 | #define LUAC_FORMAT 0
32 |
33 | /* size of header of binary files */
34 | #define LUAC_HEADERSIZE 12
35 |
36 | #endif
37 |
--------------------------------------------------------------------------------
/src/lvm.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $
3 | ** Lua virtual machine
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 | #ifndef lvm_h
8 | #define lvm_h
9 |
10 |
11 | #include "ldo.h"
12 | #include "lobject.h"
13 | #include "ltm.h"
14 |
15 |
16 | #define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o)))
17 |
18 | #define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \
19 | (((o) = luaV_tonumber(o,n)) != NULL))
20 |
21 | #define equalobj(L,o1,o2) \
22 | (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
23 |
24 |
25 | LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
26 | LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2);
27 | LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n);
28 | LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj);
29 | LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
30 | StkId val);
31 | LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
32 | StkId val);
33 | LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls);
34 | LUAI_FUNC void luaV_concat (lua_State *L, int total, int last);
35 |
36 | #endif
37 |
--------------------------------------------------------------------------------
/src/lzio.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $
3 | ** a generic input stream interface
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 |
8 | #include
9 |
10 | #define lzio_c
11 | #define LUA_CORE
12 |
13 | #include "lua.h"
14 |
15 | #include "llimits.h"
16 | #include "lmem.h"
17 | #include "lstate.h"
18 | #include "lzio.h"
19 |
20 |
21 | int luaZ_fill (ZIO *z) {
22 | size_t size;
23 | lua_State *L = z->L;
24 | const char *buff;
25 | lua_unlock(L);
26 | buff = z->reader(L, z->data, &size);
27 | lua_lock(L);
28 | if (buff == NULL || size == 0) return EOZ;
29 | z->n = size - 1;
30 | z->p = buff;
31 | return char2int(*(z->p++));
32 | }
33 |
34 | // 向前预读一个数据
35 | int luaZ_lookahead (ZIO *z) {
36 | if (z->n == 0) {
37 | // 如果当前缓冲区没有元素可读,则继续从输入中读取数据
38 | if (luaZ_fill(z) == EOZ)
39 | // 如果没有数据可读了
40 | return EOZ;
41 | else {
42 | // 否则,读到了数据,则将指针和计数器加1
43 | z->n++; /* luaZ_fill removed first byte; put back it */
44 | z->p--;
45 | }
46 | }
47 | // OK了,将它作为字符返回
48 | return char2int(*z->p);
49 | }
50 |
51 |
52 | void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) {
53 | z->L = L;
54 | z->reader = reader;
55 | z->data = data;
56 | z->n = 0;
57 | z->p = NULL;
58 | }
59 |
60 |
61 | /* --------------------------------------------------------------- read --- */
62 | size_t luaZ_read (ZIO *z, void *b, size_t n) {
63 | while (n) {
64 | size_t m;
65 | if (luaZ_lookahead(z) == EOZ)
66 | return n; /* return number of missing bytes */
67 | m = (n <= z->n) ? n : z->n; /* min. between n and z->n */
68 | memcpy(b, z->p, m);
69 | z->n -= m;
70 | z->p += m;
71 | b = (char *)b + m;
72 | n -= m;
73 | }
74 | return 0;
75 | }
76 |
77 | /* ------------------------------------------------------------------------ */
78 | char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {
79 | if (n > buff->buffsize) {
80 | if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;
81 | luaZ_resizebuffer(L, buff, n);
82 | }
83 | return buff->buffer;
84 | }
85 |
86 |
87 |
--------------------------------------------------------------------------------
/src/lzio.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $
3 | ** Buffered streams
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 |
8 | #ifndef lzio_h
9 | #define lzio_h
10 |
11 | #include "lua.h"
12 |
13 | #include "lmem.h"
14 |
15 |
16 | #define EOZ (-1) /* end of stream */
17 |
18 | typedef struct Zio ZIO;
19 |
20 | #define char2int(c) cast(int, cast(unsigned char, (c)))
21 |
22 | #define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z))
23 |
24 | typedef struct Mbuffer {
25 | char *buffer;
26 | size_t n;
27 | size_t buffsize;
28 | } Mbuffer;
29 |
30 | #define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)
31 |
32 | #define luaZ_buffer(buff) ((buff)->buffer)
33 | #define luaZ_sizebuffer(buff) ((buff)->buffsize)
34 | #define luaZ_bufflen(buff) ((buff)->n)
35 |
36 | #define luaZ_resetbuffer(buff) ((buff)->n = 0)
37 |
38 |
39 | #define luaZ_resizebuffer(L, buff, size) \
40 | (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \
41 | (buff)->buffsize = size)
42 |
43 | #define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
44 |
45 |
46 | LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
47 | LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,
48 | void *data);
49 | LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */
50 | LUAI_FUNC int luaZ_lookahead (ZIO *z);
51 |
52 |
53 |
54 | /* --------- Private Part ------------------ */
55 |
56 | struct Zio {
57 | size_t n; /* bytes still unread */
58 | const char *p; /* current position in buffer */
59 | lua_Reader reader;
60 | void* data; /* additional data */
61 | lua_State *L; /* Lua state (for reader) */
62 | };
63 |
64 |
65 | LUAI_FUNC int luaZ_fill (ZIO *z);
66 |
67 | #endif
68 |
--------------------------------------------------------------------------------
/src/print.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** $Id: print.c,v 1.55a 2006/05/31 13:30:05 lhf Exp $
3 | ** print bytecodes
4 | ** See Copyright Notice in lua.h
5 | */
6 |
7 | #include
8 | #include
9 |
10 | #define luac_c
11 | #define LUA_CORE
12 |
13 | #include "ldebug.h"
14 | #include "lobject.h"
15 | #include "lopcodes.h"
16 | #include "lundump.h"
17 |
18 | #define PrintFunction luaU_print
19 |
20 | #define Sizeof(x) ((int)sizeof(x))
21 | #define VOID(p) ((const void*)(p))
22 |
23 | static void PrintString(const TString* ts)
24 | {
25 | const char* s=getstr(ts);
26 | size_t i,n=ts->tsv.len;
27 | putchar('"');
28 | for (i=0; ik[i];
54 | switch (ttype(o))
55 | {
56 | case LUA_TNIL:
57 | printf("nil");
58 | break;
59 | case LUA_TBOOLEAN:
60 | printf(bvalue(o) ? "true" : "false");
61 | break;
62 | case LUA_TNUMBER:
63 | printf(LUA_NUMBER_FMT,nvalue(o));
64 | break;
65 | case LUA_TSTRING:
66 | PrintString(rawtsvalue(o));
67 | break;
68 | default: /* cannot happen */
69 | printf("? type=%d",ttype(o));
70 | break;
71 | }
72 | }
73 |
74 | static void PrintCode(const Proto* f)
75 | {
76 | const Instruction* code=f->code;
77 | int pc,n=f->sizecode;
78 | for (pc=0; pc0) printf("[%d]\t",line); else printf("[-]\t");
90 | printf("%-9s\t",luaP_opnames[o]);
91 | switch (getOpMode(o))
92 | {
93 | case iABC:
94 | printf("%d",a);
95 | if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (-1-INDEXK(b)) : b);
96 | if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (-1-INDEXK(c)) : c);
97 | break;
98 | case iABx:
99 | if (getBMode(o)==OpArgK) printf("%d %d",a,-1-bx); else printf("%d %d",a,bx);
100 | break;
101 | case iAsBx:
102 | if (o==OP_JMP) printf("%d",sbx); else printf("%d %d",a,sbx);
103 | break;
104 | }
105 | switch (o)
106 | {
107 | case OP_LOADK:
108 | printf("\t; "); PrintConstant(f,bx);
109 | break;
110 | case OP_GETUPVAL:
111 | case OP_SETUPVAL:
112 | printf("\t; %s", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : "-");
113 | break;
114 | case OP_GETGLOBAL:
115 | case OP_SETGLOBAL:
116 | printf("\t; %s",svalue(&f->k[bx]));
117 | break;
118 | case OP_GETTABLE:
119 | case OP_SELF:
120 | if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); }
121 | break;
122 | case OP_SETTABLE:
123 | case OP_ADD:
124 | case OP_SUB:
125 | case OP_MUL:
126 | case OP_DIV:
127 | case OP_POW:
128 | case OP_EQ:
129 | case OP_LT:
130 | case OP_LE:
131 | if (ISK(b) || ISK(c))
132 | {
133 | printf("\t; ");
134 | if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-");
135 | printf(" ");
136 | if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-");
137 | }
138 | break;
139 | case OP_JMP:
140 | case OP_FORLOOP:
141 | case OP_FORPREP:
142 | printf("\t; to %d",sbx+pc+2);
143 | break;
144 | case OP_CLOSURE:
145 | printf("\t; %p",VOID(f->p[bx]));
146 | break;
147 | case OP_SETLIST:
148 | if (c==0) printf("\t; %d",(int)code[++pc]);
149 | else printf("\t; %d",c);
150 | break;
151 | default:
152 | break;
153 | }
154 | printf("\n");
155 | }
156 | }
157 |
158 | #define SS(x) (x==1)?"":"s"
159 | #define S(x) x,SS(x)
160 |
161 | static void PrintHeader(const Proto* f)
162 | {
163 | const char* s=getstr(f->source);
164 | if (*s=='@' || *s=='=')
165 | s++;
166 | else if (*s==LUA_SIGNATURE[0])
167 | s="(bstring)";
168 | else
169 | s="(string)";
170 | printf("\n%s <%s:%d,%d> (%d instruction%s, %d bytes at %p)\n",
171 | (f->linedefined==0)?"main":"function",s,
172 | f->linedefined,f->lastlinedefined,
173 | S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f));
174 | printf("%d%s param%s, %d slot%s, %d upvalue%s, ",
175 | f->numparams,f->is_vararg?"+":"",SS(f->numparams),
176 | S(f->maxstacksize),S(f->nups));
177 | printf("%d local%s, %d constant%s, %d function%s\n",
178 | S(f->sizelocvars),S(f->sizek),S(f->sizep));
179 | }
180 |
181 | static void PrintConstants(const Proto* f)
182 | {
183 | int i,n=f->sizek;
184 | printf("constants (%d) for %p:\n",n,VOID(f));
185 | for (i=0; isizelocvars;
196 | printf("locals (%d) for %p:\n",n,VOID(f));
197 | for (i=0; ilocvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1);
201 | }
202 | }
203 |
204 | static void PrintUpvalues(const Proto* f)
205 | {
206 | int i,n=f->sizeupvalues;
207 | printf("upvalues (%d) for %p:\n",n,VOID(f));
208 | if (f->upvalues==NULL) return;
209 | for (i=0; iupvalues[i]));
212 | }
213 | }
214 |
215 | void PrintFunction(const Proto* f, int full)
216 | {
217 | int i,n=f->sizep;
218 | PrintHeader(f);
219 | PrintCode(f);
220 | if (full)
221 | {
222 | PrintConstants(f);
223 | PrintLocals(f);
224 | PrintUpvalues(f);
225 | }
226 | for (i=0; ip[i],full);
227 | }
228 |
--------------------------------------------------------------------------------
/src/tags:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lichuang/Lua-5.1.4-codedump/7e5a0089d4a3199318230c2832c3e5c103f55437/src/tags
--------------------------------------------------------------------------------
/test/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | gcc -g -o test.o -c test.c
3 | gcc -g -o test test.o -rdynamic -llua -ldl -lm
4 | gcc -g -o testusrdata.o -c testusrdata.c
5 | gcc -g -o testusrdata testusrdata.o -rdynamic -llua -ldl -lm
6 |
7 | clean:
8 | rm test test.o
9 |
--------------------------------------------------------------------------------
/test/README:
--------------------------------------------------------------------------------
1 | These are simple tests for Lua. Some of them contain useful code.
2 | They are meant to be run to make sure Lua is built correctly and also
3 | to be read, to see how Lua programs look.
4 |
5 | Here is a one-line summary of each program:
6 |
7 | bisect.lua bisection method for solving non-linear equations
8 | cf.lua temperature conversion table (celsius to farenheit)
9 | echo.lua echo command line arguments
10 | env.lua environment variables as automatic global variables
11 | factorial.lua factorial without recursion
12 | fib.lua fibonacci function with cache
13 | fibfor.lua fibonacci numbers with coroutines and generators
14 | globals.lua report global variable usage
15 | hello.lua the first program in every language
16 | life.lua Conway's Game of Life
17 | luac.lua bare-bones luac
18 | printf.lua an implementation of printf
19 | readonly.lua make global variables readonly
20 | sieve.lua the sieve of of Eratosthenes programmed with coroutines
21 | sort.lua two implementations of a sort function
22 | table.lua make table, grouping all data for the same item
23 | trace-calls.lua trace calls
24 | trace-globals.lua trace assigments to global variables
25 | xd.lua hex dump
26 |
27 |
--------------------------------------------------------------------------------
/test/bisect.lua:
--------------------------------------------------------------------------------
1 | -- bisection method for solving non-linear equations
2 |
3 | delta=1e-6 -- tolerance
4 |
5 | function bisect(f,a,b,fa,fb)
6 | local c=(a+b)/2
7 | io.write(n," c=",c," a=",a," b=",b,"\n")
8 | if c==a or c==b or math.abs(a-b)y end)
58 | show("after reverse selection sort",x)
59 | qsort(x,1,n,function (x,y) return x
2 | #include
3 | #include
4 | #include
5 |
6 | int main(int argc, char *argv[]) {
7 | char *file = NULL;
8 | if (argc == 1) {
9 | file = "my.lua";
10 | } else {
11 | file = argv[1];
12 | }
13 |
14 | lua_State *L = lua_open();
15 | luaL_openlibs(L);
16 | luaL_dofile(L, file);
17 |
18 | return 0;
19 | }
20 |
--------------------------------------------------------------------------------
/test/testusrdata.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #define BITS_PER_WORD (CHAR_BIT * sizeof(int))
7 | #define I_WORD(i) ((unsigned int)(i))/BITS_PER_WORD
8 | #define I_BIT(i) (1 << ((unsigned int)(i)%BITS_PER_WORD))
9 |
10 | typedef struct NumArray {
11 | int size;
12 | unsigned int values[1];
13 | } NumArray;
14 |
15 | int newArray(lua_State* L)
16 | {
17 | //1. 检查第一个参数是否为整型。以及该参数的值是否大于等于1.
18 | int n = luaL_checkint(L,1);
19 | int i;
20 | luaL_argcheck(L, n >= 1, 1, "invalid size.");
21 | size_t nbytes = sizeof(NumArray) + I_WORD(n - 1) * sizeof(int);
22 | //2. 参数表示Lua为userdata分配的字节数。同时将分配后的userdata对象压入栈中。
23 | NumArray* a = (NumArray*)lua_newuserdata(L,nbytes);
24 | a->size = n;
25 | for (i = 0; i < I_WORD(n - 1); ++i)
26 | a->values[i] = 0;
27 | //获取注册表变量myarray,该key的值为metatable。
28 | luaL_getmetatable(L,"myarray");
29 | //将userdata的元表设置为和myarray关联的table。同时将栈顶元素弹出。
30 | lua_setmetatable(L,-2);
31 | return 1;
32 | }
33 |
34 | int setArray(lua_State* L)
35 | {
36 | //1. Lua传给该函数的第一个参数必须是userdata,该对象的元表也必须是注册表中和myarray关联的table。
37 | //否则该函数报错并终止程序。
38 | NumArray* a = (NumArray*)luaL_checkudata(L,1,"myarray");
39 | int index = luaL_checkint(L,2) - 1;
40 | //2. 由于任何类型的数据都可以成为布尔值,因此这里使用any只是为了确保有3个参数。
41 | luaL_checkany(L,3);
42 | luaL_argcheck(L,a != NULL,1,"'array' expected.");
43 | luaL_argcheck(L,0 <= index && index < a->size,2,"index out of range.");
44 | if (lua_toboolean(L,3))
45 | a->values[I_WORD(index)] |= I_BIT(index);
46 | else
47 | a->values[I_WORD(index)] &= ~I_BIT(index);
48 | return 0;
49 | }
50 |
51 | int getArray(lua_State* L)
52 | {
53 | NumArray* a = (NumArray*)luaL_checkudata(L,1,"myarray");
54 | int index = luaL_checkint(L,2) - 1;
55 | luaL_argcheck(L, a != NULL, 1, "'array' expected.");
56 | luaL_argcheck(L, 0 <= index && index < a->size,2,"index out of range");
57 | lua_pushboolean(L,a->values[I_WORD(index)] & I_BIT(index));
58 | return 1;
59 | }
60 |
61 | int getSize(lua_State* L)
62 | {
63 | NumArray* a = (NumArray*)luaL_checkudata(L,1,"myarray");
64 | luaL_argcheck(L,a != NULL,1,"'array' expected.");
65 | lua_pushinteger(L,a->size);
66 | return 1;
67 | }
68 |
69 | int array2string(lua_State* L)
70 | {
71 | NumArray* a = (NumArray*)luaL_checkudata(L,1,"myarray");
72 | lua_pushfstring(L,"array(%d)",a->size);
73 | return 1;
74 | }
75 |
76 | static luaL_Reg arraylib_f [] = {
77 | {"new", newArray},
78 | {NULL, NULL}
79 | };
80 |
81 | static luaL_Reg arraylib_m [] = {
82 | {"set", setArray},
83 | {"get", getArray},
84 | {"size", getSize},
85 | {"__tostring", array2string}, //print(a)时Lua会调用该元方法。
86 | {NULL, NULL}
87 | };
88 |
89 | int luaopen_testuserdata(lua_State* L)
90 | {
91 | //1. 创建元表,并将该元表指定给newArray函数新创建的userdata。在Lua中userdata也是以table的身份表现的。
92 | //这样在调用对象函数时,可以通过验证其metatable的名称来确定参数userdata是否合法。
93 | luaL_newmetatable(L,"myarray");
94 | lua_pushvalue(L,-1);
95 | //2. 为了实现面对对象的调用方式,需要将元表的__index字段指向自身,同时再将arraylib_m数组中的函数注册到
96 | //元表中,之后基于这些注册函数的调用就可以以面向对象的形式调用了。
97 | //lua_setfield在执行后会将栈顶的table弹出。
98 | lua_setfield(L,-2,"__index");
99 | //将这些成员函数注册给元表,以保证Lua在寻找方法时可以定位。NULL参数表示将用栈顶的table代替第二个参数。
100 | luaL_register(L,NULL,arraylib_m);
101 | //这里只注册的工厂方法。
102 | luaL_register(L,"testuserdata",arraylib_f);
103 | return 1;
104 | }
105 |
106 | int main(){
107 | char *file = NULL;
108 | file = "my.lua";
109 |
110 | lua_State *L = lua_open();
111 | luaL_openlibs(L);
112 | luaopen_testuserdata(L);
113 | if (luaL_dofile(L, file)) {
114 | printf("error: %s\n", lua_tostring(L, -1));
115 | }
116 |
117 | return 0;
118 | }
119 |
120 |
--------------------------------------------------------------------------------
/test/trace-calls.lua:
--------------------------------------------------------------------------------
1 | -- trace calls
2 | -- example: lua -ltrace-calls bisect.lua
3 |
4 | local level=0
5 |
6 | local function hook(event)
7 | local t=debug.getinfo(3)
8 | io.write(level," >>> ",string.rep(" ",level))
9 | if t~=nil and t.currentline>=0 then io.write(t.short_src,":",t.currentline," ") end
10 | t=debug.getinfo(2)
11 | if event=="call" then
12 | level=level+1
13 | else
14 | level=level-1 if level<0 then level=0 end
15 | end
16 | if t.what=="main" then
17 | if event=="call" then
18 | io.write("begin ",t.short_src)
19 | else
20 | io.write("end ",t.short_src)
21 | end
22 | elseif t.what=="Lua" then
23 | -- table.foreach(t,print)
24 | io.write(event," ",t.name or "(Lua)"," <",t.linedefined,":",t.short_src,">")
25 | else
26 | io.write(event," ",t.name or "(C)"," [",t.what,"] ")
27 | end
28 | io.write("\n")
29 | end
30 |
31 | debug.sethook(hook,"cr")
32 | level=0
33 |
--------------------------------------------------------------------------------
/test/trace-globals.lua:
--------------------------------------------------------------------------------
1 | -- trace assigments to global variables
2 |
3 | do
4 | -- a tostring that quotes strings. note the use of the original tostring.
5 | local _tostring=tostring
6 | local tostring=function(a)
7 | if type(a)=="string" then
8 | return string.format("%q",a)
9 | else
10 | return _tostring(a)
11 | end
12 | end
13 |
14 | local log=function (name,old,new)
15 | local t=debug.getinfo(3,"Sl")
16 | local line=t.currentline
17 | io.write(t.short_src)
18 | if line>=0 then io.write(":",line) end
19 | io.write(": ",name," is now ",tostring(new)," (was ",tostring(old),")","\n")
20 | end
21 |
22 | local g={}
23 | local set=function (t,name,value)
24 | log(name,g[name],value)
25 | g[name]=value
26 | end
27 | setmetatable(getfenv(),{__index=g,__newindex=set})
28 | end
29 |
30 | -- an example
31 |
32 | a=1
33 | b=2
34 | a=10
35 | b=20
36 | b=nil
37 | b=200
38 | print(a,b,c)
39 |
--------------------------------------------------------------------------------
/test/xd.lua:
--------------------------------------------------------------------------------
1 | -- hex dump
2 | -- usage: lua xd.lua < file
3 |
4 | local offset=0
5 | while true do
6 | local s=io.read(16)
7 | if s==nil then return end
8 | io.write(string.format("%08X ",offset))
9 | string.gsub(s,"(.)",
10 | function (c) io.write(string.format("%02X ",string.byte(c))) end)
11 | io.write(string.rep(" ",3*(16-string.len(s))))
12 | io.write(" ",string.gsub(s,"%c","."),"\n")
13 | offset=offset+16
14 | end
15 |
--------------------------------------------------------------------------------