mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-23 11:33:09 +00:00
Compare commits
426 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ee85a91f9 | ||
|
|
8a3a0c1b71 | ||
|
|
b4752f2394 | ||
|
|
f110b51290 | ||
|
|
e0f16b8df5 | ||
|
|
08e56f4316 | ||
|
|
7e57e498f6 | ||
|
|
98b5c7c7c6 | ||
|
|
02d5f4fbe9 | ||
|
|
818ff8314d | ||
|
|
d23e6f8d8e | ||
|
|
f217a56f6e | ||
|
|
46b49adf9e | ||
|
|
d9fb4d06ec | ||
|
|
34a9979255 | ||
|
|
89e7a06deb | ||
|
|
43d02ac456 | ||
|
|
c839159470 | ||
|
|
823b773051 | ||
|
|
f8434d34b6 | ||
|
|
61980c8a1f | ||
|
|
35176383b7 | ||
|
|
c96e20e6c3 | ||
|
|
ce0cdc7bd3 | ||
|
|
7e63080c03 | ||
|
|
1c8ed8a46e | ||
|
|
c4334be9c3 | ||
|
|
e6e69ae805 | ||
|
|
8ce816de7f | ||
|
|
2fb52f6fce | ||
|
|
c72d4d2134 | ||
|
|
18a36c171f | ||
|
|
7b3c1631d1 | ||
|
|
4613fde654 | ||
|
|
143baec319 | ||
|
|
168a07d658 | ||
|
|
281acf4c71 | ||
|
|
d2ab6863e3 | ||
|
|
e55ad63d3c | ||
|
|
ec2eaa70a4 | ||
|
|
d402619347 | ||
|
|
c101d9df17 | ||
|
|
b5653a68ea | ||
|
|
c9942deaa9 | ||
|
|
2df1446c37 | ||
|
|
9421815327 | ||
|
|
1a0c9997ec | ||
|
|
16f060f864 | ||
|
|
ea7c6402dd | ||
|
|
07db2580c4 | ||
|
|
1df72c0afe | ||
|
|
0e41231298 | ||
|
|
8224b5a62a | ||
|
|
d8ab9dea1b | ||
|
|
a8e5c31381 | ||
|
|
3a1556e1fd | ||
|
|
4b5fbab129 | ||
|
|
b1ec1f4d18 | ||
|
|
16d8f4c774 | ||
|
|
f8b5ec48e8 | ||
|
|
7a26926965 | ||
|
|
2990fbc7cf | ||
|
|
e8e38f1682 | ||
|
|
35b4a09c3d | ||
|
|
9035fbe96b | ||
|
|
a41a5fadd2 | ||
|
|
d6f265e703 | ||
|
|
596c77afcd | ||
|
|
e53d985c4f | ||
|
|
348e53245b | ||
|
|
2fde0a0ae4 | ||
|
|
85ec428f3f | ||
|
|
a8ab809928 | ||
|
|
6c7cb5313d | ||
|
|
188e38198a | ||
|
|
294f557268 | ||
|
|
4dd622e180 | ||
|
|
5f8e5f9be5 | ||
|
|
e561896966 | ||
|
|
ea25e20c88 | ||
|
|
003b0fdb02 | ||
|
|
8de6500677 | ||
|
|
7df13e922b | ||
|
|
182d7c7dc7 | ||
|
|
f4d5bc7aa4 | ||
|
|
d53d98b625 | ||
|
|
2bfba716ef | ||
|
|
4cbe33d15d | ||
|
|
a9852273cb | ||
|
|
eb8a2b5e65 | ||
|
|
7304a990cb | ||
|
|
311d7c8f6a | ||
|
|
5a3d2fdac7 | ||
|
|
4b88f68ab8 | ||
|
|
70c224c3e7 | ||
|
|
1932d33b41 | ||
|
|
9cf4525a8f | ||
|
|
0846a6533d | ||
|
|
484404295e | ||
|
|
3e54becb95 | ||
|
|
ab13305b64 | ||
|
|
6fdb123df4 | ||
|
|
6cdc1cf95c | ||
|
|
2dd5a06616 | ||
|
|
e7436bfa95 | ||
|
|
084aab4bcd | ||
|
|
cd99557368 | ||
|
|
04f4004934 | ||
|
|
bbf46f935a | ||
|
|
b792c7144d | ||
|
|
5d5112257c | ||
|
|
747e6c7848 | ||
|
|
45d848c910 | ||
|
|
f12fa7e8f9 | ||
|
|
568a435e9e | ||
|
|
c46f2633be | ||
|
|
b51e28a3e0 | ||
|
|
badfab8561 | ||
|
|
d5c0d687b3 | ||
|
|
57f08426ee | ||
|
|
ba59b879ad | ||
|
|
1e9e16f16b | ||
|
|
ece075ef6e | ||
|
|
c4c429b699 | ||
|
|
21f881910b | ||
|
|
37157273ff | ||
|
|
460ed2e9e2 | ||
|
|
03ce7ab385 | ||
|
|
1c605bed2b | ||
|
|
55136b77ad | ||
|
|
d8798a280a | ||
|
|
c8d6ffd393 | ||
|
|
100329f09f | ||
|
|
553c30c6d1 | ||
|
|
415459e656 | ||
|
|
596e8cfab2 | ||
|
|
dab4419335 | ||
|
|
932ebfa0fd | ||
|
|
9d74307836 | ||
|
|
7be5ea0148 | ||
|
|
525279e9dd | ||
|
|
d0fbf0802f | ||
|
|
fad154f474 | ||
|
|
40543d42d5 | ||
|
|
fa763181c0 | ||
|
|
e48e6c40e7 | ||
|
|
64a318a9f1 | ||
|
|
5e50aeab2b | ||
|
|
53fef98acf | ||
|
|
f94ca6f4b3 | ||
|
|
90536e4a0d | ||
|
|
9c37f5292a | ||
|
|
23ee7dd814 | ||
|
|
990bede9b2 | ||
|
|
b8d18d198e | ||
|
|
6d81c2b818 | ||
|
|
f966199f28 | ||
|
|
793fa4fdeb | ||
|
|
814cd31cee | ||
|
|
bf9466d568 | ||
|
|
317b4fb08f | ||
|
|
2b5c5e3dd3 | ||
|
|
d6eb49e4eb | ||
|
|
751517d7c1 | ||
|
|
03acc7f5a9 | ||
|
|
9320d8b28d | ||
|
|
86883c7d9a | ||
|
|
2553afd6c9 | ||
|
|
9fc8754369 | ||
|
|
ba59ed2e6c | ||
|
|
14aab9085a | ||
|
|
eb2bc91e3f | ||
|
|
38171f3bc9 | ||
|
|
72b6039328 | ||
|
|
c10cceb1f7 | ||
|
|
7dd78ec89d | ||
|
|
01032087ec | ||
|
|
933f6730b2 | ||
|
|
2b7b51614c | ||
|
|
a9122a9fe1 | ||
|
|
78ea3d4091 | ||
|
|
b3c60d1de2 | ||
|
|
b438d5a6b0 | ||
|
|
aa42534208 | ||
|
|
171f8eef01 | ||
|
|
e96b4e782d | ||
|
|
626ad544b7 | ||
|
|
c53da829d3 | ||
|
|
eeb06014da | ||
|
|
cc138adda9 | ||
|
|
5632dbeec3 | ||
|
|
8ca47f76bf | ||
|
|
48e031f2fb | ||
|
|
5479848df6 | ||
|
|
52026eb8f2 | ||
|
|
af1769aa25 | ||
|
|
953fa2c819 | ||
|
|
6f670685e2 | ||
|
|
9618dd47ce | ||
|
|
c72a133178 | ||
|
|
7a4189f830 | ||
|
|
a8b5b36737 | ||
|
|
6e36cf9940 | ||
|
|
1328895ff9 | ||
|
|
4e54a27500 | ||
|
|
a0ac8640c7 | ||
|
|
38e4d81fb1 | ||
|
|
2798c778c7 | ||
|
|
94374cf06f | ||
|
|
624fbf6f22 | ||
|
|
5aa3ed8d8f | ||
|
|
c7d2e2cb0e | ||
|
|
895c0dae3b | ||
|
|
1d364b5c22 | ||
|
|
5a4ebe6a73 | ||
|
|
2be915e3c7 | ||
|
|
f9f009a4c1 | ||
|
|
f1ed482001 | ||
|
|
8a6243d2a0 | ||
|
|
24537b3001 | ||
|
|
25763fc70b | ||
|
|
7400e51451 | ||
|
|
a504c5e624 | ||
|
|
648504119e | ||
|
|
acb0c57844 | ||
|
|
ea129cd9f6 | ||
|
|
4b2efd4785 | ||
|
|
72e3973cf9 | ||
|
|
d4eeb1ff28 | ||
|
|
fd427843a9 | ||
|
|
73e61a9cc6 | ||
|
|
cce8f0086a | ||
|
|
a7be332023 | ||
|
|
3fb46241f2 | ||
|
|
1153873321 | ||
|
|
000b46ec37 | ||
|
|
3b6b31266d | ||
|
|
89d771929a | ||
|
|
77ed1bd68b | ||
|
|
b7d79ff343 | ||
|
|
dab5a4e308 | ||
|
|
999a941110 | ||
|
|
ad36be1bd7 | ||
|
|
66f8fbd1b7 | ||
|
|
7b10ee8d56 | ||
|
|
62a4bcdc71 | ||
|
|
312943c6a0 | ||
|
|
61d13846cd | ||
|
|
8e7796a672 | ||
|
|
6fa241453c | ||
|
|
1f4a84edc2 | ||
|
|
6699279d53 | ||
|
|
2a79d7bed9 | ||
|
|
fd0291845f | ||
|
|
570a8356e6 | ||
|
|
6289b2b8e4 | ||
|
|
3a4a673b43 | ||
|
|
67b055009d | ||
|
|
80d9ec379f | ||
|
|
673ffcce00 | ||
|
|
6170346da2 | ||
|
|
b00b006c4a | ||
|
|
48034ae22e | ||
|
|
1cdc0d7558 | ||
|
|
cb19ab54e9 | ||
|
|
feab147563 | ||
|
|
f5911342e8 | ||
|
|
c6cbc2f6b6 | ||
|
|
ca290355fa | ||
|
|
2b55bc57a4 | ||
|
|
5c831e2465 | ||
|
|
521a387271 | ||
|
|
f25e396181 | ||
|
|
6fd1072fde | ||
|
|
d637d720db | ||
|
|
5c508e45a7 | ||
|
|
2e919505f1 | ||
|
|
af6b5609de | ||
|
|
9e90ee2dde | ||
|
|
8bc018fe20 | ||
|
|
2dbb0129d3 | ||
|
|
f10793e99b | ||
|
|
1e51af2d62 | ||
|
|
7ee9cdb29b | ||
|
|
a3eccf5e37 | ||
|
|
ace41d7c22 | ||
|
|
d0a41eb494 | ||
|
|
060e5384f5 | ||
|
|
0e6a106180 | ||
|
|
bac383441e | ||
|
|
3498bf9329 | ||
|
|
708d57a77e | ||
|
|
c5fb8ef3f7 | ||
|
|
ffe5de468e | ||
|
|
249ffb9362 | ||
|
|
07a1499886 | ||
|
|
9c6f8f8b82 | ||
|
|
f48eeca667 | ||
|
|
ccb0e1b24c | ||
|
|
18bc3216ae | ||
|
|
0782b355a4 | ||
|
|
c91efa5134 | ||
|
|
26ad20aa2b | ||
|
|
283c3f10fe | ||
|
|
2f23367671 | ||
|
|
c082d71a56 | ||
|
|
e2fa2a1a4d | ||
|
|
9882dd1cfd | ||
|
|
b278106336 | ||
|
|
97538286fd | ||
|
|
fd1b230a54 | ||
|
|
33321e89a1 | ||
|
|
b50e663a3a | ||
|
|
14a699cb85 | ||
|
|
098d44162b | ||
|
|
16af94795e | ||
|
|
00f41c6bc9 | ||
|
|
0465688403 | ||
|
|
8cd5834d28 | ||
|
|
040089639f | ||
|
|
81c4e47a6d | ||
|
|
2aef994aa4 | ||
|
|
ffa2bbf1e4 | ||
|
|
6a54fe8293 | ||
|
|
2020ce3c9c | ||
|
|
2557559d5c | ||
|
|
bb0143e476 | ||
|
|
fd2c814fe0 | ||
|
|
bd3d9b70ec | ||
|
|
ee1a218870 | ||
|
|
84ee3da79a | ||
|
|
fdee7de36d | ||
|
|
bf5b74b6ca | ||
|
|
d9b0347741 | ||
|
|
9546537256 | ||
|
|
f84fe84b96 | ||
|
|
ea9bc53261 | ||
|
|
0edb839c95 | ||
|
|
b8bb327f98 | ||
|
|
27d69334ee | ||
|
|
838e63ab62 | ||
|
|
ba264700dc | ||
|
|
e00ad7ab79 | ||
|
|
de176b735f | ||
|
|
cc3e985834 | ||
|
|
3b5f45eea2 | ||
|
|
c3056b04c1 | ||
|
|
58755a6772 | ||
|
|
1cf976c4e4 | ||
|
|
5be836527c | ||
|
|
e9f397945d | ||
|
|
78df0b8161 | ||
|
|
db17245005 | ||
|
|
4edb586077 | ||
|
|
ed1a8313f4 | ||
|
|
c450b7b5d7 | ||
|
|
56846b7dda | ||
|
|
fb232cc43e | ||
|
|
a5c79cc4bd | ||
|
|
4b96ade660 | ||
|
|
76d1e6fa1f | ||
|
|
a6299a0748 | ||
|
|
6cc558bb82 | ||
|
|
84b08bf286 | ||
|
|
4ada09b93c | ||
|
|
2862568eca | ||
|
|
ed2e16a346 | ||
|
|
45d46b9072 | ||
|
|
4924c6d30b | ||
|
|
6b2eb80188 | ||
|
|
298e4baf0e | ||
|
|
c5fb93823a | ||
|
|
f238113677 | ||
|
|
f56d777cc2 | ||
|
|
b124d4c1b8 | ||
|
|
4fe098713f | ||
|
|
146f8ea09d | ||
|
|
69b5bd8c13 | ||
|
|
dd7e962c94 | ||
|
|
5332021086 | ||
|
|
8de3149485 | ||
|
|
e3fee604e1 | ||
|
|
dd152fc910 | ||
|
|
c4b45acae3 | ||
|
|
cf50a582f2 | ||
|
|
ca5e855c34 | ||
|
|
13d1d9fc9d | ||
|
|
242ff32bca | ||
|
|
ba451c1cd2 | ||
|
|
e5490522ce | ||
|
|
ae717c3e7d | ||
|
|
1a7df9108a | ||
|
|
7771e180ec | ||
|
|
82bbb1c944 | ||
|
|
cbf22ac9f3 | ||
|
|
bacaf10f1b | ||
|
|
8f7fa6a562 | ||
|
|
7b96eb28eb | ||
|
|
14ccf96eb0 | ||
|
|
6303886b8c | ||
|
|
ea8557296b | ||
|
|
2a821fb62a | ||
|
|
d982009260 | ||
|
|
a3f028ee3d | ||
|
|
d34b092cdd | ||
|
|
77f4071191 | ||
|
|
653b29145d | ||
|
|
96e0a4e3cc | ||
|
|
1da92850a0 | ||
|
|
9747cf9aee | ||
|
|
7f45b3fd10 | ||
|
|
217ab47577 | ||
|
|
532f47444b | ||
|
|
24f9ee1560 | ||
|
|
d7a76c7c72 | ||
|
|
c175d66e23 | ||
|
|
30cbcfd013 | ||
|
|
05003e3e2a | ||
|
|
64c2cb1b51 | ||
|
|
7f0e4eac8a | ||
|
|
141a4d0992 | ||
|
|
645ce72e7e | ||
|
|
fca4d67a43 | ||
|
|
014cbb9676 | ||
|
|
a39e822184 | ||
|
|
716ecccaed |
Submodule 3rd/jemalloc updated: 91010a9e2e...61efbda709
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpcap.h,v 1.2 2015/02/27 17:13:17 roberto Exp $
|
||||
** $Id: lpcap.h,v 1.3 2016/09/13 17:45:58 roberto Exp $
|
||||
*/
|
||||
|
||||
#if !defined(lpcap_h)
|
||||
@@ -11,8 +11,21 @@
|
||||
|
||||
/* kinds of captures */
|
||||
typedef enum CapKind {
|
||||
Cclose, Cposition, Cconst, Cbackref, Carg, Csimple, Ctable, Cfunction,
|
||||
Cquery, Cstring, Cnum, Csubst, Cfold, Cruntime, Cgroup
|
||||
Cclose, /* not used in trees */
|
||||
Cposition,
|
||||
Cconst, /* ktable[key] is Lua constant */
|
||||
Cbackref, /* ktable[key] is "name" of group to get capture */
|
||||
Carg, /* 'key' is arg's number */
|
||||
Csimple, /* next node is pattern */
|
||||
Ctable, /* next node is pattern */
|
||||
Cfunction, /* ktable[key] is function; next node is pattern */
|
||||
Cquery, /* ktable[key] is table; next node is pattern */
|
||||
Cstring, /* ktable[key] is string; next node is pattern */
|
||||
Cnum, /* numbered capture; 'key' is number of value to return */
|
||||
Csubst, /* substitution capture; next node is pattern */
|
||||
Cfold, /* ktable[key] is function; next node is pattern */
|
||||
Cruntime, /* not used in trees (is uses another type for tree) */
|
||||
Cgroup /* ktable[key] is group's "name" */
|
||||
} CapKind;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpcode.c,v 1.23 2015/06/12 18:36:47 roberto Exp $
|
||||
** $Id: lpcode.c,v 1.24 2016/09/15 17:46:13 roberto Exp $
|
||||
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
*/
|
||||
|
||||
@@ -125,6 +125,27 @@ int tocharset (TTree *tree, Charset *cs) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Visit a TCall node taking care to stop recursion. If node not yet
|
||||
** visited, return 'f(sib2(tree))', otherwise return 'def' (default
|
||||
** value)
|
||||
*/
|
||||
static int callrecursive (TTree *tree, int f (TTree *t), int def) {
|
||||
int key = tree->key;
|
||||
assert(tree->tag == TCall);
|
||||
assert(sib2(tree)->tag == TRule);
|
||||
if (key == 0) /* node already visited? */
|
||||
return def; /* return default value */
|
||||
else { /* first visit */
|
||||
int result;
|
||||
tree->key = 0; /* mark call as already visited */
|
||||
result = f(sib2(tree)); /* go to called rule */
|
||||
tree->key = key; /* restore tree */
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Check whether a pattern tree has captures
|
||||
*/
|
||||
@@ -134,14 +155,17 @@ int hascaptures (TTree *tree) {
|
||||
case TCapture: case TRunTime:
|
||||
return 1;
|
||||
case TCall:
|
||||
tree = sib2(tree); goto tailcall; /* return hascaptures(sib2(tree)); */
|
||||
return callrecursive(tree, hascaptures, 0);
|
||||
case TRule: /* do not follow siblings */
|
||||
tree = sib1(tree); goto tailcall;
|
||||
case TOpenCall: assert(0);
|
||||
default: {
|
||||
switch (numsiblings[tree->tag]) {
|
||||
case 1: /* return hascaptures(sib1(tree)); */
|
||||
tree = sib1(tree); goto tailcall;
|
||||
case 2:
|
||||
if (hascaptures(sib1(tree))) return 1;
|
||||
if (hascaptures(sib1(tree)))
|
||||
return 1;
|
||||
/* else return hascaptures(sib2(tree)); */
|
||||
tree = sib2(tree); goto tailcall;
|
||||
default: assert(numsiblings[tree->tag] == 0); return 0;
|
||||
@@ -208,9 +232,9 @@ int checkaux (TTree *tree, int pred) {
|
||||
|
||||
/*
|
||||
** number of characters to match a pattern (or -1 if variable)
|
||||
** ('count' avoids infinite loops for grammars)
|
||||
*/
|
||||
int fixedlenx (TTree *tree, int count, int len) {
|
||||
int fixedlen (TTree *tree) {
|
||||
int len = 0; /* to accumulate in tail calls */
|
||||
tailcall:
|
||||
switch (tree->tag) {
|
||||
case TChar: case TSet: case TAny:
|
||||
@@ -220,26 +244,29 @@ int fixedlenx (TTree *tree, int count, int len) {
|
||||
case TRep: case TRunTime: case TOpenCall:
|
||||
return -1;
|
||||
case TCapture: case TRule: case TGrammar:
|
||||
/* return fixedlenx(sib1(tree), count); */
|
||||
/* return fixedlen(sib1(tree)); */
|
||||
tree = sib1(tree); goto tailcall;
|
||||
case TCall:
|
||||
if (count++ >= MAXRULES)
|
||||
return -1; /* may be a loop */
|
||||
/* else return fixedlenx(sib2(tree), count); */
|
||||
tree = sib2(tree); goto tailcall;
|
||||
case TCall: {
|
||||
int n1 = callrecursive(tree, fixedlen, -1);
|
||||
if (n1 < 0)
|
||||
return -1;
|
||||
else
|
||||
return len + n1;
|
||||
}
|
||||
case TSeq: {
|
||||
len = fixedlenx(sib1(tree), count, len);
|
||||
if (len < 0) return -1;
|
||||
/* else return fixedlenx(sib2(tree), count, len); */
|
||||
tree = sib2(tree); goto tailcall;
|
||||
int n1 = fixedlen(sib1(tree));
|
||||
if (n1 < 0)
|
||||
return -1;
|
||||
/* else return fixedlen(sib2(tree)) + len; */
|
||||
len += n1; tree = sib2(tree); goto tailcall;
|
||||
}
|
||||
case TChoice: {
|
||||
int n1, n2;
|
||||
n1 = fixedlenx(sib1(tree), count, len);
|
||||
if (n1 < 0) return -1;
|
||||
n2 = fixedlenx(sib2(tree), count, len);
|
||||
if (n1 == n2) return n1;
|
||||
else return -1;
|
||||
int n1 = fixedlen(sib1(tree));
|
||||
int n2 = fixedlen(sib2(tree));
|
||||
if (n1 != n2 || n1 < 0)
|
||||
return -1;
|
||||
else
|
||||
return len + n1;
|
||||
}
|
||||
default: assert(0); return 0;
|
||||
};
|
||||
@@ -710,9 +737,10 @@ static void codeand (CompileState *compst, TTree *tree, int tt) {
|
||||
|
||||
|
||||
/*
|
||||
** Captures: if pattern has fixed (and not too big) length, use
|
||||
** a single IFullCapture instruction after the match; otherwise,
|
||||
** enclose the pattern with OpenCapture - CloseCapture.
|
||||
** Captures: if pattern has fixed (and not too big) length, and it
|
||||
** has no nested captures, use a single IFullCapture instruction
|
||||
** after the match; otherwise, enclose the pattern with OpenCapture -
|
||||
** CloseCapture.
|
||||
*/
|
||||
static void codecapture (CompileState *compst, TTree *tree, int tt,
|
||||
const Charset *fl) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpcode.h,v 1.7 2015/06/12 18:24:45 roberto Exp $
|
||||
** $Id: lpcode.h,v 1.8 2016/09/15 17:46:13 roberto Exp $
|
||||
*/
|
||||
|
||||
#if !defined(lpcode_h)
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
int tocharset (TTree *tree, Charset *cs);
|
||||
int checkaux (TTree *tree, int pred);
|
||||
int fixedlenx (TTree *tree, int count, int len);
|
||||
int fixedlen (TTree *tree);
|
||||
int hascaptures (TTree *tree);
|
||||
int lp_gc (lua_State *L);
|
||||
Instruction *compile (lua_State *L, Pattern *p);
|
||||
@@ -35,8 +35,6 @@ int sizei (const Instruction *i);
|
||||
*/
|
||||
#define nullable(t) checkaux(t, PEnullable)
|
||||
|
||||
#define fixedlen(t) fixedlenx(t, 0, 0)
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- $Id: lpeg.html,v 1.75 2015/09/28 17:17:41 roberto Exp $ -->
|
||||
<!-- $Id: lpeg.html,v 1.77 2017/01/13 13:40:05 roberto Exp $ -->
|
||||
|
||||
<div id="container">
|
||||
|
||||
@@ -577,8 +577,9 @@ It is equivalent to the following grammar in standard PEG notation:
|
||||
<h2><a name="captures">Captures</a></h2>
|
||||
|
||||
<p>
|
||||
A <em>capture</em> is a pattern that creates values
|
||||
(the so called <em>semantic information</em>) when it matches.
|
||||
A <em>capture</em> is a pattern that produces values
|
||||
(the so called <em>semantic information</em>)
|
||||
according to what it matches.
|
||||
LPeg offers several kinds of captures,
|
||||
which produces values based on matches and combine these values to
|
||||
produce new values.
|
||||
@@ -632,10 +633,7 @@ or no value when <code>number</code> is zero.</td></tr>
|
||||
</tbody></table>
|
||||
|
||||
<p>
|
||||
A capture pattern produces its values every time it succeeds.
|
||||
For instance,
|
||||
a capture inside a loop produces as many values as matched by the loop.
|
||||
A capture produces a value only when it succeeds.
|
||||
A capture pattern produces its values only when it succeeds.
|
||||
For instance,
|
||||
the pattern <code>lpeg.C(lpeg.P"a"^-1)</code>
|
||||
produces the empty string when there is no <code>"a"</code>
|
||||
@@ -643,14 +641,20 @@ produces the empty string when there is no <code>"a"</code>
|
||||
while the pattern <code>lpeg.C("a")^-1</code>
|
||||
does not produce any value when there is no <code>"a"</code>
|
||||
(because the pattern <code>"a"</code> fails).
|
||||
A pattern inside a loop or inside a recursive structure
|
||||
produces values for each match.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Usually,
|
||||
LPeg evaluates all captures only after (and if) the entire match succeeds.
|
||||
During <em>match time</em> it only gathers enough information
|
||||
to produce the capture values later.
|
||||
As a particularly important consequence,
|
||||
LPeg does not specify when (and if) it evaluates its captures.
|
||||
(As an example,
|
||||
consider the pattern <code>lpeg.P"a" / func / 0</code>.
|
||||
Because the "division" by 0 instructs LPeg to throw away the
|
||||
results from the pattern,
|
||||
LPeg may or may not call <code>func</code>.)
|
||||
Therefore, captures should avoid side effects.
|
||||
Moreover,
|
||||
most captures cannot affect the way a pattern matches a subject.
|
||||
The only exception to this rule is the
|
||||
so-called <a href="#matchtime"><em>match-time capture</em></a>.
|
||||
@@ -700,6 +704,12 @@ An <em>Outermost</em> capture means that the capture is not inside
|
||||
another complete capture.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In the same way that LPeg does not specify when it evaluates captures,
|
||||
it does not specify whether it reuses
|
||||
values previously produced by the group
|
||||
or re-evaluates them.
|
||||
</p>
|
||||
|
||||
<h3><a name="cap-cc"></a><code>lpeg.Cc ([value, ...])</code></h3>
|
||||
<p>
|
||||
@@ -806,7 +816,7 @@ all replacements.
|
||||
<h3><a name="cap-t"></a><code>lpeg.Ct (patt)</code></h3>
|
||||
<p>
|
||||
Creates a <em>table capture</em>.
|
||||
This capture creates a table and puts all values from all anonymous captures
|
||||
This capture returns a table with all values from all anonymous captures
|
||||
made by <code>patt</code> inside this table in successive integer keys,
|
||||
starting at 1.
|
||||
Moreover,
|
||||
@@ -872,7 +882,8 @@ there is no captured value.
|
||||
<p>
|
||||
Creates a <em>match-time capture</em>.
|
||||
Unlike all other captures,
|
||||
this one is evaluated immediately when a match occurs.
|
||||
this one is evaluated immediately when a match occurs
|
||||
(even if it is part of a larger pattern that fails later).
|
||||
It forces the immediate evaluation of all its nested captures
|
||||
and then calls <code>function</code>.
|
||||
</p>
|
||||
@@ -1380,13 +1391,13 @@ and the new term for each repetition.
|
||||
<h2><a name="download"></a>Download</h2>
|
||||
|
||||
<p>LPeg
|
||||
<a href="http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.0.tar.gz">source code</a>.</p>
|
||||
<a href="http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.1.tar.gz">source code</a>.</p>
|
||||
|
||||
|
||||
<h2><a name="license">License</a></h2>
|
||||
|
||||
<p>
|
||||
Copyright © 2007-2015 Lua.org, PUC-Rio.
|
||||
Copyright © 2007-2017 Lua.org, PUC-Rio.
|
||||
</p>
|
||||
<p>
|
||||
Permission is hereby granted, free of charge,
|
||||
@@ -1424,7 +1435,7 @@ THE SOFTWARE.
|
||||
|
||||
<div id="about">
|
||||
<p><small>
|
||||
$Id: lpeg.html,v 1.75 2015/09/28 17:17:41 roberto Exp $
|
||||
$Id: lpeg.html,v 1.77 2017/01/13 13:40:05 roberto Exp $
|
||||
</small></p>
|
||||
</div> <!-- id="about" -->
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpprint.c,v 1.9 2015/06/15 16:09:57 roberto Exp $
|
||||
** $Id: lpprint.c,v 1.10 2016/09/13 16:06:03 roberto Exp $
|
||||
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
*/
|
||||
|
||||
@@ -37,13 +37,13 @@ void printcharset (const byte *st) {
|
||||
}
|
||||
|
||||
|
||||
static void printcapkind (int kind) {
|
||||
static const char *capkind (int kind) {
|
||||
const char *const modes[] = {
|
||||
"close", "position", "constant", "backref",
|
||||
"argument", "simple", "table", "function",
|
||||
"query", "string", "num", "substitution", "fold",
|
||||
"runtime", "group"};
|
||||
printf("%s", modes[kind]);
|
||||
return modes[kind];
|
||||
}
|
||||
|
||||
|
||||
@@ -73,13 +73,12 @@ void printinst (const Instruction *op, const Instruction *p) {
|
||||
break;
|
||||
}
|
||||
case IFullCapture: {
|
||||
printcapkind(getkind(p));
|
||||
printf(" (size = %d) (idx = %d)", getoff(p), p->i.key);
|
||||
printf("%s (size = %d) (idx = %d)",
|
||||
capkind(getkind(p)), getoff(p), p->i.key);
|
||||
break;
|
||||
}
|
||||
case IOpenCapture: {
|
||||
printcapkind(getkind(p));
|
||||
printf(" (idx = %d)", p->i.key);
|
||||
printf("%s (idx = %d)", capkind(getkind(p)), p->i.key);
|
||||
break;
|
||||
}
|
||||
case ISet: {
|
||||
@@ -124,8 +123,8 @@ void printpatt (Instruction *p, int n) {
|
||||
|
||||
#if defined(LPEG_DEBUG)
|
||||
static void printcap (Capture *cap) {
|
||||
printcapkind(cap->kind);
|
||||
printf(" (idx: %d - size: %d) -> %p\n", cap->idx, cap->siz, cap->s);
|
||||
printf("%s (idx: %d - size: %d) -> %p\n",
|
||||
capkind(cap->kind), cap->idx, cap->siz, cap->s);
|
||||
}
|
||||
|
||||
|
||||
@@ -177,7 +176,8 @@ void printtree (TTree *tree, int ident) {
|
||||
break;
|
||||
}
|
||||
case TOpenCall: case TCall: {
|
||||
printf(" key: %d\n", tree->key);
|
||||
assert(sib2(tree)->tag == TRule);
|
||||
printf(" key: %d (rule: %d)\n", tree->key, sib2(tree)->cap);
|
||||
break;
|
||||
}
|
||||
case TBehind: {
|
||||
@@ -186,7 +186,7 @@ void printtree (TTree *tree, int ident) {
|
||||
break;
|
||||
}
|
||||
case TCapture: {
|
||||
printf(" cap: %d key: %d n: %d\n", tree->cap, tree->key, tree->u.n);
|
||||
printf(" kind: '%s' key: %d\n", capkind(tree->cap), tree->key);
|
||||
printtree(sib1(tree), ident + 2);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lptree.c,v 1.21 2015/09/28 17:01:25 roberto Exp $
|
||||
** $Id: lptree.c,v 1.22 2016/09/13 18:10:22 roberto Exp $
|
||||
** Copyright 2013, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
*/
|
||||
|
||||
@@ -64,7 +64,7 @@ static void fixonecall (lua_State *L, int postable, TTree *g, TTree *t) {
|
||||
t->tag = TCall;
|
||||
t->u.ps = n - (t - g); /* position relative to node */
|
||||
assert(sib2(t)->tag == TRule);
|
||||
sib2(t)->key = t->key;
|
||||
sib2(t)->key = t->key; /* fix rule's key */
|
||||
}
|
||||
|
||||
|
||||
@@ -935,7 +935,7 @@ static void buildgrammar (lua_State *L, TTree *grammar, int frule, int n) {
|
||||
int rulesize;
|
||||
TTree *rn = gettree(L, ridx, &rulesize);
|
||||
nd->tag = TRule;
|
||||
nd->key = 0;
|
||||
nd->key = 0; /* will be fixed when rule is used */
|
||||
nd->cap = i; /* rule number */
|
||||
nd->u.ps = rulesize + 1; /* point to next rule */
|
||||
memcpy(sib1(nd), rn, rulesize * sizeof(TTree)); /* copy rule */
|
||||
@@ -969,6 +969,11 @@ static int checkloops (TTree *tree) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Give appropriate error message for 'verifyrule'. If a rule appears
|
||||
** twice in 'passed', there is path from it back to itself without
|
||||
** advancing the subject.
|
||||
*/
|
||||
static int verifyerror (lua_State *L, int *passed, int npassed) {
|
||||
int i, j;
|
||||
for (i = npassed - 1; i >= 0; i--) { /* search for a repetition */
|
||||
@@ -990,6 +995,8 @@ static int verifyerror (lua_State *L, int *passed, int npassed) {
|
||||
** is only relevant if the first is nullable.
|
||||
** Parameter 'nb' works as an accumulator, to allow tail calls in
|
||||
** choices. ('nb' true makes function returns true.)
|
||||
** Parameter 'passed' is a list of already visited rules, 'npassed'
|
||||
** counts the elements in 'passed'.
|
||||
** Assume ktable at the top of the stack.
|
||||
*/
|
||||
static int verifyrule (lua_State *L, TTree *tree, int *passed, int npassed,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lptree.h,v 1.2 2013/03/24 13:51:12 roberto Exp $
|
||||
** $Id: lptree.h,v 1.3 2016/09/13 18:07:51 roberto Exp $
|
||||
*/
|
||||
|
||||
#if !defined(lptree_h)
|
||||
@@ -13,38 +13,43 @@
|
||||
** types of trees
|
||||
*/
|
||||
typedef enum TTag {
|
||||
TChar = 0, TSet, TAny, /* standard PEG elements */
|
||||
TTrue, TFalse,
|
||||
TRep,
|
||||
TSeq, TChoice,
|
||||
TNot, TAnd,
|
||||
TCall,
|
||||
TOpenCall,
|
||||
TRule, /* sib1 is rule's pattern, sib2 is 'next' rule */
|
||||
TGrammar, /* sib1 is initial (and first) rule */
|
||||
TBehind, /* match behind */
|
||||
TCapture, /* regular capture */
|
||||
TRunTime /* run-time capture */
|
||||
TChar = 0, /* 'n' = char */
|
||||
TSet, /* the set is stored in next CHARSETSIZE bytes */
|
||||
TAny,
|
||||
TTrue,
|
||||
TFalse,
|
||||
TRep, /* 'sib1'* */
|
||||
TSeq, /* 'sib1' 'sib2' */
|
||||
TChoice, /* 'sib1' / 'sib2' */
|
||||
TNot, /* !'sib1' */
|
||||
TAnd, /* &'sib1' */
|
||||
TCall, /* ktable[key] is rule's key; 'sib2' is rule being called */
|
||||
TOpenCall, /* ktable[key] is rule's key */
|
||||
TRule, /* ktable[key] is rule's key (but key == 0 for unused rules);
|
||||
'sib1' is rule's pattern;
|
||||
'sib2' is next rule; 'cap' is rule's sequential number */
|
||||
TGrammar, /* 'sib1' is initial (and first) rule */
|
||||
TBehind, /* 'sib1' is pattern, 'n' is how much to go back */
|
||||
TCapture, /* captures: 'cap' is kind of capture (enum 'CapKind');
|
||||
ktable[key] is Lua value associated with capture;
|
||||
'sib1' is capture body */
|
||||
TRunTime /* run-time capture: 'key' is Lua function;
|
||||
'sib1' is capture body */
|
||||
} TTag;
|
||||
|
||||
/* number of siblings for each tree */
|
||||
extern const byte numsiblings[];
|
||||
|
||||
|
||||
/*
|
||||
** Tree trees
|
||||
** The first sibling of a tree (if there is one) is immediately after
|
||||
** the tree. A reference to a second sibling (ps) is its position
|
||||
** relative to the position of the tree itself. A key in ktable
|
||||
** uses the (unique) address of the original tree that created that
|
||||
** entry. NULL means no data.
|
||||
** The first child of a tree (if there is one) is immediately after
|
||||
** the tree. A reference to a second child (ps) is its position
|
||||
** relative to the position of the tree itself.
|
||||
*/
|
||||
typedef struct TTree {
|
||||
byte tag;
|
||||
byte cap; /* kind of capture (if it is a capture) */
|
||||
unsigned short key; /* key in ktable for Lua data (0 if no key) */
|
||||
union {
|
||||
int ps; /* occasional second sibling */
|
||||
int ps; /* occasional second child */
|
||||
int n; /* occasional counter */
|
||||
} u;
|
||||
} TTree;
|
||||
@@ -61,10 +66,10 @@ typedef struct Pattern {
|
||||
} Pattern;
|
||||
|
||||
|
||||
/* number of siblings for each tree */
|
||||
/* number of children for each tree */
|
||||
extern const byte numsiblings[];
|
||||
|
||||
/* access to siblings */
|
||||
/* access to children */
|
||||
#define sib1(t) ((t) + 1)
|
||||
#define sib2(t) ((t) + (t)->u.ps)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
** $Id: lptypes.h,v 1.14 2015/09/28 17:17:41 roberto Exp $
|
||||
** $Id: lptypes.h,v 1.16 2017/01/13 13:33:17 roberto Exp $
|
||||
** LPeg - PEG pattern matching for Lua
|
||||
** Copyright 2007-2015, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
** Copyright 2007-2017, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
** written by Roberto Ierusalimschy
|
||||
*/
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "lua.h"
|
||||
|
||||
|
||||
#define VERSION "1.0.0"
|
||||
#define VERSION "1.0.1"
|
||||
|
||||
|
||||
#define PATTERN_T "lpeg-pattern"
|
||||
@@ -55,9 +55,9 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* maximum number of rules in a grammar */
|
||||
/* maximum number of rules in a grammar (limited by 'unsigned char') */
|
||||
#if !defined(MAXRULES)
|
||||
#define MAXRULES 1000
|
||||
#define MAXRULES 250
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpvm.c,v 1.6 2015/09/28 17:01:25 roberto Exp $
|
||||
** $Id: lpvm.c,v 1.9 2016/06/03 20:11:18 roberto Exp $
|
||||
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
*/
|
||||
|
||||
@@ -45,14 +45,16 @@ typedef struct Stack {
|
||||
|
||||
|
||||
/*
|
||||
** Double the size of the array of captures
|
||||
** Make the size of the array of captures 'cap' twice as large as needed
|
||||
** (which is 'captop'). ('n' is the number of new elements.)
|
||||
*/
|
||||
static Capture *doublecap (lua_State *L, Capture *cap, int captop, int ptop) {
|
||||
static Capture *doublecap (lua_State *L, Capture *cap, int captop,
|
||||
int n, int ptop) {
|
||||
Capture *newc;
|
||||
if (captop >= INT_MAX/((int)sizeof(Capture) * 2))
|
||||
luaL_error(L, "too many captures");
|
||||
newc = (Capture *)lua_newuserdata(L, captop * 2 * sizeof(Capture));
|
||||
memcpy(newc, cap, captop * sizeof(Capture));
|
||||
memcpy(newc, cap, (captop - n) * sizeof(Capture));
|
||||
lua_replace(L, caplistidx(ptop));
|
||||
return newc;
|
||||
}
|
||||
@@ -113,8 +115,8 @@ static int resdyncaptures (lua_State *L, int fr, int curr, int limit) {
|
||||
*/
|
||||
static void adddyncaptures (const char *s, Capture *base, int n, int fd) {
|
||||
int i;
|
||||
/* Cgroup capture is already there */
|
||||
assert(base[0].kind == Cgroup && base[0].siz == 0);
|
||||
base[0].kind = Cgroup; /* create group capture */
|
||||
base[0].siz = 0;
|
||||
base[0].idx = 0; /* make it an anonymous group */
|
||||
for (i = 1; i <= n; i++) { /* add runtime captures */
|
||||
base[i].kind = Cruntime;
|
||||
@@ -157,10 +159,11 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
|
||||
lua_pushlightuserdata(L, stackbase);
|
||||
for (;;) {
|
||||
#if defined(DEBUG)
|
||||
printf("s: |%s| stck:%d, dyncaps:%d, caps:%d ",
|
||||
s, stack - getstackbase(L, ptop), ndyncap, captop);
|
||||
printinst(op, p);
|
||||
printf("-------------------------------------\n");
|
||||
printcaplist(capture, capture + captop);
|
||||
printf("s: |%s| stck:%d, dyncaps:%d, caps:%d ",
|
||||
s, (int)(stack - getstackbase(L, ptop)), ndyncap, captop);
|
||||
printinst(op, p);
|
||||
#endif
|
||||
assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop);
|
||||
switch ((Opcode)p->i.code) {
|
||||
@@ -284,6 +287,9 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
|
||||
ndyncap -= removedyncap(L, capture, stack->caplevel, captop);
|
||||
captop = stack->caplevel;
|
||||
p = stack->p;
|
||||
#if defined(DEBUG)
|
||||
printf("**FAIL**\n");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
case ICloseRunTime: {
|
||||
@@ -293,16 +299,19 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
|
||||
cs.s = o; cs.L = L; cs.ocap = capture; cs.ptop = ptop;
|
||||
n = runtimecap(&cs, capture + captop, s, &rem); /* call function */
|
||||
captop -= n; /* remove nested captures */
|
||||
ndyncap -= rem; /* update number of dynamic captures */
|
||||
fr -= rem; /* 'rem' items were popped from Lua stack */
|
||||
res = resdyncaptures(L, fr, s - o, e - o); /* get result */
|
||||
if (res == -1) /* fail? */
|
||||
goto fail;
|
||||
s = o + res; /* else update current position */
|
||||
n = lua_gettop(L) - fr + 1; /* number of new captures */
|
||||
ndyncap += n - rem; /* update number of dynamic captures */
|
||||
ndyncap += n; /* update number of dynamic captures */
|
||||
if (n > 0) { /* any new capture? */
|
||||
if (fr + n >= SHRT_MAX)
|
||||
luaL_error(L, "too many results in match-time capture");
|
||||
if ((captop += n + 2) >= capsize) {
|
||||
capture = doublecap(L, capture, captop, ptop);
|
||||
capture = doublecap(L, capture, captop, n + 2, ptop);
|
||||
capsize = 2 * captop;
|
||||
}
|
||||
/* add new captures to 'capture' list */
|
||||
@@ -339,7 +348,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
|
||||
capture[captop].idx = p->i.key;
|
||||
capture[captop].kind = getkind(p);
|
||||
if (++captop >= capsize) {
|
||||
capture = doublecap(L, capture, captop, ptop);
|
||||
capture = doublecap(L, capture, captop, 0, ptop);
|
||||
capsize = 2 * captop;
|
||||
}
|
||||
p++;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- $Id: re.html,v 1.23 2015/09/28 17:17:41 roberto Exp $ -->
|
||||
<!-- $Id: re.html,v 1.24 2016/09/20 17:41:27 roberto Exp $ -->
|
||||
|
||||
<div id="container">
|
||||
|
||||
@@ -406,7 +406,7 @@ of patterns accepted by <code>re</code>.
|
||||
p = [=[
|
||||
|
||||
pattern <- exp !.
|
||||
exp <- S (alternative / grammar)
|
||||
exp <- S (grammar / alternative)
|
||||
|
||||
alternative <- seq ('/' S seq)*
|
||||
seq <- prefix*
|
||||
@@ -488,7 +488,7 @@ THE SOFTWARE.
|
||||
|
||||
<div id="about">
|
||||
<p><small>
|
||||
$Id: re.html,v 1.23 2015/09/28 17:17:41 roberto Exp $
|
||||
$Id: re.html,v 1.24 2016/09/20 17:41:27 roberto Exp $
|
||||
</small></p>
|
||||
</div> <!-- id="about" -->
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
-- $Id: test.lua,v 1.109 2015/09/28 17:01:25 roberto Exp $
|
||||
-- $Id: test.lua,v 1.112 2017/01/14 18:55:22 roberto Exp $
|
||||
|
||||
-- require"strict" -- just to be pedantic
|
||||
|
||||
@@ -202,6 +202,14 @@ do
|
||||
end
|
||||
|
||||
|
||||
-- bug: loop in 'hascaptures'
|
||||
do
|
||||
local p = m.C(-m.P{m.P'x' * m.V(1) + m.P'y'})
|
||||
assert(p:match("xxx") == "")
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- test for small capture boundary
|
||||
for i = 250,260 do
|
||||
assert(#m.match(m.C(i), string.rep('a', i)) == i)
|
||||
@@ -517,6 +525,27 @@ assert(m.match(m.Cs((#((#m.P"a")/"") * 1 + m.P(1)/".")^0), "aloal") == "a..a.")
|
||||
assert(m.match(m.Cs((- -m.P("a") * 1 + m.P(1)/".")^0), "aloal") == "a..a.")
|
||||
assert(m.match(m.Cs((-((-m.P"a")/"") * 1 + m.P(1)/".")^0), "aloal") == "a..a.")
|
||||
|
||||
|
||||
-- fixed length
|
||||
do
|
||||
-- 'and' predicate using fixed length
|
||||
local p = m.C(#("a" * (m.P("bd") + "cd")) * 2)
|
||||
assert(p:match("acd") == "ac")
|
||||
|
||||
p = #m.P{ "a" * m.V(2), m.P"b" } * 2
|
||||
assert(p:match("abc") == 3)
|
||||
|
||||
p = #(m.P"abc" * m.B"c")
|
||||
assert(p:match("abc") == 1 and not p:match("ab"))
|
||||
|
||||
p = m.P{ "a" * m.V(2), m.P"b"^1 }
|
||||
checkerr("pattern may not have fixed length", m.B, p)
|
||||
|
||||
p = "abc" * (m.P"b"^1 + m.P"a"^0)
|
||||
checkerr("pattern may not have fixed length", m.B, p)
|
||||
end
|
||||
|
||||
|
||||
p = -m.P'a' * m.Cc(1) + -m.P'b' * m.Cc(2) + -m.P'c' * m.Cc(3)
|
||||
assert(p:match('a') == 2 and p:match('') == 1 and p:match('b') == 1)
|
||||
|
||||
@@ -1098,6 +1127,32 @@ do
|
||||
assert(c == 11)
|
||||
end
|
||||
|
||||
|
||||
-- Return a match-time capture that returns 'n' captures
|
||||
local function manyCmt (n)
|
||||
return m.Cmt("a", function ()
|
||||
local a = {}; for i = 1, n do a[i] = n - i end
|
||||
return true, unpack(a)
|
||||
end)
|
||||
end
|
||||
|
||||
-- bug in 1.0: failed match-time that used previous match-time results
|
||||
do
|
||||
local x
|
||||
local function aux (...) x = #{...}; return false end
|
||||
local res = {m.match(m.Cmt(manyCmt(20), aux) + manyCmt(10), "a")}
|
||||
assert(#res == 10 and res[1] == 9 and res[10] == 0)
|
||||
end
|
||||
|
||||
|
||||
-- bug in 1.0: problems with math-times returning too many captures
|
||||
do
|
||||
local lim = 2^11 - 10
|
||||
local res = {m.match(manyCmt(lim), "a")}
|
||||
assert(#res == lim and res[1] == lim - 1 and res[lim] == 0)
|
||||
checkerr("too many", m.match, manyCmt(2^15), "a")
|
||||
end
|
||||
|
||||
p = (m.P(function () return true, "a" end) * 'a'
|
||||
+ m.P(function (s, i) return i, "aa", 20 end) * 'b'
|
||||
+ m.P(function (s,i) if i <= #s then return i, "aaa" end end) * 1)^0
|
||||
|
||||
@@ -19,7 +19,7 @@ SYSCFLAGS=
|
||||
SYSLDFLAGS=
|
||||
SYSLIBS=
|
||||
|
||||
MYCFLAGS=-I../../skynet-src
|
||||
MYCFLAGS=-I../../skynet-src -g
|
||||
MYLDFLAGS=
|
||||
MYLIBS=
|
||||
MYOBJS=
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lapi.c,v 2.257 2015/11/02 18:48:07 roberto Exp $
|
||||
** $Id: lapi.c,v 2.259.1.2 2017/12/06 18:35:12 roberto Exp $
|
||||
** Lua API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -379,9 +379,9 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
|
||||
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 */
|
||||
luaO_tostring(L, o);
|
||||
lua_unlock(L);
|
||||
}
|
||||
if (len != NULL)
|
||||
@@ -480,10 +480,10 @@ LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
|
||||
LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) {
|
||||
TString *ts;
|
||||
lua_lock(L);
|
||||
luaC_checkGC(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);
|
||||
}
|
||||
@@ -495,12 +495,12 @@ LUA_API const char *lua_pushstring (lua_State *L, const char *s) {
|
||||
setnilvalue(L->top);
|
||||
else {
|
||||
TString *ts;
|
||||
luaC_checkGC(L);
|
||||
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;
|
||||
}
|
||||
@@ -510,8 +510,8 @@ LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
|
||||
va_list argp) {
|
||||
const char *ret;
|
||||
lua_lock(L);
|
||||
luaC_checkGC(L);
|
||||
ret = luaO_pushvfstring(L, fmt, argp);
|
||||
luaC_checkGC(L);
|
||||
lua_unlock(L);
|
||||
return ret;
|
||||
}
|
||||
@@ -521,10 +521,10 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
|
||||
const char *ret;
|
||||
va_list argp;
|
||||
lua_lock(L);
|
||||
luaC_checkGC(L);
|
||||
va_start(argp, fmt);
|
||||
ret = luaO_pushvfstring(L, fmt, argp);
|
||||
va_end(argp);
|
||||
luaC_checkGC(L);
|
||||
lua_unlock(L);
|
||||
return ret;
|
||||
}
|
||||
@@ -534,12 +534,12 @@ 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");
|
||||
luaC_checkGC(L);
|
||||
cl = luaF_newCclosure(L, n);
|
||||
cl->f = fn;
|
||||
L->top -= n;
|
||||
@@ -548,8 +548,9 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
|
||||
/* does not need barrier because closure is white */
|
||||
}
|
||||
setclCvalue(L, L->top, cl);
|
||||
api_incr_top(L);
|
||||
luaC_checkGC(L);
|
||||
}
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
@@ -586,16 +587,16 @@ LUA_API int lua_pushthread (lua_State *L) {
|
||||
|
||||
|
||||
static int auxgetstr (lua_State *L, const TValue *t, const char *k) {
|
||||
const TValue *aux;
|
||||
const TValue *slot;
|
||||
TString *str = luaS_new(L, k);
|
||||
if (luaV_fastget(L, t, str, aux, luaH_getstr)) {
|
||||
setobj2s(L, L->top, aux);
|
||||
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, aux);
|
||||
luaV_finishget(L, t, L->top - 1, L->top - 1, slot);
|
||||
}
|
||||
lua_unlock(L);
|
||||
return ttnov(L->top - 1);
|
||||
@@ -627,17 +628,17 @@ LUA_API int lua_getfield (lua_State *L, int idx, const char *k) {
|
||||
|
||||
LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
|
||||
StkId t;
|
||||
const TValue *aux;
|
||||
const TValue *slot;
|
||||
lua_lock(L);
|
||||
t = index2addr(L, idx);
|
||||
if (luaV_fastget(L, t, n, aux, luaH_getint)) {
|
||||
setobj2s(L, L->top, aux);
|
||||
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, aux);
|
||||
luaV_finishget(L, t, L->top - 1, L->top - 1, slot);
|
||||
}
|
||||
lua_unlock(L);
|
||||
return ttnov(L->top - 1);
|
||||
@@ -684,12 +685,12 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
|
||||
LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
|
||||
Table *t;
|
||||
lua_lock(L);
|
||||
luaC_checkGC(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);
|
||||
}
|
||||
|
||||
@@ -741,15 +742,15 @@ LUA_API int lua_getuservalue (lua_State *L, int idx) {
|
||||
** 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 *aux;
|
||||
const TValue *slot;
|
||||
TString *str = luaS_new(L, k);
|
||||
api_checknelems(L, 1);
|
||||
if (luaV_fastset(L, t, str, aux, luaH_getstr, L->top - 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, aux);
|
||||
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 */
|
||||
@@ -782,16 +783,16 @@ LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
|
||||
|
||||
LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
|
||||
StkId t;
|
||||
const TValue *aux;
|
||||
const TValue *slot;
|
||||
lua_lock(L);
|
||||
api_checknelems(L, 1);
|
||||
t = index2addr(L, idx);
|
||||
if (luaV_fastset(L, t, n, aux, luaH_getint, L->top - 1))
|
||||
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, aux);
|
||||
luaV_finishset(L, t, L->top - 1, L->top - 2, slot);
|
||||
L->top -= 2; /* pop value and key */
|
||||
}
|
||||
lua_unlock(L);
|
||||
@@ -1012,10 +1013,9 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
|
||||
return status;
|
||||
}
|
||||
|
||||
static Proto * cloneproto (lua_State *L, const Proto *src) {
|
||||
static void cloneproto (lua_State *L, Proto *f, const Proto *src) {
|
||||
/* copy constants and nested proto */
|
||||
int i,n;
|
||||
Proto *f = luaF_newproto(L, src->sp);
|
||||
n = src->sp->sizek;
|
||||
f->k=luaM_newvector(L,n,TValue);
|
||||
for (i=0; i<n; i++) setnilvalue(&f->k[i]);
|
||||
@@ -1033,9 +1033,9 @@ static Proto * cloneproto (lua_State *L, const Proto *src) {
|
||||
f->p=luaM_newvector(L,n,struct Proto *);
|
||||
for (i=0; i<n; i++) f->p[i]=NULL;
|
||||
for (i=0; i<n; i++) {
|
||||
f->p[i]=cloneproto(L, src->p[i]);
|
||||
f->p[i]= luaF_newproto(L, src->p[i]->sp);
|
||||
cloneproto(L, f->p[i], src->p[i]);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
LUA_API void lua_clonefunction (lua_State *L, const void * fp) {
|
||||
@@ -1049,9 +1049,10 @@ LUA_API void lua_clonefunction (lua_State *L, const void * fp) {
|
||||
return;
|
||||
}
|
||||
cl = luaF_newLclosure(L,f->nupvalues);
|
||||
cl->p = cloneproto(L, f->p);
|
||||
setclLvalue(L,L->top,cl);
|
||||
api_incr_top(L);
|
||||
cl->p = luaF_newproto(L, f->p->sp);
|
||||
cloneproto(L, cl->p, f->p);
|
||||
luaF_initupvals(L, cl);
|
||||
|
||||
if (cl->nupvalues >= 1) { /* does it have an upvalue? */
|
||||
@@ -1193,7 +1194,6 @@ LUA_API void lua_concat (lua_State *L, int n) {
|
||||
lua_lock(L);
|
||||
api_checknelems(L, n);
|
||||
if (n >= 2) {
|
||||
luaC_checkGC(L);
|
||||
luaV_concat(L, n);
|
||||
}
|
||||
else if (n == 0) { /* push empty string */
|
||||
@@ -1201,6 +1201,7 @@ LUA_API void lua_concat (lua_State *L, int n) {
|
||||
api_incr_top(L);
|
||||
}
|
||||
/* else n == 1; nothing to do */
|
||||
luaC_checkGC(L);
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
@@ -1236,10 +1237,10 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {
|
||||
LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
|
||||
Udata *u;
|
||||
lua_lock(L);
|
||||
luaC_checkGC(L);
|
||||
u = luaS_newudata(L, size);
|
||||
setuvalue(L, L->top, u);
|
||||
api_incr_top(L);
|
||||
luaC_checkGC(L);
|
||||
lua_unlock(L);
|
||||
return getudatamem(u);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lapi.h,v 2.9 2015/03/06 19:49:50 roberto Exp $
|
||||
** $Id: lapi.h,v 2.9.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Auxiliary functions from Lua API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lauxlib.c,v 1.284 2015/11/19 19:16:22 roberto Exp $
|
||||
** $Id: lauxlib.c,v 1.289.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Auxiliary functions for building Lua libraries
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -17,7 +17,8 @@
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* This file uses only the official API of Lua.
|
||||
/*
|
||||
** This file uses only the official API of Lua.
|
||||
** Any function declared here could be written as an application function.
|
||||
*/
|
||||
|
||||
@@ -68,12 +69,11 @@ static int findfield (lua_State *L, int objidx, int level) {
|
||||
|
||||
/*
|
||||
** Search for a name for a function in all loaded modules
|
||||
** (registry._LOADED).
|
||||
*/
|
||||
static int pushglobalfuncname (lua_State *L, lua_Debug *ar) {
|
||||
int top = lua_gettop(L);
|
||||
lua_getinfo(L, "f", ar); /* push function */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
|
||||
if (findfield(L, top + 1, 2)) {
|
||||
const char *name = lua_tostring(L, -1);
|
||||
if (strncmp(name, "_G.", 3) == 0) { /* name start with '_G.'? */
|
||||
@@ -198,6 +198,10 @@ static void tag_error (lua_State *L, int arg, int tag) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** The use of 'lua_pushfstring' ensures this function does not
|
||||
** need reserved stack space when called.
|
||||
*/
|
||||
LUALIB_API void luaL_where (lua_State *L, int level) {
|
||||
lua_Debug ar;
|
||||
if (lua_getstack(L, level, &ar)) { /* check function at level */
|
||||
@@ -207,10 +211,15 @@ LUALIB_API void luaL_where (lua_State *L, int level) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
lua_pushliteral(L, ""); /* else, no information available... */
|
||||
lua_pushfstring(L, ""); /* else, no information available... */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Again, the use of 'lua_pushvfstring' ensures this function does
|
||||
** not need reserved stack space when called. (At worst, it generates
|
||||
** an error with "stack overflow" instead of the given message.)
|
||||
*/
|
||||
LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
@@ -349,10 +358,15 @@ LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Ensures the stack has at least 'space' extra slots, raising an error
|
||||
** if it cannot fulfill the request. (The error handling needs a few
|
||||
** extra slots to format the error message. In case of an error without
|
||||
** this extra space, Lua will generate the same 'stack overflow' error,
|
||||
** but without 'msg'.)
|
||||
*/
|
||||
LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) {
|
||||
/* keep some extra space to run error routines, if needed */
|
||||
const int extra = LUA_MINSTACK;
|
||||
if (!lua_checkstack(L, space + extra)) {
|
||||
if (!lua_checkstack(L, space)) {
|
||||
if (msg)
|
||||
luaL_error(L, "stack overflow (%s)", msg);
|
||||
else
|
||||
@@ -678,7 +692,7 @@ static int skipcomment (LoadF *lf, int *cp) {
|
||||
if (c == '#') { /* first line is a comment (Unix exec. file)? */
|
||||
do { /* skip first line */
|
||||
c = getc(lf->f);
|
||||
} while (c != EOF && c != '\n') ;
|
||||
} while (c != EOF && c != '\n');
|
||||
*cp = getc(lf->f); /* skip end-of-line, if present */
|
||||
return 1; /* there was a comment */
|
||||
}
|
||||
@@ -794,13 +808,17 @@ LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) {
|
||||
|
||||
|
||||
LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
|
||||
if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */
|
||||
if (luaL_callmeta(L, idx, "__tostring")) { /* metafield? */
|
||||
if (!lua_isstring(L, -1))
|
||||
luaL_error(L, "'__tostring' must return a string");
|
||||
}
|
||||
else {
|
||||
switch (lua_type(L, idx)) {
|
||||
case LUA_TNUMBER: {
|
||||
if (lua_isinteger(L, idx))
|
||||
lua_pushfstring(L, "%I", lua_tointeger(L, idx));
|
||||
lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx));
|
||||
else
|
||||
lua_pushfstring(L, "%f", lua_tonumber(L, idx));
|
||||
lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx));
|
||||
break;
|
||||
}
|
||||
case LUA_TSTRING:
|
||||
@@ -812,10 +830,15 @@ LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
|
||||
case LUA_TNIL:
|
||||
lua_pushliteral(L, "nil");
|
||||
break;
|
||||
default:
|
||||
lua_pushfstring(L, "%s: %p", luaL_typename(L, idx),
|
||||
lua_topointer(L, idx));
|
||||
default: {
|
||||
int tt = luaL_getmetafield(L, idx, "__name"); /* try name */
|
||||
const char *kind = (tt == LUA_TSTRING) ? lua_tostring(L, -1) :
|
||||
luaL_typename(L, idx);
|
||||
lua_pushfstring(L, "%s: %p", kind, lua_topointer(L, idx));
|
||||
if (tt != LUA_TNIL)
|
||||
lua_remove(L, -2); /* remove '__name' */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return lua_tolstring(L, -1, len);
|
||||
@@ -867,23 +890,23 @@ static int libsize (const luaL_Reg *l) {
|
||||
|
||||
/*
|
||||
** Find or create a module table with a given name. The function
|
||||
** first looks at the _LOADED table and, if that fails, try a
|
||||
** first looks at the LOADED table and, if that fails, try a
|
||||
** global variable with that name. In any case, leaves on the stack
|
||||
** the module table.
|
||||
*/
|
||||
LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname,
|
||||
int sizehint) {
|
||||
luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); /* get _LOADED table */
|
||||
if (lua_getfield(L, -1, modname) != LUA_TTABLE) { /* no _LOADED[modname]? */
|
||||
luaL_findtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE, 1);
|
||||
if (lua_getfield(L, -1, modname) != LUA_TTABLE) { /* no LOADED[modname]? */
|
||||
lua_pop(L, 1); /* remove previous result */
|
||||
/* try global variable (and create one if it does not exist) */
|
||||
lua_pushglobaltable(L);
|
||||
if (luaL_findtable(L, 0, modname, sizehint) != NULL)
|
||||
luaL_error(L, "name conflict for module '%s'", modname);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -3, modname); /* _LOADED[modname] = new table */
|
||||
lua_setfield(L, -3, modname); /* LOADED[modname] = new table */
|
||||
}
|
||||
lua_remove(L, -2); /* remove _LOADED table */
|
||||
lua_remove(L, -2); /* remove LOADED table */
|
||||
}
|
||||
|
||||
|
||||
@@ -947,17 +970,17 @@ LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) {
|
||||
*/
|
||||
LUALIB_API void luaL_requiref (lua_State *L, const char *modname,
|
||||
lua_CFunction openf, int glb) {
|
||||
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
|
||||
lua_getfield(L, -1, modname); /* _LOADED[modname] */
|
||||
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
|
||||
lua_getfield(L, -1, modname); /* LOADED[modname] */
|
||||
if (!lua_toboolean(L, -1)) { /* package not already loaded? */
|
||||
lua_pop(L, 1); /* remove field */
|
||||
lua_pushcfunction(L, openf);
|
||||
lua_pushstring(L, modname); /* argument to open function */
|
||||
lua_call(L, 1, 1); /* call 'openf' to open module */
|
||||
lua_pushvalue(L, -1); /* make copy of module (call result) */
|
||||
lua_setfield(L, -3, modname); /* _LOADED[modname] = module */
|
||||
lua_setfield(L, -3, modname); /* LOADED[modname] = module */
|
||||
}
|
||||
lua_remove(L, -2); /* remove _LOADED table */
|
||||
lua_remove(L, -2); /* remove LOADED table */
|
||||
if (glb) {
|
||||
lua_pushvalue(L, -1); /* copy of module */
|
||||
lua_setglobal(L, modname); /* _G[modname] = module */
|
||||
@@ -1015,7 +1038,7 @@ LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) {
|
||||
luaL_error(L, "multiple Lua VMs detected");
|
||||
else if (*v != ver)
|
||||
luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f",
|
||||
ver, *v);
|
||||
(LUAI_UACNUMBER)ver, (LUAI_UACNUMBER)*v);
|
||||
}
|
||||
|
||||
// use clonefunction
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lauxlib.h,v 1.129 2015/11/23 11:29:43 roberto Exp $
|
||||
** $Id: lauxlib.h,v 1.131.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Auxiliary functions for building Lua libraries
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -16,10 +16,18 @@
|
||||
|
||||
|
||||
|
||||
/* extra error code for 'luaL_load' */
|
||||
/* extra error code for 'luaL_loadfilex' */
|
||||
#define LUA_ERRFILE (LUA_ERRERR+1)
|
||||
|
||||
|
||||
/* key, in the registry, for table of loaded modules */
|
||||
#define LUA_LOADED_TABLE "_LOADED"
|
||||
|
||||
|
||||
/* key, in the registry, for table of preloaded loaders */
|
||||
#define LUA_PRELOAD_TABLE "_PRELOAD"
|
||||
|
||||
|
||||
typedef struct luaL_Reg {
|
||||
const char *name;
|
||||
lua_CFunction func;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lbaselib.c,v 1.312 2015/10/29 15:21:04 roberto Exp $
|
||||
** $Id: lbaselib.c,v 1.314.1.1 2017/04/19 17:39:34 roberto Exp $
|
||||
** Basic library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -102,8 +102,8 @@ static int luaB_tonumber (lua_State *L) {
|
||||
static int luaB_error (lua_State *L) {
|
||||
int level = (int)luaL_optinteger(L, 2, 1);
|
||||
lua_settop(L, 1);
|
||||
if (lua_isstring(L, 1) && level > 0) { /* add extra information? */
|
||||
luaL_where(L, level);
|
||||
if (lua_type(L, 1) == LUA_TSTRING && level > 0) {
|
||||
luaL_where(L, level); /* add extra information */
|
||||
lua_pushvalue(L, 1);
|
||||
lua_concat(L, 2);
|
||||
}
|
||||
@@ -208,8 +208,8 @@ static int luaB_type (lua_State *L) {
|
||||
|
||||
static int pairsmeta (lua_State *L, const char *method, int iszero,
|
||||
lua_CFunction iter) {
|
||||
luaL_checkany(L, 1);
|
||||
if (luaL_getmetafield(L, 1, method) == LUA_TNIL) { /* no metamethod? */
|
||||
luaL_checktype(L, 1, LUA_TTABLE); /* argument must be a table */
|
||||
lua_pushcfunction(L, iter); /* will return generator, */
|
||||
lua_pushvalue(L, 1); /* state, */
|
||||
if (iszero) lua_pushinteger(L, 0); /* and initial value */
|
||||
@@ -251,9 +251,8 @@ static int ipairsaux (lua_State *L) {
|
||||
|
||||
|
||||
/*
|
||||
** This function will use either 'ipairsaux' or 'ipairsaux_raw' to
|
||||
** traverse a table, depending on whether the table has metamethods
|
||||
** that can affect the traversal.
|
||||
** 'ipairs' function. Returns 'ipairsaux', given "table", 0.
|
||||
** (The given "table" may not be a table.)
|
||||
*/
|
||||
static int luaB_ipairs (lua_State *L) {
|
||||
#if defined(LUA_COMPAT_IPAIRS)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lbitlib.c,v 1.30 2015/11/11 19:08:09 roberto Exp $
|
||||
** $Id: lbitlib.c,v 1.30.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Standard library for bitwise operations
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
702
3rd/lua/lcode.c
702
3rd/lua/lcode.c
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lcode.h,v 1.63 2013/12/30 20:47:58 roberto Exp $
|
||||
** $Id: lcode.h,v 1.64.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Code generator for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -40,7 +40,8 @@ typedef enum BinOpr {
|
||||
typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
|
||||
|
||||
|
||||
#define getcode(fs,e) ((fs)->f->sp->code[(e)->u.info])
|
||||
/* get (pointer to) instruction of given 'expdesc' */
|
||||
#define getinstruction(fs,e) ((fs)->f->sp->code[(e)->u.info])
|
||||
|
||||
#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lcorolib.c,v 1.9 2014/11/02 19:19:04 roberto Exp $
|
||||
** $Id: lcorolib.c,v 1.10.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Coroutine Library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -75,7 +75,7 @@ static int luaB_auxwrap (lua_State *L) {
|
||||
lua_State *co = lua_tothread(L, lua_upvalueindex(1));
|
||||
int r = auxresume(L, co, lua_gettop(L));
|
||||
if (r < 0) {
|
||||
if (lua_isstring(L, -1)) { /* error object is a string? */
|
||||
if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */
|
||||
luaL_where(L, 1); /* add extra info */
|
||||
lua_insert(L, -2);
|
||||
lua_concat(L, 2);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lctype.c,v 1.12 2014/11/02 19:19:04 roberto Exp $
|
||||
** $Id: lctype.c,v 1.12.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** 'ctype' functions for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lctype.h,v 1.12 2011/07/15 12:50:29 roberto Exp $
|
||||
** $Id: lctype.h,v 1.12.1.1 2013/04/12 18:48:47 roberto Exp $
|
||||
** 'ctype' functions for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldblib.c,v 1.151 2015/11/23 11:29:43 roberto Exp $
|
||||
** $Id: ldblib.c,v 1.151.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Interface from Lua to its debug API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldebug.c,v 2.117 2015/11/02 18:48:07 roberto Exp $
|
||||
** $Id: ldebug.c,v 2.121.1.2 2017/07/10 17:21:50 roberto Exp $
|
||||
** Debug Interface
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -38,7 +38,8 @@
|
||||
#define ci_func(ci) (clLvalue((ci)->func))
|
||||
|
||||
|
||||
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
|
||||
static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
|
||||
const char **name);
|
||||
|
||||
|
||||
static int currentpc (CallInfo *ci) {
|
||||
@@ -69,7 +70,13 @@ static void swapextra (lua_State *L) {
|
||||
|
||||
|
||||
/*
|
||||
** this function can be called asynchronous (e.g. during a signal)
|
||||
** This function can be called asynchronously (e.g. during a signal).
|
||||
** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by
|
||||
** 'resethookcount') are for debug only, and it is no problem if they
|
||||
** get arbitrary values (causes at most one wrong hook call). 'hookmask'
|
||||
** is an atomic value. We assume that pointers are atomic too (e.g., gcc
|
||||
** ensures that for all platforms where it runs). Moreover, 'hook' is
|
||||
** always checked before being called (see 'luaD_hook').
|
||||
*/
|
||||
LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
|
||||
if (func == NULL || mask == 0) { /* turn off hooks? */
|
||||
@@ -118,7 +125,7 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
|
||||
|
||||
|
||||
static const char *upvalname (Proto *p, int uv) {
|
||||
TString *s = check_exp(uv < p->sizeupvalues, p->sp->upvalues[uv].name);
|
||||
TString *s = check_exp(uv < p->sp->sizeupvalues, p->sp->upvalues[uv].name);
|
||||
if (s == NULL) return "?";
|
||||
else return getstr(s);
|
||||
}
|
||||
@@ -238,6 +245,20 @@ static void collectvalidlines (lua_State *L, Closure *f) {
|
||||
}
|
||||
|
||||
|
||||
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
|
||||
if (ci == NULL) /* no 'ci'? */
|
||||
return NULL; /* no info */
|
||||
else if (ci->callstatus & CIST_FIN) { /* is this a finalizer? */
|
||||
*name = "__gc";
|
||||
return "metamethod"; /* report it as such */
|
||||
}
|
||||
/* calling function is a known Lua function? */
|
||||
else if (!(ci->callstatus & CIST_TAIL) && isLua(ci->previous))
|
||||
return funcnamefromcode(L, ci->previous, name);
|
||||
else return NULL; /* no way to find a name */
|
||||
}
|
||||
|
||||
|
||||
static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
|
||||
Closure *f, CallInfo *ci) {
|
||||
int status = 1;
|
||||
@@ -268,11 +289,7 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
|
||||
break;
|
||||
}
|
||||
case 'n': {
|
||||
/* calling function is a known Lua function? */
|
||||
if (ci && !(ci->callstatus & CIST_TAIL) && isLua(ci->previous))
|
||||
ar->namewhat = getfuncname(L, ci->previous, &ar->name);
|
||||
else
|
||||
ar->namewhat = NULL;
|
||||
ar->namewhat = getfuncname(L, ci, &ar->name);
|
||||
if (ar->namewhat == NULL) {
|
||||
ar->namewhat = ""; /* not found */
|
||||
ar->name = NULL;
|
||||
@@ -465,8 +482,15 @@ static const char *getobjname (Proto *p, int lastpc, int reg,
|
||||
}
|
||||
|
||||
|
||||
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
|
||||
TMS tm = (TMS)0; /* to avoid warnings */
|
||||
/*
|
||||
** Try to find a name for a function based on the code that called it.
|
||||
** (Only works when function was called by a Lua function.)
|
||||
** Returns what the name is (e.g., "for iterator", "method",
|
||||
** "metamethod") and sets '*name' to point to the name.
|
||||
*/
|
||||
static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
|
||||
const char **name) {
|
||||
TMS tm = (TMS)0; /* (initial value avoids warnings) */
|
||||
Proto *p = ci_func(ci)->p; /* calling function */
|
||||
int pc = currentpc(ci); /* calling instruction index */
|
||||
Instruction i = p->sp->code[pc]; /* calling instruction */
|
||||
@@ -476,13 +500,13 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
|
||||
}
|
||||
switch (GET_OPCODE(i)) {
|
||||
case OP_CALL:
|
||||
case OP_TAILCALL: /* get function name */
|
||||
return getobjname(p, pc, GETARG_A(i), name);
|
||||
case OP_TAILCALL:
|
||||
return getobjname(p, pc, GETARG_A(i), name); /* get function name */
|
||||
case OP_TFORCALL: { /* for iterator */
|
||||
*name = "for iterator";
|
||||
return "for iterator";
|
||||
}
|
||||
/* all other instructions can call only through metamethods */
|
||||
/* other instructions can do calls through metamethods */
|
||||
case OP_SELF: case OP_GETTABUP: case OP_GETTABLE:
|
||||
tm = TM_INDEX;
|
||||
break;
|
||||
@@ -503,7 +527,8 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
|
||||
case OP_EQ: tm = TM_EQ; break;
|
||||
case OP_LT: tm = TM_LT; break;
|
||||
case OP_LE: tm = TM_LE; break;
|
||||
default: lua_assert(0); /* other instructions cannot call a function */
|
||||
default:
|
||||
return NULL; /* cannot find a reasonable name */
|
||||
}
|
||||
*name = getstr(G(L)->tmname[tm]);
|
||||
return "metamethod";
|
||||
@@ -558,7 +583,7 @@ static const char *varinfo (lua_State *L, const TValue *o) {
|
||||
|
||||
|
||||
l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
|
||||
const char *t = objtypename(o);
|
||||
const char *t = luaT_objtypename(L, o);
|
||||
luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o));
|
||||
}
|
||||
|
||||
@@ -590,9 +615,9 @@ l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) {
|
||||
|
||||
|
||||
l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
|
||||
const char *t1 = objtypename(p1);
|
||||
const char *t2 = objtypename(p2);
|
||||
if (t1 == t2)
|
||||
const char *t1 = luaT_objtypename(L, p1);
|
||||
const char *t2 = luaT_objtypename(L, p2);
|
||||
if (strcmp(t1, t2) == 0)
|
||||
luaG_runerror(L, "attempt to compare two %s values", t1);
|
||||
else
|
||||
luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
|
||||
@@ -628,6 +653,7 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
|
||||
CallInfo *ci = L->ci;
|
||||
const char *msg;
|
||||
va_list argp;
|
||||
luaC_checkGC(L); /* error message uses memory */
|
||||
va_start(argp, fmt);
|
||||
msg = luaO_pushvfstring(L, fmt, argp); /* format message */
|
||||
va_end(argp);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldebug.h,v 2.14 2015/05/22 17:45:56 roberto Exp $
|
||||
** $Id: ldebug.h,v 2.14.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Auxiliary functions from Debug Interface module
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
235
3rd/lua/ldo.c
235
3rd/lua/ldo.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldo.c,v 2.150 2015/11/19 19:16:22 roberto Exp $
|
||||
** $Id: ldo.c,v 2.157.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Stack and Call structure of Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -211,9 +211,9 @@ static int stackinuse (lua_State *L) {
|
||||
CallInfo *ci;
|
||||
StkId lim = L->top;
|
||||
for (ci = L->ci; ci != NULL; ci = ci->previous) {
|
||||
lua_assert(ci->top <= L->stack_last);
|
||||
if (lim < ci->top) lim = ci->top;
|
||||
}
|
||||
lua_assert(lim <= L->stack_last);
|
||||
return cast_int(lim - L->stack) + 1; /* part of stack in use */
|
||||
}
|
||||
|
||||
@@ -221,16 +221,19 @@ static int stackinuse (lua_State *L) {
|
||||
void luaD_shrinkstack (lua_State *L) {
|
||||
int inuse = stackinuse(L);
|
||||
int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK;
|
||||
if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK;
|
||||
if (L->stacksize > LUAI_MAXSTACK) /* was handling stack overflow? */
|
||||
if (goodsize > LUAI_MAXSTACK)
|
||||
goodsize = LUAI_MAXSTACK; /* respect stack limit */
|
||||
if (L->stacksize > LUAI_MAXSTACK) /* had been handling stack overflow? */
|
||||
luaE_freeCI(L); /* free all CIs (list grew because of an error) */
|
||||
else
|
||||
luaE_shrinkCI(L); /* shrink list */
|
||||
if (inuse <= LUAI_MAXSTACK && /* not handling stack overflow? */
|
||||
goodsize < L->stacksize) /* trying to shrink? */
|
||||
luaD_reallocstack(L, goodsize); /* shrink it */
|
||||
else
|
||||
condmovestack(L,,); /* don't change stack (change only for debugging) */
|
||||
/* if thread is currently not handling a stack overflow and its
|
||||
good size is smaller than current size, shrink its stack */
|
||||
if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) &&
|
||||
goodsize < L->stacksize)
|
||||
luaD_reallocstack(L, goodsize);
|
||||
else /* don't change stack */
|
||||
condmovestack(L,{},{}); /* (change only for debugging) */
|
||||
}
|
||||
|
||||
|
||||
@@ -242,9 +245,14 @@ void luaD_inctop (lua_State *L) {
|
||||
/* }================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
** Call a hook for the given event. Make sure there is a hook to be
|
||||
** called. (Both 'L->hook' and 'L->hookmask', which triggers this
|
||||
** function, can be changed asynchronously by signals.)
|
||||
*/
|
||||
void luaD_hook (lua_State *L, int event, int line) {
|
||||
lua_Hook hook = L->hook;
|
||||
if (hook && L->allowhook) {
|
||||
if (hook && L->allowhook) { /* make sure there is a hook */
|
||||
CallInfo *ci = L->ci;
|
||||
ptrdiff_t top = savestack(L, L->top);
|
||||
ptrdiff_t ci_top = savestack(L, ci->top);
|
||||
@@ -317,86 +325,6 @@ static void tryfuncTM (lua_State *L, StkId func) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L)))
|
||||
|
||||
|
||||
/* macro to check stack size, preserving 'p' */
|
||||
#define checkstackp(L,n,p) \
|
||||
luaD_checkstackaux(L, n, \
|
||||
ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \
|
||||
luaC_checkGC(L), /* stack grow uses memory */ \
|
||||
p = restorestack(L, t__)) /* 'pos' part: restore 'p' */
|
||||
|
||||
|
||||
/*
|
||||
** Prepares a function call: checks the stack, creates a new CallInfo
|
||||
** entry, fills in the relevant information, calls hook if needed.
|
||||
** If function is a C function, does the call, too. (Otherwise, leave
|
||||
** the execution ('luaV_execute') to the caller, to allow stackless
|
||||
** calls.) Returns true iff function has been executed (C function).
|
||||
*/
|
||||
int luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||
lua_CFunction f;
|
||||
CallInfo *ci;
|
||||
switch (ttype(func)) {
|
||||
case LUA_TCCL: /* C closure */
|
||||
f = clCvalue(func)->f;
|
||||
goto Cfunc;
|
||||
case LUA_TLCF: /* light C function */
|
||||
f = fvalue(func);
|
||||
Cfunc: {
|
||||
int n; /* number of returns */
|
||||
checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
|
||||
ci = next_ci(L); /* now 'enter' new function */
|
||||
ci->nresults = nresults;
|
||||
ci->func = func;
|
||||
ci->top = L->top + LUA_MINSTACK;
|
||||
lua_assert(ci->top <= L->stack_last);
|
||||
ci->callstatus = 0;
|
||||
if (L->hookmask & LUA_MASKCALL)
|
||||
luaD_hook(L, LUA_HOOKCALL, -1);
|
||||
lua_unlock(L);
|
||||
n = (*f)(L); /* do the actual call */
|
||||
lua_lock(L);
|
||||
api_checknelems(L, n);
|
||||
luaD_poscall(L, ci, L->top - n, n);
|
||||
return 1;
|
||||
}
|
||||
case LUA_TLCL: { /* Lua function: prepare its call */
|
||||
StkId base;
|
||||
SharedProto *p = clLvalue(func)->p->sp;
|
||||
int n = cast_int(L->top - func) - 1; /* number of real arguments */
|
||||
int fsize = p->maxstacksize; /* frame size */
|
||||
checkstackp(L, fsize, func);
|
||||
if (p->is_vararg != 1) { /* do not use vararg? */
|
||||
for (; n < p->numparams; n++)
|
||||
setnilvalue(L->top++); /* complete missing arguments */
|
||||
base = func + 1;
|
||||
}
|
||||
else
|
||||
base = adjust_varargs(L, p, n);
|
||||
ci = next_ci(L); /* now 'enter' new function */
|
||||
ci->nresults = nresults;
|
||||
ci->func = func;
|
||||
ci->u.l.base = base;
|
||||
L->top = ci->top = base + fsize;
|
||||
lua_assert(ci->top <= L->stack_last);
|
||||
ci->u.l.savedpc = p->code; /* starting point */
|
||||
ci->callstatus = CIST_LUA;
|
||||
if (L->hookmask & LUA_MASKCALL)
|
||||
callhook(L, ci);
|
||||
return 0;
|
||||
}
|
||||
default: { /* not a function */
|
||||
checkstackp(L, 1, func); /* ensure space for metamethod */
|
||||
tryfuncTM(L, func); /* try to get '__call' metamethod */
|
||||
return luaD_precall(L, func, nresults); /* now it must be a function */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'.
|
||||
** Handle most typical cases (zero results for commands, one result for
|
||||
@@ -463,6 +391,86 @@ int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L)))
|
||||
|
||||
|
||||
/* macro to check stack size, preserving 'p' */
|
||||
#define checkstackp(L,n,p) \
|
||||
luaD_checkstackaux(L, n, \
|
||||
ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \
|
||||
luaC_checkGC(L), /* stack grow uses memory */ \
|
||||
p = restorestack(L, t__)) /* 'pos' part: restore 'p' */
|
||||
|
||||
|
||||
/*
|
||||
** Prepares a function call: checks the stack, creates a new CallInfo
|
||||
** entry, fills in the relevant information, calls hook if needed.
|
||||
** If function is a C function, does the call, too. (Otherwise, leave
|
||||
** the execution ('luaV_execute') to the caller, to allow stackless
|
||||
** calls.) Returns true iff function has been executed (C function).
|
||||
*/
|
||||
int luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||
lua_CFunction f;
|
||||
CallInfo *ci;
|
||||
switch (ttype(func)) {
|
||||
case LUA_TCCL: /* C closure */
|
||||
f = clCvalue(func)->f;
|
||||
goto Cfunc;
|
||||
case LUA_TLCF: /* light C function */
|
||||
f = fvalue(func);
|
||||
Cfunc: {
|
||||
int n; /* number of returns */
|
||||
checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
|
||||
ci = next_ci(L); /* now 'enter' new function */
|
||||
ci->nresults = nresults;
|
||||
ci->func = func;
|
||||
ci->top = L->top + LUA_MINSTACK;
|
||||
lua_assert(ci->top <= L->stack_last);
|
||||
ci->callstatus = 0;
|
||||
if (L->hookmask & LUA_MASKCALL)
|
||||
luaD_hook(L, LUA_HOOKCALL, -1);
|
||||
lua_unlock(L);
|
||||
n = (*f)(L); /* do the actual call */
|
||||
lua_lock(L);
|
||||
api_checknelems(L, n);
|
||||
luaD_poscall(L, ci, L->top - n, n);
|
||||
return 1;
|
||||
}
|
||||
case LUA_TLCL: { /* Lua function: prepare its call */
|
||||
StkId base;
|
||||
SharedProto *p = clLvalue(func)->p->sp;
|
||||
int n = cast_int(L->top - func) - 1; /* number of real arguments */
|
||||
int fsize = p->maxstacksize; /* frame size */
|
||||
checkstackp(L, fsize, func);
|
||||
if (p->is_vararg)
|
||||
base = adjust_varargs(L, p, n);
|
||||
else { /* non vararg function */
|
||||
for (; n < p->numparams; n++)
|
||||
setnilvalue(L->top++); /* complete missing arguments */
|
||||
base = func + 1;
|
||||
}
|
||||
ci = next_ci(L); /* now 'enter' new function */
|
||||
ci->nresults = nresults;
|
||||
ci->func = func;
|
||||
ci->u.l.base = base;
|
||||
L->top = ci->top = base + fsize;
|
||||
lua_assert(ci->top <= L->stack_last);
|
||||
ci->u.l.savedpc = p->code; /* starting point */
|
||||
ci->callstatus = CIST_LUA;
|
||||
if (L->hookmask & LUA_MASKCALL)
|
||||
callhook(L, ci);
|
||||
return 0;
|
||||
}
|
||||
default: { /* not a function */
|
||||
checkstackp(L, 1, func); /* ensure space for metamethod */
|
||||
tryfuncTM(L, func); /* try to get '__call' metamethod */
|
||||
return luaD_precall(L, func, nresults); /* now it must be a function */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Check appropriate error for stack overflow ("regular" overflow or
|
||||
** overflow while handling stack overflow). If 'nCalls' is larger than
|
||||
@@ -515,19 +523,17 @@ static void finishCcall (lua_State *L, int status) {
|
||||
/* error status can only happen in a protected call */
|
||||
lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD);
|
||||
if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */
|
||||
ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */
|
||||
L->errfunc = ci->u.c.old_errfunc;
|
||||
ci->callstatus &= ~CIST_YPCALL; /* continuation is also inside it */
|
||||
L->errfunc = ci->u.c.old_errfunc; /* with the same error function */
|
||||
}
|
||||
/* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already
|
||||
handled */
|
||||
adjustresults(L, ci->nresults);
|
||||
/* call continuation function */
|
||||
lua_unlock(L);
|
||||
n = (*ci->u.c.k)(L, status, ci->u.c.ctx);
|
||||
n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */
|
||||
lua_lock(L);
|
||||
api_checknelems(L, n);
|
||||
/* finish 'luaD_precall' */
|
||||
luaD_poscall(L, ci, L->top - n, n);
|
||||
luaD_poscall(L, ci, L->top - n, n); /* finish 'luaD_precall' */
|
||||
}
|
||||
|
||||
|
||||
@@ -590,15 +596,16 @@ static int recover (lua_State *L, int status) {
|
||||
|
||||
|
||||
/*
|
||||
** signal an error in the call to 'resume', not in the execution of the
|
||||
** coroutine itself. (Such errors should not be handled by any coroutine
|
||||
** error handler and should not kill the coroutine.)
|
||||
** Signal an error in the call to 'lua_resume', not in the execution
|
||||
** of the coroutine itself. (Such errors should not be handled by any
|
||||
** coroutine error handler and should not kill the coroutine.)
|
||||
*/
|
||||
static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) {
|
||||
L->top = firstArg; /* remove args from the stack */
|
||||
static int resume_error (lua_State *L, const char *msg, int narg) {
|
||||
L->top -= narg; /* remove args from the stack */
|
||||
setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */
|
||||
api_incr_top(L);
|
||||
luaD_throw(L, -1); /* jump back to 'lua_resume' */
|
||||
lua_unlock(L);
|
||||
return LUA_ERRRUN;
|
||||
}
|
||||
|
||||
|
||||
@@ -610,22 +617,15 @@ static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) {
|
||||
** coroutine.
|
||||
*/
|
||||
static void resume (lua_State *L, void *ud) {
|
||||
int nCcalls = L->nCcalls;
|
||||
int n = *(cast(int*, ud)); /* number of arguments */
|
||||
StkId firstArg = L->top - n; /* first argument */
|
||||
CallInfo *ci = L->ci;
|
||||
if (nCcalls >= LUAI_MAXCCALLS)
|
||||
resume_error(L, "C stack overflow", firstArg);
|
||||
if (L->status == LUA_OK) { /* may be starting a coroutine */
|
||||
if (ci != &L->base_ci) /* not in base level? */
|
||||
resume_error(L, "cannot resume non-suspended coroutine", firstArg);
|
||||
/* coroutine is in base level; start running it */
|
||||
if (L->status == LUA_OK) { /* starting a coroutine? */
|
||||
if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */
|
||||
luaV_execute(L); /* call it */
|
||||
}
|
||||
else if (L->status != LUA_YIELD)
|
||||
resume_error(L, "cannot resume dead coroutine", firstArg);
|
||||
else { /* resuming from previous yield */
|
||||
lua_assert(L->status == LUA_YIELD);
|
||||
L->status = LUA_OK; /* mark that it is running (again) */
|
||||
ci->func = restorestack(L, ci->extra);
|
||||
if (isLua(ci)) /* yielded inside a hook? */
|
||||
@@ -642,7 +642,6 @@ static void resume (lua_State *L, void *ud) {
|
||||
}
|
||||
unroll(L, NULL); /* run continuation */
|
||||
}
|
||||
lua_assert(nCcalls == L->nCcalls);
|
||||
}
|
||||
|
||||
|
||||
@@ -650,8 +649,16 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
|
||||
int status;
|
||||
unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */
|
||||
lua_lock(L);
|
||||
luai_userstateresume(L, nargs);
|
||||
if (L->status == LUA_OK) { /* may be starting a coroutine */
|
||||
if (L->ci != &L->base_ci) /* not in base level? */
|
||||
return resume_error(L, "cannot resume non-suspended coroutine", nargs);
|
||||
}
|
||||
else if (L->status != LUA_YIELD)
|
||||
return resume_error(L, "cannot resume dead coroutine", nargs);
|
||||
L->nCcalls = (from) ? from->nCcalls + 1 : 1;
|
||||
if (L->nCcalls >= LUAI_MAXCCALLS)
|
||||
return resume_error(L, "C stack overflow", nargs);
|
||||
luai_userstateresume(L, nargs);
|
||||
L->nny = 0; /* allow yields */
|
||||
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
|
||||
status = luaD_rawrunprotected(L, resume, &nargs);
|
||||
@@ -768,7 +775,7 @@ static void f_parser (lua_State *L, void *ud) {
|
||||
checkmode(L, p->mode, "text");
|
||||
cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
|
||||
}
|
||||
lua_assert(cl->nupvalues == cl->p->sizeupvalues);
|
||||
lua_assert(cl->nupvalues == cl->p->sp->sizeupvalues);
|
||||
luaF_initupvals(L, cl);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldo.h,v 2.28 2015/11/23 11:29:43 roberto Exp $
|
||||
** $Id: ldo.h,v 2.29.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Stack and Call structure of Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -25,7 +25,7 @@
|
||||
{ pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); }
|
||||
|
||||
/* In general, 'pre'/'pos' are empty (nothing to save) */
|
||||
#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,,)
|
||||
#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldump.c,v 2.37 2015/10/08 15:53:49 roberto Exp $
|
||||
** $Id: ldump.c,v 2.37.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** save precompiled Lua chunks
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lfunc.c,v 2.45 2014/11/02 19:19:04 roberto Exp $
|
||||
** $Id: lfunc.c,v 2.45.1.1 2017/04/19 17:39:34 roberto Exp $
|
||||
** Auxiliary functions to manipulate prototypes and closures
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lfunc.h,v 2.15 2015/01/13 15:49:11 roberto Exp $
|
||||
** $Id: lfunc.h,v 2.15.1.1 2017/04/19 17:39:34 roberto Exp $
|
||||
** Auxiliary functions to manipulate prototypes and closures
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lgc.c,v 2.210 2015/11/03 18:10:44 roberto Exp $
|
||||
** $Id: lgc.c,v 2.215.1.2 2017/08/31 16:15:27 roberto Exp $
|
||||
** Garbage Collector
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -468,7 +468,7 @@ static lu_mem traversetable (global_State *g, Table *h) {
|
||||
else /* not weak */
|
||||
traversestrongtable(g, h);
|
||||
return sizeof(Table) + sizeof(TValue) * h->sizearray +
|
||||
sizeof(Node) * cast(size_t, sizenode(h));
|
||||
sizeof(Node) * cast(size_t, allocsizenode(h));
|
||||
}
|
||||
|
||||
static int marksharedproto (global_State *g, SharedProto *f) {
|
||||
@@ -492,15 +492,19 @@ static int marksharedproto (global_State *g, SharedProto *f) {
|
||||
** NULL, so the use of 'markobjectN')
|
||||
*/
|
||||
static int traverseproto (global_State *g, Proto *f) {
|
||||
int i;
|
||||
int i,nk,np;
|
||||
if (f->cache && iswhite(f->cache))
|
||||
f->cache = NULL; /* allow cache to be collected */
|
||||
for (i = 0; i < f->sp->sizek; i++) /* mark literals */
|
||||
if (f->sp == NULL)
|
||||
return sizeof(Proto);
|
||||
nk = (f->k == NULL) ? 0 : f->sp->sizek;
|
||||
np = (f->p == NULL) ? 0 : f->sp->sizep;
|
||||
for (i = 0; i < nk; i++) /* mark literals */
|
||||
markvalue(g, &f->k[i]);
|
||||
for (i = 0; i < f->sp->sizep; i++) /* mark nested protos */
|
||||
for (i = 0; i < np; i++) /* mark nested protos */
|
||||
markobjectN(g, f->p[i]);
|
||||
return sizeof(Proto) + sizeof(Proto *) * f->sp->sizep +
|
||||
sizeof(TValue) * f->sp->sizek +
|
||||
return sizeof(Proto) + sizeof(Proto *) * np +
|
||||
sizeof(TValue) * nk +
|
||||
marksharedproto(g, f->sp);
|
||||
}
|
||||
|
||||
@@ -546,7 +550,7 @@ static lu_mem traversethread (global_State *g, lua_State *th) {
|
||||
StkId lim = th->stack + th->stacksize; /* real end of stack */
|
||||
for (; o < lim; o++) /* clear not-marked stack slice */
|
||||
setnilvalue(o);
|
||||
/* 'remarkupvals' may have removed thread from 'twups' list */
|
||||
/* 'remarkupvals' may have removed thread from 'twups' list */
|
||||
if (!isintwups(th) && th->openupval != NULL) {
|
||||
th->twups = g->twups; /* link it back to the list */
|
||||
g->twups = th;
|
||||
@@ -650,8 +654,9 @@ static void clearkeys (global_State *g, GCObject *l, GCObject *f) {
|
||||
for (n = gnode(h, 0); n < limit; n++) {
|
||||
if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) {
|
||||
setnilvalue(gval(n)); /* remove value ... */
|
||||
removeentry(n); /* and remove entry from table */
|
||||
}
|
||||
if (ttisnil(gval(n))) /* is entry empty? */
|
||||
removeentry(n); /* remove entry from table */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -761,14 +766,11 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
|
||||
/*
|
||||
** sweep a list until a live object (or end of list)
|
||||
*/
|
||||
static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) {
|
||||
static GCObject **sweeptolive (lua_State *L, GCObject **p) {
|
||||
GCObject **old = p;
|
||||
int i = 0;
|
||||
do {
|
||||
i++;
|
||||
p = sweeplist(L, p, 1);
|
||||
} while (p == old);
|
||||
if (n) *n += i;
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -828,7 +830,9 @@ static void GCTM (lua_State *L, int propagateerrors) {
|
||||
setobj2s(L, L->top, tm); /* push finalizer... */
|
||||
setobj2s(L, L->top + 1, &v); /* ... and its argument */
|
||||
L->top += 2; /* and (next line) call the finalizer */
|
||||
L->ci->callstatus |= CIST_FIN; /* will run a finalizer */
|
||||
status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0);
|
||||
L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */
|
||||
L->allowhook = oldah; /* restore hooks */
|
||||
g->gcrunning = running; /* restore state */
|
||||
if (status != LUA_OK && propagateerrors) { /* error while running __gc? */
|
||||
@@ -863,10 +867,10 @@ static int runafewfinalizers (lua_State *L) {
|
||||
/*
|
||||
** call all pending finalizers
|
||||
*/
|
||||
static void callallpendingfinalizers (lua_State *L, int propagateerrors) {
|
||||
static void callallpendingfinalizers (lua_State *L) {
|
||||
global_State *g = G(L);
|
||||
while (g->tobefnz)
|
||||
GCTM(L, propagateerrors);
|
||||
GCTM(L, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -916,7 +920,7 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
|
||||
if (issweepphase(g)) {
|
||||
makewhite(g, o); /* "sweep" object 'o' */
|
||||
if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */
|
||||
g->sweepgc = sweeptolive(L, g->sweepgc, NULL); /* change 'sweepgc' */
|
||||
g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */
|
||||
}
|
||||
/* search for pointer pointing to 'o' */
|
||||
for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ }
|
||||
@@ -958,19 +962,16 @@ static void setpause (global_State *g) {
|
||||
|
||||
/*
|
||||
** Enter first sweep phase.
|
||||
** The call to 'sweeptolive' makes pointer point to an object inside
|
||||
** the list (instead of to the header), so that the real sweep do not
|
||||
** need to skip objects created between "now" and the start of the real
|
||||
** sweep.
|
||||
** Returns how many objects it swept.
|
||||
** The call to 'sweeplist' tries to make pointer point to an object
|
||||
** inside the list (instead of to the header), so that the real sweep do
|
||||
** not need to skip objects created between "now" and the start of the
|
||||
** real sweep.
|
||||
*/
|
||||
static int entersweep (lua_State *L) {
|
||||
static void entersweep (lua_State *L) {
|
||||
global_State *g = G(L);
|
||||
int n = 0;
|
||||
g->gcstate = GCSswpallgc;
|
||||
lua_assert(g->sweepgc == NULL);
|
||||
g->sweepgc = sweeptolive(L, &g->allgc, &n);
|
||||
return n;
|
||||
g->sweepgc = sweeplist(L, &g->allgc, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -978,7 +979,7 @@ void luaC_freeallobjects (lua_State *L) {
|
||||
global_State *g = G(L);
|
||||
separatetobefnz(g, 1); /* separate all objects with finalizers */
|
||||
lua_assert(g->finobj == NULL);
|
||||
callallpendingfinalizers(L, 0);
|
||||
callallpendingfinalizers(L);
|
||||
lua_assert(g->tobefnz == NULL);
|
||||
g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */
|
||||
g->gckind = KGC_NORMAL;
|
||||
@@ -1071,12 +1072,11 @@ static lu_mem singlestep (lua_State *L) {
|
||||
}
|
||||
case GCSatomic: {
|
||||
lu_mem work;
|
||||
int sw;
|
||||
propagateall(g); /* make sure gray list is empty */
|
||||
work = atomic(L); /* work is what was traversed by 'atomic' */
|
||||
sw = entersweep(L);
|
||||
entersweep(L);
|
||||
g->GCestimate = gettotalbytes(g); /* first estimate */;
|
||||
return work + sw * GCSWEEPCOST;
|
||||
return work;
|
||||
}
|
||||
case GCSswpallgc: { /* sweep "regular" objects */
|
||||
return sweepstep(L, g, GCSswpfinobj, &g->finobj);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lgc.h,v 2.90 2015/10/21 18:15:15 roberto Exp $
|
||||
** $Id: lgc.h,v 2.91.1.1 2017/04/19 17:39:34 roberto Exp $
|
||||
** Garbage Collector
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -112,7 +112,7 @@
|
||||
condchangemem(L,pre,pos); }
|
||||
|
||||
/* more often than not, 'pre'/'pos' are empty */
|
||||
#define luaC_checkGC(L) luaC_condGC(L,,)
|
||||
#define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0)
|
||||
|
||||
|
||||
#define luaC_barrier(L,p,v) ( \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: linit.c,v 1.38 2015/01/05 13:48:33 roberto Exp $
|
||||
** $Id: linit.c,v 1.39.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Initialization of libraries for lua.c and other clients
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -18,10 +18,10 @@
|
||||
** open the library, which is already linked to the application.
|
||||
** For that, do the following code:
|
||||
**
|
||||
** luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
|
||||
** luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
|
||||
** lua_pushcfunction(L, luaopen_modname);
|
||||
** lua_setfield(L, -2, modname);
|
||||
** lua_pop(L, 1); // remove _PRELOAD table
|
||||
** lua_pop(L, 1); // remove PRELOAD table
|
||||
*/
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: liolib.c,v 2.148 2015/11/23 11:36:11 roberto Exp $
|
||||
** $Id: liolib.c,v 2.151.1.1 2017/04/19 17:29:57 roberto Exp $
|
||||
** Standard I/O (and system) library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -37,10 +37,11 @@
|
||||
#endif
|
||||
|
||||
/* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */
|
||||
#define l_checkmode(mode) \
|
||||
(*mode != '\0' && strchr("rwa", *(mode++)) != NULL && \
|
||||
(*mode != '+' || (++mode, 1)) && /* skip if char is '+' */ \
|
||||
(strspn(mode, L_MODEEXT) == strlen(mode)))
|
||||
static int l_checkmode (const char *mode) {
|
||||
return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL &&
|
||||
(*mode != '+' || (++mode, 1)) && /* skip if char is '+' */
|
||||
(strspn(mode, L_MODEEXT) == strlen(mode))); /* check extensions */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -205,11 +206,16 @@ static int aux_close (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
static int f_close (lua_State *L) {
|
||||
tofile(L); /* make sure argument is an open stream */
|
||||
return aux_close(L);
|
||||
}
|
||||
|
||||
|
||||
static int io_close (lua_State *L) {
|
||||
if (lua_isnone(L, 1)) /* no argument? */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */
|
||||
tofile(L); /* make sure argument is an open stream */
|
||||
return aux_close(L);
|
||||
return f_close(L);
|
||||
}
|
||||
|
||||
|
||||
@@ -375,14 +381,17 @@ static int io_lines (lua_State *L) {
|
||||
|
||||
|
||||
/* maximum length of a numeral */
|
||||
#define MAXRN 200
|
||||
#if !defined (L_MAXLENNUM)
|
||||
#define L_MAXLENNUM 200
|
||||
#endif
|
||||
|
||||
|
||||
/* auxiliary structure used by 'read_number' */
|
||||
typedef struct {
|
||||
FILE *f; /* file being read */
|
||||
int c; /* current character (look ahead) */
|
||||
int n; /* number of elements in buffer 'buff' */
|
||||
char buff[MAXRN + 1]; /* +1 for ending '\0' */
|
||||
char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */
|
||||
} RN;
|
||||
|
||||
|
||||
@@ -390,7 +399,7 @@ typedef struct {
|
||||
** Add current char to buffer (if not out of space) and read next one
|
||||
*/
|
||||
static int nextc (RN *rn) {
|
||||
if (rn->n >= MAXRN) { /* buffer overflow? */
|
||||
if (rn->n >= L_MAXLENNUM) { /* buffer overflow? */
|
||||
rn->buff[0] = '\0'; /* invalidate result */
|
||||
return 0; /* fail */
|
||||
}
|
||||
@@ -403,10 +412,10 @@ static int nextc (RN *rn) {
|
||||
|
||||
|
||||
/*
|
||||
** Accept current char if it is in 'set' (of size 1 or 2)
|
||||
** Accept current char if it is in 'set' (of size 2)
|
||||
*/
|
||||
static int test2 (RN *rn, const char *set) {
|
||||
if (rn->c == set[0] || (rn->c == set[1] && rn->c != '\0'))
|
||||
if (rn->c == set[0] || rn->c == set[1])
|
||||
return nextc(rn);
|
||||
else return 0;
|
||||
}
|
||||
@@ -435,11 +444,11 @@ static int read_number (lua_State *L, FILE *f) {
|
||||
char decp[2];
|
||||
rn.f = f; rn.n = 0;
|
||||
decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */
|
||||
decp[1] = '\0';
|
||||
decp[1] = '.'; /* always accept a dot */
|
||||
l_lockfile(rn.f);
|
||||
do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */
|
||||
test2(&rn, "-+"); /* optional signal */
|
||||
if (test2(&rn, "0")) {
|
||||
if (test2(&rn, "00")) {
|
||||
if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */
|
||||
else count = 1; /* count initial '0' as a valid digit */
|
||||
}
|
||||
@@ -615,8 +624,10 @@ static int g_write (lua_State *L, FILE *f, int arg) {
|
||||
if (lua_type(L, arg) == LUA_TNUMBER) {
|
||||
/* optimization: could be done exactly as for strings */
|
||||
int len = lua_isinteger(L, arg)
|
||||
? fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg))
|
||||
: fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg));
|
||||
? fprintf(f, LUA_INTEGER_FMT,
|
||||
(LUAI_UACINT)lua_tointeger(L, arg))
|
||||
: fprintf(f, LUA_NUMBER_FMT,
|
||||
(LUAI_UACNUMBER)lua_tonumber(L, arg));
|
||||
status = status && (len > 0);
|
||||
}
|
||||
else {
|
||||
@@ -706,7 +717,7 @@ static const luaL_Reg iolib[] = {
|
||||
** methods for file handles
|
||||
*/
|
||||
static const luaL_Reg flib[] = {
|
||||
{"close", io_close},
|
||||
{"close", f_close},
|
||||
{"flush", f_flush},
|
||||
{"lines", f_lines},
|
||||
{"read", f_read},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: llex.c,v 2.95 2015/11/19 19:16:22 roberto Exp $
|
||||
** $Id: llex.c,v 2.96.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Lexical Analyzer
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -162,7 +162,6 @@ static void inclinenumber (LexState *ls) {
|
||||
void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source,
|
||||
int firstchar) {
|
||||
ls->t.token = 0;
|
||||
ls->decpoint = '.';
|
||||
ls->L = L;
|
||||
ls->current = firstchar;
|
||||
ls->lookahead.token = TK_EOS; /* no look-ahead token */
|
||||
@@ -207,35 +206,6 @@ static int check_next2 (LexState *ls, const char *set) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** change all characters 'from' in buffer to 'to'
|
||||
*/
|
||||
static void buffreplace (LexState *ls, char from, char to) {
|
||||
if (from != to) {
|
||||
size_t n = luaZ_bufflen(ls->buff);
|
||||
char *p = luaZ_buffer(ls->buff);
|
||||
while (n--)
|
||||
if (p[n] == from) p[n] = to;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** in case of format error, try to change decimal point separator to
|
||||
** the one defined in the current locale and check again
|
||||
*/
|
||||
static void trydecpoint (LexState *ls, TValue *o) {
|
||||
char old = ls->decpoint;
|
||||
ls->decpoint = lua_getlocaledecpoint();
|
||||
buffreplace(ls, old, ls->decpoint); /* try new decimal separator */
|
||||
if (luaO_str2num(luaZ_buffer(ls->buff), o) == 0) {
|
||||
/* format error with correct decimal point: no more options */
|
||||
buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
|
||||
lexerror(ls, "malformed number", TK_FLT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* LUA_NUMBER */
|
||||
/*
|
||||
** this function is quite liberal in what it accepts, as 'luaO_str2num'
|
||||
@@ -259,9 +229,8 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) {
|
||||
else break;
|
||||
}
|
||||
save(ls, '\0');
|
||||
buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
|
||||
if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0) /* format error? */
|
||||
trydecpoint(ls, &obj); /* try to update decimal point separator */
|
||||
lexerror(ls, "malformed number", TK_FLT);
|
||||
if (ttisinteger(&obj)) {
|
||||
seminfo->i = ivalue(&obj);
|
||||
return TK_INT;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: llex.h,v 1.78 2014/10/29 15:38:24 roberto Exp $
|
||||
** $Id: llex.h,v 1.79.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Lexical Analyzer
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -69,7 +69,6 @@ typedef struct LexState {
|
||||
struct Dyndata *dyd; /* dynamic structures used by the parser */
|
||||
TString *source; /* current source name */
|
||||
TString *envn; /* environment variable name */
|
||||
char decpoint; /* locale decimal point */
|
||||
} LexState;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: llimits.h,v 1.141 2015/11/19 19:16:22 roberto Exp $
|
||||
** $Id: llimits.h,v 1.141.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Limits, basic types, and some other 'installation-dependent' definitions
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lmathlib.c,v 1.117 2015/10/02 15:39:23 roberto Exp $
|
||||
** $Id: lmathlib.c,v 1.119.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Standard mathematical library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -184,10 +184,13 @@ static int math_log (lua_State *L) {
|
||||
else {
|
||||
lua_Number base = luaL_checknumber(L, 2);
|
||||
#if !defined(LUA_USE_C89)
|
||||
if (base == 2.0) res = l_mathop(log2)(x); else
|
||||
if (base == l_mathop(2.0))
|
||||
res = l_mathop(log2)(x); else
|
||||
#endif
|
||||
if (base == 10.0) res = l_mathop(log10)(x);
|
||||
else res = l_mathop(log)(x)/l_mathop(log)(base);
|
||||
if (base == l_mathop(10.0))
|
||||
res = l_mathop(log10)(x);
|
||||
else
|
||||
res = l_mathop(log)(x)/l_mathop(log)(base);
|
||||
}
|
||||
lua_pushnumber(L, res);
|
||||
return 1;
|
||||
@@ -262,7 +265,7 @@ static int math_random (lua_State *L) {
|
||||
default: return luaL_error(L, "wrong number of arguments");
|
||||
}
|
||||
/* random integer in the interval [low, up] */
|
||||
luaL_argcheck(L, low <= up, 1, "interval is empty");
|
||||
luaL_argcheck(L, low <= up, 1, "interval is empty");
|
||||
luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1,
|
||||
"interval too large");
|
||||
r *= (double)(up - low) + 1.0;
|
||||
@@ -281,9 +284,9 @@ static int math_randomseed (lua_State *L) {
|
||||
static int math_type (lua_State *L) {
|
||||
if (lua_type(L, 1) == LUA_TNUMBER) {
|
||||
if (lua_isinteger(L, 1))
|
||||
lua_pushliteral(L, "integer");
|
||||
lua_pushliteral(L, "integer");
|
||||
else
|
||||
lua_pushliteral(L, "float");
|
||||
lua_pushliteral(L, "float");
|
||||
}
|
||||
else {
|
||||
luaL_checkany(L, 1);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lmem.c,v 1.91 2015/03/06 19:45:54 roberto Exp $
|
||||
** $Id: lmem.c,v 1.91.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Interface to Memory Manager
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lmem.h,v 1.43 2014/12/19 17:26:14 roberto Exp $
|
||||
** $Id: lmem.h,v 1.43.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Interface to Memory Manager
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: loadlib.c,v 1.127 2015/11/23 11:30:45 roberto Exp $
|
||||
** $Id: loadlib.c,v 1.130.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Dynamic library loader for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
**
|
||||
@@ -25,40 +25,9 @@
|
||||
|
||||
|
||||
/*
|
||||
** LUA_PATH_VAR and LUA_CPATH_VAR are the names of the environment
|
||||
** variables that Lua check to set its paths.
|
||||
*/
|
||||
#if !defined(LUA_PATH_VAR)
|
||||
#define LUA_PATH_VAR "LUA_PATH"
|
||||
#endif
|
||||
|
||||
#if !defined(LUA_CPATH_VAR)
|
||||
#define LUA_CPATH_VAR "LUA_CPATH"
|
||||
#endif
|
||||
|
||||
#define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
|
||||
|
||||
#define LUA_PATHVARVERSION LUA_PATH_VAR LUA_PATHSUFFIX
|
||||
#define LUA_CPATHVARVERSION LUA_CPATH_VAR LUA_PATHSUFFIX
|
||||
|
||||
/*
|
||||
** LUA_PATH_SEP is the character that separates templates in a path.
|
||||
** LUA_PATH_MARK is the string that marks the substitution points in a
|
||||
** template.
|
||||
** LUA_EXEC_DIR in a Windows path is replaced by the executable's
|
||||
** directory.
|
||||
** LUA_IGMARK is a mark to ignore all before it when building the
|
||||
** luaopen_ function name.
|
||||
*/
|
||||
#if !defined (LUA_PATH_SEP)
|
||||
#define LUA_PATH_SEP ";"
|
||||
#endif
|
||||
#if !defined (LUA_PATH_MARK)
|
||||
#define LUA_PATH_MARK "?"
|
||||
#endif
|
||||
#if !defined (LUA_EXEC_DIR)
|
||||
#define LUA_EXEC_DIR "!"
|
||||
#endif
|
||||
#if !defined (LUA_IGMARK)
|
||||
#define LUA_IGMARK "-"
|
||||
#endif
|
||||
@@ -94,7 +63,8 @@ static const int CLIBS = 0;
|
||||
|
||||
#define LIB_FAIL "open"
|
||||
|
||||
#define setprogdir(L) ((void)0)
|
||||
|
||||
#define setprogdir(L) ((void)0)
|
||||
|
||||
|
||||
/*
|
||||
@@ -179,7 +149,6 @@ static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) {
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#undef setprogdir
|
||||
|
||||
/*
|
||||
** optional flags for LoadLibraryEx
|
||||
@@ -189,21 +158,30 @@ static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) {
|
||||
#endif
|
||||
|
||||
|
||||
#undef setprogdir
|
||||
|
||||
|
||||
/*
|
||||
** Replace in the path (on the top of the stack) any occurrence
|
||||
** of LUA_EXEC_DIR with the executable's path.
|
||||
*/
|
||||
static void setprogdir (lua_State *L) {
|
||||
char buff[MAX_PATH + 1];
|
||||
char *lb;
|
||||
DWORD nsize = sizeof(buff)/sizeof(char);
|
||||
DWORD n = GetModuleFileNameA(NULL, buff, nsize);
|
||||
DWORD n = GetModuleFileNameA(NULL, buff, nsize); /* get exec. name */
|
||||
if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL)
|
||||
luaL_error(L, "unable to get ModuleFileName");
|
||||
else {
|
||||
*lb = '\0';
|
||||
*lb = '\0'; /* cut name on the last '\\' to get the path */
|
||||
luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff);
|
||||
lua_remove(L, -2); /* remove original string */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void pusherror (lua_State *L) {
|
||||
int error = GetLastError();
|
||||
char buffer[128];
|
||||
@@ -272,6 +250,67 @@ static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) {
|
||||
#endif /* } */
|
||||
|
||||
|
||||
/*
|
||||
** {==================================================================
|
||||
** Set Paths
|
||||
** ===================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
** LUA_PATH_VAR and LUA_CPATH_VAR are the names of the environment
|
||||
** variables that Lua check to set its paths.
|
||||
*/
|
||||
#if !defined(LUA_PATH_VAR)
|
||||
#define LUA_PATH_VAR "LUA_PATH"
|
||||
#endif
|
||||
|
||||
#if !defined(LUA_CPATH_VAR)
|
||||
#define LUA_CPATH_VAR "LUA_CPATH"
|
||||
#endif
|
||||
|
||||
|
||||
#define AUXMARK "\1" /* auxiliary mark */
|
||||
|
||||
|
||||
/*
|
||||
** return registry.LUA_NOENV as a boolean
|
||||
*/
|
||||
static int noenv (lua_State *L) {
|
||||
int b;
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
|
||||
b = lua_toboolean(L, -1);
|
||||
lua_pop(L, 1); /* remove value */
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Set a path
|
||||
*/
|
||||
static void setpath (lua_State *L, const char *fieldname,
|
||||
const char *envname,
|
||||
const char *dft) {
|
||||
const char *nver = lua_pushfstring(L, "%s%s", envname, LUA_VERSUFFIX);
|
||||
const char *path = getenv(nver); /* use versioned name */
|
||||
if (path == NULL) /* no environment variable? */
|
||||
path = getenv(envname); /* try unversioned name */
|
||||
if (path == NULL || noenv(L)) /* no environment variable? */
|
||||
lua_pushstring(L, dft); /* use default */
|
||||
else {
|
||||
/* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
|
||||
path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP,
|
||||
LUA_PATH_SEP AUXMARK LUA_PATH_SEP);
|
||||
luaL_gsub(L, path, AUXMARK, dft);
|
||||
lua_remove(L, -2); /* remove result from 1st 'gsub' */
|
||||
}
|
||||
setprogdir(L);
|
||||
lua_setfield(L, -3, fieldname); /* package[fieldname] = path value */
|
||||
lua_pop(L, 1); /* pop versioned variable name */
|
||||
}
|
||||
|
||||
/* }================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
** return registry.CLIBS[path]
|
||||
*/
|
||||
@@ -520,7 +559,7 @@ static int searcher_Croot (lua_State *L) {
|
||||
|
||||
static int searcher_preload (lua_State *L) {
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
|
||||
if (lua_getfield(L, -1, name) == LUA_TNIL) /* not found? */
|
||||
lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
|
||||
return 1;
|
||||
@@ -557,9 +596,9 @@ static void findloader (lua_State *L, const char *name) {
|
||||
|
||||
static int ll_require (lua_State *L) {
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
lua_settop(L, 1); /* _LOADED table will be at index 2 */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
|
||||
lua_getfield(L, 2, name); /* _LOADED[name] */
|
||||
lua_settop(L, 1); /* LOADED table will be at index 2 */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
|
||||
lua_getfield(L, 2, name); /* LOADED[name] */
|
||||
if (lua_toboolean(L, -1)) /* is it there? */
|
||||
return 1; /* package is already loaded */
|
||||
/* else must load package */
|
||||
@@ -569,11 +608,11 @@ static int ll_require (lua_State *L) {
|
||||
lua_insert(L, -2); /* name is 1st argument (before search data) */
|
||||
lua_call(L, 2, 1); /* run loader to load module */
|
||||
if (!lua_isnil(L, -1)) /* non-nil return? */
|
||||
lua_setfield(L, 2, name); /* _LOADED[name] = returned value */
|
||||
lua_setfield(L, 2, name); /* LOADED[name] = returned value */
|
||||
if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no value? */
|
||||
lua_pushboolean(L, 1); /* use true as result */
|
||||
lua_pushvalue(L, -1); /* extra copy to be returned */
|
||||
lua_setfield(L, 2, name); /* _LOADED[name] = true */
|
||||
lua_setfield(L, 2, name); /* LOADED[name] = true */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -666,41 +705,6 @@ static int ll_seeall (lua_State *L) {
|
||||
|
||||
|
||||
|
||||
/* auxiliary mark (for internal use) */
|
||||
#define AUXMARK "\1"
|
||||
|
||||
|
||||
/*
|
||||
** return registry.LUA_NOENV as a boolean
|
||||
*/
|
||||
static int noenv (lua_State *L) {
|
||||
int b;
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
|
||||
b = lua_toboolean(L, -1);
|
||||
lua_pop(L, 1); /* remove value */
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
static void setpath (lua_State *L, const char *fieldname, const char *envname1,
|
||||
const char *envname2, const char *def) {
|
||||
const char *path = getenv(envname1);
|
||||
if (path == NULL) /* no environment variable? */
|
||||
path = getenv(envname2); /* try alternative name */
|
||||
if (path == NULL || noenv(L)) /* no environment variable? */
|
||||
lua_pushstring(L, def); /* use default */
|
||||
else {
|
||||
/* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
|
||||
path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP,
|
||||
LUA_PATH_SEP AUXMARK LUA_PATH_SEP);
|
||||
luaL_gsub(L, path, AUXMARK, def);
|
||||
lua_remove(L, -2);
|
||||
}
|
||||
setprogdir(L);
|
||||
lua_setfield(L, -2, fieldname);
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg pk_funcs[] = {
|
||||
{"loadlib", ll_loadlib},
|
||||
{"searchpath", ll_searchpath},
|
||||
@@ -764,19 +768,18 @@ LUAMOD_API int luaopen_package (lua_State *L) {
|
||||
createclibstable(L);
|
||||
luaL_newlib(L, pk_funcs); /* create 'package' table */
|
||||
createsearcherstable(L);
|
||||
/* set field 'path' */
|
||||
setpath(L, "path", LUA_PATHVARVERSION, LUA_PATH_VAR, LUA_PATH_DEFAULT);
|
||||
/* set field 'cpath' */
|
||||
setpath(L, "cpath", LUA_CPATHVARVERSION, LUA_CPATH_VAR, LUA_CPATH_DEFAULT);
|
||||
/* set paths */
|
||||
setpath(L, "path", LUA_PATH_VAR, LUA_PATH_DEFAULT);
|
||||
setpath(L, "cpath", LUA_CPATH_VAR, LUA_CPATH_DEFAULT);
|
||||
/* store config information */
|
||||
lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n"
|
||||
LUA_EXEC_DIR "\n" LUA_IGMARK "\n");
|
||||
lua_setfield(L, -2, "config");
|
||||
/* set field 'loaded' */
|
||||
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
|
||||
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
|
||||
lua_setfield(L, -2, "loaded");
|
||||
/* set field 'preload' */
|
||||
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
|
||||
luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
|
||||
lua_setfield(L, -2, "preload");
|
||||
lua_pushglobaltable(L);
|
||||
lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lobject.c,v 2.108 2015/11/02 16:09:30 roberto Exp $
|
||||
** $Id: lobject.c,v 2.113.1.1 2017/04/19 17:29:57 roberto Exp $
|
||||
** Some generic functions over Lua objects
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -243,20 +243,59 @@ static lua_Number lua_strx2number (const char *s, char **endptr) {
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
static const char *l_str2d (const char *s, lua_Number *result) {
|
||||
/* maximum length of a numeral */
|
||||
#if !defined (L_MAXLENNUM)
|
||||
#define L_MAXLENNUM 200
|
||||
#endif
|
||||
|
||||
static const char *l_str2dloc (const char *s, lua_Number *result, int mode) {
|
||||
char *endptr;
|
||||
if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */
|
||||
return NULL;
|
||||
else if (strpbrk(s, "xX")) /* hex? */
|
||||
*result = lua_strx2number(s, &endptr);
|
||||
else
|
||||
*result = lua_str2number(s, &endptr);
|
||||
if (endptr == s) return NULL; /* nothing recognized */
|
||||
while (lisspace(cast_uchar(*endptr))) endptr++;
|
||||
return (*endptr == '\0' ? endptr : NULL); /* OK if no trailing characters */
|
||||
*result = (mode == 'x') ? lua_strx2number(s, &endptr) /* try to convert */
|
||||
: lua_str2number(s, &endptr);
|
||||
if (endptr == s) return NULL; /* nothing recognized? */
|
||||
while (lisspace(cast_uchar(*endptr))) endptr++; /* skip trailing spaces */
|
||||
return (*endptr == '\0') ? endptr : NULL; /* OK if no trailing characters */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Convert string 's' to a Lua number (put in 'result'). Return NULL
|
||||
** on fail or the address of the ending '\0' on success.
|
||||
** 'pmode' points to (and 'mode' contains) special things in the string:
|
||||
** - 'x'/'X' means an hexadecimal numeral
|
||||
** - 'n'/'N' means 'inf' or 'nan' (which should be rejected)
|
||||
** - '.' just optimizes the search for the common case (nothing special)
|
||||
** This function accepts both the current locale or a dot as the radix
|
||||
** mark. If the convertion fails, it may mean number has a dot but
|
||||
** locale accepts something else. In that case, the code copies 's'
|
||||
** to a buffer (because 's' is read-only), changes the dot to the
|
||||
** current locale radix mark, and tries to convert again.
|
||||
*/
|
||||
static const char *l_str2d (const char *s, lua_Number *result) {
|
||||
const char *endptr;
|
||||
const char *pmode = strpbrk(s, ".xXnN");
|
||||
int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0;
|
||||
if (mode == 'n') /* reject 'inf' and 'nan' */
|
||||
return NULL;
|
||||
endptr = l_str2dloc(s, result, mode); /* try to convert */
|
||||
if (endptr == NULL) { /* failed? may be a different locale */
|
||||
char buff[L_MAXLENNUM + 1];
|
||||
const char *pdot = strchr(s, '.');
|
||||
if (strlen(s) > L_MAXLENNUM || pdot == NULL)
|
||||
return NULL; /* string too long or no dot; fail */
|
||||
strcpy(buff, s); /* copy string to buffer */
|
||||
buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */
|
||||
endptr = l_str2dloc(buff, result, mode); /* try again */
|
||||
if (endptr != NULL)
|
||||
endptr = s + (endptr - buff); /* make relative to 's' */
|
||||
}
|
||||
return endptr;
|
||||
}
|
||||
|
||||
|
||||
#define MAXBY10 cast(lua_Unsigned, LUA_MAXINTEGER / 10)
|
||||
#define MAXLASTD cast_int(LUA_MAXINTEGER % 10)
|
||||
|
||||
static const char *l_str2int (const char *s, lua_Integer *result) {
|
||||
lua_Unsigned a = 0;
|
||||
int empty = 1;
|
||||
@@ -273,7 +312,10 @@ static const char *l_str2int (const char *s, lua_Integer *result) {
|
||||
}
|
||||
else { /* decimal */
|
||||
for (; lisdigit(cast_uchar(*s)); s++) {
|
||||
a = a * 10 + *s - '0';
|
||||
int d = *s - '0';
|
||||
if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */
|
||||
return NULL; /* do not accept it (as integer) */
|
||||
a = a * 10 + d;
|
||||
empty = 0;
|
||||
}
|
||||
}
|
||||
@@ -351,8 +393,10 @@ static void pushstr (lua_State *L, const char *str, size_t l) {
|
||||
}
|
||||
|
||||
|
||||
/* this function handles only '%d', '%c', '%f', '%p', and '%s'
|
||||
conventional formats, plus Lua-specific '%I' and '%U' */
|
||||
/*
|
||||
** this function handles only '%d', '%c', '%f', '%p', and '%s'
|
||||
conventional formats, plus Lua-specific '%I' and '%U'
|
||||
*/
|
||||
const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
|
||||
int n = 0;
|
||||
for (;;) {
|
||||
@@ -360,13 +404,13 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
|
||||
if (e == NULL) break;
|
||||
pushstr(L, fmt, e - fmt);
|
||||
switch (*(e+1)) {
|
||||
case 's': {
|
||||
case 's': { /* zero-terminated string */
|
||||
const char *s = va_arg(argp, char *);
|
||||
if (s == NULL) s = "(null)";
|
||||
pushstr(L, s, strlen(s));
|
||||
break;
|
||||
}
|
||||
case 'c': {
|
||||
case 'c': { /* an 'int' as a character */
|
||||
char buff = cast(char, va_arg(argp, int));
|
||||
if (lisprint(cast_uchar(buff)))
|
||||
pushstr(L, &buff, 1);
|
||||
@@ -374,28 +418,29 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
|
||||
luaO_pushfstring(L, "<\\%d>", cast_uchar(buff));
|
||||
break;
|
||||
}
|
||||
case 'd': {
|
||||
case 'd': { /* an 'int' */
|
||||
setivalue(L->top, va_arg(argp, int));
|
||||
goto top2str;
|
||||
}
|
||||
case 'I': {
|
||||
case 'I': { /* a 'lua_Integer' */
|
||||
setivalue(L->top, cast(lua_Integer, va_arg(argp, l_uacInt)));
|
||||
goto top2str;
|
||||
}
|
||||
case 'f': {
|
||||
case 'f': { /* a 'lua_Number' */
|
||||
setfltvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));
|
||||
top2str:
|
||||
top2str: /* convert the top element to a string */
|
||||
luaD_inctop(L);
|
||||
luaO_tostring(L, L->top - 1);
|
||||
break;
|
||||
}
|
||||
case 'p': {
|
||||
case 'p': { /* a pointer */
|
||||
char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */
|
||||
int l = l_sprintf(buff, sizeof(buff), "%p", va_arg(argp, void *));
|
||||
void *p = va_arg(argp, void *);
|
||||
int l = lua_pointer2str(buff, sizeof(buff), p);
|
||||
pushstr(L, buff, l);
|
||||
break;
|
||||
}
|
||||
case 'U': {
|
||||
case 'U': { /* an 'int' as a UTF-8 sequence */
|
||||
char buff[UTF8BUFFSZ];
|
||||
int l = luaO_utf8esc(buff, cast(long, va_arg(argp, long)));
|
||||
pushstr(L, buff + UTF8BUFFSZ - l, l);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lobject.h,v 2.116 2015/11/03 18:33:10 roberto Exp $
|
||||
** $Id: lobject.h,v 2.117.1.1 2017/04/19 17:39:34 roberto Exp $
|
||||
** Type definitions for Lua objects
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -402,7 +402,7 @@ typedef struct LocVar {
|
||||
|
||||
typedef struct SharedProto {
|
||||
lu_byte numparams; /* number of fixed parameters */
|
||||
lu_byte is_vararg; /* 2: declared vararg; 1: uses vararg */
|
||||
lu_byte is_vararg;
|
||||
lu_byte maxstacksize; /* number of registers needed by this function */
|
||||
int sizeupvalues; /* size of 'upvalues' */
|
||||
int sizek; /* size of 'k' */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lopcodes.c,v 1.55 2015/01/05 13:48:33 roberto Exp $
|
||||
** $Id: lopcodes.c,v 1.55.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Opcodes for Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lopcodes.h,v 1.148 2014/10/25 11:50:46 roberto Exp $
|
||||
** $Id: lopcodes.h,v 1.149.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Opcodes for Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -139,7 +139,9 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */
|
||||
/* gets the index of the constant */
|
||||
#define INDEXK(r) ((int)(r) & ~BITRK)
|
||||
|
||||
#if !defined(MAXINDEXRK) /* (for debugging only) */
|
||||
#define MAXINDEXRK (BITRK - 1)
|
||||
#endif
|
||||
|
||||
/* code a constant index as a RK value */
|
||||
#define RKASK(x) ((x) | BITRK)
|
||||
|
||||
107
3rd/lua/loslib.c
107
3rd/lua/loslib.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: loslib.c,v 1.60 2015/11/19 19:16:22 roberto Exp $
|
||||
** $Id: loslib.c,v 1.65.1.1 2017/04/19 17:29:57 roberto Exp $
|
||||
** Standard Operating System library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -24,18 +24,29 @@
|
||||
|
||||
/*
|
||||
** {==================================================================
|
||||
** list of valid conversion specifiers for the 'strftime' function
|
||||
** List of valid conversion specifiers for the 'strftime' function;
|
||||
** options are grouped by length; group of length 2 start with '||'.
|
||||
** ===================================================================
|
||||
*/
|
||||
#if !defined(LUA_STRFTIMEOPTIONS) /* { */
|
||||
|
||||
#if defined(LUA_USE_C89)
|
||||
#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" }
|
||||
/* options for ANSI C 89 (only 1-char options) */
|
||||
#define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%"
|
||||
|
||||
/* options for ISO C 99 and POSIX */
|
||||
#define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \
|
||||
"||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */
|
||||
|
||||
/* options for Windows */
|
||||
#define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \
|
||||
"||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */
|
||||
|
||||
#if defined(LUA_USE_WINDOWS)
|
||||
#define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN
|
||||
#elif defined(LUA_USE_C89)
|
||||
#define LUA_STRFTIMEOPTIONS L_STRFTIMEC89
|
||||
#else /* C99 specification */
|
||||
#define LUA_STRFTIMEOPTIONS \
|
||||
{ "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "", \
|
||||
"E", "cCxXyY", \
|
||||
"O", "deHImMSuUVwWy" }
|
||||
#define LUA_STRFTIMEOPTIONS L_STRFTIMEC99
|
||||
#endif
|
||||
|
||||
#endif /* } */
|
||||
@@ -195,6 +206,23 @@ static void setboolfield (lua_State *L, const char *key, int value) {
|
||||
lua_setfield(L, -2, key);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Set all fields from structure 'tm' in the table on top of the stack
|
||||
*/
|
||||
static void setallfields (lua_State *L, struct tm *stm) {
|
||||
setfield(L, "sec", stm->tm_sec);
|
||||
setfield(L, "min", stm->tm_min);
|
||||
setfield(L, "hour", stm->tm_hour);
|
||||
setfield(L, "day", stm->tm_mday);
|
||||
setfield(L, "month", stm->tm_mon + 1);
|
||||
setfield(L, "year", stm->tm_year + 1900);
|
||||
setfield(L, "wday", stm->tm_wday + 1);
|
||||
setfield(L, "yday", stm->tm_yday + 1);
|
||||
setboolfield(L, "isdst", stm->tm_isdst);
|
||||
}
|
||||
|
||||
|
||||
static int getboolfield (lua_State *L, const char *key) {
|
||||
int res;
|
||||
res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1);
|
||||
@@ -210,18 +238,18 @@ static int getboolfield (lua_State *L, const char *key) {
|
||||
|
||||
static int getfield (lua_State *L, const char *key, int d, int delta) {
|
||||
int isnum;
|
||||
int t = lua_getfield(L, -1, key);
|
||||
int t = lua_getfield(L, -1, key); /* get field and its type */
|
||||
lua_Integer res = lua_tointegerx(L, -1, &isnum);
|
||||
if (!isnum) { /* field is not a number? */
|
||||
if (!isnum) { /* field is not an integer? */
|
||||
if (t != LUA_TNIL) /* some other value? */
|
||||
return luaL_error(L, "field '%s' not an integer", key);
|
||||
return luaL_error(L, "field '%s' is not an integer", key);
|
||||
else if (d < 0) /* absent field; no default? */
|
||||
return luaL_error(L, "field '%s' missing in date table", key);
|
||||
res = d;
|
||||
}
|
||||
else {
|
||||
if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD))
|
||||
return luaL_error(L, "field '%s' out-of-bounds", key);
|
||||
return luaL_error(L, "field '%s' is out-of-bound", key);
|
||||
res -= delta;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
@@ -229,22 +257,17 @@ static int getfield (lua_State *L, const char *key, int d, int delta) {
|
||||
}
|
||||
|
||||
|
||||
static const char *checkoption (lua_State *L, const char *conv, char *buff) {
|
||||
static const char *const options[] = LUA_STRFTIMEOPTIONS;
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(options)/sizeof(options[0]); i += 2) {
|
||||
if (*conv != '\0' && strchr(options[i], *conv) != NULL) {
|
||||
buff[1] = *conv;
|
||||
if (*options[i + 1] == '\0') { /* one-char conversion specifier? */
|
||||
buff[2] = '\0'; /* end buffer */
|
||||
return conv + 1;
|
||||
}
|
||||
else if (*(conv + 1) != '\0' &&
|
||||
strchr(options[i + 1], *(conv + 1)) != NULL) {
|
||||
buff[2] = *(conv + 1); /* valid two-char conversion specifier */
|
||||
buff[3] = '\0'; /* end buffer */
|
||||
return conv + 2;
|
||||
}
|
||||
static const char *checkoption (lua_State *L, const char *conv,
|
||||
ptrdiff_t convlen, char *buff) {
|
||||
const char *option = LUA_STRFTIMEOPTIONS;
|
||||
int oplen = 1; /* length of options being checked */
|
||||
for (; *option != '\0' && oplen <= convlen; option += oplen) {
|
||||
if (*option == '|') /* next block? */
|
||||
oplen++; /* will check options with next length (+1) */
|
||||
else if (memcmp(conv, option, oplen) == 0) { /* match? */
|
||||
memcpy(buff, conv, oplen); /* copy valid option to buffer */
|
||||
buff[oplen] = '\0';
|
||||
return conv + oplen; /* return next item */
|
||||
}
|
||||
}
|
||||
luaL_argerror(L, 1,
|
||||
@@ -258,8 +281,10 @@ static const char *checkoption (lua_State *L, const char *conv, char *buff) {
|
||||
|
||||
|
||||
static int os_date (lua_State *L) {
|
||||
const char *s = luaL_optstring(L, 1, "%c");
|
||||
size_t slen;
|
||||
const char *s = luaL_optlstring(L, 1, "%c", &slen);
|
||||
time_t t = luaL_opt(L, l_checktime, 2, time(NULL));
|
||||
const char *se = s + slen; /* 's' end */
|
||||
struct tm tmr, *stm;
|
||||
if (*s == '!') { /* UTC? */
|
||||
stm = l_gmtime(&t, &tmr);
|
||||
@@ -268,31 +293,25 @@ static int os_date (lua_State *L) {
|
||||
else
|
||||
stm = l_localtime(&t, &tmr);
|
||||
if (stm == NULL) /* invalid date? */
|
||||
luaL_error(L, "time result cannot be represented in this installation");
|
||||
return luaL_error(L,
|
||||
"time result cannot be represented in this installation");
|
||||
if (strcmp(s, "*t") == 0) {
|
||||
lua_createtable(L, 0, 9); /* 9 = number of fields */
|
||||
setfield(L, "sec", stm->tm_sec);
|
||||
setfield(L, "min", stm->tm_min);
|
||||
setfield(L, "hour", stm->tm_hour);
|
||||
setfield(L, "day", stm->tm_mday);
|
||||
setfield(L, "month", stm->tm_mon+1);
|
||||
setfield(L, "year", stm->tm_year+1900);
|
||||
setfield(L, "wday", stm->tm_wday+1);
|
||||
setfield(L, "yday", stm->tm_yday+1);
|
||||
setboolfield(L, "isdst", stm->tm_isdst);
|
||||
setallfields(L, stm);
|
||||
}
|
||||
else {
|
||||
char cc[4];
|
||||
char cc[4]; /* buffer for individual conversion specifiers */
|
||||
luaL_Buffer b;
|
||||
cc[0] = '%';
|
||||
luaL_buffinit(L, &b);
|
||||
while (*s) {
|
||||
while (s < se) {
|
||||
if (*s != '%') /* not a conversion specifier? */
|
||||
luaL_addchar(&b, *s++);
|
||||
else {
|
||||
size_t reslen;
|
||||
char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT);
|
||||
s = checkoption(L, s + 1, cc);
|
||||
s++; /* skip '%' */
|
||||
s = checkoption(L, s, se - s, cc + 1); /* copy specifier to 'cc' */
|
||||
reslen = strftime(buff, SIZETIMEFMT, cc, stm);
|
||||
luaL_addsize(&b, reslen);
|
||||
}
|
||||
@@ -319,9 +338,11 @@ static int os_time (lua_State *L) {
|
||||
ts.tm_year = getfield(L, "year", -1, 1900);
|
||||
ts.tm_isdst = getboolfield(L, "isdst");
|
||||
t = mktime(&ts);
|
||||
setallfields(L, &ts); /* update fields with normalized values */
|
||||
}
|
||||
if (t != (time_t)(l_timet)t || t == (time_t)(-1))
|
||||
luaL_error(L, "time result cannot be represented in this installation");
|
||||
return luaL_error(L,
|
||||
"time result cannot be represented in this installation");
|
||||
l_pushtime(L, t);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lparser.c,v 2.149 2015/11/02 16:09:30 roberto Exp $
|
||||
** $Id: lparser.c,v 2.155.1.2 2017/04/29 18:11:40 roberto Exp $
|
||||
** Lua Parser
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -165,7 +165,8 @@ static int registerlocalvar (LexState *ls, TString *varname) {
|
||||
int oldsize = f->sizelocvars;
|
||||
luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,
|
||||
LocVar, SHRT_MAX, "local variables");
|
||||
while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL;
|
||||
while (oldsize < f->sizelocvars)
|
||||
f->locvars[oldsize++].varname = NULL;
|
||||
f->locvars[fs->nlocvars].varname = varname;
|
||||
luaC_objbarrier(ls->L, fp, varname);
|
||||
return fs->nlocvars++;
|
||||
@@ -232,7 +233,8 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) {
|
||||
checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues");
|
||||
luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues,
|
||||
Upvaldesc, MAXUPVAL, "upvalues");
|
||||
while (oldsize < f->sizeupvalues) f->upvalues[oldsize++].name = NULL;
|
||||
while (oldsize < f->sizeupvalues)
|
||||
f->upvalues[oldsize++].name = NULL;
|
||||
f->upvalues[fs->nups].instack = (v->k == VLOCAL);
|
||||
f->upvalues[fs->nups].idx = cast_byte(v->u.info);
|
||||
f->upvalues[fs->nups].name = name;
|
||||
@@ -257,7 +259,8 @@ static int searchvar (FuncState *fs, TString *n) {
|
||||
*/
|
||||
static void markupval (FuncState *fs, int level) {
|
||||
BlockCnt *bl = fs->bl;
|
||||
while (bl->nactvar > level) bl = bl->previous;
|
||||
while (bl->nactvar > level)
|
||||
bl = bl->previous;
|
||||
bl->upval = 1;
|
||||
}
|
||||
|
||||
@@ -266,27 +269,26 @@ static void markupval (FuncState *fs, int level) {
|
||||
Find variable with given name 'n'. If it is an upvalue, add this
|
||||
upvalue into all intermediate functions.
|
||||
*/
|
||||
static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
|
||||
static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
|
||||
if (fs == NULL) /* no more levels? */
|
||||
return VVOID; /* default is global */
|
||||
init_exp(var, VVOID, 0); /* default is global */
|
||||
else {
|
||||
int v = searchvar(fs, n); /* look up locals at current level */
|
||||
if (v >= 0) { /* found? */
|
||||
init_exp(var, VLOCAL, v); /* variable is local */
|
||||
if (!base)
|
||||
markupval(fs, v); /* local will be used as an upval */
|
||||
return VLOCAL;
|
||||
}
|
||||
else { /* not found as local at current level; try upvalues */
|
||||
int idx = searchupvalue(fs, n); /* try existing upvalues */
|
||||
if (idx < 0) { /* not found? */
|
||||
if (singlevaraux(fs->prev, n, var, 0) == VVOID) /* try upper levels */
|
||||
return VVOID; /* not found; is a global */
|
||||
singlevaraux(fs->prev, n, var, 0); /* try upper levels */
|
||||
if (var->k == VVOID) /* not found? */
|
||||
return; /* it is a global */
|
||||
/* else was LOCAL or UPVAL */
|
||||
idx = newupvalue(fs, n, var); /* will be a new upvalue */
|
||||
}
|
||||
init_exp(var, VUPVAL, idx);
|
||||
return VUPVAL;
|
||||
init_exp(var, VUPVAL, idx); /* new or old upvalue */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -295,10 +297,11 @@ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
|
||||
static void singlevar (LexState *ls, expdesc *var) {
|
||||
TString *varname = str_checkname(ls);
|
||||
FuncState *fs = ls->fs;
|
||||
if (singlevaraux(fs, varname, var, 1) == VVOID) { /* global name? */
|
||||
singlevaraux(fs, varname, var, 1);
|
||||
if (var->k == VVOID) { /* global name? */
|
||||
expdesc key;
|
||||
singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
|
||||
lua_assert(var->k == VLOCAL || var->k == VUPVAL);
|
||||
lua_assert(var->k != VVOID); /* this one must exist */
|
||||
codestring(ls, &key, varname); /* key is variable name */
|
||||
luaK_indexed(fs, var, &key); /* env[varname] */
|
||||
}
|
||||
@@ -322,6 +325,8 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
|
||||
luaK_nil(fs, reg, extra);
|
||||
}
|
||||
}
|
||||
if (nexps > nvars)
|
||||
ls->fs->freereg -= nexps - nvars; /* remove extra values */
|
||||
}
|
||||
|
||||
|
||||
@@ -501,7 +506,8 @@ static Proto *addprototype (LexState *ls) {
|
||||
if (fs->np >= f->sp->sizep) {
|
||||
int oldsize = f->sp->sizep;
|
||||
luaM_growvector(L, f->p, fs->np, f->sp->sizep, Proto *, MAXARG_Bx, "functions");
|
||||
while (oldsize < f->sp->sizep) f->p[oldsize++] = NULL;
|
||||
while (oldsize < f->sp->sizep)
|
||||
f->p[oldsize++] = NULL;
|
||||
}
|
||||
f->p[fs->np++] = clp = luaF_newproto(L, NULL);
|
||||
luaC_objbarrier(L, f, clp);
|
||||
@@ -763,7 +769,7 @@ static void parlist (LexState *ls) {
|
||||
}
|
||||
case TK_DOTS: { /* param -> '...' */
|
||||
luaX_next(ls);
|
||||
f->is_vararg = 2; /* declared vararg */
|
||||
f->is_vararg = 1; /* declared vararg */
|
||||
break;
|
||||
}
|
||||
default: luaX_syntaxerror(ls, "<name> or '...' expected");
|
||||
@@ -959,7 +965,6 @@ static void simpleexp (LexState *ls, expdesc *v) {
|
||||
FuncState *fs = ls->fs;
|
||||
check_condition(ls, fs->f->sp->is_vararg,
|
||||
"cannot use '...' outside a vararg function");
|
||||
fs->f->sp->is_vararg = 1; /* function actually uses vararg */
|
||||
init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
|
||||
break;
|
||||
}
|
||||
@@ -1159,11 +1164,8 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
|
||||
int nexps;
|
||||
checknext(ls, '=');
|
||||
nexps = explist(ls, &e);
|
||||
if (nexps != nvars) {
|
||||
if (nexps != nvars)
|
||||
adjust_assign(ls, nvars, nexps, &e);
|
||||
if (nexps > nvars)
|
||||
ls->fs->freereg -= nexps - nvars; /* remove extra values */
|
||||
}
|
||||
else {
|
||||
luaK_setoneret(ls->fs, &e); /* close last expression */
|
||||
luaK_storevar(ls->fs, &lh->v, &e);
|
||||
@@ -1229,7 +1231,7 @@ static void labelstat (LexState *ls, TString *label, int line) {
|
||||
checkrepeated(fs, ll, label); /* check for repeated labels */
|
||||
checknext(ls, TK_DBCOLON); /* skip double colon */
|
||||
/* create new entry for this label */
|
||||
l = newlabelentry(ls, ll, label, line, fs->pc);
|
||||
l = newlabelentry(ls, ll, label, line, luaK_getlabel(fs));
|
||||
skipnoopstat(ls); /* skip other no-op statements */
|
||||
if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */
|
||||
/* assume that locals are already out of scope */
|
||||
@@ -1393,7 +1395,7 @@ static void test_then_block (LexState *ls, int *escapelist) {
|
||||
luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */
|
||||
enterblock(fs, &bl, 0); /* must enter block before 'goto' */
|
||||
gotostat(ls, v.t); /* handle goto/break */
|
||||
skipnoopstat(ls); /* skip other no-op statements */
|
||||
while (testnext(ls, ';')) {} /* skip colons */
|
||||
if (block_follow(ls, 0)) { /* 'goto' is the entire block? */
|
||||
leaveblock(fs);
|
||||
return; /* and that is it */
|
||||
@@ -1497,7 +1499,7 @@ static void exprstat (LexState *ls) {
|
||||
}
|
||||
else { /* stat -> func */
|
||||
check_condition(ls, v.v.k == VCALL, "syntax error");
|
||||
SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */
|
||||
SETARG_C(getinstruction(fs, &v.v), 1); /* call statement uses no results */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1514,8 +1516,8 @@ static void retstat (LexState *ls) {
|
||||
if (hasmultret(e.k)) {
|
||||
luaK_setmultret(fs, &e);
|
||||
if (e.k == VCALL && nret == 1) { /* tail call? */
|
||||
SET_OPCODE(getcode(fs,&e), OP_TAILCALL);
|
||||
lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);
|
||||
SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL);
|
||||
lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar);
|
||||
}
|
||||
first = fs->nactvar;
|
||||
nret = LUA_MULTRET; /* return all values */
|
||||
@@ -1597,7 +1599,7 @@ static void statement (LexState *ls) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg &&
|
||||
lua_assert(ls->fs->f->sp->maxstacksize >= ls->fs->freereg &&
|
||||
ls->fs->freereg >= ls->fs->nactvar);
|
||||
ls->fs->freereg = ls->fs->nactvar; /* free registers */
|
||||
leavelevel(ls);
|
||||
@@ -1614,7 +1616,7 @@ static void mainfunc (LexState *ls, FuncState *fs) {
|
||||
BlockCnt bl;
|
||||
expdesc v;
|
||||
open_func(ls, fs, &bl);
|
||||
fs->f->sp->is_vararg = 2; /* main function is always declared vararg */
|
||||
fs->f->sp->is_vararg = 1; /* main function is always declared vararg */
|
||||
init_exp(&v, VLOCAL, 0); /* create and... */
|
||||
newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */
|
||||
luaX_next(ls); /* read first token */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lparser.h,v 1.74 2014/10/25 11:50:46 roberto Exp $
|
||||
** $Id: lparser.h,v 1.76.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Lua Parser
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -13,25 +13,38 @@
|
||||
|
||||
|
||||
/*
|
||||
** Expression descriptor
|
||||
** Expression and variable descriptor.
|
||||
** Code generation for variables and expressions can be delayed to allow
|
||||
** optimizations; An 'expdesc' structure describes a potentially-delayed
|
||||
** variable/expression. It has a description of its "main" value plus a
|
||||
** list of conditional jumps that can also produce its value (generated
|
||||
** by short-circuit operators 'and'/'or').
|
||||
*/
|
||||
|
||||
/* kinds of variables/expressions */
|
||||
typedef enum {
|
||||
VVOID, /* no value */
|
||||
VNIL,
|
||||
VTRUE,
|
||||
VFALSE,
|
||||
VK, /* info = index of constant in 'k' */
|
||||
VKFLT, /* nval = numerical float value */
|
||||
VKINT, /* nval = numerical integer value */
|
||||
VNONRELOC, /* info = result register */
|
||||
VLOCAL, /* info = local register */
|
||||
VUPVAL, /* info = index of upvalue in 'upvalues' */
|
||||
VINDEXED, /* t = table register/upvalue; idx = index R/K */
|
||||
VJMP, /* info = instruction pc */
|
||||
VRELOCABLE, /* info = instruction pc */
|
||||
VCALL, /* info = instruction pc */
|
||||
VVARARG /* info = instruction pc */
|
||||
VVOID, /* when 'expdesc' describes the last expression a list,
|
||||
this kind means an empty list (so, no expression) */
|
||||
VNIL, /* constant nil */
|
||||
VTRUE, /* constant true */
|
||||
VFALSE, /* constant false */
|
||||
VK, /* constant in 'k'; info = index of constant in 'k' */
|
||||
VKFLT, /* floating constant; nval = numerical float value */
|
||||
VKINT, /* integer constant; nval = numerical integer value */
|
||||
VNONRELOC, /* expression has its value in a fixed register;
|
||||
info = result register */
|
||||
VLOCAL, /* local variable; info = local register */
|
||||
VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */
|
||||
VINDEXED, /* indexed variable;
|
||||
ind.vt = whether 't' is register or upvalue;
|
||||
ind.t = table register or upvalue;
|
||||
ind.idx = key's R/K index */
|
||||
VJMP, /* expression is a test/comparison;
|
||||
info = pc of corresponding jump instruction */
|
||||
VRELOCABLE, /* expression can put result in any register;
|
||||
info = instruction pc */
|
||||
VCALL, /* expression is a function call; info = instruction pc */
|
||||
VVARARG /* vararg expression; info = instruction pc */
|
||||
} expkind;
|
||||
|
||||
|
||||
@@ -41,14 +54,14 @@ typedef enum {
|
||||
typedef struct expdesc {
|
||||
expkind k;
|
||||
union {
|
||||
lua_Integer ival; /* for VKINT */
|
||||
lua_Number nval; /* for VKFLT */
|
||||
int info; /* for generic use */
|
||||
struct { /* for indexed variables (VINDEXED) */
|
||||
short idx; /* index (R/K) */
|
||||
lu_byte t; /* table (register or upvalue) */
|
||||
lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */
|
||||
} ind;
|
||||
int info; /* for generic use */
|
||||
lua_Number nval; /* for VKFLT */
|
||||
lua_Integer ival; /* for VKINT */
|
||||
} u;
|
||||
int t; /* patch list of 'exit when true' */
|
||||
int f; /* patch list of 'exit when false' */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lprefix.h,v 1.2 2014/12/29 16:54:13 roberto Exp $
|
||||
** $Id: lprefix.h,v 1.2.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Definitions for Lua code that must come before any other header file
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lstate.c,v 2.133 2015/11/13 12:16:51 roberto Exp $
|
||||
** $Id: lstate.c,v 2.133.1.1 2017/04/19 17:39:34 roberto Exp $
|
||||
** Global State
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lstate.h,v 2.128 2015/11/13 12:16:51 roberto Exp $
|
||||
** $Id: lstate.h,v 2.133.1.1 2017/04/19 17:39:34 roberto Exp $
|
||||
** Global State
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -23,9 +23,27 @@
|
||||
**
|
||||
** 'allgc': all objects not marked for finalization;
|
||||
** 'finobj': all objects marked for finalization;
|
||||
** 'tobefnz': all objects ready to be finalized;
|
||||
** 'tobefnz': all objects ready to be finalized;
|
||||
** 'fixedgc': all objects that are not to be collected (currently
|
||||
** only small strings, such as reserved words).
|
||||
**
|
||||
** Moreover, there is another set of lists that control gray objects.
|
||||
** These lists are linked by fields 'gclist'. (All objects that
|
||||
** can become gray have such a field. The field is not the same
|
||||
** in all objects, but it always has this name.) Any gray object
|
||||
** must belong to one of these lists, and all objects in these lists
|
||||
** must be gray:
|
||||
**
|
||||
** 'gray': regular gray objects, still waiting to be visited.
|
||||
** 'grayagain': objects that must be revisited at the atomic phase.
|
||||
** That includes
|
||||
** - black objects got in a write barrier;
|
||||
** - all kinds of weak tables during propagation phase;
|
||||
** - all threads.
|
||||
** 'weak': tables with weak values to be cleared;
|
||||
** 'ephemeron': ephemeron tables with white->white entries;
|
||||
** 'allweak': tables with weak keys and/or weak values to be cleared.
|
||||
** The last three lists are used only during the atomic phase.
|
||||
|
||||
*/
|
||||
|
||||
@@ -33,6 +51,15 @@
|
||||
struct lua_longjmp; /* defined in ldo.c */
|
||||
|
||||
|
||||
/*
|
||||
** Atomic type (relative to signals) to better ensure that 'lua_sethook'
|
||||
** is thread safe
|
||||
*/
|
||||
#if !defined(l_signalT)
|
||||
#include <signal.h>
|
||||
#define l_signalT sig_atomic_t
|
||||
#endif
|
||||
|
||||
|
||||
/* extra stack space to handle TM calls and some other extras */
|
||||
#define EXTRA_STACK 5
|
||||
@@ -57,7 +84,7 @@ typedef struct stringtable {
|
||||
** Information about a call.
|
||||
** When a thread yields, 'func' is adjusted to pretend that the
|
||||
** top function has only the yielded values in its stack; in that
|
||||
** case, the actual 'func' value is saved in field 'extra'.
|
||||
** case, the actual 'func' value is saved in field 'extra'.
|
||||
** When a function calls another with a continuation, 'extra' keeps
|
||||
** the function index so that, in case of errors, the continuation
|
||||
** function can be called with the correct top.
|
||||
@@ -79,7 +106,7 @@ typedef struct CallInfo {
|
||||
} u;
|
||||
ptrdiff_t extra;
|
||||
short nresults; /* expected number of results from this function */
|
||||
lu_byte callstatus;
|
||||
unsigned short callstatus;
|
||||
} CallInfo;
|
||||
|
||||
|
||||
@@ -95,6 +122,7 @@ typedef struct CallInfo {
|
||||
#define CIST_TAIL (1<<5) /* call was tail called */
|
||||
#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */
|
||||
#define CIST_LEQ (1<<7) /* using __lt for __le */
|
||||
#define CIST_FIN (1<<8) /* call is running a finalizer */
|
||||
|
||||
#define isLua(ci) ((ci)->callstatus & CIST_LUA)
|
||||
|
||||
@@ -162,14 +190,14 @@ struct lua_State {
|
||||
struct lua_State *twups; /* list of threads with open upvalues */
|
||||
struct lua_longjmp *errorJmp; /* current error recover point */
|
||||
CallInfo base_ci; /* CallInfo for first level (C calling Lua) */
|
||||
lua_Hook hook;
|
||||
volatile lua_Hook hook;
|
||||
ptrdiff_t errfunc; /* current error handling function (stack index) */
|
||||
int stacksize;
|
||||
int basehookcount;
|
||||
int hookcount;
|
||||
unsigned short nny; /* number of non-yieldable calls in stack */
|
||||
unsigned short nCcalls; /* number of nested C calls */
|
||||
lu_byte hookmask;
|
||||
l_signalT hookmask;
|
||||
lu_byte allowhook;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lstring.c,v 2.56 2015/11/23 11:32:51 roberto Exp $
|
||||
** $Id: lstring.c,v 2.56.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** String table (keeps all strings handled by Lua)
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -419,8 +419,11 @@ luaS_clonestring(lua_State *L, TString *ts) {
|
||||
result = query_ptr(ts);
|
||||
if (result)
|
||||
return result;
|
||||
// ts is not in SSM, so recalc hash, and add it to SSM
|
||||
h = luaS_hash(str, l, 0);
|
||||
result = query_string(h, str, l);
|
||||
if (result)
|
||||
return result;
|
||||
// ts is not in SSM, so recalc hash, and add it to SSM
|
||||
return add_string(h, str, l);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lstring.h,v 1.61 2015/11/03 15:36:01 roberto Exp $
|
||||
** $Id: lstring.h,v 1.61.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** String table (keep all strings handled by Lua)
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lstrlib.c,v 1.239 2015/11/25 16:28:17 roberto Exp $
|
||||
** $Id: lstrlib.c,v 1.254.1.1 2017/04/19 17:29:57 roberto Exp $
|
||||
** Standard library for string operations and pattern-matching
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <ctype.h>
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -26,7 +27,8 @@
|
||||
|
||||
/*
|
||||
** maximum number of captures that a pattern can do during
|
||||
** pattern-matching. This limit is arbitrary.
|
||||
** pattern-matching. This limit is arbitrary, but must fit in
|
||||
** an unsigned char.
|
||||
*/
|
||||
#if !defined(LUA_MAXCAPTURES)
|
||||
#define LUA_MAXCAPTURES 32
|
||||
@@ -214,9 +216,8 @@ typedef struct MatchState {
|
||||
const char *src_end; /* end ('\0') of source string */
|
||||
const char *p_end; /* end ('\0') of pattern */
|
||||
lua_State *L;
|
||||
size_t nrep; /* limit to avoid non-linear complexity */
|
||||
int matchdepth; /* control for recursive depth (to avoid C stack overflow) */
|
||||
int level; /* total number of captures (finished or unfinished) */
|
||||
unsigned char level; /* total number of captures (finished or unfinished) */
|
||||
struct {
|
||||
const char *init;
|
||||
ptrdiff_t len;
|
||||
@@ -234,17 +235,6 @@ static const char *match (MatchState *ms, const char *s, const char *p);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** parameters to control the maximum number of operators handled in
|
||||
** a match (to avoid non-linear complexity). The maximum will be:
|
||||
** (subject length) * A_REPS + B_REPS
|
||||
*/
|
||||
#if !defined(A_REPS)
|
||||
#define A_REPS 4
|
||||
#define B_REPS 100000
|
||||
#endif
|
||||
|
||||
|
||||
#define L_ESC '%'
|
||||
#define SPECIALS "^$*+?.([%-"
|
||||
|
||||
@@ -502,8 +492,6 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
|
||||
s = NULL; /* fail */
|
||||
}
|
||||
else { /* matched once */
|
||||
if (ms->nrep-- == 0)
|
||||
luaL_error(ms->L, "pattern too complex");
|
||||
switch (*ep) { /* handle optional suffix */
|
||||
case '?': { /* optional */
|
||||
const char *res;
|
||||
@@ -607,10 +595,6 @@ static void prepstate (MatchState *ms, lua_State *L,
|
||||
ms->src_init = s;
|
||||
ms->src_end = s + ls;
|
||||
ms->p_end = p + lp;
|
||||
if (ls < (MAX_SIZET - B_REPS) / A_REPS)
|
||||
ms->nrep = A_REPS * ls + B_REPS;
|
||||
else /* overflow (very long subject) */
|
||||
ms->nrep = MAX_SIZET; /* no limit */
|
||||
}
|
||||
|
||||
|
||||
@@ -681,6 +665,7 @@ static int str_match (lua_State *L) {
|
||||
typedef struct GMatchState {
|
||||
const char *src; /* current position */
|
||||
const char *p; /* pattern */
|
||||
const char *lastmatch; /* end of last match */
|
||||
MatchState ms; /* match state */
|
||||
} GMatchState;
|
||||
|
||||
@@ -688,14 +673,12 @@ typedef struct GMatchState {
|
||||
static int gmatch_aux (lua_State *L) {
|
||||
GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3));
|
||||
const char *src;
|
||||
gm->ms.L = L;
|
||||
for (src = gm->src; src <= gm->ms.src_end; src++) {
|
||||
const char *e;
|
||||
reprepstate(&gm->ms);
|
||||
if ((e = match(&gm->ms, src, gm->p)) != NULL) {
|
||||
if (e == src) /* empty match? */
|
||||
gm->src =src + 1; /* go at least one position */
|
||||
else
|
||||
gm->src = e;
|
||||
if ((e = match(&gm->ms, src, gm->p)) != NULL && e != gm->lastmatch) {
|
||||
gm->src = gm->lastmatch = e;
|
||||
return push_captures(&gm->ms, src, e);
|
||||
}
|
||||
}
|
||||
@@ -711,7 +694,7 @@ static int gmatch (lua_State *L) {
|
||||
lua_settop(L, 2); /* keep them on closure to avoid being collected */
|
||||
gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState));
|
||||
prepstate(&gm->ms, L, s, ls, p, lp);
|
||||
gm->src = s; gm->p = p;
|
||||
gm->src = s; gm->p = p; gm->lastmatch = NULL;
|
||||
lua_pushcclosure(L, gmatch_aux, 3);
|
||||
return 1;
|
||||
}
|
||||
@@ -778,12 +761,13 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
|
||||
|
||||
static int str_gsub (lua_State *L) {
|
||||
size_t srcl, lp;
|
||||
const char *src = luaL_checklstring(L, 1, &srcl);
|
||||
const char *p = luaL_checklstring(L, 2, &lp);
|
||||
int tr = lua_type(L, 3);
|
||||
lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1);
|
||||
const char *src = luaL_checklstring(L, 1, &srcl); /* subject */
|
||||
const char *p = luaL_checklstring(L, 2, &lp); /* pattern */
|
||||
const char *lastmatch = NULL; /* end of last match */
|
||||
int tr = lua_type(L, 3); /* replacement type */
|
||||
lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */
|
||||
int anchor = (*p == '^');
|
||||
lua_Integer n = 0;
|
||||
lua_Integer n = 0; /* replacement count */
|
||||
MatchState ms;
|
||||
luaL_Buffer b;
|
||||
luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
|
||||
@@ -796,16 +780,15 @@ static int str_gsub (lua_State *L) {
|
||||
prepstate(&ms, L, src, srcl, p, lp);
|
||||
while (n < max_s) {
|
||||
const char *e;
|
||||
reprepstate(&ms);
|
||||
if ((e = match(&ms, src, p)) != NULL) {
|
||||
reprepstate(&ms); /* (re)prepare state for new match */
|
||||
if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */
|
||||
n++;
|
||||
add_value(&ms, &b, src, e, tr);
|
||||
add_value(&ms, &b, src, e, tr); /* add replacement to buffer */
|
||||
src = lastmatch = e;
|
||||
}
|
||||
if (e && e>src) /* non empty match? */
|
||||
src = e; /* skip it */
|
||||
else if (src < ms.src_end)
|
||||
else if (src < ms.src_end) /* otherwise, skip one character */
|
||||
luaL_addchar(&b, *src++);
|
||||
else break;
|
||||
else break; /* end of subject */
|
||||
if (anchor) break;
|
||||
}
|
||||
luaL_addlstring(&b, src, ms.src_end-src);
|
||||
@@ -830,7 +813,6 @@ static int str_gsub (lua_State *L) {
|
||||
** Hexadecimal floating-point formatter
|
||||
*/
|
||||
|
||||
#include <locale.h>
|
||||
#include <math.h>
|
||||
|
||||
#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char))
|
||||
@@ -857,11 +839,12 @@ static lua_Number adddigit (char *buff, int n, lua_Number x) {
|
||||
|
||||
|
||||
static int num2straux (char *buff, int sz, lua_Number x) {
|
||||
if (x != x || x == HUGE_VAL || x == -HUGE_VAL) /* inf or NaN? */
|
||||
return l_sprintf(buff, sz, LUA_NUMBER_FMT, x); /* equal to '%g' */
|
||||
/* if 'inf' or 'NaN', format it like '%g' */
|
||||
if (x != x || x == (lua_Number)HUGE_VAL || x == -(lua_Number)HUGE_VAL)
|
||||
return l_sprintf(buff, sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)x);
|
||||
else if (x == 0) { /* can be -0... */
|
||||
/* create "0" or "-0" followed by exponent */
|
||||
return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", x);
|
||||
return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", (LUAI_UACNUMBER)x);
|
||||
}
|
||||
else {
|
||||
int e;
|
||||
@@ -896,7 +879,7 @@ static int lua_number2strx (lua_State *L, char *buff, int sz,
|
||||
buff[i] = toupper(uchar(buff[i]));
|
||||
}
|
||||
else if (fmt[SIZELENMOD] != 'a')
|
||||
luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented");
|
||||
return luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented");
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -922,16 +905,14 @@ static int lua_number2strx (lua_State *L, char *buff, int sz,
|
||||
#define MAX_FORMAT 32
|
||||
|
||||
|
||||
static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
|
||||
size_t l;
|
||||
const char *s = luaL_checklstring(L, arg, &l);
|
||||
static void addquoted (luaL_Buffer *b, const char *s, size_t len) {
|
||||
luaL_addchar(b, '"');
|
||||
while (l--) {
|
||||
while (len--) {
|
||||
if (*s == '"' || *s == '\\' || *s == '\n') {
|
||||
luaL_addchar(b, '\\');
|
||||
luaL_addchar(b, *s);
|
||||
}
|
||||
else if (*s == '\0' || iscntrl(uchar(*s))) {
|
||||
else if (iscntrl(uchar(*s))) {
|
||||
char buff[10];
|
||||
if (!isdigit(uchar(*(s+1))))
|
||||
l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s));
|
||||
@@ -946,6 +927,57 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
|
||||
luaL_addchar(b, '"');
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Ensures the 'buff' string uses a dot as the radix character.
|
||||
*/
|
||||
static void checkdp (char *buff, int nb) {
|
||||
if (memchr(buff, '.', nb) == NULL) { /* no dot? */
|
||||
char point = lua_getlocaledecpoint(); /* try locale point */
|
||||
char *ppoint = (char *)memchr(buff, point, nb);
|
||||
if (ppoint) *ppoint = '.'; /* change it to a dot */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void addliteral (lua_State *L, luaL_Buffer *b, int arg) {
|
||||
switch (lua_type(L, arg)) {
|
||||
case LUA_TSTRING: {
|
||||
size_t len;
|
||||
const char *s = lua_tolstring(L, arg, &len);
|
||||
addquoted(b, s, len);
|
||||
break;
|
||||
}
|
||||
case LUA_TNUMBER: {
|
||||
char *buff = luaL_prepbuffsize(b, MAX_ITEM);
|
||||
int nb;
|
||||
if (!lua_isinteger(L, arg)) { /* float? */
|
||||
lua_Number n = lua_tonumber(L, arg); /* write as hexa ('%a') */
|
||||
nb = lua_number2strx(L, buff, MAX_ITEM, "%" LUA_NUMBER_FRMLEN "a", n);
|
||||
checkdp(buff, nb); /* ensure it uses a dot */
|
||||
}
|
||||
else { /* integers */
|
||||
lua_Integer n = lua_tointeger(L, arg);
|
||||
const char *format = (n == LUA_MININTEGER) /* corner case? */
|
||||
? "0x%" LUA_INTEGER_FRMLEN "x" /* use hexa */
|
||||
: LUA_INTEGER_FMT; /* else use default format */
|
||||
nb = l_sprintf(buff, MAX_ITEM, format, (LUAI_UACINT)n);
|
||||
}
|
||||
luaL_addsize(b, nb);
|
||||
break;
|
||||
}
|
||||
case LUA_TNIL: case LUA_TBOOLEAN: {
|
||||
luaL_tolstring(L, arg, NULL);
|
||||
luaL_addvalue(b);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
luaL_argerror(L, arg, "value has no literal form");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
|
||||
const char *p = strfrmt;
|
||||
while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */
|
||||
@@ -1010,7 +1042,7 @@ static int str_format (lua_State *L) {
|
||||
case 'o': case 'u': case 'x': case 'X': {
|
||||
lua_Integer n = luaL_checkinteger(L, arg);
|
||||
addlenmod(form, LUA_INTEGER_FRMLEN);
|
||||
nb = l_sprintf(buff, MAX_ITEM, form, n);
|
||||
nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACINT)n);
|
||||
break;
|
||||
}
|
||||
case 'a': case 'A':
|
||||
@@ -1020,12 +1052,13 @@ static int str_format (lua_State *L) {
|
||||
break;
|
||||
case 'e': case 'E': case 'f':
|
||||
case 'g': case 'G': {
|
||||
lua_Number n = luaL_checknumber(L, arg);
|
||||
addlenmod(form, LUA_NUMBER_FRMLEN);
|
||||
nb = l_sprintf(buff, MAX_ITEM, form, luaL_checknumber(L, arg));
|
||||
nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACNUMBER)n);
|
||||
break;
|
||||
}
|
||||
case 'q': {
|
||||
addquoted(L, &b, arg);
|
||||
addliteral(L, &b, arg);
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
@@ -1070,8 +1103,8 @@ static int str_format (lua_State *L) {
|
||||
|
||||
|
||||
/* value used for padding */
|
||||
#if !defined(LUA_PACKPADBYTE)
|
||||
#define LUA_PACKPADBYTE 0x00
|
||||
#if !defined(LUAL_PACKPADBYTE)
|
||||
#define LUAL_PACKPADBYTE 0x00
|
||||
#endif
|
||||
|
||||
/* maximum size for the binary representation of an integer */
|
||||
@@ -1166,8 +1199,8 @@ static int getnum (const char **fmt, int df) {
|
||||
static int getnumlimit (Header *h, const char **fmt, int df) {
|
||||
int sz = getnum(fmt, df);
|
||||
if (sz > MAXINTSIZE || sz <= 0)
|
||||
luaL_error(h->L, "integral size (%d) out of limits [1,%d]",
|
||||
sz, MAXINTSIZE);
|
||||
return luaL_error(h->L, "integral size (%d) out of limits [1,%d]",
|
||||
sz, MAXINTSIZE);
|
||||
return sz;
|
||||
}
|
||||
|
||||
@@ -1228,7 +1261,7 @@ static KOption getoption (Header *h, const char **fmt, int *size) {
|
||||
** 'psize' is filled with option's size, 'notoalign' with its
|
||||
** alignment requirements.
|
||||
** Local variable 'size' gets the size to be aligned. (Kpadal option
|
||||
** always gets its full alignment, other options are limited by
|
||||
** always gets its full alignment, other options are limited by
|
||||
** the maximum alignment ('maxalign'). Kchar option needs no alignment
|
||||
** despite its size.
|
||||
*/
|
||||
@@ -1308,7 +1341,7 @@ static int str_pack (lua_State *L) {
|
||||
KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
|
||||
totalsize += ntoalign + size;
|
||||
while (ntoalign-- > 0)
|
||||
luaL_addchar(&b, LUA_PACKPADBYTE); /* fill alignment */
|
||||
luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */
|
||||
arg++;
|
||||
switch (opt) {
|
||||
case Kint: { /* signed integers */
|
||||
@@ -1343,13 +1376,11 @@ static int str_pack (lua_State *L) {
|
||||
case Kchar: { /* fixed-size string */
|
||||
size_t len;
|
||||
const char *s = luaL_checklstring(L, arg, &len);
|
||||
if ((size_t)size <= len) /* string larger than (or equal to) needed? */
|
||||
luaL_addlstring(&b, s, size); /* truncate string to asked size */
|
||||
else { /* string smaller than needed */
|
||||
luaL_addlstring(&b, s, len); /* add it all */
|
||||
while (len++ < (size_t)size) /* pad extra space */
|
||||
luaL_addchar(&b, LUA_PACKPADBYTE);
|
||||
}
|
||||
luaL_argcheck(L, len <= (size_t)size, arg,
|
||||
"string longer than given size");
|
||||
luaL_addlstring(&b, s, len); /* add string */
|
||||
while (len++ < (size_t)size) /* pad extra space */
|
||||
luaL_addchar(&b, LUAL_PACKPADBYTE);
|
||||
break;
|
||||
}
|
||||
case Kstring: { /* strings with length count */
|
||||
@@ -1372,7 +1403,7 @@ static int str_pack (lua_State *L) {
|
||||
totalsize += len + 1;
|
||||
break;
|
||||
}
|
||||
case Kpadding: luaL_addchar(&b, LUA_PACKPADBYTE); /* FALLTHROUGH */
|
||||
case Kpadding: luaL_addchar(&b, LUAL_PACKPADBYTE); /* FALLTHROUGH */
|
||||
case Kpaddalign: case Knop:
|
||||
arg--; /* undo increment */
|
||||
break;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ltable.c,v 2.117 2015/11/19 19:16:22 roberto Exp $
|
||||
** $Id: ltable.c,v 2.118.1.4 2018/06/08 16:22:51 roberto Exp $
|
||||
** Lua tables (hash)
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -74,8 +74,6 @@
|
||||
|
||||
#define dummynode (&dummynode_)
|
||||
|
||||
#define isdummy(n) ((n) == dummynode)
|
||||
|
||||
static const Node dummynode_ = {
|
||||
{NILCONSTANT}, /* value */
|
||||
{{NILCONSTANT, 0}} /* key */
|
||||
@@ -225,7 +223,9 @@ static unsigned int computesizes (unsigned int nums[], unsigned int *pna) {
|
||||
unsigned int na = 0; /* number of elements to go to array part */
|
||||
unsigned int optimal = 0; /* optimal size for array part */
|
||||
/* loop while keys can fill more than half of total size */
|
||||
for (i = 0, twotoi = 1; *pna > twotoi / 2; i++, twotoi *= 2) {
|
||||
for (i = 0, twotoi = 1;
|
||||
twotoi > 0 && *pna > twotoi / 2;
|
||||
i++, twotoi *= 2) {
|
||||
if (nums[i] > 0) {
|
||||
a += nums[i];
|
||||
if (a > twotoi/2) { /* more than half elements present? */
|
||||
@@ -308,14 +308,14 @@ static void setarrayvector (lua_State *L, Table *t, unsigned int size) {
|
||||
|
||||
|
||||
static void setnodevector (lua_State *L, Table *t, unsigned int size) {
|
||||
int lsize;
|
||||
if (size == 0) { /* no elements to hash part? */
|
||||
t->node = cast(Node *, dummynode); /* use common 'dummynode' */
|
||||
lsize = 0;
|
||||
t->lsizenode = 0;
|
||||
t->lastfree = NULL; /* signal that it is using dummy node */
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
lsize = luaO_ceillog2(size);
|
||||
int lsize = luaO_ceillog2(size);
|
||||
if (lsize > MAXHBITS)
|
||||
luaG_runerror(L, "table overflow");
|
||||
size = twoto(lsize);
|
||||
@@ -326,9 +326,21 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) {
|
||||
setnilvalue(wgkey(n));
|
||||
setnilvalue(gval(n));
|
||||
}
|
||||
t->lsizenode = cast_byte(lsize);
|
||||
t->lastfree = gnode(t, size); /* all positions are free */
|
||||
}
|
||||
t->lsizenode = cast_byte(lsize);
|
||||
t->lastfree = gnode(t, size); /* all positions are free */
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
Table *t;
|
||||
unsigned int nhsize;
|
||||
} AuxsetnodeT;
|
||||
|
||||
|
||||
static void auxsetnode (lua_State *L, void *ud) {
|
||||
AuxsetnodeT *asn = cast(AuxsetnodeT *, ud);
|
||||
setnodevector(L, asn->t, asn->nhsize);
|
||||
}
|
||||
|
||||
|
||||
@@ -336,13 +348,18 @@ void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
|
||||
unsigned int nhsize) {
|
||||
unsigned int i;
|
||||
int j;
|
||||
AuxsetnodeT asn;
|
||||
unsigned int oldasize = t->sizearray;
|
||||
int oldhsize = t->lsizenode;
|
||||
int oldhsize = allocsizenode(t);
|
||||
Node *nold = t->node; /* save old hash ... */
|
||||
if (nasize > oldasize) /* array part must grow? */
|
||||
setarrayvector(L, t, nasize);
|
||||
/* create new hash part with appropriate size */
|
||||
setnodevector(L, t, nhsize);
|
||||
asn.t = t; asn.nhsize = nhsize;
|
||||
if (luaD_rawrunprotected(L, auxsetnode, &asn) != LUA_OK) { /* mem. error? */
|
||||
setarrayvector(L, t, oldasize); /* array back to its original size */
|
||||
luaD_throw(L, LUA_ERRMEM); /* rethrow memory error */
|
||||
}
|
||||
if (nasize < oldasize) { /* array part must shrink? */
|
||||
t->sizearray = nasize;
|
||||
/* re-insert elements from vanishing slice */
|
||||
@@ -354,7 +371,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
|
||||
luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
|
||||
}
|
||||
/* re-insert elements from hash part */
|
||||
for (j = twoto(oldhsize) - 1; j >= 0; j--) {
|
||||
for (j = oldhsize - 1; j >= 0; j--) {
|
||||
Node *old = nold + j;
|
||||
if (!ttisnil(gval(old))) {
|
||||
/* doesn't need barrier/invalidate cache, as entry was
|
||||
@@ -362,13 +379,13 @@ void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
|
||||
setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old));
|
||||
}
|
||||
}
|
||||
if (!isdummy(nold))
|
||||
luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old hash */
|
||||
if (oldhsize > 0) /* not the dummy node? */
|
||||
luaM_freearray(L, nold, cast(size_t, oldhsize)); /* free old hash */
|
||||
}
|
||||
|
||||
|
||||
void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize) {
|
||||
int nsize = isdummy(t->node) ? 0 : sizenode(t);
|
||||
int nsize = allocsizenode(t);
|
||||
luaH_resize(L, t, nasize, nsize);
|
||||
}
|
||||
|
||||
@@ -414,7 +431,7 @@ Table *luaH_new (lua_State *L) {
|
||||
|
||||
|
||||
void luaH_free (lua_State *L, Table *t) {
|
||||
if (!isdummy(t->node))
|
||||
if (!isdummy(t))
|
||||
luaM_freearray(L, t->node, cast(size_t, sizenode(t)));
|
||||
luaM_freearray(L, t->array, t->sizearray);
|
||||
luaM_free(L, t);
|
||||
@@ -422,10 +439,12 @@ void luaH_free (lua_State *L, Table *t) {
|
||||
|
||||
|
||||
static Node *getfreepos (Table *t) {
|
||||
while (t->lastfree > t->node) {
|
||||
t->lastfree--;
|
||||
if (ttisnil(gkey(t->lastfree)))
|
||||
return t->lastfree;
|
||||
if (!isdummy(t)) {
|
||||
while (t->lastfree > t->node) {
|
||||
t->lastfree--;
|
||||
if (ttisnil(gkey(t->lastfree)))
|
||||
return t->lastfree;
|
||||
}
|
||||
}
|
||||
return NULL; /* could not find a free place */
|
||||
}
|
||||
@@ -445,7 +464,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
|
||||
if (ttisnil(key)) luaG_runerror(L, "table index is nil");
|
||||
else if (ttisfloat(key)) {
|
||||
lua_Integer k;
|
||||
if (luaV_tointeger(key, &k, 0)) { /* index is int? */
|
||||
if (luaV_tointeger(key, &k, 0)) { /* does index fit in an integer? */
|
||||
setivalue(&aux, k);
|
||||
key = &aux; /* insert it as an integer */
|
||||
}
|
||||
@@ -453,7 +472,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
|
||||
luaG_runerror(L, "table index is NaN");
|
||||
}
|
||||
mp = mainposition(t, key);
|
||||
if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */
|
||||
if (!ttisnil(gval(mp)) || isdummy(t)) { /* main position is taken? */
|
||||
Node *othern;
|
||||
Node *f = getfreepos(t); /* get a free place */
|
||||
if (f == NULL) { /* cannot find a free place? */
|
||||
@@ -461,7 +480,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
|
||||
/* whatever called 'newkey' takes care of TM cache */
|
||||
return luaH_set(L, t, key); /* insert key into grown table */
|
||||
}
|
||||
lua_assert(!isdummy(f));
|
||||
lua_assert(!isdummy(t));
|
||||
othern = mainposition(t, gkey(mp));
|
||||
if (othern != mp) { /* is colliding node out of its main position? */
|
||||
/* yes; move colliding node into free position */
|
||||
@@ -610,13 +629,13 @@ void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) {
|
||||
}
|
||||
|
||||
|
||||
static int unbound_search (Table *t, unsigned int j) {
|
||||
unsigned int i = j; /* i is zero or a present index */
|
||||
static lua_Unsigned unbound_search (Table *t, lua_Unsigned j) {
|
||||
lua_Unsigned i = j; /* i is zero or a present index */
|
||||
j++;
|
||||
/* find 'i' and 'j' such that i is present and j is not */
|
||||
while (!ttisnil(luaH_getint(t, j))) {
|
||||
i = j;
|
||||
if (j > cast(unsigned int, MAX_INT)/2) { /* overflow? */
|
||||
if (j > l_castS2U(LUA_MAXINTEGER) / 2) { /* overflow? */
|
||||
/* table was built with bad purposes: resort to linear search */
|
||||
i = 1;
|
||||
while (!ttisnil(luaH_getint(t, i))) i++;
|
||||
@@ -626,7 +645,7 @@ static int unbound_search (Table *t, unsigned int j) {
|
||||
}
|
||||
/* now do a binary search between them */
|
||||
while (j - i > 1) {
|
||||
unsigned int m = (i+j)/2;
|
||||
lua_Unsigned m = (i+j)/2;
|
||||
if (ttisnil(luaH_getint(t, m))) j = m;
|
||||
else i = m;
|
||||
}
|
||||
@@ -638,7 +657,7 @@ static int unbound_search (Table *t, unsigned int j) {
|
||||
** Try to find a boundary in table 't'. A 'boundary' is an integer index
|
||||
** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
|
||||
*/
|
||||
int luaH_getn (Table *t) {
|
||||
lua_Unsigned luaH_getn (Table *t) {
|
||||
unsigned int j = t->sizearray;
|
||||
if (j > 0 && ttisnil(&t->array[j - 1])) {
|
||||
/* there is a boundary in the array part: (binary) search for it */
|
||||
@@ -651,7 +670,7 @@ int luaH_getn (Table *t) {
|
||||
return i;
|
||||
}
|
||||
/* else must find a boundary in hash part */
|
||||
else if (isdummy(t->node)) /* hash part is empty? */
|
||||
else if (isdummy(t)) /* hash part is empty? */
|
||||
return j; /* that is easy... */
|
||||
else return unbound_search(t, j);
|
||||
}
|
||||
@@ -664,6 +683,6 @@ Node *luaH_mainposition (const Table *t, const TValue *key) {
|
||||
return mainposition(t, key);
|
||||
}
|
||||
|
||||
int luaH_isdummy (Node *n) { return isdummy(n); }
|
||||
int luaH_isdummy (const Table *t) { return isdummy(t); }
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ltable.h,v 2.21 2015/11/03 15:47:30 roberto Exp $
|
||||
** $Id: ltable.h,v 2.23.1.2 2018/05/24 19:39:05 roberto Exp $
|
||||
** Lua tables (hash)
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -15,7 +15,7 @@
|
||||
#define gnext(n) ((n)->i_key.nk.next)
|
||||
|
||||
|
||||
/* 'const' to avoid wrong writings that can mess up field 'next' */
|
||||
/* 'const' to avoid wrong writings that can mess up field 'next' */
|
||||
#define gkey(n) cast(const TValue*, (&(n)->i_key.tvk))
|
||||
|
||||
/*
|
||||
@@ -27,6 +27,14 @@
|
||||
#define invalidateTMcache(t) ((t)->flags = 0)
|
||||
|
||||
|
||||
/* true when 't' is using 'dummynode' as its hash part */
|
||||
#define isdummy(t) ((t)->lastfree == NULL)
|
||||
|
||||
|
||||
/* allocated size for hash nodes */
|
||||
#define allocsizenode(t) (isdummy(t) ? 0 : sizenode(t))
|
||||
|
||||
|
||||
/* returns the key, given the value of a table entry */
|
||||
#define keyfromval(v) \
|
||||
(gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val))))
|
||||
@@ -46,12 +54,12 @@ LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
|
||||
LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize);
|
||||
LUAI_FUNC void luaH_free (lua_State *L, Table *t);
|
||||
LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
|
||||
LUAI_FUNC int luaH_getn (Table *t);
|
||||
LUAI_FUNC lua_Unsigned luaH_getn (Table *t);
|
||||
|
||||
|
||||
#if defined(LUA_DEBUG)
|
||||
LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);
|
||||
LUAI_FUNC int luaH_isdummy (Node *n);
|
||||
LUAI_FUNC int luaH_isdummy (const Table *t);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ltablib.c,v 1.90 2015/11/25 12:48:57 roberto Exp $
|
||||
** $Id: ltablib.c,v 1.93.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Library for Table Manipulation
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -53,7 +53,7 @@ static void checktab (lua_State *L, int arg, int what) {
|
||||
lua_pop(L, n); /* pop metatable and tested metamethods */
|
||||
}
|
||||
else
|
||||
luaL_argerror(L, arg, "table expected"); /* force an error */
|
||||
luaL_checktype(L, arg, LUA_TTABLE); /* force an error */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ static int tmove (lua_State *L) {
|
||||
n = e - f + 1; /* number of elements to move */
|
||||
luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4,
|
||||
"destination wrap around");
|
||||
if (t > e || t <= f || tt != 1) {
|
||||
if (t > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) {
|
||||
for (i = 0; i < n; i++) {
|
||||
lua_geti(L, 1, f + i);
|
||||
lua_seti(L, tt, t + i);
|
||||
@@ -152,7 +152,7 @@ static int tmove (lua_State *L) {
|
||||
}
|
||||
}
|
||||
}
|
||||
lua_pushvalue(L, tt); /* return "to table" */
|
||||
lua_pushvalue(L, tt); /* return destination table */
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ static int tconcat (lua_State *L) {
|
||||
size_t lsep;
|
||||
const char *sep = luaL_optlstring(L, 2, "", &lsep);
|
||||
lua_Integer i = luaL_optinteger(L, 3, 1);
|
||||
last = luaL_opt(L, luaL_checkinteger, 4, last);
|
||||
last = luaL_optinteger(L, 4, last);
|
||||
luaL_buffinit(L, &b);
|
||||
for (; i < last; i++) {
|
||||
addfield(L, &b, i);
|
||||
@@ -232,6 +232,10 @@ static int unpack (lua_State *L) {
|
||||
*/
|
||||
|
||||
|
||||
/* type for array indices */
|
||||
typedef unsigned int IdxT;
|
||||
|
||||
|
||||
/*
|
||||
** Produce a "random" 'unsigned int' to randomize pivot choice. This
|
||||
** macro is used only when 'sort' detects a big imbalance in the result
|
||||
@@ -270,7 +274,7 @@ static unsigned int l_randomizePivot (void) {
|
||||
#define RANLIMIT 100u
|
||||
|
||||
|
||||
static void set2 (lua_State *L, unsigned int i, unsigned int j) {
|
||||
static void set2 (lua_State *L, IdxT i, IdxT j) {
|
||||
lua_seti(L, 1, i);
|
||||
lua_seti(L, 1, j);
|
||||
}
|
||||
@@ -303,10 +307,9 @@ static int sort_comp (lua_State *L, int a, int b) {
|
||||
** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up]
|
||||
** returns 'i'.
|
||||
*/
|
||||
static unsigned int partition (lua_State *L, unsigned int lo,
|
||||
unsigned int up) {
|
||||
unsigned int i = lo; /* will be incremented before first use */
|
||||
unsigned int j = up - 1; /* will be decremented before first use */
|
||||
static IdxT partition (lua_State *L, IdxT lo, IdxT up) {
|
||||
IdxT i = lo; /* will be incremented before first use */
|
||||
IdxT j = up - 1; /* will be decremented before first use */
|
||||
/* loop invariant: a[lo .. i] <= P <= a[j .. up] */
|
||||
for (;;) {
|
||||
/* next loop: repeat ++i while a[i] < P */
|
||||
@@ -340,10 +343,9 @@ static unsigned int partition (lua_State *L, unsigned int lo,
|
||||
** Choose an element in the middle (2nd-3th quarters) of [lo,up]
|
||||
** "randomized" by 'rnd'
|
||||
*/
|
||||
static unsigned int choosePivot (unsigned int lo, unsigned int up,
|
||||
unsigned int rnd) {
|
||||
unsigned int r4 = (unsigned int)(up - lo) / 4u; /* range/4 */
|
||||
unsigned int p = rnd % (r4 * 2) + (lo + r4);
|
||||
static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) {
|
||||
IdxT r4 = (up - lo) / 4; /* range/4 */
|
||||
IdxT p = rnd % (r4 * 2) + (lo + r4);
|
||||
lua_assert(lo + r4 <= p && p <= up - r4);
|
||||
return p;
|
||||
}
|
||||
@@ -352,11 +354,11 @@ static unsigned int choosePivot (unsigned int lo, unsigned int up,
|
||||
/*
|
||||
** QuickSort algorithm (recursive function)
|
||||
*/
|
||||
static void auxsort (lua_State *L, unsigned int lo, unsigned int up,
|
||||
static void auxsort (lua_State *L, IdxT lo, IdxT up,
|
||||
unsigned int rnd) {
|
||||
while (lo < up) { /* loop for tail recursion */
|
||||
unsigned int p; /* Pivot index */
|
||||
unsigned int n; /* to be used later */
|
||||
IdxT p; /* Pivot index */
|
||||
IdxT n; /* to be used later */
|
||||
/* sort elements 'lo', 'p', and 'up' */
|
||||
lua_geti(L, 1, lo);
|
||||
lua_geti(L, 1, up);
|
||||
@@ -400,7 +402,7 @@ static void auxsort (lua_State *L, unsigned int lo, unsigned int up,
|
||||
n = up - p; /* size of smaller interval */
|
||||
up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */
|
||||
}
|
||||
if ((up - lo) / 128u > n) /* partition too imbalanced? */
|
||||
if ((up - lo) / 128 > n) /* partition too imbalanced? */
|
||||
rnd = l_randomizePivot(); /* try a new randomization */
|
||||
} /* tail call auxsort(L, lo, up, rnd) */
|
||||
}
|
||||
@@ -410,11 +412,10 @@ static int sort (lua_State *L) {
|
||||
lua_Integer n = aux_getn(L, 1, TAB_RW);
|
||||
if (n > 1) { /* non-trivial interval? */
|
||||
luaL_argcheck(L, n < INT_MAX, 1, "array too big");
|
||||
luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */
|
||||
if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */
|
||||
lua_settop(L, 2); /* make sure there are two arguments */
|
||||
auxsort(L, 1, (unsigned int)n, 0u);
|
||||
auxsort(L, 1, (IdxT)n, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ltm.c,v 2.36 2015/11/03 15:47:30 roberto Exp $
|
||||
** $Id: ltm.c,v 2.38.1.1 2017/04/19 17:39:34 roberto Exp $
|
||||
** Tag methods
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "lua.h"
|
||||
|
||||
#include "ldebug.h"
|
||||
#include "ldo.h"
|
||||
#include "ldo.h"
|
||||
#include "lobject.h"
|
||||
#include "lstate.h"
|
||||
#include "lstring.h"
|
||||
@@ -83,6 +83,22 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Return the name of the type of an object. For tables and userdata
|
||||
** with metatable, use their '__name' metafield, if present.
|
||||
*/
|
||||
const char *luaT_objtypename (lua_State *L, const TValue *o) {
|
||||
Table *mt;
|
||||
if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) ||
|
||||
(ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) {
|
||||
const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name"));
|
||||
if (ttisstring(name)) /* is '__name' a string? */
|
||||
return getstr(tsvalue(name)); /* use it as type name */
|
||||
}
|
||||
return ttypename(ttnov(o)); /* else use standard type name */
|
||||
}
|
||||
|
||||
|
||||
void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
|
||||
const TValue *p2, TValue *p3, int hasres) {
|
||||
ptrdiff_t result = savestack(L, p3);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ltm.h,v 2.21 2014/10/25 11:50:46 roberto Exp $
|
||||
** $Id: ltm.h,v 2.22.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Tag methods
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -51,11 +51,12 @@ typedef enum {
|
||||
#define fasttm(l,et,e) gfasttm(G(l), et, e)
|
||||
|
||||
#define ttypename(x) luaT_typenames_[(x) + 1]
|
||||
#define objtypename(x) ttypename(ttnov(x))
|
||||
|
||||
LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS];
|
||||
|
||||
|
||||
LUAI_FUNC const char *luaT_objtypename (lua_State *L, const TValue *o);
|
||||
|
||||
LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);
|
||||
LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
|
||||
TMS event);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lua.c,v 1.226 2015/08/14 19:11:20 roberto Exp $
|
||||
** $Id: lua.c,v 1.230.1.1 2017/04/19 17:29:57 roberto Exp $
|
||||
** Lua stand-alone interpreter
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "lstring.h"
|
||||
|
||||
|
||||
|
||||
#if !defined(LUA_PROMPT)
|
||||
#define LUA_PROMPT "> "
|
||||
#define LUA_PROMPT2 ">> "
|
||||
@@ -38,8 +39,7 @@
|
||||
#define LUA_INIT_VAR "LUA_INIT"
|
||||
#endif
|
||||
|
||||
#define LUA_INITVARVERSION \
|
||||
LUA_INIT_VAR "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
|
||||
#define LUA_INITVARVERSION LUA_INIT_VAR LUA_VERSUFFIX
|
||||
|
||||
|
||||
/*
|
||||
@@ -56,6 +56,8 @@
|
||||
#elif defined(LUA_USE_WINDOWS) /* }{ */
|
||||
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
|
||||
#define lua_stdin_is_tty() _isatty(_fileno(stdin))
|
||||
|
||||
#else /* }{ */
|
||||
@@ -137,7 +139,7 @@ static void print_usage (const char *badoption) {
|
||||
"Available options are:\n"
|
||||
" -e stat execute string 'stat'\n"
|
||||
" -i enter interactive mode after executing 'script'\n"
|
||||
" -l name require library 'name'\n"
|
||||
" -l name require library 'name' into global 'name'\n"
|
||||
" -v show version information\n"
|
||||
" -E ignore environment variables\n"
|
||||
" -- stop handling options\n"
|
||||
@@ -458,7 +460,7 @@ static int handle_script (lua_State *L, char **argv) {
|
||||
/*
|
||||
** Traverses all arguments from 'argv', returning a mask with those
|
||||
** needed before running any Lua code (or an error code if it finds
|
||||
** any invalid argument). 'first' returns the first not-handled argument
|
||||
** any invalid argument). 'first' returns the first not-handled argument
|
||||
** (either the script name or a bad argument in case of error).
|
||||
*/
|
||||
static int collectargs (char **argv, int *first) {
|
||||
@@ -482,7 +484,7 @@ static int collectargs (char **argv, int *first) {
|
||||
args |= has_E;
|
||||
break;
|
||||
case 'i':
|
||||
args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */
|
||||
args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */
|
||||
case 'v':
|
||||
if (argv[i][2] != '\0') /* extra characters after 1st? */
|
||||
return has_error; /* invalid option */
|
||||
@@ -530,6 +532,7 @@ static int runargs (lua_State *L, char **argv, int n) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int handle_luainit (lua_State *L) {
|
||||
const char *name = "=" LUA_INITVARVERSION;
|
||||
const char *init = getenv(name + 1);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lua.h,v 1.329 2015/11/13 17:18:42 roberto Exp $
|
||||
** $Id: lua.h,v 1.332.1.2 2018/06/13 16:58:17 roberto Exp $
|
||||
** Lua - A Scripting Language
|
||||
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
|
||||
** See Copyright Notice at the end of this file
|
||||
@@ -19,11 +19,11 @@
|
||||
#define LUA_VERSION_MAJOR "5"
|
||||
#define LUA_VERSION_MINOR "3"
|
||||
#define LUA_VERSION_NUM 503
|
||||
#define LUA_VERSION_RELEASE "2"
|
||||
#define LUA_VERSION_RELEASE "5"
|
||||
|
||||
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
|
||||
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
|
||||
#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2015 Lua.org, PUC-Rio"
|
||||
#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2018 Lua.org, PUC-Rio"
|
||||
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
|
||||
|
||||
|
||||
@@ -363,7 +363,7 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
|
||||
#define lua_pushliteral(L, s) lua_pushstring(L, "" s)
|
||||
|
||||
#define lua_pushglobaltable(L) \
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)
|
||||
((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS))
|
||||
|
||||
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
|
||||
|
||||
@@ -467,7 +467,7 @@ LUA_API void (lua_checksig_)(lua_State *L);
|
||||
#define lua_checksig(L) if (skynet_sig_L) { lua_checksig_(L); }
|
||||
|
||||
/******************************************************************************
|
||||
* Copyright (C) 1994-2015 Lua.org, PUC-Rio.
|
||||
* Copyright (C) 1994-2018 Lua.org, PUC-Rio.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $
|
||||
** $Id: luac.c,v 1.76 2018/06/19 01:32:02 lhf Exp $
|
||||
** Lua compiler (saves bytecodes to files; also lists bytecodes)
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -208,7 +208,7 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
/*
|
||||
** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $
|
||||
** $Id: luac.c,v 1.76 2018/06/19 01:32:02 lhf Exp $
|
||||
** print bytecodes
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -350,6 +350,7 @@ static void PrintCode(const Proto* f)
|
||||
case OP_ADD:
|
||||
case OP_SUB:
|
||||
case OP_MUL:
|
||||
case OP_MOD:
|
||||
case OP_POW:
|
||||
case OP_DIV:
|
||||
case OP_IDIV:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: luaconf.h,v 1.254 2015/10/21 18:17:40 roberto Exp $
|
||||
** $Id: luaconf.h,v 1.259.1.1 2017/04/19 17:29:57 roberto Exp $
|
||||
** Configuration file for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -158,6 +158,18 @@
|
||||
** ===================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
** LUA_PATH_SEP is the character that separates templates in a path.
|
||||
** LUA_PATH_MARK is the string that marks the substitution points in a
|
||||
** template.
|
||||
** LUA_EXEC_DIR in a Windows path is replaced by the executable's
|
||||
** directory.
|
||||
*/
|
||||
#define LUA_PATH_SEP ";"
|
||||
#define LUA_PATH_MARK "?"
|
||||
#define LUA_EXEC_DIR "!"
|
||||
|
||||
|
||||
/*
|
||||
@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for
|
||||
** Lua libraries.
|
||||
@@ -404,7 +416,7 @@
|
||||
|
||||
/*
|
||||
@@ LUA_NUMBER is the floating-point type used by Lua.
|
||||
@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
|
||||
@@ LUAI_UACNUMBER is the result of a 'default argument promotion'
|
||||
@@ over a floating number.
|
||||
@@ l_mathlim(x) corrects limit name 'x' to the proper float type
|
||||
** by prefixing it with one of FLT/DBL/LDBL.
|
||||
@@ -421,7 +433,8 @@
|
||||
|
||||
#define l_floor(x) (l_mathop(floor)(x))
|
||||
|
||||
#define lua_number2str(s,sz,n) l_sprintf((s), sz, LUA_NUMBER_FMT, (n))
|
||||
#define lua_number2str(s,sz,n) \
|
||||
l_sprintf((s), sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)(n))
|
||||
|
||||
/*
|
||||
@@ lua_numbertointeger converts a float number to an integer, or
|
||||
@@ -498,7 +511,7 @@
|
||||
**
|
||||
@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER.
|
||||
**
|
||||
@@ LUAI_UACINT is the result of an 'usual argument conversion'
|
||||
@@ LUAI_UACINT is the result of a 'default argument promotion'
|
||||
@@ over a lUA_INTEGER.
|
||||
@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers.
|
||||
@@ LUA_INTEGER_FMT is the format for writing integers.
|
||||
@@ -511,10 +524,12 @@
|
||||
/* The following definitions are good for most cases here */
|
||||
|
||||
#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d"
|
||||
#define lua_integer2str(s,sz,n) l_sprintf((s), sz, LUA_INTEGER_FMT, (n))
|
||||
|
||||
#define LUAI_UACINT LUA_INTEGER
|
||||
|
||||
#define lua_integer2str(s,sz,n) \
|
||||
l_sprintf((s), sz, LUA_INTEGER_FMT, (LUAI_UACINT)(n))
|
||||
|
||||
/*
|
||||
** use LUAI_UACINT here to avoid problems with promotions (which
|
||||
** can turn a comparison between unsigneds into a signed comparison)
|
||||
@@ -606,13 +621,21 @@
|
||||
|
||||
|
||||
/*
|
||||
@@ lua_number2strx converts a float to an hexadecimal numeric string.
|
||||
@@ lua_pointer2str converts a pointer to a readable string in a
|
||||
** non-specified way.
|
||||
*/
|
||||
#define lua_pointer2str(buff,sz,p) l_sprintf(buff,sz,"%p",p)
|
||||
|
||||
|
||||
/*
|
||||
@@ lua_number2strx converts a float to an hexadecimal numeric string.
|
||||
** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that.
|
||||
** Otherwise, you can leave 'lua_number2strx' undefined and Lua will
|
||||
** provide its own implementation.
|
||||
*/
|
||||
#if !defined(LUA_USE_C89)
|
||||
#define lua_number2strx(L,b,sz,f,n) l_sprintf(b,sz,f,n)
|
||||
#define lua_number2strx(L,b,sz,f,n) \
|
||||
((void)L, l_sprintf(b,sz,f,(LUAI_UACNUMBER)(n)))
|
||||
#endif
|
||||
|
||||
|
||||
@@ -728,11 +751,11 @@
|
||||
/*
|
||||
@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
|
||||
** CHANGE it if it uses too much C-stack space. (For long double,
|
||||
** 'string.format("%.99f", 1e4932)' needs ~5030 bytes, so a
|
||||
** 'string.format("%.99f", -1e4932)' needs 5034 bytes, so a
|
||||
** smaller buffer would force a memory allocation for each call to
|
||||
** 'string.format'.)
|
||||
*/
|
||||
#if defined(LUA_FLOAT_LONGDOUBLE)
|
||||
#if LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE
|
||||
#define LUAL_BUFFERSIZE 8192
|
||||
#else
|
||||
#define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer)))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lualib.h,v 1.44 2014/02/06 17:32:33 roberto Exp $
|
||||
** $Id: lualib.h,v 1.45.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Lua standard libraries
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -11,6 +11,9 @@
|
||||
#include "lua.h"
|
||||
|
||||
|
||||
/* version suffix for environment variable names */
|
||||
#define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
|
||||
|
||||
|
||||
LUAMOD_API int (luaopen_base) (lua_State *L);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lundump.c,v 2.44 2015/11/02 16:09:30 roberto Exp $
|
||||
** $Id: lundump.c,v 2.44.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** load precompiled Lua chunks
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -273,7 +273,7 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
|
||||
luaD_inctop(L);
|
||||
cl->p = luaF_newproto(L, NULL);
|
||||
LoadFunction(&S, cl->p, NULL);
|
||||
lua_assert(cl->nupvalues == cl->p->sizeupvalues);
|
||||
lua_assert(cl->nupvalues == cl->p->sp->sizeupvalues);
|
||||
luai_verifycode(L, buff, cl->p);
|
||||
return cl;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lundump.h,v 1.45 2015/09/08 15:41:05 roberto Exp $
|
||||
** $Id: lundump.h,v 1.45.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** load precompiled Lua chunks
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lutf8lib.c,v 1.15 2015/03/28 19:16:55 roberto Exp $
|
||||
** $Id: lutf8lib.c,v 1.16.1.1 2017/04/19 17:29:57 roberto Exp $
|
||||
** Standard library for UTF-8 manipulation
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -171,7 +171,7 @@ static int byteoffset (lua_State *L) {
|
||||
}
|
||||
else {
|
||||
if (iscont(s + posi))
|
||||
luaL_error(L, "initial position is a continuation byte");
|
||||
return luaL_error(L, "initial position is a continuation byte");
|
||||
if (n < 0) {
|
||||
while (n < 0 && posi > 0) { /* move back */
|
||||
do { /* find beginning of previous character */
|
||||
@@ -194,7 +194,7 @@ static int byteoffset (lua_State *L) {
|
||||
lua_pushinteger(L, posi + 1);
|
||||
else /* no such character */
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
108
3rd/lua/lvm.c
108
3rd/lua/lvm.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lvm.c,v 2.265 2015/11/23 11:30:45 roberto Exp $
|
||||
** $Id: lvm.c,v 2.268.1.1 2017/04/19 17:39:34 roberto Exp $
|
||||
** Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -163,55 +163,69 @@ static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
|
||||
|
||||
|
||||
/*
|
||||
** Complete a table access: if 't' is a table, 'tm' has its metamethod;
|
||||
** otherwise, 'tm' is NULL.
|
||||
** Finish the table access 'val = t[key]'.
|
||||
** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to
|
||||
** t[k] entry (which must be nil).
|
||||
*/
|
||||
void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
|
||||
const TValue *tm) {
|
||||
const TValue *slot) {
|
||||
int loop; /* counter to avoid infinite loops */
|
||||
lua_assert(tm != NULL || !ttistable(t));
|
||||
const TValue *tm; /* metamethod */
|
||||
for (loop = 0; loop < MAXTAGLOOP; loop++) {
|
||||
if (tm == NULL) { /* no metamethod (from a table)? */
|
||||
if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
|
||||
if (slot == NULL) { /* 't' is not a table? */
|
||||
lua_assert(!ttistable(t));
|
||||
tm = luaT_gettmbyobj(L, t, TM_INDEX);
|
||||
if (ttisnil(tm))
|
||||
luaG_typeerror(L, t, "index"); /* no metamethod */
|
||||
/* else will try the metamethod */
|
||||
}
|
||||
if (ttisfunction(tm)) { /* metamethod is a function */
|
||||
else { /* 't' is a table */
|
||||
lua_assert(ttisnil(slot));
|
||||
tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */
|
||||
if (tm == NULL) { /* no metamethod? */
|
||||
setnilvalue(val); /* result is nil */
|
||||
return;
|
||||
}
|
||||
/* else will try the metamethod */
|
||||
}
|
||||
if (ttisfunction(tm)) { /* is metamethod a function? */
|
||||
luaT_callTM(L, tm, t, key, val, 1); /* call it */
|
||||
return;
|
||||
}
|
||||
t = tm; /* else repeat access over 'tm' */
|
||||
if (luaV_fastget(L,t,key,tm,luaH_get)) { /* try fast track */
|
||||
setobj2s(L, val, tm); /* done */
|
||||
t = tm; /* else try to access 'tm[key]' */
|
||||
if (luaV_fastget(L,t,key,slot,luaH_get)) { /* fast track? */
|
||||
setobj2s(L, val, slot); /* done */
|
||||
return;
|
||||
}
|
||||
/* else repeat */
|
||||
/* else repeat (tail call 'luaV_finishget') */
|
||||
}
|
||||
luaG_runerror(L, "gettable chain too long; possible loop");
|
||||
luaG_runerror(L, "'__index' chain too long; possible loop");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Main function for table assignment (invoking metamethods if needed).
|
||||
** Compute 't[key] = val'
|
||||
** Finish a table assignment 't[key] = val'.
|
||||
** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points
|
||||
** to the entry 't[key]', or to 'luaO_nilobject' if there is no such
|
||||
** entry. (The value at 'slot' must be nil, otherwise 'luaV_fastset'
|
||||
** would have done the job.)
|
||||
*/
|
||||
void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
||||
StkId val, const TValue *oldval) {
|
||||
StkId val, const TValue *slot) {
|
||||
int loop; /* counter to avoid infinite loops */
|
||||
for (loop = 0; loop < MAXTAGLOOP; loop++) {
|
||||
const TValue *tm;
|
||||
if (oldval != NULL) {
|
||||
lua_assert(ttistable(t) && ttisnil(oldval));
|
||||
/* must check the metamethod */
|
||||
if ((tm = fasttm(L, hvalue(t)->metatable, TM_NEWINDEX)) == NULL &&
|
||||
/* no metamethod; is there a previous entry in the table? */
|
||||
(oldval != luaO_nilobject ||
|
||||
/* no previous entry; must create one. (The next test is
|
||||
always true; we only need the assignment.) */
|
||||
(oldval = luaH_newkey(L, hvalue(t), key), 1))) {
|
||||
const TValue *tm; /* '__newindex' metamethod */
|
||||
if (slot != NULL) { /* is 't' a table? */
|
||||
Table *h = hvalue(t); /* save 't' table */
|
||||
lua_assert(ttisnil(slot)); /* old value must be nil */
|
||||
tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */
|
||||
if (tm == NULL) { /* no metamethod? */
|
||||
if (slot == luaO_nilobject) /* no previous entry? */
|
||||
slot = luaH_newkey(L, h, key); /* create one */
|
||||
/* no metamethod and (now) there is an entry with given key */
|
||||
setobj2t(L, cast(TValue *, oldval), val);
|
||||
invalidateTMcache(hvalue(t));
|
||||
luaC_barrierback(L, hvalue(t), val);
|
||||
setobj2t(L, cast(TValue *, slot), val); /* set its new value */
|
||||
invalidateTMcache(h);
|
||||
luaC_barrierback(L, h, val);
|
||||
return;
|
||||
}
|
||||
/* else will try the metamethod */
|
||||
@@ -226,11 +240,11 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
||||
return;
|
||||
}
|
||||
t = tm; /* else repeat assignment over 'tm' */
|
||||
if (luaV_fastset(L, t, key, oldval, luaH_get, val))
|
||||
if (luaV_fastset(L, t, key, slot, luaH_get, val))
|
||||
return; /* done */
|
||||
/* else loop */
|
||||
}
|
||||
luaG_runerror(L, "settable chain too long; possible loop");
|
||||
luaG_runerror(L, "'__newindex' chain too long; possible loop");
|
||||
}
|
||||
|
||||
|
||||
@@ -748,18 +762,28 @@ void luaV_finishOp (lua_State *L) {
|
||||
luai_threadyield(L); }
|
||||
|
||||
|
||||
/* fetch an instruction and prepare its execution */
|
||||
#define vmfetch() { \
|
||||
i = *(ci->u.l.savedpc++); \
|
||||
if (L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) \
|
||||
Protect(luaG_traceexec(L)); \
|
||||
ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \
|
||||
lua_assert(base == ci->u.l.base); \
|
||||
lua_assert(base <= L->top && L->top < L->stack + L->stacksize); \
|
||||
}
|
||||
|
||||
#define vmdispatch(o) switch(o)
|
||||
#define vmcase(l) case l:
|
||||
#define vmbreak break
|
||||
|
||||
|
||||
/*
|
||||
** copy of 'luaV_gettable', but protecting call to potential metamethod
|
||||
** (which can reallocate the stack)
|
||||
** copy of 'luaV_gettable', but protecting the call to potential
|
||||
** metamethod (which can reallocate the stack)
|
||||
*/
|
||||
#define gettableProtected(L,t,k,v) { const TValue *aux; \
|
||||
if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \
|
||||
else Protect(luaV_finishget(L,t,k,v,aux)); }
|
||||
#define gettableProtected(L,t,k,v) { const TValue *slot; \
|
||||
if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \
|
||||
else Protect(luaV_finishget(L,t,k,v,slot)); }
|
||||
|
||||
|
||||
/* same for 'luaV_settable' */
|
||||
@@ -782,14 +806,9 @@ void luaV_execute (lua_State *L) {
|
||||
base = ci->u.l.base; /* local copy of function's base */
|
||||
/* main loop of interpreter */
|
||||
for (;;) {
|
||||
Instruction i = *(ci->u.l.savedpc++);
|
||||
Instruction i;
|
||||
StkId ra;
|
||||
if (L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT))
|
||||
Protect(luaG_traceexec(L));
|
||||
/* WARNING: several calls may realloc the stack and invalidate 'ra' */
|
||||
ra = RA(i);
|
||||
lua_assert(base == ci->u.l.base);
|
||||
lua_assert(base <= L->top && L->top < L->stack + L->stacksize);
|
||||
vmfetch();
|
||||
vmdispatch (GET_OPCODE(i)) {
|
||||
vmcase(OP_MOVE) {
|
||||
setobjs2s(L, ra, RB(i));
|
||||
@@ -1162,7 +1181,7 @@ void luaV_execute (lua_State *L) {
|
||||
oci->u.l.savedpc = nci->u.l.savedpc;
|
||||
oci->callstatus |= CIST_TAIL; /* function was tail called */
|
||||
ci = L->ci = oci; /* remove new frame */
|
||||
lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize);
|
||||
lua_assert(L->top == oci->u.l.base + getproto(ofunc)->sp->maxstacksize);
|
||||
goto newframe; /* restart luaV_execute over new Lua function */
|
||||
}
|
||||
vmbreak;
|
||||
@@ -1182,6 +1201,7 @@ void luaV_execute (lua_State *L) {
|
||||
}
|
||||
}
|
||||
vmcase(OP_FORLOOP) {
|
||||
lua_checksig(L);
|
||||
if (ttisinteger(ra)) { /* integer loop? */
|
||||
lua_Integer step = ivalue(ra + 2);
|
||||
lua_Integer idx = intop(+, ivalue(ra), step); /* increment index */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lvm.h,v 2.39 2015/09/09 13:44:07 roberto Exp $
|
||||
** $Id: lvm.h,v 2.41.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -49,25 +49,24 @@
|
||||
|
||||
|
||||
/*
|
||||
** fast track for 'gettable': 1 means 'aux' points to resulted value;
|
||||
** 0 means 'aux' is metamethod (if 't' is a table) or NULL. 'f' is
|
||||
** the raw get function to use.
|
||||
** fast track for 'gettable': if 't' is a table and 't[k]' is not nil,
|
||||
** return 1 with 'slot' pointing to 't[k]' (final result). Otherwise,
|
||||
** return 0 (meaning it will have to check metamethod) with 'slot'
|
||||
** pointing to a nil 't[k]' (if 't' is a table) or NULL (otherwise).
|
||||
** 'f' is the raw get function to use.
|
||||
*/
|
||||
#define luaV_fastget(L,t,k,aux,f) \
|
||||
#define luaV_fastget(L,t,k,slot,f) \
|
||||
(!ttistable(t) \
|
||||
? (aux = NULL, 0) /* not a table; 'aux' is NULL and result is 0 */ \
|
||||
: (aux = f(hvalue(t), k), /* else, do raw access */ \
|
||||
!ttisnil(aux) ? 1 /* result not nil? 'aux' has it */ \
|
||||
: (aux = fasttm(L, hvalue(t)->metatable, TM_INDEX), /* get metamethod */\
|
||||
aux != NULL ? 0 /* has metamethod? must call it */ \
|
||||
: (aux = luaO_nilobject, 1)))) /* else, final result is nil */
|
||||
? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
|
||||
: (slot = f(hvalue(t), k), /* else, do raw access */ \
|
||||
!ttisnil(slot))) /* result not nil? */
|
||||
|
||||
/*
|
||||
** standard implementation for 'gettable'
|
||||
*/
|
||||
#define luaV_gettable(L,t,k,v) { const TValue *aux; \
|
||||
if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \
|
||||
else luaV_finishget(L,t,k,v,aux); }
|
||||
#define luaV_gettable(L,t,k,v) { const TValue *slot; \
|
||||
if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \
|
||||
else luaV_finishget(L,t,k,v,slot); }
|
||||
|
||||
|
||||
/*
|
||||
@@ -91,7 +90,7 @@
|
||||
#define luaV_settable(L,t,k,v) { const TValue *slot; \
|
||||
if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \
|
||||
luaV_finishset(L,t,k,v,slot); }
|
||||
|
||||
|
||||
|
||||
|
||||
LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
|
||||
@@ -100,9 +99,9 @@ LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r);
|
||||
LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n);
|
||||
LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode);
|
||||
LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key,
|
||||
StkId val, const TValue *tm);
|
||||
StkId val, const TValue *slot);
|
||||
LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
||||
StkId val, const TValue *oldval);
|
||||
StkId val, const TValue *slot);
|
||||
LUAI_FUNC void luaV_finishOp (lua_State *L);
|
||||
LUAI_FUNC void luaV_execute (lua_State *L);
|
||||
LUAI_FUNC void luaV_concat (lua_State *L, int total);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lzio.c,v 1.37 2015/09/08 15:41:05 roberto Exp $
|
||||
** $Id: lzio.c,v 1.37.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Buffered streams
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lzio.h,v 1.31 2015/09/08 15:41:05 roberto Exp $
|
||||
** $Id: lzio.h,v 1.31.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Buffered streams
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
98
HISTORY.md
98
HISTORY.md
@@ -1,3 +1,101 @@
|
||||
v1.2.0 (2018-11-6)
|
||||
-----------
|
||||
* Improve cluster support
|
||||
* Improve mongodb driver
|
||||
* Improve redis driver
|
||||
* Improve socket concurrent write
|
||||
* Improve socket channel
|
||||
* Improve service gate
|
||||
* Improve udp support
|
||||
* Add skynet.ignoreret
|
||||
* Add skynet.trace
|
||||
* Add skynet.context
|
||||
* Improve skynet.wait/wakeup
|
||||
* Add socket.netstat
|
||||
* Add socketchannel.overload
|
||||
* Fix memory leak for dead service
|
||||
* lua update to 5.3.5
|
||||
* jemalloc update to 5.1.0
|
||||
|
||||
v1.1.0 (2017-10-31)
|
||||
-----------
|
||||
* add socket.disconnected()
|
||||
* fix bugs : see comments for detail
|
||||
|
||||
v1.1.0-rc (2017-7-18)
|
||||
-----------
|
||||
* config file : support include
|
||||
* debug console : User config binding IP
|
||||
* debug console : Add call command
|
||||
* debug console : Report error message of inject code
|
||||
* debug console : Change response message
|
||||
* sharedata : Add sharedata.flush
|
||||
* sharedata : Add sharedata.deepcopy
|
||||
* cluster : Add cluster.send
|
||||
* cluster : Add API to update config table
|
||||
* skynet : Add skynet.state
|
||||
* skynet : Keep the order of skynet.wakeup
|
||||
* skynet : Add a MEMORY_CHECK macro for debugging
|
||||
* httpc : Add httpc.timeout
|
||||
* mongo driver : sort support multi-key
|
||||
* bson : Check utf8 string
|
||||
* bson : No longer support numberic key
|
||||
* daemon mode: Can output the error messages
|
||||
* sproto : Support decimal number
|
||||
* sproto: Support binary type
|
||||
* sproto: Support response nil
|
||||
* crypt: Add crypt.hmac64_md5
|
||||
* redis: Add redis-cluster support
|
||||
* socket server : Optimize socket write (Try direct write from worker thread first)
|
||||
* Add prefix skynet to all skynet lua modules
|
||||
* datasheet : New module for replacement of sharedata
|
||||
* jemalloc : Update to 5.0.1
|
||||
* lua : Update to 5.3.4
|
||||
* lpeg : Update to 1.0.1
|
||||
|
||||
v1.0.0 (2016-7-11)
|
||||
-----------
|
||||
* Version 1.0.0 Released
|
||||
|
||||
v1.0.0-rc5 (2016-7-4)
|
||||
-----------
|
||||
* MongoDB : Support auth_scram_sha1
|
||||
* MongoDB : Auto determine primary host
|
||||
* Bugfix : memory leak in multicast
|
||||
* Bugfix : Lua 5.3.3
|
||||
* Bson : support meta array
|
||||
|
||||
v1.0.0-rc4 (2016-6-13)
|
||||
-----------
|
||||
* Update lua to 5.3.3
|
||||
* Update jemalloc to 4.2.1
|
||||
* Add debug console command ping
|
||||
* Lua bson support __pairs
|
||||
* Add mongo.createIndexes and fix bug in old mongo.createIndex
|
||||
* Handle signal HUP to reopen log file (for logrotate)
|
||||
|
||||
v1.0.0-rc3 (2016-5-9)
|
||||
-----------
|
||||
* Update jemalloc 4.1.1
|
||||
* Update lua 5.3.3 rc1
|
||||
* Update sproto to support encoding empty table
|
||||
* Make skynet.init stable (keep order)
|
||||
* skynet.getenv can return empty string
|
||||
* Add lua VM memory warning
|
||||
* lua VM support memory limit
|
||||
* skynet.pcall suport varargs
|
||||
* Bugfix : Global name query
|
||||
* Bugfix : snax.queryglobal
|
||||
|
||||
v1.0.0-rc2 (2016-3-7)
|
||||
-----------
|
||||
* Fix a bug in lua 5.3.2
|
||||
* Update sproto (fix bugs and add ud for package)
|
||||
* Fix a bug in http
|
||||
* Fix a bug in harbor
|
||||
* Fix a bug in socket channel
|
||||
* Enhance remote debugger
|
||||
|
||||
v1.0.0-rc (2015-12-28)
|
||||
-----------
|
||||
* Update to lua 5.3.2
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2012-2015 codingnow.com
|
||||
Copyright (c) 2012-2017 codingnow.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
||||
66
Makefile
66
Makefile
@@ -45,10 +45,26 @@ update3rd :
|
||||
# skynet
|
||||
|
||||
CSERVICE = snlua logger gate harbor
|
||||
LUA_CLIB = skynet socketdriver bson mongo md5 netpack \
|
||||
clientsocket memory profile multicast \
|
||||
cluster crypt sharedata stm sproto lpeg \
|
||||
mysqlaux debugchannel
|
||||
LUA_CLIB = skynet \
|
||||
client \
|
||||
bson md5 sproto lpeg
|
||||
|
||||
LUA_CLIB_SKYNET = \
|
||||
lua-skynet.c lua-seri.c \
|
||||
lua-socket.c \
|
||||
lua-mongo.c \
|
||||
lua-netpack.c \
|
||||
lua-memory.c \
|
||||
lua-profile.c \
|
||||
lua-multicast.c \
|
||||
lua-cluster.c \
|
||||
lua-crypt.c lsha1.c \
|
||||
lua-sharedata.c \
|
||||
lua-stm.c \
|
||||
lua-mysqlaux.c \
|
||||
lua-debugchannel.c \
|
||||
lua-datasheet.c \
|
||||
\
|
||||
|
||||
SKYNET_SRC = skynet_main.c skynet_handle.c skynet_module.c skynet_mq.c \
|
||||
skynet_server.c skynet_start.c skynet_timer.c skynet_error.c \
|
||||
@@ -76,66 +92,30 @@ endef
|
||||
|
||||
$(foreach v, $(CSERVICE), $(eval $(call CSERVICE_TEMP,$(v))))
|
||||
|
||||
$(LUA_CLIB_PATH)/skynet.so : lualib-src/lua-skynet.c lualib-src/lua-seri.c | $(LUA_CLIB_PATH)
|
||||
$(LUA_CLIB_PATH)/skynet.so : $(addprefix lualib-src/,$(LUA_CLIB_SKYNET)) | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src -Iservice-src -Ilualib-src
|
||||
|
||||
$(LUA_CLIB_PATH)/socketdriver.so : lualib-src/lua-socket.c | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src -Iservice-src
|
||||
|
||||
$(LUA_CLIB_PATH)/bson.so : lualib-src/lua-bson.c | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) -Iskynet-src $^ -o $@ -Iskynet-src
|
||||
|
||||
$(LUA_CLIB_PATH)/mongo.so : lualib-src/lua-mongo.c | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src
|
||||
|
||||
$(LUA_CLIB_PATH)/md5.so : 3rd/lua-md5/md5.c 3rd/lua-md5/md5lib.c 3rd/lua-md5/compat-5.2.c | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) -I3rd/lua-md5 $^ -o $@
|
||||
|
||||
$(LUA_CLIB_PATH)/netpack.so : lualib-src/lua-netpack.c | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) $^ -Iskynet-src -o $@
|
||||
|
||||
$(LUA_CLIB_PATH)/clientsocket.so : lualib-src/lua-clientsocket.c | $(LUA_CLIB_PATH)
|
||||
$(LUA_CLIB_PATH)/client.so : lualib-src/lua-clientsocket.c lualib-src/lua-crypt.c lualib-src/lsha1.c | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) $^ -o $@ -lpthread
|
||||
|
||||
$(LUA_CLIB_PATH)/memory.so : lualib-src/lua-memory.c | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) -Iskynet-src $^ -o $@
|
||||
|
||||
$(LUA_CLIB_PATH)/profile.so : lualib-src/lua-profile.c | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) $^ -o $@
|
||||
|
||||
$(LUA_CLIB_PATH)/multicast.so : lualib-src/lua-multicast.c | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) -Iskynet-src $^ -o $@
|
||||
|
||||
$(LUA_CLIB_PATH)/cluster.so : lualib-src/lua-cluster.c | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) -Iskynet-src $^ -o $@
|
||||
|
||||
$(LUA_CLIB_PATH)/crypt.so : lualib-src/lua-crypt.c lualib-src/lsha1.c | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) $^ -o $@
|
||||
|
||||
$(LUA_CLIB_PATH)/sharedata.so : lualib-src/lua-sharedata.c | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) -Iskynet-src $^ -o $@
|
||||
|
||||
$(LUA_CLIB_PATH)/stm.so : lualib-src/lua-stm.c | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) -Iskynet-src $^ -o $@
|
||||
|
||||
$(LUA_CLIB_PATH)/sproto.so : lualib-src/sproto/sproto.c lualib-src/sproto/lsproto.c | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) -Ilualib-src/sproto $^ -o $@
|
||||
|
||||
$(LUA_CLIB_PATH)/lpeg.so : 3rd/lpeg/lpcap.c 3rd/lpeg/lpcode.c 3rd/lpeg/lpprint.c 3rd/lpeg/lptree.c 3rd/lpeg/lpvm.c | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) -I3rd/lpeg $^ -o $@
|
||||
|
||||
$(LUA_CLIB_PATH)/mysqlaux.so : lualib-src/lua-mysqlaux.c | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) $^ -o $@
|
||||
|
||||
$(LUA_CLIB_PATH)/debugchannel.so : lualib-src/lua-debugchannel.c | $(LUA_CLIB_PATH)
|
||||
$(CC) $(CFLAGS) $(SHARED) -Iskynet-src $^ -o $@
|
||||
|
||||
clean :
|
||||
rm -f $(SKYNET_BUILD_PATH)/skynet $(CSERVICE_PATH)/*.so $(LUA_CLIB_PATH)/*.so
|
||||
|
||||
cleanall: clean
|
||||
ifneq (,$(wildcard 3rd/jemalloc/Makefile))
|
||||
cd 3rd/jemalloc && $(MAKE) clean
|
||||
cd 3rd/jemalloc && $(MAKE) clean && rm Makefile
|
||||
endif
|
||||
cd 3rd/lua && $(MAKE) clean
|
||||
rm -f $(LUA_STATICLIB)
|
||||
|
||||
24
README.md
24
README.md
@@ -1,6 +1,10 @@
|
||||
## 
|
||||
|
||||
Skynet is a lightweight online game framework, and it can be used in many other fields.
|
||||
|
||||
## Build
|
||||
|
||||
For linux, install autoconf first for jemalloc
|
||||
For Linux, install autoconf first for jemalloc:
|
||||
|
||||
```
|
||||
git clone https://github.com/cloudwu/skynet.git
|
||||
@@ -8,33 +12,31 @@ cd skynet
|
||||
make 'PLATFORM' # PLATFORM can be linux, macosx, freebsd now
|
||||
```
|
||||
|
||||
Or you can :
|
||||
Or you can:
|
||||
|
||||
```
|
||||
export PLAT=linux
|
||||
make
|
||||
```
|
||||
|
||||
For freeBSD , use gmake instead of make .
|
||||
For FreeBSD , use gmake instead of make.
|
||||
|
||||
## Test
|
||||
|
||||
Run these in different console
|
||||
Run these in different consoles:
|
||||
|
||||
```
|
||||
./skynet examples/config # Launch first skynet node (Gate server) and a skynet-master (see config for standalone option)
|
||||
./3rd/lua/lua examples/client.lua # Launch a client, and try to input hello.
|
||||
```
|
||||
|
||||
## About Lua
|
||||
## About Lua version
|
||||
|
||||
Skynet now use a modify version of lua 5.3.2 ( http://www.lua.org/ftp/lua-5.3.2.tar.gz ) .
|
||||
Skynet now uses a modified version of lua 5.3.5 ( https://github.com/ejoy/lua/tree/skynet ) for multiple lua states.
|
||||
|
||||
For detail : http://lua-users.org/lists/lua-l/2014-03/msg00489.html
|
||||
You can also use official Lua versions, just edit the Makefile by yourself.
|
||||
|
||||
You can also use the other official Lua version , edit the makefile by yourself .
|
||||
## How To Use (Sorry, currently only available in Chinese)
|
||||
|
||||
## How To Use (Sorry, Only in Chinese now)
|
||||
|
||||
* Read Wiki https://github.com/cloudwu/skynet/wiki
|
||||
* Read Wiki for documents https://github.com/cloudwu/skynet/wiki
|
||||
* The FAQ in wiki https://github.com/cloudwu/skynet/wiki/FAQ
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
local skynet = require "skynet"
|
||||
local netpack = require "netpack"
|
||||
local socket = require "socket"
|
||||
local socket = require "skynet.socket"
|
||||
local sproto = require "sproto"
|
||||
local sprotoloader = require "sprotoloader"
|
||||
|
||||
@@ -50,7 +49,10 @@ skynet.register_protocol {
|
||||
unpack = function (msg, sz)
|
||||
return host:dispatch(msg, sz)
|
||||
end,
|
||||
dispatch = function (_, _, type, ...)
|
||||
dispatch = function (fd, _, type, ...)
|
||||
assert(fd == client_fd) -- You can use fd to reply message
|
||||
skynet.ignoreret() -- session is fd, don't call skynet.ret
|
||||
skynet.trace()
|
||||
if type == "REQUEST" then
|
||||
local ok, result = pcall(request, ...)
|
||||
if ok then
|
||||
@@ -92,6 +94,7 @@ end
|
||||
|
||||
skynet.start(function()
|
||||
skynet.dispatch("lua", function(_,_, command, ...)
|
||||
skynet.trace()
|
||||
local f = CMD[command]
|
||||
skynet.ret(skynet.pack(f(...)))
|
||||
end)
|
||||
|
||||
30
examples/checkdeadloop.lua
Normal file
30
examples/checkdeadloop.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
local skynet = require "skynet"
|
||||
|
||||
local list = {}
|
||||
|
||||
local function timeout_check(ti)
|
||||
if not next(list) then
|
||||
return
|
||||
end
|
||||
skynet.sleep(ti) -- sleep 10 sec
|
||||
for k,v in pairs(list) do
|
||||
skynet.error("timout",ti,k,v)
|
||||
end
|
||||
end
|
||||
|
||||
skynet.start(function()
|
||||
skynet.error("ping all")
|
||||
local list_ret = skynet.call(".launcher", "lua", "LIST")
|
||||
for addr, desc in pairs(list_ret) do
|
||||
list[addr] = desc
|
||||
skynet.fork(function()
|
||||
skynet.call(addr,"debug","INFO")
|
||||
list[addr] = nil
|
||||
end)
|
||||
end
|
||||
skynet.sleep(0)
|
||||
timeout_check(100)
|
||||
timeout_check(400)
|
||||
timeout_check(500)
|
||||
skynet.exit()
|
||||
end)
|
||||
@@ -5,7 +5,7 @@ if _VERSION ~= "Lua 5.3" then
|
||||
error "Use lua 5.3"
|
||||
end
|
||||
|
||||
local socket = require "clientsocket"
|
||||
local socket = require "client.socket"
|
||||
local proto = require "proto"
|
||||
local sproto = require "sproto"
|
||||
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
local skynet = require "skynet"
|
||||
local cluster = require "cluster"
|
||||
local snax = require "snax"
|
||||
local cluster = require "skynet.cluster"
|
||||
local snax = require "skynet.snax"
|
||||
|
||||
skynet.start(function()
|
||||
cluster.reload {
|
||||
db = "127.0.0.1:2528",
|
||||
db2 = "127.0.0.1:2529",
|
||||
}
|
||||
|
||||
local sdb = skynet.newservice("simpledb")
|
||||
-- register name "sdb" for simpledb, you can use cluster.query() later.
|
||||
-- See cluster2.lua
|
||||
|
||||
@@ -1,21 +1,31 @@
|
||||
local skynet = require "skynet"
|
||||
local cluster = require "cluster"
|
||||
local cluster = require "skynet.cluster"
|
||||
|
||||
skynet.start(function()
|
||||
-- query name "sdb" of cluster db.
|
||||
local sdb = cluster.query("db", "sdb")
|
||||
print("db.sbd=",sdb)
|
||||
local proxy = cluster.proxy("db", sdb)
|
||||
local proxy = cluster.proxy "db@sdb" -- cluster.proxy("db", "@sdb")
|
||||
local largekey = string.rep("X", 128*1024)
|
||||
local largevalue = string.rep("R", 100 * 1024)
|
||||
print(skynet.call(proxy, "lua", "SET", largekey, largevalue))
|
||||
skynet.call(proxy, "lua", "SET", largekey, largevalue)
|
||||
local v = skynet.call(proxy, "lua", "GET", largekey)
|
||||
assert(largevalue == v)
|
||||
skynet.send(proxy, "lua", "PING", "proxy")
|
||||
|
||||
print(cluster.call("db", sdb, "GET", "a"))
|
||||
print(cluster.call("db2", sdb, "GET", "b"))
|
||||
skynet.fork(function()
|
||||
skynet.trace("cluster")
|
||||
print(cluster.call("db", "@sdb", "GET", "a"))
|
||||
print(cluster.call("db2", "@sdb", "GET", "b"))
|
||||
cluster.send("db2", "@sdb", "PING", "db2:longstring" .. largevalue)
|
||||
end)
|
||||
|
||||
-- test snax service
|
||||
local pingserver = cluster.snax("db", "pingserver")
|
||||
skynet.timeout(300,function()
|
||||
cluster.reload {
|
||||
db = false, -- db is down
|
||||
db3 = "127.0.0.1:2529"
|
||||
}
|
||||
print(pcall(cluster.call, "db", "@sdb", "GET", "a")) -- db is down
|
||||
end)
|
||||
cluster.reload { __nowaiting = false }
|
||||
local pingserver = cluster.snax("db3", "pingserver")
|
||||
print(pingserver.req.ping "hello")
|
||||
end)
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
__nowaiting = true -- If you turn this flag off, cluster.call would block when node name is absent
|
||||
|
||||
db = "127.0.0.1:2528"
|
||||
db2 = "127.0.0.1:2529"
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
root = "./"
|
||||
include "config.path"
|
||||
|
||||
-- preload = "./examples/preload.lua" -- run preload.lua before every lua service run
|
||||
thread = 8
|
||||
logger = nil
|
||||
logpath = "."
|
||||
@@ -8,10 +10,6 @@ master = "127.0.0.1:2013"
|
||||
start = "main" -- main script
|
||||
bootstrap = "snlua bootstrap" -- The service for bootstrap
|
||||
standalone = "0.0.0.0:2013"
|
||||
luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua"
|
||||
lualoader = "lualib/loader.lua"
|
||||
-- preload = "./examples/preload.lua" -- run preload.lua before every lua service run
|
||||
snax = root.."examples/?.lua;"..root.."test/?.lua"
|
||||
-- snax_interface_g = "snax_g"
|
||||
cpath = root.."cservice/?.so"
|
||||
-- daemon = "./skynet.pid"
|
||||
|
||||
@@ -6,5 +6,6 @@ bootstrap = "snlua bootstrap" -- The service for bootstrap
|
||||
luaservice = "./service/?.lua;./test/?.lua;./examples/?.lua"
|
||||
lualoader = "lualib/loader.lua"
|
||||
cpath = "./cservice/?.so"
|
||||
cluster = "./examples/clustername.lua"
|
||||
-- use cluster.reload instead, see cluster1.lua
|
||||
-- cluster = "./examples/clustername.lua"
|
||||
snax = "./test/?.lua"
|
||||
|
||||
11
examples/config.mongodb
Normal file
11
examples/config.mongodb
Normal file
@@ -0,0 +1,11 @@
|
||||
root = "./"
|
||||
thread = 8
|
||||
logger = nil
|
||||
harbor = 0
|
||||
start = "main_mongodb" -- main script
|
||||
bootstrap = "snlua bootstrap" -- The service for bootstrap
|
||||
luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua"
|
||||
lualoader = "lualib/loader.lua"
|
||||
snax = root.."examples/?.lua;"..root.."test/?.lua"
|
||||
cpath = root.."cservice/?.so"
|
||||
-- daemon = "./skynet.pid"
|
||||
6
examples/config.path
Normal file
6
examples/config.path
Normal file
@@ -0,0 +1,6 @@
|
||||
root = "./"
|
||||
luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua;"..root.."test/?/init.lua"
|
||||
lualoader = root .. "lualib/loader.lua"
|
||||
lua_path = root.."lualib/?.lua;"..root.."lualib/?/init.lua"
|
||||
lua_cpath = root .. "luaclib/?.so"
|
||||
snax = root.."examples/?.lua;"..root.."test/?.lua"
|
||||
@@ -1,7 +1,7 @@
|
||||
package.cpath = "luaclib/?.so"
|
||||
|
||||
local socket = require "clientsocket"
|
||||
local crypt = require "crypt"
|
||||
local socket = require "client.socket"
|
||||
local crypt = require "client.crypt"
|
||||
|
||||
if _VERSION ~= "Lua 5.3" then
|
||||
error "Use lua 5.3"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
local msgserver = require "snax.msgserver"
|
||||
local crypt = require "crypt"
|
||||
local crypt = require "skynet.crypt"
|
||||
local skynet = require "skynet"
|
||||
|
||||
local loginservice = tonumber(...)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
local login = require "snax.loginserver"
|
||||
local crypt = require "crypt"
|
||||
local crypt = require "skynet.crypt"
|
||||
local skynet = require "skynet"
|
||||
|
||||
local server = {
|
||||
|
||||
@@ -4,9 +4,11 @@ local sprotoloader = require "sprotoloader"
|
||||
local max_client = 64
|
||||
|
||||
skynet.start(function()
|
||||
print("Server start")
|
||||
skynet.error("Server start")
|
||||
skynet.uniqueservice("protoloader")
|
||||
local console = skynet.newservice("console")
|
||||
if not skynet.getenv "daemon" then
|
||||
local console = skynet.newservice("console")
|
||||
end
|
||||
skynet.newservice("debug_console",8000)
|
||||
skynet.newservice("simpledb")
|
||||
local watchdog = skynet.newservice("watchdog")
|
||||
@@ -15,7 +17,6 @@ skynet.start(function()
|
||||
maxclient = max_client,
|
||||
nodelay = true,
|
||||
})
|
||||
print("Watchdog listen on ", 8888)
|
||||
|
||||
skynet.error("Watchdog listen on", 8888)
|
||||
skynet.exit()
|
||||
end)
|
||||
|
||||
12
examples/main_mongodb.lua
Normal file
12
examples/main_mongodb.lua
Normal file
@@ -0,0 +1,12 @@
|
||||
local skynet = require "skynet"
|
||||
|
||||
|
||||
skynet.start(function()
|
||||
print("Main Server start")
|
||||
local console = skynet.newservice(
|
||||
"testmongodb", "127.0.0.1", 27017, "testdb", "test", "test"
|
||||
)
|
||||
|
||||
print("Main Server exit")
|
||||
skynet.exit()
|
||||
end)
|
||||
@@ -1,5 +1,5 @@
|
||||
local skynet = require "skynet"
|
||||
local sharedata = require "sharedata"
|
||||
local sharedata = require "skynet.sharedata"
|
||||
|
||||
local mode = ...
|
||||
|
||||
|
||||
@@ -16,12 +16,23 @@ end
|
||||
|
||||
skynet.start(function()
|
||||
skynet.dispatch("lua", function(session, address, cmd, ...)
|
||||
local f = command[string.upper(cmd)]
|
||||
cmd = cmd:upper()
|
||||
if cmd == "PING" then
|
||||
assert(session == 0)
|
||||
local str = (...)
|
||||
if #str > 20 then
|
||||
str = str:sub(1,20) .. "...(" .. #str .. ")"
|
||||
end
|
||||
skynet.error(string.format("%s ping %s", skynet.address(address), str))
|
||||
return
|
||||
end
|
||||
local f = command[cmd]
|
||||
if f then
|
||||
skynet.ret(skynet.pack(f(...)))
|
||||
else
|
||||
error(string.format("Unknown command %s", tostring(cmd)))
|
||||
end
|
||||
end)
|
||||
-- skynet.traceproto("lua", false) -- true off tracelog
|
||||
skynet.register "SIMPLEDB"
|
||||
end)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
local skynet = require "skynet"
|
||||
local socket = require "socket"
|
||||
local socket = require "skynet.socket"
|
||||
local httpd = require "http.httpd"
|
||||
local sockethelper = require "http.sockethelper"
|
||||
local urllib = require "http.url"
|
||||
|
||||
@@ -1,15 +1,25 @@
|
||||
local skynet = require "skynet"
|
||||
require "skynet.manager"
|
||||
|
||||
-- register protocol text before skynet.start would be better.
|
||||
skynet.register_protocol {
|
||||
name = "text",
|
||||
id = skynet.PTYPE_TEXT,
|
||||
unpack = skynet.tostring,
|
||||
dispatch = function(_, address, msg)
|
||||
print(string.format("%x(%.2f): %s", address, skynet.time(), msg))
|
||||
print(string.format(":%08x(%.2f): %s", address, skynet.time(), msg))
|
||||
end
|
||||
}
|
||||
|
||||
skynet.register_protocol {
|
||||
name = "SYSTEM",
|
||||
id = skynet.PTYPE_SYSTEM,
|
||||
unpack = function(...) return ... end,
|
||||
dispatch = function()
|
||||
-- reopen signal
|
||||
print("SIGHUP")
|
||||
end
|
||||
}
|
||||
|
||||
skynet.start(function()
|
||||
skynet.register ".logger"
|
||||
end)
|
||||
@@ -1,5 +1,4 @@
|
||||
local skynet = require "skynet"
|
||||
local netpack = require "netpack"
|
||||
|
||||
local CMD = {}
|
||||
local SOCKET = {}
|
||||
|
||||
@@ -82,6 +82,8 @@ A million repetitions of "a"
|
||||
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
|
||||
*/
|
||||
|
||||
#define LUA_LIB
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
@@ -269,7 +271,7 @@ xor_key(uint8_t key[BLOCKSIZE], uint32_t xor) {
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
LUAMOD_API int
|
||||
lhmac_sha1(lua_State *L) {
|
||||
size_t key_sz = 0;
|
||||
const uint8_t * key = (const uint8_t *)luaL_checklstring(L, 1, &key_sz);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#define LUA_LIB
|
||||
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
@@ -198,10 +200,50 @@ write_length(struct bson *b, int32_t v, int off) {
|
||||
b->ptr[off++] = (uv >> 24)&0xff;
|
||||
}
|
||||
|
||||
#define MAXUNICODE 0x10FFFF
|
||||
|
||||
static int
|
||||
utf8_copy(const char *s, char *d, size_t limit) {
|
||||
static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF};
|
||||
unsigned int c = s[0];
|
||||
unsigned int res = 0;
|
||||
if (limit < 1)
|
||||
return 0;
|
||||
d[0] = s[0];
|
||||
if (c < 0x80) {
|
||||
return 1;
|
||||
} else {
|
||||
int count = 0;
|
||||
while (c & 0x40) {
|
||||
int cc = s[++count];
|
||||
if (limit <= count || (cc & 0xC0) != 0x80)
|
||||
return 0;
|
||||
d[count] = s[count];
|
||||
res = (res << 6) | (cc & 0x3F);
|
||||
c <<= 1;
|
||||
}
|
||||
res |= ((c & 0x7F) << (count * 5));
|
||||
if (count > 3 || res > MAXUNICODE || res <= limits[count])
|
||||
return 0;
|
||||
return count+1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
write_string(struct bson *b, const char *key, size_t sz) {
|
||||
write_string(struct bson *b, lua_State *L, const char *key, size_t sz) {
|
||||
bson_reserve(b,sz+1);
|
||||
memcpy(b->ptr + b->size, key, sz);
|
||||
char *dst = (char *)(b->ptr + b->size);
|
||||
const char *src = key;
|
||||
size_t n = sz;
|
||||
while(n > 0) {
|
||||
int c = utf8_copy(src, dst, n);
|
||||
if (c == 0) {
|
||||
luaL_error(L, "Invalid utf8 string");
|
||||
}
|
||||
src += c;
|
||||
dst += c;
|
||||
n -= c;
|
||||
}
|
||||
b->ptr[b->size+sz] = '\0';
|
||||
b->size+=sz+1;
|
||||
}
|
||||
@@ -238,12 +280,10 @@ write_double(struct bson *b, lua_Number d) {
|
||||
}
|
||||
}
|
||||
|
||||
static void pack_dict(lua_State *L, struct bson *b, bool array, int depth);
|
||||
|
||||
static inline void
|
||||
append_key(struct bson *bs, int type, const char *key, size_t sz) {
|
||||
append_key(struct bson *bs, lua_State *L, int type, const char *key, size_t sz) {
|
||||
write_byte(bs, type);
|
||||
write_string(bs, key, sz);
|
||||
write_string(bs, L, key, sz);
|
||||
}
|
||||
|
||||
static inline int
|
||||
@@ -256,38 +296,20 @@ append_number(struct bson *bs, lua_State *L, const char *key, size_t sz) {
|
||||
if (lua_isinteger(L, -1)) {
|
||||
int64_t i = lua_tointeger(L, -1);
|
||||
if (is_32bit(i)) {
|
||||
append_key(bs, BSON_INT32, key, sz);
|
||||
append_key(bs, L, BSON_INT32, key, sz);
|
||||
write_int32(bs, i);
|
||||
} else {
|
||||
append_key(bs, BSON_INT64, key, sz);
|
||||
append_key(bs, L, BSON_INT64, key, sz);
|
||||
write_int64(bs, i);
|
||||
}
|
||||
} else {
|
||||
lua_Number d = lua_tonumber(L,-1);
|
||||
append_key(bs, BSON_REAL, key, sz);
|
||||
append_key(bs, L, BSON_REAL, key, sz);
|
||||
write_double(bs, d);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
append_table(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth) {
|
||||
size_t len = lua_rawlen(L, -1);
|
||||
bool isarray = false;
|
||||
if (len > 0) {
|
||||
lua_pushinteger(L, len);
|
||||
if (lua_next(L,-2) == 0) {
|
||||
isarray = true;
|
||||
} else {
|
||||
lua_pop(L,2);
|
||||
}
|
||||
}
|
||||
if (isarray) {
|
||||
append_key(bs, BSON_ARRAY, key, sz);
|
||||
} else {
|
||||
append_key(bs, BSON_DOCUMENT, key, sz);
|
||||
}
|
||||
pack_dict(L, bs, isarray, depth);
|
||||
}
|
||||
static void append_table(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth);
|
||||
|
||||
static void
|
||||
write_binary(struct bson *b, const void * buffer, size_t sz) {
|
||||
@@ -306,7 +328,7 @@ append_one(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth)
|
||||
append_number(bs, L, key, sz);
|
||||
break;
|
||||
case LUA_TUSERDATA: {
|
||||
append_key(bs, BSON_DOCUMENT, key, sz);
|
||||
append_key(bs, L, BSON_DOCUMENT, key, sz);
|
||||
int32_t * doc = lua_touserdata(L,-1);
|
||||
int32_t sz = *doc;
|
||||
bson_reserve(bs,sz);
|
||||
@@ -319,7 +341,7 @@ append_one(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth)
|
||||
const char * str = lua_tolstring(L,-1,&len);
|
||||
if (len > 1 && str[0]==0) {
|
||||
int subt = (uint8_t)str[1];
|
||||
append_key(bs, subt, key, sz);
|
||||
append_key(bs, L, subt, key, sz);
|
||||
switch(subt) {
|
||||
case BSON_BINARY:
|
||||
write_binary(bs, str+2, len-2);
|
||||
@@ -365,8 +387,8 @@ append_one(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth)
|
||||
break;
|
||||
}
|
||||
}
|
||||
write_string(bs, str, len-i-1);
|
||||
write_string(bs, str + len-i, i);
|
||||
write_string(bs, L, str, len-i-1);
|
||||
write_string(bs, L, str + len-i, i);
|
||||
break;
|
||||
}
|
||||
case BSON_MINKEY:
|
||||
@@ -379,9 +401,9 @@ append_one(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth)
|
||||
} else {
|
||||
size_t len;
|
||||
const char * str = lua_tolstring(L,-1,&len);
|
||||
append_key(bs, BSON_STRING, key, sz);
|
||||
append_key(bs, L, BSON_STRING, key, sz);
|
||||
int off = reserve_length(bs);
|
||||
write_string(bs, str, len);
|
||||
write_string(bs, L, str, len);
|
||||
write_length(bs, len+1, off);
|
||||
}
|
||||
break;
|
||||
@@ -390,9 +412,11 @@ append_one(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth)
|
||||
append_table(bs, L, key, sz, depth+1);
|
||||
break;
|
||||
case LUA_TBOOLEAN:
|
||||
append_key(bs, BSON_BOOLEAN, key, sz);
|
||||
append_key(bs, L, BSON_BOOLEAN, key, sz);
|
||||
write_byte(bs, lua_toboolean(L,-1));
|
||||
break;
|
||||
case LUA_TNIL:
|
||||
luaL_error(L, "Bson array has a hole (nil), Use bson.null instead");
|
||||
default:
|
||||
luaL_error(L, "Invalid value type : %s", lua_typename(L,vt));
|
||||
}
|
||||
@@ -409,66 +433,132 @@ bson_numstr( char *str, unsigned int i ) {
|
||||
}
|
||||
|
||||
static void
|
||||
pack_dict(lua_State *L, struct bson *b, bool isarray, int depth) {
|
||||
if (depth > MAX_DEPTH) {
|
||||
luaL_error(L, "Too depth while encoding bson");
|
||||
}
|
||||
luaL_checkstack(L, 16, NULL); // reserve enough stack space to pack table
|
||||
pack_array(lua_State *L, struct bson *b, int depth, size_t len) {
|
||||
int length = reserve_length(b);
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L,-2) != 0) {
|
||||
int kt = lua_type(L, -2);
|
||||
size_t i;
|
||||
for (i=1;i<=len;i++) {
|
||||
char numberkey[32];
|
||||
const char * key = NULL;
|
||||
size_t sz;
|
||||
if (isarray) {
|
||||
if (kt != LUA_TNUMBER) {
|
||||
luaL_error(L, "Invalid array key type : %s", lua_typename(L, kt));
|
||||
return;
|
||||
}
|
||||
sz = bson_numstr(numberkey, (unsigned int)lua_tointeger(L,-2)-1);
|
||||
key = numberkey;
|
||||
|
||||
append_one(b, L, key, sz, depth);
|
||||
lua_pop(L,1);
|
||||
} else {
|
||||
switch(kt) {
|
||||
case LUA_TNUMBER:
|
||||
// copy key, don't change key type
|
||||
lua_pushvalue(L,-2);
|
||||
lua_insert(L,-2);
|
||||
key = lua_tolstring(L,-2,&sz);
|
||||
append_one(b, L, key, sz, depth);
|
||||
lua_pop(L,2);
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
key = lua_tolstring(L,-2,&sz);
|
||||
append_one(b, L, key, sz, depth);
|
||||
lua_pop(L,1);
|
||||
break;
|
||||
default:
|
||||
luaL_error(L, "Invalid key type : %s", lua_typename(L, kt));
|
||||
return;
|
||||
}
|
||||
}
|
||||
size_t sz = bson_numstr(numberkey, i - 1);
|
||||
const char * key = numberkey;
|
||||
lua_geti(L, -1, i);
|
||||
append_one(b, L, key, sz, depth);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
write_byte(b,0);
|
||||
write_length(b, b->size - length, length);
|
||||
}
|
||||
|
||||
static void
|
||||
pack_dict_data(lua_State *L, struct bson *b, int depth, int kt) {
|
||||
const char * key = NULL;
|
||||
size_t sz;
|
||||
switch(kt) {
|
||||
case LUA_TNUMBER:
|
||||
luaL_error(L, "Bson dictionary's key can't be number");
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
key = lua_tolstring(L,-2,&sz);
|
||||
append_one(b, L, key, sz, depth);
|
||||
lua_pop(L,1);
|
||||
break;
|
||||
default:
|
||||
luaL_error(L, "Invalid key type : %s", lua_typename(L, kt));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pack_simple_dict(lua_State *L, struct bson *b, int depth) {
|
||||
int length = reserve_length(b);
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L,-2) != 0) {
|
||||
int kt = lua_type(L, -2);
|
||||
pack_dict_data(L, b, depth, kt);
|
||||
}
|
||||
write_byte(b,0);
|
||||
write_length(b, b->size - length, length);
|
||||
}
|
||||
|
||||
static void
|
||||
pack_meta_dict(lua_State *L, struct bson *b, int depth) {
|
||||
int length = reserve_length(b);
|
||||
|
||||
lua_pushvalue(L, -2); // push meta_obj
|
||||
lua_call(L, 1, 3); // call __pairs_func => next_func, t_data, first_k
|
||||
for(;;) {
|
||||
lua_pushvalue(L, -2); // copy data
|
||||
lua_pushvalue(L, -2); // copy k
|
||||
lua_copy(L, -5, -3); // copy next_func replace old_k
|
||||
lua_call(L, 2, 2); // call next_func
|
||||
|
||||
int kt = lua_type(L, -2);
|
||||
if (kt == LUA_TNIL) {
|
||||
lua_pop(L, 4); // pop all k, v, next_func, obj
|
||||
break;
|
||||
}
|
||||
pack_dict_data(L, b, depth, kt);
|
||||
}
|
||||
write_byte(b,0);
|
||||
write_length(b, b->size - length, length);
|
||||
}
|
||||
|
||||
static bool
|
||||
is_rawarray(lua_State *L) {
|
||||
size_t len = lua_rawlen(L, -1);
|
||||
if (len > 0) {
|
||||
lua_pushinteger(L, len);
|
||||
if (lua_next(L,-2) == 0) {
|
||||
return true;
|
||||
} else {
|
||||
lua_pop(L,2);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
append_table(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth) {
|
||||
if (depth > MAX_DEPTH) {
|
||||
luaL_error(L, "Too depth while encoding bson");
|
||||
}
|
||||
luaL_checkstack(L, 16, NULL); // reserve enough stack space to pack table
|
||||
if (luaL_getmetafield(L, -1, "__len") != LUA_TNIL) {
|
||||
lua_pushvalue(L, -2);
|
||||
lua_call(L, 1, 1);
|
||||
if (!lua_isinteger(L, -1)) {
|
||||
luaL_error(L, "__len should return integer");
|
||||
}
|
||||
size_t len = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
append_key(bs, L, BSON_ARRAY, key, sz);
|
||||
pack_array(L, bs, depth, len);
|
||||
} else if (luaL_getmetafield(L, -1, "__pairs") != LUA_TNIL) {
|
||||
append_key(bs, L, BSON_DOCUMENT, key, sz);
|
||||
pack_meta_dict(L, bs, depth);
|
||||
} else if (is_rawarray(L)) {
|
||||
append_key(bs, L, BSON_ARRAY, key, sz);
|
||||
pack_array(L, bs, depth, lua_rawlen(L, -1));
|
||||
} else {
|
||||
append_key(bs, L, BSON_DOCUMENT, key, sz);
|
||||
pack_simple_dict(L, bs, depth);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pack_ordered_dict(lua_State *L, struct bson *b, int n, int depth) {
|
||||
int length = reserve_length(b);
|
||||
int i;
|
||||
size_t sz;
|
||||
// the first key is at index n
|
||||
const char * key = lua_tolstring(L, n, &sz);
|
||||
for (i=0;i<n;i+=2) {
|
||||
size_t sz;
|
||||
const char * key = lua_tolstring(L, i+1, &sz);
|
||||
if (key == NULL) {
|
||||
luaL_error(L, "Argument %d need a string", i+1);
|
||||
}
|
||||
lua_pushvalue(L, i+2);
|
||||
lua_pushvalue(L, i+1);
|
||||
append_one(b, L, key, sz, depth);
|
||||
lua_pop(L,1);
|
||||
key = lua_tolstring(L, i+2, &sz); // next key
|
||||
}
|
||||
write_byte(b,0);
|
||||
write_length(b, b->size - length, length);
|
||||
@@ -847,32 +937,66 @@ bson_meta(lua_State *L) {
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
static int
|
||||
encode_bson(lua_State *L) {
|
||||
struct bson *b = lua_touserdata(L, 2);
|
||||
lua_settop(L, 1);
|
||||
if (luaL_getmetafield(L, -1, "__pairs") != LUA_TNIL) {
|
||||
pack_meta_dict(L, b, 0);
|
||||
} else {
|
||||
pack_simple_dict(L, b, 0);
|
||||
}
|
||||
void * ud = lua_newuserdata(L, b->size);
|
||||
memcpy(ud, b->ptr, b->size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
lencode(lua_State *L) {
|
||||
struct bson b;
|
||||
bson_create(&b);
|
||||
lua_settop(L,1);
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
pack_dict(L, &b, false, 0);
|
||||
void * ud = lua_newuserdata(L, b.size);
|
||||
memcpy(ud, b.ptr, b.size);
|
||||
bson_create(&b);
|
||||
lua_pushcfunction(L, encode_bson);
|
||||
lua_pushvalue(L, 1);
|
||||
lua_pushlightuserdata(L, &b);
|
||||
if (lua_pcall(L, 2, 1, 0) != LUA_OK) {
|
||||
bson_destroy(&b);
|
||||
return lua_error(L);
|
||||
}
|
||||
bson_destroy(&b);
|
||||
bson_meta(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
encode_bson_byorder(lua_State *L) {
|
||||
int n = lua_gettop(L);
|
||||
struct bson *b = lua_touserdata(L, n);
|
||||
lua_settop(L, --n);
|
||||
pack_ordered_dict(L, b, n, 0);
|
||||
lua_settop(L,0);
|
||||
void * ud = lua_newuserdata(L, b->size);
|
||||
memcpy(ud, b->ptr, b->size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
lencode_order(lua_State *L) {
|
||||
struct bson b;
|
||||
bson_create(&b);
|
||||
int n = lua_gettop(L);
|
||||
if (n%2 != 0) {
|
||||
return luaL_error(L, "Invalid ordered dict");
|
||||
}
|
||||
pack_ordered_dict(L, &b, n, 0);
|
||||
lua_settop(L,1);
|
||||
void * ud = lua_newuserdata(L, b.size);
|
||||
memcpy(ud, b.ptr, b.size);
|
||||
bson_create(&b);
|
||||
lua_pushvalue(L, 1); // copy the first arg to n
|
||||
lua_pushcfunction(L, encode_bson_byorder);
|
||||
lua_replace(L, 1);
|
||||
lua_pushlightuserdata(L, &b);
|
||||
if (lua_pcall(L, n+1, 1, 0) != LUA_OK) {
|
||||
bson_destroy(&b);
|
||||
return lua_error(L);
|
||||
}
|
||||
bson_destroy(&b);
|
||||
bson_meta(L);
|
||||
return 1;
|
||||
@@ -1164,7 +1288,7 @@ lobjectid(lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
LUAMOD_API int
|
||||
luaopen_bson(lua_State *L) {
|
||||
luaL_checkversion(L);
|
||||
int i;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// It's only for demo, limited feature. Don't use it in your project.
|
||||
// Rewrite socket library by yourself .
|
||||
|
||||
#define LUA_LIB
|
||||
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <string.h>
|
||||
@@ -183,8 +185,8 @@ lreadstdin(lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
luaopen_clientsocket(lua_State *L) {
|
||||
LUAMOD_API int
|
||||
luaopen_client_socket(lua_State *L) {
|
||||
luaL_checkversion(L);
|
||||
luaL_Reg l[] = {
|
||||
{ "connect", lconnect },
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user