-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathlapi.c
1468 lines (1252 loc) · 35.6 KB
/
lapi.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
** $Id: lapi.c,v 2.259.1.2 2017/12/06 18:35:12 roberto Exp $
** Lua API
** C语言接口
** See Copyright Notice in lua.h
*/
#define lapi_c
#define LUA_CORE
#include "lprefix.h"
#include <stdarg.h>
#include <string.h>
#include "lua.h"
#include "lapi.h"
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lundump.h"
#include "lvm.h"
const char lua_ident[] =
"$LuaVersion: " LUA_COPYRIGHT " $"
"$LuaAuthors: " LUA_AUTHORS " $";
/* value at a non-valid index */
#define NONVALIDVALUE cast(TValue *, luaO_nilobject)
/* corresponding test */
#define isvalid(o) ((o) != luaO_nilobject)
/* test for pseudo index */
#define ispseudo(i) ((i) <= LUA_REGISTRYINDEX)
/* test for upvalue */
#define isupvalue(i) ((i) < LUA_REGISTRYINDEX)
/* test for valid but not pseudo index */
#define isstackindex(i, o) (isvalid(o) && !ispseudo(i))
#define api_checkvalidindex(l,o) api_check(l, isvalid(o), "invalid index")
#define api_checkstackindex(l, i, o) \
api_check(l, isstackindex(i, o), "index not in the stack")
/*
** 通过指定索引值idx,寻找调用栈上L->top的栈分片TValue值
** idx > 0 - 从操作栈底部开始寻找值
** idx < 0 - 从操作栈栈顶开始寻找值
*/
static TValue *index2addr (lua_State *L, int idx) {
CallInfo *ci = L->ci;
/* idx > 0 - 从操作栈底部开始寻找值 */
if (idx > 0) {
TValue *o = ci->func + idx;
api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index");
if (o >= L->top) return NONVALIDVALUE;
else return o;
}
else if (!ispseudo(idx)) { /* negative index */
api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index");
return L->top + idx;
}
else if (idx == LUA_REGISTRYINDEX)
return &G(L)->l_registry;
else { /* upvalues */
/* idx < 0 - 从操作栈栈顶开始寻找值 */
idx = LUA_REGISTRYINDEX - idx;
api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large");
if (ttislcf(ci->func)) /* light C function? */
return NONVALIDVALUE; /* it has no upvalues */
else {
CClosure *func = clCvalue(ci->func);
return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE;
}
}
}
/*
** to be called by 'lua_checkstack' in protected mode, to grow stack
** capturing memory errors
** 针对lua_State进行扩容
*/
static void growstack (lua_State *L, void *ud) {
int size = *(int *)ud;
luaD_growstack(L, size);
}
/*
** 检查lua_State的大小(默认大小为35),如果栈小了,则扩容
** 只会不断扩容,不会缩小
** 32位/64位机器栈最大为1000000
** 16位机器栈最大为15000
** 对于需要在循环中不断压入元素的操作,应该调用lua_checkstack用于检查每次的栈大小
*/
LUA_API int lua_checkstack (lua_State *L, int n) {
int res;
CallInfo *ci = L->ci;
lua_lock(L);
api_check(L, n >= 0, "negative 'n'");
if (L->stack_last - L->top > n) /* stack large enough? */
res = 1; /* yes; check is OK */
else { /* no; need to grow stack */
int inuse = cast_int(L->top - L->stack) + EXTRA_STACK;
if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */
res = 0; /* no */
else /* try to grow stack - 尝试扩容 */
res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK);
}
if (res && ci->top < L->top + n)
ci->top = L->top + n; /* adjust frame top */
lua_unlock(L);
return res;
}
/*
** 从*from虚拟机结构上向*to虚拟机结构上拷贝n个栈分片内容
*/
LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
int i;
if (from == to) return;
lua_lock(to);
api_checknelems(from, n);
api_check(from, G(from) == G(to), "moving among independent states");
api_check(from, to->ci->top - to->top >= n, "stack overflow");
from->top -= n;
for (i = 0; i < n; i++) {
setobj2s(to, to->top, from->top + i);
to->top++; /* stack already checked by previous 'api_check' */
}
lua_unlock(to);
}
LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
lua_CFunction old;
lua_lock(L);
old = G(L)->panic;
G(L)->panic = panicf;
lua_unlock(L);
return old;
}
LUA_API const lua_Number *lua_version (lua_State *L) {
static const lua_Number version = LUA_VERSION_NUM;
if (L == NULL) return &version;
else return G(L)->version;
}
/*
** basic stack manipulation
*/
/*
** convert an acceptable stack index into an absolute index
*/
LUA_API int lua_absindex (lua_State *L, int idx) {
return (idx > 0 || ispseudo(idx))
? idx
: cast_int(L->top - L->ci->func) + idx;
}
/*
** 返回Lua栈的个数
** 同时也是栈顶元素的索引,因为栈底是1
*/
LUA_API int lua_gettop (lua_State *L) {
return cast_int(L->top - (L->ci->func + 1));
}
/*
** 设置栈的高度
** 如果之前的栈顶比新设置的更高,那么高出来的元素会被丢弃,反之压入nil来补足大小
*/
LUA_API void lua_settop (lua_State *L, int idx) {
StkId func = L->ci->func;
lua_lock(L);
if (idx >= 0) {
api_check(L, idx <= L->stack_last - (func + 1), "new top too large");
while (L->top < (func + 1) + idx)
setnilvalue(L->top++);
L->top = (func + 1) + idx;
}
else {
api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top");
L->top += idx+1; /* 'subtract' index (index is negative) */
}
lua_unlock(L);
}
/*
** Reverse the stack segment from 'from' to 'to'
** (auxiliary to 'lua_rotate')
*/
static void reverse (lua_State *L, StkId from, StkId to) {
for (; from < to; from++, to--) {
TValue temp;
setobj(L, &temp, from);
setobjs2s(L, from, to);
setobj2s(L, to, &temp);
}
}
/*
** Let x = AB, where A is a prefix of length 'n'. Then,
** rotate x n == BA. But BA == (A^r . B^r)^r.
*/
LUA_API void lua_rotate (lua_State *L, int idx, int n) {
StkId p, t, m;
lua_lock(L);
t = L->top - 1; /* end of stack segment being rotated */
p = index2addr(L, idx); /* start of segment */
api_checkstackindex(L, idx, p);
api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'");
m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */
reverse(L, p, m); /* reverse the prefix with length 'n' */
reverse(L, m + 1, t); /* reverse the suffix */
reverse(L, p, t); /* reverse the entire segment */
lua_unlock(L);
}
LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) {
TValue *fr, *to;
lua_lock(L);
fr = index2addr(L, fromidx);
to = index2addr(L, toidx);
api_checkvalidindex(L, to);
setobj(L, to, fr);
if (isupvalue(toidx)) /* function upvalue? */
luaC_barrier(L, clCvalue(L->ci->func), fr);
/* LUA_REGISTRYINDEX does not need gc barrier
(collector revisits it before finishing collection) */
lua_unlock(L);
}
LUA_API void lua_pushvalue (lua_State *L, int idx) {
lua_lock(L);
setobj2s(L, L->top, index2addr(L, idx));
api_incr_top(L);
lua_unlock(L);
}
/*
** access functions (stack -> C)
*/
/*
** 类型
*/
LUA_API int lua_type (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
return (isvalid(o) ? ttnov(o) : LUA_TNONE);
}
/*
** 类型枚举转成类型名称
*/
LUA_API const char *lua_typename (lua_State *L, int t) {
UNUSED(L);
api_check(L, LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag");
return ttypename(t);
}
/*
** 判断是否为函数
*/
LUA_API int lua_iscfunction (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
return (ttislcf(o) || (ttisCclosure(o)));
}
/*
** 判断是否为整型
*/
LUA_API int lua_isinteger (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
return ttisinteger(o);
}
/*
** 判断是否为浮点数
*/
LUA_API int lua_isnumber (lua_State *L, int idx) {
lua_Number n;
const TValue *o = index2addr(L, idx);
return tonumber(o, &n);
}
/*
** 判断是否为字符串
*/
LUA_API int lua_isstring (lua_State *L, int idx) {
const TValue *o = index2addr(L, idx);
return (ttisstring(o) || cvt2str(o));
}
/*
** 判断是否为用户数据
*/
LUA_API int lua_isuserdata (lua_State *L, int idx) {
const TValue *o = index2addr(L, idx);
return (ttisfulluserdata(o) || ttislightuserdata(o));
}
/*
** 判断两个索引对应的值是否一样,如果一样返回1,否则返回0
*/
LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
StkId o1 = index2addr(L, index1);
StkId o2 = index2addr(L, index2);
return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0;
}
LUA_API void lua_arith (lua_State *L, int op) {
lua_lock(L);
if (op != LUA_OPUNM && op != LUA_OPBNOT)
api_checknelems(L, 2); /* all other operations expect two operands */
else { /* for unary operations, add fake 2nd operand */
api_checknelems(L, 1);
setobjs2s(L, L->top, L->top - 1);
api_incr_top(L);
}
/* first operand at top - 2, second at top - 1; result go to top - 2 */
luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2);
L->top--; /* remove second operand */
lua_unlock(L);
}
LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {
StkId o1, o2;
int i = 0;
lua_lock(L); /* may call tag method */
o1 = index2addr(L, index1);
o2 = index2addr(L, index2);
if (isvalid(o1) && isvalid(o2)) {
switch (op) {
case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break;
case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break;
case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break;
default: api_check(L, 0, "invalid option");
}
}
lua_unlock(L);
return i;
}
LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) {
size_t sz = luaO_str2num(s, L->top);
if (sz != 0)
api_incr_top(L);
return sz;
}
/*
** Lua从栈上获取数据,主要通过index2addr函数,寻找到操作栈CallInfo上的栈指针地址,然后获取数据
** idx > 0 - 从操作栈底部开始寻找值
** idx < 0 - 从操作栈栈顶开始寻找值
*/
/*
** 将索引处的值转换为lua_Number类型
*/
LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) {
lua_Number n;
const TValue *o = index2addr(L, idx);
int isnum = tonumber(o, &n);
if (!isnum)
n = 0; /* call to 'tonumber' may change 'n' even if it fails */
if (pisnum) *pisnum = isnum;
return n;
}
/*
** 将索引处的值转换为lua_Integer类型
** 必须为数字/字符串类型数字
*/
LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) {
lua_Integer res;
const TValue *o = index2addr(L, idx);
int isnum = tointeger(o, &res);
if (!isnum)
res = 0; /* call to 'tointeger' may change 'n' even if it fails */
if (pisnum) *pisnum = isnum;
return res;
}
/*
** 将索引处的值转换为boolean(0或1)
** 会把任何不同于false和nil的值当做1返回,否则就返回0
** 如果用一个无效索引去调用也会返回0
*/
LUA_API int lua_toboolean (lua_State *L, int idx) {
const TValue *o = index2addr(L, idx);
return !l_isfalse(o);
}
/*
** 将索引处的值转换为C字符串
** 如果len不为NULL,还把字符串长度设置到*len,
** 必须是一个字符串或者一个数字,否则返回NULL
** 如果是一个数字,还会将栈中的那个值的实际类型转换为一个字符串
*/
LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
StkId o = index2addr(L, idx);
if (!ttisstring(o)) {
if (!cvt2str(o)) { /* not convertible? */
if (len != NULL) *len = 0;
return NULL;
}
lua_lock(L); /* 'luaO_tostring' may create a new string */
luaO_tostring(L, o);
luaC_checkGC(L);
o = index2addr(L, idx); /* previous call may reallocate the stack */
lua_unlock(L);
}
if (len != NULL)
*len = vslen(o);
return svalue(o);
}
LUA_API size_t lua_rawlen (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
switch (ttype(o)) {
case LUA_TSHRSTR: return tsvalue(o)->shrlen;
case LUA_TLNGSTR: return tsvalue(o)->u.lnglen;
case LUA_TUSERDATA: return uvalue(o)->len;
case LUA_TTABLE: return luaH_getn(hvalue(o));
default: return 0;
}
}
/*
** 将索引处的值转换为C函数
*/
LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
if (ttislcf(o)) return fvalue(o);
else if (ttisCclosure(o))
return clCvalue(o)->f;
else return NULL; /* not a C function */
}
/*
** 将索引处的值转换为用户数据
*/
LUA_API void *lua_touserdata (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
switch (ttnov(o)) {
case LUA_TUSERDATA: return getudatamem(uvalue(o));
case LUA_TLIGHTUSERDATA: return pvalue(o);
default: return NULL;
}
}
/*
** 将索引处的值转换为Lua线程(由lua_State*代表)
** 这个值必须是一个线程,否则函数返回NULL
*/
LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
return (!ttisthread(o)) ? NULL : thvalue(o);
}
/*
** 将索引处的值转换为一般的C指针(void*)
** 这个值可以是一个userdata,table,thread或者function
*/
LUA_API const void *lua_topointer (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
switch (ttype(o)) {
case LUA_TTABLE: return hvalue(o);
case LUA_TLCL: return clLvalue(o);
case LUA_TCCL: return clCvalue(o);
case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o)));
case LUA_TTHREAD: return thvalue(o);
case LUA_TUSERDATA: return getudatamem(uvalue(o));
case LUA_TLIGHTUSERDATA: return pvalue(o);
default: return NULL;
}
}
/*
** push functions (C -> stack)
*/
/*
** 压入一个nil到栈L->top上
*/
LUA_API void lua_pushnil (lua_State *L) {
lua_lock(L);
setnilvalue(L->top);
api_incr_top(L);
lua_unlock(L);
}
/*
** 压入一个浮点数到栈L->top上
*/
LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
lua_lock(L);
setfltvalue(L->top, n);
api_incr_top(L);
lua_unlock(L);
}
/*
** 压入一个整数到栈L->top上
*/
LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
lua_lock(L);
setivalue(L->top, n);
api_incr_top(L);
lua_unlock(L);
}
/*
** Pushes on the stack a string with given length. Avoid using 's' when
** 'len' == 0 (as 's' can be NULL in that case), due to later use of
** 'memcmp' and 'memcpy'.
** 压入一个字符串到栈L->top上
*/
LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) {
TString *ts;
lua_lock(L);
ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len);
setsvalue2s(L, L->top, ts);
api_incr_top(L);
luaC_checkGC(L);
lua_unlock(L);
return getstr(ts);
}
/*
** Lua针对需要垃圾回收的元素,在压入栈时,都会在Lua(也就是Lua虚拟机中)生成一个副本
** C里面的值,在被压入栈时,Lua不会再依赖这个值,而是通过拷贝副本的方式,自己管理对应的值
** 以lua_pushstring为例,压入一个字符串值时,会将字符串生成一个内部副本
** Lua不会持有指向外部字符串的指针,也不会持有任何其他外部对象的指针(除了C函数,因为C函数总是静态的)
** 压入一个字符串到栈L->top上
*/
LUA_API const char *lua_pushstring (lua_State *L, const char *s) {
lua_lock(L);
if (s == NULL)
setnilvalue(L->top);
else {
TString *ts;
ts = luaS_new(L, s); /* 拷贝一个副本 */
setsvalue2s(L, L->top, ts);
s = getstr(ts); /* internal copy's address */
}
api_incr_top(L);
luaC_checkGC(L);
lua_unlock(L);
return s;
}
/*
** 压入一个字符串到栈L->top上
*/
LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
va_list argp) {
const char *ret;
lua_lock(L);
ret = luaO_pushvfstring(L, fmt, argp);
luaC_checkGC(L);
lua_unlock(L);
return ret;
}
/*
** 压入一个字符串到栈L->top上
*/
LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
const char *ret;
va_list argp;
lua_lock(L);
va_start(argp, fmt);
ret = luaO_pushvfstring(L, fmt, argp);
va_end(argp);
luaC_checkGC(L);
lua_unlock(L);
return ret;
}
/*
** 压入一个C闭包函数到栈L->top上
*/
LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
lua_lock(L);
if (n == 0) {
setfvalue(L->top, fn);
api_incr_top(L);
}
else {
CClosure *cl;
api_checknelems(L, n);
api_check(L, n <= MAXUPVAL, "upvalue index too large");
cl = luaF_newCclosure(L, n);
cl->f = fn;
L->top -= n;
while (n--) {
setobj2n(L, &cl->upvalue[n], L->top + n);
/* does not need barrier because closure is white */
}
setclCvalue(L, L->top, cl);
api_incr_top(L);
luaC_checkGC(L);
}
lua_unlock(L);
}
/*
** 压入一个布尔值到栈L->top上
*/
LUA_API void lua_pushboolean (lua_State *L, int b) {
lua_lock(L);
setbvalue(L->top, (b != 0)); /* ensure that true is 1 */
api_incr_top(L);
lua_unlock(L);
}
/*
** 压入一个轻量用户数据到栈L->top上
*/
LUA_API void lua_pushlightuserdata (lua_State *L, void *p) {
lua_lock(L);
setpvalue(L->top, p);
api_incr_top(L);
lua_unlock(L);
}
/*
** 压入一个线程到栈L->top上
** Lua线程不是OS线程,是协程
*/
LUA_API int lua_pushthread (lua_State *L) {
lua_lock(L);
setthvalue(L, L->top, L);
api_incr_top(L);
lua_unlock(L);
return (G(L)->mainthread == L);
}
/*
** get functions (Lua -> stack)
*/
static int auxgetstr (lua_State *L, const TValue *t, const char *k) {
const TValue *slot;
TString *str = luaS_new(L, k);
if (luaV_fastget(L, t, str, slot, luaH_getstr)) {
setobj2s(L, L->top, slot);
api_incr_top(L);
}
else {
setsvalue2s(L, L->top, str);
api_incr_top(L);
luaV_finishget(L, t, L->top - 1, L->top - 1, slot);
}
lua_unlock(L);
return ttnov(L->top - 1);
}
/*
** 从全局注册表中,获取一个T[name]的值,放入L->top
*/
LUA_API int lua_getglobal (lua_State *L, const char *name) {
Table *reg = hvalue(&G(L)->l_registry);
lua_lock(L);
return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name);
}
/*
** 从Table表中,获取一个T[name]的值,放入L->top
*/
LUA_API int lua_gettable (lua_State *L, int idx) {
StkId t;
lua_lock(L);
t = index2addr(L, idx);
luaV_gettable(L, t, L->top - 1, L->top - 1);
lua_unlock(L);
return ttnov(L->top - 1);
}
/*
** lua_getfield函数主要用于向Table获取值
** L - 当前执行环境栈
** idx - Table的索引值,如果是全局注册表,则idx = LUA_REGISTRYINDEX,
** 如果是栈上的一个Table表,则数字索引,
** 通过index2addr方法寻找栈对象
** k - Table的索引键
** 从T[k]上取到一个值,并将值放置到L->top栈顶上,并调整栈顶(L->top++)
** 操作注册表,实践上就是操作一个特殊的Table结构
*/
LUA_API int lua_getfield (lua_State *L, int idx, const char *k) {
lua_lock(L);
return auxgetstr(L, index2addr(L, idx), k);
}
/*
** 通过数组下标获取T[i]的值,并将值放入栈顶L->top
*/
LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
StkId t;
const TValue *slot;
lua_lock(L);
t = index2addr(L, idx);
if (luaV_fastget(L, t, n, slot, luaH_getint)) { /* 如果找到值,则压入栈顶 */
setobj2s(L, L->top, slot);
api_incr_top(L);
}
else { /* 找不到的情况下 */
setivalue(L->top, n);
api_incr_top(L);
luaV_finishget(L, t, L->top - 1, L->top - 1, slot);
}
lua_unlock(L);
return ttnov(L->top - 1);
}
LUA_API int lua_rawget (lua_State *L, int idx) {
StkId t;
lua_lock(L);
t = index2addr(L, idx);
api_check(L, ttistable(t), "table expected");
setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
lua_unlock(L);
return ttnov(L->top - 1);
}
LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) {
StkId t;
lua_lock(L);
t = index2addr(L, idx);
api_check(L, ttistable(t), "table expected");
setobj2s(L, L->top, luaH_getint(hvalue(t), n));
api_incr_top(L);
lua_unlock(L);
return ttnov(L->top - 1);
}
LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
StkId t;
TValue k;
lua_lock(L);
t = index2addr(L, idx);
api_check(L, ttistable(t), "table expected");
setpvalue(&k, cast(void *, p));
setobj2s(L, L->top, luaH_get(hvalue(t), &k));
api_incr_top(L);
lua_unlock(L);
return ttnov(L->top - 1);
}
/*
** 创建一个table,固定长度,并将之放在栈顶
** narray是该table数组部分的长度
** nrec是该tableHash部分的长度
*/
LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
Table *t;
lua_lock(L);
t = luaH_new(L);
sethvalue(L, L->top, t);
api_incr_top(L);
if (narray > 0 || nrec > 0)
luaH_resize(L, t, narray, nrec);
luaC_checkGC(L);
lua_unlock(L);
}
LUA_API int lua_getmetatable (lua_State *L, int objindex) {
const TValue *obj;
Table *mt;
int res = 0;
lua_lock(L);
obj = index2addr(L, objindex);
switch (ttnov(obj)) {
case LUA_TTABLE:
mt = hvalue(obj)->metatable;
break;
case LUA_TUSERDATA:
mt = uvalue(obj)->metatable;
break;
default:
mt = G(L)->mt[ttnov(obj)];
break;
}
if (mt != NULL) {
sethvalue(L, L->top, mt);
api_incr_top(L);
res = 1;
}
lua_unlock(L);
return res;
}
LUA_API int lua_getuservalue (lua_State *L, int idx) {
StkId o;
lua_lock(L);
o = index2addr(L, idx);
api_check(L, ttisfulluserdata(o), "full userdata expected");
getuservalue(L, uvalue(o), L->top);
api_incr_top(L);
lua_unlock(L);
return ttnov(L->top - 1);
}
/*
** set functions (stack -> Lua)
*/
/*
** t[k] = value at the top of the stack (where 'k' is a string)
*/
static void auxsetstr (lua_State *L, const TValue *t, const char *k) {
const TValue *slot;
TString *str = luaS_new(L, k);
api_checknelems(L, 1);
if (luaV_fastset(L, t, str, slot, luaH_getstr, L->top - 1))
L->top--; /* pop value */
else {
setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */
api_incr_top(L);
luaV_finishset(L, t, L->top - 1, L->top - 2, slot);
L->top -= 2; /* pop value and key */
}
lua_unlock(L); /* lock done by caller */
}
/*
** 将栈顶的值,设置到全局变量中去,以LUA_RIDX_GLOBALS[name] = L->top,
** 并调整栈顶L->top(L->top--),pop弹出栈顶值
*/
LUA_API void lua_setglobal (lua_State *L, const char *name) {
Table *reg = hvalue(&G(L)->l_registry);
lua_lock(L); /* unlock done in 'auxsetstr' */
auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name);
}
/*
** 将栈顶的值,设置到Table中去,并调整栈顶L->top(L->top-2),pop弹出栈顶值
*/
LUA_API void lua_settable (lua_State *L, int idx) {
StkId t;
lua_lock(L);
api_checknelems(L, 2);
t = index2addr(L, idx);
luaV_settable(L, t, L->top - 2, L->top - 1);
L->top -= 2; /* pop index and value */
lua_unlock(L);
}
/*
** lua_setfield函数主要用于向Table设置值
** L - 当前执行环境栈
** idx - Talbe的索引值,如果是全局注册表,则idx = LUA_REGISTRYINDEX,
** 如果是在栈上的一个Table表,则数字索引,
** 通过index2addr方法寻找栈对象
** k - Table的索引键
** 将栈顶L->top的值,赋值到T[k],并弹出栈顶值(L->top)
** 操作注册表,实际上就是操作一个特殊的Table结构
*/
LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
lua_lock(L); /* unlock done in 'auxsetstr' */
auxsetstr(L, index2addr(L, idx), k);
}
LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
StkId t;
const TValue *slot;
lua_lock(L);
api_checknelems(L, 1);
t = index2addr(L, idx);
if (luaV_fastset(L, t, n, slot, luaH_getint, L->top - 1))
L->top--; /* pop value */
else {
setivalue(L->top, n);
api_incr_top(L);
luaV_finishset(L, t, L->top - 1, L->top - 2, slot);
L->top -= 2; /* pop value and key */
}
lua_unlock(L);
}
LUA_API void lua_rawset (lua_State *L, int idx) {
StkId o;
TValue *slot;
lua_lock(L);
api_checknelems(L, 2);
o = index2addr(L, idx);
api_check(L, ttistable(o), "table expected");
slot = luaH_set(L, hvalue(o), L->top - 2);
setobj2t(L, slot, L->top - 1);
invalidateTMcache(hvalue(o));
luaC_barrierback(L, hvalue(o), L->top-1);
L->top -= 2;
lua_unlock(L);
}
LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) {
StkId o;
lua_lock(L);
api_checknelems(L, 1);
o = index2addr(L, idx);
api_check(L, ttistable(o), "table expected");
luaH_setint(L, hvalue(o), n, L->top - 1);
luaC_barrierback(L, hvalue(o), L->top-1);
L->top--;
lua_unlock(L);
}
LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) {
StkId o;
TValue k, *slot;
lua_lock(L);
api_checknelems(L, 1);