Compare commits

...

227 Commits

Author SHA1 Message Date
Cloud Wu
c28ae25c70 release 1.0.0 beta 2015-11-10 12:19:04 +08:00
Cloud Wu
9382454bcd update jemalloc to 4.0.4 2015-11-10 12:12:42 +08:00
Cloud Wu
d83fc0c00f sproto support all integer representation 2015-11-02 19:50:51 +08:00
云风
31340cf346 Merge pull request #369 from kexiao8/patch-1
repeated “struct table" of line 19
2015-11-01 19:27:16 +08:00
kexiao8
d1b26a60eb repeated “struct table" of line 19 2015-10-31 17:43:33 +08:00
Cloud Wu
ac4d51b779 bugfix issue #368 2015-10-29 11:22:26 +08:00
云风
0efab15f45 Merge pull request #366 from fztcjjl/master
add a callback for mysql auth
2015-10-28 20:49:44 +08:00
Cloud Wu
0199ba1382 sharedata support filename string 2015-10-28 17:37:06 +08:00
Cloud Wu
935863f434 report connect failed reason 2015-10-28 16:12:01 +08:00
Cloud Wu
13d920e185 body may contain ascii 0, see issue #365 2015-10-27 15:40:15 +08:00
Cloud Wu
a4af35f442 fix issue #364 2015-10-27 14:00:25 +08:00
云风
b1060478f7 Merge pull request #363 from nbwk1988/master
add hmac_md5
2015-10-27 11:39:55 +08:00
nbwk1988
1999a03ff7 优化hmac 2015-10-27 10:44:23 +08:00
nbwk1988
f5740e00b1 add hmac_md5
add hmac_md5
2015-10-26 16:12:10 +08:00
fztcjjl
1653b3213a add a callback for mysql auth 2015-10-24 06:37:25 +08:00
fztcjjl
fe3954fb04 add a callback for mysql auth 2015-10-24 01:35:16 +08:00
Cloud Wu
26cbebfcfd verify callback overflow 2015-10-21 12:58:57 +08:00
Cloud Wu
2d27df6f46 change name 2015-10-15 14:08:01 +08:00
Cloud Wu
bab91a3067 bugfix: don't use global wait_response 2015-10-15 14:01:50 +08:00
Cloud Wu
c1c032eab4 bugfix: socketchannel order mode may blocked. (used by redis driver) 2015-10-14 20:12:30 +08:00
Cloud Wu
7486e53232 avoid circular reference while encodeing bson 2015-10-14 15:44:09 +08:00
Cloud Wu
9aaa35ef14 avoid lua stack overflow 2015-10-14 15:24:51 +08:00
Cloud Wu
d2f2e299d5 call socket.abandon while auth error, see issue #355 2015-10-12 14:40:42 +08:00
Cloud Wu
d7e4e43a1b use spinlock macro 2015-10-12 13:07:09 +08:00
Cloud Wu
878110f9f7 add codecache.mode() 2015-10-12 12:29:19 +08:00
云风
60692e58dc Merge pull request #354 from xjdrew/bugfix_warning
bugfix: remove Wformat warning
2015-10-10 15:55:14 +03:00
xjdrew
515326dadc bugfix: remove Wformat warning 2015-10-10 18:39:42 +08:00
云风
4ee59edc44 Merge pull request #352 from xjdrew/gate
gate: application could control when to start receiving data
2015-10-09 05:05:33 +03:00
xjdrew
8dd9923cf6 gate: application could control when to start receiving data 2015-10-08 16:55:29 +08:00
Cloud Wu
8c1011c503 Add sproto:exist_type and sproto:exist_proto 2015-10-08 15:30:15 +08:00
Cloud Wu
8924b86ad7 check empty group, See pr #351 2015-10-08 15:15:35 +08:00
云风
14bc029864 Merge pull request #348 from xjdrew/unused_code
removte unused code
2015-10-05 05:17:29 +03:00
Cloud Wu
79e73d907e add target update3rd 2015-10-05 10:09:22 +08:00
Cloud Wu
3a06dcf534 update jemalloc to 4.0.3 2015-10-05 10:05:36 +08:00
Cloud Wu
97fd5053c9 update lpeg to 1.0.0 2015-10-05 09:56:12 +08:00
云风
3a3159d429 Merge pull request #347 from zhengfangxin/master
delete two clear_closed_event call
2015-10-05 04:51:22 +03:00
xjdrew
97ff6afc84 removte unused code 2015-09-29 17:29:33 +08:00
zhengfangxin
cb9feb34bd delete two no need call clear_closed_event 2015-09-26 21:03:38 +08:00
云风
48f79fe6d4 Merge pull request #345 from great90/master
从check_wsz发送的SKYNET_SOCKET_TYPE_WARNING消息会assert失败,导致coredump
2015-09-22 09:37:54 +08:00
great90
63942496fd 从check_wsz发送的SKYNET_SOCKET_TYPE_WARNING消息会assert失败,导致coredump 2015-09-21 23:50:18 +08:00
云风
bf9fc0c7e9 Merge pull request #343 from bingo235/master
gateserver close
2015-09-21 12:59:30 +08:00
bingo
325452a242 Signed-off-by: bingo <heidan725@qq.com> 2015-09-21 11:21:36 +08:00
Cloud Wu
752a501f68 bugfix: remove DONTCOPY tag from type 2015-09-21 10:40:09 +08:00
Cloud Wu
008351573a raise error when DH param is 0 2015-09-18 14:13:16 +08:00
Cloud Wu
00dbf6e996 DH key exchange can't be 0 , avoid attack 2015-09-18 14:10:12 +08:00
Cloud Wu
8cc5638f14 Merge branch 'master' of github.com:cloudwu/skynet 2015-09-15 14:52:44 +08:00
Cloud Wu
b8f419eb69 more error message for socket, and close listen socket when reach limit of open files. See Issue #339 2015-09-15 14:52:30 +08:00
云风
8f284e2d7f Merge pull request #340 from sanikoyes/Pr-missing-exitshr
add missing luaS_exitshr call
2015-09-14 18:05:56 +08:00
sanikoyes
846d55eaef add missing luaS_exitshr call 2015-09-14 18:03:04 +08:00
Cloud Wu
6c33f7bc44 see pr #332 2015-09-04 12:14:09 +08:00
Cloud Wu
7797de85b4 bugfix: See PR #332 2015-08-31 16:36:57 +08:00
云风
7ec452c782 Merge pull request #332 from niuys/patch-4
'response' not released
2015-08-30 22:08:37 +08:00
snail
7f9c3c8c9a local function is better
local function is the same as " local a; a = function"
2015-08-30 18:17:41 +08:00
snail
bad3472124 'response' not released
'response' not released after src service died, and defined error.
2015-08-30 16:47:34 +08:00
Cloud Wu
4f665d2469 init global string table, See issue #331 2015-08-30 12:13:23 +08:00
Cloud Wu
633e5fbe32 fix issue #331 2015-08-29 15:24:24 +08:00
云风
c1c5cd39e5 Merge pull request #328 from cloudwu/shrtbl
global shared string table
2015-08-27 21:16:47 +08:00
云风
03f5da6bb5 Merge pull request #329 from niuys/patch-3
uncomplete buffer not free
2015-08-27 18:15:12 +08:00
snail
1bfddda435 uncomplete buffer not free
'uncomplete' buffer not freed in clear
2015-08-27 18:04:56 +08:00
Cloud Wu
9b0e496afe minor amend 2015-08-27 13:49:31 +08:00
Cloud Wu
010d1c1d4f avoid dead loop 2015-08-24 11:50:40 +08:00
Cloud Wu
eb587c63d3 fix issue #327 2015-08-21 19:42:09 +08:00
Cloud Wu
bb6d5d826e add TString struct size 2015-08-21 15:59:51 +08:00
Cloud Wu
9acce94464 disable lua apicheck 2015-08-21 13:55:43 +08:00
Cloud Wu
c0862d8445 add global share string table 2015-08-21 13:52:04 +08:00
Cloud Wu
1b53e6e28d Release alpha 10 2015-08-17 11:21:20 +08:00
云风
77bdfb2ceb Merge pull request #325 from cloudwu/pthreadlock
add pthread lock
2015-08-17 10:25:36 +08:00
Cloud Wu
2583af26d7 add cluster.register and cluster.query 2015-08-14 23:22:00 +08:00
Cloud Wu
a38a3140dd error when send to address 0 2015-08-14 17:32:59 +08:00
Cloud Wu
bf8f9b8654 add pthread lock 2015-08-13 21:00:20 +08:00
Cloud Wu
0ce9921c25 remove unused sz 2015-08-12 21:16:02 +08:00
Cloud Wu
adc39705f3 remove unused netpack c api 2015-08-12 20:56:29 +08:00
Cloud Wu
a4f827a48d use string for msgserver request 2015-08-12 14:53:36 +08:00
Cloud Wu
7547126570 bugfix: memory leak , See Issue #323 2015-08-12 12:03:52 +08:00
Cloud Wu
926b44ddf6 remove unused parm 2015-08-11 14:09:16 +08:00
Cloud Wu
d3771edc9d The cluster message never great than 64K now 2015-08-11 14:04:15 +08:00
Cloud Wu
947727e33a add new socket message WARNING 2015-08-11 13:21:24 +08:00
云风
27148981d5 Merge pull request #320 from cloudwu/multipart
Multipart
2015-08-11 11:17:22 +08:00
Cloud Wu
6fa436e8ff add core.intcommand , See Issue #321 2015-08-10 22:06:36 +08:00
Cloud Wu
2935ba3521 Release alpha9 2015-08-10 16:17:55 +08:00
云风
5c8ea6f09f Merge pull request #318 from felixdae/cloud
not work with telnet due to \r\n
2015-08-08 16:45:21 +08:00
felixdae
c16ae57639 not work with telnet due to \r\n 2015-08-07 18:52:50 +08:00
云风
1c7d44fd4d Merge pull request #316 from niuys/patch-2
'hotfix' code cannot use '_ENV'
2015-08-07 16:14:13 +08:00
云风
ca7e38137d Merge pull request #317 from chuenlungwang/multipart
Packing multipart req number first byte is 1
2015-08-07 16:07:25 +08:00
BITMAN
5936d3616c Packing multipart req number first byte is 1 2015-08-07 13:51:10 +08:00
snail
e9cfdba22a 'hotfix' code cannot use '_ENV'
If there's no global variable or function used in any interface of a snax service,the upvalue "_ENV" for 'hotfix' is not set. This modify is not  complete, it depend's on the 'collect_uv' method having upvalue '_ENV',maybe other good method to get upvalue index of '_ENV'.
2015-08-07 10:38:57 +08:00
Cloud Wu
3156661e0b bugfix: response function for socket channel 2015-08-06 20:00:48 +08:00
Cloud Wu
b4048a8eab bugfix: typo 2015-08-05 16:42:05 +08:00
Cloud Wu
aff73cbed7 Increase message size 16M(24bit) limit to 56bit on 64bit arch 2015-08-05 12:23:35 +08:00
Cloud Wu
b5244b96aa cluster rpc support large package 2015-08-04 17:56:17 +08:00
Cloud Wu
704b016f2c bugfix: inc session before get channel 2015-08-04 17:51:35 +08:00
Cloud Wu
3b48beb428 bson bugfix 2015-07-30 15:41:17 +08:00
Cloud Wu
4cbead28d5 skynet.dispatch can replace old func 2015-07-29 16:12:49 +08:00
Cloud Wu
b3f966bcaa bugfix: multicast chan gc 2015-07-29 16:10:38 +08:00
Cloud Wu
7b54e37d12 Merge branch 'master' of github.com:cloudwu/skynet 2015-07-24 17:58:06 +08:00
Cloud Wu
e87ac18b84 expand lua stack first 2015-07-24 17:50:42 +08:00
云风
05af87ce8e Merge pull request #311 from jintiao/patch-1
fix "make cleanall" on macosx
2015-07-24 17:45:41 +08:00
jintiao
0ee61de22c skip jemalloc clean if jemalloc's makefile was missing 2015-07-24 00:48:24 +08:00
Cloud Wu
1da8a6b38d lazy init debug command 2015-07-23 18:35:29 +08:00
Cloud Wu
b2d8237363 improve unregister protocol error report 2015-07-23 18:23:47 +08:00
Cloud Wu
39f9a96b6c add cmemory.info() returns a table of c memory info 2015-07-23 16:47:35 +08:00
Cloud Wu
588c4a3508 bugfix 2015-07-22 16:49:25 +08:00
Cloud Wu
d6734890e0 Merge branch 'master' of github.com:cloudwu/skynet 2015-07-22 15:53:19 +08:00
Cloud Wu
4ebb139c2b bugfix: free message when cluster not connected 2015-07-22 15:52:26 +08:00
云风
20476d2280 Merge pull request #308 from jsenter/patch-1
Update cdummy.lua
2015-07-21 15:20:56 +08:00
Cloud Wu
3131bca6ef Merge branch 'master' of github.com:cloudwu/skynet 2015-07-21 11:31:41 +08:00
Cloud Wu
3f91484791 user log service 2015-07-21 11:31:27 +08:00
LiBei
a0ecd51230 Update cdummy.lua
误定义全局变量
2015-07-21 11:12:55 +08:00
云风
dba1db9cc4 Merge pull request #304 from JiessieDawn/master
sharedata serialization bugfix
2015-07-13 14:13:48 +08:00
cxj
538414408d sharedata serialization bugfix 2015-07-13 13:04:09 +08:00
云风
4cf05fb2e7 Merge pull request #303 from JiessieDawn/master
sproto optimize
2015-07-11 20:36:39 +08:00
cxj
d9ad981c8c sproto optimize, malloc newchunk and return directly if sz >= CHUNK_SIZE in pool_alloc, do not replace current chunk if sz >= p->current_used in pool_alloc, more safety checking 2015-07-10 20:21:07 +08:00
云风
21c941fe63 Merge pull request #302 from sanikoyes/Pr-optimize-sproto-lunpack
Pr-optimize-sproto-unpack
2015-07-09 18:24:06 +08:00
sanikoyes
ea2437e138 lunpack optimize, do not unpack twice if r <= osz 2015-07-09 18:07:32 +08:00
Cloud Wu
86bbc9c701 off by 1 error 2015-07-07 12:11:16 +08:00
Cloud Wu
95e1d9f45f Merge branch 'master' of github.com:cloudwu/skynet 2015-07-03 10:58:53 +08:00
Cloud Wu
55cf9375fc asterisk(*) should be once or not at all 2015-07-03 10:58:40 +08:00
云风
654f732cd5 Merge pull request #300 from sanikoyes/Pr-fix-login-client
Pr-fix-login-client
2015-07-03 10:28:24 +08:00
sanikoyes
d4023c8b63 fix invalid fd after reconnected, used in unpack_f 2015-07-02 16:25:10 +08:00
云风
375f8606b4 Merge pull request #298 from JiessieDawn/master
support sharedata serialization
2015-07-02 15:04:49 +08:00
cxj
d17e6f59fe add sharedata lua serialization test 2015-07-02 15:02:11 +08:00
cxj
a77d36911d change wb_table to call wb_table_metapairs for keeping consistent style 2015-07-02 14:47:50 +08:00
cxj
4352dc4047 Merge branch 'master' of https://github.com/cloudwu/skynet 2015-07-02 13:56:55 +08:00
cxj
172356be19 fix lua-seric.c wb_table 2015-07-02 13:51:03 +08:00
Cloud Wu
08dabd51c8 fix issue #299 2015-07-02 12:17:18 +08:00
cxj
bd55a58515 support sharedata serialization 2015-07-01 16:54:20 +08:00
Cloud Wu
b646a1b8a3 fix login example 2015-07-01 12:51:20 +08:00
Cloud Wu
6b312fa09a update readme 2015-07-01 11:35:05 +08:00
Cloud Wu
dad66010cd sproto bugfix, see sproto issue 34 for detail 2015-06-30 15:05:49 +08:00
Cloud Wu
27ae0a7500 release alpha 8 2015-06-29 11:11:32 +08:00
Cloud Wu
6001d9c2eb raise error message from response function, See issue #295 2015-06-26 14:33:33 +08:00
Cloud Wu
728abeaeb8 can't write to listen fd, See issue #294 2015-06-25 19:28:42 +08:00
Cloud Wu
2fa130997f fix atom inc 2015-06-24 19:50:45 +08:00
Cloud Wu
8c57ec192a Merge branch 'master' of github.com:cloudwu/skynet 2015-06-24 18:58:24 +08:00
Cloud Wu
0fb2b21ed5 use atom inc for object id counter 2015-06-24 18:57:47 +08:00
云风
1fd2c3de81 Merge pull request #292 from leeonix/master
修改Makefile,添加lua的清理
2015-06-24 11:12:05 +08:00
Cloud Wu
f3536bfc53 not use raw api, fix Issue #293 2015-06-24 10:27:37 +08:00
leeonix
57999456ef modify Makefile and add lua clean
modify service-src/service_gate.c space to tab
2015-06-20 11:29:56 +08:00
Cloud Wu
35b35f686c bugfix: Issue #291 2015-06-19 13:22:40 +08:00
Cloud Wu
5d9142110e patch lua_clonefunction 2015-06-18 17:39:37 +08:00
Cloud Wu
2086e13a46 hack lua to support signal 2015-06-17 22:12:48 +08:00
Cloud Wu
f36b173155 update to lua 5.3.1 2015-06-17 22:06:11 +08:00
Cloud Wu
7fa1d548ed bugfix: don't call skynet_free directly when send failed 2015-06-16 10:56:28 +08:00
Cloud Wu
039235b3a3 lock before set quit flag 2015-06-09 21:46:37 +08:00
Cloud Wu
57d43a588e Check quit flag before pthread_cond_wait 2015-06-09 20:00:20 +08:00
Cloud Wu
8214c53891 release alpha7 2015-06-08 10:31:00 +08:00
Cloud Wu
5e642b15a4 Merge branch 'master' of github.com:cloudwu/skynet 2015-06-07 12:39:33 +08:00
Cloud Wu
ac093c7142 fix memory leak, see Issue #290 2015-06-07 12:38:55 +08:00
云风
01dcc45827 Merge pull request #289 from harrywong/typo-patch
typo in type of variable
2015-06-05 23:02:16 +08:00
Harry
d3ac522dc6 typo in type of variable 2015-06-05 19:04:43 +08:00
Cloud Wu
55d0d57d5c skynet.fork returns the coroutine, see Issue #287 2015-06-04 16:06:21 +08:00
Cloud Wu
1fec2e6063 sep size may greater than buffer node, See Issue #286 2015-06-03 09:42:49 +08:00
Cloud Wu
cc4756de35 fix Issue #285 2015-06-02 11:52:55 +08:00
Cloud Wu
7fb109dbb0 See Issue #284 2015-06-01 10:57:30 +08:00
Cloud Wu
7f578be649 bugfix: Issue #283 2015-06-01 10:42:29 +08:00
Cloud Wu
69946d75c5 add config.logservice for user defined log service 2015-05-30 22:17:53 +08:00
Cloud Wu
24f6994b50 close uncomplete when socket disconnect, see Issue #280 2015-05-29 21:11:02 +08:00
Cloud Wu
07dbfd8651 add underscore 2015-05-28 16:18:56 +08:00
Cloud Wu
ca50a5f518 dns support underscore 2015-05-28 16:10:19 +08:00
Cloud Wu
b8c54cbac2 skynet.kill move into skynet.manager 2015-05-27 21:17:43 +08:00
Cloud Wu
3a2c43e9e0 set nodelay in clusterd, Issue #278 2015-05-27 14:54:26 +08:00
Cloud Wu
205824ab12 use LUA_API instead of extern 2015-05-26 16:05:31 +08:00
云风
4ac047b274 Merge pull request #277 from xiyanxiyan10/master
调整格式
2015-05-23 17:02:37 +08:00
xiyanxiyan10
987a90af8b 调整格式 2015-05-23 16:35:15 +08:00
Cloud Wu
250531c9a7 bugfix: sproto.default 2015-05-22 20:51:00 +08:00
Cloud Wu
7b471ae27d snax service support cluster 2015-05-20 16:13:11 +08:00
云风
4f93054f3a Merge pull request #275 from ximenpo/master
console服务增加启动snax服务功能
2015-05-20 15:43:55 +08:00
ximenpo
65fad89794 console服务增加启动snax服务功能
输入:
svc  -> 用snlua启动svc服务
snax svc -> 用snax启动svc服务
2015-05-20 15:14:28 +08:00
云风
286c0f2c23 Merge pull request #273 from flashjay/patch-4
Update lua-crypt.c
2015-05-19 11:41:14 +08:00
HuaYang Huang
de57064b96 Update lua-crypt.c
添加 static 避免可能导致的链接冲突
2015-05-18 23:05:24 +08:00
Cloud Wu
6c43e90708 release alpha6 2015-05-18 12:02:08 +08:00
云风
1f25b79722 Merge pull request #272 from antsmallant/patch-1
Update inject.lua
2015-05-15 17:04:27 +08:00
Cloud Wu
6a9080157f need require skynet.manager 2015-05-15 16:24:01 +08:00
antsmallant
5cc2ef3ac8 Update inject.lua
免得变量i污染全局空间
2015-05-15 15:59:47 +08:00
Cloud Wu
3baeb62b0b move some api from skynet.lua to skynet/manager.lua 2015-05-13 11:04:25 +08:00
Cloud Wu
9e27f59033 remove task overload warning 2015-05-13 09:50:53 +08:00
Cloud Wu
82fa2f979c skynet.exit will call every unresponse handle 2015-05-12 23:15:03 +08:00
Cloud Wu
07d7324332 Merge branch 'master' of github.com:cloudwu/skynet 2015-05-12 22:53:16 +08:00
Cloud Wu
d92adda2c9 If skynet.wakeup a skynet.call, raise an error 2015-05-12 22:53:03 +08:00
Cloud Wu
0587400e2d update sproto: handle empty protocol 2015-05-12 10:20:16 +08:00
Cloud Wu
35c8c63793 update sproto, bugfix sproto_dump 2015-05-11 21:39:56 +08:00
Cloud Wu
c7f5145e9e update sproto , add new api sproto:default 2015-05-11 18:20:17 +08:00
Cloud Wu
9452169f0a remove unused comment 2015-05-07 18:17:46 +08:00
云风
a15f43e0f8 Merge pull request #267 from gaopan461/master
fix:udp and udp_send
2015-05-07 18:18:36 +08:00
gaopan
0eb4754b31 @fix udp_address, in big-endian machine maybe error 2015-05-07 16:52:48 +08:00
gaopan
f987ff8199 fix:udp and udp_send 2015-05-07 15:25:47 +08:00
云风
64a5d1ca24 Merge pull request #266 from xiyanxiyan10/master
错误注释更正
2015-05-06 23:27:13 +08:00
xiyanxiyan10
fa17081012 错误注释更正 2015-05-06 23:13:06 +08:00
Cloud Wu
856cb0737d Merge branch 'master' of github.com:cloudwu/skynet 2015-05-02 20:47:29 +08:00
Cloud Wu
f61e3f46e8 fix issue #265 2015-05-02 20:47:15 +08:00
云风
6b6b943b73 Merge pull request #262 from flashjay/patch-3
fix: httpc.get
2015-04-29 22:19:31 +08:00
HuaYang Huang
75d9b07158 fix: httpc.get
:-(
此错误会导致httpc.get无法找到正确的虚拟主机
2015-04-29 20:18:13 +08:00
Cloud Wu
8682f7f82f response error when return/response package is too large 2015-04-27 16:23:12 +08:00
Cloud Wu
35a5b99bed release alpha5 2015-04-27 10:45:31 +08:00
Cloud Wu
98af25d109 better error log, see pr #260 2015-04-24 14:31:18 +08:00
Cloud Wu
cd3391461c add skynet.pcall for hotfix use (call a function with require) 2015-04-22 17:01:03 +08:00
Cloud Wu
e3b7f86075 cluster reload should reset old connection to update address:port 2015-04-21 15:35:29 +08:00
Cloud Wu
86d5865457 bugfix: wunlock first, and then release context. (may dead lock) 2015-04-18 21:11:57 +08:00
Cloud Wu
7b783076e5 use hmac_hash 2015-04-16 10:41:23 +08:00
Cloud Wu
57c0ad694c add hmac_hash to simplify hmac64(hashkey(d), key) 2015-04-16 10:35:47 +08:00
Cloud Wu
f55a31c24f sproto.request_decode returns name 2015-04-15 22:01:01 +08:00
Cloud Wu
843095afc6 add snax.printf 2015-04-15 16:52:55 +08:00
Cloud Wu
a6bad52181 add sproto new api 2015-04-14 23:38:49 +08:00
Cloud Wu
012d98380d merge lua bugfix from lua offical bugs page 2015-04-13 17:14:08 +08:00
Cloud Wu
0298997d23 release alpha 4 2015-04-13 13:04:39 +08:00
Cloud Wu
678a94bf71 update license 2015-04-10 11:35:47 +08:00
Cloud Wu
03399e86a9 udp api changed, callback recv the string 2015-04-09 12:49:40 +08:00
Cloud Wu
22364bac89 bugfix: memory leak 2015-04-09 12:14:28 +08:00
Cloud Wu
9188b5451c bugfix 1 , from http://www.lua.org/bugs.html#5.3.0-1 2015-04-09 11:55:07 +08:00
Cloud Wu
c7ed527911 add const to sproto C api 2015-04-08 11:42:06 +08:00
Cloud Wu
5a1132101b share sproto C struct 2015-04-08 11:23:52 +08:00
Cloud Wu
ca33bf8b3e bugfix sproto : support empty string 2015-04-05 20:19:30 +08:00
Cloud Wu
7d8c80c9a0 fix Issue #256 2015-04-03 11:07:11 +08:00
Cloud Wu
c6f993428e bugfix #257 2015-04-03 11:03:37 +08:00
云风
f6118b858d Merge pull request #255 from flashjay/patch-1
fix: httpc.post
2015-04-03 09:35:41 +08:00
HuaYang Huang
ec1bca238e fix: httpc.post
调用httpc.post时,如果没有在header里面设置host时有问题
2015-04-01 17:54:22 +08:00
Cloud Wu
6b87f159b4 more type check 2015-04-01 13:22:09 +08:00
Cloud Wu
41b447d41a update sproto: check table 2015-04-01 12:18:49 +08:00
Cloud Wu
c512b5f59a release alpha 3 2015-03-30 11:00:51 +08:00
云风
fc9b32b4bd Merge pull request #254 from cloudwu/dev
release alpha 3
2015-03-30 11:00:18 +08:00
Cloud Wu
36ed8679b8 you can set host in httpc header 2015-03-30 09:29:22 +08:00
Cloud Wu
a9b1993686 Add async dns query 2015-03-29 14:41:28 +08:00
Cloud Wu
05b458ddb2 update sproto 2015-03-20 09:51:00 +08:00
Cloud Wu
8d8add3710 update sproto 2015-03-18 12:17:01 +08:00
Cloud Wu
65e7da9793 more sproto error message 2015-03-18 11:50:47 +08:00
Cloud Wu
7e5d9b7399 bugfix Issue #249 2015-03-18 11:07:34 +08:00
Cloud Wu
92b7b7beff use table for multi header key 2015-03-16 20:15:57 +08:00
162 changed files with 4174 additions and 1645 deletions

View File

@@ -1,4 +1,10 @@
HISTORY for LPeg 0.12
HISTORY for LPeg 1.0
* Changes from version 0.12 to 1.0
---------------------------------
+ group "names" can be any Lua value
+ some bugs fixed
+ other small improvements
* Changes from version 0.11 to 0.12
---------------------------------

View File

@@ -1,5 +1,5 @@
/*
** $Id: lpcap.c,v 1.5 2014/12/12 16:58:47 roberto Exp $
** $Id: lpcap.c,v 1.6 2015/06/15 16:09:57 roberto Exp $
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
*/
@@ -126,7 +126,7 @@ static Capture *findback (CapState *cs, Capture *cap) {
continue; /* opening an enclosing capture: skip and get previous */
if (captype(cap) == Cgroup) {
getfromktable(cs, cap->idx); /* get group name */
if (lua_equal(L, -2, -1)) { /* right group? */
if (lp_equal(L, -2, -1)) { /* right group? */
lua_pop(L, 2); /* remove reference name and group name */
return cap;
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lpcap.h,v 1.1 2013/03/21 20:25:12 roberto Exp $
** $Id: lpcap.h,v 1.2 2015/02/27 17:13:17 roberto Exp $
*/
#if !defined(lpcap_h)
@@ -18,7 +18,7 @@ typedef enum CapKind {
typedef struct Capture {
const char *s; /* subject position */
short idx; /* extra info about capture (group name, arg index, etc.) */
unsigned short idx; /* extra info (group name, arg index, etc.) */
byte kind; /* kind of capture */
byte siz; /* size of full capture + 1 (0 = not a full capture) */
} Capture;

View File

@@ -1,5 +1,5 @@
/*
** $Id: lpcode.c,v 1.21 2014/12/12 17:01:29 roberto Exp $
** $Id: lpcode.c,v 1.23 2015/06/12 18:36:47 roberto Exp $
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
*/
@@ -431,11 +431,11 @@ typedef struct CompileState {
/*
** code generation is recursive; 'opt' indicates that the code is
** being generated under a 'IChoice' operator jumping to its end
** (that is, the match is "optional").
** 'tt' points to a previous test protecting this code. 'fl' is
** the follow set of the pattern.
** code generation is recursive; 'opt' indicates that the code is being
** generated as the last thing inside an optional pattern (so, if that
** code is optional too, it can reuse the 'IChoice' already in place for
** the outer pattern). 'tt' points to a previous test protecting this
** code (or NOINST). 'fl' is the follow set of the pattern.
*/
static void codegen (CompileState *compst, TTree *tree, int opt, int tt,
const Charset *fl);
@@ -638,13 +638,13 @@ static void codebehind (CompileState *compst, TTree *tree) {
/*
** Choice; optimizations:
** - when p1 is headfail
** - when first(p1) and first(p2) are disjoint; than
** - when p1 is headfail or
** when first(p1) and first(p2) are disjoint, than
** a character not in first(p1) cannot go to p1, and a character
** in first(p1) cannot go to p2 (at it is not in first(p2)).
** (The optimization is not valid if p1 accepts the empty string,
** as then there is no character at all...)
** - when p2 is empty and opt is true; a IPartialCommit can resuse
** - when p2 is empty and opt is true; a IPartialCommit can reuse
** the Choice already active in the stack.
*/
static void codechoice (CompileState *compst, TTree *p1, TTree *p2, int opt,
@@ -671,7 +671,7 @@ static void codechoice (CompileState *compst, TTree *p1, TTree *p2, int opt,
}
else {
/* <p1 / p2> ==
test(fail(p1)) -> L1; choice L1; <p1>; commit L2; L1: <p2>; L2: */
test(first(p1)) -> L1; choice L1; <p1>; commit L2; L1: <p2>; L2: */
int pcommit;
int test = codetestset(compst, &cs1, e1);
int pchoice = addoffsetinst(compst, IChoice);
@@ -759,7 +759,7 @@ static void coderep (CompileState *compst, TTree *tree, int opt,
/* L1: test (fail(p1)) -> L2; <p>; jmp L1; L2: */
int jmp;
int test = codetestset(compst, &st, 0);
codegen(compst, tree, opt, test, fullset);
codegen(compst, tree, 0, test, fullset);
jmp = addoffsetinst(compst, IJmp);
jumptohere(compst, test);
jumptothere(compst, jmp, test);

View File

@@ -1,5 +1,5 @@
/*
** $Id: lpcode.h,v 1.6 2013/11/28 14:56:02 roberto Exp $
** $Id: lpcode.h,v 1.7 2015/06/12 18:24:45 roberto Exp $
*/
#if !defined(lpcode_h)
@@ -24,7 +24,15 @@ int sizei (const Instruction *i);
#define PEnullable 0
#define PEnofail 1
/*
** nofail(t) implies that 't' cannot fail with any input
*/
#define nofail(t) checkaux(t, PEnofail)
/*
** (not nullable(t)) implies 't' cannot match without consuming
** something
*/
#define nullable(t) checkaux(t, PEnullable)
#define fixedlen(t) fixedlenx(t, 0, 0)

View File

@@ -10,7 +10,7 @@
</head>
<body>
<!-- $Id: lpeg.html,v 1.72 2014/12/12 17:11:35 roberto Exp $ -->
<!-- $Id: lpeg.html,v 1.75 2015/09/28 17:17:41 roberto Exp $ -->
<div id="container">
@@ -22,7 +22,7 @@
</div>
<div id="product_name"><big><strong>LPeg</strong></big></div>
<div id="product_description">
Parsing Expression Grammars For Lua, version 0.12
Parsing Expression Grammars For Lua, version 1.0
</div>
</div> <!-- id="product" -->
@@ -195,13 +195,16 @@ Returns a string with the running version of LPeg.
<h3><a name="f-setstack"></a><code>lpeg.setmaxstack (max)</code></h3>
<p>
Sets the maximum size for the backtrack stack used by LPeg to
Sets a limit for the size of the backtrack stack used by LPeg to
track calls and choices.
(The default limit is 400.)
Most well-written patterns need little backtrack levels and
therefore you seldom need to change this maximum;
but a few useful patterns may need more space.
Before changing this maximum you should try to rewrite your
therefore you seldom need to change this limit;
before changing it you should try to rewrite your
pattern to avoid the need for extra space.
Nevertheless, a few useful patterns may overflow.
Also, with recursive grammars,
subjects with deep recursion may also need larger limits.
</p>
@@ -682,7 +685,8 @@ argument given in the call to <code>lpeg.match</code>.
Creates a <em>back capture</em>.
This pattern matches the empty string and
produces the values produced by the <em>most recent</em>
<a href="#cap-g">group capture</a> named <code>name</code>.
<a href="#cap-g">group capture</a> named <code>name</code>
(where <code>name</code> can be any Lua value).
</p>
<p>
@@ -762,7 +766,8 @@ Creates a <em>group capture</em>.
It groups all values returned by <code>patt</code>
into a single capture.
The group may be anonymous (if no name is given)
or named with the given name.
or named with the given name
(which can be any non-nil Lua value).
</p>
<p>
@@ -1375,13 +1380,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-0.12.1.tar.gz">source code</a>.</p>
<a href="http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.0.tar.gz">source code</a>.</p>
<h2><a name="license">License</a></h2>
<p>
Copyright &copy; 2014 Lua.org, PUC-Rio.
Copyright &copy; 2007-2015 Lua.org, PUC-Rio.
</p>
<p>
Permission is hereby granted, free of charge,
@@ -1419,7 +1424,7 @@ THE SOFTWARE.
<div id="about">
<p><small>
$Id: lpeg.html,v 1.72 2014/12/12 17:11:35 roberto Exp $
$Id: lpeg.html,v 1.75 2015/09/28 17:17:41 roberto Exp $
</small></p>
</div> <!-- id="about" -->

View File

@@ -1,5 +1,5 @@
/*
** $Id: lpprint.c,v 1.7 2013/04/12 16:29:49 roberto Exp $
** $Id: lpprint.c,v 1.9 2015/06/15 16:09:57 roberto Exp $
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
*/
@@ -52,7 +52,7 @@ static void printjmp (const Instruction *op, const Instruction *p) {
}
static void printinst (const Instruction *op, const Instruction *p) {
void printinst (const Instruction *op, const Instruction *p) {
const char *const names[] = {
"any", "char", "set",
"testany", "testchar", "testset",
@@ -221,10 +221,10 @@ void printtree (TTree *tree, int ident) {
void printktable (lua_State *L, int idx) {
int n, i;
lua_getfenv(L, idx);
lua_getuservalue(L, idx);
if (lua_isnil(L, -1)) /* no ktable? */
return;
n = lua_objlen(L, -1);
n = lua_rawlen(L, -1);
printf("[");
for (i = 1; i <= n; i++) {
printf("%d = ", i);

View File

@@ -1,5 +1,5 @@
/*
** $Id: lpprint.h,v 1.1 2013/03/21 20:25:12 roberto Exp $
** $Id: lpprint.h,v 1.2 2015/06/12 18:18:08 roberto Exp $
*/
@@ -18,6 +18,7 @@ void printtree (TTree *tree, int ident);
void printktable (lua_State *L, int idx);
void printcharset (const byte *st);
void printcaplist (Capture *cap, Capture *limit);
void printinst (const Instruction *op, const Instruction *p);
#else

View File

@@ -1,5 +1,5 @@
/*
** $Id: lptree.c,v 1.13 2014/12/12 16:59:10 roberto Exp $
** $Id: lptree.c,v 1.21 2015/09/28 17:01:25 roberto Exp $
** Copyright 2013, Lua.org & PUC-Rio (see 'lpeg.html' for license)
*/
@@ -126,6 +126,189 @@ static void finalfix (lua_State *L, int postable, TTree *g, TTree *t) {
}
/*
** {===================================================================
** KTable manipulation
**
** - The ktable of a pattern 'p' can be shared by other patterns that
** contain 'p' and no other constants. Because of this sharing, we
** should not add elements to a 'ktable' unless it was freshly created
** for the new pattern.
**
** - The maximum index in a ktable is USHRT_MAX, because trees and
** patterns use unsigned shorts to store those indices.
** ====================================================================
*/
/*
** Create a new 'ktable' to the pattern at the top of the stack.
*/
static void newktable (lua_State *L, int n) {
lua_createtable(L, n, 0); /* create a fresh table */
lua_setuservalue(L, -2); /* set it as 'ktable' for pattern */
}
/*
** Add element 'idx' to 'ktable' of pattern at the top of the stack;
** Return index of new element.
** If new element is nil, does not add it to table (as it would be
** useless) and returns 0, as ktable[0] is always nil.
*/
static int addtoktable (lua_State *L, int idx) {
if (lua_isnil(L, idx)) /* nil value? */
return 0;
else {
int n;
lua_getuservalue(L, -1); /* get ktable from pattern */
n = lua_rawlen(L, -1);
if (n >= USHRT_MAX)
luaL_error(L, "too many Lua values in pattern");
lua_pushvalue(L, idx); /* element to be added */
lua_rawseti(L, -2, ++n);
lua_pop(L, 1); /* remove 'ktable' */
return n;
}
}
/*
** Return the number of elements in the ktable at 'idx'.
** In Lua 5.2/5.3, default "environment" for patterns is nil, not
** a table. Treat it as an empty table. In Lua 5.1, assumes that
** the environment has no numeric indices (len == 0)
*/
static int ktablelen (lua_State *L, int idx) {
if (!lua_istable(L, idx)) return 0;
else return lua_rawlen(L, idx);
}
/*
** Concatentate the contents of table 'idx1' into table 'idx2'.
** (Assume that both indices are negative.)
** Return the original length of table 'idx2' (or 0, if no
** element was added, as there is no need to correct any index).
*/
static int concattable (lua_State *L, int idx1, int idx2) {
int i;
int n1 = ktablelen(L, idx1);
int n2 = ktablelen(L, idx2);
if (n1 + n2 > USHRT_MAX)
luaL_error(L, "too many Lua values in pattern");
if (n1 == 0) return 0; /* nothing to correct */
for (i = 1; i <= n1; i++) {
lua_rawgeti(L, idx1, i);
lua_rawseti(L, idx2 - 1, n2 + i); /* correct 'idx2' */
}
return n2;
}
/*
** When joining 'ktables', constants from one of the subpatterns must
** be renumbered; 'correctkeys' corrects their indices (adding 'n'
** to each of them)
*/
static void correctkeys (TTree *tree, int n) {
if (n == 0) return; /* no correction? */
tailcall:
switch (tree->tag) {
case TOpenCall: case TCall: case TRunTime: case TRule: {
if (tree->key > 0)
tree->key += n;
break;
}
case TCapture: {
if (tree->key > 0 && tree->cap != Carg && tree->cap != Cnum)
tree->key += n;
break;
}
default: break;
}
switch (numsiblings[tree->tag]) {
case 1: /* correctkeys(sib1(tree), n); */
tree = sib1(tree); goto tailcall;
case 2:
correctkeys(sib1(tree), n);
tree = sib2(tree); goto tailcall; /* correctkeys(sib2(tree), n); */
default: assert(numsiblings[tree->tag] == 0); break;
}
}
/*
** Join the ktables from p1 and p2 the ktable for the new pattern at the
** top of the stack, reusing them when possible.
*/
static void joinktables (lua_State *L, int p1, TTree *t2, int p2) {
int n1, n2;
lua_getuservalue(L, p1); /* get ktables */
lua_getuservalue(L, p2);
n1 = ktablelen(L, -2);
n2 = ktablelen(L, -1);
if (n1 == 0 && n2 == 0) /* are both tables empty? */
lua_pop(L, 2); /* nothing to be done; pop tables */
else if (n2 == 0 || lp_equal(L, -2, -1)) { /* 2nd table empty or equal? */
lua_pop(L, 1); /* pop 2nd table */
lua_setuservalue(L, -2); /* set 1st ktable into new pattern */
}
else if (n1 == 0) { /* first table is empty? */
lua_setuservalue(L, -3); /* set 2nd table into new pattern */
lua_pop(L, 1); /* pop 1st table */
}
else {
lua_createtable(L, n1 + n2, 0); /* create ktable for new pattern */
/* stack: new p; ktable p1; ktable p2; new ktable */
concattable(L, -3, -1); /* from p1 into new ktable */
concattable(L, -2, -1); /* from p2 into new ktable */
lua_setuservalue(L, -4); /* new ktable becomes 'p' environment */
lua_pop(L, 2); /* pop other ktables */
correctkeys(t2, n1); /* correction for indices from p2 */
}
}
/*
** copy 'ktable' of element 'idx' to new tree (on top of stack)
*/
static void copyktable (lua_State *L, int idx) {
lua_getuservalue(L, idx);
lua_setuservalue(L, -2);
}
/*
** merge 'ktable' from 'stree' at stack index 'idx' into 'ktable'
** from tree at the top of the stack, and correct corresponding
** tree.
*/
static void mergektable (lua_State *L, int idx, TTree *stree) {
int n;
lua_getuservalue(L, -1); /* get ktables */
lua_getuservalue(L, idx);
n = concattable(L, -1, -2);
lua_pop(L, 2); /* remove both ktables */
correctkeys(stree, n);
}
/*
** Create a new 'ktable' to the pattern at the top of the stack, adding
** all elements from pattern 'p' (if not 0) plus element 'idx' to it.
** Return index of new element.
*/
static int addtonewktable (lua_State *L, int p, int idx) {
newktable(L, 1);
if (p)
mergektable(L, p, NULL);
return addtoktable(L, idx);
}
/* }====================================================== */
/*
** {======================================================
** Tree generation
@@ -155,7 +338,7 @@ static Pattern *getpattern (lua_State *L, int idx) {
static int getsize (lua_State *L, int idx) {
return (lua_objlen(L, idx) - sizeof(Pattern)) / sizeof(TTree) + 1;
return (lua_rawlen(L, idx) - sizeof(Pattern)) / sizeof(TTree) + 1;
}
@@ -168,12 +351,16 @@ static TTree *gettree (lua_State *L, int idx, int *len) {
/*
** create a pattern
** create a pattern. Set its uservalue (the 'ktable') equal to its
** metatable. (It could be any empty sequence; the metatable is at
** hand here, so we use it.)
*/
static TTree *newtree (lua_State *L, int len) {
size_t size = (len - 1) * sizeof(TTree) + sizeof(Pattern);
Pattern *p = (Pattern *)lua_newuserdata(L, size);
luaL_getmetatable(L, PATTERN_T);
lua_pushvalue(L, -1);
lua_setuservalue(L, -3);
lua_setmetatable(L, -2);
p->code = NULL; p->codesize = 0;
return p->tree;
@@ -206,35 +393,6 @@ static TTree *seqaux (TTree *tree, TTree *sib, int sibsize) {
}
/*
** Add element 'idx' to 'ktable' of pattern at the top of the stack;
** create new 'ktable' if necessary. Return index of new element.
** If new element is nil, does not add it to table (as it would be
** useless) and returns 0, as ktable[0] is always nil.
*/
static int addtoktable (lua_State *L, int idx) {
if (idx == 0) /* no actual value to insert? */
return 0;
else {
int n;
lua_getfenv(L, -1); /* get ktable from pattern */
n = lua_objlen(L, -1);
if (n == 0) { /* is it empty/non-existent? */
lua_pop(L, 1); /* remove it */
lua_createtable(L, 1, 0); /* create a fresh table */
lua_pushvalue(L, -1); /* make a copy */
lua_setfenv(L, -3); /* set it as 'ktable' for pattern */
}
if (!lua_isnil(L, idx)) { /* non-nil value? */
lua_pushvalue(L, idx); /* element to be added */
lua_rawseti(L, -2, ++n);
}
lua_pop(L, 1); /* remove 'ktable' */
return n;
}
}
/*
** Build a sequence of 'n' nodes, each with tag 'tag' and 'u.n' got
** from the array 's' (or 0 if array is NULL). (TSeq is binary, so it
@@ -310,7 +468,7 @@ static TTree *getpatt (lua_State *L, int idx, int *len) {
case LUA_TFUNCTION: {
tree = newtree(L, 2);
tree->tag = TRunTime;
tree->key = addtoktable(L, idx);
tree->key = addtonewktable(L, 0, idx);
sib1(tree)->tag = TTrue;
break;
}
@@ -325,123 +483,6 @@ static TTree *getpatt (lua_State *L, int idx, int *len) {
}
/*
** Return the number of elements in the ktable of pattern at 'idx'.
** In Lua 5.2, default "environment" for patterns is nil, not
** a table. Treat it as an empty table. In Lua 5.1, assumes that
** the environment has no numeric indices (len == 0)
*/
static int ktablelen (lua_State *L, int idx) {
if (!lua_istable(L, idx)) return 0;
else return lua_objlen(L, idx);
}
/*
** Concatentate the contents of table 'idx1' into table 'idx2'.
** (Assume that both indices are negative.)
** Return the original length of table 'idx2'
*/
static int concattable (lua_State *L, int idx1, int idx2) {
int i;
int n1 = ktablelen(L, idx1);
int n2 = ktablelen(L, idx2);
if (n1 == 0) return 0; /* nothing to correct */
for (i = 1; i <= n1; i++) {
lua_rawgeti(L, idx1, i);
lua_rawseti(L, idx2 - 1, n2 + i); /* correct 'idx2' */
}
return n2;
}
/*
** Make a merge of ktables from p1 and p2 the ktable for the new
** pattern at the top of the stack.
*/
static int joinktables (lua_State *L, int p1, int p2) {
int n1, n2;
lua_getfenv(L, p1); /* get ktables */
lua_getfenv(L, p2);
n1 = ktablelen(L, -2);
n2 = ktablelen(L, -1);
if (n1 == 0 && n2 == 0) { /* are both tables empty? */
lua_pop(L, 2); /* nothing to be done; pop tables */
return 0; /* nothing to correct */
}
if (n2 == 0 || lua_equal(L, -2, -1)) { /* second table is empty or equal? */
lua_pop(L, 1); /* pop 2nd table */
lua_setfenv(L, -2); /* set 1st ktable into new pattern */
return 0; /* nothing to correct */
}
if (n1 == 0) { /* first table is empty? */
lua_setfenv(L, -3); /* set 2nd table into new pattern */
lua_pop(L, 1); /* pop 1st table */
return 0; /* nothing to correct */
}
else {
lua_createtable(L, n1 + n2, 0); /* create ktable for new pattern */
/* stack: new p; ktable p1; ktable p2; new ktable */
concattable(L, -3, -1); /* from p1 into new ktable */
concattable(L, -2, -1); /* from p2 into new ktable */
lua_setfenv(L, -4); /* new ktable becomes p env */
lua_pop(L, 2); /* pop other ktables */
return n1; /* correction for indices from p2 */
}
}
static void correctkeys (TTree *tree, int n) {
if (n == 0) return; /* no correction? */
tailcall:
switch (tree->tag) {
case TOpenCall: case TCall: case TRunTime: case TRule: {
if (tree->key > 0)
tree->key += n;
break;
}
case TCapture: {
if (tree->key > 0 && tree->cap != Carg && tree->cap != Cnum)
tree->key += n;
break;
}
default: break;
}
switch (numsiblings[tree->tag]) {
case 1: /* correctkeys(sib1(tree), n); */
tree = sib1(tree); goto tailcall;
case 2:
correctkeys(sib1(tree), n);
tree = sib2(tree); goto tailcall; /* correctkeys(sib2(tree), n); */
default: assert(numsiblings[tree->tag] == 0); break;
}
}
/*
** copy 'ktable' of element 'idx' to new tree (on top of stack)
*/
static void copyktable (lua_State *L, int idx) {
lua_getfenv(L, idx);
lua_setfenv(L, -2);
}
/*
** merge 'ktable' from rule at stack index 'idx' into 'ktable'
** from tree at the top of the stack, and correct corresponding
** tree.
*/
static void mergektable (lua_State *L, int idx, TTree *rule) {
int n;
lua_getfenv(L, -1); /* get ktables */
lua_getfenv(L, idx);
n = concattable(L, -1, -2);
lua_pop(L, 2); /* remove both ktables */
correctkeys(rule, n);
}
/*
** create a new tree, whith a new root and one sibling.
** Sibling must be on the Lua stack, at index 1.
@@ -470,7 +511,7 @@ static TTree *newroot2sib (lua_State *L, int tag) {
tree->u.ps = 1 + s1;
memcpy(sib1(tree), tree1, s1 * sizeof(TTree));
memcpy(sib2(tree), tree2, s2 * sizeof(TTree));
correctkeys(sib2(tree), joinktables(L, 1, 2));
joinktables(L, 1, sib2(tree), 2);
return tree;
}
@@ -599,7 +640,7 @@ static int lp_sub (lua_State *L) {
sib1(tree)->tag = TNot; /* ...not... */
memcpy(sib1(sib1(tree)), t2, s2 * sizeof(TTree)); /* ...t2 */
memcpy(sib2(tree), t1, s1 * sizeof(TTree)); /* ... and t1 */
correctkeys(sib1(tree), joinktables(L, 1, 2));
joinktables(L, 1, sib1(tree), 2);
}
return 1;
}
@@ -640,7 +681,7 @@ static int lp_behind (lua_State *L) {
TTree *tree;
TTree *tree1 = getpatt(L, 1, NULL);
int n = fixedlen(tree1);
luaL_argcheck(L, n > 0, 1, "pattern may not have fixed length");
luaL_argcheck(L, n >= 0, 1, "pattern may not have fixed length");
luaL_argcheck(L, !hascaptures(tree1), 1, "pattern have captures");
luaL_argcheck(L, n <= MAXBEHIND, 1, "pattern too long to look behind");
tree = newroot1sib(L, TBehind);
@@ -655,7 +696,7 @@ static int lp_behind (lua_State *L) {
static int lp_V (lua_State *L) {
TTree *tree = newleaf(L, TOpenCall);
luaL_argcheck(L, !lua_isnoneornil(L, 1), 1, "non-nil value expected");
tree->key = addtoktable(L, 1);
tree->key = addtonewktable(L, 0, 1);
return 1;
}
@@ -668,7 +709,7 @@ static int lp_V (lua_State *L) {
static int capture_aux (lua_State *L, int cap, int labelidx) {
TTree *tree = newroot1sib(L, TCapture);
tree->cap = cap;
tree->key = addtoktable(L, labelidx);
tree->key = (labelidx == 0) ? 0 : addtonewktable(L, 1, labelidx);
return 1;
}
@@ -676,10 +717,9 @@ static int capture_aux (lua_State *L, int cap, int labelidx) {
/*
** Fill a tree with an empty capture, using an empty (TTrue) sibling.
*/
static TTree *auxemptycap (lua_State *L, TTree *tree, int cap, int idx) {
static TTree *auxemptycap (TTree *tree, int cap) {
tree->tag = TCapture;
tree->cap = cap;
tree->key = addtoktable(L, idx);
sib1(tree)->tag = TTrue;
return tree;
}
@@ -688,8 +728,18 @@ static TTree *auxemptycap (lua_State *L, TTree *tree, int cap, int idx) {
/*
** Create a tree for an empty capture
*/
static TTree *newemptycap (lua_State *L, int cap, int idx) {
return auxemptycap(L, newtree(L, 2), cap, idx);
static TTree *newemptycap (lua_State *L, int cap) {
return auxemptycap(newtree(L, 2), cap);
}
/*
** Create a tree for an empty capture with an associated Lua value
*/
static TTree *newemptycapkey (lua_State *L, int cap, int idx) {
TTree *tree = auxemptycap(newtree(L, 2), cap);
tree->key = addtonewktable(L, 0, idx);
return tree;
}
@@ -728,10 +778,8 @@ static int lp_tablecapture (lua_State *L) {
static int lp_groupcapture (lua_State *L) {
if (lua_isnoneornil(L, 2))
return capture_aux(L, Cgroup, 0);
else {
luaL_checkstring(L, 2);
else
return capture_aux(L, Cgroup, 2);
}
}
@@ -747,14 +795,14 @@ static int lp_simplecapture (lua_State *L) {
static int lp_poscapture (lua_State *L) {
newemptycap(L, Cposition, 0);
newemptycap(L, Cposition);
return 1;
}
static int lp_argcapture (lua_State *L) {
int n = (int)luaL_checkinteger(L, 1);
TTree *tree = newemptycap(L, Carg, 0);
TTree *tree = newemptycap(L, Carg);
tree->key = n;
luaL_argcheck(L, 0 < n && n <= SHRT_MAX, 1, "invalid argument index");
return 1;
@@ -762,8 +810,8 @@ static int lp_argcapture (lua_State *L) {
static int lp_backref (lua_State *L) {
luaL_checkstring(L, 1);
newemptycap(L, Cbackref, 1);
luaL_checkany(L, 1);
newemptycapkey(L, Cbackref, 1);
return 1;
}
@@ -777,9 +825,10 @@ static int lp_constcapture (lua_State *L) {
if (n == 0) /* no values? */
newleaf(L, TTrue); /* no capture */
else if (n == 1)
newemptycap(L, Cconst, 1); /* single constant capture */
newemptycapkey(L, Cconst, 1); /* single constant capture */
else { /* create a group capture with all values */
TTree *tree = newtree(L, 1 + 3 * (n - 1) + 2);
newktable(L, n); /* create a 'ktable' for new tree */
tree->tag = TCapture;
tree->cap = Cgroup;
tree->key = 0;
@@ -787,10 +836,12 @@ static int lp_constcapture (lua_State *L) {
for (i = 1; i <= n - 1; i++) {
tree->tag = TSeq;
tree->u.ps = 3; /* skip TCapture and its sibling */
auxemptycap(L, sib1(tree), Cconst, i);
auxemptycap(sib1(tree), Cconst);
sib1(tree)->key = addtoktable(L, i);
tree = sib2(tree);
}
auxemptycap(L, tree, Cconst, i);
auxemptycap(tree, Cconst);
tree->key = addtoktable(L, i);
}
return 1;
}
@@ -800,7 +851,7 @@ static int lp_matchtime (lua_State *L) {
TTree *tree;
luaL_checktype(L, 2, LUA_TFUNCTION);
tree = newroot1sib(L, TRunTime);
tree->key = addtoktable(L, 2);
tree->key = addtonewktable(L, 1, 2);
return 1;
}
@@ -857,7 +908,7 @@ static int collectrules (lua_State *L, int arg, int *totalsize) {
lua_pushnil(L); /* prepare to traverse grammar table */
while (lua_next(L, arg) != 0) {
if (lua_tonumber(L, -2) == 1 ||
lua_equal(L, -2, postab + 1)) { /* initial rule? */
lp_equal(L, -2, postab + 1)) { /* initial rule? */
lua_pop(L, 1); /* remove value (keep key for lua_next) */
continue;
}
@@ -934,36 +985,40 @@ static int verifyerror (lua_State *L, int *passed, int npassed) {
/*
** Check whether a rule can be left recursive; raise an error in that
** case; otherwise return 1 iff pattern is nullable. Assume ktable at
** the top of the stack.
** case; otherwise return 1 iff pattern is nullable.
** The return value is used to check sequences, where the second pattern
** 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.)
** Assume ktable at the top of the stack.
*/
static int verifyrule (lua_State *L, TTree *tree, int *passed, int npassed,
int nullable) {
int nb) {
tailcall:
switch (tree->tag) {
case TChar: case TSet: case TAny:
case TFalse:
return nullable; /* cannot pass from here */
return nb; /* cannot pass from here */
case TTrue:
case TBehind: /* look-behind cannot have calls */
return 1;
case TNot: case TAnd: case TRep:
/* return verifyrule(L, sib1(tree), passed, npassed, 1); */
tree = sib1(tree); nullable = 1; goto tailcall;
tree = sib1(tree); nb = 1; goto tailcall;
case TCapture: case TRunTime:
/* return verifyrule(L, sib1(tree), passed, npassed); */
/* return verifyrule(L, sib1(tree), passed, npassed, nb); */
tree = sib1(tree); goto tailcall;
case TCall:
/* return verifyrule(L, sib2(tree), passed, npassed); */
/* return verifyrule(L, sib2(tree), passed, npassed, nb); */
tree = sib2(tree); goto tailcall;
case TSeq: /* only check 2nd child if first is nullable */
case TSeq: /* only check 2nd child if first is nb */
if (!verifyrule(L, sib1(tree), passed, npassed, 0))
return nullable;
/* else return verifyrule(L, sib2(tree), passed, npassed); */
return nb;
/* else return verifyrule(L, sib2(tree), passed, npassed, nb); */
tree = sib2(tree); goto tailcall;
case TChoice: /* must check both children */
nullable = verifyrule(L, sib1(tree), passed, npassed, nullable);
/* return verifyrule(L, sib2(tree), passed, npassed, nullable); */
nb = verifyrule(L, sib1(tree), passed, npassed, nb);
/* return verifyrule(L, sib2(tree), passed, npassed, nb); */
tree = sib2(tree); goto tailcall;
case TRule:
if (npassed >= MAXRULES)
@@ -1006,7 +1061,7 @@ static void verifygrammar (lua_State *L, TTree *grammar) {
*/
static void initialrulename (lua_State *L, TTree *grammar, int frule) {
if (sib1(grammar)->key == 0) { /* initial rule is not referenced? */
int n = lua_objlen(L, -1) + 1; /* index for name */
int n = lua_rawlen(L, -1) + 1; /* index for name */
lua_pushvalue(L, frule); /* rule's name */
lua_rawseti(L, -2, n); /* ktable was on the top of the stack */
sib1(grammar)->key = n;
@@ -1022,9 +1077,9 @@ static TTree *newgrammar (lua_State *L, int arg) {
luaL_argcheck(L, n <= MAXRULES, arg, "grammar has too many rules");
g->tag = TGrammar; g->u.n = n;
lua_newtable(L); /* create 'ktable' */
lua_setfenv(L, -2);
lua_setuservalue(L, -2);
buildgrammar(L, g, frule, n);
lua_getfenv(L, -1); /* get 'ktable' for new tree */
lua_getuservalue(L, -1); /* get 'ktable' for new tree */
finalfix(L, frule - 1, g, sib1(g));
initialrulename(L, g, frule);
verifygrammar(L, g);
@@ -1038,7 +1093,7 @@ static TTree *newgrammar (lua_State *L, int arg) {
static Instruction *prepcompile (lua_State *L, Pattern *p, int idx) {
lua_getfenv(L, idx); /* push 'ktable' (may be used by 'finalfix') */
lua_getuservalue(L, idx); /* push 'ktable' (may be used by 'finalfix') */
finalfix(L, 0, NULL, p->tree);
lua_pop(L, 1); /* remove 'ktable' */
return compile(L, p);
@@ -1049,7 +1104,7 @@ static int lp_printtree (lua_State *L) {
TTree *tree = getpatt(L, 1, NULL);
int c = lua_toboolean(L, 2);
if (c) {
lua_getfenv(L, 1); /* push 'ktable' (may be used by 'finalfix') */
lua_getuservalue(L, 1); /* push 'ktable' (may be used by 'finalfix') */
finalfix(L, 0, NULL, tree);
lua_pop(L, 1); /* remove 'ktable' */
}
@@ -1102,7 +1157,7 @@ static int lp_match (lua_State *L) {
int ptop = lua_gettop(L);
lua_pushnil(L); /* initialize subscache */
lua_pushlightuserdata(L, capture); /* initialize caplistidx */
lua_getfenv(L, 1); /* initialize penvidx */
lua_getuservalue(L, 1); /* initialize penvidx */
r = match(L, s, s + i, s + l, code, capture, ptop);
if (r == NULL) {
lua_pushnil(L);
@@ -1119,8 +1174,12 @@ static int lp_match (lua_State *L) {
** =======================================================
*/
/* maximum limit for stack size */
#define MAXLIM (INT_MAX / 100)
static int lp_setmax (lua_State *L) {
luaL_optinteger(L, 1, -1);
lua_Integer lim = luaL_checkinteger(L, 1);
luaL_argcheck(L, 0 < lim && lim <= MAXLIM, 1, "out of range");
lua_settop(L, 1);
lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);
return 0;
@@ -1144,8 +1203,7 @@ static int lp_type (lua_State *L) {
int lp_gc (lua_State *L) {
Pattern *p = getpattern(L, 1);
if (p->codesize > 0)
realloccode(L, p, 0);
realloccode(L, p, 0); /* delete code block */
return 0;
}
@@ -1228,8 +1286,8 @@ int luaopen_lpeg (lua_State *L) {
luaL_newmetatable(L, PATTERN_T);
lua_pushnumber(L, MAXBACK); /* initialize maximum backtracking */
lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);
luaL_register(L, NULL, metareg);
luaL_register(L, "lpeg", pattreg);
luaL_setfuncs(L, metareg, 0);
luaL_newlib(L, pattreg);
lua_pushvalue(L, -1);
lua_setfield(L, -3, "__index");
return 1;

View File

@@ -1,7 +1,7 @@
/*
** $Id: lptypes.h,v 1.10 2014/12/12 17:11:35 roberto Exp $
** $Id: lptypes.h,v 1.14 2015/09/28 17:17:41 roberto Exp $
** LPeg - PEG pattern matching for Lua
** Copyright 2007-2014, Lua.org & PUC-Rio (see 'lpeg.html' for license)
** Copyright 2007-2015, Lua.org & PUC-Rio (see 'lpeg.html' for license)
** written by Roberto Ierusalimschy
*/
@@ -19,7 +19,7 @@
#include "lua.h"
#define VERSION "0.12.1"
#define VERSION "1.0.0"
#define PATTERN_T "lpeg-pattern"
@@ -27,31 +27,31 @@
/*
** compatibility with Lua 5.2
** compatibility with Lua 5.1
*/
#if (LUA_VERSION_NUM >= 502)
#if (LUA_VERSION_NUM == 501)
#undef lua_equal
#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ)
#define lp_equal lua_equal
#undef lua_getfenv
#define lua_getfenv lua_getuservalue
#undef lua_setfenv
#define lua_setfenv lua_setuservalue
#define lua_getuservalue lua_getfenv
#define lua_setuservalue lua_setfenv
#undef lua_objlen
#define lua_objlen lua_rawlen
#define lua_rawlen lua_objlen
#undef luaL_register
#define luaL_register(L,n,f) \
{ if ((n) == NULL) luaL_setfuncs(L,f,0); else luaL_newlib(L,f); }
#define luaL_setfuncs(L,f,n) luaL_register(L,NULL,f)
#define luaL_newlib(L,f) luaL_register(L,"lpeg",f)
#endif
#if !defined(lp_equal)
#define lp_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ)
#endif
/* default maximum size for call/backtrack stack */
#if !defined(MAXBACK)
#define MAXBACK 100
#define MAXBACK 400
#endif

View File

@@ -1,5 +1,5 @@
/*
** $Id: lpvm.c,v 1.5 2013/04/12 16:29:49 roberto Exp $
** $Id: lpvm.c,v 1.6 2015/09/28 17:01:25 roberto Exp $
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
*/
@@ -18,7 +18,7 @@
/* initial size for call/backtrack stack */
#if !defined(INITBACK)
#define INITBACK 100
#define INITBACK MAXBACK
#endif
@@ -70,7 +70,7 @@ static Stack *doublestack (lua_State *L, Stack **stacklimit, int ptop) {
max = lua_tointeger(L, -1); /* maximum allowed size */
lua_pop(L, 1);
if (n >= max) /* already at maximum size? */
luaL_error(L, "too many pending calls/choices");
luaL_error(L, "backtrack stack overflow (current limit is %d)", max);
newn = 2 * n; /* new size */
if (newn > max) newn = max;
newstack = (Stack *)lua_newuserdata(L, newn * sizeof(Stack));

View File

@@ -10,7 +10,7 @@
</head>
<body>
<!-- $Id: re.html,v 1.21 2013/03/28 20:43:30 roberto Exp $ -->
<!-- $Id: re.html,v 1.23 2015/09/28 17:17:41 roberto Exp $ -->
<div id="container">
@@ -296,7 +296,7 @@ it would be useful if each table had
a <code>tag</code> field telling what non terminal
that table represents.
We can add such a tag using
<a href="lpeg.html/#cap-g">named group captures</a>:
<a href="lpeg.html#cap-g">named group captures</a>:
</p>
<pre class="example">
x = re.compile[[
@@ -450,7 +450,7 @@ print(re.match(p, p)) -- a self description must match itself
<h2><a name="license">License</a></h2>
<p>
Copyright &copy; 2008-2010 Lua.org, PUC-Rio.
Copyright &copy; 2008-2015 Lua.org, PUC-Rio.
</p>
<p>
Permission is hereby granted, free of charge,
@@ -488,7 +488,7 @@ THE SOFTWARE.
<div id="about">
<p><small>
$Id: re.html,v 1.21 2013/03/28 20:43:30 roberto Exp $
$Id: re.html,v 1.23 2015/09/28 17:17:41 roberto Exp $
</small></p>
</div> <!-- id="about" -->

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env lua5.1
#!/usr/bin/env lua
-- $Id: test.lua,v 1.105 2014/12/12 17:00:39 roberto Exp $
-- $Id: test.lua,v 1.109 2015/09/28 17:01:25 roberto Exp $
-- require"strict" -- just to be pedantic
@@ -16,9 +16,6 @@ local unpack = rawget(table, "unpack") or unpack
local loadstring = rawget(_G, "loadstring") or load
-- most tests here do not need much stack space
m.setmaxstack(5)
local any = m.P(1)
local space = m.S" \t\n"^0
@@ -291,6 +288,13 @@ assert(m.match(m.P"ab"^-1 - "c", "abcd") == 3)
p = ('Aa' * ('Bb' * ('Cc' * m.P'Dd'^0)^0)^0)^-1
assert(p:match("AaBbCcDdBbCcDdDdDdBb") == 21)
-- bug in 0.12.2
-- p = { ('ab' ('c' 'ef'?)*)? }
p = m.C(('ab' * ('c' * m.P'ef'^-1)^0)^-1)
s = "abcefccefc"
assert(s == p:match(s))
pi = "3.14159 26535 89793 23846 26433 83279 50288 41971 69399 37510"
@@ -352,6 +356,11 @@ checkeq(t, {hi = 10, ho = 20})
t = p:match'abc'
checkeq(t, {hi = 10, ho = 20, 'a', 'b', 'c'})
-- non-string group names
p = m.Ct(m.Cg(1, print) * m.Cg(1, 23.5) * m.Cg(1, io))
t = p:match('abcdefghij')
assert(t[print] == 'a' and t[23.5] == 'b' and t[io] == 'c')
-- test for error messages
local function checkerr (msg, f, ...)
@@ -388,6 +397,25 @@ p = m.P { (m.P {m.P'abc'} + 'ayz') * m.V'y'; y = m.P'x' }
assert(p:match('abcx') == 5 and p:match('ayzx') == 5 and not p:match'abc')
do
-- large dynamic Cc
local lim = 2^16 - 1
local c = 0
local function seq (n)
if n == 1 then c = c + 1; return m.Cc(c)
else
local m = math.floor(n / 2)
return seq(m) * seq(n - m)
end
end
p = m.Ct(seq(lim))
t = p:match('')
assert(t[lim] == lim)
checkerr("too many", function () p = p / print end)
checkerr("too many", seq, lim + 1)
end
-- tests for non-pattern as arguments to pattern functions
p = { ('a' * m.V(1))^-1 } * m.P'b' * { 'a' * m.V(2); m.V(1)^-1 }
@@ -575,9 +603,9 @@ assert(not p:match(string.rep("011", 10001)))
-- this grammar does need backtracking info.
local lim = 10000
p = m.P{ '0' * m.V(1) + '0' }
checkerr("too many pending", m.match, p, string.rep("0", lim))
checkerr("stack overflow", m.match, p, string.rep("0", lim))
m.setmaxstack(2*lim)
checkerr("too many pending", m.match, p, string.rep("0", lim))
checkerr("stack overflow", m.match, p, string.rep("0", lim))
m.setmaxstack(2*lim + 4)
assert(m.match(p, string.rep("0", lim)) == lim + 1)
@@ -586,7 +614,7 @@ p = m.P{ ('a' * m.V(1))^0 * 'b' + 'c' }
m.setmaxstack(200)
assert(p:match(string.rep('a', 180) .. 'c' .. string.rep('b', 180)) == 362)
m.setmaxstack(5) -- restore original limit
m.setmaxstack(100) -- restore low limit
-- tests for optional start position
assert(m.match("a", "abc", 1))
@@ -718,6 +746,10 @@ t = {m.match(m.Cc(nil,nil,4) * m.Cc(nil,3) * m.Cc(nil, nil) / g / g, "")}
t1 = {1,1,nil,nil,4,nil,3,nil,nil}
for i=1,10 do assert(t[i] == t1[i]) end
-- bug in 0.12.2: ktable with only nil could be eliminated when joining
-- with a pattern without ktable
assert((m.P"aaa" * m.Cc(nil)):match"aaa" == nil)
t = {m.match((m.C(1) / function (x) return x, x.."x" end)^0, "abc")}
checkeq(t, {"a", "ax", "b", "bx", "c", "cx"})
@@ -925,6 +957,13 @@ p = m.Cg(m.C(1) * m.C(1), "k") * m.Ct(m.Cb("k"))
t = p:match("ab")
checkeq(t, {"a", "b"})
p = m.P(true)
for i = 1, 10 do p = p * m.Cg(1, i) end
for i = 1, 10 do
local p = p * m.Cb(i)
assert(p:match('abcdefghij') == string.sub('abcdefghij', i, i))
end
t = {}
function foo (p) t[#t + 1] = p; return p .. "x" end

View File

@@ -19,7 +19,7 @@ SYSCFLAGS=
SYSLDFLAGS=
SYSLIBS=
MYCFLAGS=
MYCFLAGS=-I../../skynet-src
MYLDFLAGS=
MYLIBS=
MYOBJS=
@@ -130,68 +130,68 @@ solaris:
# DO NOT DELETE
lapi.o: lapi.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \
ltable.h lundump.h lvm.h
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \
ltable.h lundump.h lvm.h
lauxlib.o: lauxlib.c lprefix.h lua.h luaconf.h lauxlib.h
lbaselib.o: lbaselib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lbitlib.o: lbitlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lcode.o: lcode.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
ldo.h lgc.h lstring.h ltable.h lvm.h
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
ldo.h lgc.h lstring.h ltable.h lvm.h
lcorolib.o: lcorolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lctype.o: lctype.c lprefix.h lctype.h lua.h luaconf.h llimits.h
ldblib.o: ldblib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ldebug.o: ldebug.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \
ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h
lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \
ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h
ldo.o: ldo.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \
lparser.h lstring.h ltable.h lundump.h lvm.h
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \
lparser.h lstring.h ltable.h lundump.h lvm.h
ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.h \
ltm.h lzio.h lmem.h lundump.h
ltm.h lzio.h lmem.h lundump.h
lfunc.o: lfunc.c lprefix.h lua.h luaconf.h lfunc.h lobject.h llimits.h \
lgc.h lstate.h ltm.h lzio.h lmem.h
lgc.h lstate.h ltm.h lzio.h lmem.h
lgc.o: lgc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h
linit.o: linit.c lprefix.h lua.h luaconf.h lualib.h lauxlib.h
liolib.o: liolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldo.h \
lobject.h lstate.h ltm.h lzio.h lmem.h lgc.h llex.h lparser.h lstring.h \
ltable.h
llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldebug.h \
lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lgc.h llex.h lparser.h \
lstring.h ltable.h
lmathlib.o: lmathlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lmem.o: lmem.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h
loadlib.o: loadlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lobject.o: lobject.c lprefix.h lua.h luaconf.h lctype.h llimits.h \
ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \
lvm.h
ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \
lvm.h
lopcodes.o: lopcodes.c lprefix.h lopcodes.h llimits.h lua.h luaconf.h
loslib.o: loslib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lparser.o: lparser.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
ldo.h lfunc.h lstring.h lgc.h ltable.h
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
ldo.h lfunc.h lstring.h lgc.h ltable.h
lstate.o: lstate.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \
lstring.h ltable.h
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \
lstring.h ltable.h
lstring.o: lstring.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h
lstrlib.o: lstrlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ltable.o: ltable.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
ltablib.o: ltablib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h ltable.h lvm.h
llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h ltable.h lvm.h
lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
luac.o: luac.c lprefix.h lua.h luaconf.h lauxlib.h lobject.h llimits.h \
lstate.h ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h
lstate.h ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h
lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \
lundump.h
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \
lundump.h
lutf8lib.o: lutf8lib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lvm.o: lvm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \
ltable.h lvm.h
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \
ltable.h lvm.h
lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \
lobject.h ltm.h lzio.h
lobject.h ltm.h lzio.h
# (end of Makefile)

View File

@@ -1,5 +1,6 @@
This is a modify version of lua 5.3.0 (http://www.lua.org/ftp/lua-5.3.0.tar.gz) .
For detail : http://lua-users.org/lists/lua-l/2014-03/msg00489.html
This is a modify version of lua 5.3.1 (http://www.lua.org/ftp/lua-5.3.1.tar.gz) .
For detail ,
Shared Proto : http://lua-users.org/lists/lua-l/2014-03/msg00489.html
Shared short string table : http://blog.codingnow.com/2015/08/lua_vm_share_string.html

View File

@@ -1,5 +1,5 @@
/*
** $Id: lapi.c,v 2.244 2014/12/26 14:43:45 roberto Exp $
** $Id: lapi.c,v 2.249 2015/04/06 12:23:48 roberto Exp $
** Lua API
** See Copyright Notice in lua.h
*/
@@ -52,29 +52,29 @@ const char lua_ident[] =
/* test for valid but not pseudo index */
#define isstackindex(i, o) (isvalid(o) && !ispseudo(i))
#define api_checkvalidindex(o) api_check(isvalid(o), "invalid index")
#define api_checkvalidindex(l,o) api_check(l, isvalid(o), "invalid index")
#define api_checkstackindex(i, o) \
api_check(isstackindex(i, o), "index not in the stack")
#define api_checkstackindex(l, i, o) \
api_check(l, isstackindex(i, o), "index not in the stack")
static TValue *index2addr (lua_State *L, int idx) {
CallInfo *ci = L->ci;
if (idx > 0) {
TValue *o = ci->func + idx;
api_check(idx <= ci->top - (ci->func + 1), "unacceptable index");
api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index");
if (o >= L->top) return NONVALIDVALUE;
else return o;
}
else if (!ispseudo(idx)) { /* negative index */
api_check(idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index");
api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index");
return L->top + idx;
}
else if (idx == LUA_REGISTRYINDEX)
return &G(L)->l_registry;
else { /* upvalues */
idx = LUA_REGISTRYINDEX - idx;
api_check(idx <= MAXUPVAL + 1, "upvalue index too large");
api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large");
if (ttislcf(ci->func)) /* light C function? */
return NONVALIDVALUE; /* it has no upvalues */
else {
@@ -99,7 +99,7 @@ LUA_API int lua_checkstack (lua_State *L, int n) {
int res;
CallInfo *ci = L->ci;
lua_lock(L);
api_check(n >= 0, "negative 'n'");
api_check(L, n >= 0, "negative 'n'");
if (L->stack_last - L->top > n) /* stack large enough? */
res = 1; /* yes; check is OK */
else { /* no; need to grow stack */
@@ -121,11 +121,12 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
if (from == to) return;
lua_lock(to);
api_checknelems(from, n);
api_check(G(from) == G(to), "moving among independent states");
api_check(to->ci->top - to->top >= n, "not enough elements to move");
api_check(from, G(from) == G(to), "moving among independent states");
api_check(from, to->ci->top - to->top >= n, "not enough elements to move");
from->top -= n;
for (i = 0; i < n; i++) {
setobj2s(to, to->top++, from->top + i);
setobj2s(to, to->top, from->top + i);
api_incr_top(to);
}
lua_unlock(to);
}
@@ -160,7 +161,7 @@ LUA_API const lua_Number *lua_version (lua_State *L) {
LUA_API int lua_absindex (lua_State *L, int idx) {
return (idx > 0 || ispseudo(idx))
? idx
: cast_int(L->top - L->ci->func + idx);
: cast_int(L->top - L->ci->func) + idx;
}
@@ -173,13 +174,13 @@ LUA_API void lua_settop (lua_State *L, int idx) {
StkId func = L->ci->func;
lua_lock(L);
if (idx >= 0) {
api_check(idx <= L->stack_last - (func + 1), "new top too large");
api_check(L, idx <= L->stack_last - (func + 1), "new top too large");
while (L->top < (func + 1) + idx)
setnilvalue(L->top++);
L->top = (func + 1) + idx;
}
else {
api_check(-(idx+1) <= (L->top - (func + 1)), "invalid new top");
api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top");
L->top += idx+1; /* 'subtract' index (index is negative) */
}
lua_unlock(L);
@@ -209,8 +210,8 @@ LUA_API void lua_rotate (lua_State *L, int idx, int n) {
lua_lock(L);
t = L->top - 1; /* end of stack segment being rotated */
p = index2addr(L, idx); /* start of segment */
api_checkstackindex(idx, p);
api_check((n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'");
api_checkstackindex(L, idx, p);
api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'");
m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */
reverse(L, p, m); /* reverse the prefix with length 'n' */
reverse(L, m + 1, t); /* reverse the suffix */
@@ -224,7 +225,7 @@ LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) {
lua_lock(L);
fr = index2addr(L, fromidx);
to = index2addr(L, toidx);
api_checkvalidindex(to);
api_checkvalidindex(L, to);
setobj(L, to, fr);
if (isupvalue(toidx)) /* function upvalue? */
luaC_barrier(L, clCvalue(L->ci->func), fr);
@@ -256,7 +257,7 @@ LUA_API int lua_type (lua_State *L, int idx) {
LUA_API const char *lua_typename (lua_State *L, int t) {
UNUSED(L);
api_check(LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag");
api_check(L, LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag");
return ttypename(t);
}
@@ -306,7 +307,7 @@ LUA_API void lua_arith (lua_State *L, int op) {
else { /* for unary operations, add fake 2nd operand */
api_checknelems(L, 1);
setobjs2s(L, L->top, L->top - 1);
L->top++;
api_incr_top(L);
}
/* first operand at top - 2, second at top - 1; result go to top - 2 */
luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2);
@@ -326,7 +327,7 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {
case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break;
case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break;
case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break;
default: api_check(0, "invalid option");
default: api_check(L, 0, "invalid option");
}
}
lua_unlock(L);
@@ -383,15 +384,17 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
luaO_tostring(L, o);
lua_unlock(L);
}
if (len != NULL) *len = tsvalue(o)->len;
if (len != NULL)
*len = vslen(o);
return svalue(o);
}
LUA_API size_t lua_rawlen (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
switch (ttnov(o)) {
case LUA_TSTRING: return tsvalue(o)->len;
switch (ttype(o)) {
case LUA_TSHRSTR: return tsvalue(o)->shrlen;
case LUA_TLNGSTR: return tsvalue(o)->u.lnglen;
case LUA_TUSERDATA: return uvalue(o)->len;
case LUA_TTABLE: return luaH_getn(hvalue(o));
default: return 0;
@@ -432,9 +435,8 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) {
case LUA_TCCL: return clCvalue(o);
case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o)));
case LUA_TTHREAD: return thvalue(o);
case LUA_TUSERDATA:
case LUA_TLIGHTUSERDATA:
return lua_touserdata(L, idx);
case LUA_TUSERDATA: return getudatamem(uvalue(o));
case LUA_TLIGHTUSERDATA: return pvalue(o);
default: return NULL;
}
}
@@ -483,20 +485,19 @@ LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) {
LUA_API const char *lua_pushstring (lua_State *L, const char *s) {
if (s == NULL) {
lua_pushnil(L);
return NULL;
}
lua_lock(L);
if (s == NULL)
setnilvalue(L->top);
else {
TString *ts;
lua_lock(L);
luaC_checkGC(L);
ts = luaS_new(L, s);
setsvalue2s(L, L->top, ts);
api_incr_top(L);
lua_unlock(L);
return getstr(ts);
s = getstr(ts); /* internal copy's address */
}
api_incr_top(L);
lua_unlock(L);
return s;
}
@@ -532,7 +533,7 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
else {
CClosure *cl;
api_checknelems(L, n);
api_check(n <= MAXUPVAL, "upvalue index too large");
api_check(L, n <= MAXUPVAL, "upvalue index too large");
luaC_checkGC(L);
cl = luaF_newCclosure(L, n);
cl->f = fn;
@@ -584,7 +585,8 @@ LUA_API int lua_getglobal (lua_State *L, const char *name) {
const TValue *gt; /* global table */
lua_lock(L);
gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
setsvalue2s(L, L->top++, luaS_new(L, name));
setsvalue2s(L, L->top, luaS_new(L, name));
api_incr_top(L);
luaV_gettable(L, gt, L->top - 1, L->top - 1);
lua_unlock(L);
return ttnov(L->top - 1);
@@ -629,7 +631,7 @@ LUA_API int lua_rawget (lua_State *L, int idx) {
StkId t;
lua_lock(L);
t = index2addr(L, idx);
api_check(ttistable(t), "table expected");
api_check(L, ttistable(t), "table expected");
setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
lua_unlock(L);
return ttnov(L->top - 1);
@@ -640,7 +642,7 @@ LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) {
StkId t;
lua_lock(L);
t = index2addr(L, idx);
api_check(ttistable(t), "table expected");
api_check(L, ttistable(t), "table expected");
setobj2s(L, L->top, luaH_getint(hvalue(t), n));
api_incr_top(L);
lua_unlock(L);
@@ -653,7 +655,7 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
TValue k;
lua_lock(L);
t = index2addr(L, idx);
api_check(ttistable(t), "table expected");
api_check(L, ttistable(t), "table expected");
setpvalue(&k, cast(void *, p));
setobj2s(L, L->top, luaH_get(hvalue(t), &k));
api_incr_top(L);
@@ -706,7 +708,7 @@ LUA_API int lua_getuservalue (lua_State *L, int idx) {
StkId o;
lua_lock(L);
o = index2addr(L, idx);
api_check(ttisfulluserdata(o), "full userdata expected");
api_check(L, ttisfulluserdata(o), "full userdata expected");
getuservalue(L, uvalue(o), L->top);
api_incr_top(L);
lua_unlock(L);
@@ -725,7 +727,8 @@ LUA_API void lua_setglobal (lua_State *L, const char *name) {
lua_lock(L);
api_checknelems(L, 1);
gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
setsvalue2s(L, L->top++, luaS_new(L, name));
setsvalue2s(L, L->top, luaS_new(L, name));
api_incr_top(L);
luaV_settable(L, gt, L->top - 1, L->top - 2);
L->top -= 2; /* pop value and key */
lua_unlock(L);
@@ -748,7 +751,8 @@ LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
lua_lock(L);
api_checknelems(L, 1);
t = index2addr(L, idx);
setsvalue2s(L, L->top++, luaS_new(L, k));
setsvalue2s(L, L->top, luaS_new(L, k));
api_incr_top(L);
luaV_settable(L, t, L->top - 1, L->top - 2);
L->top -= 2; /* pop value and key */
lua_unlock(L);
@@ -760,7 +764,8 @@ LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
lua_lock(L);
api_checknelems(L, 1);
t = index2addr(L, idx);
setivalue(L->top++, n);
setivalue(L->top, n);
api_incr_top(L);
luaV_settable(L, t, L->top - 1, L->top - 2);
L->top -= 2; /* pop value and key */
lua_unlock(L);
@@ -773,7 +778,7 @@ LUA_API void lua_rawset (lua_State *L, int idx) {
lua_lock(L);
api_checknelems(L, 2);
o = index2addr(L, idx);
api_check(ttistable(o), "table expected");
api_check(L, ttistable(o), "table expected");
t = hvalue(o);
setobj2t(L, luaH_set(L, t, L->top-2), L->top-1);
invalidateTMcache(t);
@@ -789,7 +794,7 @@ LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) {
lua_lock(L);
api_checknelems(L, 1);
o = index2addr(L, idx);
api_check(ttistable(o), "table expected");
api_check(L, ttistable(o), "table expected");
t = hvalue(o);
luaH_setint(L, t, n, L->top - 1);
luaC_barrierback(L, t, L->top-1);
@@ -805,7 +810,7 @@ LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) {
lua_lock(L);
api_checknelems(L, 1);
o = index2addr(L, idx);
api_check(ttistable(o), "table expected");
api_check(L, ttistable(o), "table expected");
t = hvalue(o);
setpvalue(&k, cast(void *, p));
setobj2t(L, luaH_set(L, t, &k), L->top - 1);
@@ -824,7 +829,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
if (ttisnil(L->top - 1))
mt = NULL;
else {
api_check(ttistable(L->top - 1), "table expected");
api_check(L, ttistable(L->top - 1), "table expected");
mt = hvalue(L->top - 1);
}
switch (ttnov(obj)) {
@@ -860,7 +865,7 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) {
lua_lock(L);
api_checknelems(L, 1);
o = index2addr(L, idx);
api_check(ttisfulluserdata(o), "full userdata expected");
api_check(L, ttisfulluserdata(o), "full userdata expected");
setuservalue(L, uvalue(o), L->top - 1);
luaC_barrier(L, gcvalue(o), L->top - 1);
L->top--;
@@ -874,7 +879,7 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) {
#define checkresults(L,na,nr) \
api_check((nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \
api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \
"results from function overflow current stack size")
@@ -882,10 +887,10 @@ LUA_API void lua_callk (lua_State *L, int nargs, int nresults,
lua_KContext ctx, lua_KFunction k) {
StkId func;
lua_lock(L);
api_check(k == NULL || !isLua(L->ci),
api_check(L, k == NULL || !isLua(L->ci),
"cannot use continuations inside hooks");
api_checknelems(L, nargs+1);
api_check(L->status == LUA_OK, "cannot do calls on non-normal thread");
api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
checkresults(L, nargs, nresults);
func = L->top - (nargs+1);
if (k != NULL && L->nny == 0) { /* need to prepare continuation? */
@@ -923,16 +928,16 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
int status;
ptrdiff_t func;
lua_lock(L);
api_check(k == NULL || !isLua(L->ci),
api_check(L, k == NULL || !isLua(L->ci),
"cannot use continuations inside hooks");
api_checknelems(L, nargs+1);
api_check(L->status == LUA_OK, "cannot do calls on non-normal thread");
api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
checkresults(L, nargs, nresults);
if (errfunc == 0)
func = 0;
else {
StkId o = index2addr(L, errfunc);
api_checkstackindex(errfunc, o);
api_checkstackindex(L, errfunc, o);
func = savestack(L, o);
}
c.func = L->top - (nargs+1); /* function to be called */
@@ -984,7 +989,6 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
return status;
}
static Proto * cloneproto (lua_State *L, const Proto *src) {
/* copy constants and nested proto */
int i,n;
@@ -996,7 +1000,7 @@ static Proto * cloneproto (lua_State *L, const Proto *src) {
const TValue *s=&src->k[i];
TValue *o=&f->k[i];
if (ttisstring(s)) {
TString * str = luaS_newlstr(L,svalue(s),tsvalue(s)->len);
TString * str = luaS_clonestring(L,tsvalue(s));
setsvalue2n(L,o,str);
} else {
setobj(L,o,s);
@@ -1150,7 +1154,7 @@ LUA_API int lua_next (lua_State *L, int idx) {
int more;
lua_lock(L);
t = index2addr(L, idx);
api_check(ttistable(t), "table expected");
api_check(L, ttistable(t), "table expected");
more = luaH_next(L, hvalue(t), L->top - 1);
if (more) {
api_incr_top(L);
@@ -1282,9 +1286,9 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {
LClosure *f;
StkId fi = index2addr(L, fidx);
api_check(ttisLclosure(fi), "Lua function expected");
api_check(L, ttisLclosure(fi), "Lua function expected");
f = clLvalue(fi);
api_check((1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");
api_check(L, (1 <= n && n <= f->p->sp->sizeupvalues), "invalid upvalue index");
if (pf) *pf = f;
return &f->upvals[n - 1]; /* get its upvalue pointer */
}
@@ -1298,11 +1302,11 @@ LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) {
}
case LUA_TCCL: { /* C closure */
CClosure *f = clCvalue(fi);
api_check(1 <= n && n <= f->nupvalues, "invalid upvalue index");
api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index");
return &f->upvalue[n - 1];
}
default: {
api_check(0, "closure expected");
api_check(L, 0, "closure expected");
return NULL;
}
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lapi.h,v 2.8 2014/07/15 21:26:50 roberto Exp $
** $Id: lapi.h,v 2.9 2015/03/06 19:49:50 roberto Exp $
** Auxiliary functions from Lua API
** See Copyright Notice in lua.h
*/
@@ -11,13 +11,13 @@
#include "llimits.h"
#include "lstate.h"
#define api_incr_top(L) {L->top++; api_check(L->top <= L->ci->top, \
#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \
"stack overflow");}
#define adjustresults(L,nres) \
{ if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
#define api_checknelems(L,n) api_check((n) < (L->top - L->ci->func), \
#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \
"not enough elements in the stack")

View File

@@ -1,5 +1,5 @@
/*
** $Id: lauxlib.c,v 1.279 2014/12/14 18:32:26 roberto Exp $
** $Id: lauxlib.c,v 1.280 2015/02/03 17:38:24 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@@ -286,7 +286,7 @@ LUALIB_API int luaL_execresult (lua_State *L, int stat) {
*/
LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
if (luaL_getmetatable(L, tname)) /* name already in use? */
if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */
return 0; /* leave previous value on top, but return 0 */
lua_pop(L, 1);
lua_newtable(L); /* create metatable */
@@ -972,29 +972,28 @@ LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) {
// use clonefunction
#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
#define UNLOCK(q) __sync_lock_release(&(q)->lock);
#include "spinlock.h"
struct codecache {
int lock;
struct spinlock lock;
lua_State *L;
};
static struct codecache CC = { 0 , NULL };
static struct codecache CC;
static void
clearcache() {
if (CC.L == NULL)
return;
LOCK(&CC)
SPIN_LOCK(&CC)
lua_close(CC.L);
CC.L = luaL_newstate();
UNLOCK(&CC)
SPIN_UNLOCK(&CC)
}
static void
init() {
CC.lock = 0;
SPIN_INIT(&CC);
CC.L = luaL_newstate();
}
@@ -1002,13 +1001,13 @@ static const void *
load(const char *key) {
if (CC.L == NULL)
return NULL;
LOCK(&CC)
SPIN_LOCK(&CC)
lua_State *L = CC.L;
lua_pushstring(L, key);
lua_rawget(L, LUA_REGISTRYINDEX);
const void * result = lua_touserdata(L, -1);
lua_pop(L, 1);
UNLOCK(&CC)
SPIN_UNLOCK(&CC)
return result;
}
@@ -1018,7 +1017,7 @@ save(const char *key, const void * proto) {
lua_State *L;
const void * result = NULL;
LOCK(&CC)
SPIN_LOCK(&CC)
if (CC.L == NULL) {
init();
L = CC.L;
@@ -1036,17 +1035,66 @@ save(const char *key, const void * proto) {
lua_pop(L,2);
}
}
UNLOCK(&CC)
SPIN_UNLOCK(&CC)
return result;
}
#define CACHE_OFF 0
#define CACHE_EXIST 1
#define CACHE_ON 2
static int cache_key = 0;
static int cache_level(lua_State *L) {
int t = lua_rawgetp(L, LUA_REGISTRYINDEX, &cache_key);
int r = lua_tointeger(L, -1);
lua_pop(L,1);
if (t == LUA_TNUMBER) {
return r;
}
return CACHE_ON;
}
static int cache_mode(lua_State *L) {
static const char * lst[] = {
"OFF",
"EXIST",
"ON",
NULL,
};
if (lua_isnoneornil(L,1)) {
int t = lua_rawgetp(L, LUA_REGISTRYINDEX, &cache_key);
int r = lua_tointeger(L, -1);
if (t == LUA_TNUMBER) {
if (r < 0 || r >= CACHE_ON) {
r = CACHE_ON;
}
} else {
r = CACHE_ON;
}
lua_pushstring(L, lst[r]);
return 1;
}
int t = luaL_checkoption(L, 1, "OFF" , lst);
lua_pushinteger(L, t);
lua_rawsetp(L, LUA_REGISTRYINDEX, &cache_key);
return 0;
}
LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
const char *mode) {
int level = cache_level(L);
if (level == CACHE_OFF) {
return luaL_loadfilex_(L, filename, mode);
}
const void * proto = load(filename);
if (proto) {
lua_clonefunction(L, proto);
return LUA_OK;
}
if (level == CACHE_EXIST) {
return luaL_loadfilex_(L, filename, mode);
}
lua_State * eL = luaL_newstate();
if (eL == NULL) {
lua_pushliteral(L, "New state failed");
@@ -1083,10 +1131,11 @@ cache_clear(lua_State *L) {
LUAMOD_API int luaopen_cache(lua_State *L) {
luaL_Reg l[] = {
{ "clear", cache_clear },
{ "mode", cache_mode },
{ NULL, NULL },
};
luaL_newlib(L,l);
lua_getglobal(L, "loadfile");
lua_setfield(L, -2, "loadfile");
return 1;
}
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lbaselib.c,v 1.309 2014/12/10 12:26:42 roberto Exp $
** $Id: lbaselib.c,v 1.310 2015/03/28 19:14:47 roberto Exp $
** Basic library
** See Copyright Notice in lua.h
*/
@@ -55,7 +55,7 @@ static const char *b_str2int (const char *s, int base, lua_Integer *pn) {
return NULL;
do {
int digit = (isdigit((unsigned char)*s)) ? *s - '0'
: toupper((unsigned char)*s) - 'A' + 10;
: (toupper((unsigned char)*s) - 'A') + 10;
if (digit >= base) return NULL; /* invalid numeral */
n = n * base + digit;
s++;

View File

@@ -1,5 +1,5 @@
/*
** $Id: lcode.c,v 2.99 2014/12/29 16:49:25 roberto Exp $
** $Id: lcode.c,v 2.101 2015/04/29 18:24:11 roberto Exp $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
@@ -29,8 +29,8 @@
#include "lvm.h"
/* Maximum number of registers in a Lua function */
#define MAXREGS 250
/* Maximum number of registers in a Lua function (must fit in 8 bits) */
#define MAXREGS 255
#define hasjumps(e) ((e)->t != (e)->f)
@@ -279,7 +279,8 @@ void luaK_checkstack (FuncState *fs, int n) {
int newstack = fs->freereg + n;
if (newstack > fs->f->sp->maxstacksize) {
if (newstack >= MAXREGS)
luaX_syntaxerror(fs->ls, "function or expression too complex");
luaX_syntaxerror(fs->ls,
"function or expression needs too many registers");
fs->f->sp->maxstacksize = cast_byte(newstack);
}
}
@@ -573,8 +574,8 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) {
case VKFLT: {
e->u.info = luaK_numberK(fs, e->u.nval);
e->k = VK;
/* go through */
}
/* FALLTHROUGH */
case VK: {
vk:
if (e->u.info <= MAXINDEXRK) /* constant fits in 'argC'? */
@@ -793,7 +794,7 @@ static int constfolding (FuncState *fs, int op, expdesc *e1, expdesc *e2) {
static void codeexpval (FuncState *fs, OpCode op,
expdesc *e1, expdesc *e2, int line) {
lua_assert(op >= OP_ADD);
if (op <= OP_BNOT && constfolding(fs, op - OP_ADD + LUA_OPADD, e1, e2))
if (op <= OP_BNOT && constfolding(fs, (op - OP_ADD) + LUA_OPADD, e1, e2))
return; /* result has been folded */
else {
int o1, o2;
@@ -920,11 +921,11 @@ void luaK_posfix (FuncState *fs, BinOpr op,
break;
}
case OPR_EQ: case OPR_LT: case OPR_LE: {
codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2);
codecomp(fs, cast(OpCode, (op - OPR_EQ) + OP_EQ), 1, e1, e2);
break;
}
case OPR_NE: case OPR_GT: case OPR_GE: {
codecomp(fs, cast(OpCode, op - OPR_NE + OP_EQ), 0, e1, e2);
codecomp(fs, cast(OpCode, (op - OPR_NE) + OP_EQ), 0, e1, e2);
break;
}
default: lua_assert(0);

View File

@@ -1,5 +1,5 @@
/*
** $Id: ldblib.c,v 1.148 2015/01/02 12:52:22 roberto Exp $
** $Id: ldblib.c,v 1.149 2015/02/19 17:06:21 roberto Exp $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
@@ -27,6 +27,17 @@
static const int HOOKKEY = 0;
/*
** If L1 != L, L1 can be in any state, and therefore there is no
** garanties about its stack space; any push in L1 must be
** checked.
*/
static void checkstack (lua_State *L, lua_State *L1, int n) {
if (L != L1 && !lua_checkstack(L1, n))
luaL_error(L, "stack overflow");
}
static int db_getregistry (lua_State *L) {
lua_pushvalue(L, LUA_REGISTRYINDEX);
return 1;
@@ -127,12 +138,16 @@ static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
/*
** Calls 'lua_getinfo' and collects all results in a new table.
** L1 needs stack space for an optional input (function) plus
** two optional outputs (function and line table) from function
** 'lua_getinfo'.
*/
static int db_getinfo (lua_State *L) {
lua_Debug ar;
int arg;
lua_State *L1 = getthread(L, &arg);
const char *options = luaL_optstring(L, arg+2, "flnStu");
checkstack(L, L1, 3);
if (lua_isfunction(L, arg + 1)) { /* info about a function? */
options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */
lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */
@@ -190,6 +205,7 @@ static int db_getlocal (lua_State *L) {
int level = (int)luaL_checkinteger(L, arg + 1);
if (!lua_getstack(L1, level, &ar)) /* out of range? */
return luaL_argerror(L, arg+1, "level out of range");
checkstack(L, L1, 1);
name = lua_getlocal(L1, &ar, nvar);
if (name) {
lua_xmove(L1, L, 1); /* move local value */
@@ -216,6 +232,7 @@ static int db_setlocal (lua_State *L) {
return luaL_argerror(L, arg+1, "level out of range");
luaL_checkany(L, arg+3);
lua_settop(L, arg+3);
checkstack(L, L1, 1);
lua_xmove(L, L1, 1);
name = lua_setlocal(L1, &ar, nvar);
if (name == NULL)
@@ -350,6 +367,7 @@ static int db_sethook (lua_State *L) {
lua_pushvalue(L, -1);
lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */
}
checkstack(L, L1, 1);
lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */
lua_pushvalue(L, arg + 1); /* value (hook function) */
lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */
@@ -370,6 +388,7 @@ static int db_gethook (lua_State *L) {
lua_pushliteral(L, "external hook");
else { /* hook table must exist */
lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY);
checkstack(L, L1, 1);
lua_pushthread(L1); lua_xmove(L1, L, 1);
lua_rawget(L, -2); /* 1st result = hooktable[L1] */
lua_remove(L, -2); /* remove hook table */

View File

@@ -1,5 +1,5 @@
/*
** $Id: ldebug.c,v 2.110 2015/01/02 12:52:22 roberto Exp $
** $Id: ldebug.c,v 2.115 2015/05/22 17:45:56 roberto Exp $
** Debug Interface
** See Copyright Notice in lua.h
*/
@@ -34,6 +34,10 @@
#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL)
/* Active Lua function (given call info) */
#define ci_func(ci) (clLvalue((ci)->func))
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
@@ -122,7 +126,7 @@ static const char *upvalname (Proto *p, int uv) {
static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
int nparams = clLvalue(ci->func)->p->sp->numparams;
if (n >= ci->u.l.base - ci->func - nparams)
if (n >= cast_int(ci->u.l.base - ci->func) - nparams)
return NULL; /* no such vararg */
else {
*pos = ci->func + nparams + n;
@@ -168,7 +172,7 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0);
}
else { /* active function; get information through 'ar' */
StkId pos = 0; /* to avoid warnings */
StkId pos = NULL; /* to avoid warnings */
name = findlocal(L, ar->i_ci, n, &pos);
if (name) {
setobj2s(L, L->top, pos);
@@ -182,7 +186,7 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
StkId pos = 0; /* to avoid warnings */
StkId pos = NULL; /* to avoid warnings */
const char *name;
lua_lock(L);
swapextra(L);
@@ -295,7 +299,7 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
if (*what == '>') {
ci = NULL;
func = L->top - 1;
api_check(ttisfunction(func), "function expected");
api_check(L, ttisfunction(func), "function expected");
what++; /* skip the '>' */
L->top--; /* pop function */
}
@@ -595,19 +599,16 @@ l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
}
static void addinfo (lua_State *L, const char *msg) {
CallInfo *ci = L->ci;
if (isLua(ci)) { /* is Lua code? */
char buff[LUA_IDSIZE]; /* add file:line information */
int line = currentline(ci);
TString *src = ci_func(ci)->p->sp->source;
if (src)
luaO_chunkid(buff, getstr(src), LUA_IDSIZE);
else { /* no source available; use "?" instead */
buff[0] = '?'; buff[1] = '\0';
}
luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
/* add src:line information to 'msg' */
const char *luaG_addinfo (lua_State *L, const char *msg, TString *src,
int line) {
char buff[LUA_IDSIZE];
if (src)
luaO_chunkid(buff, getstr(src), LUA_IDSIZE);
else { /* no source available; use "?" instead */
buff[0] = '?'; buff[1] = '\0';
}
return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
}
@@ -624,10 +625,14 @@ l_noret luaG_errormsg (lua_State *L) {
l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
CallInfo *ci = L->ci;
const char *msg;
va_list argp;
va_start(argp, fmt);
addinfo(L, luaO_pushvfstring(L, fmt, argp));
msg = luaO_pushvfstring(L, fmt, argp); /* format message */
va_end(argp);
if (isLua(ci)) /* if Lua function, add source:line information */
luaG_addinfo(L, msg, ci_func(ci)->p->sp->source, currentline(ci));
luaG_errormsg(L);
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: ldebug.h,v 2.12 2014/11/10 14:46:05 roberto Exp $
** $Id: ldebug.h,v 2.14 2015/05/22 17:45:56 roberto Exp $
** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h
*/
@@ -17,9 +17,6 @@
#define resethookcount(L) (L->hookcount = L->basehookcount)
/* Active Lua function (given call info) */
#define ci_func(ci) (clLvalue((ci)->func))
LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
const char *opname);
@@ -33,6 +30,8 @@ LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1,
LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1,
const TValue *p2);
LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...);
LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg,
TString *src, int line);
LUAI_FUNC l_noret luaG_errormsg (lua_State *L);
LUAI_FUNC void luaG_traceexec (lua_State *L);

View File

@@ -1,5 +1,5 @@
/*
** $Id: ldo.c,v 2.135 2014/11/11 17:13:39 roberto Exp $
** $Id: ldo.c,v 2.138 2015/05/22 17:48:19 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -323,6 +323,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
case LUA_TCCL: { /* C closure */
f = clCvalue(func)->f;
Cfunc:
luaC_checkGC(L); /* stack grow uses memory */
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
ci = next_ci(L); /* now 'enter' new function */
ci->nresults = nresults;
@@ -330,20 +331,20 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
ci->top = L->top + LUA_MINSTACK;
lua_assert(ci->top <= L->stack_last);
ci->callstatus = 0;
luaC_checkGC(L); /* stack grow uses memory */
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, L->top - n);
luaD_poscall(L, L->top - n, n);
return 1;
}
case LUA_TLCL: { /* Lua function: prepare its call */
StkId base;
SharedProto *p = clLvalue(func)->p->sp;
n = cast_int(L->top - func) - 1; /* number of real arguments */
luaC_checkGC(L); /* stack grow uses memory */
luaD_checkstack(L, p->maxstacksize);
for (; n < p->numparams; n++)
setnilvalue(L->top++); /* complete missing arguments */
@@ -364,7 +365,6 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
ci->u.l.savedpc = p->code; /* starting point */
ci->callstatus = CIST_LUA;
L->top = ci->top;
luaC_checkGC(L); /* stack grow uses memory */
if (L->hookmask & LUA_MASKCALL)
callhook(L, ci);
return 0;
@@ -379,7 +379,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
}
int luaD_poscall (lua_State *L, StkId firstResult) {
int luaD_poscall (lua_State *L, StkId firstResult, int nres) {
StkId res;
int wanted, i;
CallInfo *ci = L->ci;
@@ -393,9 +393,9 @@ int luaD_poscall (lua_State *L, StkId firstResult) {
}
res = ci->func; /* res == final position of 1st result */
wanted = ci->nresults;
L->ci = ci = ci->previous; /* back to caller */
L->ci = ci->previous; /* back to caller */
/* move results to correct place */
for (i = wanted; i != 0 && firstResult < L->top; i--)
for (i = wanted; i != 0 && nres-- > 0; i--)
setobjs2s(L, res++, firstResult++);
while (i-- > 0)
setnilvalue(res++);
@@ -449,7 +449,7 @@ static void finishCcall (lua_State *L, int status) {
lua_lock(L);
api_checknelems(L, n);
/* finish 'luaD_precall' */
luaD_poscall(L, L->top - n);
luaD_poscall(L, L->top - n, n);
}
@@ -533,7 +533,8 @@ static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) {
*/
static void resume (lua_State *L, void *ud) {
int nCcalls = L->nCcalls;
StkId firstArg = cast(StkId, ud);
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);
@@ -553,14 +554,13 @@ static void resume (lua_State *L, void *ud) {
luaV_execute(L); /* just continue running Lua code */
else { /* 'common' yield */
if (ci->u.c.k != NULL) { /* does it have a continuation function? */
int n;
lua_unlock(L);
n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */
lua_lock(L);
api_checknelems(L, n);
firstArg = L->top - n; /* yield results come from continuation */
}
luaD_poscall(L, firstArg); /* finish 'luaD_precall' */
luaD_poscall(L, firstArg, n); /* finish 'luaD_precall' */
}
unroll(L, NULL); /* run continuation */
}
@@ -576,7 +576,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
L->nCcalls = (from) ? from->nCcalls + 1 : 1;
L->nny = 0; /* allow yields */
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
status = luaD_rawrunprotected(L, resume, L->top - nargs);
status = luaD_rawrunprotected(L, resume, &nargs);
if (status == -1) /* error calling 'lua_resume'? */
status = LUA_ERRRUN;
else { /* continue running after recoverable errors */
@@ -619,7 +619,7 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx,
L->status = LUA_YIELD;
ci->extra = savestack(L, ci->func); /* save current 'func' */
if (isLua(ci)) { /* inside a hook? */
api_check(k == NULL, "hooks cannot continue after yielding");
api_check(L, k == NULL, "hooks cannot continue after yielding");
}
else {
if ((ci->u.c.k = k) != NULL) /* is there a continuation? */

View File

@@ -1,5 +1,5 @@
/*
** $Id: ldo.h,v 2.21 2014/10/25 11:50:46 roberto Exp $
** $Id: ldo.h,v 2.22 2015/05/22 17:48:19 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -34,7 +34,7 @@ LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults,
int allowyield);
LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t oldtop, ptrdiff_t ef);
LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);
LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult, int nres);
LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
LUAI_FUNC void luaD_growstack (lua_State *L, int n);
LUAI_FUNC void luaD_shrinkstack (lua_State *L);

View File

@@ -1,5 +1,5 @@
/*
** $Id: ldump.c,v 2.34 2014/11/02 19:19:04 roberto Exp $
** $Id: ldump.c,v 2.36 2015/03/30 15:43:51 roberto Exp $
** save precompiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -74,14 +74,15 @@ static void DumpString (const TString *s, DumpState *D) {
if (s == NULL)
DumpByte(0, D);
else {
size_t size = s->len + 1; /* include trailing '\0' */
size_t size = tsslen(s) + 1; /* include trailing '\0' */
const char *str = getstr(s);
if (size < 0xFF)
DumpByte(cast_int(size), D);
else {
DumpByte(0xFF, D);
DumpVar(size, D);
}
DumpVector(getstr(s), size - 1, D); /* no need to save '\0' */
DumpVector(str, size - 1, D); /* no need to save '\0' */
}
}

View File

@@ -127,6 +127,7 @@ Proto *luaF_newproto (lua_State *L, SharedProto *sp) {
return f;
}
static void freesharedproto (lua_State *L, SharedProto *f) {
if (f == NULL || G(L) != f->l_G)
return;
@@ -137,7 +138,6 @@ static void freesharedproto (lua_State *L, SharedProto *f) {
luaM_free(L, f);
}
void luaF_freeproto (lua_State *L, Proto *f) {
luaM_freearray(L, f->p, f->sp->sizep);
luaM_freearray(L, f->k, f->sp->sizek);

View File

@@ -1,5 +1,5 @@
/*
** $Id: lfunc.h,v 2.14 2014/06/19 18:27:20 roberto Exp $
** $Id: lfunc.h,v 2.15 2015/01/13 15:49:11 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
@@ -22,6 +22,13 @@
#define isintwups(L) (L->twups != L)
/*
** maximum number of upvalues in a closure (both C and Lua). (Value
** must fit in a VM register.)
*/
#define MAXUPVAL 255
/*
** Upvalues for Lua closures
*/

View File

@@ -1,5 +1,5 @@
/*
** $Id: lgc.c,v 2.201 2014/12/20 13:58:15 roberto Exp $
** $Id: lgc.c,v 2.205 2015/03/25 13:42:19 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -83,8 +83,13 @@
#define markvalue(g,o) { checkconsistency(o); \
if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
#define markobject(g,t) \
{ if ((t) && iswhite(t)) reallymarkobject(g, obj2gco(t)); }
#define markobject(g,t) { if (iswhite(t)) reallymarkobject(g, obj2gco(t)); }
/*
** mark an object that can be NULL (either because it is really optional,
** or it was stripped as debug info, or inside an uncompleted structure)
*/
#define markobjectN(g,t) { if (t) markobject(g,t); }
static void reallymarkobject (global_State *g, GCObject *o);
@@ -183,7 +188,8 @@ void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) {
void luaC_fix (lua_State *L, GCObject *o) {
global_State *g = G(L);
lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */
if (g->allgc != o)
return; /* if object is not 1st in 'allgc' list, it is in global short string table */
white2gray(o); /* they will be gray forever */
g->allgc = o->next; /* remove object from 'allgc' list */
o->next = g->fixedgc; /* link it to 'fixedgc' list */
@@ -226,15 +232,19 @@ static void reallymarkobject (global_State *g, GCObject *o) {
reentry:
white2gray(o);
switch (o->tt) {
case LUA_TSHRSTR:
case LUA_TSHRSTR: {
gray2black(o);
g->GCmemtrav += sizelstring(gco2ts(o)->shrlen);
break;
}
case LUA_TLNGSTR: {
gray2black(o);
g->GCmemtrav += sizestring(gco2ts(o));
g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen);
break;
}
case LUA_TUSERDATA: {
TValue uvalue;
markobject(g, gco2u(o)->metatable); /* mark its metatable */
markobjectN(g, gco2u(o)->metatable); /* mark its metatable */
gray2black(o);
g->GCmemtrav += sizeudata(gco2u(o));
getuservalue(g->mainthread, gco2u(o), &uvalue);
@@ -275,7 +285,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
static void markmt (global_State *g) {
int i;
for (i=0; i < LUA_NUMTAGS; i++)
markobject(g, g->mt[i]);
markobjectN(g, g->mt[i]);
}
@@ -437,7 +447,7 @@ static void traversestrongtable (global_State *g, Table *h) {
static lu_mem traversetable (global_State *g, Table *h) {
const char *weakkey, *weakvalue;
const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
markobject(g, h->metatable);
markobjectN(g, h->metatable);
if (mode && ttisstring(mode) && /* is there a weak mode? */
((weakkey = strchr(svalue(mode), 'k')),
(weakvalue = strchr(svalue(mode), 'v')),
@@ -460,17 +470,22 @@ static int marksharedproto (global_State *g, SharedProto *f) {
int i;
if (g != f->l_G)
return 0;
markobject(g, f->source);
markobjectN(g, f->source);
for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */
markobject(g, f->upvalues[i].name);
markobjectN(g, f->upvalues[i].name);
for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */
markobject(g, f->locvars[i].varname);
markobjectN(g, f->locvars[i].varname);
return sizeof(Instruction) * f->sizecode +
sizeof(int) * f->sizelineinfo +
sizeof(LocVar) * f->sizelocvars +
sizeof(Upvaldesc) * f->sizeupvalues;
}
/*
** Traverse a prototype. (While a prototype is being build, its
** arrays can be larger than needed; the extra slots are filled with
** NULL, so the use of 'markobjectN')
*/
static int traverseproto (global_State *g, Proto *f) {
int i;
if (f->cache && iswhite(f->cache))
@@ -478,7 +493,7 @@ static int traverseproto (global_State *g, Proto *f) {
for (i = 0; i < f->sp->sizek; i++) /* mark literals */
markvalue(g, &f->k[i]);
for (i = 0; i < f->sp->sizep; i++) /* mark nested protos */
markobject(g, f->p[i]);
markobjectN(g, f->p[i]);
return sizeof(Proto) + sizeof(Proto *) * f->sp->sizep +
sizeof(TValue) * f->sp->sizek +
marksharedproto(g, f->sp);
@@ -500,7 +515,7 @@ static lu_mem traverseCclosure (global_State *g, CClosure *cl) {
*/
static lu_mem traverseLclosure (global_State *g, LClosure *cl) {
int i;
markobject(g, cl->p); /* mark its prototype */
markobjectN(g, cl->p); /* mark its prototype */
for (i = 0; i < cl->nupvalues; i++) { /* mark its upvalues */
UpVal *uv = cl->upvals[i];
if (uv != NULL) {
@@ -695,9 +710,10 @@ static void freeobj (lua_State *L, GCObject *o) {
case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break;
case LUA_TSHRSTR:
luaS_remove(L, gco2ts(o)); /* remove it from hash table */
/* go through */
luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen));
break;
case LUA_TLNGSTR: {
luaM_freemem(L, o, sizestring(gco2ts(o)));
luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen));
break;
}
default: lua_assert(0);
@@ -1008,6 +1024,7 @@ static l_mem atomic (lua_State *L) {
/* clear values from resurrected weak tables */
clearvalues(g, g->weak, origweak);
clearvalues(g, g->allweak, origall);
luaS_clearcache(g);
g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
work += g->GCmemtrav; /* complete counting */
return work; /* estimate of memory marked by 'atomic' */

View File

@@ -1,5 +1,5 @@
/*
** $Id: liolib.c,v 2.142 2015/01/02 12:50:28 roberto Exp $
** $Id: liolib.c,v 2.144 2015/04/03 18:41:57 roberto Exp $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
@@ -410,12 +410,6 @@ static int readdigits (RN *rn, int hex) {
}
/* access to locale "radix character" (decimal point) */
#if !defined(l_getlocaledecpoint)
#define l_getlocaledecpoint() (localeconv()->decimal_point[0])
#endif
/*
** Read a number: first reads a valid prefix of a numeral into a buffer.
** Then it calls 'lua_stringtonumber' to check whether the format is
@@ -425,9 +419,10 @@ static int read_number (lua_State *L, FILE *f) {
RN rn;
int count = 0;
int hex = 0;
char decp[2] = ".";
char decp[2];
rn.f = f; rn.n = 0;
decp[0] = l_getlocaledecpoint(); /* get decimal point from locale */
decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */
decp[1] = '\0';
l_lockfile(rn.f);
do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */
test2(&rn, "-+"); /* optional signal */
@@ -457,7 +452,7 @@ static int read_number (lua_State *L, FILE *f) {
static int test_eof (lua_State *L, FILE *f) {
int c = getc(f);
ungetc(c, f); /* no-op when c == EOF */
lua_pushlstring(L, NULL, 0);
lua_pushliteral(L, "");
return (c != EOF);
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: llex.c,v 2.89 2014/11/14 16:06:09 roberto Exp $
** $Id: llex.c,v 2.93 2015/05/22 17:45:56 roberto Exp $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
@@ -16,6 +16,7 @@
#include "lua.h"
#include "lctype.h"
#include "ldebug.h"
#include "ldo.h"
#include "lgc.h"
#include "llex.h"
@@ -68,7 +69,7 @@ static void save (LexState *ls, int c) {
void luaX_init (lua_State *L) {
int i;
TString *e = luaS_new(L, LUA_ENV); /* create env name */
TString *e = luaS_newliteral(L, LUA_ENV); /* create env name */
luaC_fix(L, obj2gco(e)); /* never collect this name */
for (i=0; i<NUM_RESERVED; i++) {
TString *ts = luaS_new(L, luaX_tokens[i]);
@@ -106,9 +107,7 @@ static const char *txtToken (LexState *ls, int token) {
static l_noret lexerror (LexState *ls, const char *msg, int token) {
char buff[LUA_IDSIZE];
luaO_chunkid(buff, getstr(ls->source), LUA_IDSIZE);
msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg);
msg = luaG_addinfo(ls->L, msg, ls->source, ls->linenumber);
if (token)
luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token));
luaD_throw(ls->L, LUA_ERRSYNTAX);
@@ -172,7 +171,7 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source,
ls->linenumber = 1;
ls->lastline = 1;
ls->source = source;
ls->envn = luaS_new(L, LUA_ENV); /* get env name */
ls->envn = luaS_newliteral(L, LUA_ENV); /* get env name */
luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */
}
@@ -221,11 +220,6 @@ static void buffreplace (LexState *ls, char from, char to) {
}
#if !defined(l_getlocaledecpoint)
#define l_getlocaledecpoint() (localeconv()->decimal_point[0])
#endif
#define buff2num(b,o) (luaO_str2num(luaZ_buffer(b), o) != 0)
/*
@@ -234,7 +228,7 @@ static void buffreplace (LexState *ls, char from, char to) {
*/
static void trydecpoint (LexState *ls, TValue *o) {
char old = ls->decpoint;
ls->decpoint = l_getlocaledecpoint();
ls->decpoint = lua_getlocaledecpoint();
buffreplace(ls, old, ls->decpoint); /* try new decimal separator */
if (!buff2num(ls->buff, o)) {
/* format error with correct decimal point: no more options */
@@ -283,8 +277,9 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) {
/*
** skip a sequence '[=*[' or ']=*]' and return its number of '='s or
** -1 if sequence is malformed
** skip a sequence '[=*[' or ']=*]'; if sequence is wellformed, return
** its number of '='s; otherwise, return a negative number (-1 iff there
** are no '='s after initial bracket)
*/
static int skip_sep (LexState *ls) {
int count = 0;
@@ -501,8 +496,9 @@ static int llex (LexState *ls, SemInfo *seminfo) {
read_long_string(ls, seminfo, sep);
return TK_STRING;
}
else if (sep == -1) return '[';
else lexerror(ls, "invalid long string delimiter", TK_STRING);
else if (sep != -1) /* '[=...' missing second bracket */
lexerror(ls, "invalid long string delimiter", TK_STRING);
return '[';
}
case '=': {
next(ls);

View File

@@ -1,5 +1,5 @@
/*
** $Id: llimits.h,v 1.125 2014/12/19 13:30:23 roberto Exp $
** $Id: llimits.h,v 1.135 2015/06/09 14:21:00 roberto Exp $
** Limits, basic types, and some other 'installation-dependent' definitions
** See Copyright Notice in lua.h
*/
@@ -52,11 +52,11 @@ typedef unsigned char lu_byte;
/*
** conversion of pointer to integer:
** conversion of pointer to unsigned integer:
** this is for hashing only; there is no problem if the integer
** cannot hold the whole pointer value
*/
#define point2int(p) ((unsigned int)((size_t)(p) & UINT_MAX))
#define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX))
@@ -88,22 +88,20 @@ typedef LUAI_UACINT l_uacInt;
/*
** assertion for checking API calls
*/
#if defined(LUA_USE_APICHECK)
#include <assert.h>
#define luai_apicheck(e) assert(e)
#else
#define luai_apicheck(e) lua_assert(e)
#if !defined(luai_apicheck)
#define luai_apicheck(l,e) lua_assert(e)
#endif
#define api_check(e,msg) luai_apicheck((e) && msg)
#define api_check(l,e,msg) luai_apicheck(l,(e) && msg)
/* macro to avoid warnings about unused variables */
#if !defined(UNUSED)
#define UNUSED(x) ((void)(x)) /* to avoid warnings */
#define UNUSED(x) ((void)(x))
#endif
/* type casts (a macro highlights casts in the code) */
#define cast(t, exp) ((t)(exp))
#define cast_void(i) cast(void, (i))
@@ -149,11 +147,6 @@ typedef LUAI_UACINT l_uacInt;
#define LUAI_MAXCCALLS 200
#endif
/*
** maximum number of upvalues in a closure (both C and Lua). (Value
** must fit in an unsigned char.)
*/
#define MAXUPVAL UCHAR_MAX
/*
@@ -168,10 +161,33 @@ typedef unsigned long Instruction;
/*
** Maximum length for short strings, that is, strings that are
** internalized. (Cannot be smaller than reserved words or tags for
** metamethods, as these strings must be internalized;
** #("function") = 8, #("__newindex") = 10.)
*/
#if !defined(LUAI_MAXSHORTLEN)
#define LUAI_MAXSHORTLEN 40
#endif
/* minimum size for the string table (must be power of 2) */
/*
** Initial size for the string table (must be power of 2).
** The Lua core alone registers ~50 strings (reserved words +
** metaevent keys + a few others). Libraries would typically add
** a few dozens more.
*/
#if !defined(MINSTRTABSIZE)
#define MINSTRTABSIZE 64 /* minimum size for "predefined" strings */
#define MINSTRTABSIZE 128
#endif
/*
** Size of cache for strings in the API (better be a prime)
*/
#if !defined(STRCACHE_SIZE)
#define STRCACHE_SIZE 127
#endif
@@ -181,11 +197,19 @@ typedef unsigned long Instruction;
#endif
/*
** macros that are executed whenether program enters the Lua core
** ('lua_lock') and leaves the core ('lua_unlock')
*/
#if !defined(lua_lock)
#define lua_lock(L) ((void) 0)
#define lua_unlock(L) ((void) 0)
#endif
/*
** macro executed during Lua functions at points where the
** function can yield.
*/
#if !defined(luai_threadyield)
#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);}
#endif
@@ -222,6 +246,53 @@ typedef unsigned long Instruction;
/*
** The luai_num* macros define the primitive operations over numbers.
*/
/* floor division (defined as 'floor(a/b)') */
#if !defined(luai_numidiv)
#define luai_numidiv(L,a,b) ((void)L, l_floor(luai_numdiv(L,a,b)))
#endif
/* float division */
#if !defined(luai_numdiv)
#define luai_numdiv(L,a,b) ((a)/(b))
#endif
/*
** modulo: defined as 'a - floor(a/b)*b'; this definition gives NaN when
** 'b' is huge, but the result should be 'a'. 'fmod' gives the result of
** 'a - trunc(a/b)*b', and therefore must be corrected when 'trunc(a/b)
** ~= floor(a/b)'. That happens when the division has a non-integer
** negative result, which is equivalent to the test below.
*/
#if !defined(luai_nummod)
#define luai_nummod(L,a,b,m) \
{ (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); }
#endif
/* exponentiation */
#if !defined(luai_numpow)
#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b))
#endif
/* the others are quite standard operations */
#if !defined(luai_numadd)
#define luai_numadd(L,a,b) ((a)+(b))
#define luai_numsub(L,a,b) ((a)-(b))
#define luai_nummul(L,a,b) ((a)*(b))
#define luai_numunm(L,a) (-(a))
#define luai_numeq(a,b) ((a)==(b))
#define luai_numlt(a,b) ((a)<(b))
#define luai_numle(a,b) ((a)<=(b))
#define luai_numisnan(a) (!luai_numeq((a), (a)))
#endif
/*
** macro to control inclusion of some hard tests on stack reallocation
*/

View File

@@ -1,5 +1,5 @@
/*
** $Id: lmathlib.c,v 1.114 2014/12/27 20:32:26 roberto Exp $
** $Id: lmathlib.c,v 1.115 2015/03/12 14:04:04 roberto Exp $
** Standard mathematical library
** See Copyright Notice in lua.h
*/
@@ -183,6 +183,9 @@ static int math_log (lua_State *L) {
res = l_mathop(log)(x);
else {
lua_Number base = luaL_checknumber(L, 2);
#if !defined(LUA_USE_C89)
if (base == 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);
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lmem.c,v 1.89 2014/11/02 19:33:33 roberto Exp $
** $Id: lmem.c,v 1.91 2015/03/06 19:45:54 roberto Exp $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
@@ -85,10 +85,11 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
#endif
newblock = (*g->frealloc)(g->ud, block, osize, nsize);
if (newblock == NULL && nsize > 0) {
api_check( nsize > realosize,
"realloc cannot fail when shrinking a block");
luaC_fullgc(L, 1); /* try to free some memory... */
newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */
lua_assert(nsize > realosize); /* cannot fail when shrinking a block */
if (g->version) { /* is state fully built? */
luaC_fullgc(L, 1); /* try to free some memory... */
newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */
}
if (newblock == NULL)
luaD_throw(L, LUA_ERRMEM);
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: loadlib.c,v 1.124 2015/01/05 13:51:39 roberto Exp $
** $Id: loadlib.c,v 1.126 2015/02/16 13:14:33 roberto Exp $
** Dynamic library loader for Lua
** See Copyright Notice in lua.h
**
@@ -14,6 +14,7 @@
#include "lprefix.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -136,8 +137,8 @@ static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym);
#include <dlfcn.h>
/*
** Macro to covert pointer to void* to pointer to function. This cast
** is undefined according to ISO C, but POSIX assumes that it must work.
** Macro to convert pointer-to-void* to pointer-to-function. This cast
** is undefined according to ISO C, but POSIX assumes that it works.
** (The '__extension__' in gnu compilers is only to avoid warnings.)
*/
#if defined(__GNUC__)

View File

@@ -1,5 +1,5 @@
/*
** $Id: lobject.c,v 2.101 2014/12/26 14:43:45 roberto Exp $
** $Id: lobject.c,v 2.104 2015/04/11 18:30:08 roberto Exp $
** Some generic functions over Lua objects
** See Copyright Notice in lua.h
*/
@@ -10,6 +10,8 @@
#include "lprefix.h"
#include <locale.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -39,8 +41,12 @@ LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT};
int luaO_int2fb (unsigned int x) {
int e = 0; /* exponent */
if (x < 8) return x;
while (x >= 0x10) {
x = (x+1) >> 1;
while (x >= (8 << 4)) { /* coarse steps */
x = (x + 0xf) >> 4; /* x = ceil(x / 16) */
e += 4;
}
while (x >= (8 << 1)) { /* fine steps */
x = (x + 1) >> 1; /* x = ceil(x / 2) */
e++;
}
return ((e+1) << 3) | (cast_int(x) - 8);
@@ -55,8 +61,11 @@ int luaO_fb2int (int x) {
}
/*
** Computes ceil(log2(x))
*/
int luaO_ceillog2 (unsigned int x) {
static const lu_byte log_2[256] = {
static const lu_byte log_2[256] = { /* log_2[i] = ceil(log2(i - 1)) */
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
@@ -149,13 +158,13 @@ void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2,
}
/* could not perform raw operation; try metamethod */
lua_assert(L != NULL); /* should not fail when folding (compile time) */
luaT_trybinTM(L, p1, p2, res, cast(TMS, op - LUA_OPADD + TM_ADD));
luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD));
}
int luaO_hexavalue (int c) {
if (lisdigit(c)) return c - '0';
else return ltolower(c) - 'a' + 10;
else return (ltolower(c) - 'a') + 10;
}
@@ -172,9 +181,8 @@ static int isneg (const char **s) {
** Lua's implementation for 'lua_strx2number'
** ===================================================================
*/
#if !defined(lua_strx2number)
#include <math.h>
#if !defined(lua_strx2number)
/* maximum number of significant digits to read (to avoid overflows
even with single floats) */
@@ -185,21 +193,22 @@ static int isneg (const char **s) {
** C99 specification for 'strtod'
*/
static lua_Number lua_strx2number (const char *s, char **endptr) {
int dot = lua_getlocaledecpoint();
lua_Number r = 0.0; /* result (accumulator) */
int sigdig = 0; /* number of significant digits */
int nosigdig = 0; /* number of non-significant digits */
int e = 0; /* exponent correction */
int neg; /* 1 if number is negative */
int dot = 0; /* true after seen a dot */
int hasdot = 0; /* true after seen a dot */
*endptr = cast(char *, s); /* nothing is valid yet */
while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */
neg = isneg(&s); /* check signal */
if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */
return 0.0; /* invalid format (no '0x') */
for (s += 2; ; s++) { /* skip '0x' and read numeral */
if (*s == '.') {
if (dot) break; /* second dot? stop loop */
else dot = 1;
if (*s == dot) {
if (hasdot) break; /* second dot? stop loop */
else hasdot = 1;
}
else if (lisxdigit(cast_uchar(*s))) {
if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */
@@ -207,7 +216,7 @@ static lua_Number lua_strx2number (const char *s, char **endptr) {
else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */
r = (r * cast_num(16.0)) + luaO_hexavalue(*s);
else e++; /* too many digits; ignore, but still count for exponent */
if (dot) e--; /* decimal digit? correct exponent */
if (hasdot) e--; /* decimal digit? correct exponent */
}
else break; /* neither a dot nor a digit */
}
@@ -244,7 +253,7 @@ static const char *l_str2d (const char *s, lua_Number *result) {
*result = lua_strx2number(s, &endptr);
else
*result = lua_str2number(s, &endptr);
if (endptr == s) return 0; /* nothing recognized */
if (endptr == s) return NULL; /* nothing recognized */
while (lisspace(cast_uchar(*endptr))) endptr++;
return (*endptr == '\0' ? endptr : NULL); /* OK if no trailing characters */
}
@@ -290,7 +299,7 @@ size_t luaO_str2num (const char *s, TValue *o) {
}
else
return 0; /* conversion failed */
return (e - s + 1); /* success; return string size */
return (e - s) + 1; /* success; return string size */
}
@@ -329,7 +338,7 @@ void luaO_tostring (lua_State *L, StkId obj) {
len = lua_number2str(buff, fltvalue(obj));
#if !defined(LUA_COMPAT_FLOATSTRING)
if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */
buff[len++] = '.';
buff[len++] = lua_getlocaledecpoint();
buff[len++] = '0'; /* adds '.0' to result */
}
#endif

View File

@@ -1,5 +1,5 @@
/*
** $Id: lobject.h,v 2.106 2015/01/05 13:52:37 roberto Exp $
** $Id: lobject.h,v 2.111 2015/06/09 14:21:42 roberto Exp $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
@@ -35,8 +35,6 @@
** bit 6: whether value is collectable
*/
#define VARBITS (3 << 4)
/*
** LUA_TFUNCTION variants:
@@ -190,9 +188,15 @@ typedef struct lua_TValue TValue;
#define setfltvalue(obj,x) \
{ TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_TNUMFLT); }
#define chgfltvalue(obj,x) \
{ TValue *io=(obj); lua_assert(ttisfloat(io)); val_(io).n=(x); }
#define setivalue(obj,x) \
{ TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_TNUMINT); }
#define chgivalue(obj,x) \
{ TValue *io=(obj); lua_assert(ttisinteger(io)); val_(io).i=(x); }
#define setnilvalue(obj) settt_(obj, LUA_TNIL)
#define setfvalue(obj,x) \
@@ -303,9 +307,12 @@ typedef TValue *StkId; /* index to stack elements */
typedef struct TString {
CommonHeader;
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
lu_byte shrlen; /* length for short strings */
unsigned int hash;
size_t len; /* number of characters in string */
struct TString *hnext; /* linked list for hash table */
union {
size_t lnglen; /* length for long strings */
struct TString *hnext; /* linked list for hash table */
} u;
} TString;
@@ -329,6 +336,12 @@ typedef union UTString {
/* get the actual string (array of bytes) from a Lua value */
#define svalue(o) getstr(tsvalue(o))
/* get string length from 'TString *s' */
#define tsslen(s) ((s)->tt == LUA_TSHRSTR ? (s)->shrlen : (s)->u.lnglen)
/* get string length from 'TValue *o' */
#define vslen(o) tsslen(tsvalue(o))
/*
** Header for userdata; memory area follows the end of this structure
@@ -361,13 +374,13 @@ typedef union UUdata {
#define setuservalue(L,u,o) \
{ const TValue *io=(o); Udata *iu = (u); \
iu->user_ = io->value_; iu->ttuv_ = io->tt_; \
iu->user_ = io->value_; iu->ttuv_ = rttype(io); \
checkliveness(G(L),io); }
#define getuservalue(L,u,o) \
{ TValue *io=(o); const Udata *iu = (u); \
io->value_ = iu->user_; io->tt_ = iu->ttuv_; \
io->value_ = iu->user_; settt_(io, iu->ttuv_); \
checkliveness(G(L),io); }
@@ -376,7 +389,7 @@ typedef union UUdata {
*/
typedef struct Upvaldesc {
TString *name; /* upvalue name (for debug information) */
lu_byte instack; /* whether it is in stack */
lu_byte instack; /* whether it is in stack (register) */
lu_byte idx; /* index of upvalue (in stack or in outer function's list) */
} Upvaldesc;
@@ -391,11 +404,10 @@ typedef struct LocVar {
int endpc; /* first point where variable is dead */
} LocVar;
typedef struct SharedProto {
lu_byte numparams; /* number of fixed parameters */
lu_byte is_vararg;
lu_byte maxstacksize; /* maximum stack used by this function */
lu_byte maxstacksize; /* number of registers needed by this function */
int sizeupvalues; /* size of 'upvalues' */
int sizek; /* size of 'k' */
int sizecode;
@@ -405,7 +417,7 @@ typedef struct SharedProto {
int linedefined;
int lastlinedefined;
void *l_G; /* global state belongs to */
Instruction *code;
Instruction *code; /* opcodes */
int *lineinfo; /* map from opcodes to source lines (debug information) */
LocVar *locvars; /* information about local variables (debug information) */
Upvaldesc *upvalues; /* upvalue information */
@@ -420,7 +432,7 @@ typedef struct Proto {
struct SharedProto *sp;
TValue *k; /* constants used by the function */
struct Proto **p; /* functions defined inside the function */
struct LClosure *cache; /* last created closure with this prototype */
struct LClosure *cache; /* last-created closure with this prototype */
GCObject *gclist;
} Proto;

View File

@@ -1,5 +1,5 @@
/*
** $Id: loslib.c,v 1.54 2014/12/26 14:46:07 roberto Exp $
** $Id: loslib.c,v 1.57 2015/04/10 17:41:04 roberto Exp $
** Standard Operating System library
** See Copyright Notice in lua.h
*/
@@ -22,10 +22,12 @@
#include "lualib.h"
#if !defined(LUA_STRFTIMEOPTIONS) /* { */
/*
** {==================================================================
** list of valid conversion specifiers for the 'strftime' function
** ===================================================================
*/
#if !defined(LUA_STRFTIMEOPTIONS) /* { */
#if defined(LUA_USE_C89)
#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" }
@@ -37,8 +39,14 @@
#endif
#endif /* } */
/* }================================================================== */
/*
** {==================================================================
** Configuration for time-related stuff
** ===================================================================
*/
#if !defined(l_time_t) /* { */
/*
@@ -51,15 +59,41 @@
#endif /* } */
#if !defined(lua_tmpnam) /* { */
#if !defined(l_gmtime) /* { */
/*
** By default, Lua uses tmpnam except when POSIX is available, where it
** uses mkstemp.
** By default, Lua uses gmtime/localtime, except when POSIX is available,
** where it uses gmtime_r/localtime_r
*/
#if defined(LUA_USE_POSIX) /* { */
#define l_gmtime(t,r) gmtime_r(t,r)
#define l_localtime(t,r) localtime_r(t,r)
#else /* }{ */
/* ISO C definitions */
#define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t))
#define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t))
#endif /* } */
#endif /* } */
/* }================================================================== */
/*
** {==================================================================
** Configuration for 'tmpnam':
** By default, Lua uses tmpnam except when POSIX is available, where
** it uses mkstemp.
** ===================================================================
*/
#if !defined(lua_tmpnam) /* { */
#if defined(LUA_USE_POSIX) /* { */
#include <unistd.h>
#define LUA_TMPNAMBUFSIZE 32
@@ -83,31 +117,10 @@
#endif /* } */
#endif /* } */
/* }================================================================== */
#if !defined(l_gmtime) /* { */
/*
** By default, Lua uses gmtime/localtime, except when POSIX is available,
** where it uses gmtime_r/localtime_r
*/
#if defined(LUA_USE_POSIX) /* { */
#define l_gmtime(t,r) gmtime_r(t,r)
#define l_localtime(t,r) localtime_r(t,r)
#else /* }{ */
/* ISO C definitions */
#define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t))
#define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t))
#endif /* } */
#endif /* } */
static int os_execute (lua_State *L) {
const char *cmd = luaL_optstring(L, 1, NULL);
@@ -287,7 +300,7 @@ static int os_time (lua_State *L) {
t = mktime(&ts);
}
if (t != (time_t)(l_timet)t)
luaL_error(L, "time result cannot be represented in this Lua instalation");
luaL_error(L, "time result cannot be represented in this Lua installation");
else if (t == (time_t)(-1))
lua_pushnil(L);
else
@@ -297,8 +310,9 @@ static int os_time (lua_State *L) {
static int os_difftime (lua_State *L) {
double res = difftime((l_checktime(L, 1)), (l_checktime(L, 2)));
lua_pushnumber(L, (lua_Number)res);
time_t t1 = l_checktime(L, 1);
time_t t2 = l_checktime(L, 2);
lua_pushnumber(L, (lua_Number)difftime(t1, t2));
return 1;
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lstate.c,v 2.127 2014/11/02 19:33:33 roberto Exp $
** $Id: lstate.c,v 2.128 2015/03/04 13:31:21 roberto Exp $
** Global State
** See Copyright Notice in lua.h
*/
@@ -37,9 +37,6 @@
#endif
#define MEMERRMSG "not enough memory"
/*
** a macro to help the creation of a unique random seed when a state is
** created; the seed is used to randomize hashes.
@@ -200,12 +197,9 @@ static void f_luaopen (lua_State *L, void *ud) {
UNUSED(ud);
stack_init(L, L); /* init stack */
init_registry(L, g);
luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
luaS_init(L);
luaT_init(L);
luaX_init(L);
/* pre-create memory-error message */
g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */
g->gcrunning = 1; /* allow gc */
g->version = lua_version(NULL);
luai_userstateopen(L);

View File

@@ -1,5 +1,5 @@
/*
** $Id: lstate.h,v 2.119 2014/10/30 18:53:28 roberto Exp $
** $Id: lstate.h,v 2.122 2015/06/01 16:34:37 roberto Exp $
** Global State
** See Copyright Notice in lua.h
*/
@@ -94,6 +94,7 @@ typedef struct CallInfo {
#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */
#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 isLua(ci) ((ci)->callstatus & CIST_LUA)
@@ -140,6 +141,7 @@ typedef struct global_State {
TString *memerrmsg; /* memory-error message */
TString *tmname[TM_N]; /* array with tag-method names */
struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */
TString *strcache[STRCACHE_SIZE][1]; /* cache for strings in API */
} global_State;

View File

@@ -1,5 +1,5 @@
/*
** $Id: lstring.c,v 2.45 2014/11/02 19:19:04 roberto Exp $
** $Id: lstring.c,v 2.49 2015/06/01 16:34:37 roberto Exp $
** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -22,6 +22,8 @@
#include "lstring.h"
#define MEMERRMSG "not enough memory"
/*
** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to
@@ -36,10 +38,10 @@
** equality for long strings
*/
int luaS_eqlngstr (TString *a, TString *b) {
size_t len = a->len;
size_t len = a->u.lnglen;
lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR);
return (a == b) || /* same instance or... */
((len == b->len) && /* equal length and ... */
((len == b->u.lnglen) && /* equal length and ... */
(memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */
}
@@ -69,9 +71,9 @@ void luaS_resize (lua_State *L, int newsize) {
TString *p = tb->hash[i];
tb->hash[i] = NULL;
while (p) { /* for each node in the list */
TString *hnext = p->hnext; /* save next */
TString *hnext = p->u.hnext; /* save next */
unsigned int h = lmod(p->hash, newsize); /* new position */
p->hnext = tb->hash[h]; /* chain it */
p->u.hnext = tb->hash[h]; /* chain it */
tb->hash[h] = p;
p = hnext;
}
@@ -85,6 +87,34 @@ void luaS_resize (lua_State *L, int newsize) {
}
/*
** Clear API string cache. (Entries cannot be empty, so fill them with
** a non-collectable string.)
*/
void luaS_clearcache (global_State *g) {
int i;
for (i = 0; i < STRCACHE_SIZE; i++) {
if (iswhite(g->strcache[i][0])) /* will entry be collected? */
g->strcache[i][0] = g->memerrmsg; /* replace it with something fixed */
}
}
/*
** Initialize the string table and the string cache
*/
void luaS_init (lua_State *L) {
global_State *g = G(L);
int i;
luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
/* pre-create memory-error message */
g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */
for (i = 0; i < STRCACHE_SIZE; i++) /* fill cache with valid strings */
g->strcache[i][0] = g->memerrmsg;
}
/*
** creates a new string object
@@ -97,7 +127,6 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l,
totalsize = sizelstring(l);
o = luaC_newobj(L, tag, totalsize);
ts = gco2ts(o);
ts->len = l;
ts->hash = h;
ts->extra = 0;
memcpy(getaddrstr(ts), str, l * sizeof(char));
@@ -110,8 +139,8 @@ void luaS_remove (lua_State *L, TString *ts) {
stringtable *tb = &G(L)->strt;
TString **p = &tb->hash[lmod(ts->hash, tb->size)];
while (*p != ts) /* find previous element */
p = &(*p)->hnext;
*p = (*p)->hnext; /* remove element from its list */
p = &(*p)->u.hnext;
*p = (*p)->u.hnext; /* remove element from its list */
tb->nuse--;
}
@@ -119,13 +148,12 @@ void luaS_remove (lua_State *L, TString *ts) {
/*
** checks whether short string exists and reuses it or creates a new one
*/
static TString *internshrstr (lua_State *L, const char *str, size_t l) {
static TString *queryshrstr (lua_State *L, const char *str, size_t l, unsigned int h) {
TString *ts;
global_State *g = G(L);
unsigned int h = luaS_hash(str, l, g->seed);
TString **list = &g->strt.hash[lmod(h, g->strt.size)];
for (ts = *list; ts != NULL; ts = ts->hnext) {
if (l == ts->len &&
for (ts = *list; ts != NULL; ts = ts->u.hnext) {
if (l == ts->shrlen &&
(memcmp(str, getstr(ts), l * sizeof(char)) == 0)) {
/* found! */
if (isdead(g, ts)) /* dead (but not collected yet)? */
@@ -133,17 +161,26 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
return ts;
}
}
return NULL;
}
static TString *addshrstr (lua_State *L, const char *str, size_t l, unsigned int h) {
TString *ts;
global_State *g = G(L);
TString **list = &g->strt.hash[lmod(h, g->strt.size)];
if (g->strt.nuse >= g->strt.size && g->strt.size <= MAX_INT/2) {
luaS_resize(L, g->strt.size * 2);
list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */
}
ts = createstrobj(L, str, l, LUA_TSHRSTR, h);
ts->hnext = *list;
ts->shrlen = cast_byte(l);
ts->u.hnext = *list;
*list = ts;
g->strt.nuse++;
return ts;
}
static TString *internshrstr (lua_State *L, const char *str, size_t l);
/*
** new string (with explicit length)
@@ -152,18 +189,32 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
if (l <= LUAI_MAXSHORTLEN) /* short string? */
return internshrstr(L, str, l);
else {
TString *ts;
if (l + 1 > (MAX_SIZE - sizeof(TString))/sizeof(char))
luaM_toobig(L);
return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed);
ts = createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed);
ts->u.lnglen = l;
return ts;
}
}
/*
** new zero-terminated string
** Create or reuse a zero-terminated string, first checking in the
** cache (using the string address as a key). The cache can contain
** only zero-terminated strings, so it is safe to use 'strcmp' to
** check hits.
*/
TString *luaS_new (lua_State *L, const char *str) {
return luaS_newlstr(L, str, strlen(str));
unsigned int i = point2uint(str) % STRCACHE_SIZE; /* hash */
TString **p = G(L)->strcache[i];
if (strcmp(str, getstr(p[0])) == 0) /* hit? */
return p[0]; /* that it is */
else { /* normal route */
TString *s = luaS_newlstr(L, str, strlen(str));
p[0] = s;
return s;
}
}
@@ -180,3 +231,213 @@ Udata *luaS_newudata (lua_State *L, size_t s) {
return u;
}
/*
* global shared table
*/
#include "rwlock.h"
#include "atomic.h"
#include <stdlib.h>
#define SHRSTR_SLOT 0x10000
#define HASH_NODE(h) ((h) % SHRSTR_SLOT)
struct shrmap_slot {
struct rwlock lock;
TString *str;
};
struct shrmap {
struct shrmap_slot h[SHRSTR_SLOT];
int n;
};
static struct shrmap SSM;
LUA_API void
luaS_initshr() {
struct shrmap * s = &SSM;
int i;
for (i=0;i<SHRSTR_SLOT;i++) {
rwlock_init(&s->h[i].lock);
}
}
LUA_API void
luaS_exitshr() {
int i;
for (i=0;i<SHRSTR_SLOT;i++) {
TString *str = SSM.h[i].str;
while (str) {
TString * next = str->u.hnext;
free(str);
str = next;
}
}
}
static TString *
query_string(unsigned int h, const char *str, lu_byte l) {
struct shrmap_slot *s = &SSM.h[HASH_NODE(h)];
rwlock_rlock(&s->lock);
TString *ts = s->str;
while (ts) {
if (ts->hash == h &&
ts->shrlen == l &&
memcmp(str, ts+1, l) == 0) {
break;
}
ts = ts->u.hnext;
}
rwlock_runlock(&s->lock);
return ts;
}
static TString *
query_ptr(TString *t) {
unsigned int h = t->hash;
struct shrmap_slot *s = &SSM.h[HASH_NODE(h)];
rwlock_rlock(&s->lock);
TString *ts = s->str;
while (ts) {
if (ts == t)
break;
ts = ts->u.hnext;
}
rwlock_runlock(&s->lock);
return ts;
}
static TString *
new_string(unsigned int h, const char *str, lu_byte l) {
size_t sz = sizelstring(l);
TString *ts = malloc(sz);
memset(ts, 0, sz);
ts->tt = LUA_TSHRSTR;
ts->hash = h;
ts->shrlen = l;
memcpy(ts+1, str, l);
return ts;
}
static TString *
add_string(unsigned int h, const char *str, lu_byte l) {
TString * tmp = new_string(h, str, l);
struct shrmap_slot *s = &SSM.h[HASH_NODE(h)];
rwlock_wlock(&s->lock);
TString *ts = s->str;
while (ts) {
if (ts->hash == h &&
ts->shrlen == l &&
memcmp(str, ts+1, l) == 0) {
break;
}
ts = ts->u.hnext;
}
if (ts == NULL) {
ts = tmp;
ts->u.hnext = s->str;
s->str = ts;
tmp = NULL;
}
rwlock_wunlock(&s->lock);
if (tmp) {
// string is create by other thread, so free tmp
free(tmp);
}
return ts;
}
static TString *
internshrstr (lua_State *L, const char *str, size_t l) {
TString *ts;
global_State *g = G(L);
unsigned int h = luaS_hash(str, l, g->seed);
unsigned int h0;
// lookup global state of this L first
ts = queryshrstr (L, str, l, h);
if (ts)
return ts;
// lookup SSM again
h0 = luaS_hash(str, l, 0);
ts = query_string(h0, str, l);
if (ts)
return ts;
// If SSM.n greate than 0, add it to SSM
if (SSM.n > 0) {
ATOM_DEC(&SSM.n);
return add_string(h0, str, l);
}
// Else add it to global state (local)
return addshrstr (L, str, l, h);
}
LUA_API void
luaS_expandshr(int n) {
ATOM_ADD(&SSM.n, n);
}
LUAI_FUNC TString *
luaS_clonestring(lua_State *L, TString *ts) {
unsigned int h;
int l;
const char * str = getaddrstr(ts);
global_State *g = G(L);
TString *result;
if (ts->tt == LUA_TLNGSTR)
return luaS_newlstr(L, str, ts->u.lnglen);
// look up global state of this L first
l = ts->shrlen;
h = luaS_hash(str, l, g->seed);
result = queryshrstr (L, str, l, h);
if (result)
return result;
// look up SSM by ptr
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);
return add_string(h, str, l);
}
struct slotinfo {
int len;
int size;
};
static void
getslot(struct shrmap_slot *s, struct slotinfo *info) {
memset(info, 0, sizeof(*info));
rwlock_rlock(&s->lock);
TString *ts = s->str;
while (ts) {
++info->len;
info->size += sizelstring(ts->shrlen);
ts = ts->u.hnext;
}
rwlock_runlock(&s->lock);
}
LUA_API int
luaS_shrinfo(lua_State *L) {
struct slotinfo total;
struct slotinfo tmp;
memset(&total, 0, sizeof(total));
int i;
int len = 0;
for (i=0;i<SHRSTR_SLOT;i++) {
struct shrmap_slot *s = &SSM.h[i];
getslot(s, &tmp);
len += tmp.len;
if (tmp.len > total.len) {
total.len = tmp.len;
}
total.size += tmp.size;
}
lua_pushinteger(L, len);
lua_pushinteger(L, total.size);
lua_pushinteger(L, total.len);
lua_pushinteger(L, SSM.n);
return 4;
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lstring.h,v 1.56 2014/07/18 14:46:47 roberto Exp $
** $Id: lstring.h,v 1.59 2015/03/25 13:42:19 roberto Exp $
** String table (keep all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -13,7 +13,6 @@
#define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char))
#define sizestring(s) sizelstring((s)->len)
#define sizeludata(l) (sizeof(union UUdata) + (l))
#define sizeudata(u) sizeludata((u)->len)
@@ -37,10 +36,19 @@
LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed);
LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
LUAI_FUNC void luaS_clearcache (global_State *g);
LUAI_FUNC void luaS_init (lua_State *L);
LUAI_FUNC void luaS_remove (lua_State *L, TString *ts);
LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s);
LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
LUAI_FUNC TString *luaS_new (lua_State *L, const char *str);
#define ENABLE_SHORT_STRING_TABLE
LUA_API void luaS_initshr();
LUA_API void luaS_exitshr();
LUA_API void luaS_expandshr(int n);
LUAI_FUNC TString *luaS_clonestring(lua_State *L, TString *);
LUA_API int luaS_shrinfo(lua_State *L);
#endif

View File

@@ -1,5 +1,5 @@
/*
** $Id: lstrlib.c,v 1.221 2014/12/11 14:03:07 roberto Exp $
** $Id: lstrlib.c,v 1.229 2015/05/20 17:39:23 roberto Exp $
** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h
*/
@@ -11,6 +11,7 @@
#include <ctype.h>
#include <float.h>
#include <limits.h>
#include <stddef.h>
#include <stdio.h>
@@ -70,7 +71,7 @@ static int str_sub (lua_State *L) {
if (start < 1) start = 1;
if (end > (lua_Integer)l) end = l;
if (start <= end)
lua_pushlstring(L, s + start - 1, (size_t)(end - start + 1));
lua_pushlstring(L, s + start - 1, (size_t)(end - start) + 1);
else lua_pushliteral(L, "");
return 1;
}
@@ -149,9 +150,9 @@ static int str_byte (lua_State *L) {
if (posi < 1) posi = 1;
if (pose > (lua_Integer)l) pose = l;
if (posi > pose) return 0; /* empty interval; return no values */
n = (int)(pose - posi + 1);
if (posi + n <= pose) /* arithmetic overflow? */
if (pose - posi >= INT_MAX) /* arithmetic overflow? */
return luaL_error(L, "string slice too long");
n = (int)(pose - posi) + 1;
luaL_checkstack(L, n, "string slice too long");
for (i=0; i<n; i++)
lua_pushinteger(L, uchar(s[posi+i-1]));
@@ -499,7 +500,7 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
}
case '+': /* 1 or more repetitions */
s++; /* 1 match already done */
/* go through */
/* FALLTHROUGH */
case '*': /* 0 or more repetitions */
s = max_expand(ms, s, p, ep);
break;
@@ -554,7 +555,7 @@ static void push_onecapture (MatchState *ms, int i, const char *s,
ptrdiff_t l = ms->capture[i].len;
if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
if (l == CAP_POSITION)
lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);
lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1);
else
lua_pushlstring(ms->L, ms->capture[i].init, l);
}
@@ -598,8 +599,8 @@ static int str_find_aux (lua_State *L, int find) {
/* do a plain search */
const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp);
if (s2) {
lua_pushinteger(L, s2 - s + 1);
lua_pushinteger(L, s2 - s + lp);
lua_pushinteger(L, (s2 - s) + 1);
lua_pushinteger(L, (s2 - s) + lp);
return 2;
}
}
@@ -621,7 +622,7 @@ static int str_find_aux (lua_State *L, int find) {
lua_assert(ms.matchdepth == MAXCCALLS);
if ((res=match(&ms, s1, p)) != NULL) {
if (find) {
lua_pushinteger(L, s1 - s + 1); /* start */
lua_pushinteger(L, (s1 - s) + 1); /* start */
lua_pushinteger(L, res - s); /* end */
return push_captures(&ms, NULL, 0) + 2;
}
@@ -797,17 +798,100 @@ static int str_gsub (lua_State *L) {
** =======================================================
*/
/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
#define MAX_ITEM 512
#if !defined(lua_number2strx) /* { */
/*
** Hexadecimal floating-point formatter
*/
#include <locale.h>
#include <math.h>
#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char))
/*
** Number of bits that goes into the first digit. It can be any value
** between 1 and 4; the following definition tries to align the number
** to nibble boundaries by making what is left after that first digit a
** multiple of 4.
*/
#define L_NBFD ((l_mathlim(MANT_DIG) - 1)%4 + 1)
/*
** Add integer part of 'x' to buffer and return new 'x'
*/
static lua_Number adddigit (char *buff, int n, lua_Number x) {
lua_Number dd = l_mathop(floor)(x); /* get integer part from 'x' */
int d = (int)dd;
buff[n] = (d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */
return x - dd; /* return what is left */
}
static int num2straux (char *buff, lua_Number x) {
if (x != x || x == HUGE_VAL || x == -HUGE_VAL) /* inf or NaN? */
return sprintf(buff, LUA_NUMBER_FMT, x); /* equal to '%g' */
else if (x == 0) { /* can be -0... */
sprintf(buff, LUA_NUMBER_FMT, x);
strcat(buff, "x0p+0"); /* reuses '0/-0' from 'sprintf'... */
return strlen(buff);
}
else {
int e;
lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */
int n = 0; /* character count */
if (m < 0) { /* is number negative? */
buff[n++] = '-'; /* add signal */
m = -m; /* make it positive */
}
buff[n++] = '0'; buff[n++] = 'x'; /* add "0x" */
m = adddigit(buff, n++, m * (1 << L_NBFD)); /* add first digit */
e -= L_NBFD; /* this digit goes before the radix point */
if (m > 0) { /* more digits? */
buff[n++] = lua_getlocaledecpoint(); /* add radix point */
do { /* add as many digits as needed */
m = adddigit(buff, n++, m * 16);
} while (m > 0);
}
n += sprintf(buff + n, "p%+d", e); /* add exponent */
return n;
}
}
static int lua_number2strx (lua_State *L, char *buff, const char *fmt,
lua_Number x) {
int n = num2straux(buff, x);
if (fmt[SIZELENMOD] == 'A') {
int i;
for (i = 0; i < n; i++)
buff[i] = toupper(uchar(buff[i]));
}
else if (fmt[SIZELENMOD] != 'a')
luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented");
return n;
}
#endif /* } */
/*
** Maximum size of each formatted item. This maximum size is produced
** by format('%.99f', minfloat), and is equal to 99 + 2 ('-' and '.') +
** number of decimal digits to represent minfloat.
*/
#define MAX_ITEM (120 + l_mathlim(MAX_10_EXP))
/* valid flags in a format specification */
#define FLAGS "-+ #0"
/*
** maximum size of each format specification (such as "%-099.99d")
** (+2 for length modifiers; +10 accounts for %99.99x plus margin of error)
*/
#define MAX_FORMAT (sizeof(FLAGS) + 2 + 10)
#define MAX_FORMAT 32
static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
@@ -849,8 +933,8 @@ static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
if (isdigit(uchar(*p)))
luaL_error(L, "invalid format (width or precision too long)");
*(form++) = '%';
memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char));
form += p - strfrmt + 1;
memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char));
form += (p - strfrmt) + 1;
*form = '\0';
return p;
}
@@ -901,9 +985,10 @@ static int str_format (lua_State *L) {
nb = sprintf(buff, form, n);
break;
}
#if defined(LUA_USE_AFORMAT)
case 'a': case 'A':
#endif
addlenmod(form, LUA_NUMBER_FRMLEN);
nb = lua_number2strx(L, buff, form, luaL_checknumber(L, arg));
break;
case 'e': case 'E': case 'f':
case 'g': case 'G': {
addlenmod(form, LUA_NUMBER_FRMLEN);
@@ -921,13 +1006,12 @@ static int str_format (lua_State *L) {
/* no precision and string is too long to be formatted;
keep original string */
luaL_addvalue(&b);
break;
}
else {
nb = sprintf(buff, form, s);
lua_pop(L, 1); /* remove result from 'luaL_tolstring' */
break;
}
break;
}
default: { /* also treat cases 'pnLlh' */
return luaL_error(L, "invalid option '%%%c' to 'format'",
@@ -1249,7 +1333,7 @@ static int str_pack (lua_State *L) {
totalsize += len + 1;
break;
}
case Kpadding: luaL_addchar(&b, LUA_PACKPADBYTE); /* go through */
case Kpadding: luaL_addchar(&b, LUA_PACKPADBYTE); /* FALLTHROUGH */
case Kpaddalign: case Knop:
arg--; /* undo increment */
break;

View File

@@ -1,5 +1,5 @@
/*
** $Id: ltable.c,v 2.100 2015/01/05 13:52:37 roberto Exp $
** $Id: ltable.c,v 2.111 2015/06/09 14:21:13 roberto Exp $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -14,8 +14,8 @@
** Implementation of tables (aka arrays, objects, or hash tables).
** Tables keep its elements in two parts: an array part and a hash part.
** Non-negative integer keys are all candidates to be kept in the array
** part. The actual size of the array is the largest 'n' such that at
** least half the slots between 0 and n are in use.
** part. The actual size of the array is the largest 'n' such that
** more than half the slots between 1 and n are in use.
** Hash uses a mix of chained scatter table with Brent's variation.
** A main invariant of these tables is that, if an element is not
** in its main position (i.e. the 'original' position that its hash gives
@@ -23,9 +23,7 @@
** Hence even when the load factor reaches 100%, performance remains good.
*/
#include <float.h>
#include <math.h>
#include <string.h>
#include <limits.h>
#include "lua.h"
@@ -71,7 +69,7 @@
#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
#define hashpointer(t,p) hashmod(t, point2int(p))
#define hashpointer(t,p) hashmod(t, point2uint(p))
#define dummynode (&dummynode_)
@@ -85,31 +83,33 @@ static const Node dummynode_ = {
/*
** Checks whether a float has a value representable as a lua_Integer
** (and does the conversion if so)
** Hash for floating-point numbers.
** The main computation should be just
** n = frepx(n, &i); return (n * INT_MAX) + i
** but there are some numerical subtleties.
** In a two-complement representation, INT_MAX does not has an exact
** representation as a float, but INT_MIN does; because the absolute
** value of 'frexp' is smaller than 1 (unless 'n' is inf/NaN), the
** absolute value of the product 'frexp * -INT_MIN' is smaller or equal
** to INT_MAX. Next, the use of 'unsigned int' avoids overflows when
** adding 'i'; the use of '~u' (instead of '-u') avoids problems with
** INT_MIN.
*/
static int numisinteger (lua_Number x, lua_Integer *p) {
if ((x) == l_floor(x)) /* integral value? */
return lua_numbertointeger(x, p); /* try as an integer */
else return 0;
}
/*
** hash for floating-point numbers
*/
static Node *hashfloat (const Table *t, lua_Number n) {
#if !defined(l_hashfloat)
static int l_hashfloat (lua_Number n) {
int i;
n = l_mathop(frexp)(n, &i) * cast_num(INT_MAX - DBL_MAX_EXP);
i += cast_int(n);
if (i < 0) {
if (cast(unsigned int, i) == 0u - i) /* use unsigned to avoid overflows */
i = 0; /* handle INT_MIN */
i = -i; /* must be a positive value */
lua_Integer ni;
n = l_mathop(frexp)(n, &i) * -cast_num(INT_MIN);
if (!lua_numbertointeger(n, &ni)) { /* is 'n' inf/-inf/NaN? */
lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == HUGE_VAL);
return 0;
}
else { /* normal case */
unsigned int u = cast(unsigned int, i) + cast(unsigned int, ni);
return cast_int(u <= cast(unsigned int, INT_MAX) ? u : ~u);
}
return hashmod(t, i);
}
#endif
/*
@@ -121,13 +121,13 @@ static Node *mainposition (const Table *t, const TValue *key) {
case LUA_TNUMINT:
return hashint(t, ivalue(key));
case LUA_TNUMFLT:
return hashfloat(t, fltvalue(key));
return hashmod(t, l_hashfloat(fltvalue(key)));
case LUA_TSHRSTR:
return hashstr(t, tsvalue(key));
case LUA_TLNGSTR: {
TString *s = tsvalue(key);
if (s->extra == 0) { /* no hash? */
s->hash = luaS_hash(getstr(s), s->len, s->hash);
s->hash = luaS_hash(getstr(s), s->u.lnglen, s->hash);
s->extra = 1; /* now it has its hash */
}
return hashstr(t, tsvalue(key));
@@ -219,28 +219,29 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
/*
** Compute the optimal size for the array part of table 't'. 'nums' is a
** "count array" where 'nums[i]' is the number of integers in the table
** between 2^(i - 1) + 1 and 2^i. Put in '*narray' the optimal size, and
** return the number of elements that will go to that part.
** between 2^(i - 1) + 1 and 2^i. 'pna' enters with the total number of
** integer keys in the table and leaves with the number of keys that
** will go to the array part; return the optimal size.
*/
static unsigned int computesizes (unsigned int nums[], unsigned int *narray) {
static unsigned int computesizes (unsigned int nums[], unsigned int *pna) {
int i;
unsigned int twotoi; /* 2^i */
unsigned int twotoi; /* 2^i (candidate for optimal size) */
unsigned int a = 0; /* number of elements smaller than 2^i */
unsigned int na = 0; /* number of elements to go to array part */
unsigned int n = 0; /* optimal size for array part */
for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {
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) {
if (nums[i] > 0) {
a += nums[i];
if (a > twotoi/2) { /* more than half elements present? */
n = twotoi; /* optimal size (till now) */
na = a; /* all elements up to 'n' will go to array part */
optimal = twotoi; /* optimal size (till now) */
na = a; /* all elements up to 'optimal' will go to array part */
}
}
if (a == *narray) break; /* all elements already counted */
}
*narray = n;
lua_assert(*narray/2 <= na && na <= *narray);
return na;
lua_assert((optimal == 0 || optimal / 2 < na) && na <= optimal);
*pna = na;
return optimal;
}
@@ -255,6 +256,11 @@ static int countint (const TValue *key, unsigned int *nums) {
}
/*
** Count keys in array part of table 't': Fill 'nums[i]' with
** number of keys that will go into corresponding slice and return
** total number of non-nil keys.
*/
static unsigned int numusearray (const Table *t, unsigned int *nums) {
int lg;
unsigned int ttlg; /* 2^lg */
@@ -281,8 +287,7 @@ static unsigned int numusearray (const Table *t, unsigned int *nums) {
}
static int numusehash (const Table *t, unsigned int *nums,
unsigned int *pnasize) {
static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) {
int totaluse = 0; /* total number of elements */
int ause = 0; /* elements added to 'nums' (can go to array part) */
int i = sizenode(t);
@@ -293,7 +298,7 @@ static int numusehash (const Table *t, unsigned int *nums,
totaluse++;
}
}
*pnasize += ause;
*pna += ause;
return totaluse;
}
@@ -363,7 +368,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
}
}
if (!isdummy(nold))
luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old array */
luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old hash */
}
@@ -376,21 +381,22 @@ void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize) {
** nums[i] = number of keys 'k' where 2^(i - 1) < k <= 2^i
*/
static void rehash (lua_State *L, Table *t, const TValue *ek) {
unsigned int nasize, na;
unsigned int asize; /* optimal size for array part */
unsigned int na; /* number of keys in the array part */
unsigned int nums[MAXABITS + 1];
int i;
int totaluse;
for (i = 0; i <= MAXABITS; i++) nums[i] = 0; /* reset counts */
nasize = numusearray(t, nums); /* count keys in array part */
totaluse = nasize; /* all those keys are integer keys */
totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */
na = numusearray(t, nums); /* count keys in array part */
totaluse = na; /* all those keys are integer keys */
totaluse += numusehash(t, nums, &na); /* count keys in hash part */
/* count extra key */
nasize += countint(ek, nums);
na += countint(ek, nums);
totaluse++;
/* compute new size for array part */
na = computesizes(nums, &nasize);
asize = computesizes(nums, &na);
/* resize the table to new computed sizes */
luaH_resize(L, t, nasize, totaluse - na);
luaH_resize(L, t, asize, totaluse - na);
}
@@ -443,14 +449,13 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
TValue aux;
if (ttisnil(key)) luaG_runerror(L, "table index is nil");
else if (ttisfloat(key)) {
lua_Number n = fltvalue(key);
lua_Integer k;
if (luai_numisnan(n))
luaG_runerror(L, "table index is NaN");
if (numisinteger(n, &k)) { /* index is int? */
if (luaV_tointeger(key, &k, 0)) { /* index is int? */
setivalue(&aux, k);
key = &aux; /* insert it as an integer */
}
else if (luai_numisnan(fltvalue(key)))
luaG_runerror(L, "table index is NaN");
}
mp = mainposition(t, key);
if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */
@@ -544,10 +549,10 @@ const TValue *luaH_get (Table *t, const TValue *key) {
case LUA_TNIL: return luaO_nilobject;
case LUA_TNUMFLT: {
lua_Integer k;
if (numisinteger(fltvalue(key), &k)) /* index is int? */
if (luaV_tointeger(key, &k, 0)) /* index is int? */
return luaH_getint(t, k); /* use specialized version */
/* else go through */
}
/* else... */
} /* FALLTHROUGH */
default: {
Node *n = mainposition(t, key);
for (;;) { /* check whether 'key' is somewhere in the chain */

View File

@@ -1,5 +1,5 @@
/*
** $Id: ltablib.c,v 1.79 2014/11/02 19:19:04 roberto Exp $
** $Id: ltablib.c,v 1.80 2015/01/13 16:27:29 roberto Exp $
** Library for Table Manipulation
** See Copyright Notice in lua.h
*/
@@ -124,8 +124,6 @@ static int tmove (lua_State *L) {
lua_Integer e = luaL_checkinteger(L, 3);
lua_Integer t = luaL_checkinteger(L, 4);
int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */
/* the following restriction avoids several problems with overflows */
luaL_argcheck(L, f > 0, 2, "initial position must be positive");
if (e >= f) { /* otherwise, nothing to move */
lua_Integer n, i;
ta.geti = (luaL_getmetafield(L, 1, "__index") == LUA_TNIL)
@@ -134,7 +132,11 @@ static int tmove (lua_State *L) {
ta.seti = (luaL_getmetafield(L, tt, "__newindex") == LUA_TNIL)
? (luaL_checktype(L, tt, LUA_TTABLE), lua_rawseti)
: lua_seti;
luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3,
"too many elements to move");
n = e - f + 1; /* number of elements to move */
luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4,
"destination wrap around");
if (t > f) {
for (i = n - 1; i >= 0; i--) {
(*ta.geti)(L, 1, f + i);

View File

@@ -1,5 +1,5 @@
/*
** $Id: ltm.c,v 2.33 2014/11/21 12:15:57 roberto Exp $
** $Id: ltm.c,v 2.34 2015/03/30 15:42:27 roberto Exp $
** Tag methods
** See Copyright Notice in lua.h
*/
@@ -117,6 +117,7 @@ void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
switch (event) {
case TM_CONCAT:
luaG_concaterror(L, p1, p2);
/* call never returns, but to avoid warnings: *//* FALLTHROUGH */
case TM_BAND: case TM_BOR: case TM_BXOR:
case TM_SHL: case TM_SHR: case TM_BNOT: {
lua_Number dummy;
@@ -124,8 +125,8 @@ void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
luaG_tointerror(L, p1, p2);
else
luaG_opinterror(L, p1, p2, "perform bitwise operation on");
/* else go through */
}
/* calls never return, but to avoid warnings: *//* FALLTHROUGH */
default:
luaG_opinterror(L, p1, p2, "perform arithmetic on");
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lua.c,v 1.222 2014/11/11 19:41:27 roberto Exp $
** $Id: lua.c,v 1.225 2015/03/30 15:42:59 roberto Exp $
** Lua stand-alone interpreter
** See Copyright Notice in lua.h
*/
@@ -18,6 +18,7 @@
#include "lauxlib.h"
#include "lualib.h"
#include "lstring.h"
#if !defined(LUA_PROMPT)
@@ -80,9 +81,7 @@
#include <readline/readline.h>
#include <readline/history.h>
#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
#define lua_saveline(L,idx) \
if (lua_rawlen(L,idx) > 0) /* non-empty line? */ \
add_history(lua_tostring(L, idx)); /* add it to history */
#define lua_saveline(L,line) ((void)L, add_history(line))
#define lua_freeline(L,b) ((void)L, free(b))
#else /* }{ */
@@ -90,7 +89,7 @@
#define lua_readline(L,b,p) \
((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
#define lua_saveline(L,idx) { (void)L; (void)idx; }
#define lua_saveline(L,line) { (void)L; (void)line; }
#define lua_freeline(L,b) { (void)L; (void)b; }
#endif /* } */
@@ -315,11 +314,11 @@ static int pushline (lua_State *L, int firstline) {
lua_pop(L, 1); /* remove prompt */
l = strlen(b);
if (l > 0 && b[l-1] == '\n') /* line ends with newline? */
b[l-1] = '\0'; /* remove it */
b[--l] = '\0'; /* remove it */
if (firstline && b[0] == '=') /* for compatibility with 5.2, ... */
lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */
else
lua_pushstring(L, b);
lua_pushlstring(L, b, l);
lua_freeline(L, b);
return 1;
}
@@ -336,8 +335,12 @@ static int addreturn (lua_State *L) {
lua_pushvalue(L, -2); /* duplicate line */
lua_concat(L, 2); /* new line is "return ..." */
line = lua_tolstring(L, -1, &len);
if ((status = luaL_loadbuffer(L, line, len, "=stdin")) == LUA_OK)
if ((status = luaL_loadbuffer(L, line, len, "=stdin")) == LUA_OK) {
lua_remove(L, -3); /* remove original line */
line += sizeof("return")/sizeof(char); /* remove 'return' for history */
if (line[0] != '\0') /* non empty? */
lua_saveline(L, line); /* keep history */
}
else
lua_pop(L, 2); /* remove result from 'luaL_loadbuffer' and new line */
return status;
@@ -352,8 +355,10 @@ static int multiline (lua_State *L) {
size_t len;
const char *line = lua_tolstring(L, 1, &len); /* get what it has */
int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */
if (!incomplete(L, status) || !pushline(L, 0))
if (!incomplete(L, status) || !pushline(L, 0)) {
lua_saveline(L, line); /* keep history */
return status; /* cannot or should not try to add continuation line */
}
lua_pushliteral(L, "\n"); /* add newline... */
lua_insert(L, -2); /* ...between the two lines */
lua_concat(L, 3); /* join them */
@@ -374,7 +379,6 @@ static int loadline (lua_State *L) {
return -1; /* no input */
if ((status = addreturn(L)) != LUA_OK) /* 'return ...' did not work? */
status = multiline(L); /* try as command, maybe with continuation lines */
lua_saveline(L, 1); /* keep history */
lua_remove(L, 1); /* remove line from the stack */
lua_assert(lua_gettop(L) == 1);
return status;
@@ -482,14 +486,14 @@ static int collectargs (char **argv, int *first) {
args |= has_E;
break;
case 'i':
args |= has_i; /* goes through (-i implies -v) */
args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */
case 'v':
if (argv[i][2] != '\0') /* extra characters after 1st? */
return has_error; /* invalid option */
args |= has_v;
break;
case 'e':
args |= has_e; /* go through */
args |= has_e; /* FALLTHROUGH */
case 'l': /* both options need an argument */
if (argv[i][2] == '\0') { /* no concatenated argument? */
i++; /* try next 'argv' */
@@ -513,17 +517,16 @@ static int collectargs (char **argv, int *first) {
static int runargs (lua_State *L, char **argv, int n) {
int i;
for (i = 1; i < n; i++) {
int status;
int option = argv[i][1];
lua_assert(argv[i][0] == '-'); /* already checked */
if (option == 'e' || option == 'l') {
int status;
const char *extra = argv[i] + 2; /* both options need an argument */
if (*extra == '\0') extra = argv[++i];
lua_assert(extra != NULL);
if (option == 'e')
status = dostring(L, extra, "=(command line)");
else
status = dolibrary(L, extra);
status = (option == 'e')
? dostring(L, extra, "=(command line)")
: dolibrary(L, extra);
if (status != LUA_OK) return 0;
}
}
@@ -594,7 +597,9 @@ static int pmain (lua_State *L) {
int main (int argc, char **argv) {
int status, result;
lua_State *L = luaL_newstate(); /* create state */
lua_State *L;
luaS_initshr(); /* init global short string table */
L = luaL_newstate(); /* create state */
if (L == NULL) {
l_message(argv[0], "cannot create state: not enough memory");
return EXIT_FAILURE;
@@ -606,6 +611,7 @@ int main (int argc, char **argv) {
result = lua_toboolean(L, -1); /* get result */
report(L, status);
lua_close(L);
luaS_exitshr();
return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lua.h,v 1.325 2014/12/26 17:24:27 roberto Exp $
** $Id: lua.h,v 1.328 2015/06/03 13:03:38 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,7 +19,7 @@
#define LUA_VERSION_MAJOR "5"
#define LUA_VERSION_MINOR "3"
#define LUA_VERSION_NUM 503
#define LUA_VERSION_RELEASE "0"
#define LUA_VERSION_RELEASE "1"
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
@@ -35,9 +35,11 @@
/*
** pseudo-indices
** Pseudo-indices
** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty
** space after that to help overflow detection)
*/
#define LUA_REGISTRYINDEX LUAI_FIRSTPSEUDOIDX
#define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000)
#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i))
@@ -282,6 +284,7 @@ LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip);
LUA_API void (lua_clonefunction) (lua_State *L, const void *eL);
/*
** coroutine functions
*/
@@ -357,8 +360,7 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
#define lua_pushliteral(L, s) \
lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
#define lua_pushliteral(L, s) lua_pushstring(L, "" s)
#define lua_pushglobaltable(L) \
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)
@@ -460,7 +462,7 @@ struct lua_Debug {
/* Add by skynet */
extern lua_State * skynet_sig_L;
LUA_API lua_State * skynet_sig_L;
LUA_API void (lua_checksig_)(lua_State *L);
#define lua_checksig(L) if (skynet_sig_L) { lua_checksig_(L); }

View File

@@ -1,5 +1,5 @@
/*
** $Id: luac.c,v 1.72 2015/01/06 03:09:13 lhf Exp $
** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $
** Lua compiler (saves bytecodes to files; also lists bytecodes)
** See Copyright Notice in lua.h
*/
@@ -21,6 +21,7 @@
#include "lobject.h"
#include "lstate.h"
#include "lundump.h"
#include "lstring.h"
static void PrintFunction(const Proto* f, int full);
#define luaU_print PrintFunction
@@ -195,6 +196,7 @@ int main(int argc, char* argv[])
int i=doargs(argc,argv);
argc-=i; argv+=i;
if (argc<=0) usage("no input files given");
luaS_initshr();
L=luaL_newstate();
if (L==NULL) fatal("cannot create state: not enough memory");
lua_pushcfunction(L,&pmain);
@@ -206,7 +208,7 @@ int main(int argc, char* argv[])
}
/*
** $Id: print.c,v 1.76 2015/01/05 16:12:50 lhf Exp $
** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $
** print bytecodes
** See Copyright Notice in lua.h
*/
@@ -226,7 +228,7 @@ int main(int argc, char* argv[])
static void PrintString(const TString* ts)
{
const char* s=getstr(ts);
size_t i,n=ts->len;
size_t i,n=tsslen(ts);
printf("%c",'"');
for (i=0; i<n; i++)
{
@@ -287,9 +289,8 @@ static void PrintConstant(const Proto* f, int i)
static void PrintCode(const Proto* f)
{
const SharedProto *sp = f->sp;
const Instruction* code=sp->code;
int pc,n=sp->sizecode;
const Instruction* code=f->sp->code;
int pc,n=f->sp->sizecode;
for (pc=0; pc<n; pc++)
{
Instruction i=code[pc];

View File

@@ -1,5 +1,5 @@
/*
** $Id: luaconf.h,v 1.238 2014/12/29 13:27:55 roberto Exp $
** $Id: luaconf.h,v 1.251 2015/05/20 17:39:23 roberto Exp $
** Configuration file for Lua
** See Copyright Notice in lua.h
*/
@@ -96,10 +96,8 @@
/*
@@ LUA_INT_INT / LUA_INT_LONG / LUA_INT_LONGLONG defines the type for
** Lua integers.
@@ LUA_REAL_FLOAT / LUA_REAL_DOUBLE / LUA_REAL_LONGDOUBLE defines
** the type for Lua floats.
@@ LUA_INT_TYPE defines the type for Lua integers.
@@ LUA_FLOAT_TYPE defines the type for Lua floats.
** Lua should work fine with any mix of these options (if supported
** by your C compiler). The usual configurations are 64-bit integers
** and 'double' (the default), 32-bit integers and 'float' (for
@@ -107,31 +105,46 @@
** compliant with C99, which may not have support for 'long long').
*/
/* predefined options for LUA_INT_TYPE */
#define LUA_INT_INT 1
#define LUA_INT_LONG 2
#define LUA_INT_LONGLONG 3
/* predefined options for LUA_FLOAT_TYPE */
#define LUA_FLOAT_FLOAT 1
#define LUA_FLOAT_DOUBLE 2
#define LUA_FLOAT_LONGDOUBLE 3
#if defined(LUA_32BITS) /* { */
/*
** 32-bit integers and 'float'
*/
#if LUAI_BITSINT >= 32 /* use 'int' if big enough */
#define LUA_INT_INT
#define LUA_INT_TYPE LUA_INT_INT
#else /* otherwise use 'long' */
#define LUA_INT_LONG
#define LUA_INT_TYPE LUA_INT_LONG
#endif
#define LUA_REAL_FLOAT
#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT
#elif defined(LUA_C89_NUMBERS) /* }{ */
/*
** largest types available for C89 ('long' and 'double')
*/
#define LUA_INT_LONG
#define LUA_REAL_DOUBLE
#define LUA_INT_TYPE LUA_INT_LONG
#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE
#endif /* } */
#else /* }{ */
/*
** default configuration for 64-bit Lua ('long long' and 'double')
*/
#define LUA_INT_LONGLONG
#define LUA_REAL_DOUBLE
#if !defined(LUA_INT_TYPE)
#define LUA_INT_TYPE LUA_INT_LONGLONG
#endif
#if !defined(LUA_FLOAT_TYPE)
#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE
#endif /* } */
/* }================================================================== */
@@ -155,7 +168,7 @@
** non-conventional directories.
*/
#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
#if defined(_WIN32) /* { */
#if defined(_WIN32) /* { */
/*
** In Windows, any exclamation mark ('!') in the path is replaced by the
** path of the directory of the executable file of the current process.
@@ -300,20 +313,15 @@
*/
#define LUA_COMPAT_APIINTCASTS
/*
@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a
@@ a float mark ('.0').
** This macro is not on by default even in compatibility mode,
** because this is not really an incompatibility.
*/
/* #define LUA_COMPAT_FLOATSTRING */
#endif /* } */
#if defined(LUA_COMPAT_5_1) /* { */
/* Incompatibilities from 5.2 -> 5.3 */
#define LUA_COMPAT_MATHLIB
#define LUA_COMPAT_APIINTCASTS
/*
@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'.
** You can replace it with 'table.unpack'.
@@ -373,6 +381,15 @@
#endif /* } */
/*
@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a
@@ a float mark ('.0').
** This macro is not on by default even in compatibility mode,
** because this is not really an incompatibility.
*/
/* #define LUA_COMPAT_FLOATSTRING */
/* }================================================================== */
@@ -380,30 +397,30 @@
/*
** {==================================================================
** Configuration for Numbers.
** Change these definitions if no predefined LUA_REAL_* / LUA_INT_*
** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_*
** satisfy your needs.
** ===================================================================
*/
/*
@@ LUA_NUMBER is the floating-point type used by Lua.
**
@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
@@ 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.
@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats.
@@ LUA_NUMBER_FMT is the format for writing floats.
@@ lua_number2str converts a float to a string.
**
@@ l_mathop allows the addition of an 'l' or 'f' to all math operations.
**
@@ lua_str2number converts a decimal numeric string to a number.
*/
#if defined(LUA_REAL_FLOAT) /* { single float */
#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */
#define LUA_NUMBER float
#define l_mathlim(n) (FLT_##n)
#define LUAI_UACNUMBER double
#define LUA_NUMBER_FRMLEN ""
@@ -414,10 +431,12 @@
#define lua_str2number(s,p) strtof((s), (p))
#elif defined(LUA_REAL_LONGDOUBLE) /* }{ long double */
#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */
#define LUA_NUMBER long double
#define l_mathlim(n) (LDBL_##n)
#define LUAI_UACNUMBER long double
#define LUA_NUMBER_FRMLEN "L"
@@ -427,10 +446,12 @@
#define lua_str2number(s,p) strtold((s), (p))
#elif defined(LUA_REAL_DOUBLE) /* }{ double */
#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */
#define LUA_NUMBER double
#define l_mathlim(n) (DBL_##n)
#define LUAI_UACNUMBER double
#define LUA_NUMBER_FRMLEN ""
@@ -440,9 +461,9 @@
#define lua_str2number(s,p) strtod((s), (p))
#else /* }{ */
#else /* }{ */
#error "numeric real type not defined"
#error "numeric float type not defined"
#endif /* } */
@@ -466,46 +487,6 @@
(*(p) = (LUA_INTEGER)(n), 1))
/*
@@ The luai_num* macros define the primitive operations over numbers.
** They should work for any size of floating numbers.
*/
/* the following operations need the math library */
#if defined(lobject_c) || defined(lvm_c)
#include <math.h>
/* floor division (defined as 'floor(a/b)') */
#define luai_numidiv(L,a,b) ((void)L, l_mathop(floor)(luai_numdiv(L,a,b)))
/*
** module: defined as 'a - floor(a/b)*b'; the previous definition gives
** NaN when 'b' is huge, but the result should be 'a'. 'fmod' gives the
** result of 'a - trunc(a/b)*b', and therefore must be corrected when
** 'trunc(a/b) ~= floor(a/b)'. That happens when the division has a
** non-integer negative result, which is equivalent to the test below
*/
#define luai_nummod(L,a,b,m) \
{ (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); }
/* exponentiation */
#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b))
#endif
/* these are quite standard operations */
#if defined(LUA_CORE)
#define luai_numadd(L,a,b) ((a)+(b))
#define luai_numsub(L,a,b) ((a)-(b))
#define luai_nummul(L,a,b) ((a)*(b))
#define luai_numdiv(L,a,b) ((a)/(b))
#define luai_numunm(L,a) (-(a))
#define luai_numeq(a,b) ((a)==(b))
#define luai_numlt(a,b) ((a)<(b))
#define luai_numle(a,b) ((a)<=(b))
#define luai_numisnan(a) (!luai_numeq((a), (a)))
#endif
/*
@@ LUA_INTEGER is the integer type used by Lua.
@@ -538,7 +519,7 @@
/* now the variable definitions */
#if defined(LUA_INT_INT) /* { int */
#if LUA_INT_TYPE == LUA_INT_INT /* { int */
#define LUA_INTEGER int
#define LUA_INTEGER_FRMLEN ""
@@ -546,7 +527,7 @@
#define LUA_MAXINTEGER INT_MAX
#define LUA_MININTEGER INT_MIN
#elif defined(LUA_INT_LONG) /* }{ long */
#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */
#define LUA_INTEGER long
#define LUA_INTEGER_FRMLEN "l"
@@ -554,7 +535,7 @@
#define LUA_MAXINTEGER LONG_MAX
#define LUA_MININTEGER LONG_MIN
#elif defined(LUA_INT_LONGLONG) /* }{ long long */
#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */
#if defined(LLONG_MAX) /* { */
/* use ISO C99 stuff */
@@ -592,13 +573,13 @@
/*
** {==================================================================
** Dependencies with C99
** Dependencies with C99 and other C details
** ===================================================================
*/
/*
@@ lua_strx2number converts an hexadecimal numeric string to a number.
** In C99, 'strtod' does both conversions. Otherwise, you can
** In C99, 'strtod' does that conversion. Otherwise, you can
** leave 'lua_strx2number' undefined and Lua will provide its own
** implementation.
*/
@@ -608,12 +589,13 @@
/*
@@ LUA_USE_AFORMAT allows '%a'/'%A' specifiers in 'string.format'
** Enable it if the C function 'printf' supports these specifiers.
** (C99 demands it and Windows also supports it.)
@@ 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) || defined(LUA_USE_WINDOWS)
#define LUA_USE_AFORMAT
#if !defined(LUA_USE_C89)
#define lua_number2strx(L,b,f,n) sprintf(b,f,n)
#endif
@@ -642,12 +624,50 @@
#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \
__STDC_VERSION__ >= 199901L
#include <stdint.h>
#if defined (INTPTR_MAX) /* even in C99 this type is optional */
#if defined(INTPTR_MAX) /* even in C99 this type is optional */
#undef LUA_KCONTEXT
#define LUA_KCONTEXT intptr_t
#endif
#endif
/*
@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point).
** Change that if you do not want to use C locales. (Code using this
** macro must include header 'locale.h'.)
*/
#if !defined(lua_getlocaledecpoint)
#define lua_getlocaledecpoint() (localeconv()->decimal_point[0])
#endif
/* }================================================================== */
/*
** {==================================================================
** Language Variations
** =====================================================================
*/
/*
@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some
** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from
** numbers to strings. Define LUA_NOCVTS2N to turn off automatic
** coercion from strings to numbers.
*/
/* #define LUA_NOCVTN2S */
/* #define LUA_NOCVTS2N */
/*
@@ LUA_USE_APICHECK turns on several consistency checks on the C API.
** Define it as a help when debugging C code.
*/
#if defined(LUA_USE_APICHECK)
#include <assert.h>
#define luai_apicheck(l,e) assert(e)
#endif
/* }================================================================== */
@@ -671,9 +691,6 @@
#define LUAI_MAXSTACK 15000
#endif
/* reserve some space for error handling */
#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000)
/*
@@ LUA_EXTRASPACE defines the size of a raw memory area associated with
@@ -691,20 +708,18 @@
#define LUA_IDSIZE 60
/*
@@ LUAI_MAXSHORTLEN is the maximum length for short strings, that is,
** strings that are internalized. (Cannot be smaller than reserved words
** or tags for metamethods, as these strings must be internalized;
** #("function") = 8, #("__newindex") = 10.)
*/
#define LUAI_MAXSHORTLEN 40
/*
@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
** CHANGE it if it uses too much C-stack space.
** CHANGE it if it uses too much C-stack space. (For long double,
** 'string.format("%.99f", 1e4932)' needs ~5030 bytes, so a
** smaller buffer would force a memory allocation for each call to
** 'string.format'.)
*/
#define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer)))
#if defined(LUA_FLOAT_LONGDOUBLE)
#define LUAL_BUFFERSIZE 8192
#else
#define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer)))
#endif
/* }================================================================== */

View File

@@ -1,5 +1,5 @@
/*
** $Id: lutf8lib.c,v 1.13 2014/11/02 19:19:04 roberto Exp $
** $Id: lutf8lib.c,v 1.15 2015/03/28 19:16:55 roberto Exp $
** Standard library for UTF-8 manipulation
** See Copyright Notice in lua.h
*/
@@ -11,6 +11,7 @@
#include <assert.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
@@ -37,7 +38,7 @@ static lua_Integer u_posrelat (lua_Integer pos, size_t len) {
** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid.
*/
static const char *utf8_decode (const char *o, int *val) {
static unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF};
static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF};
const unsigned char *s = (const unsigned char *)o;
unsigned int c = s[0];
unsigned int res = 0; /* final result */
@@ -106,9 +107,9 @@ static int codepoint (lua_State *L) {
luaL_argcheck(L, posi >= 1, 2, "out of range");
luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range");
if (posi > pose) return 0; /* empty interval; return no values */
n = (int)(pose - posi + 1);
if (posi + n <= pose) /* (lua_Integer -> int) overflow? */
if (pose - posi >= INT_MAX) /* (lua_Integer -> int) overflow? */
return luaL_error(L, "string slice too long");
n = (int)(pose - posi) + 1;
luaL_checkstack(L, n, "string slice too long");
n = 0;
se = s + pose;
@@ -234,7 +235,7 @@ static int iter_codes (lua_State *L) {
#define UTF8PATT "[\0-\x7F\xC2-\xF4][\x80-\xBF]*"
static struct luaL_Reg funcs[] = {
static const luaL_Reg funcs[] = {
{"offset", byteoffset},
{"codepoint", codepoint},
{"char", utfchar},
@@ -248,7 +249,7 @@ static struct luaL_Reg funcs[] = {
LUAMOD_API int luaopen_utf8 (lua_State *L) {
luaL_newlib(L, funcs);
lua_pushliteral(L, UTF8PATT);
lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT)/sizeof(char) - 1);
lua_setfield(L, -2, "charpattern");
return 1;
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lvm.c,v 2.232 2014/12/27 20:30:38 roberto Exp $
** $Id: lvm.c,v 2.245 2015/06/09 15:53:35 roberto Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -9,8 +9,9 @@
#include "lprefix.h"
#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -30,19 +31,38 @@
#include "lvm.h"
/*
** You can define LUA_FLOORN2I if you want to convert floats to integers
** by flooring them (instead of raising an error if they are not
** integral values)
*/
#if !defined(LUA_FLOORN2I)
#define LUA_FLOORN2I 0
#endif
/* limit for table tag-method chains (to avoid loops) */
#define MAXTAGLOOP 2000
/*
** 'l_intfitsf' checks whether a given integer can be converted to a
** float without rounding. Used in comparisons. Left undefined if
** all integers fit in a float precisely.
*/
#if !defined(l_intfitsf)
/* number of bits in the mantissa of a float */
#define NBM (l_mathlim(MANT_DIG))
/*
** Check whether some integers may not fit in a float, that is, whether
** (maxinteger >> NBM) > 0 (that implies (1 << NBM) <= maxinteger).
** (The shifts are done in parts to avoid shifting by more than the size
** of an integer. In a worst case, NBM == 113 for long double and
** sizeof(integer) == 32.)
*/
#if ((((LUA_MAXINTEGER >> (NBM / 4)) >> (NBM / 4)) >> (NBM / 4)) \
>> (NBM - (3 * (NBM / 4)))) > 0
#define l_intfitsf(i) \
(-((lua_Integer)1 << NBM) <= (i) && (i) <= ((lua_Integer)1 << NBM))
#endif
#endif
/* Add by skynet */
lua_State * skynet_sig_L = NULL;
@@ -55,24 +75,6 @@ lua_checksig_(lua_State *L) {
}
}
/*
** Similar to 'tonumber', but does not attempt to convert strings and
** ensure correct precision (no extra bits). Used in comparisons.
*/
static int tofloat (const TValue *obj, lua_Number *n) {
if (ttisfloat(obj)) *n = fltvalue(obj);
else if (ttisinteger(obj)) {
volatile lua_Number x = cast_num(ivalue(obj)); /* avoid extra precision */
*n = x;
}
else {
*n = 0; /* to avoid warnings */
return 0;
}
return 1;
}
/*
** Try to convert a value to a float. The float case is already handled
** by the macro 'tonumber'.
@@ -84,7 +86,7 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
return 1;
}
else if (cvt2num(obj) && /* string convertible to number? */
luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) {
luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) {
*n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */
return 1;
}
@@ -99,7 +101,7 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
** mode == 1: takes the floor of the number
** mode == 2: takes the ceil of the number
*/
static int tointeger_aux (const TValue *obj, lua_Integer *p, int mode) {
int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) {
TValue v;
again:
if (ttisfloat(obj)) {
@@ -117,7 +119,7 @@ static int tointeger_aux (const TValue *obj, lua_Integer *p, int mode) {
return 1;
}
else if (cvt2num(obj) &&
luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) {
luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) {
obj = &v;
goto again; /* convert result from 'luaO_str2num' to an integer */
}
@@ -125,14 +127,6 @@ static int tointeger_aux (const TValue *obj, lua_Integer *p, int mode) {
}
/*
** try to convert a value to an integer
*/
int luaV_tointeger_ (const TValue *obj, lua_Integer *p) {
return tointeger_aux(obj, p, LUA_FLOORN2I);
}
/*
** Try to convert a 'for' limit to an integer, preserving the
** semantics of the loop.
@@ -151,11 +145,11 @@ int luaV_tointeger_ (const TValue *obj, lua_Integer *p) {
static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
int *stopnow) {
*stopnow = 0; /* usually, let loops run */
if (!tointeger_aux(obj, p, (step < 0 ? 2 : 1))) { /* not fit in integer? */
if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) { /* not fit in integer? */
lua_Number n; /* try to convert to float */
if (!tonumber(obj, &n)) /* cannot convert to float? */
return 0; /* not a number */
if (n > 0) { /* if true, float is larger than max integer */
if (luai_numlt(0, n)) { /* if true, float is larger than max integer */
*p = LUA_MAXINTEGER;
if (step < 0) *stopnow = 1;
}
@@ -250,9 +244,9 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
*/
static int l_strcmp (const TString *ls, const TString *rs) {
const char *l = getstr(ls);
size_t ll = ls->len;
size_t ll = tsslen(ls);
const char *r = getstr(rs);
size_t lr = rs->len;
size_t lr = tsslen(rs);
for (;;) { /* for each segment */
int temp = strcoll(l, r);
if (temp != 0) /* not equal? */
@@ -271,16 +265,103 @@ static int l_strcmp (const TString *ls, const TString *rs) {
}
/*
** Check whether integer 'i' is less than float 'f'. If 'i' has an
** exact representation as a float ('l_intfitsf'), compare numbers as
** floats. Otherwise, if 'f' is outside the range for integers, result
** is trivial. Otherwise, compare them as integers. (When 'i' has no
** float representation, either 'f' is "far away" from 'i' or 'f' has
** no precision left for a fractional part; either way, how 'f' is
** truncated is irrelevant.) When 'f' is NaN, comparisons must result
** in false.
*/
static int LTintfloat (lua_Integer i, lua_Number f) {
#if defined(l_intfitsf)
if (!l_intfitsf(i)) {
if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */
return 1; /* f >= maxint + 1 > i */
else if (f > cast_num(LUA_MININTEGER)) /* minint < f <= maxint ? */
return (i < cast(lua_Integer, f)); /* compare them as integers */
else /* f <= minint <= i (or 'f' is NaN) --> not(i < f) */
return 0;
}
#endif
return luai_numlt(cast_num(i), f); /* compare them as floats */
}
/*
** Check whether integer 'i' is less than or equal to float 'f'.
** See comments on previous function.
*/
static int LEintfloat (lua_Integer i, lua_Number f) {
#if defined(l_intfitsf)
if (!l_intfitsf(i)) {
if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */
return 1; /* f >= maxint + 1 > i */
else if (f >= cast_num(LUA_MININTEGER)) /* minint <= f <= maxint ? */
return (i <= cast(lua_Integer, f)); /* compare them as integers */
else /* f < minint <= i (or 'f' is NaN) --> not(i <= f) */
return 0;
}
#endif
return luai_numle(cast_num(i), f); /* compare them as floats */
}
/*
** Return 'l < r', for numbers.
*/
static int LTnum (const TValue *l, const TValue *r) {
if (ttisinteger(l)) {
lua_Integer li = ivalue(l);
if (ttisinteger(r))
return li < ivalue(r); /* both are integers */
else /* 'l' is int and 'r' is float */
return LTintfloat(li, fltvalue(r)); /* l < r ? */
}
else {
lua_Number lf = fltvalue(l); /* 'l' must be float */
if (ttisfloat(r))
return luai_numlt(lf, fltvalue(r)); /* both are float */
else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */
return 0; /* NaN < i is always false */
else /* without NaN, (l < r) <--> not(r <= l) */
return !LEintfloat(ivalue(r), lf); /* not (r <= l) ? */
}
}
/*
** Return 'l <= r', for numbers.
*/
static int LEnum (const TValue *l, const TValue *r) {
if (ttisinteger(l)) {
lua_Integer li = ivalue(l);
if (ttisinteger(r))
return li <= ivalue(r); /* both are integers */
else /* 'l' is int and 'r' is float */
return LEintfloat(li, fltvalue(r)); /* l <= r ? */
}
else {
lua_Number lf = fltvalue(l); /* 'l' must be float */
if (ttisfloat(r))
return luai_numle(lf, fltvalue(r)); /* both are float */
else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */
return 0; /* NaN <= i is always false */
else /* without NaN, (l <= r) <--> not(r < l) */
return !LTintfloat(ivalue(r), lf); /* not (r < l) ? */
}
}
/*
** Main operation less than; return 'l < r'.
*/
int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
int res;
lua_Number nl, nr;
if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */
return (ivalue(l) < ivalue(r));
else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */
return luai_numlt(nl, nr);
if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */
return LTnum(l, r);
else if (ttisstring(l) && ttisstring(r)) /* both are strings? */
return l_strcmp(tsvalue(l), tsvalue(r)) < 0;
else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) /* no metamethod? */
@@ -290,27 +371,34 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
/*
** Main operation less than or equal to; return 'l <= r'.
** Main operation less than or equal to; return 'l <= r'. If it needs
** a metamethod and there is no '__le', try '__lt', based on
** l <= r iff !(r < l) (assuming a total order). If the metamethod
** yields during this substitution, the continuation has to know
** about it (to negate the result of r<l); bit CIST_LEQ in the call
** status keeps that information.
*/
int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
int res;
lua_Number nl, nr;
if (ttisinteger(l) && ttisinteger(r)) /* both operands are integers? */
return (ivalue(l) <= ivalue(r));
else if (tofloat(l, &nl) && tofloat(r, &nr)) /* both are numbers? */
return luai_numle(nl, nr);
if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */
return LEnum(l, r);
else if (ttisstring(l) && ttisstring(r)) /* both are strings? */
return l_strcmp(tsvalue(l), tsvalue(r)) <= 0;
else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* first try 'le' */
else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* try 'le' */
return res;
else if ((res = luaT_callorderTM(L, r, l, TM_LT)) < 0) /* else try 'lt' */
luaG_ordererror(L, l, r);
return !res;
else { /* try 'lt': */
L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */
res = luaT_callorderTM(L, r, l, TM_LT);
L->ci->callstatus ^= CIST_LEQ; /* clear mark */
if (res < 0)
luaG_ordererror(L, l, r);
return !res; /* result is negated */
}
}
/*
** Main operation for equality of Lua values; return 't1 == t2'.
** Main operation for equality of Lua values; return 't1 == t2'.
** L == NULL means raw equality (no metamethods)
*/
int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
@@ -319,10 +407,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER)
return 0; /* only numbers can be equal with different variants */
else { /* two numbers with different variants */
lua_Number n1, n2; /* compare them as floats */
lua_assert(ttisnumber(t1) && ttisnumber(t2));
cast_void(tofloat(t1, &n1)); cast_void(tofloat(t2, &n2));
return luai_numeq(n1, n2);
lua_Integer i1, i2; /* compare them as integers */
return (tointeger(t1, &i1) && tointeger(t2, &i2) && i1 == i2);
}
}
/* values have same type and same variant */
@@ -365,6 +451,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
#define tostring(L,o) \
(ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1)))
#define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0)
/*
** Main operation for concatenation: concat 'total' values in the stack,
** from 'L->top - total' up to 'L->top - 1'.
@@ -376,19 +464,19 @@ void luaV_concat (lua_State *L, int total) {
int n = 2; /* number of elements handled in this pass (at least 2) */
if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1))
luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT);
else if (tsvalue(top-1)->len == 0) /* second operand is empty? */
else if (isemptystr(top - 1)) /* second operand is empty? */
cast_void(tostring(L, top - 2)); /* result is first operand */
else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) {
else if (isemptystr(top - 2)) { /* first operand is an empty string? */
setobjs2s(L, top - 2, top - 1); /* result is second op. */
}
else {
/* at least two non-empty string values; get as many as possible */
size_t tl = tsvalue(top-1)->len;
size_t tl = vslen(top - 1);
char *buffer;
int i;
/* collect total length */
for (i = 1; i < total && tostring(L, top-i-1); i++) {
size_t l = tsvalue(top-i-1)->len;
size_t l = vslen(top - i - 1);
if (l >= (MAX_SIZE/sizeof(char)) - tl)
luaG_runerror(L, "string length overflow");
tl += l;
@@ -397,7 +485,7 @@ void luaV_concat (lua_State *L, int total) {
tl = 0;
n = i;
do { /* copy all strings to buffer */
size_t l = tsvalue(top-i)->len;
size_t l = vslen(top - i);
memcpy(buffer+tl, svalue(top-i), l * sizeof(char));
tl += l;
} while (--i > 0);
@@ -414,7 +502,7 @@ void luaV_concat (lua_State *L, int total) {
*/
void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
const TValue *tm;
switch (ttnov(rb)) {
switch (ttype(rb)) {
case LUA_TTABLE: {
Table *h = hvalue(rb);
tm = fasttm(L, h->metatable, TM_LEN);
@@ -422,8 +510,12 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
setivalue(ra, luaH_getn(h)); /* else primitive len */
return;
}
case LUA_TSTRING: {
setivalue(ra, tsvalue(rb)->len);
case LUA_TSHRSTR: {
setivalue(ra, tsvalue(rb)->shrlen);
return;
}
case LUA_TLNGSTR: {
setivalue(ra, tsvalue(rb)->u.lnglen);
return;
}
default: { /* try metamethod */
@@ -459,7 +551,7 @@ lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) {
/*
** Integer modulus; return 'm % n'. (Assume that C '%' with
** Integer modulus; return 'm % n'. (Assume that C '%' with
** negative operands follows C99 behavior. See previous comment
** about luaV_div.)
*/
@@ -564,11 +656,11 @@ void luaV_finishOp (lua_State *L) {
case OP_LE: case OP_LT: case OP_EQ: {
int res = !l_isfalse(L->top - 1);
L->top--;
/* metamethod should not be called when operand is K */
lua_assert(!ISK(GETARG_B(inst)));
if (op == OP_LE && /* "<=" using "<" instead? */
ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE)))
res = !res; /* invert result */
if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */
lua_assert(op == OP_LE);
ci->callstatus ^= CIST_LEQ; /* clear mark */
res = !res; /* negate result */
}
lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP);
if (res != GETARG_A(inst)) /* condition failed? */
ci->u.l.savedpc++; /* skip jump instruction */
@@ -618,7 +710,7 @@ void luaV_finishOp (lua_State *L) {
** some macros for common tasks in 'luaV_execute'
*/
#if !defined luai_runtimecheck
#if !defined(luai_runtimecheck)
#define luai_runtimecheck(L, c) /* void */
#endif
@@ -754,7 +846,7 @@ void luaV_execute (lua_State *L) {
Protect(luaV_gettable(L, rb, RKC(i), ra));
vmbreak;
}
vmcase(OP_ADD) {
vmcase(OP_ADD) {
TValue *rb = RKB(i);
TValue *rc = RKC(i);
lua_Number nb; lua_Number nc;
@@ -939,7 +1031,7 @@ void luaV_execute (lua_State *L) {
L->top = base + c + 1; /* mark the end of concat operands */
Protect(luaV_concat(L, c - b + 1));
ra = RA(i); /* 'luav_concat' may invoke TMs and move the stack */
rb = b + base;
rb = base + b;
setobjs2s(L, ra, rb);
checkGC(L, (ra >= rb ? ra + 1 : rb));
L->top = ci->top; /* restore top */
@@ -1045,9 +1137,8 @@ void luaV_execute (lua_State *L) {
}
vmcase(OP_RETURN) {
int b = GETARG_B(i);
if (b != 0) L->top = ra+b-1;
if (cl->p->sp->sizep > 0) luaF_close(L, base);
b = luaD_poscall(L, ra);
b = luaD_poscall(L, ra, (b != 0 ? b - 1 : L->top - ra));
if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */
return; /* external invocation: return */
else { /* invocation via reentry: continue execution */
@@ -1065,7 +1156,7 @@ void luaV_execute (lua_State *L) {
lua_Integer limit = ivalue(ra + 1);
if ((0 < step) ? (idx <= limit) : (limit <= idx)) {
ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
setivalue(ra, idx); /* update internal index... */
chgivalue(ra, idx); /* update internal index... */
setivalue(ra + 3, idx); /* ...and external index */
}
}
@@ -1076,7 +1167,7 @@ void luaV_execute (lua_State *L) {
if (luai_numlt(0, step) ? luai_numle(idx, limit)
: luai_numle(limit, idx)) {
ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
setfltvalue(ra, idx); /* update internal index... */
chgfltvalue(ra, idx); /* update internal index... */
setfltvalue(ra + 3, idx); /* ...and external index */
}
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lvm.h,v 2.34 2014/08/01 17:24:02 roberto Exp $
** $Id: lvm.h,v 2.35 2015/02/20 14:27:53 roberto Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -27,11 +27,21 @@
#endif
/*
** You can define LUA_FLOORN2I if you want to convert floats to integers
** by flooring them (instead of raising an error if they are not
** integral values)
*/
#if !defined(LUA_FLOORN2I)
#define LUA_FLOORN2I 0
#endif
#define tonumber(o,n) \
(ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n))
#define tointeger(o,i) \
(ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger_(o,i))
(ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I))
#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2))
@@ -42,7 +52,7 @@ LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
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);
LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode);
LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
StkId val);
LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,

View File

@@ -1,3 +1,96 @@
v1.0.0-beta (2015-11-10)
-----------
* Improve and fix bug for sproto
* Add global short string pool for lua vm
* Add code cache mode
* Add a callback for mysql auth
* Add hmac_md5
* Sharedata support filename as a string
* Fix a bug in socket.httpc
* Fix a lua stack overflow bug in lua bson
* Fix a socketchannel bug may block the data steam
* Avoid dead loop when sending message to the service exiting
* Fix memory leak in netpack
* Improve DH key exchange implement
* Minor fix for socket
* Minor fix for multicast
* Update jemalloc to 4.0.4
* Update lpeg to 1.0.0
v1.0.0-alpha10 (2015-8-17)
-----------
* Remove the size limit of cluster RPC message.
* Remove the size limit of local message.
* Add cluster.query and clsuter.register.
* Add an option of pthread mutex lock.
* Add skynet.core.intcommand to optimize skynet.sleep etc.
* Fix a memory leak bug in lua shared proto.
* snax.msgserver use string instead of lightuserdata/size.
* Remove some unused api in netpack.
* Raise error when skynet.send to 0.
v1.0.0-alpha9 (2015-8-10)
-----------
* Improve lua serialization , support pairs metamethod.
* Bugfix : sproto (See commits log of sproto)
* Add user log service support (In config)
* Other minor bugfix (See commits log)
v1.0.0-alpha8 (2015-6-29)
-----------
* Update lua 5.3.1
* Bugfix: skynet exit issue
* Bugfix: timer race condition
* Use atom increment in bson object id
* remove assert when write to a listen fd
* sproto encode doesn't use raw table api
v1.0.0-alpha7 (2015-6-8)
-----------
* console support launch snax service
* Add cluster.snax
* Add nodelay in clusterd
* Merge sproto bugfix patch
* Move some skynet api into skynet.manager
* DNS support underscore
* Add logservice in config file for user defined log service
* skynet.fork returns coroutine
* Fix a few of bugs , see the commits log
v1.0.0-alpha6 (2015-5-18)
-----------
* bugfix: httpc.get
* bugfix: seri lib stack overflow
* bugfix: udp send
* bugfix: udp address
* bugfix: sproto dump
* add: sproto default
* improve: skynet.wakeup (can wakeup skynet.call by raise an error)
* improve: skynet.exit (raise error when uncall response)
* remove: task overload warning
* move: some skynet api move into skynet.manager
v1.0.0-alpha5 (2015-4-27)
-----------
* merge lua 5.3 offical bugfix
* improve sproto rpc api
* fix a deadlock bug when service retire
* improve cluster config reload
* add skynet.pcall for calling a function with `require`
* better error log in loginserver
v1.0.0-alpha4 (2015-4-13)
-----------
* sproto can share c struct between states
* udp api changed (use lua string now)
* fix memory leak in dns module
v1.0.0-alpha3 (2015-3-30)
-----------
* Update sproto (bugfix)
* Add async dns query
* improve httpc
v1.0.0-alpha2 (2015-3-16)
-----------
* Update examples client to lua 5.3

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2012-2014 codingnow.com
Copyright (c) 2012-2015 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

View File

@@ -5,7 +5,8 @@ CSERVICE_PATH ?= cservice
SKYNET_BUILD_PATH ?= .
CFLAGS = -g -O2 -Wall -I$(LUA_INC) $(MYCFLAGS)
CFLAGS = -g -O2 -Wall -I$(LUA_INC) $(MYCFLAGS)
# CFLAGS += -DUSE_PTHREAD_LOCK
# lua
@@ -23,7 +24,7 @@ JEMALLOC_INC := 3rd/jemalloc/include/jemalloc
all : jemalloc
.PHONY : jemalloc
.PHONY : jemalloc update3rd
MALLOC_STATICLIB := $(JEMALLOC_STATICLIB)
@@ -38,6 +39,9 @@ $(JEMALLOC_STATICLIB) : 3rd/jemalloc/Makefile
jemalloc : $(MALLOC_STATICLIB)
update3rd :
rm -rf 3rd/jemalloc && git submodule update --init
# skynet
CSERVICE = snlua logger gate harbor
@@ -79,7 +83,7 @@ $(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) $^ -o $@ -Iskynet-src
$(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
@@ -109,7 +113,7 @@ $(LUA_CLIB_PATH)/crypt.so : lualib-src/lua-crypt.c lualib-src/lsha1.c | $(LUA_CL
$(CC) $(CFLAGS) $(SHARED) $^ -o $@
$(LUA_CLIB_PATH)/sharedata.so : lualib-src/lua-sharedata.c | $(LUA_CLIB_PATH)
$(CC) $(CFLAGS) $(SHARED) $^ -o $@
$(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 $@
@@ -124,12 +128,15 @@ $(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) $^ -o $@
$(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
endif
cd 3rd/lua && $(MAKE) clean
rm -f $(LUA_STATICLIB)

View File

@@ -28,7 +28,9 @@ Run these in different console
## About Lua
Skynet now use Lua 5.3.0 final, http://www.lua.org/ftp/lua-5.3.0.tar.gz
Skynet now use a modify version of lua 5.3.1 (http://www.lua.org/ftp/lua-5.3.1.tar.gz) .
For detail : http://lua-users.org/lists/lua-l/2014-03/msg00489.html
You can also use the other official Lua version , edit the makefile by yourself .

View File

@@ -1,3 +1,4 @@
local skynet = require "skynet"
require "skynet.manager" -- import skynet.abort
skynet.abort()

View File

@@ -4,6 +4,7 @@ local socket = require "socket"
local sproto = require "sproto"
local sprotoloader = require "sprotoloader"
local WATCHDOG
local host
local send_request
@@ -26,6 +27,10 @@ function REQUEST:handshake()
return { msg = "Welcome to skynet, I will send heartbeat every 5 sec." }
end
function REQUEST:quit()
skynet.call(WATCHDOG, "lua", "close", client_fd)
end
local function request(name, args, response)
local f = assert(REQUEST[name])
local r = f(args)
@@ -62,7 +67,10 @@ skynet.register_protocol {
end
}
function CMD.start(gate, fd)
function CMD.start(conf)
local fd = conf.client
local gate = conf.gate
WATCHDOG = conf.watchdog
-- slot 1,2 set at main.lua
host = sprotoloader.load(1):host "package"
send_request = host:attach(sprotoloader.load(2))
@@ -77,6 +85,11 @@ function CMD.start(gate, fd)
skynet.call(gate, "lua", "forward", fd)
end
function CMD.disconnect()
-- todo: do something before exit
skynet.exit()
end
skynet.start(function()
skynet.dispatch("lua", function(_,_, command, ...)
local f = CMD[command]

View File

@@ -104,7 +104,11 @@ while true do
dispatch_package()
local cmd = socket.readstdin()
if cmd then
send_request("get", { what = cmd })
if cmd == "quit" then
send_request("quit")
else
send_request("get", { what = cmd })
end
else
socket.usleep(100)
end

View File

@@ -1,10 +1,19 @@
local skynet = require "skynet"
local cluster = require "cluster"
local snax = require "snax"
skynet.start(function()
local sdb = skynet.newservice("simpledb")
skynet.name(".simpledb", sdb)
print(skynet.call(".simpledb", "lua", "SET", "a", "foobar"))
print(skynet.call(".simpledb", "lua", "GET", "a"))
-- register name "sdb" for simpledb, you can use cluster.query() later.
-- See cluster2.lua
cluster.register("sdb", sdb)
print(skynet.call(sdb, "lua", "SET", "a", "foobar"))
print(skynet.call(sdb, "lua", "SET", "b", "foobar2"))
print(skynet.call(sdb, "lua", "GET", "a"))
print(skynet.call(sdb, "lua", "GET", "b"))
cluster.open "db"
cluster.open "db2"
-- unique snax service
snax.uniqueservice "pingserver"
end)

View File

@@ -2,7 +2,20 @@ local skynet = require "skynet"
local cluster = require "cluster"
skynet.start(function()
local proxy = cluster.proxy("db", ".simpledb")
print(skynet.call(proxy, "lua", "GET", "a"))
print(cluster.call("db", ".simpledb", "GET", "a"))
-- query name "sdb" of cluster db.
local sdb = cluster.query("db", "sdb")
print("db.sbd=",sdb)
local proxy = 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))
local v = skynet.call(proxy, "lua", "GET", largekey)
assert(largevalue == v)
print(cluster.call("db", sdb, "GET", "a"))
print(cluster.call("db2", sdb, "GET", "b"))
-- test snax service
local pingserver = cluster.snax("db", "pingserver")
print(pingserver.req.ping "hello")
end)

View File

@@ -1 +1,2 @@
db = "127.0.0.1:2528"
db2 = "127.0.0.1:2529"

View File

@@ -6,4 +6,5 @@ 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"
cluster = "./examples/clustername.lua"
snax = "./test/?.lua"

View File

@@ -6,4 +6,5 @@ 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"
cluster = "./examples/clustername.lua"
snax = "./test/?.lua"

15
examples/config.userlog Normal file
View File

@@ -0,0 +1,15 @@
root = "./"
thread = 8
logger = "userlog"
logservice = "snlua"
logpath = "."
harbor = 0
start = "main" -- main script
bootstrap = "snlua bootstrap" -- The service for bootstrap
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"

View File

@@ -1,4 +1,5 @@
local skynet = require "skynet"
require "skynet.manager" -- import skynet.register
skynet.start(function()
skynet.dispatch("lua", function(session, address, ...)

View File

@@ -131,7 +131,7 @@ local text = "echo"
local index = 1
print("connect")
local fd = assert(socket.connect("127.0.0.1", 8888))
fd = assert(socket.connect("127.0.0.1", 8888))
last = ""
local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index)
@@ -151,7 +151,7 @@ socket.close(fd)
index = index + 1
print("connect again")
local fd = assert(socket.connect("127.0.0.1", 8888))
fd = assert(socket.connect("127.0.0.1", 8888))
last = ""
local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index)

View File

@@ -17,7 +17,8 @@ function server.login_handler(uid, secret)
end
internal_id = internal_id + 1
local username = msgserver.username(uid, internal_id, servername)
local id = internal_id -- don't use internal_id directly
local username = msgserver.username(uid, id, servername)
-- you can use a pool to alloc new agent
local agent = skynet.newservice "msgagent"
@@ -25,11 +26,11 @@ function server.login_handler(uid, secret)
username = username,
agent = agent,
uid = uid,
subid = internal_id,
subid = id,
}
-- trash subid (no used)
skynet.call(agent, "lua", "login", uid, internal_id, secret)
skynet.call(agent, "lua", "login", uid, id, secret)
users[uid] = u
username_map[username] = u
@@ -37,7 +38,7 @@ function server.login_handler(uid, secret)
msgserver.login(username, secret)
-- you should return unique subid
return internal_id
return id
end
-- call by agent
@@ -73,9 +74,9 @@ function server.disconnect_handler(username)
end
-- call by self (when recv a request from client)
function server.request_handler(username, msg, sz)
function server.request_handler(username, msg)
local u = username_map[username]
return skynet.tostring(skynet.rawcall(u.agent, "client", msg, sz))
return skynet.tostring(skynet.rawcall(u.agent, "client", msg))
end
-- call by self (when gate open)

View File

@@ -1,5 +1,6 @@
local skynet = require "skynet"
local harbor = require "skynet.harbor"
require "skynet.manager" -- import skynet.monitor
local function monitor_master()
harbor.linkmaster()

View File

@@ -30,6 +30,8 @@ set 3 {
}
}
quit 4 {}
]]
proto.s2c = sprotoparser.parse [[

View File

@@ -37,6 +37,16 @@ skynet.start(function()
skynet.error(string.format("b[%d]=%s", k,v))
end
-- test lua serialization
local s = skynet.packstring(obj)
local nobj = skynet.unpack(s)
for k,v in pairs(nobj) do
skynet.error(string.format("nobj[%s]=%s", k,v))
end
for k,v in ipairs(nobj.b) do
skynet.error(string.format("nobj.b[%d]=%s", k,v))
end
for i = 1, 5 do
skynet.sleep(100)
skynet.error("second " ..i)

View File

@@ -1,4 +1,5 @@
local skynet = require "skynet"
require "skynet.manager" -- import skynet.register
local db = {}
local command = {}

15
examples/userlog.lua Normal file
View File

@@ -0,0 +1,15 @@
local skynet = require "skynet"
require "skynet.manager"
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))
end
}
skynet.start(function()
skynet.register ".logger"
end)

View File

@@ -9,14 +9,16 @@ local agent = {}
function SOCKET.open(fd, addr)
skynet.error("New client from : " .. addr)
agent[fd] = skynet.newservice("agent")
skynet.call(agent[fd], "lua", "start", gate, fd)
skynet.call(agent[fd], "lua", "start", { gate = gate, client = fd, watchdog = skynet.self() })
end
local function close_agent(fd)
local a = agent[fd]
agent[fd] = nil
if a then
skynet.kill(a)
agent[fd] = nil
skynet.call(gate, "lua", "kick", fd)
-- disconnect never return
skynet.send(a, "lua", "disconnect")
end
end
@@ -30,6 +32,11 @@ function SOCKET.error(fd, msg)
close_agent(fd)
end
function SOCKET.warning(fd, size)
-- size K bytes havn't send out in fd
print("socket warning", fd, size)
end
function SOCKET.data(fd, msg)
end
@@ -37,6 +44,10 @@ function CMD.start(conf)
skynet.call(gate, "lua", "open" , conf)
end
function CMD.close(fd)
close_agent(fd)
end
skynet.start(function()
skynet.dispatch("lua", function(session, source, cmd, subcmd, ...)
if cmd == "socket" then

View File

@@ -8,9 +8,12 @@
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "atomic.h"
#define DEFAULT_CAP 64
#define MAX_NUMBER 1024
// avoid circular reference while encodeing
#define MAX_DEPTH 128
#define BSON_REAL 1
#define BSON_STRING 2
@@ -235,7 +238,7 @@ write_double(struct bson *b, lua_Number d) {
}
}
static void pack_dict(lua_State *L, struct bson *b, bool array);
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) {
@@ -243,12 +246,16 @@ append_key(struct bson *bs, int type, const char *key, size_t sz) {
write_string(bs, key, sz);
}
static inline int
is_32bit(int64_t v) {
return v >= INT32_MIN && v <= INT32_MAX;
}
static void
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);
int si = i >> 31;
if (si == 0 || si == -1) {
if (is_32bit(i)) {
append_key(bs, BSON_INT32, key, sz);
write_int32(bs, i);
} else {
@@ -263,7 +270,7 @@ append_number(struct bson *bs, lua_State *L, const char *key, size_t sz) {
}
static void
append_table(struct bson *bs, lua_State *L, const char *key, size_t sz) {
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) {
@@ -279,7 +286,7 @@ append_table(struct bson *bs, lua_State *L, const char *key, size_t sz) {
} else {
append_key(bs, BSON_DOCUMENT, key, sz);
}
pack_dict(L, bs, isarray);
pack_dict(L, bs, isarray, depth);
}
static void
@@ -292,7 +299,7 @@ write_binary(struct bson *b, const void * buffer, size_t sz) {
}
static void
append_one(struct bson *bs, lua_State *L, const char *key, size_t sz) {
append_one(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth) {
int vt = lua_type(L,-1);
switch(vt) {
case LUA_TNUMBER:
@@ -380,7 +387,7 @@ append_one(struct bson *bs, lua_State *L, const char *key, size_t sz) {
break;
}
case LUA_TTABLE:
append_table(bs, L, key, sz);
append_table(bs, L, key, sz, depth+1);
break;
case LUA_TBOOLEAN:
append_key(bs, BSON_BOOLEAN, key, sz);
@@ -402,7 +409,11 @@ bson_numstr( char *str, unsigned int i ) {
}
static void
pack_dict(lua_State *L, struct bson *b, bool isarray) {
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
int length = reserve_length(b);
lua_pushnil(L);
while(lua_next(L,-2) != 0) {
@@ -418,7 +429,7 @@ pack_dict(lua_State *L, struct bson *b, bool isarray) {
sz = bson_numstr(numberkey, (unsigned int)lua_tointeger(L,-2)-1);
key = numberkey;
append_one(b, L, key, sz);
append_one(b, L, key, sz, depth);
lua_pop(L,1);
} else {
switch(kt) {
@@ -427,12 +438,12 @@ pack_dict(lua_State *L, struct bson *b, bool isarray) {
lua_pushvalue(L,-2);
lua_insert(L,-2);
key = lua_tolstring(L,-2,&sz);
append_one(b, L, key, 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);
append_one(b, L, key, sz, depth);
lua_pop(L,1);
break;
default:
@@ -446,7 +457,7 @@ pack_dict(lua_State *L, struct bson *b, bool isarray) {
}
static void
pack_ordered_dict(lua_State *L, struct bson *b, int n) {
pack_ordered_dict(lua_State *L, struct bson *b, int n, int depth) {
int length = reserve_length(b);
int i;
for (i=0;i<n;i+=2) {
@@ -456,7 +467,7 @@ pack_ordered_dict(lua_State *L, struct bson *b, int n) {
luaL_error(L, "Argument %d need a string", i+1);
}
lua_pushvalue(L, i+2);
append_one(b, L, key, sz);
append_one(b, L, key, sz, depth);
lua_pop(L,1);
}
write_byte(b,0);
@@ -490,6 +501,7 @@ make_object(lua_State *L, int type, const void * ptr, size_t len) {
static void
unpack_dict(lua_State *L, struct bson_reader *br, bool array) {
luaL_checkstack(L, 16, NULL); // reserve enough stack space to unpack table
int sz = read_int32(L, br);
const void * bytes = read_bytes(L, br, sz-5);
struct bson_reader t = { bytes, sz-5 };
@@ -841,7 +853,7 @@ lencode(lua_State *L) {
bson_create(&b);
lua_settop(L,1);
luaL_checktype(L, 1, LUA_TTABLE);
pack_dict(L, &b, false);
pack_dict(L, &b, false, 0);
void * ud = lua_newuserdata(L, b.size);
memcpy(ud, b.ptr, b.size);
bson_destroy(&b);
@@ -857,7 +869,7 @@ lencode_order(lua_State *L) {
if (n%2 != 0) {
return luaL_error(L, "Invalid ordered dict");
}
pack_ordered_dict(L, &b, n);
pack_ordered_dict(L, &b, n, 0);
lua_settop(L,1);
void * ud = lua_newuserdata(L, b.size);
memcpy(ud, b.ptr, b.size);
@@ -1135,15 +1147,17 @@ lobjectid(lua_State *L) {
}
} else {
time_t ti = time(NULL);
// old_counter is a static var, use atom inc.
uint32_t id = ATOM_FINC(&oid_counter);
oid[2] = (ti>>24) & 0xff;
oid[3] = (ti>>16) & 0xff;
oid[4] = (ti>>8) & 0xff;
oid[5] = ti & 0xff;
memcpy(oid+6 , oid_header, 5);
oid[11] = (oid_counter>>16) & 0xff;
oid[12] = (oid_counter>>8) & 0xff;
oid[13] = oid_counter & 0xff;
++oid_counter;
oid[11] = (id>>16) & 0xff;
oid[12] = (id>>8) & 0xff;
oid[13] = id & 0xff;
}
lua_pushlstring( L, (const char *)oid, 14);

View File

@@ -128,11 +128,8 @@ lusleep(lua_State *L) {
#define QUEUE_SIZE 1024
#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
#define UNLOCK(q) __sync_lock_release(&(q)->lock);
struct queue {
int lock;
pthread_mutex_t lock;
int head;
int tail;
char * queue[QUEUE_SIZE];
@@ -153,7 +150,7 @@ readline_stdin(void * arg) {
memcpy(str, tmp, n);
str[n] = 0;
LOCK(q);
pthread_mutex_lock(&q->lock);
q->queue[q->tail] = str;
if (++q->tail >= QUEUE_SIZE) {
@@ -163,7 +160,7 @@ readline_stdin(void * arg) {
// queue overflow
exit(1);
}
UNLOCK(q);
pthread_mutex_unlock(&q->lock);
}
return NULL;
}
@@ -171,16 +168,16 @@ readline_stdin(void * arg) {
static int
lreadstdin(lua_State *L) {
struct queue *q = lua_touserdata(L, lua_upvalueindex(1));
LOCK(q);
pthread_mutex_lock(&q->lock);
if (q->head == q->tail) {
UNLOCK(q);
pthread_mutex_unlock(&q->lock);
return 0;
}
char * str = q->queue[q->head];
if (++q->head >= QUEUE_SIZE) {
q->head = 0;
}
UNLOCK(q);
pthread_mutex_unlock(&q->lock);
lua_pushstring(L, str);
free(str);
return 1;
@@ -201,6 +198,7 @@ luaopen_clientsocket(lua_State *L) {
struct queue * q = lua_newuserdata(L, sizeof(*q));
memset(q, 0, sizeof(*q));
pthread_mutex_init(&q->lock, NULL);
lua_pushcclosure(L, lreadstdin, 1);
lua_setfield(L, -2, "readstdin");

View File

@@ -1,6 +1,7 @@
#include <lua.h>
#include <lauxlib.h>
#include <string.h>
#include <assert.h>
#include "skynet.h"
@@ -15,7 +16,8 @@
uint32_t next_session
*/
#define TEMP_LENGTH 0x10007
#define TEMP_LENGTH 0x8200
#define MULTI_PART 0x8000
static void
fill_uint32(uint8_t * buf, uint32_t n) {
@@ -26,30 +28,75 @@ fill_uint32(uint8_t * buf, uint32_t n) {
}
static void
fill_header(lua_State *L, uint8_t *buf, int sz, void *msg) {
if (sz >= 0x10000) {
skynet_free(msg);
luaL_error(L, "request message is too long %d", sz);
}
fill_header(lua_State *L, uint8_t *buf, int sz) {
assert(sz < 0x10000);
buf[0] = (sz >> 8) & 0xff;
buf[1] = sz & 0xff;
}
static void
packreq_number(lua_State *L, int session, void * msg, size_t sz) {
/*
The request package :
size <= 0x8000 (32K) and address is id
WORD sz+9
BYTE 0
DWORD addr
DWORD session
PADDING msg(sz)
size > 0x8000 and address is id
DWORD 13
BYTE 1 ; multireq
DWORD addr
DWORD session
DWORD sz
size <= 0x8000 (32K) and address is string
WORD sz+6+namelen
BYTE 0x80
BYTE namelen
STRING name
DWORD session
PADDING msg(sz)
size > 0x8000 and address is string
DWORD 10 + namelen
BYTE 0x81
BYTE namelen
STRING name
DWORD session
DWORD sz
multi req
WORD sz + 5
BYTE 2/3 ; 2:multipart, 3:multipart end
DWORD SESSION
PADDING msgpart(sz)
*/
static int
packreq_number(lua_State *L, int session, void * msg, uint32_t sz) {
uint32_t addr = (uint32_t)lua_tointeger(L,1);
uint8_t buf[TEMP_LENGTH];
fill_header(L, buf, sz+9, msg);
buf[2] = 0;
fill_uint32(buf+3, addr);
fill_uint32(buf+7, (uint32_t)session);
memcpy(buf+11,msg,sz);
if (sz < MULTI_PART) {
fill_header(L, buf, sz+9);
buf[2] = 0;
fill_uint32(buf+3, addr);
fill_uint32(buf+7, (uint32_t)session);
memcpy(buf+11,msg,sz);
lua_pushlstring(L, (const char *)buf, sz+11);
lua_pushlstring(L, (const char *)buf, sz+11);
return 0;
} else {
int part = (sz - 1) / MULTI_PART + 1;
fill_header(L, buf, 13);
buf[2] = 1;
fill_uint32(buf+3, addr);
fill_uint32(buf+7, (uint32_t)session);
fill_uint32(buf+11, sz);
lua_pushlstring(L, (const char *)buf, 15);
return part;
}
}
static void
packreq_string(lua_State *L, int session, void * msg, size_t sz) {
static int
packreq_string(lua_State *L, int session, void * msg, uint32_t sz) {
size_t namelen = 0;
const char *name = lua_tolstring(L, 1, &namelen);
if (name == NULL || namelen < 1 || namelen > 255) {
@@ -58,13 +105,53 @@ packreq_string(lua_State *L, int session, void * msg, size_t sz) {
}
uint8_t buf[TEMP_LENGTH];
fill_header(L, buf, sz+5+namelen, msg);
buf[2] = (uint8_t)namelen;
memcpy(buf+3, name, namelen);
fill_uint32(buf+3+namelen, (uint32_t)session);
memcpy(buf+7+namelen,msg,sz);
if (sz < MULTI_PART) {
fill_header(L, buf, sz+6+namelen);
buf[2] = 0x80;
buf[3] = (uint8_t)namelen;
memcpy(buf+4, name, namelen);
fill_uint32(buf+4+namelen, (uint32_t)session);
memcpy(buf+8+namelen,msg,sz);
lua_pushlstring(L, (const char *)buf, sz+7+namelen);
lua_pushlstring(L, (const char *)buf, sz+8+namelen);
return 0;
} else {
int part = (sz - 1) / MULTI_PART + 1;
fill_header(L, buf, 10+namelen);
buf[2] = 0x81;
buf[3] = (uint8_t)namelen;
memcpy(buf+4, name, namelen);
fill_uint32(buf+4+namelen, (uint32_t)session);
fill_uint32(buf+8+namelen, sz);
lua_pushlstring(L, (const char *)buf, 12+namelen);
return part;
}
}
static void
packreq_multi(lua_State *L, int session, void * msg, uint32_t sz) {
uint8_t buf[TEMP_LENGTH];
int part = (sz - 1) / MULTI_PART + 1;
int i;
char *ptr = msg;
for (i=0;i<part;i++) {
uint32_t s;
if (sz > MULTI_PART) {
s = MULTI_PART;
buf[2] = 2;
} else {
s = sz;
buf[2] = 3; // the last multi part
}
fill_header(L, buf, s+5);
fill_uint32(buf+3, (uint32_t)session);
memcpy(buf+7, ptr, s);
lua_pushlstring(L, (const char *)buf, s+7);
lua_rawseti(L, -2, i+1);
sz -= s;
ptr += s;
}
}
static int
@@ -73,23 +160,33 @@ lpackrequest(lua_State *L) {
if (msg == NULL) {
return luaL_error(L, "Invalid request message");
}
size_t sz = (size_t)luaL_checkinteger(L,4);
uint32_t sz = (uint32_t)luaL_checkinteger(L,4);
int session = luaL_checkinteger(L,2);
if (session <= 0) {
skynet_free(msg);
return luaL_error(L, "Invalid request session %d", session);
}
int addr_type = lua_type(L,1);
int multipak;
if (addr_type == LUA_TNUMBER) {
packreq_number(L, session, msg, sz);
multipak = packreq_number(L, session, msg, sz);
} else {
packreq_string(L, session, msg, sz);
multipak = packreq_string(L, session, msg, sz);
}
int current_session = session;
if (++session < 0) {
session = 1;
}
skynet_free(msg);
lua_pushinteger(L, session);
return 2;
if (multipak) {
lua_createtable(L, multipak, 0);
packreq_multi(L, current_session, msg, sz);
skynet_free(msg);
return 3;
} else {
skynet_free(msg);
return 2;
}
}
/*
@@ -98,6 +195,7 @@ lpackrequest(lua_State *L) {
uint32_t or string addr
int session
string msg
boolean padding
*/
static inline uint32_t
@@ -106,44 +204,122 @@ unpack_uint32(const uint8_t * buf) {
}
static int
unpackreq_number(lua_State *L, const uint8_t * buf, size_t sz) {
unpackreq_number(lua_State *L, const uint8_t * buf, int sz) {
if (sz < 9) {
return luaL_error(L, "Invalid cluster message");
return luaL_error(L, "Invalid cluster message (size=%d)", sz);
}
uint32_t address = unpack_uint32(buf+1);
uint32_t session = unpack_uint32(buf+5);
lua_pushinteger(L, (uint32_t)address);
lua_pushinteger(L, (uint32_t)session);
lua_pushinteger(L, address);
lua_pushinteger(L, session);
lua_pushlstring(L, (const char *)buf+9, sz-9);
return 3;
}
static int
unpackreq_string(lua_State *L, const uint8_t * buf, size_t sz) {
size_t namesz = buf[0];
if (sz < namesz + 5) {
return luaL_error(L, "Invalid cluster message");
unpackmreq_number(lua_State *L, const uint8_t * buf, int sz) {
if (sz != 13) {
return luaL_error(L, "Invalid cluster message size %d (multi req must be 13)", sz);
}
lua_pushlstring(L, (const char *)buf+1, namesz);
uint32_t session = unpack_uint32(buf + namesz + 1);
uint32_t address = unpack_uint32(buf+1);
uint32_t session = unpack_uint32(buf+5);
uint32_t size = unpack_uint32(buf+9);
lua_pushinteger(L, address);
lua_pushinteger(L, session);
lua_pushinteger(L, size);
lua_pushboolean(L, 1); // padding multi part
return 4;
}
static int
unpackmreq_part(lua_State *L, const uint8_t * buf, int sz) {
if (sz < 5) {
return luaL_error(L, "Invalid cluster multi part message");
}
int padding = (buf[0] == 2);
uint32_t session = unpack_uint32(buf+1);
lua_pushboolean(L, 0); // no address
lua_pushinteger(L, session);
lua_pushlstring(L, (const char *)buf+5, sz-5);
lua_pushboolean(L, padding);
return 4;
}
static int
unpackreq_string(lua_State *L, const uint8_t * buf, int sz) {
if (sz < 2) {
return luaL_error(L, "Invalid cluster message (size=%d)", sz);
}
size_t namesz = buf[1];
if (sz < namesz + 6) {
return luaL_error(L, "Invalid cluster message (size=%d)", sz);
}
lua_pushlstring(L, (const char *)buf+2, namesz);
uint32_t session = unpack_uint32(buf + namesz + 2);
lua_pushinteger(L, (uint32_t)session);
lua_pushlstring(L, (const char *)buf+1+namesz+4, sz - namesz - 5);
lua_pushlstring(L, (const char *)buf+2+namesz+4, sz - namesz - 6);
return 3;
}
static int
unpackmreq_string(lua_State *L, const uint8_t * buf, int sz) {
if (sz < 2) {
return luaL_error(L, "Invalid cluster message (size=%d)", sz);
}
size_t namesz = buf[1];
if (sz < namesz + 10) {
return luaL_error(L, "Invalid cluster message (size=%d)", sz);
}
lua_pushlstring(L, (const char *)buf+2, namesz);
uint32_t session = unpack_uint32(buf + namesz + 2);
uint32_t size = unpack_uint32(buf + namesz + 6);
lua_pushinteger(L, session);
lua_pushinteger(L, size);
lua_pushboolean(L, 1); // padding multipart
return 4;
}
static int
lunpackrequest(lua_State *L) {
size_t sz;
const char *msg = luaL_checklstring(L,1,&sz);
if (msg[0] == 0) {
size_t ssz;
const char *msg = luaL_checklstring(L,1,&ssz);
int sz = (int)ssz;
switch (msg[0]) {
case 0:
return unpackreq_number(L, (const uint8_t *)msg, sz);
} else {
case 1:
return unpackmreq_number(L, (const uint8_t *)msg, sz);
case 2:
case 3:
return unpackmreq_part(L, (const uint8_t *)msg, sz);
case '\x80':
return unpackreq_string(L, (const uint8_t *)msg, sz);
case '\x81':
return unpackmreq_string(L, (const uint8_t *)msg, sz);
default:
return luaL_error(L, "Invalid req package type %d", msg[0]);
}
}
/*
DWORD session
BYTE type
0: error
1: ok
2: multi begin
3: multi part
4: multi end
PADDING msg
type = 0, error msg
type = 1, msg
type = 2, DWORD size
type = 3/4, msg
*/
/*
int session
boolean ok
@@ -162,16 +338,56 @@ lpackresponse(lua_State *L) {
if (lua_type(L,3) == LUA_TSTRING) {
msg = (void *)lua_tolstring(L, 3, &sz);
if (sz > 0x1000) {
sz = 0x1000;
}
} else {
msg = lua_touserdata(L,3);
sz = (size_t)luaL_checkinteger(L, 4);
}
if (!ok) {
if (sz > MULTI_PART) {
// truncate the error msg if too long
sz = MULTI_PART;
}
} else {
if (sz > MULTI_PART) {
// return
int part = (sz - 1) / MULTI_PART + 1;
lua_createtable(L, part+1, 0);
uint8_t buf[TEMP_LENGTH];
// multi part begin
fill_header(L, buf, 9);
fill_uint32(buf+2, session);
buf[6] = 2;
fill_uint32(buf+7, (uint32_t)sz);
lua_pushlstring(L, (const char *)buf, 11);
lua_rawseti(L, -2, 1);
char * ptr = msg;
int i;
for (i=0;i<part;i++) {
int s;
if (sz > MULTI_PART) {
s = MULTI_PART;
buf[6] = 3;
} else {
s = sz;
buf[6] = 4;
}
fill_header(L, buf, s+5);
fill_uint32(buf+2, session);
memcpy(buf+7,ptr,s);
lua_pushlstring(L, (const char *)buf, s+7);
lua_rawseti(L, -2, i+2);
sz -= s;
ptr += s;
}
return 1;
}
}
uint8_t buf[TEMP_LENGTH];
fill_header(L, buf, sz+5, msg);
fill_header(L, buf, sz+5);
fill_uint32(buf+2, session);
buf[6] = ok;
memcpy(buf+7,msg,sz);
@@ -186,6 +402,7 @@ lpackresponse(lua_State *L) {
return integer session
boolean ok
string msg
boolean padding
*/
static int
lunpackresponse(lua_State *L) {
@@ -196,10 +413,66 @@ lunpackresponse(lua_State *L) {
}
uint32_t session = unpack_uint32((const uint8_t *)buf);
lua_pushinteger(L, (lua_Integer)session);
lua_pushboolean(L, buf[4]);
lua_pushlstring(L, buf+5, sz-5);
switch(buf[4]) {
case 0: // error
lua_pushboolean(L, 0);
lua_pushlstring(L, buf+5, sz-5);
return 3;
case 1: // ok
case 4: // multi end
lua_pushboolean(L, 1);
lua_pushlstring(L, buf+5, sz-5);
return 3;
case 2: // multi begin
if (sz != 9) {
return 0;
}
sz = unpack_uint32((const uint8_t *)buf+5);
lua_pushboolean(L, 1);
lua_pushinteger(L, sz);
lua_pushboolean(L, 1);
return 4;
case 3: // multi part
lua_pushboolean(L, 1);
lua_pushlstring(L, buf+5, sz-5);
lua_pushboolean(L, 1);
return 4;
default:
return 0;
}
}
return 3;
static int
lconcat(lua_State *L) {
if (!lua_istable(L,1))
return 0;
if (lua_geti(L,1,1) != LUA_TNUMBER)
return 0;
int sz = lua_tointeger(L,-1);
lua_pop(L,1);
char * buff = skynet_malloc(sz);
int idx = 2;
int offset = 0;
while(lua_geti(L,1,idx) == LUA_TSTRING) {
size_t s;
const char * str = lua_tolstring(L, -1, &s);
if (s+offset > sz) {
skynet_free(buff);
return 0;
}
memcpy(buff+offset, str, s);
lua_pop(L,1);
offset += s;
++idx;
}
if (offset != sz) {
skynet_free(buff);
return 0;
}
// buff/sz will send to other service, See clusterd.lua
lua_pushlightuserdata(L, buff);
lua_pushinteger(L, sz);
return 2;
}
int
@@ -209,6 +482,7 @@ luaopen_cluster_core(lua_State *L) {
{ "unpackrequest", lunpackrequest },
{ "packresponse", lpackresponse },
{ "unpackresponse", lunpackresponse },
{ "concat", lconcat },
{ NULL, NULL },
};
luaL_checkversion(L);

View File

@@ -10,7 +10,7 @@
/* the eight DES S-boxes */
uint32_t SB1[64] = {
static uint32_t SB1[64] = {
0x01010400, 0x00000000, 0x00010000, 0x01010404,
0x01010004, 0x00010404, 0x00000004, 0x00010000,
0x00000400, 0x01010400, 0x01010404, 0x00000400,
@@ -338,8 +338,13 @@ static int
lrandomkey(lua_State *L) {
char tmp[8];
int i;
char x = 0;
for (i=0;i<8;i++) {
tmp[i] = random() & 0xff;
x ^= tmp[i];
}
if (x==0) {
tmp[0] |= 1; // avoid 0
}
lua_pushlstring(L, tmp, 8);
return 1;
@@ -602,11 +607,7 @@ read64(lua_State *L, uint32_t xx[2], uint32_t yy[2]) {
}
static int
lhmac64(lua_State *L) {
uint32_t x[2], y[2];
read64(L, x, y);
uint32_t result[2];
hmac(x,y,result);
pushqword(lua_State *L, uint32_t result[2]) {
uint8_t tmp[8];
tmp[0] = result[0] & 0xff;
tmp[1] = (result[0] >> 8 )& 0xff;
@@ -621,6 +622,40 @@ lhmac64(lua_State *L) {
return 1;
}
static int
lhmac64(lua_State *L) {
uint32_t x[2], y[2];
read64(L, x, y);
uint32_t result[2];
hmac(x,y,result);
return pushqword(L, result);
}
/*
8bytes key
string text
*/
static int
lhmac_hash(lua_State *L) {
uint32_t key[2];
size_t sz = 0;
const uint8_t *x = (const uint8_t *)luaL_checklstring(L, 1, &sz);
if (sz != 8) {
luaL_error(L, "Invalid uint64 key");
}
key[0] = x[0] | x[1]<<8 | x[2]<<16 | x[3]<<24;
key[1] = x[4] | x[5]<<8 | x[6]<<16 | x[7]<<24;
const char * text = luaL_checklstring(L, 2, &sz);
uint8_t h[8];
Hash(text,(int)sz,h);
uint32_t htext[2];
htext[0] = h[0] | h[1]<<8 | h[2]<<16 | h[3]<<24;
htext[1] = h[4] | h[5]<<8 | h[6]<<16 | h[7]<<24;
uint32_t result[2];
hmac(htext,key,result);
return pushqword(L, result);
}
// powmodp64 for DH-key exchange
// The biggest 64bit prime
@@ -688,8 +723,11 @@ static int
ldhsecret(lua_State *L) {
uint32_t x[2], y[2];
read64(L, x, y);
uint64_t r = powmodp((uint64_t)x[0] | (uint64_t)x[1]<<32,
(uint64_t)y[0] | (uint64_t)y[1]<<32);
uint64_t xx = (uint64_t)x[0] | (uint64_t)x[1]<<32;
uint64_t yy = (uint64_t)y[0] | (uint64_t)y[1]<<32;
if (xx == 0 || yy == 0)
return luaL_error(L, "Can't be 0");
uint64_t r = powmodp(xx, yy);
push64(L, r);
@@ -709,7 +747,11 @@ ldhexchange(lua_State *L) {
xx[0] = x[0] | x[1]<<8 | x[2]<<16 | x[3]<<24;
xx[1] = x[4] | x[5]<<8 | x[6]<<16 | x[7]<<24;
uint64_t r = powmodp(5, (uint64_t)xx[0] | (uint64_t)xx[1]<<32);
uint64_t x64 = (uint64_t)xx[0] | (uint64_t)xx[1]<<32;
if (x64 == 0)
return luaL_error(L, "Can't be 0");
uint64_t r = powmodp(5, x64);
push64(L, r);
return 1;
}
@@ -858,6 +900,7 @@ luaopen_crypt(lua_State *L) {
{ "base64decode", lb64decode },
{ "sha1", lsha1 },
{ "hmac_sha1", lhmac_sha1 },
{ "hmac_hash", lhmac_hash },
{ NULL, NULL },
};
luaL_newlib(L,l);

View File

@@ -4,10 +4,9 @@
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "spinlock.h"
#define METANAME "debugchannel"
#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
#define UNLOCK(q) __sync_lock_release(&(q)->lock);
struct command {
struct command * next;
@@ -15,7 +14,7 @@ struct command {
};
struct channel {
int lock;
struct spinlock lock;
int ref;
struct command * head;
struct command * tail;
@@ -26,6 +25,7 @@ channel_new() {
struct channel * c = malloc(sizeof(*c));
memset(c, 0 , sizeof(*c));
c->ref = 1;
SPIN_INIT(c)
return c;
}
@@ -33,21 +33,21 @@ channel_new() {
static struct channel *
channel_connect(struct channel *c) {
struct channel * ret = NULL;
LOCK(c)
SPIN_LOCK(c)
if (c->ref == 1) {
++c->ref;
ret = c;
}
UNLOCK(c)
SPIN_UNLOCK(c)
return ret;
}
static struct channel *
channel_release(struct channel *c) {
LOCK(c)
SPIN_LOCK(c)
--c->ref;
if (c->ref > 0) {
UNLOCK(c)
SPIN_UNLOCK(c)
return c;
}
// never unlock while reference is 0
@@ -59,6 +59,9 @@ channel_release(struct channel *c) {
free(p);
p = next;
}
SPIN_UNLOCK(c)
SPIN_DESTROY(c)
free(c);
return NULL;
}
@@ -66,9 +69,9 @@ channel_release(struct channel *c) {
static struct command *
channel_read(struct channel *c, double timeout) {
struct command * ret = NULL;
LOCK(c)
SPIN_LOCK(c)
if (c->head == NULL) {
UNLOCK(c)
SPIN_UNLOCK(c)
int ti = (int)(timeout * 100000);
usleep(ti);
return NULL;
@@ -78,7 +81,7 @@ channel_read(struct channel *c, double timeout) {
if (c->head == NULL) {
c->tail = NULL;
}
UNLOCK(c)
SPIN_UNLOCK(c)
return ret;
}
@@ -89,14 +92,14 @@ channel_write(struct channel *c, const char * s, size_t sz) {
cmd->sz = sz;
cmd->next = NULL;
memcpy(cmd+1, s, sz);
LOCK(c)
SPIN_LOCK(c)
if (c->tail == NULL) {
c->head = c->tail = cmd;
} else {
c->tail->next = cmd;
c->tail = cmd;
}
UNLOCK(c)
SPIN_UNLOCK(c)
}
struct channel_box {

View File

@@ -2,6 +2,7 @@
#include <lauxlib.h>
#include "malloc_hook.h"
#include "luashrtbl.h"
static int
ltotal(lua_State *L) {
@@ -33,6 +34,13 @@ ldump(lua_State *L) {
return 0;
}
static int
lexpandshrtbl(lua_State *L) {
int n = luaL_checkinteger(L, 1);
luaS_expandshr(n);
return 0;
}
int
luaopen_memory(lua_State *L) {
luaL_checkversion(L);
@@ -42,6 +50,9 @@ luaopen_memory(lua_State *L) {
{ "block", lblock },
{ "dumpinfo", ldumpinfo },
{ "dump", ldump },
{ "info", dump_mem_lua },
{ "ssinfo", luaS_shrinfo },
{ "ssexpand", lexpandshrtbl },
{ NULL, NULL },
};

View File

@@ -5,6 +5,8 @@
#include <stdint.h>
#include <string.h>
#include "atomic.h"
struct mc_package {
int reference;
uint32_t size;
@@ -116,7 +118,7 @@ static int
mc_closelocal(lua_State *L) {
struct mc_package *pack = lua_touserdata(L,1);
int ref = __sync_sub_and_fetch(&pack->reference, 1);
int ref = ATOM_DEC(&pack->reference);
if (ref <= 0) {
skynet_free(pack->data);
skynet_free(pack);

View File

@@ -19,6 +19,7 @@
#define TYPE_ERROR 3
#define TYPE_OPEN 4
#define TYPE_CLOSE 5
#define TYPE_WARNING 6
/*
Each package is uint16 + data , uint16 (serialized in big-endian) is the number of bytes comprising the data .
@@ -48,6 +49,7 @@ struct queue {
static void
clear_list(struct uncomplete * uc) {
while (uc) {
skynet_free(uc->pack.buffer);
void * tmp = uc;
uc = uc->next;
skynet_free(tmp);
@@ -210,6 +212,16 @@ push_more(lua_State *L, int fd, uint8_t *buffer, int size) {
}
}
static void
close_uncomplete(lua_State *L, int fd) {
struct queue *q = lua_touserdata(L,1);
struct uncomplete * uc = find_uncomplete(q, fd);
if (uc) {
skynet_free(uc->pack.buffer);
skynet_free(uc);
}
}
static int
filter_data_(lua_State *L, int fd, uint8_t * buffer, int size) {
struct queue *q = lua_touserdata(L,1);
@@ -343,6 +355,8 @@ lfilter(lua_State *L) {
// ignore listen fd connect
return 1;
case SKYNET_SOCKET_TYPE_CLOSE:
// no more data in fd (message->id)
close_uncomplete(L, message->id);
lua_pushvalue(L, lua_upvalueindex(TYPE_CLOSE));
lua_pushinteger(L, message->id);
return 3;
@@ -353,10 +367,17 @@ lfilter(lua_State *L) {
pushstring(L, buffer, size);
return 4;
case SKYNET_SOCKET_TYPE_ERROR:
// no more data in fd (message->id)
close_uncomplete(L, message->id);
lua_pushvalue(L, lua_upvalueindex(TYPE_ERROR));
lua_pushinteger(L, message->id);
pushstring(L, buffer, size);
return 4;
case SKYNET_SOCKET_TYPE_WARNING:
lua_pushvalue(L, lua_upvalueindex(TYPE_WARNING));
lua_pushinteger(L, message->id);
lua_pushinteger(L, message->ud);
return 4;
default:
// never get here
return 1;
@@ -428,57 +449,6 @@ lpack(lua_State *L) {
return 2;
}
static int
lpack_string(lua_State *L) {
uint8_t tmp[SMALLSTRING+2];
size_t len;
uint8_t *buffer;
const char * ptr = tolstring(L, &len, 1);
if (len > 0x10000) {
return luaL_error(L, "Invalid size (too long) of data : %d", (int)len);
}
if (len <= SMALLSTRING) {
buffer = tmp;
} else {
buffer = lua_newuserdata(L, len + 2);
}
write_size(buffer, len);
memcpy(buffer+2, ptr, len);
lua_pushlstring(L, (const char *)buffer, len+2);
return 1;
}
static int
lpack_padding(lua_State *L) {
uint8_t tmp[SMALLSTRING+2];
size_t content_sz;
uint8_t *buffer;
const char * ptr = tolstring(L, &content_sz, 2);
size_t cookie_sz = 0;
const char * cookie = luaL_checklstring(L,1,&cookie_sz);
size_t len = cookie_sz + content_sz;
if (len > 0x10000) {
return luaL_error(L, "Invalid size (too long) of data : %d", (int)len);
}
if (len <= SMALLSTRING) {
buffer = tmp;
} else {
buffer = lua_newuserdata(L, len + 2);
}
write_size(buffer, len);
memcpy(buffer+2, ptr, content_sz);
memcpy(buffer+2+content_sz, cookie, cookie_sz);
lua_pushlstring(L, (const char *)buffer, len+2);
return 1;
}
static int
ltostring(lua_State *L) {
void * ptr = lua_touserdata(L, 1);
@@ -486,19 +456,8 @@ ltostring(lua_State *L) {
if (ptr == NULL) {
lua_pushliteral(L, "");
} else {
if (lua_isnumber(L, 3)) {
int offset = lua_tointeger(L, 3);
if (offset < 0) {
return luaL_error(L, "Invalid offset %d", offset);
}
if (offset > size) {
offset = size;
}
lua_pushlstring(L, (const char *)ptr + offset, size-offset);
} else {
lua_pushlstring(L, (const char *)ptr, size);
skynet_free(ptr);
}
lua_pushlstring(L, (const char *)ptr, size);
skynet_free(ptr);
}
return 1;
}
@@ -509,8 +468,6 @@ luaopen_netpack(lua_State *L) {
luaL_Reg l[] = {
{ "pop", lpop },
{ "pack", lpack },
{ "pack_string", lpack_string },
{ "pack_padding", lpack_padding },
{ "clear", lclear },
{ "tostring", ltostring },
{ NULL, NULL },
@@ -523,8 +480,9 @@ luaopen_netpack(lua_State *L) {
lua_pushliteral(L, "error");
lua_pushliteral(L, "open");
lua_pushliteral(L, "close");
lua_pushliteral(L, "warning");
lua_pushcclosure(L, lfilter, 5);
lua_pushcclosure(L, lfilter, 6);
lua_setfield(L, -2, "filter");
return 1;

View File

@@ -254,13 +254,41 @@ wb_table_hash(lua_State *L, struct write_block * wb, int index, int depth, int a
wb_nil(wb);
}
static void
wb_table_metapairs(lua_State *L, struct write_block *wb, int index, int depth) {
uint8_t n = COMBINE_TYPE(TYPE_TABLE, 0);
wb_push(wb, &n, 1);
lua_pushvalue(L, index);
lua_call(L, 1, 3);
for(;;) {
lua_pushvalue(L, -2);
lua_pushvalue(L, -2);
lua_copy(L, -5, -3);
lua_call(L, 2, 2);
int type = lua_type(L, -2);
if (type == LUA_TNIL) {
lua_pop(L, 4);
break;
}
pack_one(L, wb, -2, depth);
pack_one(L, wb, -1, depth);
lua_pop(L, 1);
}
wb_nil(wb);
}
static void
wb_table(lua_State *L, struct write_block *wb, int index, int depth) {
luaL_checkstack(L, LUA_MINSTACK, NULL);
if (index < 0) {
index = lua_gettop(L) + index + 1;
}
int array_size = wb_table_array(L, wb, index, depth);
wb_table_hash(L, wb, index, depth, array_size);
if (luaL_getmetafield(L, index, "__pairs") != LUA_TNIL) {
wb_table_metapairs(L, wb, index, depth);
} else {
int array_size = wb_table_array(L, wb, index, depth);
wb_table_hash(L, wb, index, depth, array_size);
}
}
static void
@@ -416,6 +444,7 @@ unpack_table(lua_State *L, struct read_block *rb, int array_size) {
}
array_size = get_integer(L,rb,cookie);
}
luaL_checkstack(L,LUA_MINSTACK,NULL);
lua_createtable(L,array_size,0);
int i;
for (i=1;i<=array_size;i++) {
@@ -549,8 +578,8 @@ _luaseri_unpack(lua_State *L) {
int i;
for (i=0;;i++) {
if (i%16==15) {
lua_checkstack(L,i);
if (i%8==7) {
luaL_checkstack(L,LUA_MINSTACK,NULL);
}
uint8_t type = 0;
uint8_t *t = rb_read(&rb, sizeof(type));

View File

@@ -4,6 +4,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "atomic.h"
#define KEYTYPE_INTEGER 0
#define KEYTYPE_STRING 1
@@ -35,8 +36,6 @@ struct node {
uint8_t nocolliding; // 0 means colliding slot
};
struct table;
struct state {
int dirty;
int ref;
@@ -376,6 +375,7 @@ pconv(lua_State *L) {
static void
convert_stringmap(struct context *ctx, struct table *tbl) {
lua_State *L = ctx->L;
lua_checkstack(L, ctx->string_index + LUA_MINSTACK);
lua_settop(L, ctx->string_index + 1);
lua_pushvalue(L, 1);
struct state * s = lua_newuserdata(L, sizeof(*s));
@@ -662,7 +662,7 @@ releaseobj(lua_State *L) {
struct ctrl *c = lua_touserdata(L, 1);
struct table *tbl = c->root;
struct state *s = lua_touserdata(tbl->L, 1);
__sync_fetch_and_sub(&s->ref, 1);
ATOM_DEC(&s->ref);
c->root = NULL;
c->update = NULL;
@@ -673,7 +673,7 @@ static int
lboxconf(lua_State *L) {
struct table * tbl = get_table(L,1);
struct state * s = lua_touserdata(tbl->L, 1);
__sync_fetch_and_add(&s->ref, 1);
ATOM_INC(&s->ref);
struct ctrl * c = lua_newuserdata(L, sizeof(*c));
c->root = tbl;
@@ -718,7 +718,7 @@ static int
lincref(lua_State *L) {
struct table *tbl = get_table(L,1);
struct state * s = lua_touserdata(tbl->L, 1);
int ref = __sync_add_and_fetch(&s->ref, 1);
int ref = ATOM_INC(&s->ref);
lua_pushinteger(L , ref);
return 1;
@@ -728,7 +728,7 @@ static int
ldecref(lua_State *L) {
struct table *tbl = get_table(L,1);
struct state * s = lua_touserdata(tbl->L, 1);
int ref = __sync_sub_and_fetch(&s->ref, 1);
int ref = ATOM_DEC(&s->ref);
lua_pushinteger(L , ref);
return 1;

View File

@@ -118,6 +118,28 @@ _command(lua_State *L) {
return 0;
}
static int
_intcommand(lua_State *L) {
struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
const char * cmd = luaL_checkstring(L,1);
const char * result;
const char * parm = NULL;
char tmp[64]; // for integer parm
if (lua_gettop(L) == 2) {
int32_t n = (int32_t)luaL_checkinteger(L,2);
sprintf(tmp, "%d", n);
parm = tmp;
}
result = skynet_command(context, cmd, parm);
if (result) {
lua_Integer r = strtoll(result, NULL, 0);
lua_pushinteger(L, r);
return 1;
}
return 0;
}
static int
_genid(lua_State *L) {
struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
@@ -150,6 +172,9 @@ _send(lua_State *L) {
uint32_t dest = (uint32_t)lua_tointeger(L, 1);
const char * dest_string = NULL;
if (dest == 0) {
if (lua_type(L,1) == LUA_TNUMBER) {
return luaL_error(L, "Invalid service address 0");
}
dest_string = get_dest_string(L, 1);
}
@@ -310,6 +335,7 @@ luaopen_skynet_core(lua_State *L) {
{ "genid", _genid },
{ "redirect", _redirect },
{ "command" , _command },
{ "intcommand", _intcommand },
{ "error", _error },
{ "tostring", _tostring },
{ "harbor", _harbor },

View File

@@ -190,7 +190,10 @@ pop_lstring(lua_State *L, struct socket_buffer *sb, int sz, int skip) {
}
break;
}
luaL_addlstring(&b, current->msg + sb->offset, (sz - skip < bytes) ? sz - skip : bytes);
int real_sz = sz - skip;
if (real_sz > 0) {
luaL_addlstring(&b, current->msg + sb->offset, (real_sz < bytes) ? real_sz : bytes);
}
return_free_node(L,2,sb);
sz-=bytes;
if (sz==0)
@@ -534,12 +537,6 @@ lnodelay(lua_State *L) {
skynet_socket_nodelay(ctx,id);
return 0;
}
/*
int skynet_socket_udp(struct skynet_context *ctx, const char * addr, int port);
int skynet_socket_udp_connect(struct skynet_context *ctx, int id, const char * addr, int port);
int skynet_socket_udp_send(struct skynet_context *ctx, int id, const char * address, const void *buffer, int sz);
const char * skynet_socket_udp_address(struct skynet_context *ctx, struct skynet_socket_message *, int *addrsz);
*/
static int
ludp(lua_State *L) {
@@ -599,7 +596,9 @@ static int
ludp_address(lua_State *L) {
size_t sz = 0;
const uint8_t * addr = (const uint8_t *)luaL_checklstring(L, 1, &sz);
int port = addr[1] * 256 + addr[2];
uint16_t port = 0;
memcpy(&port, addr+1, sizeof(uint16_t));
port = ntohs(port);
const void * src = addr+3;
char tmp[256];
int family;

View File

@@ -7,6 +7,7 @@
#include "rwlock.h"
#include "skynet_malloc.h"
#include "atomic.h"
struct stm_object {
struct rwlock lock;
@@ -45,7 +46,7 @@ static void
stm_releasecopy(struct stm_copy *copy) {
if (copy == NULL)
return;
if (__sync_sub_and_fetch(&copy->reference, 1) == 0) {
if (ATOM_DEC(&copy->reference) == 0) {
skynet_free(copy->msg);
skynet_free(copy);
}
@@ -70,7 +71,7 @@ stm_release(struct stm_object *obj) {
static void
stm_releasereader(struct stm_object *obj) {
rwlock_rlock(&obj->lock);
if (__sync_sub_and_fetch(&obj->reference,1) == 0) {
if (ATOM_DEC(&obj->reference) == 0) {
// last reader, no writer. so no need to unlock
assert(obj->copy == NULL);
skynet_free(obj);
@@ -82,7 +83,7 @@ stm_releasereader(struct stm_object *obj) {
static void
stm_grab(struct stm_object *obj) {
rwlock_rlock(&obj->lock);
int ref = __sync_fetch_and_add(&obj->reference,1);
int ref = ATOM_FINC(&obj->reference);
rwlock_runlock(&obj->lock);
assert(ref > 0);
}
@@ -92,7 +93,7 @@ stm_copy(struct stm_object *obj) {
rwlock_rlock(&obj->lock);
struct stm_copy * ret = obj->copy;
if (ret) {
int ref = __sync_fetch_and_add(&ret->reference,1);
int ref = ATOM_FINC(&ret->reference);
assert(ref > 0);
}
rwlock_runlock(&obj->lock);

View File

@@ -39,17 +39,32 @@ LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
#endif
#if LUA_VERSION_NUM < 503
#if LUA_VERSION_NUM < 502
static lua_Integer lua_tointegerx(lua_State *L, int idx, int *isnum) {
if (lua_isnumber(L, idx)) {
if (isnum) *isnum = 1;
return lua_tointeger(L, idx);
}
else {
if (isnum) *isnum = 0;
return 0;
}
}
#endif
// work around , use push & lua_gettable may be better
#define lua_geti lua_rawgeti
#define lua_seti lua_rawseti
#endif
static int
lnewproto(lua_State *L) {
size_t sz = 0;
void * buffer;
struct sproto * sp;
if (lua_isuserdata(L,1)) {
buffer = lua_touserdata(L,1);
sz = luaL_checkinteger(L,2);
} else {
buffer = (void *)luaL_checklstring(L,1,&sz);
}
size_t sz;
void * buffer = (void *)luaL_checklstring(L,1,&sz);
sp = sproto_create(buffer, sz);
if (sp) {
lua_pushlightuserdata(L, sp);
@@ -104,6 +119,7 @@ encode(const struct sproto_arg *args) {
return luaL_error(L, "The table is too deep");
if (args->index > 0) {
if (args->tagname != self->array_tag) {
// a new array
self->array_tag = args->tagname;
lua_getfield(L, self->tbl_index, args->tagname);
if (lua_isnil(L, -1)) {
@@ -113,6 +129,10 @@ encode(const struct sproto_arg *args) {
self->array_index = 0;
return 0;
}
if (!lua_istable(L, -1)) {
return luaL_error(L, ".*%s(%d) should be a table (Is a %s)",
args->tagname, args->index, lua_typename(L, lua_type(L, -1)));
}
if (self->array_index) {
lua_replace(L, self->array_index);
} else {
@@ -133,7 +153,7 @@ encode(const struct sproto_arg *args) {
lua_insert(L, -2);
lua_replace(L, self->iter_index);
} else {
lua_rawgeti(L, self->array_index, args->index);
lua_geti(L, self->array_index, args->index);
}
} else {
lua_getfield(L, self->tbl_index, args->tagname);
@@ -144,8 +164,14 @@ encode(const struct sproto_arg *args) {
}
switch (args->type) {
case SPROTO_TINTEGER: {
lua_Integer v = luaL_checkinteger(L, -1);
lua_Integer v;
lua_Integer vh;
int isnum;
v = lua_tointegerx(L, -1, &isnum);
if(!isnum) {
return luaL_error(L, ".%s[%d] is not an integer (Is a %s)",
args->tagname, args->index, lua_typename(L, lua_type(L, -1)));
}
lua_pop(L,1);
// notice: in lua 5.2, lua_Integer maybe 52bit
vh = v >> 31;
@@ -160,32 +186,47 @@ encode(const struct sproto_arg *args) {
}
case SPROTO_TBOOLEAN: {
int v = lua_toboolean(L, -1);
if (!lua_isboolean(L,-1)) {
return luaL_error(L, ".%s[%d] is not a boolean (Is a %s)",
args->tagname, args->index, lua_typename(L, lua_type(L, -1)));
}
*(int *)args->value = v;
lua_pop(L,1);
return 4;
}
case SPROTO_TSTRING: {
size_t sz = 0;
const char * str = luaL_checklstring(L, -1, &sz);
const char * str;
if (!lua_isstring(L, -1)) {
return luaL_error(L, ".%s[%d] is not a string (Is a %s)",
args->tagname, args->index, lua_typename(L, lua_type(L, -1)));
} else {
str = lua_tolstring(L, -1, &sz);
}
if (sz > args->length)
return -1;
memcpy(args->value, str, sz);
lua_pop(L,1);
return sz;
return sz + 1; // The length of empty string is 1.
}
case SPROTO_TSTRUCT: {
struct encode_ud sub;
int r;
int top = lua_gettop(L);
if (!lua_istable(L, top)) {
return luaL_error(L, ".%s[%d] is not a table (Is a %s)",
args->tagname, args->index, lua_typename(L, lua_type(L, -1)));
}
sub.L = L;
sub.st = args->subtype;
sub.tbl_index = lua_gettop(L);
sub.tbl_index = top;
sub.array_tag = NULL;
sub.array_index = 0;
sub.deep = self->deep + 1;
lua_pushnil(L); // prepare an iterator slot
sub.iter_index = sub.tbl_index + 1;
r = sproto_encode(args->subtype, args->value, args->length, encode, &sub);
lua_pop(L,2); // pop the value and the iterator slot
lua_settop(L, top-1); // pop the value
return r;
}
default:
@@ -222,29 +263,30 @@ lencode(lua_State *L) {
struct encode_ud self;
void * buffer = lua_touserdata(L, lua_upvalueindex(1));
int sz = lua_tointeger(L, lua_upvalueindex(2));
int tbl_index = 2;
struct sproto_type * st = lua_touserdata(L, 1);
if (st == NULL) {
return luaL_argerror(L, 1, "Need a sproto_type object");
}
luaL_checktype(L, 2, LUA_TTABLE);
luaL_checktype(L, tbl_index, LUA_TTABLE);
luaL_checkstack(L, ENCODE_DEEPLEVEL*2 + 8, NULL);
self.L = L;
self.st = st;
self.tbl_index = 2;
self.array_tag = NULL;
self.array_index = 0;
self.deep = 0;
lua_pushnil(L); // for iterator (stack 3)
self.iter_index = 3;
self.tbl_index = tbl_index;
for (;;) {
int r = sproto_encode(st, buffer, sz, encode, &self);
int r;
self.array_tag = NULL;
self.array_index = 0;
self.deep = 0;
lua_settop(L, tbl_index);
lua_pushnil(L); // for iterator (stack slot 3)
self.iter_index = tbl_index+1;
r = sproto_encode(st, buffer, sz, encode, &self);
if (r<0) {
buffer = expand_buffer(L, sz, sz*2);
sz *= 2;
// reset iterator slot
lua_pushnil(L);
lua_replace(L, 3);
} else {
lua_pushlstring(L, buffer, r);
return 1;
@@ -322,7 +364,7 @@ decode(const struct sproto_arg *args) {
luaL_error(L, "Can't find main index (tag=%d) in [%s]", args->mainindex, args->tagname);
}
lua_pushvalue(L, sub.result_index);
lua_rawset(L, self->array_index);
lua_settable(L, self->array_index);
lua_settop(L, sub.result_index-1);
return 0;
} else {
@@ -339,7 +381,7 @@ decode(const struct sproto_arg *args) {
luaL_error(L, "Invalid type");
}
if (args->index > 0) {
lua_rawseti(L, self->array_index, args->index);
lua_seti(L, self->array_index, args->index);
} else {
if (self->mainindex_tag == args->tagid) {
// This tag is marked, save the value to key_index
@@ -455,10 +497,10 @@ lunpack(lua_State *L) {
return luaL_error(L, "Invalid unpack stream");
if (r > osz) {
output = expand_buffer(L, osz, r);
r = sproto_unpack(buffer, sz, output, r);
if (r < 0)
return luaL_error(L, "Invalid unpack stream");
}
r = sproto_unpack(buffer, sz, output, r);
if (r < 0)
return luaL_error(L, "Invalid unpack stream");
lua_pushlstring(L, output, r);
return 1;
}
@@ -511,48 +553,98 @@ lprotocol(lua_State *L) {
return 3;
}
/* global sproto pointer for multi states */
struct sproto_bin {
void *ptr;
size_t sz;
};
static struct sproto_bin G_sproto[MAX_GLOBALSPROTO];
/* global sproto pointer for multi states
NOTICE : It is not thread safe
*/
static struct sproto * G_sproto[MAX_GLOBALSPROTO];
static int
lsaveproto(lua_State *L) {
size_t sz;
void * buffer = (void *)luaL_checklstring(L,1,&sz);
struct sproto * sp = lua_touserdata(L, 1);
int index = luaL_optinteger(L, 2, 0);
void * tmp;
struct sproto_bin * sbin = &G_sproto[index];
if (index < 0 || index >= MAX_GLOBALSPROTO) {
return luaL_error(L, "Invalid global slot index %d", index);
}
tmp = malloc(sz);
memcpy(tmp, buffer, sz);
if (sbin->ptr) {
free(sbin->ptr);
}
sbin->ptr = tmp;
sbin->sz = sz;
/* TODO : release old object (memory leak now, but thread safe)*/
G_sproto[index] = sp;
return 0;
}
static int
lloadproto(lua_State *L) {
int index = luaL_optinteger(L, 1, 0);
struct sproto_bin * sbin = &G_sproto[index];
struct sproto * sp;
if (index < 0 || index >= MAX_GLOBALSPROTO) {
return luaL_error(L, "Invalid global slot index %d", index);
}
if (sbin->ptr == NULL) {
sp = G_sproto[index];
if (sp == NULL) {
return luaL_error(L, "nil sproto at index %d", index);
}
lua_pushlightuserdata(L, sbin->ptr);
lua_pushinteger(L, sbin->sz);
return 2;
lua_pushlightuserdata(L, sp);
return 1;
}
static int
encode_default(const struct sproto_arg *args) {
lua_State *L = args->ud;
lua_pushstring(L, args->tagname);
if (args->index > 0) {
lua_newtable(L);
} else {
switch(args->type) {
case SPROTO_TINTEGER:
lua_pushinteger(L, 0);
break;
case SPROTO_TBOOLEAN:
lua_pushboolean(L, 0);
break;
case SPROTO_TSTRING:
lua_pushliteral(L, "");
break;
case SPROTO_TSTRUCT:
lua_createtable(L, 0, 1);
lua_pushstring(L, sproto_name(args->subtype));
lua_setfield(L, -2, "__type");
break;
}
}
lua_rawset(L, -3);
return 0;
}
/*
lightuserdata sproto_type
return default table
*/
static int
ldefault(lua_State *L) {
int ret;
// 64 is always enough for dummy buffer, except the type has many fields ( > 27).
char dummy[64];
struct sproto_type * st = lua_touserdata(L, 1);
if (st == NULL) {
return luaL_argerror(L, 1, "Need a sproto_type object");
}
lua_newtable(L);
ret = sproto_encode(st, dummy, sizeof(dummy), encode_default, L);
if (ret<0) {
// try again
int sz = sizeof(dummy) * 2;
void * tmp = lua_newuserdata(L, sz);
lua_insert(L, -2);
for (;;) {
ret = sproto_encode(st, tmp, sz, encode_default, L);
if (ret >= 0)
break;
sz *= 2;
tmp = lua_newuserdata(L, sz);
lua_replace(L, -3);
}
}
return 1;
}
int
@@ -569,6 +661,7 @@ luaopen_sproto_core(lua_State *L) {
{ "protocol", lprotocol },
{ "loadproto", lloadproto },
{ "saveproto", lsaveproto },
{ "default", ldefault },
{ NULL, NULL },
};
luaL_newlib(L,l);

View File

@@ -83,7 +83,7 @@ static void *
pool_alloc(struct pool *p, size_t sz) {
// align by 8
sz = (sz + 7) & ~7;
if (sz > CHUNK_SIZE) {
if (sz >= CHUNK_SIZE) {
return pool_newchunk(p, sz);
}
if (p->current == NULL) {
@@ -97,7 +97,7 @@ pool_alloc(struct pool *p, size_t sz) {
return ret;
}
if (sz > p->current_used) {
if (sz >= p->current_used) {
return pool_newchunk(p, sz);
} else {
void * ret = pool_newchunk(p, CHUNK_SIZE);
@@ -152,7 +152,7 @@ struct_field(const uint8_t * stream, size_t sz) {
sz -= header;
stream += header;
for (i=0;i<fn;i++) {
int value= toword(field + i * SIZEOF_FIELD + SIZEOF_HEADER);
int value= toword(field + i * SIZEOF_FIELD);
uint32_t dsz;
if (value != 0)
continue;
@@ -305,7 +305,7 @@ import_type(struct sproto *s, struct sproto_type *t, const uint8_t * stream) {
if (stream == NULL)
return NULL;
tag = f->tag;
if (tag < last)
if (tag <= last)
return NULL; // tag must in ascending order
if (tag > last+1) {
++maxn;
@@ -394,7 +394,7 @@ create_from_bundle(struct sproto *s, const uint8_t * stream, size_t sz) {
const uint8_t * protocoldata = NULL;
int fn = struct_field(stream, sz);
int i;
if (fn < 0)
if (fn < 0 || fn > 2)
return NULL;
stream += SIZEOF_HEADER;
@@ -500,7 +500,11 @@ sproto_dump(struct sproto *s) {
printf("=== %d protocol ===\n", s->protocol_n);
for (i=0;i<s->protocol_n;i++) {
struct protocol *p = &s->proto[i];
printf("\t%s (%d) request:%s", p->name, p->tag, p->p[SPROTO_REQUEST]->name);
if (p->p[SPROTO_REQUEST]) {
printf("\t%s (%d) request:%s", p->name, p->tag, p->p[SPROTO_REQUEST]->name);
} else {
printf("\t%s (%d) request:(null)", p->name, p->tag);
}
if (p->p[SPROTO_RESPONSE]) {
printf(" response:%s", p->p[SPROTO_RESPONSE]->name);
}
@@ -510,7 +514,7 @@ sproto_dump(struct sproto *s) {
// query
int
sproto_prototag(struct sproto *sp, const char * name) {
sproto_prototag(const struct sproto *sp, const char * name) {
int i;
for (i=0;i<sp->protocol_n;i++) {
if (strcmp(name, sp->proto[i].name) == 0) {
@@ -521,7 +525,7 @@ sproto_prototag(struct sproto *sp, const char * name) {
}
static struct protocol *
query_proto(struct sproto *sp, int tag) {
query_proto(const struct sproto *sp, int tag) {
int begin = 0, end = sp->protocol_n;
while(begin<end) {
int mid = (begin+end)/2;
@@ -539,7 +543,7 @@ query_proto(struct sproto *sp, int tag) {
}
struct sproto_type *
sproto_protoquery(struct sproto *sp, int proto, int what) {
sproto_protoquery(const struct sproto *sp, int proto, int what) {
struct protocol * p;
if (what <0 || what >1) {
return NULL;
@@ -552,7 +556,7 @@ sproto_protoquery(struct sproto *sp, int proto, int what) {
}
const char *
sproto_protoname(struct sproto *sp, int proto) {
sproto_protoname(const struct sproto *sp, int proto) {
struct protocol * p = query_proto(sp, proto);
if (p) {
return p->name;
@@ -561,7 +565,7 @@ sproto_protoname(struct sproto *sp, int proto) {
}
struct sproto_type *
sproto_type(struct sproto *sp, const char * type_name) {
sproto_type(const struct sproto *sp, const char * type_name) {
int i;
for (i=0;i<sp->type_n;i++) {
if (strcmp(type_name, sp->type[i].name) == 0) {
@@ -577,7 +581,7 @@ sproto_name(struct sproto_type * st) {
}
static struct field *
findtag(struct sproto_type *st, int tag) {
findtag(const struct sproto_type *st, int tag) {
int begin, end;
if (st->base >=0 ) {
tag -= st->base;
@@ -609,10 +613,6 @@ findtag(struct sproto_type *st, int tag) {
static inline int
fill_size(uint8_t * data, int sz) {
if (sz < 0)
return -1;
if (sz == 0)
return 0;
data[0] = sz & 0xff;
data[1] = (sz >> 8) & 0xff;
data[2] = (sz >> 16) & 0xff;
@@ -677,6 +677,12 @@ encode_object(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int si
args->value = data+SIZEOF_LENGTH;
args->length = size-SIZEOF_LENGTH;
sz = cb(args);
if (sz <= 0)
return sz;
if (args->type == SPROTO_TSTRING) {
--sz; // the length of null string is 1
}
assert(sz <= size-SIZEOF_LENGTH); // verify buffer overflow
return fill_size(data, sz);
}
@@ -718,7 +724,7 @@ encode_integer_array(sproto_callback cb, struct sproto_arg *args, uint8_t *buffe
sz = cb(args);
if (sz < 0)
return NULL;
if (sz == 0)
if (sz == 0) // nil object, end of array
break;
if (size < sizeof(uint64_t))
return NULL;
@@ -798,7 +804,7 @@ encode_array(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int siz
sz = cb(args);
if (sz < 0)
return -1;
if (sz == 0)
if (sz == 0) // nil object , end of array
break;
if (size < 1)
return -1;
@@ -817,10 +823,13 @@ encode_array(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int siz
args->value = buffer+SIZEOF_LENGTH;
args->length = size;
sz = cb(args);
if (sz < 0)
return -1;
if (sz == 0)
break;
if (sz < 0)
return -1;
if (args->type == SPROTO_TSTRING) {
--sz;
}
fill_size(buffer, sz);
buffer += SIZEOF_LENGTH+sz;
size -=sz;
@@ -829,13 +838,13 @@ encode_array(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int siz
break;
}
sz = buffer - (data + SIZEOF_LENGTH);
if (sz == 0)
if (sz == 0) // empty array
return 0;
return fill_size(data, sz);
}
int
sproto_encode(struct sproto_type *st, void * buffer, int size, sproto_callback cb, void *ud) {
sproto_encode(const struct sproto_type *st, void * buffer, int size, sproto_callback cb, void *ud) {
struct sproto_arg args;
uint8_t * header = buffer;
uint8_t * data;
@@ -878,7 +887,7 @@ sproto_encode(struct sproto_type *st, void * buffer, int size, sproto_callback c
sz = cb(&args);
if (sz < 0)
return -1;
if (sz == 0)
if (sz == 0) // nil object
continue;
if (sz == sizeof(uint32_t)) {
if (u.u32 < 0x7fff) {
@@ -895,11 +904,10 @@ sproto_encode(struct sproto_type *st, void * buffer, int size, sproto_callback c
break;
}
case SPROTO_TSTRUCT:
case SPROTO_TSTRING: {
case SPROTO_TSTRING:
sz = encode_object(cb, &args, data, size);
break;
}
}
}
if (sz < 0)
return -1;
@@ -1032,7 +1040,7 @@ decode_array(sproto_callback cb, struct sproto_arg *args, uint8_t * stream) {
}
int
sproto_decode(struct sproto_type *st, const void * data, int size, sproto_callback cb, void *ud) {
sproto_decode(const struct sproto_type *st, const void * data, int size, sproto_callback cb, void *ud) {
struct sproto_arg args;
int total = size;
uint8_t * stream;

View File

@@ -17,12 +17,12 @@ struct sproto_type;
struct sproto * sproto_create(const void * proto, size_t sz);
void sproto_release(struct sproto *);
int sproto_prototag(struct sproto *, const char * name);
const char * sproto_protoname(struct sproto *, int proto);
int sproto_prototag(const struct sproto *, const char * name);
const char * sproto_protoname(const struct sproto *, int proto);
// SPROTO_REQUEST(0) : request, SPROTO_RESPONSE(1): response
struct sproto_type * sproto_protoquery(struct sproto *, int proto, int what);
struct sproto_type * sproto_protoquery(const struct sproto *, int proto, int what);
struct sproto_type * sproto_type(struct sproto *, const char * type_name);
struct sproto_type * sproto_type(const struct sproto *, const char * type_name);
int sproto_pack(const void * src, int srcsz, void * buffer, int bufsz);
int sproto_unpack(const void * src, int srcsz, void * buffer, int bufsz);
@@ -41,8 +41,8 @@ struct sproto_arg {
typedef int (*sproto_callback)(const struct sproto_arg *args);
int sproto_decode(struct sproto_type *, const void * data, int size, sproto_callback cb, void *ud);
int sproto_encode(struct sproto_type *, void * buffer, int size, sproto_callback cb, void *ud);
int sproto_decode(const struct sproto_type *, const void * data, int size, sproto_callback cb, void *ud);
int sproto_encode(const struct sproto_type *, void * buffer, int size, sproto_callback cb, void *ud);
// for debug use
void sproto_dump(struct sproto *);

View File

@@ -24,6 +24,25 @@ function cluster.proxy(node, name)
return skynet.call(clusterd, "lua", "proxy", node, name)
end
function cluster.snax(node, name, address)
local snax = require "snax"
if not address then
address = cluster.call(node, ".service", "QUERY", "snaxd" , name)
end
local handle = skynet.call(clusterd, "lua", "proxy", node, address)
return snax.bind(handle, name)
end
function cluster.register(name, addr)
assert(type(name) == "string")
assert(addr == nil or type(addr) == "number")
return skynet.call(clusterd, "lua", "register", name, addr)
end
function cluster.query(node, name)
return skynet.call(clusterd, "lua", "req", node, 0, skynet.pack(name))
end
skynet.init(function()
clusterd = skynet.uniqueservice("clusterd")
end)

290
lualib/dns.lua Normal file
View File

@@ -0,0 +1,290 @@
--[[
lua dns resolver library
See https://github.com/xjdrew/levent/blob/master/levent/dns.lua for more detail
-- resource record type:
-- TYPE value and meaning
-- A 1 a host address
-- NS 2 an authoritative name server
-- MD 3 a mail destination (Obsolete - use MX)
-- MF 4 a mail forwarder (Obsolete - use MX)
-- CNAME 5 the canonical name for an alias
-- SOA 6 marks the start of a zone of authority
-- MB 7 a mailbox domain name (EXPERIMENTAL)
-- MG 8 a mail group member (EXPERIMENTAL)
-- MR 9 a mail rename domain name (EXPERIMENTAL)
-- NULL 10 a null RR (EXPERIMENTAL)
-- WKS 11 a well known service description
-- PTR 12 a domain name pointer
-- HINFO 13 host information
-- MINFO 14 mailbox or mail list information
-- MX 15 mail exchange
-- TXT 16 text strings
-- AAAA 28 a ipv6 host address
-- only appear in the question section:
-- AXFR 252 A request for a transfer of an entire zone
-- MAILB 253 A request for mailbox-related records (MB, MG or MR)
-- MAILA 254 A request for mail agent RRs (Obsolete - see MX)
-- * 255 A request for all records
--
-- resource recode class:
-- IN 1 the Internet
-- CS 2 the CSNET class (Obsolete - used only for examples in some obsolete RFCs)
-- CH 3 the CHAOS class
-- HS 4 Hesiod [Dyer 87]
-- only appear in the question section:
-- * 255 any class
-- ]]
--[[
-- struct header {
-- uint16_t tid # identifier assigned by the program that generates any kind of query.
-- uint16_t flags # flags
-- uint16_t qdcount # the number of entries in the question section.
-- uint16_t ancount # the number of resource records in the answer section.
-- uint16_t nscount # the number of name server resource records in the authority records section.
-- uint16_t arcount # the number of resource records in the additional records section.
-- }
--
-- request body:
-- struct request {
-- string name
-- uint16_t atype
-- uint16_t class
-- }
--
-- response body:
-- struct response {
-- string name
-- uint16_t atype
-- uint16_t class
-- uint16_t ttl
-- uint16_t rdlength
-- string rdata
-- }
--]]
local skynet = require "skynet"
local socket = require "socket"
local MAX_DOMAIN_LEN = 1024
local MAX_LABEL_LEN = 63
local MAX_PACKET_LEN = 2048
local DNS_HEADER_LEN = 12
local QTYPE = {
A = 1,
CNAME = 5,
AAAA = 28,
}
local QCLASS = {
IN = 1,
}
local dns = {}
local function verify_domain_name(name)
if #name > MAX_DOMAIN_LEN then
return false
end
if not name:match("^[_%l%d%-%.]+$") then
return false
end
for w in name:gmatch("([_%w%-]+)%.?") do
if #w > MAX_LABEL_LEN then
return false
end
end
return true
end
local next_tid = 1
local function gen_tid()
local tid = next_tid
next_tid = next_tid + 1
return tid
end
local function pack_header(t)
return string.pack(">HHHHHH",
t.tid, t.flags, t.qdcount, t.ancount or 0, t.nscount or 0, t.arcount or 0)
end
local function pack_question(name, qtype, qclass)
local labels = {}
for w in name:gmatch("([_%w%-]+)%.?") do
table.insert(labels, string.pack("s1",w))
end
table.insert(labels, '\0')
table.insert(labels, string.pack(">HH", qtype, qclass))
return table.concat(labels)
end
local function unpack_header(chunk)
local tid, flags, qdcount, ancount, nscount, arcount, left = string.unpack(">HHHHHH", chunk)
return {
tid = tid,
flags = flags,
qdcount = qdcount,
ancount = ancount,
nscount = nscount,
arcount = arcount
}, left
end
-- unpack a resource name
local function unpack_name(chunk, left)
local t = {}
local jump_pointer
local tag, offset, label
while true do
tag, left = string.unpack("B", chunk, left)
if tag & 0xc0 == 0xc0 then
-- pointer
offset,left = string.unpack(">H", chunk, left - 1)
offset = offset & 0x3fff
if not jump_pointer then
jump_pointer = left
end
-- offset is base 0, need to plus 1
left = offset + 1
elseif tag == 0 then
break
else
label, left = string.unpack("s1", chunk, left - 1)
t[#t+1] = label
end
end
return table.concat(t, "."), jump_pointer or left
end
local function unpack_question(chunk, left)
local name, left = unpack_name(chunk, left)
local atype, class, left = string.unpack(">HH", chunk, left)
return {
name = name,
atype = atype,
class = class
}, left
end
local function unpack_answer(chunk, left)
local name, left = unpack_name(chunk, left)
local atype, class, ttl, rdata, left = string.unpack(">HHI4s2", chunk, left)
return {
name = name,
atype = atype,
class = class,
ttl = ttl,
rdata = rdata
},left
end
local function unpack_rdata(qtype, chunk)
if qtype == QTYPE.A then
local a,b,c,d = string.unpack("BBBB", chunk)
return string.format("%d.%d.%d.%d", a,b,c,d)
elseif qtype == QTYPE.AAAA then
local a,b,c,d,e,f,g,h = string.unpack(">HHHHHHHH", chunk)
return string.format("%x:%x:%x:%x:%x:%x:%x:%x", a, b, c, d, e, f, g, h)
else
error("Error qtype " .. qtype)
end
end
local dns_server
local request_pool = {}
local function resolve(content)
if #content < DNS_HEADER_LEN then
-- drop
skynet.error("Recv an invalid package when dns query")
return
end
local answer_header,left = unpack_header(content)
-- verify answer
assert(answer_header.qdcount == 1, "malformed packet")
local resp = request_pool[answer_header.tid]
if not resp then
skynet.error("Recv an invalid tid when dns query")
return
end
local question,left = unpack_question(content, left)
if question.name ~= resp.name then
skynet.error("Recv an invalid name when dns query")
return
end
local ttl
local answer
local answers = {}
for i=1, answer_header.ancount do
answer, left = unpack_answer(content, left)
-- only extract qtype address
if answer.atype == resp.qtype then
local ip = unpack_rdata(resp.qtype, answer.rdata)
ttl = ttl and math.min(ttl, answer.ttl) or answer.ttl
answers[#answers+1] = ip
end
end
if #answers > 0 then
resp.answers = answers
end
skynet.wakeup(resp.co)
end
function dns.server(server, port)
if not server then
local f = assert(io.open "/etc/resolv.conf")
for line in f:lines() do
server = line:match("%s*nameserver%s+([^%s]+)")
if server then
break
end
end
assert(server, "Can't get nameserver")
end
dns_server = socket.udp(function(str, from)
resolve(str)
end)
socket.udp_connect(dns_server, server, port or 53)
return server
end
local function suspend(tid, name, qtype)
local req = {
name = name,
tid = tid,
qtype = qtype,
time = skynet.now(), -- for timeout
co = coroutine.running(),
}
request_pool[tid] = req
skynet.wait(req.co)
local answers = request_pool[tid].answers
request_pool[tid] = nil
assert(answers, "no ip")
return answers[1], answers
end
function dns.resolve(name, ipv6)
local qtype = ipv6 and QTYPE.AAAA or QTYPE.A
local name = name:lower()
assert(verify_domain_name(name) , "illegal name")
local question_header = {
tid = gen_tid(),
flags = 0x100, -- flags: 00000001 00000000, set RD
qdcount = 1,
}
local req = pack_header(question_header) .. pack_question(name, qtype, QCLASS.IN)
assert(dns_server, "Call dns.server first")
socket.write(dns_server, req)
return suspend(question_header.tid, name, qtype)
end
return dns

View File

@@ -11,16 +11,22 @@ local function request(fd, method, host, url, recvheader, header, content)
local write = socket.writefunc(fd)
local header_content = ""
if header then
if not header.host then
header.host = host
end
for k,v in pairs(header) do
header_content = string.format("%s%s:%s\r\n", header_content, k, v)
end
else
header_content = string.format("host:%s\r\n",host)
end
if content then
local data = string.format("%s %s HTTP/1.1\r\nhost:%s\r\ncontent-length:%d\r\n%s\r\n%s", method, url, host, #content, header_content, content)
local data = string.format("%s %s HTTP/1.1\r\n%scontent-length:%d\r\n\r\n", method, url, header_content, #content)
write(data)
write(content)
else
local request_header = string.format("%s %s HTTP/1.1\r\nhost:%s\r\ncontent-length:0\r\n%s\r\n", method, url, host, header_content)
local request_header = string.format("%s %s HTTP/1.1\r\n%scontent-length:0\r\n\r\n", method, url, header_content)
write(request_header)
end

View File

@@ -2,6 +2,7 @@ local internal = require "http.internal"
local table = table
local string = string
local type = type
local httpd = {}
@@ -113,7 +114,13 @@ local function writeall(writefunc, statuscode, bodyfunc, header)
writefunc(statusline)
if header then
for k,v in pairs(header) do
writefunc(string.format("%s: %s\r\n", k,v))
if type(v) == "table" then
for _,v in ipairs(v) do
writefunc(string.format("%s: %s\r\n", k,v))
end
else
writefunc(string.format("%s: %s\r\n", k,v))
end
end
end
local t = type(bodyfunc)

View File

@@ -1,3 +1,6 @@
local table = table
local type = type
local M = {}
local LIMIT = 8192
@@ -83,7 +86,12 @@ function M.parseheader(lines, from, header)
end
name = name:lower()
if header[name] then
header[name] = header[name] .. ", " .. value
local v = header[name]
if type(v) == "table" then
table.insert(v, value)
else
header[name] = { v , value }
end
else
header[name] = value
end

View File

@@ -15,4 +15,24 @@ function core.sumhexa (k)
end))
end
return core
local function get_ipad(c)
return string.char(c:byte() ~ 0x36)
end
local function get_opad(c)
return string.char(c:byte() ~ 0x5c)
end
function core.hmacmd5(data,key)
if #key>64 then
key=core.sum(key)
key=key:sub(1,16)
end
local ipad_s=key:gsub(".", get_ipad)..string.rep("6",64-#key)
local opad_s=key:gsub(".", get_opad)..string.rep("\\",64-#key)
local istr=core.sum(ipad_s..data)
local ostr=core.sumhexa(opad_s..istr)
return ostr
end
return core

View File

@@ -8,7 +8,9 @@ local dispatch = setmetatable({} , {__mode = "kv" })
local chan = {}
local chan_meta = {
__index = chan,
__gc = unsubscribe,
__gc = function(self)
self:unsubscribe()
end,
__tostring = function (self)
return string.format("[Multicast:%x]",self.channel)
end,

16
lualib/mysql.lua Executable file → Normal file
View File

@@ -386,7 +386,8 @@ end
local function _recv_decode_packet_resp(self)
return function(sock)
return true, _recv_packet(self,sock)
-- don't return more than 2 results
return true, (_recv_packet(self,sock))
end
end
@@ -417,7 +418,7 @@ local function _recv_auth_resp(self)
end
local function _mysql_login(self,user,password,database)
local function _mysql_login(self,user,password,database,on_connect)
return function(sockchannel)
local packet, typ, err = sockchannel:response( _recv_decode_packet_resp(self) )
@@ -489,7 +490,10 @@ local function _mysql_login(self,user,password,database)
local packet_len = #req
local authpacket=_compose_packet(self,req,packet_len)
return sockchannel:request(authpacket,_recv_auth_resp(self))
sockchannel:request(authpacket,_recv_auth_resp(self))
if on_connect then
on_connect(self)
end
end
end
@@ -625,7 +629,7 @@ local function _query_resp(self)
end
end
function _M.connect( opts)
function _M.connect(opts)
local self = setmetatable( {}, mt)
@@ -644,11 +648,11 @@ function _M.connect( opts)
local channel = socketchannel.channel {
host = opts.host,
port = opts.port or 3306,
auth = _mysql_login(self,user,password,database ),
auth = _mysql_login(self,user,password,database,opts.on_connect),
}
self.sockchannel = channel
-- try connect first only once
channel:connect(true)
self.sockchannel = channel
return self

Some files were not shown because too many files have changed in this diff Show More