Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
072a9052c7 | ||
|
|
00af23bcbf | ||
|
|
15c9497280 | ||
|
|
45bd4a1853 | ||
|
|
0327d9b8e9 | ||
|
|
1e81d971dc | ||
|
|
9a3a84bfdf | ||
|
|
1126d5aa49 | ||
|
|
b6fe152b83 | ||
|
|
1270a13667 | ||
|
|
98f5abb6e3 | ||
|
|
ab648d973d | ||
|
|
5ab72bedb7 | ||
|
|
9a83d13fb5 | ||
|
|
6662806a26 | ||
|
|
6e3f1a9e47 | ||
|
|
d12f26c231 | ||
|
|
a502f48320 | ||
|
|
0c71939c05 | ||
|
|
a4f46f211c | ||
|
|
8185c2e9f1 | ||
|
|
71bb31bf16 | ||
|
|
c7d23f3ed1 | ||
|
|
09cefcfbb3 | ||
|
|
1ca8deebef | ||
|
|
b7f667b553 | ||
|
|
067ad37f96 | ||
|
|
a6e312bf9a | ||
|
|
0e841b998a | ||
|
|
cd0458470e | ||
|
|
678dbc48fd | ||
|
|
3a91aca033 | ||
|
|
9286ecd767 | ||
|
|
902a656f7a | ||
|
|
a58e486d79 | ||
|
|
b0fcf23304 | ||
|
|
57f611d953 | ||
|
|
20c26321c2 | ||
|
|
2017d8baf7 | ||
|
|
a511ce1b49 | ||
|
|
1f164f4e1d | ||
|
|
9f775040c8 | ||
|
|
6ca793fc21 | ||
|
|
01ac844ba2 | ||
|
|
79b9ec53d1 | ||
|
|
4c2d5f0980 | ||
|
|
056c2acaea | ||
|
|
f85c383b6c | ||
|
|
3ae56d8458 | ||
|
|
0807f5b9ff | ||
|
|
2eae7cbc7d | ||
|
|
693618f1c1 | ||
|
|
c67e8d3bf6 | ||
|
|
411cb75bcd | ||
|
|
794419192e | ||
|
|
481a05cd23 | ||
|
|
b9a65682fb | ||
|
|
e3d1c8b080 | ||
|
|
682b63312e | ||
|
|
6fd1a72712 | ||
|
|
2e48ad5422 | ||
|
|
67f594f9b5 | ||
|
|
b7bf29059e | ||
|
|
889d468e51 | ||
|
|
84f48cc401 | ||
|
|
44690ab15f | ||
|
|
a72c0423b4 | ||
|
|
c8d0013f38 | ||
|
|
5ca75751ed | ||
|
|
af14408e5c | ||
|
|
ed56ad5689 | ||
|
|
c427f5d3c1 | ||
|
|
325d2eb8b5 | ||
|
|
0fb6212cf4 | ||
|
|
f602318349 | ||
|
|
2401c3eccb | ||
|
|
8d9804bf40 | ||
|
|
da30c9e1e3 | ||
|
|
3c51d3b36b | ||
|
|
00c7f312cc | ||
|
|
b10913b93d | ||
|
|
cbf01c0e01 | ||
|
|
214cf63730 | ||
|
|
4a4f4cb5ff | ||
|
|
a57bd791e9 | ||
|
|
ed9f997ce5 | ||
|
|
55eea93cae | ||
|
|
753e91b6c1 | ||
|
|
a830d941a7 | ||
|
|
9c3a89853c | ||
|
|
7ca6672338 | ||
|
|
6c68df4f32 | ||
|
|
8b58723eb2 | ||
|
|
abd4cd7827 | ||
|
|
81c74eb48f | ||
|
|
a395ce2659 | ||
|
|
3a4afb0473 | ||
|
|
63aed54a27 | ||
|
|
64cb15799c | ||
|
|
19453556d4 | ||
|
|
91654a40e7 | ||
|
|
619174117d | ||
|
|
0462d983c2 | ||
|
|
847fc09855 | ||
|
|
d229160e18 | ||
|
|
5dc2a4885d | ||
|
|
30b345ddbb | ||
|
|
06966abc66 | ||
|
|
99509ab257 | ||
|
|
c755c637c6 | ||
|
|
1ecfcb9380 | ||
|
|
616da6585a | ||
|
|
5d5fe340e0 | ||
|
|
b04e800b98 | ||
|
|
f2ac94876d | ||
|
|
13572dc21b | ||
|
|
eb48b10738 | ||
|
|
307868e149 | ||
|
|
322ad08697 | ||
|
|
b90c72c86a | ||
|
|
61751a4dc4 | ||
|
|
4dfecf64e1 | ||
|
|
7638130d6e | ||
|
|
6c194dae58 | ||
|
|
7a4c4682f2 | ||
|
|
054ed87d85 | ||
|
|
8dcec3bf25 | ||
|
|
7dc811b8cb | ||
|
|
0f3be53d7d | ||
|
|
4e5b1d3851 | ||
|
|
27c8f84c66 | ||
|
|
32463852be | ||
|
|
567d575dbe | ||
|
|
a7982fed9e | ||
|
|
b590cedff1 | ||
|
|
02d71527d8 | ||
|
|
112569d12d | ||
|
|
82c6e9c297 | ||
|
|
fcf862d22b | ||
|
|
16d227ef2d | ||
|
|
ac1eda60b0 | ||
|
|
598387b970 | ||
|
|
8789dc82aa | ||
|
|
7f90bcfaee | ||
|
|
860e3ade2d | ||
|
|
0042a2d737 | ||
|
|
0811e89c80 | ||
|
|
fe71355df9 | ||
|
|
33d00ff7d5 | ||
|
|
c60a0f588e | ||
|
|
942354f925 | ||
|
|
cd7a497164 | ||
|
|
5fca35da3f | ||
|
|
d260b9a499 | ||
|
|
45df42c9fe | ||
|
|
6e326c81dc | ||
|
|
83533b622e | ||
|
|
913090ec63 | ||
|
|
51501514e9 | ||
|
|
09843df1dd | ||
|
|
4f8cf6a23c | ||
|
|
0d119ad3a3 | ||
|
|
6a1275bcab | ||
|
|
3769dbd722 | ||
|
|
afc151d3ba | ||
|
|
6ac57f16cb | ||
|
|
61a707af39 | ||
|
|
5cb0558e8c | ||
|
|
e5dbbc20f1 | ||
|
|
1f036c6587 | ||
|
|
7dd1e95288 | ||
|
|
ecfc0583da | ||
|
|
ff8d85885e | ||
|
|
d89db584fa | ||
|
|
1f2af715cb | ||
|
|
78c05caf5e | ||
|
|
10e4b58312 | ||
|
|
de6ba77bc4 | ||
|
|
5d64f21792 | ||
|
|
86277eee4c | ||
|
|
24430cb820 | ||
|
|
604d26ffde | ||
|
|
338e44a6e7 | ||
|
|
de77addb36 | ||
|
|
9f517b920e | ||
|
|
d0f710ea09 | ||
|
|
d0d72c19d3 | ||
|
|
da49700d5a | ||
|
|
ba07e1f505 | ||
|
|
8ec9d6ef69 | ||
|
|
deff2338fa | ||
|
|
2ee7dd362c | ||
|
|
fddd64e610 | ||
|
|
d275513b04 | ||
|
|
2618476032 | ||
|
|
c924df8c83 | ||
|
|
01f36192c8 | ||
|
|
6e258c76bf | ||
|
|
355d8cb0b5 | ||
|
|
f1e072c57d | ||
|
|
a244985d1d | ||
|
|
b83a52c6f8 | ||
|
|
20dad91bdf | ||
|
|
d548f3daad | ||
|
|
992fe21706 | ||
|
|
2f170ad733 | ||
|
|
29a87f23b1 | ||
|
|
0882fe5e43 | ||
|
|
7e5cf2660c | ||
|
|
91867a5ea2 | ||
|
|
1c30cad1ab | ||
|
|
bd50301f3e | ||
|
|
760dec3a6c | ||
|
|
e8852d782d | ||
|
|
1f84b0648b | ||
|
|
73f01b0606 | ||
|
|
552a6fb39d | ||
|
|
5045ff843a | ||
|
|
c92283770d | ||
|
|
44d4b87f1f | ||
|
|
cebac46589 | ||
|
|
68495c46fe | ||
|
|
3dffb8e21e | ||
|
|
1c53928fca | ||
|
|
660a0cdf02 | ||
|
|
01fc59b787 | ||
|
|
ff8187844a | ||
|
|
1dabf116d8 | ||
|
|
5b97a708fc | ||
|
|
17f41d49b4 | ||
|
|
8514f3c035 | ||
|
|
3fa46ef069 | ||
|
|
3c2fe3f88d | ||
|
|
687054849e | ||
|
|
577b084e3c | ||
|
|
6a9764d183 | ||
|
|
c138dc7da4 | ||
|
|
1b905277bb | ||
|
|
cf7a138684 | ||
|
|
edfd6ae76b | ||
|
|
408e12dcaa | ||
|
|
dfeb899b2d | ||
|
|
2b886275e9 | ||
|
|
93db956e06 | ||
|
|
27fc6199ca | ||
|
|
0b01578d2e | ||
|
|
920c45b818 | ||
|
|
cf6c3f4b04 | ||
|
|
fb90934c47 | ||
|
|
207ca3cedd | ||
|
|
97d3b7dc8d | ||
|
|
abdbfc14c0 | ||
|
|
724376a0df | ||
|
|
476f044db6 | ||
|
|
8b2449dca0 | ||
|
|
763d6165ea | ||
|
|
2e18193f5b | ||
|
|
7f9c973467 | ||
|
|
366e872d4d | ||
|
|
4d8f13ddc3 | ||
|
|
3e518093b6 | ||
|
|
99cec798bb | ||
|
|
ccf96e197b | ||
|
|
8f0a41be98 | ||
|
|
63b29390b2 | ||
|
|
46aa0e2472 | ||
|
|
07d9e35637 | ||
|
|
2e12082b3e | ||
|
|
08532b1e99 | ||
|
|
771ea6e1a6 | ||
|
|
c5802e3f4a | ||
|
|
eab8382d18 | ||
|
|
efc77ad91c | ||
|
|
a3886e29a6 | ||
|
|
db912c5a93 | ||
|
|
2165ac5573 | ||
|
|
f8224a4f90 | ||
|
|
679de7ae2f | ||
|
|
efc3f1783d | ||
|
|
0b8c9eac68 | ||
|
|
4c36024f51 | ||
|
|
8e1db6a05f | ||
|
|
d3882605c0 | ||
|
|
3d6eade781 | ||
|
|
6b017e615f | ||
|
|
3164869d78 | ||
|
|
b38c299886 | ||
|
|
5b40d6e656 | ||
|
|
8c3b630561 | ||
|
|
4484e3b591 | ||
|
|
453a906fc9 | ||
|
|
de5d4be994 | ||
|
|
69bfdcf7d4 | ||
|
|
699465c31e | ||
|
|
45332cc47b | ||
|
|
2d2c17b075 | ||
|
|
048c0f0f37 | ||
|
|
3eb3cc9da4 | ||
|
|
74f6ee8dd5 | ||
|
|
7a55d72f28 | ||
|
|
4e4b3b943c | ||
|
|
61e2547675 | ||
|
|
595b5974f8 | ||
|
|
58418d7c3e | ||
|
|
c02bda324f | ||
|
|
1afef16d88 | ||
|
|
7377aacd84 | ||
|
|
eece2d528c | ||
|
|
eb5aeaf138 | ||
|
|
1a6281f52f | ||
|
|
c2571b314a | ||
|
|
97aeda9828 | ||
|
|
ca9d961073 | ||
|
|
2446fbb3bb | ||
|
|
970e813be2 | ||
|
|
a36d524562 | ||
|
|
bbaf76ea2f | ||
|
|
669f302e16 | ||
|
|
71791e7a8e | ||
|
|
2f91d7ada4 | ||
|
|
5ef8f9531d | ||
|
|
3ce30a6906 | ||
|
|
65e79a8272 | ||
|
|
ef8bc13d0d | ||
|
|
0ffeadd290 | ||
|
|
db0e263b42 | ||
|
|
d526d09e41 | ||
|
|
9738e587da | ||
|
|
da67b5f59a | ||
|
|
825d2904d1 | ||
|
|
3becef9ee6 | ||
|
|
2ccf6e81a6 | ||
|
|
e18b59ae7e | ||
|
|
8ff1353766 | ||
|
|
99677e89d0 | ||
|
|
f43502fb0e | ||
|
|
ebb07fb4bb | ||
|
|
c13c4080e5 | ||
|
|
360664c9c8 | ||
|
|
7ac1b364fe | ||
|
|
1b2b8cbbde | ||
|
|
f487bbbfe2 | ||
|
|
4b2499cf2f | ||
|
|
01a0b09886 | ||
|
|
90419b5681 | ||
|
|
ae7db3fe83 | ||
|
|
454f4bfd28 | ||
|
|
1408d147e4 | ||
|
|
78055bd4ca | ||
|
|
736d447380 | ||
|
|
71b6f64f2a | ||
|
|
c4e93cadfb | ||
|
|
0540df22ba | ||
|
|
9ac5be2ebe | ||
|
|
b902c1413e | ||
|
|
54e9f28922 | ||
|
|
dd889d884f | ||
|
|
1443a814d0 | ||
|
|
076ff11c06 | ||
|
|
4769dc7826 | ||
|
|
039357e471 |
+1
-8
@@ -1,4 +1,3 @@
|
||||
.*.swp
|
||||
*.o
|
||||
*.rdb
|
||||
*.log
|
||||
@@ -8,6 +7,7 @@ redis-benchmark
|
||||
redis-check-dump
|
||||
redis-check-aof
|
||||
doc-tools
|
||||
mkrelease.sh
|
||||
release
|
||||
misc/*
|
||||
src/release.h
|
||||
@@ -17,10 +17,3 @@ release.h
|
||||
src/transfer.sh
|
||||
src/configs
|
||||
src/redis-server.dSYM
|
||||
redis.ds
|
||||
src/redis.conf
|
||||
deps/lua/src/lua
|
||||
deps/lua/src/luac
|
||||
deps/lua/src/liblua.a
|
||||
.make-*
|
||||
.prerequisites
|
||||
|
||||
+94
-83
@@ -1,109 +1,120 @@
|
||||
Redis 2.6 release notes
|
||||
Redis 2.4 release notes
|
||||
|
||||
Migrating from 2.4 to 2.6
|
||||
Migrating from 2.2 to 2.4
|
||||
=========================
|
||||
|
||||
Redis 2.4 is mostly a strict subset of 2.6. However there are a few things
|
||||
that you should be aware of:
|
||||
Redis 2.2 is mostly a strict subset of 2.4.
|
||||
The only thing you should be aware is that you can't use .rdb and AOF files
|
||||
generated with 2.4 into a 2.2 instance.
|
||||
|
||||
* You can't use .rdb and AOF files generated with 2.6 into a 2.4 instance.
|
||||
* 2.4 slaves can be attached to 2.6 masters, but not the contrary, and only
|
||||
for the time needed to perform the version upgrade.
|
||||
2.4 slaves can be attached to 2.2 masters, but not the contrary, and only for
|
||||
the time needed to perform the version upgrade.
|
||||
|
||||
There are also a few API differences, that are unlikely to cause problems,
|
||||
but it is better to keep them in mind:
|
||||
|
||||
* SORT now will refuse to sort in numerical mode elements that can't be parsed
|
||||
as numbers.
|
||||
* EXPIREs now all have millisecond resolution (but this is very unlikely to
|
||||
break code that was not conceived exploting the previous resolution error
|
||||
in some way.)
|
||||
* INFO output is a bit different now, and contains empty lines and comments
|
||||
starting with '#'. All the major clients should be already fixed to work
|
||||
with the new INFO format.
|
||||
|
||||
Also the following redis.conf and CONFIG GET / SET parameters changed name:
|
||||
|
||||
* hash-max-zipmap-entries, now replaced by hash-max-ziplist-entries
|
||||
* hash-max-zipmap-value, now replaced by hash-max-ziplist-value
|
||||
* glueoutputbuf option was now completely removed (was deprecated)
|
||||
From the point of view of the API Redis 2.4 only adds new commands
|
||||
(other commands now accepts a variable number of arguments) so you don't need
|
||||
to modify your program in order to use Redis 2.4.
|
||||
|
||||
---------
|
||||
CHANGELOG
|
||||
---------
|
||||
|
||||
What's new in Redis 2.5.8 (aka 2.6 Release Candidate 2)
|
||||
=======================================================
|
||||
What's new in Redis 2.4.2
|
||||
=========================
|
||||
|
||||
UPGRADE URGENCY: high for all the users of the KEYS command, otherwise low.
|
||||
* [BUGFIX] Unix socket creation mask config directive fixed.
|
||||
* [BUGFIX] Fixed a bug that forced Redis to continously rewrite the AOF file
|
||||
when a manual BGREWRITEAOF was issued during a BGSAVE was
|
||||
still in progress.
|
||||
* [BUGFIX] Fixed a server crash resulting from bad handling of SLAVEOF NO ONE.
|
||||
* [BUGFIX] Fixed a memory leak in redis-cli.
|
||||
* Debian/Ubuntu Redis system-wide installation script added under /utils.
|
||||
|
||||
* [BUGFIX] Fix for KEYS command: if the DB contains keys with expires the KEYS
|
||||
command may return the wrong output, having duplicated or missing
|
||||
keys. See issue #487 and #488 on github for details.
|
||||
What's new in Redis 2.4.1
|
||||
=========================
|
||||
|
||||
What's new in Redis 2.5.7 (aka 2.6 Release Candidate 1)
|
||||
=======================================================
|
||||
* [BUGFIX] FLUSHALL was not replicated nor written into the Append Only File.
|
||||
* [BUGFIX] FLUSHALL now only performs a sync SAVE if there is at least
|
||||
one save point configured.
|
||||
|
||||
UPGRADE URGENCY: upgrade not recommended because this is an RC release.
|
||||
What's new in Redis 2.4.0
|
||||
=========================
|
||||
|
||||
* This is the first release candidate for Redis 2.6. We are not aware of
|
||||
bugs, but part of this code is young and was never tested in production
|
||||
environments, so handle with care.
|
||||
* [BUGFIX] redis-cli segfault with single numerical argument fixed.
|
||||
* [BUGFIX] OpenBSD compilation problem fixed.
|
||||
* [BUGFIX] More robust Redis test, with better random port selection.
|
||||
* [BUGFIX] Fix for bug #128 about the RENAME command.
|
||||
* [BUGFIX] Fixed Issue #131. stime/utime reported in INFO was inverted.
|
||||
* [BUGFIX] Unlink Unix socket file on shutdown.
|
||||
* [BUGFIX] AUTH now returns error if no password is set on the server.
|
||||
* [BUGFIX] Exit with Fatal error at startup on RDB loading errors.
|
||||
* redis-check-dump: RDB version 2 now supported.
|
||||
* More informative error when DEBUG RELOAD fails.
|
||||
* Added a config directive for a Unix socket mask.
|
||||
* CONFIG SET/GET for loglevel.
|
||||
|
||||
An overview of new features and changes in Redis 2.6.x
|
||||
======================================================
|
||||
What's new in Redis 2.3.11 (2.4 Release Candidate 8)
|
||||
====================================================
|
||||
|
||||
* Server side Lua scripting, see http://redis.io/commands/eval
|
||||
* Virtual Memory removed (was deprecated in 2.4)
|
||||
* Hardcoded limits about max number of clients removed.
|
||||
* AOF low level semantics is generally more sane, and especially when used
|
||||
in slaves.
|
||||
* Milliseconds resolution expires, also added new commands with milliseconds
|
||||
precision (PEXPIRE, PTTL, ...).
|
||||
* Better memory usage for "small" lists, ziplists and hashes when fields or
|
||||
values contain small integers.
|
||||
* Read only slaves.
|
||||
* Clients max output buffer soft and hard limits. You can specifiy different
|
||||
limits for different classes of clients (normal,pubsub,slave).
|
||||
* AOF is now able to rewrite aggregate data types using variadic commands,
|
||||
often producing an AOF that is faster to save, load, and is smaller in size.
|
||||
* Every redis.conf directive is now accepted as a command line option for the
|
||||
redis-server binary, with the same name and number of arguments.
|
||||
* Hash table seed randomization for protection against collisions attacks.
|
||||
* Performances improved when writing large objects to Redis.
|
||||
* Integrated memory test, see redis-server --test-memory.
|
||||
* INCRBYFLOAT and HINCRBYFLOAT commands.
|
||||
* New DUMP, RESTORE, MIGRATE commands (back ported from Redis Cluster to 2.6).
|
||||
* CRC64 checksump in RDB files.
|
||||
* Better MONITOR output and behavior (now commands are logged before execution).
|
||||
* "Software Watchdog" feature to debug latency issues.
|
||||
* Significant parts of the core refactored or rewritten. New internal APIs
|
||||
and core changes allowed to develop Redis Cluster on top of the new code,
|
||||
however for 2.6 all the cluster code was removed, and will be released with
|
||||
Redis 3.0 when it is more complete and stable.
|
||||
* Redis ASCII art logo added at startup.
|
||||
* Crash report on memory violation or failed asserts improved significantly
|
||||
to make debugging of hard to catch bugs simpler.
|
||||
* redis-benchmark improvements: ability to run selected tests,
|
||||
CSV output, faster, better help.
|
||||
* redis-cli improvements: --eval for comfortable development of Lua scripts.
|
||||
* SHUTDOWN now supports two optional arguments: "SAVE" and "NOSAVE".
|
||||
* INFO output split into sections, the command is now able to just show
|
||||
pecific sections.
|
||||
* New statistics about how many time a command was called, and how much
|
||||
execution time it used (INFO commandstats).
|
||||
* More predictable SORT behavior in edge cases.
|
||||
* Better support for big endian and *BSD systems.
|
||||
* Build system improved.
|
||||
* [BUGFIX] Fixed a rare but possible AOF race condition that could result into
|
||||
duplicated commands inside the AOF.
|
||||
* [BUGFIX] Fixed issue 620, don't segfault on corrupted (by hand) AOF.
|
||||
* [BUGFIX] Fixed compilation on Mac/PPC.
|
||||
* [BUGFIX] Don't replicate SAVE.
|
||||
* LRANGE optimization may drastically improve performances when querying the
|
||||
final part of a long list.
|
||||
* redis-cli now implements a --latency mode to monitory Redis delay.
|
||||
* Hash type settings removed from INFO (same info is available via config GET)
|
||||
* Include port number on error when can't bind.
|
||||
* AOF fsync is now performed in background when fsync policy is 'everysec'.
|
||||
* AOF performances improved moving in background a possibly slow close(2) call.
|
||||
* AOF protocol synthesis speedup.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
What's new in Redis 2.3.10 (2.4 Release Candidate 7)
|
||||
====================================================
|
||||
|
||||
* [BUGFIX] Fixed issue 593 (BRPOPLPUSH related crash).
|
||||
* [BUGFIX] Fixed an issue with the networking layer that may prevent Redis from sending the whole reply back to client under extreme conditions.
|
||||
|
||||
What's new in Redis 2.3.9 (2.4 Release Candidate 6)
|
||||
===================================================
|
||||
|
||||
* [BUGFIX] Fixed a bug with the automatic AOF rewrite causing continuous
|
||||
rewrites for AOF files bigger than 4 GB.
|
||||
* New maxmemory tests.
|
||||
|
||||
What's new in Redis 2.3.8 (2.4 Release Candidate 5)
|
||||
===================================================
|
||||
|
||||
Compared to Redis 2.3.7 (RC4) there are the following changes:
|
||||
|
||||
* [BUGFIX] HDEL: Abort deleting fields when hash is removed.
|
||||
* [BUGFIX] Fix adding bulk reply when getcwd fails.
|
||||
|
||||
WHAT'S NEW IN REDIS 2.4 compared to the 2.2 version?
|
||||
====================================================
|
||||
|
||||
* Specially encoded sorted sets, now small sorted sets will use little memory.
|
||||
* Native persistence of specially encoded data types (ziplists, zipmaps,
|
||||
intsets). Many data sets will be saved and loaded an order of magnitude
|
||||
faster.
|
||||
* Variadic versions of commands: SADD, HDEL, SREM, ZREM, ZADD, L/RPUSH.
|
||||
* Jemalloc support (enabled by default for Linux build) in order to
|
||||
avoid fragmentation issues.
|
||||
* Reduced memory usage while saving.
|
||||
* More info fields (peak memory, fork time, ...)
|
||||
* OBJECT command for objects introspection.
|
||||
* CLIENT command for clients introspection.
|
||||
* Non blocking slave -> master connection.
|
||||
* Better redis-cli connection handling. New redis-cli features.
|
||||
* Better redis-benchmark, now able to benchmark user provided commands.
|
||||
* Colorized Make.
|
||||
* VM deprecated. Still supported but with a big warning... don't use it.
|
||||
* Many speed optimizations and bug fixes.
|
||||
|
||||
Credits: Where not specified the implementation and design are done by
|
||||
Salvatore Sanfilippo and Pieter Noordhuis. Thanks to VMware for making all
|
||||
this possible. Also many thanks to all the other contributors and the amazing
|
||||
community we have.
|
||||
|
||||
See commit messages for more credits.
|
||||
|
||||
Cheers,
|
||||
Salvatore
|
||||
|
||||
@@ -1 +1 @@
|
||||
Plese check https://github.com/antirez/redis/issues
|
||||
Plese check http://code.google.com/p/redis/issues/list
|
||||
|
||||
+3
-3
@@ -1,13 +1,13 @@
|
||||
1. Enter irc.freenode.org #redis and start talking with 'antirez' and/or 'pietern' to check if there is interest for such a feature and to understand the probability of it being merged. We'll try hard to keep Redis simple... so you'll likely encounter high resistance.
|
||||
1. Enter irc.freenode.org #redis and start talking with 'antirez' and/or 'pietern' to check if there is interest for such a feature and to understand the probability of it being merged. We'll try hard to keep Redis simple... so you'll likely encounter an high resistence.
|
||||
|
||||
2. Drop a message to the Redis Google Group with a proposal of semantics/API.
|
||||
|
||||
3. If steps 1 and 2 are ok, use the following procedure to submit a patch:
|
||||
|
||||
a. Fork Redis on github ( http://help.github.com/fork-a-repo/ )
|
||||
a. Fork Redis on github
|
||||
b. Create a topic branch (git checkout -b my_branch)
|
||||
c. Push to your branch (git push origin my_branch)
|
||||
d. Initiate a pull request on github ( http://help.github.com/send-pull-requests/ )
|
||||
d. Create an issue in the Redis google code site with a link to your patch
|
||||
e. Done :)
|
||||
|
||||
Thanks!
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
[Note: this is the Redis manifesto, for general information about
|
||||
installing and running Redis read the README file instead.]
|
||||
|
||||
Redis Manifesto
|
||||
===============
|
||||
|
||||
1 - A DSL for Abstract Data Types. Redis is a DSL (Domain Specific Language) that manipulates abstract data types and implemented as a TCP daemon. Commands manipulate a key space where keys are binary-safe strings and values are different kinds of abstract data types. Every data type represents an abstract version of a fundamental data structure. For instance Redis Lists are an abstract representation of linked lists. In Redis, the essence of a data type isn't just the kind of operations that the data types support, but also the space and time complexity of the data type and the operations performed upon it.
|
||||
|
||||
2 - Memory storage is #1. The Redis data set, composed of defined key-value pairs, is primarily stored in the computer's memory. The amount of memory in all kinds of computers, including entry-level servers, is increasing significantly each year. Memory is fast, and allows Redis to have very predictable performance. Datasets composed of 10k or 40 millions keys will perform similarly. Complex data types like Redis Sorted Sets are easy to implement and manipulate in memory with good performance, making Redis very simple. Redis will continue to explore alternative options (where data can be optionally stored on disk, say) but the main goal of the project remains the development of an in-memory database.
|
||||
|
||||
3 - Fundamental data structures for a fundamental API. The Redis API is a direct consequence of fundamental data structures. APIs can often be arbitrary but not an API that resembles the nature of fundamental data structures. If we ever meet intelligent life forms from another part of the universe, they'll likely know, understand and recognize the same basic data structures we have in our computer science books. Redis will avoid intermediate layers in API, so that the complexity is obvious and more complex operations can be performed as the sum of the basic operations.
|
||||
|
||||
4 - Code is like a poem; it's not just something we write to reach some practical result. Sometimes people that are far from the Redis philosophy suggest using other code written by other authors (frequently in other languages) in order to implement something Redis currently lacks. But to us this is like if Shakespeare decided to end Enrico IV using the Paradiso from the Divina Commedia. Is using any external code a bad idea? Not at all. Like in "One Thousand and One Nights" smaller self contained stories are embedded in a bigger story, we'll be happy to use beautiful self contained libraries when needed. At the same time, when writing the Redis story we're trying to write smaller stories that will fit in to other code.
|
||||
|
||||
5 - We're against complexity. We believe designing systems is a fight against complexity. We'll accept to fight the complexity when it's worthwhile but we'll try hard to recognize when a small feature is not worth 1000s of lines of code. Most of the time the best way to fight complexity is by not creating it at all.
|
||||
|
||||
6 - Two levels of API. The Redis API has two levels: 1) a subset of the API fits naturally into a distributed version of Redis and 2) a more complex API that supports multi-key operations. Both are useful if used judiciously but there's no way to make the more complex multi-keys API distributed in an opaque way without violating our other principles. We don't want to provide the illusion of something that will work magically when actually it can't in all cases. Instead we'll provide commands to quickly migrate keys from one instance to another to perform multi-key operations and expose the tradeoffs to the user.
|
||||
|
||||
7 - We optimize for joy. We believe writing code is a lot of hard work, and the only way it can be worth is by enjoying it. When there is no longer joy in writing code, the best thing to do is stop. To prevent this, we'll avoid taking paths that will make Redis less of a joy to develop.
|
||||
|
||||
@@ -1,7 +1,23 @@
|
||||
# Top level makefile, the real shit is at src/Makefile
|
||||
|
||||
default: all
|
||||
TARGETS=32bit noopt test
|
||||
|
||||
.DEFAULT:
|
||||
all:
|
||||
cd src && $(MAKE) $@
|
||||
|
||||
install: dummy
|
||||
cd src && $(MAKE) $@
|
||||
|
||||
clean:
|
||||
cd src && $(MAKE) $@
|
||||
cd deps/hiredis && $(MAKE) $@
|
||||
cd deps/linenoise && $(MAKE) $@
|
||||
-(cd deps/jemalloc && $(MAKE) distclean)
|
||||
|
||||
$(TARGETS):
|
||||
cd src && $(MAKE) $@
|
||||
|
||||
src/help.h:
|
||||
@./utils/generate-command-help.rb > $@
|
||||
|
||||
dummy:
|
||||
|
||||
@@ -7,13 +7,6 @@ documentation at http://redis.io
|
||||
Building Redis
|
||||
--------------
|
||||
|
||||
Redis can be compiled and used on Linux, OSX, OpenBSD, NetBSD, FreeBSD.
|
||||
We support big endian and little endian architectures.
|
||||
|
||||
It may compile on Solaris derived systems (for instance SmartOS) but our
|
||||
support for this platform is "best effort" and Redis is not guaranteed to
|
||||
work as well as in Linux, OSX, and *BSD there.
|
||||
|
||||
It is as simple as:
|
||||
|
||||
% make
|
||||
@@ -33,19 +26,18 @@ NOTE: if after building Redis with a 32 bit target you need to rebuild it
|
||||
Allocator
|
||||
---------
|
||||
|
||||
Selecting a non-default memory allocator when building Redis is done by setting
|
||||
the `MALLOC` environment variable. Redis is compiled and linked against libc
|
||||
malloc by default, with the exception of jemalloc being the default on Linux
|
||||
systems. This default was picked because jemalloc has proven to have fewer
|
||||
fragmentation problems than libc malloc.
|
||||
By default Redis compiles and links against jemalloc under Linux, since
|
||||
glibc malloc() has memory fragmentation problems.
|
||||
|
||||
To force compiling against libc malloc, use:
|
||||
To force a libc malloc() build use:
|
||||
|
||||
% make MALLOC=libc
|
||||
% make FORCE_LIBC_MALLOC=yes
|
||||
|
||||
To compile against jemalloc on Mac OS X systems, use:
|
||||
In all the other non Linux systems the libc malloc() is used by default.
|
||||
|
||||
% make MALLOC=jemalloc
|
||||
On Mac OS X you can force a jemalloc based build using the following:
|
||||
|
||||
% make USE_JEMALLOC=yes
|
||||
|
||||
Verbose build
|
||||
-------------
|
||||
@@ -69,15 +61,6 @@ parameter (the path of the configuration file):
|
||||
% cd src
|
||||
% ./redis-server /path/to/redis.conf
|
||||
|
||||
It is possible to alter the Redis configuration passing parameters directly
|
||||
as options using the command line. Examples:
|
||||
|
||||
% ./redis-server --port 9999 --slaveof 127.0.0.1 6379
|
||||
% ./redis-server /etc/redis/6379.conf --loglevel debug
|
||||
|
||||
All the options in redis.conf are also supported as options using the command
|
||||
line, with exactly the same name.
|
||||
|
||||
Playing with Redis
|
||||
------------------
|
||||
|
||||
|
||||
@@ -1,45 +1,4 @@
|
||||
Redis TODO
|
||||
----------
|
||||
This is a stable release! No TODO file here.
|
||||
Please check the TODO file in the master branch on github.
|
||||
|
||||
WARNING: are you a possible Redis contributor?
|
||||
Before implementing what is listed in this file
|
||||
please drop a message in the Redis google group or chat with
|
||||
antirez or pietern on irc.freenode.org #redis to check if the work
|
||||
is already in progress and if the feature is still interesting for
|
||||
us, and *how* exactly this can be implemented to have good changes
|
||||
of a merge. Otherwise it is probably wasted work! Thank you
|
||||
|
||||
|
||||
CLUSTER
|
||||
=======
|
||||
|
||||
* Implement rehashing and cluster check in redis-trib.
|
||||
* Reimplement MIGRATE / RESTORE to use just in memory buffers (no disk at
|
||||
all). This will require touching a lot of the RDB stuff around, but we may
|
||||
hand with faster persistence for RDB.
|
||||
* Implement the slave nodes semantics and election.
|
||||
* Allow redis-trib to create a cluster-wide snapshot (using SYNC).
|
||||
* Allow redis-trib to restore a cluster-wide snapshot (implement UPLOAD?).
|
||||
|
||||
SCRIPTING
|
||||
=========
|
||||
|
||||
* SCRIPT FLUSH or alike to start a fresh interpreter?
|
||||
|
||||
OPTIMIZATIONS
|
||||
=============
|
||||
|
||||
* SORT: Don't copy the list into a vector when BY argument is constant.
|
||||
* Write the hash table size of every db in the dump, so that Redis can resize the hash table just one time when loading a big DB.
|
||||
* Read-only mode for slaves.
|
||||
* Redis big lists as linked lists of small ziplists?
|
||||
Possibly a simple heuristic that join near nodes when some node gets smaller than the low_level, and split it into two if gets bigger than high_level.
|
||||
|
||||
KNOWN BUGS
|
||||
==========
|
||||
|
||||
* #519: Slave may have expired keys that were never read in the master (so a DEL
|
||||
is not sent in the replication channel) but are already expired since
|
||||
a lot of time. Maybe after a given delay that is undoubtably greater than
|
||||
the replication link latency we should expire this key on the slave on
|
||||
access?
|
||||
https://github.com/antirez/redis/raw/master/TODO
|
||||
|
||||
Vendored
-78
@@ -1,78 +0,0 @@
|
||||
# Redis dependency Makefile
|
||||
|
||||
uname_S:= $(shell sh -c 'uname -s 2>/dev/null || echo not')
|
||||
|
||||
CCCOLOR="\033[34m"
|
||||
LINKCOLOR="\033[34;1m"
|
||||
SRCCOLOR="\033[33m"
|
||||
BINCOLOR="\033[37;1m"
|
||||
MAKECOLOR="\033[32;1m"
|
||||
ENDCOLOR="\033[0m"
|
||||
|
||||
default:
|
||||
@echo "Explicit target required"
|
||||
|
||||
.PHONY: default
|
||||
|
||||
# Prerequisites target
|
||||
.make-prerequisites:
|
||||
@touch $@
|
||||
|
||||
# Clean everything when CFLAGS is different
|
||||
ifneq ($(shell sh -c '[ -f .make-cflags ] && cat .make-cflags || echo none'), $(CFLAGS))
|
||||
.make-cflags: distclean
|
||||
-(echo "$(CFLAGS)" > .make-cflags)
|
||||
.make-prerequisites: .make-cflags
|
||||
endif
|
||||
|
||||
# Clean everything when LDFLAGS is different
|
||||
ifneq ($(shell sh -c '[ -f .make-ldflags ] && cat .make-ldflags || echo none'), $(LDFLAGS))
|
||||
.make-ldflags: distclean
|
||||
-(echo "$(LDFLAGS)" > .make-ldflags)
|
||||
.make-prerequisites: .make-ldflags
|
||||
endif
|
||||
|
||||
distclean:
|
||||
-(cd hiredis && $(MAKE) clean) > /dev/null || true
|
||||
-(cd linenoise && $(MAKE) clean) > /dev/null || true
|
||||
-(cd lua && $(MAKE) clean) > /dev/null || true
|
||||
-(cd jemalloc && [ -f Makefile ] && $(MAKE) distclean) > /dev/null || true
|
||||
-(rm -f .make-*)
|
||||
|
||||
.PHONY: distclean
|
||||
|
||||
hiredis: .make-prerequisites
|
||||
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)
|
||||
cd hiredis && $(MAKE) static
|
||||
|
||||
.PHONY: hiredis
|
||||
|
||||
linenoise: .make-prerequisites
|
||||
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)
|
||||
cd linenoise && $(MAKE)
|
||||
|
||||
.PHONY: linenoise
|
||||
|
||||
ifeq ($(uname_S),SunOS)
|
||||
# Make isinf() available
|
||||
LUA_CFLAGS= -D__C99FEATURES__=1
|
||||
endif
|
||||
|
||||
LUA_CFLAGS+= -O2 -Wall -DLUA_ANSI $(CFLAGS)
|
||||
LUA_LDFLAGS+= $(LDFLAGS)
|
||||
|
||||
lua: .make-prerequisites
|
||||
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)
|
||||
cd lua/src && $(MAKE) all CFLAGS="$(LUA_CFLAGS)" MYLDFLAGS="$(LUA_LDFLAGS)"
|
||||
|
||||
.PHONY: lua
|
||||
|
||||
JEMALLOC_CFLAGS= -std=gnu99 -Wall -pipe -g3 -O3 -funroll-loops $(CFLAGS)
|
||||
JEMALLOC_LDFLAGS= $(LDFLAGS)
|
||||
|
||||
jemalloc: .make-prerequisites
|
||||
@printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)
|
||||
cd jemalloc && ./configure --with-jemalloc-prefix=je_ --enable-cc-silence CFLAGS="$(JEMALLOC_CFLAGS)" LDFLAGS="$(JEMALLOC_LDFLAGS)"
|
||||
cd jemalloc && $(MAKE) lib/libjemalloc.a
|
||||
|
||||
.PHONY: jemalloc
|
||||
Vendored
-16
@@ -1,16 +0,0 @@
|
||||
### 0.10.1
|
||||
|
||||
* Makefile overhaul. Important to check out if you override one or more
|
||||
variables using environment variables or via arguments to the "make" tool.
|
||||
|
||||
* Issue #45: Fix potential memory leak for a multi bulk reply with 0 elements
|
||||
being created by the default reply object functions.
|
||||
|
||||
* Issue #43: Don't crash in an asynchronous context when Redis returns an error
|
||||
reply after the connection has been made (this happens when the maximum
|
||||
number of connections is reached).
|
||||
|
||||
### 0.10.0
|
||||
|
||||
* See commit log.
|
||||
|
||||
Vendored
+6
-25
@@ -1,29 +1,10 @@
|
||||
Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
|
||||
Copyright (c) 2006-2009, Salvatore Sanfilippo
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Redis nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of Redis nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Vendored
+65
-98
@@ -1,148 +1,115 @@
|
||||
# Hiredis Makefile
|
||||
# Copyright (C) 2010-2011 Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
# Copyright (C) 2010-2011 Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
# Copyright (C) 2010 Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
# This file is released under the BSD license, see the COPYING file
|
||||
|
||||
OBJ=net.o hiredis.o sds.o async.o
|
||||
BINS=hiredis-example hiredis-test
|
||||
LIBNAME=libhiredis
|
||||
OBJ = net.o hiredis.o sds.o async.o
|
||||
BINS = hiredis-example hiredis-test
|
||||
|
||||
HIREDIS_MAJOR=0
|
||||
HIREDIS_MINOR=10
|
||||
|
||||
# Fallback to gcc when $CC is not in $PATH.
|
||||
CC:=$(shell sh -c 'type $(CC) >/dev/null 2>/dev/null && echo $(CC) || echo gcc')
|
||||
OPTIMIZATION?=-O3
|
||||
WARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings
|
||||
DEBUG?= -g -ggdb
|
||||
REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CFLAGS) $(WARNINGS) $(DEBUG) $(ARCH)
|
||||
REAL_LDFLAGS=$(LDFLAGS) $(ARCH)
|
||||
|
||||
DYLIBSUFFIX=so
|
||||
STLIBSUFFIX=a
|
||||
DYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR).$(HIREDIS_MINOR)
|
||||
DYLIB_MAJOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR)
|
||||
DYLIBNAME=$(LIBNAME).$(DYLIBSUFFIX)
|
||||
DYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)
|
||||
STLIBNAME=$(LIBNAME).$(STLIBSUFFIX)
|
||||
STLIB_MAKE_CMD=ar rcs $(STLIBNAME)
|
||||
|
||||
# Platform-specific overrides
|
||||
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
|
||||
OPTIMIZATION?=-O3
|
||||
ifeq ($(uname_S),SunOS)
|
||||
REAL_LDFLAGS+= -ldl -lnsl -lsocket
|
||||
DYLIB_MAKE_CMD=$(CC) -G -o $(DYLIBNAME) -h $(DYLIB_MINOR_NAME) $(LDFLAGS)
|
||||
INSTALL= cp -r
|
||||
endif
|
||||
CFLAGS?=-std=c99 -pedantic $(OPTIMIZATION) -fPIC -Wall -W -D__EXTENSIONS__ -D_XPG6 $(ARCH) $(PROF)
|
||||
CCLINK?=-ldl -lnsl -lsocket -lm -lpthread
|
||||
LDFLAGS?=-L. -Wl,-R,.
|
||||
DYLIBNAME?=libhiredis.so
|
||||
DYLIB_MAKE_CMD?=$(CC) -G -o ${DYLIBNAME} ${OBJ}
|
||||
STLIBNAME?=libhiredis.a
|
||||
STLIB_MAKE_CMD?=ar rcs ${STLIBNAME} ${OBJ}
|
||||
else
|
||||
ifeq ($(uname_S),Darwin)
|
||||
DYLIBSUFFIX=dylib
|
||||
DYLIB_MINOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(HIREDIS_MINOR).$(DYLIBSUFFIX)
|
||||
DYLIB_MAJOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(DYLIBSUFFIX)
|
||||
DYLIB_MAKE_CMD=$(CC) -shared -Wl,-install_name,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)
|
||||
CFLAGS?=-std=c99 -pedantic $(OPTIMIZATION) -fPIC -Wall -W -Wstrict-prototypes -Wwrite-strings $(ARCH) $(PROF)
|
||||
CCLINK?=-lm -pthread
|
||||
LDFLAGS?=-L. -Wl,-rpath,.
|
||||
OBJARCH?=-arch i386 -arch x86_64
|
||||
DYLIBNAME?=libhiredis.dylib
|
||||
DYLIB_MAKE_CMD?=libtool -dynamic -o ${DYLIBNAME} -lm ${DEBUG} - ${OBJ}
|
||||
STLIBNAME?=libhiredis.a
|
||||
STLIB_MAKE_CMD?=libtool -static -o ${STLIBNAME} - ${OBJ}
|
||||
else
|
||||
CFLAGS?=-std=c99 -pedantic $(OPTIMIZATION) -fPIC -Wall -W -Wstrict-prototypes -Wwrite-strings $(ARCH) $(PROF)
|
||||
CCLINK?=-lm -pthread
|
||||
LDFLAGS?=-L. -Wl,-rpath,.
|
||||
DYLIBNAME?=libhiredis.so
|
||||
DYLIB_MAKE_CMD?=gcc -shared -Wl,-soname,${DYLIBNAME} -o ${DYLIBNAME} ${OBJ}
|
||||
STLIBNAME?=libhiredis.a
|
||||
STLIB_MAKE_CMD?=ar rcs ${STLIBNAME} ${OBJ}
|
||||
endif
|
||||
endif
|
||||
|
||||
all: $(DYLIBNAME) $(BINS)
|
||||
CCOPT= $(CFLAGS) $(CCLINK)
|
||||
DEBUG?= -g -ggdb
|
||||
|
||||
PREFIX?= /usr/local
|
||||
INSTALL_INC= $(PREFIX)/include/hiredis
|
||||
INSTALL_LIB= $(PREFIX)/lib
|
||||
INSTALL= cp -a
|
||||
|
||||
all: ${DYLIBNAME} ${BINS}
|
||||
|
||||
# Deps (use make dep to generate this)
|
||||
net.o: net.c fmacros.h net.h hiredis.h
|
||||
async.o: async.c async.h hiredis.h sds.h dict.c dict.h
|
||||
net.o: net.c fmacros.h net.h
|
||||
async.o: async.c async.h hiredis.h sds.h util.h dict.c dict.h
|
||||
example.o: example.c hiredis.h
|
||||
hiredis.o: hiredis.c fmacros.h hiredis.h net.h sds.h
|
||||
hiredis.o: hiredis.c hiredis.h net.h sds.h util.h
|
||||
sds.o: sds.c sds.h
|
||||
test.o: test.c hiredis.h
|
||||
|
||||
$(DYLIBNAME): $(OBJ)
|
||||
$(DYLIB_MAKE_CMD) $(OBJ)
|
||||
${DYLIBNAME}: ${OBJ}
|
||||
${DYLIB_MAKE_CMD}
|
||||
|
||||
$(STLIBNAME): $(OBJ)
|
||||
$(STLIB_MAKE_CMD) $(OBJ)
|
||||
${STLIBNAME}: ${OBJ}
|
||||
${STLIB_MAKE_CMD}
|
||||
|
||||
dynamic: $(DYLIBNAME)
|
||||
static: $(STLIBNAME)
|
||||
dynamic: ${DYLIBNAME}
|
||||
static: ${STLIBNAME}
|
||||
|
||||
# Binaries:
|
||||
hiredis-example-libevent: example-libevent.c adapters/libevent.h $(STLIBNAME)
|
||||
$(CC) -o $@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -levent example-libevent.c $(STLIBNAME)
|
||||
hiredis-example-libevent: example-libevent.c adapters/libevent.h ${DYLIBNAME}
|
||||
$(CC) -o $@ $(CCOPT) $(DEBUG) $(LDFLAGS) -lhiredis -levent example-libevent.c
|
||||
|
||||
hiredis-example-libev: example-libev.c adapters/libev.h $(STLIBNAME)
|
||||
$(CC) -o $@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -lev example-libev.c $(STLIBNAME)
|
||||
hiredis-example-libev: example-libev.c adapters/libev.h ${DYLIBNAME}
|
||||
$(CC) -o $@ $(CCOPT) $(DEBUG) $(LDFLAGS) -lhiredis -lev example-libev.c
|
||||
|
||||
ifndef AE_DIR
|
||||
hiredis-example-ae:
|
||||
@echo "Please specify AE_DIR (e.g. <redis repository>/src)"
|
||||
@false
|
||||
else
|
||||
hiredis-example-ae: example-ae.c adapters/ae.h $(STLIBNAME)
|
||||
$(CC) -o $@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I$(AE_DIR) $(AE_DIR)/ae.o $(AE_DIR)/zmalloc.o example-ae.c $(STLIBNAME)
|
||||
hiredis-example-ae: example-ae.c adapters/ae.h ${DYLIBNAME}
|
||||
$(CC) -o $@ $(CCOPT) $(DEBUG) -I$(AE_DIR) $(LDFLAGS) -lhiredis example-ae.c $(AE_DIR)/ae.o $(AE_DIR)/zmalloc.o
|
||||
endif
|
||||
|
||||
hiredis-%: %.o $(STLIBNAME)
|
||||
$(CC) -o $@ $(REAL_LDFLAGS) $< $(STLIBNAME)
|
||||
hiredis-%: %.o ${DYLIBNAME}
|
||||
$(CC) -o $@ $(CCOPT) $(DEBUG) $(LDFLAGS) -lhiredis $<
|
||||
|
||||
test: hiredis-test
|
||||
./hiredis-test
|
||||
|
||||
check: hiredis-test
|
||||
echo \
|
||||
"daemonize yes\n" \
|
||||
"pidfile /tmp/hiredis-test-redis.pid\n" \
|
||||
"port 56379\n" \
|
||||
"bind 127.0.0.1\n" \
|
||||
"unixsocket /tmp/hiredis-test-redis.sock" \
|
||||
| redis-server -
|
||||
./hiredis-test -h 127.0.0.1 -p 56379 -s /tmp/hiredis-test-redis.sock || \
|
||||
( kill `cat /tmp/hiredis-test-redis.pid` && false )
|
||||
kill `cat /tmp/hiredis-test-redis.pid`
|
||||
|
||||
.c.o:
|
||||
$(CC) -std=c99 -pedantic -c $(REAL_CFLAGS) $<
|
||||
$(CC) -c $(CFLAGS) $(OBJARCH) $(DEBUG) $(COMPILE_TIME) $<
|
||||
|
||||
clean:
|
||||
rm -rf $(DYLIBNAME) $(STLIBNAME) $(BINS) hiredis-example* *.o *.gcda *.gcno *.gcov
|
||||
rm -rf ${DYLIBNAME} ${STLIBNAME} $(BINS) hiredis-example* *.o *.gcda *.gcno *.gcov
|
||||
|
||||
dep:
|
||||
$(CC) -MM *.c
|
||||
|
||||
# Installation related variables and target
|
||||
PREFIX?=/usr/local
|
||||
INCLUDE_PATH?=include/hiredis
|
||||
LIBRARY_PATH?=lib
|
||||
INSTALL_INCLUDE_PATH= $(PREFIX)/$(INCLUDE_PATH)
|
||||
INSTALL_LIBRARY_PATH= $(PREFIX)/$(LIBRARY_PATH)
|
||||
|
||||
ifeq ($(uname_S),SunOS)
|
||||
INSTALL?= cp -r
|
||||
endif
|
||||
|
||||
INSTALL?= cp -a
|
||||
|
||||
install: $(DYLIBNAME) $(STLIBNAME)
|
||||
mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH)
|
||||
$(INSTALL) hiredis.h async.h adapters $(INSTALL_INCLUDE_PATH)
|
||||
$(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME)
|
||||
cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIB_MAJOR_NAME)
|
||||
cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MAJOR_NAME) $(DYLIBNAME)
|
||||
$(INSTALL) $(STLIBNAME) $(INSTALL_LIBRARY_PATH)
|
||||
install: ${DYLIBNAME} ${STLIBNAME}
|
||||
mkdir -p $(INSTALL_INC) $(INSTALL_LIB)
|
||||
$(INSTALL) hiredis.h async.h adapters $(INSTALL_INC)
|
||||
$(INSTALL) ${DYLIBNAME} ${STLIBNAME} $(INSTALL_LIB)
|
||||
|
||||
32bit:
|
||||
@echo ""
|
||||
@echo "WARNING: if this fails under Linux you probably need to install libc6-dev-i386"
|
||||
@echo "WARNING: if it fails under Linux you probably need to install libc6-dev-i386"
|
||||
@echo ""
|
||||
$(MAKE) CFLAGS="-m32" LDFLAGS="-m32"
|
||||
$(MAKE) ARCH="-m32"
|
||||
|
||||
gprof:
|
||||
$(MAKE) CFLAGS="-pg" LDFLAGS="-pg"
|
||||
$(MAKE) PROF="-pg"
|
||||
|
||||
gcov:
|
||||
$(MAKE) CFLAGS="-fprofile-arcs -ftest-coverage" LDFLAGS="-fprofile-arcs"
|
||||
|
||||
coverage: gcov
|
||||
make check
|
||||
mkdir -p tmp/lcov
|
||||
lcov -d . -c -o tmp/lcov/hiredis.info
|
||||
genhtml --legend -o tmp/lcov/report tmp/lcov/hiredis.info
|
||||
$(MAKE) PROF="-fprofile-arcs -ftest-coverage"
|
||||
|
||||
noopt:
|
||||
$(MAKE) OPTIMIZATION=""
|
||||
|
||||
.PHONY: all test check clean dep install 32bit gprof gcov noopt
|
||||
|
||||
Vendored
+2
-43
@@ -116,12 +116,6 @@ Note that this function will take care of freeing sub-replies objects
|
||||
contained in arrays and nested arrays, so there is no need for the user to
|
||||
free the sub replies (it is actually harmful and will corrupt the memory).
|
||||
|
||||
**Important:** the current version of hiredis (0.10.0) free's replies when the
|
||||
asynchronous API is used. This means you should not call `freeReplyObject` when
|
||||
you use this API. The reply is cleaned up by hiredis _after_ the callback
|
||||
returns. This behavior will probably change in future releases, so make sure to
|
||||
keep an eye on the changelog when upgrading (see issue #39).
|
||||
|
||||
### Cleaning up
|
||||
|
||||
To disconnect and free the context the following function can be used:
|
||||
@@ -286,8 +280,7 @@ is being disconnected per user-request, no new commands may be added to the outp
|
||||
returned on calls to the `redisAsyncCommand` family.
|
||||
|
||||
If the reply for a command with a `NULL` callback is read, it is immediately free'd. When the callback
|
||||
for a command is non-`NULL`, the memory is free'd immediately following the callback: the reply is only
|
||||
valid for the duration of the callback.
|
||||
for a command is non-`NULL`, it is responsible for cleaning up the reply.
|
||||
|
||||
All pending callbacks are called with a `NULL` reply when the context encountered an error.
|
||||
|
||||
@@ -310,41 +303,7 @@ See the `adapters/` directory for bindings to *libev* and *libevent*.
|
||||
|
||||
## Reply parsing API
|
||||
|
||||
Hiredis comes with a reply parsing API that makes it easy for writing higher
|
||||
level language bindings.
|
||||
|
||||
The reply parsing API consists of the following functions:
|
||||
|
||||
redisReader *redisReaderCreate(void);
|
||||
void redisReaderFree(redisReader *reader);
|
||||
int redisReaderFeed(redisReader *reader, const char *buf, size_t len);
|
||||
int redisReaderGetReply(redisReader *reader, void **reply);
|
||||
|
||||
### Usage
|
||||
|
||||
The function `redisReaderCreate` creates a `redisReader` structure that holds a
|
||||
buffer with unparsed data and state for the protocol parser.
|
||||
|
||||
Incoming data -- most likely from a socket -- can be placed in the internal
|
||||
buffer of the `redisReader` using `redisReaderFeed`. This function will make a
|
||||
copy of the buffer pointed to by `buf` for `len` bytes. This data is parsed
|
||||
when `redisReaderGetReply` is called. This function returns an integer status
|
||||
and a reply object (as described above) via `void **reply`. The returned status
|
||||
can be either `REDIS_OK` or `REDIS_ERR`, where the latter means something went
|
||||
wrong (either a protocol error, or an out of memory error).
|
||||
|
||||
### Customizing replies
|
||||
|
||||
The function `redisReaderGetReply` creates `redisReply` and makes the function
|
||||
argument `reply` point to the created `redisReply` variable. For instance, if
|
||||
the response of type `REDIS_REPLY_STATUS` then the `str` field of `redisReply`
|
||||
will hold the status as a vanilla C string. However, the functions that are
|
||||
responsible for creating instances of the `redisReply` can be customized by
|
||||
setting the `fn` field on the `redisReader` struct. This should be done
|
||||
immediately after creating the `redisReader`.
|
||||
|
||||
For example, [hiredis-rb](https://github.com/pietern/hiredis-rb/blob/master/ext/hiredis_ext/reader.c)
|
||||
uses customized reply object functions to create Ruby objects.
|
||||
To be done.
|
||||
|
||||
## AUTHORS
|
||||
|
||||
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
- add redisCommandVector()
|
||||
- add support for pipelining
|
||||
Vendored
+16
-18
@@ -1,5 +1,3 @@
|
||||
#ifndef __HIREDIS_AE_H__
|
||||
#define __HIREDIS_AE_H__
|
||||
#include <sys/types.h>
|
||||
#include <ae.h>
|
||||
#include "../hiredis.h"
|
||||
@@ -12,21 +10,21 @@ typedef struct redisAeEvents {
|
||||
int reading, writing;
|
||||
} redisAeEvents;
|
||||
|
||||
static void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) {
|
||||
void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) {
|
||||
((void)el); ((void)fd); ((void)mask);
|
||||
|
||||
redisAeEvents *e = (redisAeEvents*)privdata;
|
||||
redisAsyncHandleRead(e->context);
|
||||
}
|
||||
|
||||
static void redisAeWriteEvent(aeEventLoop *el, int fd, void *privdata, int mask) {
|
||||
void redisAeWriteEvent(aeEventLoop *el, int fd, void *privdata, int mask) {
|
||||
((void)el); ((void)fd); ((void)mask);
|
||||
|
||||
redisAeEvents *e = (redisAeEvents*)privdata;
|
||||
redisAsyncHandleWrite(e->context);
|
||||
}
|
||||
|
||||
static void redisAeAddRead(void *privdata) {
|
||||
void redisAeAddRead(void *privdata) {
|
||||
redisAeEvents *e = (redisAeEvents*)privdata;
|
||||
aeEventLoop *loop = e->loop;
|
||||
if (!e->reading) {
|
||||
@@ -35,7 +33,7 @@ static void redisAeAddRead(void *privdata) {
|
||||
}
|
||||
}
|
||||
|
||||
static void redisAeDelRead(void *privdata) {
|
||||
void redisAeDelRead(void *privdata) {
|
||||
redisAeEvents *e = (redisAeEvents*)privdata;
|
||||
aeEventLoop *loop = e->loop;
|
||||
if (e->reading) {
|
||||
@@ -44,7 +42,7 @@ static void redisAeDelRead(void *privdata) {
|
||||
}
|
||||
}
|
||||
|
||||
static void redisAeAddWrite(void *privdata) {
|
||||
void redisAeAddWrite(void *privdata) {
|
||||
redisAeEvents *e = (redisAeEvents*)privdata;
|
||||
aeEventLoop *loop = e->loop;
|
||||
if (!e->writing) {
|
||||
@@ -53,7 +51,7 @@ static void redisAeAddWrite(void *privdata) {
|
||||
}
|
||||
}
|
||||
|
||||
static void redisAeDelWrite(void *privdata) {
|
||||
void redisAeDelWrite(void *privdata) {
|
||||
redisAeEvents *e = (redisAeEvents*)privdata;
|
||||
aeEventLoop *loop = e->loop;
|
||||
if (e->writing) {
|
||||
@@ -62,19 +60,19 @@ static void redisAeDelWrite(void *privdata) {
|
||||
}
|
||||
}
|
||||
|
||||
static void redisAeCleanup(void *privdata) {
|
||||
void redisAeCleanup(void *privdata) {
|
||||
redisAeEvents *e = (redisAeEvents*)privdata;
|
||||
redisAeDelRead(privdata);
|
||||
redisAeDelWrite(privdata);
|
||||
free(e);
|
||||
}
|
||||
|
||||
static int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) {
|
||||
int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) {
|
||||
redisContext *c = &(ac->c);
|
||||
redisAeEvents *e;
|
||||
|
||||
/* Nothing should be attached when something is already attached */
|
||||
if (ac->ev.data != NULL)
|
||||
if (ac->_adapter_data != NULL)
|
||||
return REDIS_ERR;
|
||||
|
||||
/* Create container for context and r/w events */
|
||||
@@ -85,13 +83,13 @@ static int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) {
|
||||
e->reading = e->writing = 0;
|
||||
|
||||
/* Register functions to start/stop listening for events */
|
||||
ac->ev.addRead = redisAeAddRead;
|
||||
ac->ev.delRead = redisAeDelRead;
|
||||
ac->ev.addWrite = redisAeAddWrite;
|
||||
ac->ev.delWrite = redisAeDelWrite;
|
||||
ac->ev.cleanup = redisAeCleanup;
|
||||
ac->ev.data = e;
|
||||
ac->evAddRead = redisAeAddRead;
|
||||
ac->evDelRead = redisAeDelRead;
|
||||
ac->evAddWrite = redisAeAddWrite;
|
||||
ac->evDelWrite = redisAeDelWrite;
|
||||
ac->evCleanup = redisAeCleanup;
|
||||
ac->_adapter_data = e;
|
||||
|
||||
return REDIS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Vendored
+15
-19
@@ -1,6 +1,3 @@
|
||||
#ifndef __HIREDIS_LIBEV_H__
|
||||
#define __HIREDIS_LIBEV_H__
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <ev.h>
|
||||
#include "../hiredis.h"
|
||||
@@ -13,7 +10,7 @@ typedef struct redisLibevEvents {
|
||||
ev_io rev, wev;
|
||||
} redisLibevEvents;
|
||||
|
||||
static void redisLibevReadEvent(EV_P_ ev_io *watcher, int revents) {
|
||||
void redisLibevReadEvent(EV_P_ ev_io *watcher, int revents) {
|
||||
#if EV_MULTIPLICITY
|
||||
((void)loop);
|
||||
#endif
|
||||
@@ -23,7 +20,7 @@ static void redisLibevReadEvent(EV_P_ ev_io *watcher, int revents) {
|
||||
redisAsyncHandleRead(e->context);
|
||||
}
|
||||
|
||||
static void redisLibevWriteEvent(EV_P_ ev_io *watcher, int revents) {
|
||||
void redisLibevWriteEvent(EV_P_ ev_io *watcher, int revents) {
|
||||
#if EV_MULTIPLICITY
|
||||
((void)loop);
|
||||
#endif
|
||||
@@ -33,7 +30,7 @@ static void redisLibevWriteEvent(EV_P_ ev_io *watcher, int revents) {
|
||||
redisAsyncHandleWrite(e->context);
|
||||
}
|
||||
|
||||
static void redisLibevAddRead(void *privdata) {
|
||||
void redisLibevAddRead(void *privdata) {
|
||||
redisLibevEvents *e = (redisLibevEvents*)privdata;
|
||||
struct ev_loop *loop = e->loop;
|
||||
((void)loop);
|
||||
@@ -43,7 +40,7 @@ static void redisLibevAddRead(void *privdata) {
|
||||
}
|
||||
}
|
||||
|
||||
static void redisLibevDelRead(void *privdata) {
|
||||
void redisLibevDelRead(void *privdata) {
|
||||
redisLibevEvents *e = (redisLibevEvents*)privdata;
|
||||
struct ev_loop *loop = e->loop;
|
||||
((void)loop);
|
||||
@@ -53,7 +50,7 @@ static void redisLibevDelRead(void *privdata) {
|
||||
}
|
||||
}
|
||||
|
||||
static void redisLibevAddWrite(void *privdata) {
|
||||
void redisLibevAddWrite(void *privdata) {
|
||||
redisLibevEvents *e = (redisLibevEvents*)privdata;
|
||||
struct ev_loop *loop = e->loop;
|
||||
((void)loop);
|
||||
@@ -63,7 +60,7 @@ static void redisLibevAddWrite(void *privdata) {
|
||||
}
|
||||
}
|
||||
|
||||
static void redisLibevDelWrite(void *privdata) {
|
||||
void redisLibevDelWrite(void *privdata) {
|
||||
redisLibevEvents *e = (redisLibevEvents*)privdata;
|
||||
struct ev_loop *loop = e->loop;
|
||||
((void)loop);
|
||||
@@ -73,19 +70,19 @@ static void redisLibevDelWrite(void *privdata) {
|
||||
}
|
||||
}
|
||||
|
||||
static void redisLibevCleanup(void *privdata) {
|
||||
void redisLibevCleanup(void *privdata) {
|
||||
redisLibevEvents *e = (redisLibevEvents*)privdata;
|
||||
redisLibevDelRead(privdata);
|
||||
redisLibevDelWrite(privdata);
|
||||
free(e);
|
||||
}
|
||||
|
||||
static int redisLibevAttach(EV_P_ redisAsyncContext *ac) {
|
||||
int redisLibevAttach(EV_P_ redisAsyncContext *ac) {
|
||||
redisContext *c = &(ac->c);
|
||||
redisLibevEvents *e;
|
||||
|
||||
/* Nothing should be attached when something is already attached */
|
||||
if (ac->ev.data != NULL)
|
||||
if (ac->_adapter_data != NULL)
|
||||
return REDIS_ERR;
|
||||
|
||||
/* Create container for context and r/w events */
|
||||
@@ -101,12 +98,12 @@ static int redisLibevAttach(EV_P_ redisAsyncContext *ac) {
|
||||
e->wev.data = e;
|
||||
|
||||
/* Register functions to start/stop listening for events */
|
||||
ac->ev.addRead = redisLibevAddRead;
|
||||
ac->ev.delRead = redisLibevDelRead;
|
||||
ac->ev.addWrite = redisLibevAddWrite;
|
||||
ac->ev.delWrite = redisLibevDelWrite;
|
||||
ac->ev.cleanup = redisLibevCleanup;
|
||||
ac->ev.data = e;
|
||||
ac->evAddRead = redisLibevAddRead;
|
||||
ac->evDelRead = redisLibevDelRead;
|
||||
ac->evAddWrite = redisLibevAddWrite;
|
||||
ac->evDelWrite = redisLibevDelWrite;
|
||||
ac->evCleanup = redisLibevCleanup;
|
||||
ac->_adapter_data = e;
|
||||
|
||||
/* Initialize read/write events */
|
||||
ev_io_init(&e->rev,redisLibevReadEvent,c->fd,EV_READ);
|
||||
@@ -114,4 +111,3 @@ static int redisLibevAttach(EV_P_ redisAsyncContext *ac) {
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
+16
-18
@@ -1,5 +1,4 @@
|
||||
#ifndef __HIREDIS_LIBEVENT_H__
|
||||
#define __HIREDIS_LIBEVENT_H__
|
||||
#include <sys/types.h>
|
||||
#include <event.h>
|
||||
#include "../hiredis.h"
|
||||
#include "../async.h"
|
||||
@@ -9,51 +8,51 @@ typedef struct redisLibeventEvents {
|
||||
struct event rev, wev;
|
||||
} redisLibeventEvents;
|
||||
|
||||
static void redisLibeventReadEvent(int fd, short event, void *arg) {
|
||||
void redisLibeventReadEvent(int fd, short event, void *arg) {
|
||||
((void)fd); ((void)event);
|
||||
redisLibeventEvents *e = (redisLibeventEvents*)arg;
|
||||
redisAsyncHandleRead(e->context);
|
||||
}
|
||||
|
||||
static void redisLibeventWriteEvent(int fd, short event, void *arg) {
|
||||
void redisLibeventWriteEvent(int fd, short event, void *arg) {
|
||||
((void)fd); ((void)event);
|
||||
redisLibeventEvents *e = (redisLibeventEvents*)arg;
|
||||
redisAsyncHandleWrite(e->context);
|
||||
}
|
||||
|
||||
static void redisLibeventAddRead(void *privdata) {
|
||||
void redisLibeventAddRead(void *privdata) {
|
||||
redisLibeventEvents *e = (redisLibeventEvents*)privdata;
|
||||
event_add(&e->rev,NULL);
|
||||
}
|
||||
|
||||
static void redisLibeventDelRead(void *privdata) {
|
||||
void redisLibeventDelRead(void *privdata) {
|
||||
redisLibeventEvents *e = (redisLibeventEvents*)privdata;
|
||||
event_del(&e->rev);
|
||||
}
|
||||
|
||||
static void redisLibeventAddWrite(void *privdata) {
|
||||
void redisLibeventAddWrite(void *privdata) {
|
||||
redisLibeventEvents *e = (redisLibeventEvents*)privdata;
|
||||
event_add(&e->wev,NULL);
|
||||
}
|
||||
|
||||
static void redisLibeventDelWrite(void *privdata) {
|
||||
void redisLibeventDelWrite(void *privdata) {
|
||||
redisLibeventEvents *e = (redisLibeventEvents*)privdata;
|
||||
event_del(&e->wev);
|
||||
}
|
||||
|
||||
static void redisLibeventCleanup(void *privdata) {
|
||||
void redisLibeventCleanup(void *privdata) {
|
||||
redisLibeventEvents *e = (redisLibeventEvents*)privdata;
|
||||
event_del(&e->rev);
|
||||
event_del(&e->wev);
|
||||
free(e);
|
||||
}
|
||||
|
||||
static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) {
|
||||
int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) {
|
||||
redisContext *c = &(ac->c);
|
||||
redisLibeventEvents *e;
|
||||
|
||||
/* Nothing should be attached when something is already attached */
|
||||
if (ac->ev.data != NULL)
|
||||
if (ac->_adapter_data != NULL)
|
||||
return REDIS_ERR;
|
||||
|
||||
/* Create container for context and r/w events */
|
||||
@@ -61,12 +60,12 @@ static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) {
|
||||
e->context = ac;
|
||||
|
||||
/* Register functions to start/stop listening for events */
|
||||
ac->ev.addRead = redisLibeventAddRead;
|
||||
ac->ev.delRead = redisLibeventDelRead;
|
||||
ac->ev.addWrite = redisLibeventAddWrite;
|
||||
ac->ev.delWrite = redisLibeventDelWrite;
|
||||
ac->ev.cleanup = redisLibeventCleanup;
|
||||
ac->ev.data = e;
|
||||
ac->evAddRead = redisLibeventAddRead;
|
||||
ac->evDelRead = redisLibeventDelRead;
|
||||
ac->evAddWrite = redisLibeventAddWrite;
|
||||
ac->evDelWrite = redisLibeventDelWrite;
|
||||
ac->evCleanup = redisLibeventCleanup;
|
||||
ac->_adapter_data = e;
|
||||
|
||||
/* Initialize and install read/write events */
|
||||
event_set(&e->rev,c->fd,EV_READ,redisLibeventReadEvent,e);
|
||||
@@ -75,4 +74,3 @@ static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) {
|
||||
event_base_set(base,&e->wev);
|
||||
return REDIS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
Vendored
+28
-87
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
* Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -29,33 +29,14 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "fmacros.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include "async.h"
|
||||
#include "net.h"
|
||||
#include "dict.c"
|
||||
#include "sds.h"
|
||||
|
||||
#define _EL_ADD_READ(ctx) do { \
|
||||
if ((ctx)->ev.addRead) (ctx)->ev.addRead((ctx)->ev.data); \
|
||||
} while(0)
|
||||
#define _EL_DEL_READ(ctx) do { \
|
||||
if ((ctx)->ev.delRead) (ctx)->ev.delRead((ctx)->ev.data); \
|
||||
} while(0)
|
||||
#define _EL_ADD_WRITE(ctx) do { \
|
||||
if ((ctx)->ev.addWrite) (ctx)->ev.addWrite((ctx)->ev.data); \
|
||||
} while(0)
|
||||
#define _EL_DEL_WRITE(ctx) do { \
|
||||
if ((ctx)->ev.delWrite) (ctx)->ev.delWrite((ctx)->ev.data); \
|
||||
} while(0)
|
||||
#define _EL_CLEANUP(ctx) do { \
|
||||
if ((ctx)->ev.cleanup) (ctx)->ev.cleanup((ctx)->ev.data); \
|
||||
} while(0);
|
||||
#include "util.h"
|
||||
|
||||
/* Forward declaration of function in hiredis.c */
|
||||
void __redisAppendCommand(redisContext *c, char *cmd, size_t len);
|
||||
@@ -155,6 +136,11 @@ redisAsyncContext *redisAsyncConnectUnix(const char *path) {
|
||||
return ac;
|
||||
}
|
||||
|
||||
int redisAsyncSetReplyObjectFunctions(redisAsyncContext *ac, redisReplyObjectFunctions *fn) {
|
||||
redisContext *c = &(ac->c);
|
||||
return redisSetReplyObjectFunctions(c,fn);
|
||||
}
|
||||
|
||||
int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn) {
|
||||
if (ac->onConnect == NULL) {
|
||||
ac->onConnect = fn;
|
||||
@@ -162,7 +148,7 @@ int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn
|
||||
/* The common way to detect an established connection is to wait for
|
||||
* the first write event to be fired. This assumes the related event
|
||||
* library functions are already set. */
|
||||
_EL_ADD_WRITE(ac);
|
||||
if (ac->ev.addWrite) ac->ev.addWrite(ac->ev.data);
|
||||
return REDIS_OK;
|
||||
}
|
||||
return REDIS_ERR;
|
||||
@@ -182,6 +168,7 @@ static int __redisPushCallback(redisCallbackList *list, redisCallback *source) {
|
||||
|
||||
/* Copy callback from stack to heap */
|
||||
cb = malloc(sizeof(*cb));
|
||||
if (!cb) redisOOM();
|
||||
if (source != NULL) {
|
||||
memcpy(cb,source,sizeof(*cb));
|
||||
cb->next = NULL;
|
||||
@@ -250,7 +237,7 @@ static void __redisAsyncFree(redisAsyncContext *ac) {
|
||||
dictRelease(ac->sub.patterns);
|
||||
|
||||
/* Signal event lib to clean up */
|
||||
_EL_CLEANUP(ac);
|
||||
if (ac->ev.cleanup) ac->ev.cleanup(ac->ev.data);
|
||||
|
||||
/* Execute disconnect callback. When redisAsyncFree() initiated destroying
|
||||
* this context, the status will always be REDIS_OK. */
|
||||
@@ -381,27 +368,14 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
|
||||
/* Even if the context is subscribed, pending regular callbacks will
|
||||
* get a reply before pub/sub messages arrive. */
|
||||
if (__redisShiftCallback(&ac->replies,&cb) != REDIS_OK) {
|
||||
/* A spontaneous reply in a not-subscribed context can only be the
|
||||
* error reply that is sent when a new connection exceeds the
|
||||
* maximum number of allowed connections on the server side. This
|
||||
* is seen as an error instead of a regular reply because the
|
||||
* server closes the connection after sending it. To prevent the
|
||||
* error from being overwritten by an EOF error the connection is
|
||||
* closed here. See issue #43. */
|
||||
if ( !(c->flags & REDIS_SUBSCRIBED) && ((redisReply*)reply)->type == REDIS_REPLY_ERROR ) {
|
||||
c->err = REDIS_ERR_OTHER;
|
||||
snprintf(c->errstr,sizeof(c->errstr),"%s",((redisReply*)reply)->str);
|
||||
__redisAsyncDisconnect(ac);
|
||||
return;
|
||||
}
|
||||
/* No more regular callbacks and no errors, the context *must* be subscribed. */
|
||||
/* No more regular callbacks, the context *must* be subscribed. */
|
||||
assert(c->flags & REDIS_SUBSCRIBED);
|
||||
__redisGetSubscribeCallback(ac,reply,&cb);
|
||||
}
|
||||
|
||||
if (cb.fn != NULL) {
|
||||
__redisRunCallback(ac,&cb,reply);
|
||||
c->reader->fn->freeObject(reply);
|
||||
c->fn->freeObject(reply);
|
||||
|
||||
/* Proceed with free'ing when redisAsyncFree() was called. */
|
||||
if (c->flags & REDIS_FREEING) {
|
||||
@@ -413,7 +387,7 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
|
||||
* or there were no callbacks to begin with. Either way, don't
|
||||
* abort with an error, but simply ignore it because the client
|
||||
* doesn't know what the server will spit out over the wire. */
|
||||
c->reader->fn->freeObject(reply);
|
||||
c->fn->freeObject(reply);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,48 +396,17 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
|
||||
__redisAsyncDisconnect(ac);
|
||||
}
|
||||
|
||||
/* Internal helper function to detect socket status the first time a read or
|
||||
* write event fires. When connecting was not succesful, the connect callback
|
||||
* is called with a REDIS_ERR status and the context is free'd. */
|
||||
static int __redisAsyncHandleConnect(redisAsyncContext *ac) {
|
||||
redisContext *c = &(ac->c);
|
||||
|
||||
if (redisCheckSocketError(c,c->fd) == REDIS_ERR) {
|
||||
/* Try again later when connect(2) is still in progress. */
|
||||
if (errno == EINPROGRESS)
|
||||
return REDIS_OK;
|
||||
|
||||
if (ac->onConnect) ac->onConnect(ac,REDIS_ERR);
|
||||
__redisAsyncDisconnect(ac);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
/* Mark context as connected. */
|
||||
c->flags |= REDIS_CONNECTED;
|
||||
if (ac->onConnect) ac->onConnect(ac,REDIS_OK);
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
/* This function should be called when the socket is readable.
|
||||
* It processes all replies that can be read and executes their callbacks.
|
||||
*/
|
||||
void redisAsyncHandleRead(redisAsyncContext *ac) {
|
||||
redisContext *c = &(ac->c);
|
||||
|
||||
if (!(c->flags & REDIS_CONNECTED)) {
|
||||
/* Abort connect was not successful. */
|
||||
if (__redisAsyncHandleConnect(ac) != REDIS_OK)
|
||||
return;
|
||||
/* Try again later when the context is still not connected. */
|
||||
if (!(c->flags & REDIS_CONNECTED))
|
||||
return;
|
||||
}
|
||||
|
||||
if (redisBufferRead(c) == REDIS_ERR) {
|
||||
__redisAsyncDisconnect(ac);
|
||||
} else {
|
||||
/* Always re-schedule reads */
|
||||
_EL_ADD_READ(ac);
|
||||
if (ac->ev.addRead) ac->ev.addRead(ac->ev.data);
|
||||
redisProcessCallbacks(ac);
|
||||
}
|
||||
}
|
||||
@@ -472,26 +415,24 @@ void redisAsyncHandleWrite(redisAsyncContext *ac) {
|
||||
redisContext *c = &(ac->c);
|
||||
int done = 0;
|
||||
|
||||
if (!(c->flags & REDIS_CONNECTED)) {
|
||||
/* Abort connect was not successful. */
|
||||
if (__redisAsyncHandleConnect(ac) != REDIS_OK)
|
||||
return;
|
||||
/* Try again later when the context is still not connected. */
|
||||
if (!(c->flags & REDIS_CONNECTED))
|
||||
return;
|
||||
}
|
||||
|
||||
if (redisBufferWrite(c,&done) == REDIS_ERR) {
|
||||
__redisAsyncDisconnect(ac);
|
||||
} else {
|
||||
/* Continue writing when not done, stop writing otherwise */
|
||||
if (!done)
|
||||
_EL_ADD_WRITE(ac);
|
||||
else
|
||||
_EL_DEL_WRITE(ac);
|
||||
if (!done) {
|
||||
if (ac->ev.addWrite) ac->ev.addWrite(ac->ev.data);
|
||||
} else {
|
||||
if (ac->ev.delWrite) ac->ev.delWrite(ac->ev.data);
|
||||
}
|
||||
|
||||
/* Always schedule reads after writes */
|
||||
_EL_ADD_READ(ac);
|
||||
if (ac->ev.addRead) ac->ev.addRead(ac->ev.data);
|
||||
|
||||
/* Fire onConnect when this is the first write event. */
|
||||
if (!(c->flags & REDIS_CONNECTED)) {
|
||||
c->flags |= REDIS_CONNECTED;
|
||||
if (ac->onConnect) ac->onConnect(ac);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,7 +510,7 @@ static int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void
|
||||
__redisAppendCommand(c,cmd,len);
|
||||
|
||||
/* Always schedule a write when the write buffer is non-empty */
|
||||
_EL_ADD_WRITE(ac);
|
||||
if (ac->ev.addWrite) ac->ev.addWrite(ac->ev.data);
|
||||
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
Vendored
+4
-3
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
* Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -55,7 +55,7 @@ typedef struct redisCallbackList {
|
||||
|
||||
/* Connection callback prototypes */
|
||||
typedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status);
|
||||
typedef void (redisConnectCallback)(const struct redisAsyncContext*, int status);
|
||||
typedef void (redisConnectCallback)(const struct redisAsyncContext*);
|
||||
|
||||
/* Context for an async connection to Redis */
|
||||
typedef struct redisAsyncContext {
|
||||
@@ -103,6 +103,7 @@ typedef struct redisAsyncContext {
|
||||
/* Functions that proxy to hiredis */
|
||||
redisAsyncContext *redisAsyncConnect(const char *ip, int port);
|
||||
redisAsyncContext *redisAsyncConnectUnix(const char *path);
|
||||
int redisAsyncSetReplyObjectFunctions(redisAsyncContext *ac, redisReplyObjectFunctions *fn);
|
||||
int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn);
|
||||
int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);
|
||||
void redisAsyncDisconnect(redisAsyncContext *ac);
|
||||
|
||||
Vendored
+5
-8
@@ -18,20 +18,17 @@ void getCallback(redisAsyncContext *c, void *r, void *privdata) {
|
||||
redisAsyncDisconnect(c);
|
||||
}
|
||||
|
||||
void connectCallback(const redisAsyncContext *c, int status) {
|
||||
if (status != REDIS_OK) {
|
||||
printf("Error: %s\n", c->errstr);
|
||||
return;
|
||||
}
|
||||
printf("Connected...\n");
|
||||
void connectCallback(const redisAsyncContext *c) {
|
||||
((void)c);
|
||||
printf("connected...\n");
|
||||
}
|
||||
|
||||
void disconnectCallback(const redisAsyncContext *c, int status) {
|
||||
if (status != REDIS_OK) {
|
||||
printf("Error: %s\n", c->errstr);
|
||||
return;
|
||||
}
|
||||
printf("Disconnected...\n");
|
||||
printf("disconnected...\n");
|
||||
aeStop(loop);
|
||||
}
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
|
||||
Vendored
+4
-8
@@ -15,20 +15,16 @@ void getCallback(redisAsyncContext *c, void *r, void *privdata) {
|
||||
redisAsyncDisconnect(c);
|
||||
}
|
||||
|
||||
void connectCallback(const redisAsyncContext *c, int status) {
|
||||
if (status != REDIS_OK) {
|
||||
printf("Error: %s\n", c->errstr);
|
||||
return;
|
||||
}
|
||||
printf("Connected...\n");
|
||||
void connectCallback(const redisAsyncContext *c) {
|
||||
((void)c);
|
||||
printf("connected...\n");
|
||||
}
|
||||
|
||||
void disconnectCallback(const redisAsyncContext *c, int status) {
|
||||
if (status != REDIS_OK) {
|
||||
printf("Error: %s\n", c->errstr);
|
||||
return;
|
||||
}
|
||||
printf("Disconnected...\n");
|
||||
printf("disconnected...\n");
|
||||
}
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
|
||||
Vendored
+4
-8
@@ -15,20 +15,16 @@ void getCallback(redisAsyncContext *c, void *r, void *privdata) {
|
||||
redisAsyncDisconnect(c);
|
||||
}
|
||||
|
||||
void connectCallback(const redisAsyncContext *c, int status) {
|
||||
if (status != REDIS_OK) {
|
||||
printf("Error: %s\n", c->errstr);
|
||||
return;
|
||||
}
|
||||
printf("Connected...\n");
|
||||
void connectCallback(const redisAsyncContext *c) {
|
||||
((void)c);
|
||||
printf("connected...\n");
|
||||
}
|
||||
|
||||
void disconnectCallback(const redisAsyncContext *c, int status) {
|
||||
if (status != REDIS_OK) {
|
||||
printf("Error: %s\n", c->errstr);
|
||||
return;
|
||||
}
|
||||
printf("Disconnected...\n");
|
||||
printf("disconnected...\n");
|
||||
}
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
|
||||
Vendored
+3
-5
@@ -1,14 +1,12 @@
|
||||
#ifndef __HIREDIS_FMACRO_H
|
||||
#define __HIREDIS_FMACRO_H
|
||||
|
||||
#if !defined(_BSD_SOURCE)
|
||||
#ifndef _BSD_SOURCE
|
||||
#define _BSD_SOURCE
|
||||
#endif
|
||||
|
||||
#if defined(__sun__)
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#elif defined(__linux__)
|
||||
#define _XOPEN_SOURCE 600
|
||||
#ifdef __linux__
|
||||
#define _XOPEN_SOURCE 700
|
||||
#else
|
||||
#define _XOPEN_SOURCE
|
||||
#endif
|
||||
|
||||
Vendored
+251
-454
File diff suppressed because it is too large
Load Diff
Vendored
+31
-51
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
* Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -36,8 +36,8 @@
|
||||
#include <sys/time.h> /* for struct timeval */
|
||||
|
||||
#define HIREDIS_MAJOR 0
|
||||
#define HIREDIS_MINOR 10
|
||||
#define HIREDIS_PATCH 1
|
||||
#define HIREDIS_MINOR 9
|
||||
#define HIREDIS_PATCH 2
|
||||
|
||||
#define REDIS_ERR -1
|
||||
#define REDIS_OK 0
|
||||
@@ -46,11 +46,10 @@
|
||||
* error that occured. REDIS_ERR_IO means there was an I/O error and you
|
||||
* should use the "errno" variable to find out what is wrong.
|
||||
* For other values, the "errstr" field will hold a description. */
|
||||
#define REDIS_ERR_IO 1 /* Error in read or write */
|
||||
#define REDIS_ERR_EOF 3 /* End of file */
|
||||
#define REDIS_ERR_PROTOCOL 4 /* Protocol error */
|
||||
#define REDIS_ERR_OOM 5 /* Out of memory */
|
||||
#define REDIS_ERR_OTHER 2 /* Everything else... */
|
||||
#define REDIS_ERR_IO 1 /* error in read or write */
|
||||
#define REDIS_ERR_EOF 3 /* eof */
|
||||
#define REDIS_ERR_PROTOCOL 4 /* protocol error */
|
||||
#define REDIS_ERR_OTHER 2 /* something else */
|
||||
|
||||
/* Connection type can be blocking or non-blocking and is set in the
|
||||
* least significant bit of the flags field in redisContext. */
|
||||
@@ -114,56 +113,36 @@ typedef struct redisReplyObjectFunctions {
|
||||
void (*freeObject)(void*);
|
||||
} redisReplyObjectFunctions;
|
||||
|
||||
/* State for the protocol parser */
|
||||
typedef struct redisReader {
|
||||
struct redisContext; /* need forward declaration of redisContext */
|
||||
|
||||
/* Context for a connection to Redis */
|
||||
typedef struct redisContext {
|
||||
int fd;
|
||||
int flags;
|
||||
char *obuf; /* Write buffer */
|
||||
int err; /* Error flags, 0 when there is no error */
|
||||
char errstr[128]; /* String representation of error when applicable */
|
||||
|
||||
char *buf; /* Read buffer */
|
||||
size_t pos; /* Buffer cursor */
|
||||
size_t len; /* Buffer length */
|
||||
|
||||
redisReadTask rstack[9];
|
||||
int ridx; /* Index of current read task */
|
||||
void *reply; /* Temporary reply pointer */
|
||||
char *errstr; /* String representation of error when applicable */
|
||||
|
||||
/* Function set for reply buildup and reply reader */
|
||||
redisReplyObjectFunctions *fn;
|
||||
void *privdata;
|
||||
} redisReader;
|
||||
void *reader;
|
||||
} redisContext;
|
||||
|
||||
/* Public API for the protocol parser. */
|
||||
redisReader *redisReaderCreate(void);
|
||||
void redisReaderFree(redisReader *r);
|
||||
int redisReaderFeed(redisReader *r, const char *buf, size_t len);
|
||||
int redisReaderGetReply(redisReader *r, void **reply);
|
||||
|
||||
/* Backwards compatibility, can be removed on big version bump. */
|
||||
#define redisReplyReaderCreate redisReaderCreate
|
||||
#define redisReplyReaderFree redisReaderFree
|
||||
#define redisReplyReaderFeed redisReaderFeed
|
||||
#define redisReplyReaderGetReply redisReaderGetReply
|
||||
#define redisReplyReaderSetPrivdata(_r, _p) (int)(((redisReader*)(_r))->privdata = (_p))
|
||||
#define redisReplyReaderGetObject(_r) (((redisReader*)(_r))->reply)
|
||||
#define redisReplyReaderGetError(_r) (((redisReader*)(_r))->errstr)
|
||||
|
||||
/* Function to free the reply objects hiredis returns by default. */
|
||||
void freeReplyObject(void *reply);
|
||||
void *redisReplyReaderCreate(void);
|
||||
int redisReplyReaderSetReplyObjectFunctions(void *reader, redisReplyObjectFunctions *fn);
|
||||
int redisReplyReaderSetPrivdata(void *reader, void *privdata);
|
||||
void *redisReplyReaderGetObject(void *reader);
|
||||
char *redisReplyReaderGetError(void *reader);
|
||||
void redisReplyReaderFree(void *ptr);
|
||||
void redisReplyReaderFeed(void *reader, const char *buf, size_t len);
|
||||
int redisReplyReaderGetReply(void *reader, void **reply);
|
||||
|
||||
/* Functions to format a command according to the protocol. */
|
||||
int redisvFormatCommand(char **target, const char *format, va_list ap);
|
||||
int redisFormatCommand(char **target, const char *format, ...);
|
||||
int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen);
|
||||
|
||||
/* Context for a connection to Redis */
|
||||
typedef struct redisContext {
|
||||
int err; /* Error flags, 0 when there is no error */
|
||||
char errstr[128]; /* String representation of error when applicable */
|
||||
int fd;
|
||||
int flags;
|
||||
char *obuf; /* Write buffer */
|
||||
redisReader *reader; /* Protocol reader */
|
||||
} redisContext;
|
||||
|
||||
redisContext *redisConnect(const char *ip, int port);
|
||||
redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv);
|
||||
redisContext *redisConnectNonBlock(const char *ip, int port);
|
||||
@@ -171,6 +150,7 @@ redisContext *redisConnectUnix(const char *path);
|
||||
redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv);
|
||||
redisContext *redisConnectUnixNonBlock(const char *path);
|
||||
int redisSetTimeout(redisContext *c, struct timeval tv);
|
||||
int redisSetReplyObjectFunctions(redisContext *c, redisReplyObjectFunctions *fn);
|
||||
void redisFree(redisContext *c);
|
||||
int redisBufferRead(redisContext *c);
|
||||
int redisBufferWrite(redisContext *c, int *done);
|
||||
@@ -184,9 +164,9 @@ int redisGetReplyFromReader(redisContext *c, void **reply);
|
||||
|
||||
/* Write a command to the output buffer. Use these functions in blocking mode
|
||||
* to get a pipeline of commands. */
|
||||
int redisvAppendCommand(redisContext *c, const char *format, va_list ap);
|
||||
int redisAppendCommand(redisContext *c, const char *format, ...);
|
||||
int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
|
||||
void redisvAppendCommand(redisContext *c, const char *format, va_list ap);
|
||||
void redisAppendCommand(redisContext *c, const char *format, ...);
|
||||
void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
|
||||
|
||||
/* Issue a command to Redis. In a blocking context, it is identical to calling
|
||||
* redisAppendCommand, followed by redisGetReply. The function will return
|
||||
|
||||
Vendored
+75
-102
@@ -1,7 +1,7 @@
|
||||
/* Extracted from anet.c to work properly with Hiredis error reporting.
|
||||
*
|
||||
* Copyright (c) 2006-2011, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
* Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -49,37 +49,19 @@
|
||||
#include "net.h"
|
||||
#include "sds.h"
|
||||
|
||||
/* Defined in hiredis.c */
|
||||
void __redisSetError(redisContext *c, int type, const char *str);
|
||||
|
||||
static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) {
|
||||
char buf[128];
|
||||
size_t len = 0;
|
||||
|
||||
if (prefix != NULL)
|
||||
len = snprintf(buf,sizeof(buf),"%s: ",prefix);
|
||||
strerror_r(errno,buf+len,sizeof(buf)-len);
|
||||
__redisSetError(c,type,buf);
|
||||
}
|
||||
|
||||
static int redisSetReuseAddr(redisContext *c, int fd) {
|
||||
int on = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
close(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
return REDIS_OK;
|
||||
}
|
||||
/* Forward declaration */
|
||||
void __redisSetError(redisContext *c, int type, sds err);
|
||||
|
||||
static int redisCreateSocket(redisContext *c, int type) {
|
||||
int s;
|
||||
int s, on = 1;
|
||||
if ((s = socket(type, SOCK_STREAM, 0)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
__redisSetError(c,REDIS_ERR_IO,NULL);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
if (type == AF_INET) {
|
||||
if (redisSetReuseAddr(c,s) == REDIS_ERR) {
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
|
||||
__redisSetError(c,REDIS_ERR_IO,NULL);
|
||||
close(s);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
}
|
||||
@@ -93,7 +75,8 @@ static int redisSetBlocking(redisContext *c, int fd, int blocking) {
|
||||
* Note that fcntl(2) for F_GETFL and F_SETFL can't be
|
||||
* interrupted by a signal. */
|
||||
if ((flags = fcntl(fd, F_GETFL)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)");
|
||||
__redisSetError(c,REDIS_ERR_IO,
|
||||
sdscatprintf(sdsempty(), "fcntl(F_GETFL): %s", strerror(errno)));
|
||||
close(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
@@ -104,7 +87,8 @@ static int redisSetBlocking(redisContext *c, int fd, int blocking) {
|
||||
flags |= O_NONBLOCK;
|
||||
|
||||
if (fcntl(fd, F_SETFL, flags) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_SETFL)");
|
||||
__redisSetError(c,REDIS_ERR_IO,
|
||||
sdscatprintf(sdsempty(), "fcntl(F_SETFL): %s", strerror(errno)));
|
||||
close(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
@@ -114,7 +98,8 @@ static int redisSetBlocking(redisContext *c, int fd, int blocking) {
|
||||
static int redisSetTcpNoDelay(redisContext *c, int fd) {
|
||||
int yes = 1;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_NODELAY)");
|
||||
__redisSetError(c,REDIS_ERR_IO,
|
||||
sdscatprintf(sdsempty(), "setsockopt(TCP_NODELAY): %s", strerror(errno)));
|
||||
close(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
@@ -125,6 +110,8 @@ static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *
|
||||
struct timeval to;
|
||||
struct timeval *toptr = NULL;
|
||||
fd_set wfd;
|
||||
int err;
|
||||
socklen_t errlen;
|
||||
|
||||
/* Only use timeout when not NULL. */
|
||||
if (timeout != NULL) {
|
||||
@@ -137,115 +124,101 @@ static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *
|
||||
FD_SET(fd, &wfd);
|
||||
|
||||
if (select(FD_SETSIZE, NULL, &wfd, NULL, toptr) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"select(2)");
|
||||
__redisSetError(c,REDIS_ERR_IO,
|
||||
sdscatprintf(sdsempty(), "select(2): %s", strerror(errno)));
|
||||
close(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
if (!FD_ISSET(fd, &wfd)) {
|
||||
errno = ETIMEDOUT;
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
__redisSetError(c,REDIS_ERR_IO,NULL);
|
||||
close(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
if (redisCheckSocketError(c, fd) != REDIS_OK)
|
||||
err = 0;
|
||||
errlen = sizeof(err);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
|
||||
__redisSetError(c,REDIS_ERR_IO,
|
||||
sdscatprintf(sdsempty(), "getsockopt(SO_ERROR): %s", strerror(errno)));
|
||||
close(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
errno = err;
|
||||
__redisSetError(c,REDIS_ERR_IO,NULL);
|
||||
close(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
__redisSetError(c,REDIS_ERR_IO,NULL);
|
||||
close(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
int redisCheckSocketError(redisContext *c, int fd) {
|
||||
int err = 0;
|
||||
socklen_t errlen = sizeof(err);
|
||||
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"getsockopt(SO_ERROR)");
|
||||
close(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
errno = err;
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
close(fd);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
int redisContextSetTimeout(redisContext *c, struct timeval tv) {
|
||||
if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)");
|
||||
__redisSetError(c,REDIS_ERR_IO,
|
||||
sdscatprintf(sdsempty(), "setsockopt(SO_RCVTIMEO): %s", strerror(errno)));
|
||||
return REDIS_ERR;
|
||||
}
|
||||
if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_SNDTIMEO)");
|
||||
__redisSetError(c,REDIS_ERR_IO,
|
||||
sdscatprintf(sdsempty(), "setsockopt(SO_SNDTIMEO): %s", strerror(errno)));
|
||||
return REDIS_ERR;
|
||||
}
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout) {
|
||||
int s, rv;
|
||||
char _port[6]; /* strlen("65535"); */
|
||||
struct addrinfo hints, *servinfo, *p;
|
||||
int s;
|
||||
int blocking = (c->flags & REDIS_BLOCK);
|
||||
struct sockaddr_in sa;
|
||||
|
||||
snprintf(_port, 6, "%d", port);
|
||||
memset(&hints,0,sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {
|
||||
__redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv));
|
||||
if ((s = redisCreateSocket(c,AF_INET)) < 0)
|
||||
return REDIS_ERR;
|
||||
if (redisSetBlocking(c,s,0) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
}
|
||||
for (p = servinfo; p != NULL; p = p->ai_next) {
|
||||
if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)
|
||||
continue;
|
||||
|
||||
if (redisSetBlocking(c,s,0) != REDIS_OK)
|
||||
goto error;
|
||||
if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {
|
||||
if (errno == EHOSTUNREACH) {
|
||||
close(s);
|
||||
continue;
|
||||
} else if (errno == EINPROGRESS && !blocking) {
|
||||
/* This is ok. */
|
||||
} else {
|
||||
if (redisContextWaitReady(c,s,timeout) != REDIS_OK)
|
||||
goto error;
|
||||
}
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(port);
|
||||
if (inet_aton(addr, &sa.sin_addr) == 0) {
|
||||
struct hostent *he;
|
||||
|
||||
he = gethostbyname(addr);
|
||||
if (he == NULL) {
|
||||
__redisSetError(c,REDIS_ERR_OTHER,
|
||||
sdscatprintf(sdsempty(),"Can't resolve: %s",addr));
|
||||
close(s);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
if (blocking && redisSetBlocking(c,s,1) != REDIS_OK)
|
||||
goto error;
|
||||
if (redisSetTcpNoDelay(c,s) != REDIS_OK)
|
||||
goto error;
|
||||
|
||||
c->fd = s;
|
||||
c->flags |= REDIS_CONNECTED;
|
||||
rv = REDIS_OK;
|
||||
goto end;
|
||||
}
|
||||
if (p == NULL) {
|
||||
char buf[128];
|
||||
snprintf(buf,sizeof(buf),"Can't create socket: %s",strerror(errno));
|
||||
__redisSetError(c,REDIS_ERR_OTHER,buf);
|
||||
goto error;
|
||||
memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr));
|
||||
}
|
||||
|
||||
error:
|
||||
rv = REDIS_ERR;
|
||||
end:
|
||||
freeaddrinfo(servinfo);
|
||||
return rv; // Need to return REDIS_OK if alright
|
||||
if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
|
||||
if (errno == EINPROGRESS && !blocking) {
|
||||
/* This is ok. */
|
||||
} else {
|
||||
if (redisContextWaitReady(c,s,timeout) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset socket to be blocking after connect(2). */
|
||||
if (blocking && redisSetBlocking(c,s,1) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
|
||||
if (redisSetTcpNoDelay(c,s) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
|
||||
c->fd = s;
|
||||
c->flags |= REDIS_CONNECTED;
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout) {
|
||||
|
||||
Vendored
+2
-3
@@ -1,7 +1,7 @@
|
||||
/* Extracted from anet.c to work properly with Hiredis error reporting.
|
||||
*
|
||||
* Copyright (c) 2006-2011, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
* Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -39,7 +39,6 @@
|
||||
#define AF_LOCAL AF_UNIX
|
||||
#endif
|
||||
|
||||
int redisCheckSocketError(redisContext *c, int fd);
|
||||
int redisContextSetTimeout(redisContext *c, struct timeval tv);
|
||||
int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout);
|
||||
int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout);
|
||||
|
||||
Vendored
+12
-23
@@ -28,18 +28,18 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define SDS_ABORT_ON_OOM
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "sds.h"
|
||||
|
||||
#ifdef SDS_ABORT_ON_OOM
|
||||
static void sdsOomAbort(void) {
|
||||
fprintf(stderr,"SDS: Out Of Memory (SDS_ABORT_ON_OOM defined)\n");
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
sds sdsnewlen(const void *init, size_t initlen) {
|
||||
struct sdshdr *sh;
|
||||
@@ -378,19 +378,17 @@ sds sdsfromlonglong(long long value) {
|
||||
|
||||
sds sdscatrepr(sds s, char *p, size_t len) {
|
||||
s = sdscatlen(s,"\"",1);
|
||||
if (s == NULL) return NULL;
|
||||
|
||||
while(len--) {
|
||||
switch(*p) {
|
||||
case '\\':
|
||||
case '"':
|
||||
s = sdscatprintf(s,"\\%c",*p);
|
||||
break;
|
||||
case '\n': s = sdscatlen(s,"\\n",2); break;
|
||||
case '\r': s = sdscatlen(s,"\\r",2); break;
|
||||
case '\t': s = sdscatlen(s,"\\t",2); break;
|
||||
case '\a': s = sdscatlen(s,"\\a",2); break;
|
||||
case '\b': s = sdscatlen(s,"\\b",2); break;
|
||||
case '\n': s = sdscatlen(s,"\\n",1); break;
|
||||
case '\r': s = sdscatlen(s,"\\r",1); break;
|
||||
case '\t': s = sdscatlen(s,"\\t",1); break;
|
||||
case '\a': s = sdscatlen(s,"\\a",1); break;
|
||||
case '\b': s = sdscatlen(s,"\\b",1); break;
|
||||
default:
|
||||
if (isprint(*p))
|
||||
s = sdscatprintf(s,"%c",*p);
|
||||
@@ -399,7 +397,6 @@ sds sdscatrepr(sds s, char *p, size_t len) {
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
if (s == NULL) return NULL;
|
||||
}
|
||||
return sdscatlen(s,"\"",1);
|
||||
}
|
||||
@@ -419,7 +416,7 @@ sds sdscatrepr(sds s, char *p, size_t len) {
|
||||
sds *sdssplitargs(char *line, int *argc) {
|
||||
char *p = line;
|
||||
char *current = NULL;
|
||||
char **vector = NULL, **_vector = NULL;
|
||||
char **vector = NULL;
|
||||
|
||||
*argc = 0;
|
||||
while(1) {
|
||||
@@ -430,11 +427,7 @@ sds *sdssplitargs(char *line, int *argc) {
|
||||
int inq=0; /* set to 1 if we are in "quotes" */
|
||||
int done=0;
|
||||
|
||||
if (current == NULL) {
|
||||
current = sdsempty();
|
||||
if (current == NULL) goto err;
|
||||
}
|
||||
|
||||
if (current == NULL) current = sdsempty();
|
||||
while(!done) {
|
||||
if (inq) {
|
||||
if (*p == '\\' && *(p+1)) {
|
||||
@@ -478,13 +471,9 @@ sds *sdssplitargs(char *line, int *argc) {
|
||||
}
|
||||
}
|
||||
if (*p) p++;
|
||||
if (current == NULL) goto err;
|
||||
}
|
||||
/* add the token to the vector */
|
||||
_vector = realloc(vector,((*argc)+1)*sizeof(char*));
|
||||
if (_vector == NULL) goto err;
|
||||
|
||||
vector = _vector;
|
||||
vector = realloc(vector,((*argc)+1)*sizeof(char*));
|
||||
vector[*argc] = current;
|
||||
(*argc)++;
|
||||
current = NULL;
|
||||
@@ -496,8 +485,8 @@ sds *sdssplitargs(char *line, int *argc) {
|
||||
err:
|
||||
while((*argc)--)
|
||||
sdsfree(vector[*argc]);
|
||||
if (vector != NULL) free(vector);
|
||||
if (current != NULL) sdsfree(current);
|
||||
free(vector);
|
||||
if (current) sdsfree(current);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+146
-268
@@ -1,4 +1,3 @@
|
||||
#include "fmacros.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -11,28 +10,10 @@
|
||||
|
||||
#include "hiredis.h"
|
||||
|
||||
enum connection_type {
|
||||
CONN_TCP,
|
||||
CONN_UNIX
|
||||
};
|
||||
|
||||
struct config {
|
||||
enum connection_type type;
|
||||
|
||||
struct {
|
||||
const char *host;
|
||||
int port;
|
||||
} tcp;
|
||||
|
||||
struct {
|
||||
const char *path;
|
||||
} unix;
|
||||
};
|
||||
|
||||
/* The following lines make up our testing "framework" :) */
|
||||
static int tests = 0, fails = 0;
|
||||
#define test(_s) { printf("#%02d ", ++tests); printf(_s); }
|
||||
#define test_cond(_c) if(_c) printf("\033[0;32mPASSED\033[0;0m\n"); else {printf("\033[0;31mFAILED\033[0;0m\n"); fails++;}
|
||||
#define test_cond(_c) if(_c) printf("PASSED\n"); else {printf("FAILED\n"); fails++;}
|
||||
|
||||
static long long usec(void) {
|
||||
struct timeval tv;
|
||||
@@ -40,60 +21,15 @@ static long long usec(void) {
|
||||
return (((long long)tv.tv_sec)*1000000)+tv.tv_usec;
|
||||
}
|
||||
|
||||
static redisContext *select_database(redisContext *c) {
|
||||
redisReply *reply;
|
||||
|
||||
/* Switch to DB 9 for testing, now that we know we can chat. */
|
||||
reply = redisCommand(c,"SELECT 9");
|
||||
assert(reply != NULL);
|
||||
freeReplyObject(reply);
|
||||
|
||||
/* Make sure the DB is emtpy */
|
||||
reply = redisCommand(c,"DBSIZE");
|
||||
assert(reply != NULL);
|
||||
if (reply->type == REDIS_REPLY_INTEGER && reply->integer == 0) {
|
||||
/* Awesome, DB 9 is empty and we can continue. */
|
||||
freeReplyObject(reply);
|
||||
} else {
|
||||
printf("Database #9 is not empty, test can not continue\n");
|
||||
static int use_unix = 0;
|
||||
static redisContext *blocking_context = NULL;
|
||||
static void __connect(redisContext **target) {
|
||||
*target = blocking_context = (use_unix ?
|
||||
redisConnectUnix("/tmp/redis.sock") : redisConnect((char*)"127.0.0.1", 6379));
|
||||
if (blocking_context->err) {
|
||||
printf("Connection error: %s\n", blocking_context->errstr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static void disconnect(redisContext *c) {
|
||||
redisReply *reply;
|
||||
|
||||
/* Make sure we're on DB 9. */
|
||||
reply = redisCommand(c,"SELECT 9");
|
||||
assert(reply != NULL);
|
||||
freeReplyObject(reply);
|
||||
reply = redisCommand(c,"FLUSHDB");
|
||||
assert(reply != NULL);
|
||||
freeReplyObject(reply);
|
||||
|
||||
/* Free the context as well. */
|
||||
redisFree(c);
|
||||
}
|
||||
|
||||
static redisContext *connect(struct config config) {
|
||||
redisContext *c = NULL;
|
||||
|
||||
if (config.type == CONN_TCP) {
|
||||
c = redisConnect(config.tcp.host, config.tcp.port);
|
||||
} else if (config.type == CONN_UNIX) {
|
||||
c = redisConnectUnix(config.unix.path);
|
||||
} else {
|
||||
assert(NULL);
|
||||
}
|
||||
|
||||
if (c->err) {
|
||||
printf("Connection error: %s\n", c->errstr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return select_database(c);
|
||||
}
|
||||
|
||||
static void test_format_commands(void) {
|
||||
@@ -142,43 +78,29 @@ static void test_format_commands(void) {
|
||||
len == 4+4+(3+2)+4+(1+2)+4+(1+2));
|
||||
free(cmd);
|
||||
|
||||
/* Vararg width depends on the type. These tests make sure that the
|
||||
* width is correctly determined using the format and subsequent varargs
|
||||
* can correctly be interpolated. */
|
||||
#define INTEGER_WIDTH_TEST(fmt, type) do { \
|
||||
type value = 123; \
|
||||
test("Format command with printf-delegation (" #type "): "); \
|
||||
len = redisFormatCommand(&cmd,"key:%08" fmt " str:%s", value, "hello"); \
|
||||
test_cond(strncmp(cmd,"*2\r\n$12\r\nkey:00000123\r\n$9\r\nstr:hello\r\n",len) == 0 && \
|
||||
len == 4+5+(12+2)+4+(9+2)); \
|
||||
free(cmd); \
|
||||
} while(0)
|
||||
test("Format command with printf-delegation (long long): ");
|
||||
len = redisFormatCommand(&cmd,"key:%08lld",1234ll);
|
||||
test_cond(strncmp(cmd,"*1\r\n$12\r\nkey:00001234\r\n",len) == 0 &&
|
||||
len == 4+5+(12+2));
|
||||
free(cmd);
|
||||
|
||||
#define FLOAT_WIDTH_TEST(type) do { \
|
||||
type value = 123.0; \
|
||||
test("Format command with printf-delegation (" #type "): "); \
|
||||
len = redisFormatCommand(&cmd,"key:%08.3f str:%s", value, "hello"); \
|
||||
test_cond(strncmp(cmd,"*2\r\n$12\r\nkey:0123.000\r\n$9\r\nstr:hello\r\n",len) == 0 && \
|
||||
len == 4+5+(12+2)+4+(9+2)); \
|
||||
free(cmd); \
|
||||
} while(0)
|
||||
test("Format command with printf-delegation (float): ");
|
||||
len = redisFormatCommand(&cmd,"v:%06.1f",12.34f);
|
||||
test_cond(strncmp(cmd,"*1\r\n$8\r\nv:0012.3\r\n",len) == 0 &&
|
||||
len == 4+4+(8+2));
|
||||
free(cmd);
|
||||
|
||||
INTEGER_WIDTH_TEST("d", int);
|
||||
INTEGER_WIDTH_TEST("hhd", char);
|
||||
INTEGER_WIDTH_TEST("hd", short);
|
||||
INTEGER_WIDTH_TEST("ld", long);
|
||||
INTEGER_WIDTH_TEST("lld", long long);
|
||||
INTEGER_WIDTH_TEST("u", unsigned int);
|
||||
INTEGER_WIDTH_TEST("hhu", unsigned char);
|
||||
INTEGER_WIDTH_TEST("hu", unsigned short);
|
||||
INTEGER_WIDTH_TEST("lu", unsigned long);
|
||||
INTEGER_WIDTH_TEST("llu", unsigned long long);
|
||||
FLOAT_WIDTH_TEST(float);
|
||||
FLOAT_WIDTH_TEST(double);
|
||||
test("Format command with printf-delegation and extra interpolation: ");
|
||||
len = redisFormatCommand(&cmd,"key:%d %b",1234,"foo",3);
|
||||
test_cond(strncmp(cmd,"*2\r\n$8\r\nkey:1234\r\n$3\r\nfoo\r\n",len) == 0 &&
|
||||
len == 4+4+(8+2)+4+(3+2));
|
||||
free(cmd);
|
||||
|
||||
test("Format command with invalid printf format: ");
|
||||
len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",3);
|
||||
test_cond(len == -1);
|
||||
test("Format command with wrong printf format and extra interpolation: ");
|
||||
len = redisFormatCommand(&cmd,"key:%08p %b",1234,"foo",3);
|
||||
test_cond(strncmp(cmd,"*2\r\n$6\r\nkey:8p\r\n$3\r\nfoo\r\n",len) == 0 &&
|
||||
len == 4+4+(6+2)+4+(3+2));
|
||||
free(cmd);
|
||||
|
||||
const char *argv[3];
|
||||
argv[0] = "SET";
|
||||
@@ -200,117 +122,42 @@ static void test_format_commands(void) {
|
||||
free(cmd);
|
||||
}
|
||||
|
||||
static void test_reply_reader(void) {
|
||||
redisReader *reader;
|
||||
void *reply;
|
||||
int ret;
|
||||
|
||||
test("Error handling in reply parser: ");
|
||||
reader = redisReaderCreate();
|
||||
redisReaderFeed(reader,(char*)"@foo\r\n",6);
|
||||
ret = redisReaderGetReply(reader,NULL);
|
||||
test_cond(ret == REDIS_ERR &&
|
||||
strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0);
|
||||
redisReaderFree(reader);
|
||||
|
||||
/* when the reply already contains multiple items, they must be free'd
|
||||
* on an error. valgrind will bark when this doesn't happen. */
|
||||
test("Memory cleanup in reply parser: ");
|
||||
reader = redisReaderCreate();
|
||||
redisReaderFeed(reader,(char*)"*2\r\n",4);
|
||||
redisReaderFeed(reader,(char*)"$5\r\nhello\r\n",11);
|
||||
redisReaderFeed(reader,(char*)"@foo\r\n",6);
|
||||
ret = redisReaderGetReply(reader,NULL);
|
||||
test_cond(ret == REDIS_ERR &&
|
||||
strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0);
|
||||
redisReaderFree(reader);
|
||||
|
||||
test("Set error on nested multi bulks with depth > 2: ");
|
||||
reader = redisReaderCreate();
|
||||
redisReaderFeed(reader,(char*)"*1\r\n",4);
|
||||
redisReaderFeed(reader,(char*)"*1\r\n",4);
|
||||
redisReaderFeed(reader,(char*)"*1\r\n",4);
|
||||
redisReaderFeed(reader,(char*)"*1\r\n",4);
|
||||
ret = redisReaderGetReply(reader,NULL);
|
||||
test_cond(ret == REDIS_ERR &&
|
||||
strncasecmp(reader->errstr,"No support for",14) == 0);
|
||||
redisReaderFree(reader);
|
||||
|
||||
test("Works with NULL functions for reply: ");
|
||||
reader = redisReaderCreate();
|
||||
reader->fn = NULL;
|
||||
redisReaderFeed(reader,(char*)"+OK\r\n",5);
|
||||
ret = redisReaderGetReply(reader,&reply);
|
||||
test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);
|
||||
redisReaderFree(reader);
|
||||
|
||||
test("Works when a single newline (\\r\\n) covers two calls to feed: ");
|
||||
reader = redisReaderCreate();
|
||||
reader->fn = NULL;
|
||||
redisReaderFeed(reader,(char*)"+OK\r",4);
|
||||
ret = redisReaderGetReply(reader,&reply);
|
||||
assert(ret == REDIS_OK && reply == NULL);
|
||||
redisReaderFeed(reader,(char*)"\n",1);
|
||||
ret = redisReaderGetReply(reader,&reply);
|
||||
test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);
|
||||
redisReaderFree(reader);
|
||||
|
||||
test("Don't reset state after protocol error: ");
|
||||
reader = redisReaderCreate();
|
||||
reader->fn = NULL;
|
||||
redisReaderFeed(reader,(char*)"x",1);
|
||||
ret = redisReaderGetReply(reader,&reply);
|
||||
assert(ret == REDIS_ERR);
|
||||
ret = redisReaderGetReply(reader,&reply);
|
||||
test_cond(ret == REDIS_ERR && reply == NULL);
|
||||
redisReaderFree(reader);
|
||||
|
||||
/* Regression test for issue #45 on GitHub. */
|
||||
test("Don't do empty allocation for empty multi bulk: ");
|
||||
reader = redisReaderCreate();
|
||||
redisReaderFeed(reader,(char*)"*0\r\n",4);
|
||||
ret = redisReaderGetReply(reader,&reply);
|
||||
test_cond(ret == REDIS_OK &&
|
||||
((redisReply*)reply)->type == REDIS_REPLY_ARRAY &&
|
||||
((redisReply*)reply)->elements == 0);
|
||||
freeReplyObject(reply);
|
||||
redisReaderFree(reader);
|
||||
}
|
||||
|
||||
static void test_blocking_connection_errors(void) {
|
||||
static void test_blocking_connection(void) {
|
||||
redisContext *c;
|
||||
redisReply *reply;
|
||||
int major, minor;
|
||||
|
||||
test("Returns error when host cannot be resolved: ");
|
||||
c = redisConnect((char*)"idontexist.local", 6379);
|
||||
test_cond(c->err == REDIS_ERR_OTHER &&
|
||||
(strcmp(c->errstr,"Name or service not known") == 0 ||
|
||||
strcmp(c->errstr,"Can't resolve: idontexist.local") == 0));
|
||||
strcmp(c->errstr,"Can't resolve: idontexist.local") == 0);
|
||||
redisFree(c);
|
||||
|
||||
test("Returns error when the port is not open: ");
|
||||
c = redisConnect((char*)"localhost", 1);
|
||||
c = redisConnect((char*)"localhost", 56380);
|
||||
test_cond(c->err == REDIS_ERR_IO &&
|
||||
strcmp(c->errstr,"Connection refused") == 0);
|
||||
redisFree(c);
|
||||
|
||||
test("Returns error when the unix socket path doesn't accept connections: ");
|
||||
c = redisConnectUnix((char*)"/tmp/idontexist.sock");
|
||||
test_cond(c->err == REDIS_ERR_IO); /* Don't care about the message... */
|
||||
redisFree(c);
|
||||
}
|
||||
|
||||
static void test_blocking_connection(struct config config) {
|
||||
redisContext *c;
|
||||
redisReply *reply;
|
||||
|
||||
c = connect(config);
|
||||
|
||||
__connect(&c);
|
||||
test("Is able to deliver commands: ");
|
||||
reply = redisCommand(c,"PING");
|
||||
test_cond(reply->type == REDIS_REPLY_STATUS &&
|
||||
strcasecmp(reply->str,"pong") == 0)
|
||||
freeReplyObject(reply);
|
||||
|
||||
/* Switch to DB 9 for testing, now that we know we can chat. */
|
||||
reply = redisCommand(c,"SELECT 9");
|
||||
freeReplyObject(reply);
|
||||
|
||||
/* Make sure the DB is emtpy */
|
||||
reply = redisCommand(c,"DBSIZE");
|
||||
if (reply->type != REDIS_REPLY_INTEGER || reply->integer != 0) {
|
||||
printf("Database #9 is not empty, test can not continue\n");
|
||||
exit(1);
|
||||
}
|
||||
freeReplyObject(reply);
|
||||
|
||||
test("Is a able to send commands verbatim: ");
|
||||
reply = redisCommand(c,"SET foo bar");
|
||||
test_cond (reply->type == REDIS_REPLY_STATUS &&
|
||||
@@ -374,17 +221,6 @@ static void test_blocking_connection(struct config config) {
|
||||
strcasecmp(reply->element[1]->str,"pong") == 0);
|
||||
freeReplyObject(reply);
|
||||
|
||||
disconnect(c);
|
||||
}
|
||||
|
||||
static void test_blocking_io_errors(struct config config) {
|
||||
redisContext *c;
|
||||
redisReply *reply;
|
||||
void *_reply;
|
||||
int major, minor;
|
||||
|
||||
/* Connect to target given by config. */
|
||||
c = connect(config);
|
||||
{
|
||||
/* Find out Redis version to determine the path for the next test */
|
||||
const char *field = "redis_version:";
|
||||
@@ -404,7 +240,7 @@ static void test_blocking_io_errors(struct config config) {
|
||||
/* > 2.0 returns OK on QUIT and read() should be issued once more
|
||||
* to know the descriptor is at EOF. */
|
||||
test_cond(strcasecmp(reply->str,"OK") == 0 &&
|
||||
redisGetReply(c,&_reply) == REDIS_ERR);
|
||||
redisGetReply(c,(void**)&reply) == REDIS_ERR);
|
||||
freeReplyObject(reply);
|
||||
} else {
|
||||
test_cond(reply == NULL);
|
||||
@@ -419,20 +255,91 @@ static void test_blocking_io_errors(struct config config) {
|
||||
strcmp(c->errstr,"Server closed the connection") == 0);
|
||||
redisFree(c);
|
||||
|
||||
c = connect(config);
|
||||
__connect(&c);
|
||||
test("Returns I/O error on socket timeout: ");
|
||||
struct timeval tv = { 0, 1000 };
|
||||
assert(redisSetTimeout(c,tv) == REDIS_OK);
|
||||
test_cond(redisGetReply(c,&_reply) == REDIS_ERR &&
|
||||
test_cond(redisGetReply(c,(void**)&reply) == REDIS_ERR &&
|
||||
c->err == REDIS_ERR_IO && errno == EAGAIN);
|
||||
redisFree(c);
|
||||
|
||||
/* Context should be connected */
|
||||
__connect(&c);
|
||||
}
|
||||
|
||||
static void test_throughput(struct config config) {
|
||||
redisContext *c = connect(config);
|
||||
redisReply **replies;
|
||||
static void test_reply_reader(void) {
|
||||
void *reader;
|
||||
void *reply;
|
||||
char *err;
|
||||
int ret;
|
||||
|
||||
test("Error handling in reply parser: ");
|
||||
reader = redisReplyReaderCreate();
|
||||
redisReplyReaderFeed(reader,(char*)"@foo\r\n",6);
|
||||
ret = redisReplyReaderGetReply(reader,NULL);
|
||||
err = redisReplyReaderGetError(reader);
|
||||
test_cond(ret == REDIS_ERR &&
|
||||
strcasecmp(err,"Protocol error, got \"@\" as reply type byte") == 0);
|
||||
redisReplyReaderFree(reader);
|
||||
|
||||
/* when the reply already contains multiple items, they must be free'd
|
||||
* on an error. valgrind will bark when this doesn't happen. */
|
||||
test("Memory cleanup in reply parser: ");
|
||||
reader = redisReplyReaderCreate();
|
||||
redisReplyReaderFeed(reader,(char*)"*2\r\n",4);
|
||||
redisReplyReaderFeed(reader,(char*)"$5\r\nhello\r\n",11);
|
||||
redisReplyReaderFeed(reader,(char*)"@foo\r\n",6);
|
||||
ret = redisReplyReaderGetReply(reader,NULL);
|
||||
err = redisReplyReaderGetError(reader);
|
||||
test_cond(ret == REDIS_ERR &&
|
||||
strcasecmp(err,"Protocol error, got \"@\" as reply type byte") == 0);
|
||||
redisReplyReaderFree(reader);
|
||||
|
||||
test("Set error on nested multi bulks with depth > 1: ");
|
||||
reader = redisReplyReaderCreate();
|
||||
redisReplyReaderFeed(reader,(char*)"*1\r\n",4);
|
||||
redisReplyReaderFeed(reader,(char*)"*1\r\n",4);
|
||||
redisReplyReaderFeed(reader,(char*)"*1\r\n",4);
|
||||
ret = redisReplyReaderGetReply(reader,NULL);
|
||||
err = redisReplyReaderGetError(reader);
|
||||
test_cond(ret == REDIS_ERR &&
|
||||
strncasecmp(err,"No support for",14) == 0);
|
||||
redisReplyReaderFree(reader);
|
||||
|
||||
test("Works with NULL functions for reply: ");
|
||||
reader = redisReplyReaderCreate();
|
||||
redisReplyReaderSetReplyObjectFunctions(reader,NULL);
|
||||
redisReplyReaderFeed(reader,(char*)"+OK\r\n",5);
|
||||
ret = redisReplyReaderGetReply(reader,&reply);
|
||||
test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);
|
||||
redisReplyReaderFree(reader);
|
||||
|
||||
test("Works when a single newline (\\r\\n) covers two calls to feed: ");
|
||||
reader = redisReplyReaderCreate();
|
||||
redisReplyReaderSetReplyObjectFunctions(reader,NULL);
|
||||
redisReplyReaderFeed(reader,(char*)"+OK\r",4);
|
||||
ret = redisReplyReaderGetReply(reader,&reply);
|
||||
assert(ret == REDIS_OK && reply == NULL);
|
||||
redisReplyReaderFeed(reader,(char*)"\n",1);
|
||||
ret = redisReplyReaderGetReply(reader,&reply);
|
||||
test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS);
|
||||
redisReplyReaderFree(reader);
|
||||
|
||||
test("Properly reset state after protocol error: ");
|
||||
reader = redisReplyReaderCreate();
|
||||
redisReplyReaderSetReplyObjectFunctions(reader,NULL);
|
||||
redisReplyReaderFeed(reader,(char*)"x",1);
|
||||
ret = redisReplyReaderGetReply(reader,&reply);
|
||||
assert(ret == REDIS_ERR);
|
||||
ret = redisReplyReaderGetReply(reader,&reply);
|
||||
test_cond(ret == REDIS_OK && reply == NULL)
|
||||
}
|
||||
|
||||
static void test_throughput(void) {
|
||||
int i, num;
|
||||
long long t1, t2;
|
||||
redisContext *c = blocking_context;
|
||||
redisReply **replies;
|
||||
|
||||
test("Throughput:\n");
|
||||
for (i = 0; i < 500; i++)
|
||||
@@ -489,8 +396,18 @@ static void test_throughput(struct config config) {
|
||||
for (i = 0; i < num; i++) freeReplyObject(replies[i]);
|
||||
free(replies);
|
||||
printf("\t(%dx LRANGE with 500 elements (pipelined): %.3fs)\n", num, (t2-t1)/1000000.0);
|
||||
}
|
||||
|
||||
disconnect(c);
|
||||
static void cleanup(void) {
|
||||
redisContext *c = blocking_context;
|
||||
redisReply *reply;
|
||||
|
||||
/* Make sure we're on DB 9 */
|
||||
reply = redisCommand(c,"SELECT 9");
|
||||
assert(reply != NULL); freeReplyObject(reply);
|
||||
reply = redisCommand(c,"FLUSHDB");
|
||||
assert(reply != NULL); freeReplyObject(reply);
|
||||
redisFree(c);
|
||||
}
|
||||
|
||||
// static long __test_callback_flags = 0;
|
||||
@@ -512,7 +429,7 @@ static void test_throughput(struct config config) {
|
||||
// static redisContext *__connect_nonblock() {
|
||||
// /* Reset callback flags */
|
||||
// __test_callback_flags = 0;
|
||||
// return redisConnectNonBlock("127.0.0.1", port, NULL);
|
||||
// return redisConnectNonBlock("127.0.0.1", 6379, NULL);
|
||||
// }
|
||||
//
|
||||
// static void test_nonblocking_connection() {
|
||||
@@ -593,62 +510,23 @@ static void test_throughput(struct config config) {
|
||||
// }
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
struct config cfg = {
|
||||
.tcp = {
|
||||
.host = "127.0.0.1",
|
||||
.port = 6379
|
||||
},
|
||||
.unix = {
|
||||
.path = "/tmp/redis.sock"
|
||||
}
|
||||
};
|
||||
int throughput = 1;
|
||||
if (argc > 1) {
|
||||
if (strcmp(argv[1],"-s") == 0)
|
||||
use_unix = 1;
|
||||
}
|
||||
|
||||
/* Ignore broken pipe signal (for I/O error tests). */
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
/* Parse command line options. */
|
||||
argv++; argc--;
|
||||
while (argc) {
|
||||
if (argc >= 2 && !strcmp(argv[0],"-h")) {
|
||||
argv++; argc--;
|
||||
cfg.tcp.host = argv[0];
|
||||
} else if (argc >= 2 && !strcmp(argv[0],"-p")) {
|
||||
argv++; argc--;
|
||||
cfg.tcp.port = atoi(argv[0]);
|
||||
} else if (argc >= 2 && !strcmp(argv[0],"-s")) {
|
||||
argv++; argc--;
|
||||
cfg.unix.path = argv[0];
|
||||
} else if (argc >= 1 && !strcmp(argv[0],"--skip-throughput")) {
|
||||
throughput = 0;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid argument: %s\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
argv++; argc--;
|
||||
}
|
||||
|
||||
test_format_commands();
|
||||
test_blocking_connection();
|
||||
test_reply_reader();
|
||||
test_blocking_connection_errors();
|
||||
// test_nonblocking_connection();
|
||||
test_throughput();
|
||||
cleanup();
|
||||
|
||||
printf("\nTesting against TCP connection (%s:%d):\n", cfg.tcp.host, cfg.tcp.port);
|
||||
cfg.type = CONN_TCP;
|
||||
test_blocking_connection(cfg);
|
||||
test_blocking_io_errors(cfg);
|
||||
if (throughput) test_throughput(cfg);
|
||||
|
||||
printf("\nTesting against Unix socket connection (%s):\n", cfg.unix.path);
|
||||
cfg.type = CONN_UNIX;
|
||||
test_blocking_connection(cfg);
|
||||
test_blocking_io_errors(cfg);
|
||||
if (throughput) test_throughput(cfg);
|
||||
|
||||
if (fails) {
|
||||
if (fails == 0) {
|
||||
printf("ALL TESTS PASSED\n");
|
||||
} else {
|
||||
printf("*** %d TESTS FAILED ***\n", fails);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("ALL TESTS PASSED\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
+11
-34
@@ -1,8 +1,5 @@
|
||||
/* See endianconv.c top comments for more information
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2011-2012, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
/*
|
||||
* Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -28,36 +25,16 @@
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
*/
|
||||
|
||||
#ifndef __ENDIANCONV_H
|
||||
#define __ENDIANCONV_H
|
||||
#ifndef __UTIL_H
|
||||
#define __UTIL_H
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void memrev16(void *p);
|
||||
void memrev32(void *p);
|
||||
void memrev64(void *p);
|
||||
uint16_t intrev16(uint16_t v);
|
||||
uint32_t intrev32(uint32_t v);
|
||||
uint64_t intrev64(uint64_t v);
|
||||
|
||||
/* variants of the function doing the actual convertion only if the target
|
||||
* host is big endian */
|
||||
#if (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
#define memrev16ifbe(p)
|
||||
#define memrev32ifbe(p)
|
||||
#define memrev64ifbe(p)
|
||||
#define intrev16ifbe(v) (v)
|
||||
#define intrev32ifbe(v) (v)
|
||||
#define intrev64ifbe(v) (v)
|
||||
#else
|
||||
#define memrev16ifbe(p) memrev16(p)
|
||||
#define memrev32ifbe(p) memrev32(p)
|
||||
#define memrev64ifbe(p) memrev64(p)
|
||||
#define intrev16ifbe(v) intrev16(v)
|
||||
#define intrev32ifbe(v) intrev32(v)
|
||||
#define intrev64ifbe(v) intrev64(v)
|
||||
#endif
|
||||
/* Abort on out of memory */
|
||||
static void redisOOM(void) {
|
||||
fprintf(stderr,"Out of memory in hiredis");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#endif
|
||||
+14
-22
@@ -1,23 +1,15 @@
|
||||
/autom4te.cache/
|
||||
/config.stamp
|
||||
/config.log
|
||||
/config.status
|
||||
/configure
|
||||
/doc/html.xsl
|
||||
/doc/manpages.xsl
|
||||
/doc/jemalloc.xml
|
||||
/doc/jemalloc.html
|
||||
/doc/jemalloc.3
|
||||
/lib/
|
||||
/Makefile
|
||||
/include/jemalloc/internal/jemalloc_internal\.h
|
||||
/include/jemalloc/jemalloc\.h
|
||||
/include/jemalloc/jemalloc_defs\.h
|
||||
/test/jemalloc_test\.h
|
||||
/src/*.[od]
|
||||
/test/*.[od]
|
||||
/test/*.out
|
||||
/test/[a-z]*
|
||||
!test/*.c
|
||||
!test/*.exp
|
||||
/VERSION
|
||||
/config.stamp
|
||||
/config.status
|
||||
|
||||
/doc/html.xsl
|
||||
/doc/jemalloc.xml
|
||||
/doc/manpages.xsl
|
||||
|
||||
/src/*.d
|
||||
/lib
|
||||
|
||||
# The following headers are generated
|
||||
/include/jemalloc/*.h
|
||||
/include/jemalloc/internal/jemalloc_internal.h
|
||||
/test/jemalloc_test.h
|
||||
|
||||
Vendored
-37
@@ -6,43 +6,6 @@ found in the git revision history:
|
||||
http://www.canonware.com/cgi-bin/gitweb.cgi?p=jemalloc.git
|
||||
git://canonware.com/jemalloc.git
|
||||
|
||||
* 2.2.5 (November 14, 2011)
|
||||
|
||||
Bug fixes:
|
||||
- Fix huge_ralloc() race when using mremap(2). This is a serious bug that
|
||||
could cause memory corruption and/or crashes.
|
||||
- Fix huge_ralloc() to maintain chunk statistics.
|
||||
- Fix malloc_stats_print(..., "a") output.
|
||||
|
||||
* 2.2.4 (November 5, 2011)
|
||||
|
||||
Bug fixes:
|
||||
- Initialize arenas_tsd before using it. This bug existed for 2.2.[0-3], as
|
||||
well as for --disable-tls builds in earlier releases.
|
||||
- Do not assume a 4 KiB page size in test/rallocm.c.
|
||||
|
||||
* 2.2.3 (August 31, 2011)
|
||||
|
||||
This version fixes numerous bugs related to heap profiling.
|
||||
|
||||
Bug fixes:
|
||||
- Fix a prof-related race condition. This bug could cause memory corruption,
|
||||
but only occurred in non-default configurations (prof_accum:false).
|
||||
- Fix off-by-one backtracing issues (make sure that prof_alloc_prep() is
|
||||
excluded from backtraces).
|
||||
- Fix a prof-related bug in realloc() (only triggered by OOM errors).
|
||||
- Fix prof-related bugs in allocm() and rallocm().
|
||||
- Fix prof_tdata_cleanup() for --disable-tls builds.
|
||||
- Fix a relative include path, to fix objdir builds.
|
||||
|
||||
* 2.2.2 (July 30, 2011)
|
||||
|
||||
Bug fixes:
|
||||
- Fix a build error for --disable-tcache.
|
||||
- Fix assertions in arena_purge() (for real this time).
|
||||
- Add the --with-private-namespace option. This is a workaround for symbol
|
||||
conflicts that can inadvertently arise when using static libraries.
|
||||
|
||||
* 2.2.1 (March 30, 2011)
|
||||
|
||||
Bug fixes:
|
||||
|
||||
Vendored
-6
@@ -42,12 +42,6 @@ any of the following arguments (not a definitive list) to 'configure':
|
||||
jemalloc overlays the default malloc zone, but makes no attempt to actually
|
||||
replace the "malloc", "calloc", etc. symbols.
|
||||
|
||||
--with-private-namespace=<prefix>
|
||||
Prefix all library-private APIs with <prefix>. For shared libraries,
|
||||
symbol visibility mechanisms prevent these symbols from being exported, but
|
||||
for static libraries, naming collisions are a real possibility. By
|
||||
default, the prefix is "" (empty string).
|
||||
|
||||
--with-install-suffix=<suffix>
|
||||
Append <suffix> to the base name of all installed files, such that multiple
|
||||
versions of jemalloc can coexist in the same installation directory. For
|
||||
|
||||
Vendored
+2
-2
@@ -136,9 +136,9 @@ doc: $(DOCS)
|
||||
@objroot@lib/libjemalloc@install_suffix@.$(SO)
|
||||
@mkdir -p $(@D)
|
||||
ifneq (@RPATH@, )
|
||||
$(CC) -o $@ $< @RPATH@@objroot@lib -L@objroot@lib -ljemalloc@install_suffix@ -lpthread
|
||||
$(CC) -o $@ $< @RPATH@@objroot@lib -L@objroot@lib -ljemalloc@install_suffix@
|
||||
else
|
||||
$(CC) -o $@ $< -L@objroot@lib -ljemalloc@install_suffix@ -lpthread
|
||||
$(CC) -o $@ $< -L@objroot@lib -ljemalloc@install_suffix@
|
||||
endif
|
||||
|
||||
install_bin:
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
2.2.5-0-gfc1bb70e5f0d9a58b39efa39cc549b5af5104760
|
||||
2.2.1-0-g5ef7abf6d846720fb3fb8c737861c99b5ad1d862
|
||||
|
||||
Vendored
+7
-33
@@ -617,6 +617,8 @@ enable_prof
|
||||
enable_stats
|
||||
enable_debug
|
||||
install_suffix
|
||||
jemalloc_cprefix
|
||||
jemalloc_prefix
|
||||
AUTOCONF
|
||||
LD
|
||||
AR
|
||||
@@ -703,7 +705,6 @@ with_xslroot
|
||||
with_rpath
|
||||
enable_autogen
|
||||
with_jemalloc_prefix
|
||||
with_private_namespace
|
||||
with_install_suffix
|
||||
enable_cc_silence
|
||||
enable_debug
|
||||
@@ -1374,8 +1375,6 @@ Optional Packages:
|
||||
--with-rpath=<rpath> Colon-separated rpath (ELF systems only)
|
||||
--with-jemalloc-prefix=<prefix>
|
||||
Prefix to prepend to all public APIs
|
||||
--with-private-namespace=<prefix>
|
||||
Prefix to prepend to all library-private APIs
|
||||
--with-install-suffix=<suffix>
|
||||
Suffix to append to all installed files
|
||||
--with-static-libunwind=<libunwind.a>
|
||||
@@ -4801,6 +4800,10 @@ _ACEOF
|
||||
#define JEMALLOC_CPREFIX "$JEMALLOC_CPREFIX"
|
||||
_ACEOF
|
||||
|
||||
jemalloc_prefix="$JEMALLOC_PREFIX"
|
||||
jemalloc_cprefix="$JEMALLOC_CPREFIX"
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define JEMALLOC_P(string_that_no_one_should_want_to_use_as_a_jemalloc_API_prefix) ${JEMALLOC_PREFIX}##string_that_no_one_should_want_to_use_as_a_jemalloc_API_prefix
|
||||
_ACEOF
|
||||
@@ -4808,31 +4811,6 @@ _ACEOF
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --with-private_namespace was given.
|
||||
if test "${with_private_namespace+set}" = set; then :
|
||||
withval=$with_private_namespace; JEMALLOC_PRIVATE_NAMESPACE="$with_private_namespace"
|
||||
else
|
||||
JEMALLOC_PRIVATE_NAMESPACE=""
|
||||
|
||||
fi
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define JEMALLOC_PRIVATE_NAMESPACE "$JEMALLOC_PRIVATE_NAMESPACE"
|
||||
_ACEOF
|
||||
|
||||
if test "x$JEMALLOC_PRIVATE_NAMESPACE" != "x" ; then
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define JEMALLOC_N(string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix) ${JEMALLOC_PRIVATE_NAMESPACE}##string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix
|
||||
_ACEOF
|
||||
|
||||
else
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define JEMALLOC_N(string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix) string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --with-install_suffix was given.
|
||||
if test "${with_install_suffix+set}" = set; then :
|
||||
withval=$with_install_suffix; INSTALL_SUFFIX="$with_install_suffix"
|
||||
@@ -5530,7 +5508,7 @@ fi
|
||||
|
||||
|
||||
|
||||
if test -d "${srcroot}.git" ; then
|
||||
if test -d "${srcroot}../.git" ; then
|
||||
git describe --long --abbrev=40 > ${srcroot}VERSION
|
||||
fi
|
||||
jemalloc_version=`cat ${srcroot}VERSION`
|
||||
@@ -7368,10 +7346,6 @@ $as_echo "abs_objroot : ${abs_objroot}" >&6; }
|
||||
$as_echo "" >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: JEMALLOC_PREFIX : ${JEMALLOC_PREFIX}" >&5
|
||||
$as_echo "JEMALLOC_PREFIX : ${JEMALLOC_PREFIX}" >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: JEMALLOC_PRIVATE_NAMESPACE" >&5
|
||||
$as_echo "JEMALLOC_PRIVATE_NAMESPACE" >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: : ${JEMALLOC_PRIVATE_NAMESPACE}" >&5
|
||||
$as_echo " : ${JEMALLOC_PRIVATE_NAMESPACE}" >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: install_suffix : ${install_suffix}" >&5
|
||||
$as_echo "install_suffix : ${install_suffix}" >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: autogen : ${enable_autogen}" >&5
|
||||
|
||||
Vendored
+5
-16
@@ -292,22 +292,13 @@ if test "x$JEMALLOC_PREFIX" != "x" ; then
|
||||
JEMALLOC_CPREFIX=`echo ${JEMALLOC_PREFIX} | tr "a-z" "A-Z"`
|
||||
AC_DEFINE_UNQUOTED([JEMALLOC_PREFIX], ["$JEMALLOC_PREFIX"])
|
||||
AC_DEFINE_UNQUOTED([JEMALLOC_CPREFIX], ["$JEMALLOC_CPREFIX"])
|
||||
jemalloc_prefix="$JEMALLOC_PREFIX"
|
||||
jemalloc_cprefix="$JEMALLOC_CPREFIX"
|
||||
AC_SUBST([jemalloc_prefix])
|
||||
AC_SUBST([jemalloc_cprefix])
|
||||
AC_DEFINE_UNQUOTED([JEMALLOC_P(string_that_no_one_should_want_to_use_as_a_jemalloc_API_prefix)], [${JEMALLOC_PREFIX}##string_that_no_one_should_want_to_use_as_a_jemalloc_API_prefix])
|
||||
fi
|
||||
|
||||
dnl Do not mangle library-private APIs by default.
|
||||
AC_ARG_WITH([private_namespace],
|
||||
[AS_HELP_STRING([--with-private-namespace=<prefix>], [Prefix to prepend to all library-private APIs])],
|
||||
[JEMALLOC_PRIVATE_NAMESPACE="$with_private_namespace"],
|
||||
[JEMALLOC_PRIVATE_NAMESPACE=""]
|
||||
)
|
||||
AC_DEFINE_UNQUOTED([JEMALLOC_PRIVATE_NAMESPACE], ["$JEMALLOC_PRIVATE_NAMESPACE"])
|
||||
if test "x$JEMALLOC_PRIVATE_NAMESPACE" != "x" ; then
|
||||
AC_DEFINE_UNQUOTED([JEMALLOC_N(string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix)], [${JEMALLOC_PRIVATE_NAMESPACE}##string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix])
|
||||
else
|
||||
AC_DEFINE_UNQUOTED([JEMALLOC_N(string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix)], [string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix])
|
||||
fi
|
||||
|
||||
dnl Do not add suffix to installed files by default.
|
||||
AC_ARG_WITH([install_suffix],
|
||||
[AS_HELP_STRING([--with-install-suffix=<suffix>], [Suffix to append to all installed files])],
|
||||
@@ -697,7 +688,7 @@ dnl jemalloc configuration.
|
||||
dnl
|
||||
|
||||
dnl Set VERSION if source directory has an embedded git repository.
|
||||
if test -d "${srcroot}.git" ; then
|
||||
if test -d "${srcroot}../.git" ; then
|
||||
git describe --long --abbrev=40 > ${srcroot}VERSION
|
||||
fi
|
||||
jemalloc_version=`cat ${srcroot}VERSION`
|
||||
@@ -914,8 +905,6 @@ AC_MSG_RESULT([objroot : ${objroot}])
|
||||
AC_MSG_RESULT([abs_objroot : ${abs_objroot}])
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_RESULT([JEMALLOC_PREFIX : ${JEMALLOC_PREFIX}])
|
||||
AC_MSG_RESULT([JEMALLOC_PRIVATE_NAMESPACE])
|
||||
AC_MSG_RESULT([ : ${JEMALLOC_PRIVATE_NAMESPACE}])
|
||||
AC_MSG_RESULT([install_suffix : ${install_suffix}])
|
||||
AC_MSG_RESULT([autogen : ${enable_autogen}])
|
||||
AC_MSG_RESULT([cc-silence : ${enable_cc_silence}])
|
||||
|
||||
Vendored
+5
-5
@@ -2,12 +2,12 @@
|
||||
.\" Title: JEMALLOC
|
||||
.\" Author: Jason Evans
|
||||
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
|
||||
.\" Date: 11/14/2011
|
||||
.\" Date: 03/30/2011
|
||||
.\" Manual: User Manual
|
||||
.\" Source: jemalloc 2.2.5-0-gfc1bb70e5f0d9a58b39efa39cc549b5af5104760
|
||||
.\" Source: jemalloc 2.2.1-0-g5ef7abf6d846720fb3fb8c737861c99b5ad1d862
|
||||
.\" Language: English
|
||||
.\"
|
||||
.TH "JEMALLOC" "3" "11/14/2011" "jemalloc 2.2.5-0-gfc1bb70e5f0d" "User Manual"
|
||||
.TH "JEMALLOC" "3" "03/30/2011" "jemalloc 2.2.1-0-g5ef7abf6d846" "User Manual"
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" * Define some portability stuff
|
||||
.\" -----------------------------------------------------------------
|
||||
@@ -31,7 +31,7 @@
|
||||
jemalloc \- general purpose memory allocation functions
|
||||
.SH "LIBRARY"
|
||||
.PP
|
||||
This manual describes jemalloc 2\&.2\&.5\-0\-gfc1bb70e5f0d9a58b39efa39cc549b5af5104760\&. More information can be found at the
|
||||
This manual describes jemalloc 2\&.2\&.1\-0\-g5ef7abf6d846720fb3fb8c737861c99b5ad1d862\&. More information can be found at the
|
||||
\m[blue]\fBjemalloc website\fR\m[]\&\s-2\u[1]\d\s+2\&.
|
||||
.SH "SYNOPSIS"
|
||||
.sp
|
||||
@@ -1215,7 +1215,7 @@ is successfully written to\&.
|
||||
Number of file descriptors in use for swap\&.
|
||||
.RE
|
||||
.PP
|
||||
"swap\&.fds" (\fBint *\fR) rw [\fB\-\-enable\-swap\fR]
|
||||
"swap\&.fds" (\fBint *\fR) r\- [\fB\-\-enable\-swap\fR]
|
||||
.RS 4
|
||||
When written to, the files associated with the specified file descriptors are contiguously mapped via
|
||||
\fBmmap\fR(2)\&. The resulting virtual memory region is preferred over anonymous
|
||||
|
||||
Vendored
+9
-9
@@ -1,8 +1,8 @@
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>JEMALLOC</title><meta name="generator" content="DocBook XSL Stylesheets V1.75.2"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" title="JEMALLOC"><a name="id2968890"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>jemalloc — general purpose memory allocation functions</p></div><div class="refsect1" title="LIBRARY"><a name="library"></a><h2>LIBRARY</h2><p>This manual describes jemalloc 2.2.5-0-gfc1bb70e5f0d9a58b39efa39cc549b5af5104760. More information
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>JEMALLOC</title><meta name="generator" content="DocBook XSL Stylesheets V1.75.2"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" title="JEMALLOC"><a name="id2783946"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>jemalloc — general purpose memory allocation functions</p></div><div class="refsect1" title="LIBRARY"><a name="library"></a><h2>LIBRARY</h2><p>This manual describes jemalloc 2.2.1-0-g5ef7abf6d846720fb3fb8c737861c99b5ad1d862. More information
|
||||
can be found at the <a class="ulink" href="http://www.canonware.com/jemalloc/" target="_top">jemalloc website</a>.</p></div><div class="refsynopsisdiv" title="SYNOPSIS"><h2>SYNOPSIS</h2><div class="funcsynopsis"><pre class="funcsynopsisinfo">#include <<code class="filename">stdlib.h</code>>
|
||||
#include <<code class="filename">jemalloc/jemalloc.h</code>></pre><div class="refsect2" title="Standard API"><a name="id2992781"></a><h3>Standard API</h3><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void *<b class="fsfunc">malloc</b>(</code></td><td>size_t <var class="pdparam">size</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void *<b class="fsfunc">calloc</b>(</code></td><td>size_t <var class="pdparam">number</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">size</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">posix_memalign</b>(</code></td><td>void **<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">alignment</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">size</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void *<b class="fsfunc">realloc</b>(</code></td><td>void *<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">size</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void <b class="fsfunc">free</b>(</code></td><td>void *<var class="pdparam">ptr</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div></div><div class="refsect2" title="Non-standard API"><a name="id2998350"></a><h3>Non-standard API</h3><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">size_t <b class="fsfunc">malloc_usable_size</b>(</code></td><td>const void *<var class="pdparam">ptr</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void <b class="fsfunc">malloc_stats_print</b>(</code></td><td>void <var class="pdparam">(*write_cb)</var>
|
||||
#include <<code class="filename">jemalloc/jemalloc.h</code>></pre><div class="refsect2" title="Standard API"><a name="id2830421"></a><h3>Standard API</h3><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void *<b class="fsfunc">malloc</b>(</code></td><td>size_t <var class="pdparam">size</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void *<b class="fsfunc">calloc</b>(</code></td><td>size_t <var class="pdparam">number</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">size</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">posix_memalign</b>(</code></td><td>void **<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">alignment</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">size</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void *<b class="fsfunc">realloc</b>(</code></td><td>void *<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">size</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void <b class="fsfunc">free</b>(</code></td><td>void *<var class="pdparam">ptr</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div></div><div class="refsect2" title="Non-standard API"><a name="id2837717"></a><h3>Non-standard API</h3><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">size_t <b class="fsfunc">malloc_usable_size</b>(</code></td><td>const void *<var class="pdparam">ptr</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void <b class="fsfunc">malloc_stats_print</b>(</code></td><td>void <var class="pdparam">(*write_cb)</var>
|
||||
<code>(</code>void *, const char *<code>)</code>
|
||||
, </td></tr><tr><td> </td><td>void *<var class="pdparam">cbopaque</var>, </td></tr><tr><td> </td><td>const char *<var class="pdparam">opts</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">mallctl</b>(</code></td><td>const char *<var class="pdparam">name</var>, </td></tr><tr><td> </td><td>void *<var class="pdparam">oldp</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">oldlenp</var>, </td></tr><tr><td> </td><td>void *<var class="pdparam">newp</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">newlen</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">mallctlnametomib</b>(</code></td><td>const char *<var class="pdparam">name</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">mibp</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">miblenp</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">mallctlbymib</b>(</code></td><td>const size_t *<var class="pdparam">mib</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">miblen</var>, </td></tr><tr><td> </td><td>void *<var class="pdparam">oldp</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">oldlenp</var>, </td></tr><tr><td> </td><td>void *<var class="pdparam">newp</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">newlen</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void <b class="fsfunc">(*malloc_message)</b>(</code></td><td>void *<var class="pdparam">cbopaque</var>, </td></tr><tr><td> </td><td>const char *<var class="pdparam">s</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><p><span class="type">const char *</span><code class="varname">malloc_conf</code>;</p></div><div class="refsect2" title="Experimental API"><a name="id3014125"></a><h3>Experimental API</h3><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">allocm</b>(</code></td><td>void **<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">rsize</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">size</var>, </td></tr><tr><td> </td><td>int <var class="pdparam">flags</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">rallocm</b>(</code></td><td>void **<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">rsize</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">size</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">extra</var>, </td></tr><tr><td> </td><td>int <var class="pdparam">flags</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">sallocm</b>(</code></td><td>const void *<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">rsize</var>, </td></tr><tr><td> </td><td>int <var class="pdparam">flags</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">dallocm</b>(</code></td><td>void *<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>int <var class="pdparam">flags</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div></div></div></div><div class="refsect1" title="DESCRIPTION"><a name="description"></a><h2>DESCRIPTION</h2><div class="refsect2" title="Standard API"><a name="id3014924"></a><h3>Standard API</h3><p>The <code class="function">malloc</code>(<em class="parameter"><code></code></em>) function allocates
|
||||
, </td></tr><tr><td> </td><td>void *<var class="pdparam">cbopaque</var>, </td></tr><tr><td> </td><td>const char *<var class="pdparam">opts</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">mallctl</b>(</code></td><td>const char *<var class="pdparam">name</var>, </td></tr><tr><td> </td><td>void *<var class="pdparam">oldp</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">oldlenp</var>, </td></tr><tr><td> </td><td>void *<var class="pdparam">newp</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">newlen</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">mallctlnametomib</b>(</code></td><td>const char *<var class="pdparam">name</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">mibp</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">miblenp</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">mallctlbymib</b>(</code></td><td>const size_t *<var class="pdparam">mib</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">miblen</var>, </td></tr><tr><td> </td><td>void *<var class="pdparam">oldp</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">oldlenp</var>, </td></tr><tr><td> </td><td>void *<var class="pdparam">newp</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">newlen</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">void <b class="fsfunc">(*malloc_message)</b>(</code></td><td>void *<var class="pdparam">cbopaque</var>, </td></tr><tr><td> </td><td>const char *<var class="pdparam">s</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><p><span class="type">const char *</span><code class="varname">malloc_conf</code>;</p></div><div class="refsect2" title="Experimental API"><a name="id2830042"></a><h3>Experimental API</h3><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">allocm</b>(</code></td><td>void **<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">rsize</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">size</var>, </td></tr><tr><td> </td><td>int <var class="pdparam">flags</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">rallocm</b>(</code></td><td>void **<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">rsize</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">size</var>, </td></tr><tr><td> </td><td>size_t <var class="pdparam">extra</var>, </td></tr><tr><td> </td><td>int <var class="pdparam">flags</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">sallocm</b>(</code></td><td>const void *<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>size_t *<var class="pdparam">rsize</var>, </td></tr><tr><td> </td><td>int <var class="pdparam">flags</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div><table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" class="funcprototype-table"><tr><td><code class="funcdef">int <b class="fsfunc">dallocm</b>(</code></td><td>void *<var class="pdparam">ptr</var>, </td></tr><tr><td> </td><td>int <var class="pdparam">flags</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div></div></div></div><div class="refsect1" title="DESCRIPTION"><a name="description"></a><h2>DESCRIPTION</h2><div class="refsect2" title="Standard API"><a name="id2840968"></a><h3>Standard API</h3><p>The <code class="function">malloc</code>(<em class="parameter"><code></code></em>) function allocates
|
||||
<em class="parameter"><code>size</code></em> bytes of uninitialized memory. The allocated
|
||||
space is suitably aligned (after possible pointer coercion) for storage
|
||||
of any type of object.</p><p>The <code class="function">calloc</code>(<em class="parameter"><code></code></em>) function allocates
|
||||
@@ -32,7 +32,7 @@
|
||||
<code class="function">malloc</code>(<em class="parameter"><code></code></em>) for the specified size.</p><p>The <code class="function">free</code>(<em class="parameter"><code></code></em>) function causes the
|
||||
allocated memory referenced by <em class="parameter"><code>ptr</code></em> to be made
|
||||
available for future allocations. If <em class="parameter"><code>ptr</code></em> is
|
||||
<code class="constant">NULL</code>, no action occurs.</p></div><div class="refsect2" title="Non-standard API"><a name="id3025603"></a><h3>Non-standard API</h3><p>The <code class="function">malloc_usable_size</code>(<em class="parameter"><code></code></em>) function
|
||||
<code class="constant">NULL</code>, no action occurs.</p></div><div class="refsect2" title="Non-standard API"><a name="id2827225"></a><h3>Non-standard API</h3><p>The <code class="function">malloc_usable_size</code>(<em class="parameter"><code></code></em>) function
|
||||
returns the usable size of the allocation pointed to by
|
||||
<em class="parameter"><code>ptr</code></em>. The return value may be larger than the size
|
||||
that was requested during allocation. The
|
||||
@@ -112,7 +112,7 @@ for (i = 0; i < nbins; i++) {
|
||||
len = sizeof(bin_size);
|
||||
mallctlbymib(mib, miblen, &bin_size, &len, NULL, 0);
|
||||
/* Do something with bin_size... */
|
||||
}</pre></div><div class="refsect2" title="Experimental API"><a name="id3013809"></a><h3>Experimental API</h3><p>The experimental API is subject to change or removal without regard
|
||||
}</pre></div><div class="refsect2" title="Experimental API"><a name="id2807945"></a><h3>Experimental API</h3><p>The experimental API is subject to change or removal without regard
|
||||
for backward compatibility.</p><p>The <code class="function">allocm</code>(<em class="parameter"><code></code></em>),
|
||||
<code class="function">rallocm</code>(<em class="parameter"><code></code></em>),
|
||||
<code class="function">sallocm</code>(<em class="parameter"><code></code></em>), and
|
||||
@@ -1397,7 +1397,7 @@ malloc_conf = "xmalloc:true";</pre><p>
|
||||
"<code class="mallctl">swap.fds</code>"
|
||||
|
||||
(<span class="type">int *</span>)
|
||||
<code class="literal">rw</code>
|
||||
<code class="literal">r-</code>
|
||||
[<code class="option">--enable-swap</code>]
|
||||
</span></dt><dd><p>When written to, the files associated with the
|
||||
specified file descriptors are contiguously mapped via
|
||||
@@ -1447,7 +1447,7 @@ malloc_conf = "xmalloc:true";</pre><p>
|
||||
<code class="function">malloc_stats_print</code>(<em class="parameter"><code></code></em>), followed by a string
|
||||
pointer. Please note that doing anything which tries to allocate memory in
|
||||
this function is likely to result in a crash or deadlock.</p><p>All messages are prefixed by
|
||||
“<code class="computeroutput"><jemalloc>: </code>”.</p></div><div class="refsect1" title="RETURN VALUES"><a name="return_values"></a><h2>RETURN VALUES</h2><div class="refsect2" title="Standard API"><a name="id3029250"></a><h3>Standard API</h3><p>The <code class="function">malloc</code>(<em class="parameter"><code></code></em>) and
|
||||
“<code class="computeroutput"><jemalloc>: </code>”.</p></div><div class="refsect1" title="RETURN VALUES"><a name="return_values"></a><h2>RETURN VALUES</h2><div class="refsect2" title="Standard API"><a name="id2844722"></a><h3>Standard API</h3><p>The <code class="function">malloc</code>(<em class="parameter"><code></code></em>) and
|
||||
<code class="function">calloc</code>(<em class="parameter"><code></code></em>) functions return a pointer to the
|
||||
allocated memory if successful; otherwise a <code class="constant">NULL</code>
|
||||
pointer is returned and <code class="varname">errno</code> is set to
|
||||
@@ -1467,7 +1467,7 @@ malloc_conf = "xmalloc:true";</pre><p>
|
||||
allocation failure. The <code class="function">realloc</code>(<em class="parameter"><code></code></em>)
|
||||
function always leaves the original buffer intact when an error occurs.
|
||||
</p><p>The <code class="function">free</code>(<em class="parameter"><code></code></em>) function returns no
|
||||
value.</p></div><div class="refsect2" title="Non-standard API"><a name="id3029403"></a><h3>Non-standard API</h3><p>The <code class="function">malloc_usable_size</code>(<em class="parameter"><code></code></em>) function
|
||||
value.</p></div><div class="refsect2" title="Non-standard API"><a name="id2844875"></a><h3>Non-standard API</h3><p>The <code class="function">malloc_usable_size</code>(<em class="parameter"><code></code></em>) function
|
||||
returns the usable size of the allocation pointed to by
|
||||
<em class="parameter"><code>ptr</code></em>. </p><p>The <code class="function">mallctl</code>(<em class="parameter"><code></code></em>),
|
||||
<code class="function">mallctlnametomib</code>(<em class="parameter"><code></code></em>), and
|
||||
@@ -1486,7 +1486,7 @@ malloc_conf = "xmalloc:true";</pre><p>
|
||||
occurred.</p></dd><dt><span class="term"><span class="errorname">EFAULT</span></span></dt><dd><p>An interface with side effects failed in some way
|
||||
not directly related to <code class="function">mallctl*</code>(<em class="parameter"><code></code></em>)
|
||||
read/write processing.</p></dd></dl></div><p>
|
||||
</p></div><div class="refsect2" title="Experimental API"><a name="id3029581"></a><h3>Experimental API</h3><p>The <code class="function">allocm</code>(<em class="parameter"><code></code></em>),
|
||||
</p></div><div class="refsect2" title="Experimental API"><a name="id2845053"></a><h3>Experimental API</h3><p>The <code class="function">allocm</code>(<em class="parameter"><code></code></em>),
|
||||
<code class="function">rallocm</code>(<em class="parameter"><code></code></em>),
|
||||
<code class="function">sallocm</code>(<em class="parameter"><code></code></em>), and
|
||||
<code class="function">dallocm</code>(<em class="parameter"><code></code></em>) functions return
|
||||
|
||||
Vendored
+1
-1
@@ -2025,7 +2025,7 @@ malloc_conf = "xmalloc:true";]]></programlisting>
|
||||
<term>
|
||||
<mallctl>swap.fds</mallctl>
|
||||
(<type>int *</type>)
|
||||
<literal>rw</literal>
|
||||
<literal>r-</literal>
|
||||
[<option>--enable-swap</option>]
|
||||
</term>
|
||||
<listitem><para>When written to, the files associated with the
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ extern size_t map_bias; /* Number of arena chunk header pages. */
|
||||
extern size_t arena_maxclass; /* Max size class for arenas. */
|
||||
|
||||
void *chunk_alloc(size_t size, bool base, bool *zero);
|
||||
void chunk_dealloc(void *chunk, size_t size, bool unmap);
|
||||
void chunk_dealloc(void *chunk, size_t size);
|
||||
bool chunk_boot(void);
|
||||
|
||||
#endif /* JEMALLOC_H_EXTERNS */
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ uint64_t hash(const void *key, size_t len, uint64_t seed);
|
||||
JEMALLOC_INLINE uint64_t
|
||||
hash(const void *key, size_t len, uint64_t seed)
|
||||
{
|
||||
const uint64_t m = 0xc6a4a7935bd1e995LLU;
|
||||
const uint64_t m = 0xc6a4a7935bd1e995;
|
||||
const int r = 47;
|
||||
uint64_t h = seed ^ (len * m);
|
||||
const uint64_t *data = (const uint64_t *)key;
|
||||
|
||||
@@ -33,8 +33,6 @@
|
||||
#define JEMALLOC_MANGLE
|
||||
#include "../jemalloc@install_suffix@.h"
|
||||
|
||||
#include "jemalloc/internal/private_namespace.h"
|
||||
|
||||
#if (defined(JEMALLOC_OSATOMIC) || defined(JEMALLOC_OSSPIN))
|
||||
#include <libkern/OSAtomic.h>
|
||||
#endif
|
||||
@@ -635,11 +633,7 @@ ipalloc(size_t usize, size_t alignment, bool zero)
|
||||
if (usize <= arena_maxclass && alignment <= PAGE_SIZE)
|
||||
ret = arena_malloc(usize, zero);
|
||||
else {
|
||||
size_t run_size
|
||||
#ifdef JEMALLOC_CC_SILENCE
|
||||
= 0
|
||||
#endif
|
||||
;
|
||||
size_t run_size = 0;
|
||||
|
||||
/*
|
||||
* Ideally we would only ever call sa2u() once per aligned
|
||||
|
||||
@@ -1,195 +0,0 @@
|
||||
#define arena_bin_index JEMALLOC_N(arena_bin_index)
|
||||
#define arena_boot JEMALLOC_N(arena_boot)
|
||||
#define arena_dalloc JEMALLOC_N(arena_dalloc)
|
||||
#define arena_dalloc_bin JEMALLOC_N(arena_dalloc_bin)
|
||||
#define arena_dalloc_large JEMALLOC_N(arena_dalloc_large)
|
||||
#define arena_malloc JEMALLOC_N(arena_malloc)
|
||||
#define arena_malloc_large JEMALLOC_N(arena_malloc_large)
|
||||
#define arena_malloc_small JEMALLOC_N(arena_malloc_small)
|
||||
#define arena_new JEMALLOC_N(arena_new)
|
||||
#define arena_palloc JEMALLOC_N(arena_palloc)
|
||||
#define arena_prof_accum JEMALLOC_N(arena_prof_accum)
|
||||
#define arena_prof_ctx_get JEMALLOC_N(arena_prof_ctx_get)
|
||||
#define arena_prof_ctx_set JEMALLOC_N(arena_prof_ctx_set)
|
||||
#define arena_prof_promoted JEMALLOC_N(arena_prof_promoted)
|
||||
#define arena_purge_all JEMALLOC_N(arena_purge_all)
|
||||
#define arena_ralloc JEMALLOC_N(arena_ralloc)
|
||||
#define arena_ralloc_no_move JEMALLOC_N(arena_ralloc_no_move)
|
||||
#define arena_run_regind JEMALLOC_N(arena_run_regind)
|
||||
#define arena_salloc JEMALLOC_N(arena_salloc)
|
||||
#define arena_salloc_demote JEMALLOC_N(arena_salloc_demote)
|
||||
#define arena_stats_merge JEMALLOC_N(arena_stats_merge)
|
||||
#define arena_tcache_fill_small JEMALLOC_N(arena_tcache_fill_small)
|
||||
#define arenas_bin_i_index JEMALLOC_N(arenas_bin_i_index)
|
||||
#define arenas_extend JEMALLOC_N(arenas_extend)
|
||||
#define arenas_lrun_i_index JEMALLOC_N(arenas_lrun_i_index)
|
||||
#define atomic_add_uint32 JEMALLOC_N(atomic_add_uint32)
|
||||
#define atomic_add_uint64 JEMALLOC_N(atomic_add_uint64)
|
||||
#define atomic_sub_uint32 JEMALLOC_N(atomic_sub_uint32)
|
||||
#define atomic_sub_uint64 JEMALLOC_N(atomic_sub_uint64)
|
||||
#define base_alloc JEMALLOC_N(base_alloc)
|
||||
#define base_boot JEMALLOC_N(base_boot)
|
||||
#define base_node_alloc JEMALLOC_N(base_node_alloc)
|
||||
#define base_node_dealloc JEMALLOC_N(base_node_dealloc)
|
||||
#define bitmap_full JEMALLOC_N(bitmap_full)
|
||||
#define bitmap_get JEMALLOC_N(bitmap_get)
|
||||
#define bitmap_info_init JEMALLOC_N(bitmap_info_init)
|
||||
#define bitmap_info_ngroups JEMALLOC_N(bitmap_info_ngroups)
|
||||
#define bitmap_init JEMALLOC_N(bitmap_init)
|
||||
#define bitmap_set JEMALLOC_N(bitmap_set)
|
||||
#define bitmap_sfu JEMALLOC_N(bitmap_sfu)
|
||||
#define bitmap_size JEMALLOC_N(bitmap_size)
|
||||
#define bitmap_unset JEMALLOC_N(bitmap_unset)
|
||||
#define bt_init JEMALLOC_N(bt_init)
|
||||
#define buferror JEMALLOC_N(buferror)
|
||||
#define choose_arena JEMALLOC_N(choose_arena)
|
||||
#define choose_arena_hard JEMALLOC_N(choose_arena_hard)
|
||||
#define chunk_alloc JEMALLOC_N(chunk_alloc)
|
||||
#define chunk_alloc_dss JEMALLOC_N(chunk_alloc_dss)
|
||||
#define chunk_alloc_mmap JEMALLOC_N(chunk_alloc_mmap)
|
||||
#define chunk_alloc_mmap_noreserve JEMALLOC_N(chunk_alloc_mmap_noreserve)
|
||||
#define chunk_alloc_swap JEMALLOC_N(chunk_alloc_swap)
|
||||
#define chunk_boot JEMALLOC_N(chunk_boot)
|
||||
#define chunk_dealloc JEMALLOC_N(chunk_dealloc)
|
||||
#define chunk_dealloc_dss JEMALLOC_N(chunk_dealloc_dss)
|
||||
#define chunk_dealloc_mmap JEMALLOC_N(chunk_dealloc_mmap)
|
||||
#define chunk_dealloc_swap JEMALLOC_N(chunk_dealloc_swap)
|
||||
#define chunk_dss_boot JEMALLOC_N(chunk_dss_boot)
|
||||
#define chunk_in_dss JEMALLOC_N(chunk_in_dss)
|
||||
#define chunk_in_swap JEMALLOC_N(chunk_in_swap)
|
||||
#define chunk_mmap_boot JEMALLOC_N(chunk_mmap_boot)
|
||||
#define chunk_swap_boot JEMALLOC_N(chunk_swap_boot)
|
||||
#define chunk_swap_enable JEMALLOC_N(chunk_swap_enable)
|
||||
#define ckh_bucket_search JEMALLOC_N(ckh_bucket_search)
|
||||
#define ckh_count JEMALLOC_N(ckh_count)
|
||||
#define ckh_delete JEMALLOC_N(ckh_delete)
|
||||
#define ckh_evict_reloc_insert JEMALLOC_N(ckh_evict_reloc_insert)
|
||||
#define ckh_insert JEMALLOC_N(ckh_insert)
|
||||
#define ckh_isearch JEMALLOC_N(ckh_isearch)
|
||||
#define ckh_iter JEMALLOC_N(ckh_iter)
|
||||
#define ckh_new JEMALLOC_N(ckh_new)
|
||||
#define ckh_pointer_hash JEMALLOC_N(ckh_pointer_hash)
|
||||
#define ckh_pointer_keycomp JEMALLOC_N(ckh_pointer_keycomp)
|
||||
#define ckh_rebuild JEMALLOC_N(ckh_rebuild)
|
||||
#define ckh_remove JEMALLOC_N(ckh_remove)
|
||||
#define ckh_search JEMALLOC_N(ckh_search)
|
||||
#define ckh_string_hash JEMALLOC_N(ckh_string_hash)
|
||||
#define ckh_string_keycomp JEMALLOC_N(ckh_string_keycomp)
|
||||
#define ckh_try_bucket_insert JEMALLOC_N(ckh_try_bucket_insert)
|
||||
#define ckh_try_insert JEMALLOC_N(ckh_try_insert)
|
||||
#define create_zone JEMALLOC_N(create_zone)
|
||||
#define ctl_boot JEMALLOC_N(ctl_boot)
|
||||
#define ctl_bymib JEMALLOC_N(ctl_bymib)
|
||||
#define ctl_byname JEMALLOC_N(ctl_byname)
|
||||
#define ctl_nametomib JEMALLOC_N(ctl_nametomib)
|
||||
#define extent_tree_ad_first JEMALLOC_N(extent_tree_ad_first)
|
||||
#define extent_tree_ad_insert JEMALLOC_N(extent_tree_ad_insert)
|
||||
#define extent_tree_ad_iter JEMALLOC_N(extent_tree_ad_iter)
|
||||
#define extent_tree_ad_iter_recurse JEMALLOC_N(extent_tree_ad_iter_recurse)
|
||||
#define extent_tree_ad_iter_start JEMALLOC_N(extent_tree_ad_iter_start)
|
||||
#define extent_tree_ad_last JEMALLOC_N(extent_tree_ad_last)
|
||||
#define extent_tree_ad_new JEMALLOC_N(extent_tree_ad_new)
|
||||
#define extent_tree_ad_next JEMALLOC_N(extent_tree_ad_next)
|
||||
#define extent_tree_ad_nsearch JEMALLOC_N(extent_tree_ad_nsearch)
|
||||
#define extent_tree_ad_prev JEMALLOC_N(extent_tree_ad_prev)
|
||||
#define extent_tree_ad_psearch JEMALLOC_N(extent_tree_ad_psearch)
|
||||
#define extent_tree_ad_remove JEMALLOC_N(extent_tree_ad_remove)
|
||||
#define extent_tree_ad_reverse_iter JEMALLOC_N(extent_tree_ad_reverse_iter)
|
||||
#define extent_tree_ad_reverse_iter_recurse JEMALLOC_N(extent_tree_ad_reverse_iter_recurse)
|
||||
#define extent_tree_ad_reverse_iter_start JEMALLOC_N(extent_tree_ad_reverse_iter_start)
|
||||
#define extent_tree_ad_search JEMALLOC_N(extent_tree_ad_search)
|
||||
#define extent_tree_szad_first JEMALLOC_N(extent_tree_szad_first)
|
||||
#define extent_tree_szad_insert JEMALLOC_N(extent_tree_szad_insert)
|
||||
#define extent_tree_szad_iter JEMALLOC_N(extent_tree_szad_iter)
|
||||
#define extent_tree_szad_iter_recurse JEMALLOC_N(extent_tree_szad_iter_recurse)
|
||||
#define extent_tree_szad_iter_start JEMALLOC_N(extent_tree_szad_iter_start)
|
||||
#define extent_tree_szad_last JEMALLOC_N(extent_tree_szad_last)
|
||||
#define extent_tree_szad_new JEMALLOC_N(extent_tree_szad_new)
|
||||
#define extent_tree_szad_next JEMALLOC_N(extent_tree_szad_next)
|
||||
#define extent_tree_szad_nsearch JEMALLOC_N(extent_tree_szad_nsearch)
|
||||
#define extent_tree_szad_prev JEMALLOC_N(extent_tree_szad_prev)
|
||||
#define extent_tree_szad_psearch JEMALLOC_N(extent_tree_szad_psearch)
|
||||
#define extent_tree_szad_remove JEMALLOC_N(extent_tree_szad_remove)
|
||||
#define extent_tree_szad_reverse_iter JEMALLOC_N(extent_tree_szad_reverse_iter)
|
||||
#define extent_tree_szad_reverse_iter_recurse JEMALLOC_N(extent_tree_szad_reverse_iter_recurse)
|
||||
#define extent_tree_szad_reverse_iter_start JEMALLOC_N(extent_tree_szad_reverse_iter_start)
|
||||
#define extent_tree_szad_search JEMALLOC_N(extent_tree_szad_search)
|
||||
#define hash JEMALLOC_N(hash)
|
||||
#define huge_boot JEMALLOC_N(huge_boot)
|
||||
#define huge_dalloc JEMALLOC_N(huge_dalloc)
|
||||
#define huge_malloc JEMALLOC_N(huge_malloc)
|
||||
#define huge_palloc JEMALLOC_N(huge_palloc)
|
||||
#define huge_prof_ctx_get JEMALLOC_N(huge_prof_ctx_get)
|
||||
#define huge_prof_ctx_set JEMALLOC_N(huge_prof_ctx_set)
|
||||
#define huge_ralloc JEMALLOC_N(huge_ralloc)
|
||||
#define huge_ralloc_no_move JEMALLOC_N(huge_ralloc_no_move)
|
||||
#define huge_salloc JEMALLOC_N(huge_salloc)
|
||||
#define iallocm JEMALLOC_N(iallocm)
|
||||
#define icalloc JEMALLOC_N(icalloc)
|
||||
#define idalloc JEMALLOC_N(idalloc)
|
||||
#define imalloc JEMALLOC_N(imalloc)
|
||||
#define ipalloc JEMALLOC_N(ipalloc)
|
||||
#define iralloc JEMALLOC_N(iralloc)
|
||||
#define isalloc JEMALLOC_N(isalloc)
|
||||
#define ivsalloc JEMALLOC_N(ivsalloc)
|
||||
#define jemalloc_darwin_init JEMALLOC_N(jemalloc_darwin_init)
|
||||
#define jemalloc_postfork JEMALLOC_N(jemalloc_postfork)
|
||||
#define jemalloc_prefork JEMALLOC_N(jemalloc_prefork)
|
||||
#define malloc_cprintf JEMALLOC_N(malloc_cprintf)
|
||||
#define malloc_mutex_destroy JEMALLOC_N(malloc_mutex_destroy)
|
||||
#define malloc_mutex_init JEMALLOC_N(malloc_mutex_init)
|
||||
#define malloc_mutex_lock JEMALLOC_N(malloc_mutex_lock)
|
||||
#define malloc_mutex_trylock JEMALLOC_N(malloc_mutex_trylock)
|
||||
#define malloc_mutex_unlock JEMALLOC_N(malloc_mutex_unlock)
|
||||
#define malloc_printf JEMALLOC_N(malloc_printf)
|
||||
#define malloc_write JEMALLOC_N(malloc_write)
|
||||
#define mb_write JEMALLOC_N(mb_write)
|
||||
#define pow2_ceil JEMALLOC_N(pow2_ceil)
|
||||
#define prof_backtrace JEMALLOC_N(prof_backtrace)
|
||||
#define prof_boot0 JEMALLOC_N(prof_boot0)
|
||||
#define prof_boot1 JEMALLOC_N(prof_boot1)
|
||||
#define prof_boot2 JEMALLOC_N(prof_boot2)
|
||||
#define prof_ctx_get JEMALLOC_N(prof_ctx_get)
|
||||
#define prof_ctx_set JEMALLOC_N(prof_ctx_set)
|
||||
#define prof_free JEMALLOC_N(prof_free)
|
||||
#define prof_gdump JEMALLOC_N(prof_gdump)
|
||||
#define prof_idump JEMALLOC_N(prof_idump)
|
||||
#define prof_lookup JEMALLOC_N(prof_lookup)
|
||||
#define prof_malloc JEMALLOC_N(prof_malloc)
|
||||
#define prof_mdump JEMALLOC_N(prof_mdump)
|
||||
#define prof_realloc JEMALLOC_N(prof_realloc)
|
||||
#define prof_sample_accum_update JEMALLOC_N(prof_sample_accum_update)
|
||||
#define prof_sample_threshold_update JEMALLOC_N(prof_sample_threshold_update)
|
||||
#define prof_tdata_init JEMALLOC_N(prof_tdata_init)
|
||||
#define pthread_create JEMALLOC_N(pthread_create)
|
||||
#define rtree_get JEMALLOC_N(rtree_get)
|
||||
#define rtree_get_locked JEMALLOC_N(rtree_get_locked)
|
||||
#define rtree_new JEMALLOC_N(rtree_new)
|
||||
#define rtree_set JEMALLOC_N(rtree_set)
|
||||
#define s2u JEMALLOC_N(s2u)
|
||||
#define sa2u JEMALLOC_N(sa2u)
|
||||
#define stats_arenas_i_bins_j_index JEMALLOC_N(stats_arenas_i_bins_j_index)
|
||||
#define stats_arenas_i_index JEMALLOC_N(stats_arenas_i_index)
|
||||
#define stats_arenas_i_lruns_j_index JEMALLOC_N(stats_arenas_i_lruns_j_index)
|
||||
#define stats_cactive_add JEMALLOC_N(stats_cactive_add)
|
||||
#define stats_cactive_get JEMALLOC_N(stats_cactive_get)
|
||||
#define stats_cactive_sub JEMALLOC_N(stats_cactive_sub)
|
||||
#define stats_print JEMALLOC_N(stats_print)
|
||||
#define szone2ozone JEMALLOC_N(szone2ozone)
|
||||
#define tcache_alloc_easy JEMALLOC_N(tcache_alloc_easy)
|
||||
#define tcache_alloc_large JEMALLOC_N(tcache_alloc_large)
|
||||
#define tcache_alloc_small JEMALLOC_N(tcache_alloc_small)
|
||||
#define tcache_alloc_small_hard JEMALLOC_N(tcache_alloc_small_hard)
|
||||
#define tcache_bin_flush_large JEMALLOC_N(tcache_bin_flush_large)
|
||||
#define tcache_bin_flush_small JEMALLOC_N(tcache_bin_flush_small)
|
||||
#define tcache_boot JEMALLOC_N(tcache_boot)
|
||||
#define tcache_create JEMALLOC_N(tcache_create)
|
||||
#define tcache_dalloc_large JEMALLOC_N(tcache_dalloc_large)
|
||||
#define tcache_dalloc_small JEMALLOC_N(tcache_dalloc_small)
|
||||
#define tcache_destroy JEMALLOC_N(tcache_destroy)
|
||||
#define tcache_event JEMALLOC_N(tcache_event)
|
||||
#define tcache_get JEMALLOC_N(tcache_get)
|
||||
#define tcache_stats_merge JEMALLOC_N(tcache_stats_merge)
|
||||
#define thread_allocated_get JEMALLOC_N(thread_allocated_get)
|
||||
#define thread_allocated_get_hard JEMALLOC_N(thread_allocated_get_hard)
|
||||
#define u2s JEMALLOC_N(u2s)
|
||||
+68
-54
@@ -227,60 +227,9 @@ bool prof_boot2(void);
|
||||
/******************************************************************************/
|
||||
#ifdef JEMALLOC_H_INLINES
|
||||
|
||||
#define PROF_ALLOC_PREP(nignore, size, ret) do { \
|
||||
prof_tdata_t *prof_tdata; \
|
||||
prof_bt_t bt; \
|
||||
\
|
||||
assert(size == s2u(size)); \
|
||||
\
|
||||
prof_tdata = PROF_TCACHE_GET(); \
|
||||
if (prof_tdata == NULL) { \
|
||||
prof_tdata = prof_tdata_init(); \
|
||||
if (prof_tdata == NULL) { \
|
||||
ret = NULL; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (opt_prof_active == false) { \
|
||||
/* Sampling is currently inactive, so avoid sampling. */\
|
||||
ret = (prof_thr_cnt_t *)(uintptr_t)1U; \
|
||||
} else if (opt_lg_prof_sample == 0) { \
|
||||
/* Don't bother with sampling logic, since sampling */\
|
||||
/* interval is 1. */\
|
||||
bt_init(&bt, prof_tdata->vec); \
|
||||
prof_backtrace(&bt, nignore, prof_bt_max); \
|
||||
ret = prof_lookup(&bt); \
|
||||
} else { \
|
||||
if (prof_tdata->threshold == 0) { \
|
||||
/* Initialize. Seed the prng differently for */\
|
||||
/* each thread. */\
|
||||
prof_tdata->prn_state = \
|
||||
(uint64_t)(uintptr_t)&size; \
|
||||
prof_sample_threshold_update(prof_tdata); \
|
||||
} \
|
||||
\
|
||||
/* Determine whether to capture a backtrace based on */\
|
||||
/* whether size is enough for prof_accum to reach */\
|
||||
/* prof_tdata->threshold. However, delay updating */\
|
||||
/* these variables until prof_{m,re}alloc(), because */\
|
||||
/* we don't know for sure that the allocation will */\
|
||||
/* succeed. */\
|
||||
/* */\
|
||||
/* Use subtraction rather than addition to avoid */\
|
||||
/* potential integer overflow. */\
|
||||
if (size >= prof_tdata->threshold - \
|
||||
prof_tdata->accum) { \
|
||||
bt_init(&bt, prof_tdata->vec); \
|
||||
prof_backtrace(&bt, nignore, prof_bt_max); \
|
||||
ret = prof_lookup(&bt); \
|
||||
} else \
|
||||
ret = (prof_thr_cnt_t *)(uintptr_t)1U; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifndef JEMALLOC_ENABLE_INLINE
|
||||
void prof_sample_threshold_update(prof_tdata_t *prof_tdata);
|
||||
prof_thr_cnt_t *prof_alloc_prep(size_t size);
|
||||
prof_ctx_t *prof_ctx_get(const void *ptr);
|
||||
void prof_ctx_set(const void *ptr, prof_ctx_t *ctx);
|
||||
bool prof_sample_accum_update(size_t size);
|
||||
@@ -323,6 +272,71 @@ prof_sample_threshold_update(prof_tdata_t *prof_tdata)
|
||||
+ (uint64_t)1U;
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE prof_thr_cnt_t *
|
||||
prof_alloc_prep(size_t size)
|
||||
{
|
||||
#ifdef JEMALLOC_ENABLE_INLINE
|
||||
/* This function does not have its own stack frame, because it is inlined. */
|
||||
# define NIGNORE 1
|
||||
#else
|
||||
# define NIGNORE 2
|
||||
#endif
|
||||
prof_thr_cnt_t *ret;
|
||||
prof_tdata_t *prof_tdata;
|
||||
prof_bt_t bt;
|
||||
|
||||
assert(size == s2u(size));
|
||||
|
||||
prof_tdata = PROF_TCACHE_GET();
|
||||
if (prof_tdata == NULL) {
|
||||
prof_tdata = prof_tdata_init();
|
||||
if (prof_tdata == NULL)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (opt_prof_active == false) {
|
||||
/* Sampling is currently inactive, so avoid sampling. */
|
||||
ret = (prof_thr_cnt_t *)(uintptr_t)1U;
|
||||
} else if (opt_lg_prof_sample == 0) {
|
||||
/*
|
||||
* Don't bother with sampling logic, since sampling interval is
|
||||
* 1.
|
||||
*/
|
||||
bt_init(&bt, prof_tdata->vec);
|
||||
prof_backtrace(&bt, NIGNORE, prof_bt_max);
|
||||
ret = prof_lookup(&bt);
|
||||
} else {
|
||||
if (prof_tdata->threshold == 0) {
|
||||
/*
|
||||
* Initialize. Seed the prng differently for each
|
||||
* thread.
|
||||
*/
|
||||
prof_tdata->prn_state = (uint64_t)(uintptr_t)&size;
|
||||
prof_sample_threshold_update(prof_tdata);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine whether to capture a backtrace based on whether
|
||||
* size is enough for prof_accum to reach
|
||||
* prof_tdata->threshold. However, delay updating these
|
||||
* variables until prof_{m,re}alloc(), because we don't know
|
||||
* for sure that the allocation will succeed.
|
||||
*
|
||||
* Use subtraction rather than addition to avoid potential
|
||||
* integer overflow.
|
||||
*/
|
||||
if (size >= prof_tdata->threshold - prof_tdata->accum) {
|
||||
bt_init(&bt, prof_tdata->vec);
|
||||
prof_backtrace(&bt, NIGNORE, prof_bt_max);
|
||||
ret = prof_lookup(&bt);
|
||||
} else
|
||||
ret = (prof_thr_cnt_t *)(uintptr_t)1U;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
#undef NIGNORE
|
||||
}
|
||||
|
||||
JEMALLOC_INLINE prof_ctx_t *
|
||||
prof_ctx_get(const void *ptr)
|
||||
{
|
||||
@@ -401,7 +415,7 @@ prof_malloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt)
|
||||
* always possible to tell in advance how large an
|
||||
* object's usable size will be, so there should never
|
||||
* be a difference between the size passed to
|
||||
* PROF_ALLOC_PREP() and prof_malloc().
|
||||
* prof_alloc_prep() and prof_malloc().
|
||||
*/
|
||||
assert((uintptr_t)cnt == (uintptr_t)1U);
|
||||
}
|
||||
@@ -445,7 +459,7 @@ prof_realloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt,
|
||||
if (prof_sample_accum_update(size)) {
|
||||
/*
|
||||
* Don't sample. The size passed to
|
||||
* PROF_ALLOC_PREP() was larger than what
|
||||
* prof_alloc_prep() was larger than what
|
||||
* actually got allocated, so a backtrace was
|
||||
* captured for this allocation, even though
|
||||
* its actual size was insufficient to cross
|
||||
|
||||
@@ -18,15 +18,6 @@
|
||||
#undef JEMALLOC_P
|
||||
#endif
|
||||
|
||||
/*
|
||||
* JEMALLOC_PRIVATE_NAMESPACE is used as a prefix for all library-private APIs.
|
||||
* For shared libraries, symbol visibility mechanisms prevent these symbols
|
||||
* from being exported, but for static libraries, naming collisions are a real
|
||||
* possibility.
|
||||
*/
|
||||
#undef JEMALLOC_PRIVATE_NAMESPACE
|
||||
#undef JEMALLOC_N
|
||||
|
||||
/*
|
||||
* Hyper-threaded CPUs may need a special instruction inside spin loops in
|
||||
* order to yield to another virtual CPU.
|
||||
|
||||
Vendored
+3
-4
@@ -569,7 +569,7 @@ arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk)
|
||||
arena->ndirty -= spare->ndirty;
|
||||
}
|
||||
malloc_mutex_unlock(&arena->lock);
|
||||
chunk_dealloc((void *)spare, chunksize, true);
|
||||
chunk_dealloc((void *)spare, chunksize);
|
||||
malloc_mutex_lock(&arena->lock);
|
||||
#ifdef JEMALLOC_STATS
|
||||
arena->stats.mapped -= chunksize;
|
||||
@@ -869,9 +869,9 @@ arena_purge(arena_t *arena, bool all)
|
||||
assert(ndirty == arena->ndirty);
|
||||
#endif
|
||||
assert(arena->ndirty > arena->npurgatory || all);
|
||||
assert(arena->ndirty - arena->npurgatory > chunk_npages || all);
|
||||
assert(arena->ndirty > chunk_npages || all);
|
||||
assert((arena->nactive >> opt_lg_dirty_mult) < (arena->ndirty -
|
||||
arena->npurgatory) || all);
|
||||
npurgatory) || all);
|
||||
|
||||
#ifdef JEMALLOC_STATS
|
||||
arena->stats.npurge++;
|
||||
@@ -1657,7 +1657,6 @@ arena_prof_promoted(const void *ptr, size_t size)
|
||||
assert(ptr != NULL);
|
||||
assert(CHUNK_ADDR2BASE(ptr) != ptr);
|
||||
assert(isalloc(ptr) == PAGE_SIZE);
|
||||
assert(size <= small_maxclass);
|
||||
|
||||
chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
|
||||
pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT;
|
||||
|
||||
Vendored
+7
-9
@@ -70,7 +70,7 @@ RETURN:
|
||||
#ifdef JEMALLOC_IVSALLOC
|
||||
if (base == false && ret != NULL) {
|
||||
if (rtree_set(chunks_rtree, (uintptr_t)ret, ret)) {
|
||||
chunk_dealloc(ret, size, true);
|
||||
chunk_dealloc(ret, size);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
@@ -108,7 +108,7 @@ RETURN:
|
||||
}
|
||||
|
||||
void
|
||||
chunk_dealloc(void *chunk, size_t size, bool unmap)
|
||||
chunk_dealloc(void *chunk, size_t size)
|
||||
{
|
||||
|
||||
assert(chunk != NULL);
|
||||
@@ -125,17 +125,15 @@ chunk_dealloc(void *chunk, size_t size, bool unmap)
|
||||
malloc_mutex_unlock(&chunks_mtx);
|
||||
#endif
|
||||
|
||||
if (unmap) {
|
||||
#ifdef JEMALLOC_SWAP
|
||||
if (swap_enabled && chunk_dealloc_swap(chunk, size) == false)
|
||||
return;
|
||||
if (swap_enabled && chunk_dealloc_swap(chunk, size) == false)
|
||||
return;
|
||||
#endif
|
||||
#ifdef JEMALLOC_DSS
|
||||
if (chunk_dealloc_dss(chunk, size) == false)
|
||||
return;
|
||||
if (chunk_dealloc_dss(chunk, size) == false)
|
||||
return;
|
||||
#endif
|
||||
chunk_dealloc_mmap(chunk, size);
|
||||
}
|
||||
chunk_dealloc_mmap(chunk, size);
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
Vendored
+1
-1
@@ -556,7 +556,7 @@ ckh_string_hash(const void *key, unsigned minbits, size_t *hash1, size_t *hash2)
|
||||
} else {
|
||||
ret1 = h;
|
||||
ret2 = hash(key, strlen((const char *)key),
|
||||
0x8432a476666bbc13LLU);
|
||||
0x8432a476666bbc13U);
|
||||
}
|
||||
|
||||
*hash1 = ret1;
|
||||
|
||||
Vendored
-2
@@ -1151,13 +1151,11 @@ thread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
|
||||
|
||||
/* Set new arena association. */
|
||||
ARENA_SET(arena);
|
||||
#ifdef JEMALLOC_TCACHE
|
||||
{
|
||||
tcache_t *tcache = TCACHE_GET();
|
||||
if (tcache != NULL)
|
||||
tcache->arena = arena;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
Vendored
+7
-14
@@ -110,12 +110,12 @@ huge_palloc(size_t size, size_t alignment, bool zero)
|
||||
if (offset == 0) {
|
||||
/* Trim trailing space. */
|
||||
chunk_dealloc((void *)((uintptr_t)ret + chunk_size), alloc_size
|
||||
- chunk_size, true);
|
||||
- chunk_size);
|
||||
} else {
|
||||
size_t trailsize;
|
||||
|
||||
/* Trim leading space. */
|
||||
chunk_dealloc(ret, alignment - offset, true);
|
||||
chunk_dealloc(ret, alignment - offset);
|
||||
|
||||
ret = (void *)((uintptr_t)ret + (alignment - offset));
|
||||
|
||||
@@ -124,7 +124,7 @@ huge_palloc(size_t size, size_t alignment, bool zero)
|
||||
/* Trim trailing space. */
|
||||
assert(trailsize < alloc_size);
|
||||
chunk_dealloc((void *)((uintptr_t)ret + chunk_size),
|
||||
trailsize, true);
|
||||
trailsize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,13 +234,6 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
|
||||
) {
|
||||
size_t newsize = huge_salloc(ret);
|
||||
|
||||
/*
|
||||
* Remove ptr from the tree of huge allocations before
|
||||
* performing the remap operation, in order to avoid the
|
||||
* possibility of another thread acquiring that mapping before
|
||||
* this one removes it from the tree.
|
||||
*/
|
||||
huge_dalloc(ptr, false);
|
||||
if (mremap(ptr, oldsize, newsize, MREMAP_MAYMOVE|MREMAP_FIXED,
|
||||
ret) == MAP_FAILED) {
|
||||
/*
|
||||
@@ -260,8 +253,9 @@ huge_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra,
|
||||
if (opt_abort)
|
||||
abort();
|
||||
memcpy(ret, ptr, copysize);
|
||||
chunk_dealloc_mmap(ptr, oldsize);
|
||||
}
|
||||
idalloc(ptr);
|
||||
} else
|
||||
huge_dalloc(ptr, false);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@@ -301,10 +295,9 @@ huge_dalloc(void *ptr, bool unmap)
|
||||
memset(node->addr, 0x5a, node->size);
|
||||
#endif
|
||||
#endif
|
||||
chunk_dealloc(node->addr, node->size);
|
||||
}
|
||||
|
||||
chunk_dealloc(node->addr, node->size, unmap);
|
||||
|
||||
base_node_dealloc(node);
|
||||
}
|
||||
|
||||
|
||||
Vendored
+32
-66
@@ -84,7 +84,6 @@ static void malloc_conf_error(const char *msg, const char *k, size_t klen,
|
||||
const char *v, size_t vlen);
|
||||
static void malloc_conf_init(void);
|
||||
static bool malloc_init_hard(void);
|
||||
static int imemalign(void **memptr, size_t alignment, size_t size);
|
||||
|
||||
/******************************************************************************/
|
||||
/* malloc_message() setup. */
|
||||
@@ -689,7 +688,7 @@ malloc_init_hard(void)
|
||||
|
||||
result = sysconf(_SC_PAGESIZE);
|
||||
assert(result != -1);
|
||||
pagesize = (size_t)result;
|
||||
pagesize = (unsigned)result;
|
||||
|
||||
/*
|
||||
* We assume that pagesize is a power of 2 when calculating
|
||||
@@ -769,14 +768,6 @@ malloc_init_hard(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (malloc_mutex_init(&arenas_lock))
|
||||
return (true);
|
||||
|
||||
if (pthread_key_create(&arenas_tsd, arenas_cleanup) != 0) {
|
||||
malloc_mutex_unlock(&init_lock);
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create enough scaffolding to allow recursive allocation in
|
||||
* malloc_ncpus().
|
||||
@@ -803,6 +794,14 @@ malloc_init_hard(void)
|
||||
ARENA_SET(arenas[0]);
|
||||
arenas[0]->nthreads++;
|
||||
|
||||
if (malloc_mutex_init(&arenas_lock))
|
||||
return (true);
|
||||
|
||||
if (pthread_key_create(&arenas_tsd, arenas_cleanup) != 0) {
|
||||
malloc_mutex_unlock(&init_lock);
|
||||
return (true);
|
||||
}
|
||||
|
||||
#ifdef JEMALLOC_PROF
|
||||
if (prof_boot2()) {
|
||||
malloc_mutex_unlock(&init_lock);
|
||||
@@ -940,8 +939,7 @@ JEMALLOC_P(malloc)(size_t size)
|
||||
#ifdef JEMALLOC_PROF
|
||||
if (opt_prof) {
|
||||
usize = s2u(size);
|
||||
PROF_ALLOC_PREP(1, usize, cnt);
|
||||
if (cnt == NULL) {
|
||||
if ((cnt = prof_alloc_prep(usize)) == NULL) {
|
||||
ret = NULL;
|
||||
goto OOM;
|
||||
}
|
||||
@@ -990,15 +988,9 @@ RETURN:
|
||||
}
|
||||
|
||||
JEMALLOC_ATTR(nonnull(1))
|
||||
#ifdef JEMALLOC_PROF
|
||||
/*
|
||||
* Avoid any uncertainty as to how many backtrace frames to ignore in
|
||||
* PROF_ALLOC_PREP().
|
||||
*/
|
||||
JEMALLOC_ATTR(noinline)
|
||||
#endif
|
||||
static int
|
||||
imemalign(void **memptr, size_t alignment, size_t size)
|
||||
JEMALLOC_ATTR(visibility("default"))
|
||||
int
|
||||
JEMALLOC_P(posix_memalign)(void **memptr, size_t alignment, size_t size)
|
||||
{
|
||||
int ret;
|
||||
size_t usize
|
||||
@@ -1065,8 +1057,7 @@ imemalign(void **memptr, size_t alignment, size_t size)
|
||||
|
||||
#ifdef JEMALLOC_PROF
|
||||
if (opt_prof) {
|
||||
PROF_ALLOC_PREP(2, usize, cnt);
|
||||
if (cnt == NULL) {
|
||||
if ((cnt = prof_alloc_prep(usize)) == NULL) {
|
||||
result = NULL;
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
@@ -1119,15 +1110,6 @@ RETURN:
|
||||
return (ret);
|
||||
}
|
||||
|
||||
JEMALLOC_ATTR(nonnull(1))
|
||||
JEMALLOC_ATTR(visibility("default"))
|
||||
int
|
||||
JEMALLOC_P(posix_memalign)(void **memptr, size_t alignment, size_t size)
|
||||
{
|
||||
|
||||
return imemalign(memptr, alignment, size);
|
||||
}
|
||||
|
||||
JEMALLOC_ATTR(malloc)
|
||||
JEMALLOC_ATTR(visibility("default"))
|
||||
void *
|
||||
@@ -1183,8 +1165,7 @@ JEMALLOC_P(calloc)(size_t num, size_t size)
|
||||
#ifdef JEMALLOC_PROF
|
||||
if (opt_prof) {
|
||||
usize = s2u(num_size);
|
||||
PROF_ALLOC_PREP(1, usize, cnt);
|
||||
if (cnt == NULL) {
|
||||
if ((cnt = prof_alloc_prep(usize)) == NULL) {
|
||||
ret = NULL;
|
||||
goto RETURN;
|
||||
}
|
||||
@@ -1297,9 +1278,7 @@ JEMALLOC_P(realloc)(void *ptr, size_t size)
|
||||
if (opt_prof) {
|
||||
usize = s2u(size);
|
||||
old_ctx = prof_ctx_get(ptr);
|
||||
PROF_ALLOC_PREP(1, usize, cnt);
|
||||
if (cnt == NULL) {
|
||||
old_ctx = NULL;
|
||||
if ((cnt = prof_alloc_prep(usize)) == NULL) {
|
||||
ret = NULL;
|
||||
goto OOM;
|
||||
}
|
||||
@@ -1309,13 +1288,8 @@ JEMALLOC_P(realloc)(void *ptr, size_t size)
|
||||
false, false);
|
||||
if (ret != NULL)
|
||||
arena_prof_promoted(ret, usize);
|
||||
else
|
||||
old_ctx = NULL;
|
||||
} else {
|
||||
} else
|
||||
ret = iralloc(ptr, size, 0, 0, false, false);
|
||||
if (ret == NULL)
|
||||
old_ctx = NULL;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@@ -1353,8 +1327,7 @@ OOM:
|
||||
#ifdef JEMALLOC_PROF
|
||||
if (opt_prof) {
|
||||
usize = s2u(size);
|
||||
PROF_ALLOC_PREP(1, usize, cnt);
|
||||
if (cnt == NULL)
|
||||
if ((cnt = prof_alloc_prep(usize)) == NULL)
|
||||
ret = NULL;
|
||||
else {
|
||||
if (prof_promote && (uintptr_t)cnt !=
|
||||
@@ -1459,7 +1432,7 @@ JEMALLOC_P(memalign)(size_t alignment, size_t size)
|
||||
#ifdef JEMALLOC_CC_SILENCE
|
||||
int result =
|
||||
#endif
|
||||
imemalign(&ret, alignment, size);
|
||||
JEMALLOC_P(posix_memalign)(&ret, alignment, size);
|
||||
#ifdef JEMALLOC_CC_SILENCE
|
||||
if (result != 0)
|
||||
return (NULL);
|
||||
@@ -1478,7 +1451,7 @@ JEMALLOC_P(valloc)(size_t size)
|
||||
#ifdef JEMALLOC_CC_SILENCE
|
||||
int result =
|
||||
#endif
|
||||
imemalign(&ret, PAGE_SIZE, size);
|
||||
JEMALLOC_P(posix_memalign)(&ret, PAGE_SIZE, size);
|
||||
#ifdef JEMALLOC_CC_SILENCE
|
||||
if (result != 0)
|
||||
return (NULL);
|
||||
@@ -1593,14 +1566,14 @@ JEMALLOC_P(allocm)(void **ptr, size_t *rsize, size_t size, int flags)
|
||||
if (malloc_init())
|
||||
goto OOM;
|
||||
|
||||
usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment, NULL);
|
||||
usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment,
|
||||
NULL);
|
||||
if (usize == 0)
|
||||
goto OOM;
|
||||
|
||||
#ifdef JEMALLOC_PROF
|
||||
if (opt_prof) {
|
||||
PROF_ALLOC_PREP(1, usize, cnt);
|
||||
if (cnt == NULL)
|
||||
if ((cnt = prof_alloc_prep(usize)) == NULL)
|
||||
goto OOM;
|
||||
if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize <=
|
||||
small_maxclass) {
|
||||
@@ -1617,7 +1590,7 @@ JEMALLOC_P(allocm)(void **ptr, size_t *rsize, size_t size, int flags)
|
||||
if (p == NULL)
|
||||
goto OOM;
|
||||
}
|
||||
prof_malloc(p, usize, cnt);
|
||||
|
||||
if (rsize != NULL)
|
||||
*rsize = usize;
|
||||
} else
|
||||
@@ -1672,6 +1645,7 @@ JEMALLOC_P(rallocm)(void **ptr, size_t *rsize, size_t size, size_t extra,
|
||||
bool no_move = flags & ALLOCM_NO_MOVE;
|
||||
#ifdef JEMALLOC_PROF
|
||||
prof_thr_cnt_t *cnt;
|
||||
prof_ctx_t *old_ctx;
|
||||
#endif
|
||||
|
||||
assert(ptr != NULL);
|
||||
@@ -1686,33 +1660,25 @@ JEMALLOC_P(rallocm)(void **ptr, size_t *rsize, size_t size, size_t extra,
|
||||
/*
|
||||
* usize isn't knowable before iralloc() returns when extra is
|
||||
* non-zero. Therefore, compute its maximum possible value and
|
||||
* use that in PROF_ALLOC_PREP() to decide whether to capture a
|
||||
* use that in prof_alloc_prep() to decide whether to capture a
|
||||
* backtrace. prof_realloc() will use the actual usize to
|
||||
* decide whether to sample.
|
||||
*/
|
||||
size_t max_usize = (alignment == 0) ? s2u(size+extra) :
|
||||
sa2u(size+extra, alignment, NULL);
|
||||
prof_ctx_t *old_ctx = prof_ctx_get(p);
|
||||
old_size = isalloc(p);
|
||||
PROF_ALLOC_PREP(1, max_usize, cnt);
|
||||
if (cnt == NULL)
|
||||
old_ctx = prof_ctx_get(p);
|
||||
if ((cnt = prof_alloc_prep(max_usize)) == NULL)
|
||||
goto OOM;
|
||||
/*
|
||||
* Use minimum usize to determine whether promotion may happen.
|
||||
*/
|
||||
if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U
|
||||
&& ((alignment == 0) ? s2u(size) : sa2u(size,
|
||||
alignment, NULL)) <= small_maxclass) {
|
||||
if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && max_usize
|
||||
<= small_maxclass) {
|
||||
q = iralloc(p, small_maxclass+1, (small_maxclass+1 >=
|
||||
size+extra) ? 0 : size+extra - (small_maxclass+1),
|
||||
alignment, zero, no_move);
|
||||
if (q == NULL)
|
||||
goto ERR;
|
||||
if (max_usize < PAGE_SIZE) {
|
||||
usize = max_usize;
|
||||
arena_prof_promoted(q, usize);
|
||||
} else
|
||||
usize = isalloc(q);
|
||||
usize = isalloc(q);
|
||||
arena_prof_promoted(q, usize);
|
||||
} else {
|
||||
q = iralloc(p, size, extra, alignment, zero, no_move);
|
||||
if (q == NULL)
|
||||
|
||||
Vendored
+48
-49
@@ -474,23 +474,11 @@ prof_lookup(prof_bt_t *bt)
|
||||
/*
|
||||
* Artificially raise curobjs, in order to avoid a race
|
||||
* condition with prof_ctx_merge()/prof_ctx_destroy().
|
||||
*
|
||||
* No locking is necessary for ctx here because no other
|
||||
* threads have had the opportunity to fetch it from
|
||||
* bt2ctx yet.
|
||||
*/
|
||||
ctx.p->cnt_merged.curobjs++;
|
||||
new_ctx = true;
|
||||
} else {
|
||||
/*
|
||||
* Artificially raise curobjs, in order to avoid a race
|
||||
* condition with prof_ctx_merge()/prof_ctx_destroy().
|
||||
*/
|
||||
malloc_mutex_lock(&ctx.p->lock);
|
||||
ctx.p->cnt_merged.curobjs++;
|
||||
malloc_mutex_unlock(&ctx.p->lock);
|
||||
} else
|
||||
new_ctx = false;
|
||||
}
|
||||
prof_leave();
|
||||
|
||||
/* Link a prof_thd_cnt_t into ctx for this thread. */
|
||||
@@ -503,9 +491,8 @@ prof_lookup(prof_bt_t *bt)
|
||||
*/
|
||||
ret.p = ql_last(&prof_tdata->lru_ql, lru_link);
|
||||
assert(ret.v != NULL);
|
||||
if (ckh_remove(&prof_tdata->bt2cnt, ret.p->ctx->bt,
|
||||
NULL, NULL))
|
||||
assert(false);
|
||||
ckh_remove(&prof_tdata->bt2cnt, ret.p->ctx->bt, NULL,
|
||||
NULL);
|
||||
ql_remove(&prof_tdata->lru_ql, ret.p, lru_link);
|
||||
prof_ctx_merge(ret.p->ctx, ret.p);
|
||||
/* ret can now be re-used. */
|
||||
@@ -516,8 +503,11 @@ prof_lookup(prof_bt_t *bt)
|
||||
/* Allocate and partially initialize a new cnt. */
|
||||
ret.v = imalloc(sizeof(prof_thr_cnt_t));
|
||||
if (ret.p == NULL) {
|
||||
if (new_ctx)
|
||||
prof_ctx_destroy(ctx.p);
|
||||
if (new_ctx) {
|
||||
malloc_mutex_lock(&ctx.p->lock);
|
||||
ctx.p->cnt_merged.curobjs--;
|
||||
malloc_mutex_unlock(&ctx.p->lock);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
ql_elm_new(ret.p, cnts_link);
|
||||
@@ -528,15 +518,19 @@ prof_lookup(prof_bt_t *bt)
|
||||
ret.p->epoch = 0;
|
||||
memset(&ret.p->cnts, 0, sizeof(prof_cnt_t));
|
||||
if (ckh_insert(&prof_tdata->bt2cnt, btkey.v, ret.v)) {
|
||||
if (new_ctx)
|
||||
prof_ctx_destroy(ctx.p);
|
||||
if (new_ctx) {
|
||||
malloc_mutex_lock(&ctx.p->lock);
|
||||
ctx.p->cnt_merged.curobjs--;
|
||||
malloc_mutex_unlock(&ctx.p->lock);
|
||||
}
|
||||
idalloc(ret.v);
|
||||
return (NULL);
|
||||
}
|
||||
ql_head_insert(&prof_tdata->lru_ql, ret.p, lru_link);
|
||||
malloc_mutex_lock(&ctx.p->lock);
|
||||
ql_tail_insert(&ctx.p->cnts_ql, ret.p, cnts_link);
|
||||
ctx.p->cnt_merged.curobjs--;
|
||||
if (new_ctx)
|
||||
ctx.p->cnt_merged.curobjs--;
|
||||
malloc_mutex_unlock(&ctx.p->lock);
|
||||
} else {
|
||||
/* Move ret to the front of the LRU. */
|
||||
@@ -650,10 +644,11 @@ prof_ctx_destroy(prof_ctx_t *ctx)
|
||||
|
||||
/*
|
||||
* Check that ctx is still unused by any thread cache before destroying
|
||||
* it. prof_lookup() artificially raises ctx->cnt_merge.curobjs in
|
||||
* order to avoid a race condition with this function, as does
|
||||
* prof_ctx_merge() in order to avoid a race between the main body of
|
||||
* prof_ctx_merge() and entry into this function.
|
||||
* it. prof_lookup() interlocks bt2ctx_mtx and ctx->lock in order to
|
||||
* avoid a race condition with this function, and prof_ctx_merge()
|
||||
* artificially raises ctx->cnt_merged.curobjs in order to avoid a race
|
||||
* between the main body of prof_ctx_merge() and entry into this
|
||||
* function.
|
||||
*/
|
||||
prof_enter();
|
||||
malloc_mutex_lock(&ctx->lock);
|
||||
@@ -662,8 +657,7 @@ prof_ctx_destroy(prof_ctx_t *ctx)
|
||||
assert(ctx->cnt_merged.accumobjs == 0);
|
||||
assert(ctx->cnt_merged.accumbytes == 0);
|
||||
/* Remove ctx from bt2ctx. */
|
||||
if (ckh_remove(&bt2ctx, ctx->bt, NULL, NULL))
|
||||
assert(false);
|
||||
ckh_remove(&bt2ctx, ctx->bt, NULL, NULL);
|
||||
prof_leave();
|
||||
/* Destroy ctx. */
|
||||
malloc_mutex_unlock(&ctx->lock);
|
||||
@@ -671,10 +665,7 @@ prof_ctx_destroy(prof_ctx_t *ctx)
|
||||
malloc_mutex_destroy(&ctx->lock);
|
||||
idalloc(ctx);
|
||||
} else {
|
||||
/*
|
||||
* Compensate for increment in prof_ctx_merge() or
|
||||
* prof_lookup().
|
||||
*/
|
||||
/* Compensate for increment in prof_ctx_merge(). */
|
||||
ctx->cnt_merged.curobjs--;
|
||||
malloc_mutex_unlock(&ctx->lock);
|
||||
prof_leave();
|
||||
@@ -1081,7 +1072,7 @@ prof_bt_hash(const void *key, unsigned minbits, size_t *hash1, size_t *hash2)
|
||||
} else {
|
||||
ret1 = h;
|
||||
ret2 = hash(bt->vec, bt->len * sizeof(void *),
|
||||
0x8432a476666bbc13LLU);
|
||||
0x8432a476666bbc13U);
|
||||
}
|
||||
|
||||
*hash1 = ret1;
|
||||
@@ -1118,6 +1109,7 @@ prof_tdata_init(void)
|
||||
|
||||
prof_tdata->vec = imalloc(sizeof(void *) * prof_bt_max);
|
||||
if (prof_tdata->vec == NULL) {
|
||||
|
||||
ckh_delete(&prof_tdata->bt2cnt);
|
||||
idalloc(prof_tdata);
|
||||
return (NULL);
|
||||
@@ -1135,26 +1127,33 @@ prof_tdata_init(void)
|
||||
static void
|
||||
prof_tdata_cleanup(void *arg)
|
||||
{
|
||||
prof_thr_cnt_t *cnt;
|
||||
prof_tdata_t *prof_tdata = (prof_tdata_t *)arg;
|
||||
prof_tdata_t *prof_tdata;
|
||||
|
||||
/*
|
||||
* Delete the hash table. All of its contents can still be iterated
|
||||
* over via the LRU.
|
||||
*/
|
||||
ckh_delete(&prof_tdata->bt2cnt);
|
||||
prof_tdata = PROF_TCACHE_GET();
|
||||
if (prof_tdata != NULL) {
|
||||
prof_thr_cnt_t *cnt;
|
||||
|
||||
/* Iteratively merge cnt's into the global stats and delete them. */
|
||||
while ((cnt = ql_last(&prof_tdata->lru_ql, lru_link)) != NULL) {
|
||||
ql_remove(&prof_tdata->lru_ql, cnt, lru_link);
|
||||
prof_ctx_merge(cnt->ctx, cnt);
|
||||
idalloc(cnt);
|
||||
/*
|
||||
* Delete the hash table. All of its contents can still be
|
||||
* iterated over via the LRU.
|
||||
*/
|
||||
ckh_delete(&prof_tdata->bt2cnt);
|
||||
|
||||
/*
|
||||
* Iteratively merge cnt's into the global stats and delete
|
||||
* them.
|
||||
*/
|
||||
while ((cnt = ql_last(&prof_tdata->lru_ql, lru_link)) != NULL) {
|
||||
prof_ctx_merge(cnt->ctx, cnt);
|
||||
ql_remove(&prof_tdata->lru_ql, cnt, lru_link);
|
||||
idalloc(cnt);
|
||||
}
|
||||
|
||||
idalloc(prof_tdata->vec);
|
||||
|
||||
idalloc(prof_tdata);
|
||||
PROF_TCACHE_SET(NULL);
|
||||
}
|
||||
|
||||
idalloc(prof_tdata->vec);
|
||||
|
||||
idalloc(prof_tdata);
|
||||
PROF_TCACHE_SET(NULL);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Vendored
+1
-1
@@ -748,7 +748,7 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
|
||||
ninitialized++;
|
||||
}
|
||||
|
||||
if (ninitialized > 1 || unmerged == false) {
|
||||
if (ninitialized > 1) {
|
||||
/* Print merged arena stats. */
|
||||
malloc_cprintf(write_cb, cbopaque,
|
||||
"\nMerged arenas stats:\n");
|
||||
|
||||
Vendored
+4
-14
@@ -1,8 +1,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define JEMALLOC_MANGLE
|
||||
#include "jemalloc_test.h"
|
||||
@@ -10,20 +8,12 @@
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
size_t pagesize;
|
||||
void *p, *q;
|
||||
size_t sz, tsz;
|
||||
int r;
|
||||
|
||||
fprintf(stderr, "Test begin\n");
|
||||
|
||||
/* Get page size. */
|
||||
{
|
||||
long result = sysconf(_SC_PAGESIZE);
|
||||
assert(result != -1);
|
||||
pagesize = (size_t)result;
|
||||
}
|
||||
|
||||
r = JEMALLOC_P(allocm)(&p, &sz, 42, 0);
|
||||
if (r != ALLOCM_SUCCESS) {
|
||||
fprintf(stderr, "Unexpected allocm() error\n");
|
||||
@@ -76,7 +66,7 @@ main(void)
|
||||
p = q;
|
||||
sz = tsz;
|
||||
|
||||
r = JEMALLOC_P(rallocm)(&q, &tsz, pagesize*2, 0, 0);
|
||||
r = JEMALLOC_P(rallocm)(&q, &tsz, 8192, 0, 0);
|
||||
if (r != ALLOCM_SUCCESS)
|
||||
fprintf(stderr, "Unexpected rallocm() error\n");
|
||||
if (q == p)
|
||||
@@ -88,7 +78,7 @@ main(void)
|
||||
p = q;
|
||||
sz = tsz;
|
||||
|
||||
r = JEMALLOC_P(rallocm)(&q, &tsz, pagesize*4, 0, 0);
|
||||
r = JEMALLOC_P(rallocm)(&q, &tsz, 16384, 0, 0);
|
||||
if (r != ALLOCM_SUCCESS)
|
||||
fprintf(stderr, "Unexpected rallocm() error\n");
|
||||
if (tsz == sz) {
|
||||
@@ -98,7 +88,7 @@ main(void)
|
||||
p = q;
|
||||
sz = tsz;
|
||||
|
||||
r = JEMALLOC_P(rallocm)(&q, &tsz, pagesize*2, 0, ALLOCM_NO_MOVE);
|
||||
r = JEMALLOC_P(rallocm)(&q, &tsz, 8192, 0, ALLOCM_NO_MOVE);
|
||||
if (r != ALLOCM_SUCCESS)
|
||||
fprintf(stderr, "Unexpected rallocm() error\n");
|
||||
if (q != p)
|
||||
@@ -109,7 +99,7 @@ main(void)
|
||||
}
|
||||
sz = tsz;
|
||||
|
||||
r = JEMALLOC_P(rallocm)(&q, &tsz, pagesize*4, 0, ALLOCM_NO_MOVE);
|
||||
r = JEMALLOC_P(rallocm)(&q, &tsz, 16384, 0, ALLOCM_NO_MOVE);
|
||||
if (r != ALLOCM_SUCCESS)
|
||||
fprintf(stderr, "Unexpected rallocm() error\n");
|
||||
if (q != p)
|
||||
|
||||
Vendored
+3
-14
@@ -1,21 +1,10 @@
|
||||
STD=
|
||||
WARN= -Wall
|
||||
OPT= -Os
|
||||
|
||||
R_CFLAGS= $(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS)
|
||||
R_LDFLAGS= $(LDFLAGS)
|
||||
DEBUG= -g
|
||||
|
||||
R_CC=$(CC) $(R_CFLAGS)
|
||||
R_LD=$(CC) $(R_LDFLAGS)
|
||||
|
||||
linenoise.o: linenoise.h linenoise.c
|
||||
linenoise_example: linenoise.h linenoise.c
|
||||
|
||||
linenoise_example: linenoise.o example.o
|
||||
$(R_LD) -o $@ $^
|
||||
$(CC) $(ARCH) -Wall -W -Os -g -o linenoise_example linenoise.o example.o
|
||||
|
||||
.c.o:
|
||||
$(R_CC) -c $<
|
||||
$(CC) $(ARCH) -c -Wall -W -Os -g $<
|
||||
|
||||
clean:
|
||||
rm -f linenoise_example *.o
|
||||
|
||||
Vendored
-34
@@ -1,34 +0,0 @@
|
||||
Lua License
|
||||
-----------
|
||||
|
||||
Lua is licensed under the terms of the MIT license reproduced below.
|
||||
This means that Lua is free software and can be used for both academic
|
||||
and commercial purposes at absolutely no cost.
|
||||
|
||||
For details and rationale, see http://www.lua.org/license.html .
|
||||
|
||||
===============================================================================
|
||||
|
||||
Copyright (C) 1994-2008 Lua.org, PUC-Rio.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
===============================================================================
|
||||
|
||||
(end of COPYRIGHT)
|
||||
Vendored
-183
@@ -1,183 +0,0 @@
|
||||
HISTORY for Lua 5.1
|
||||
|
||||
* Changes from version 5.0 to 5.1
|
||||
-------------------------------
|
||||
Language:
|
||||
+ new module system.
|
||||
+ new semantics for control variables of fors.
|
||||
+ new semantics for setn/getn.
|
||||
+ new syntax/semantics for varargs.
|
||||
+ new long strings and comments.
|
||||
+ new `mod' operator (`%')
|
||||
+ new length operator #t
|
||||
+ metatables for all types
|
||||
API:
|
||||
+ new functions: lua_createtable, lua_get(set)field, lua_push(to)integer.
|
||||
+ user supplies memory allocator (lua_open becomes lua_newstate).
|
||||
+ luaopen_* functions must be called through Lua.
|
||||
Implementation:
|
||||
+ new configuration scheme via luaconf.h.
|
||||
+ incremental garbage collection.
|
||||
+ better handling of end-of-line in the lexer.
|
||||
+ fully reentrant parser (new Lua function `load')
|
||||
+ better support for 64-bit machines.
|
||||
+ native loadlib support for Mac OS X.
|
||||
+ standard distribution in only one library (lualib.a merged into lua.a)
|
||||
|
||||
* Changes from version 4.0 to 5.0
|
||||
-------------------------------
|
||||
Language:
|
||||
+ lexical scoping.
|
||||
+ Lua coroutines.
|
||||
+ standard libraries now packaged in tables.
|
||||
+ tags replaced by metatables and tag methods replaced by metamethods,
|
||||
stored in metatables.
|
||||
+ proper tail calls.
|
||||
+ each function can have its own global table, which can be shared.
|
||||
+ new __newindex metamethod, called when we insert a new key into a table.
|
||||
+ new block comments: --[[ ... ]].
|
||||
+ new generic for.
|
||||
+ new weak tables.
|
||||
+ new boolean type.
|
||||
+ new syntax "local function".
|
||||
+ (f()) returns the first value returned by f.
|
||||
+ {f()} fills a table with all values returned by f.
|
||||
+ \n ignored in [[\n .
|
||||
+ fixed and-or priorities.
|
||||
+ more general syntax for function definition (e.g. function a.x.y:f()...end).
|
||||
+ more general syntax for function calls (e.g. (print or write)(9)).
|
||||
+ new functions (time/date, tmpfile, unpack, require, load*, etc.).
|
||||
API:
|
||||
+ chunks are loaded by using lua_load; new luaL_loadfile and luaL_loadbuffer.
|
||||
+ introduced lightweight userdata, a simple "void*" without a metatable.
|
||||
+ new error handling protocol: the core no longer prints error messages;
|
||||
all errors are reported to the caller on the stack.
|
||||
+ new lua_atpanic for host cleanup.
|
||||
+ new, signal-safe, hook scheme.
|
||||
Implementation:
|
||||
+ new license: MIT.
|
||||
+ new, faster, register-based virtual machine.
|
||||
+ support for external multithreading and coroutines.
|
||||
+ new and consistent error message format.
|
||||
+ the core no longer needs "stdio.h" for anything (except for a single
|
||||
use of sprintf to convert numbers to strings).
|
||||
+ lua.c now runs the environment variable LUA_INIT, if present. It can
|
||||
be "@filename", to run a file, or the chunk itself.
|
||||
+ support for user extensions in lua.c.
|
||||
sample implementation given for command line editing.
|
||||
+ new dynamic loading library, active by default on several platforms.
|
||||
+ safe garbage-collector metamethods.
|
||||
+ precompiled bytecodes checked for integrity (secure binary dostring).
|
||||
+ strings are fully aligned.
|
||||
+ position capture in string.find.
|
||||
+ read('*l') can read lines with embedded zeros.
|
||||
|
||||
* Changes from version 3.2 to 4.0
|
||||
-------------------------------
|
||||
Language:
|
||||
+ new "break" and "for" statements (both numerical and for tables).
|
||||
+ uniform treatment of globals: globals are now stored in a Lua table.
|
||||
+ improved error messages.
|
||||
+ no more '$debug': full speed *and* full debug information.
|
||||
+ new read form: read(N) for next N bytes.
|
||||
+ general read patterns now deprecated.
|
||||
(still available with -DCOMPAT_READPATTERNS.)
|
||||
+ all return values are passed as arguments for the last function
|
||||
(old semantics still available with -DLUA_COMPAT_ARGRET)
|
||||
+ garbage collection tag methods for tables now deprecated.
|
||||
+ there is now only one tag method for order.
|
||||
API:
|
||||
+ New API: fully re-entrant, simpler, and more efficient.
|
||||
+ New debug API.
|
||||
Implementation:
|
||||
+ faster than ever: cleaner virtual machine and new hashing algorithm.
|
||||
+ non-recursive garbage-collector algorithm.
|
||||
+ reduced memory usage for programs with many strings.
|
||||
+ improved treatment for memory allocation errors.
|
||||
+ improved support for 16-bit machines (we hope).
|
||||
+ code now compiles unmodified as both ANSI C and C++.
|
||||
+ numbers in bases other than 10 are converted using strtoul.
|
||||
+ new -f option in Lua to support #! scripts.
|
||||
+ luac can now combine text and binaries.
|
||||
|
||||
* Changes from version 3.1 to 3.2
|
||||
-------------------------------
|
||||
+ redirected all output in Lua's core to _ERRORMESSAGE and _ALERT.
|
||||
+ increased limit on the number of constants and globals per function
|
||||
(from 2^16 to 2^24).
|
||||
+ debugging info (lua_debug and hooks) moved into lua_state and new API
|
||||
functions provided to get and set this info.
|
||||
+ new debug lib gives full debugging access within Lua.
|
||||
+ new table functions "foreachi", "sort", "tinsert", "tremove", "getn".
|
||||
+ new io functions "flush", "seek".
|
||||
|
||||
* Changes from version 3.0 to 3.1
|
||||
-------------------------------
|
||||
+ NEW FEATURE: anonymous functions with closures (via "upvalues").
|
||||
+ new syntax:
|
||||
- local variables in chunks.
|
||||
- better scope control with DO block END.
|
||||
- constructors can now be also written: { record-part; list-part }.
|
||||
- more general syntax for function calls and lvalues, e.g.:
|
||||
f(x).y=1
|
||||
o:f(x,y):g(z)
|
||||
f"string" is sugar for f("string")
|
||||
+ strings may now contain arbitrary binary data (e.g., embedded zeros).
|
||||
+ major code re-organization and clean-up; reduced module interdependecies.
|
||||
+ no arbitrary limits on the total number of constants and globals.
|
||||
+ support for multiple global contexts.
|
||||
+ better syntax error messages.
|
||||
+ new traversal functions "foreach" and "foreachvar".
|
||||
+ the default for numbers is now double.
|
||||
changing it to use floats or longs is easy.
|
||||
+ complete debug information stored in pre-compiled chunks.
|
||||
+ sample interpreter now prompts user when run interactively, and also
|
||||
handles control-C interruptions gracefully.
|
||||
|
||||
* Changes from version 2.5 to 3.0
|
||||
-------------------------------
|
||||
+ NEW CONCEPT: "tag methods".
|
||||
Tag methods replace fallbacks as the meta-mechanism for extending the
|
||||
semantics of Lua. Whereas fallbacks had a global nature, tag methods
|
||||
work on objects having the same tag (e.g., groups of tables).
|
||||
Existing code that uses fallbacks should work without change.
|
||||
+ new, general syntax for constructors {[exp] = exp, ... }.
|
||||
+ support for handling variable number of arguments in functions (varargs).
|
||||
+ support for conditional compilation ($if ... $else ... $end).
|
||||
+ cleaner semantics in API simplifies host code.
|
||||
+ better support for writing libraries (auxlib.h).
|
||||
+ better type checking and error messages in the standard library.
|
||||
+ luac can now also undump.
|
||||
|
||||
* Changes from version 2.4 to 2.5
|
||||
-------------------------------
|
||||
+ io and string libraries are now based on pattern matching;
|
||||
the old libraries are still available for compatibility
|
||||
+ dofile and dostring can now return values (via return statement)
|
||||
+ better support for 16- and 64-bit machines
|
||||
+ expanded documentation, with more examples
|
||||
|
||||
* Changes from version 2.2 to 2.4
|
||||
-------------------------------
|
||||
+ external compiler creates portable binary files that can be loaded faster
|
||||
+ interface for debugging and profiling
|
||||
+ new "getglobal" fallback
|
||||
+ new functions for handling references to Lua objects
|
||||
+ new functions in standard lib
|
||||
+ only one copy of each string is stored
|
||||
+ expanded documentation, with more examples
|
||||
|
||||
* Changes from version 2.1 to 2.2
|
||||
-------------------------------
|
||||
+ functions now may be declared with any "lvalue" as a name
|
||||
+ garbage collection of functions
|
||||
+ support for pipes
|
||||
|
||||
* Changes from version 1.1 to 2.1
|
||||
-------------------------------
|
||||
+ object-oriented support
|
||||
+ fallbacks
|
||||
+ simplified syntax for tables
|
||||
+ many internal improvements
|
||||
|
||||
(end of HISTORY)
|
||||
Vendored
-99
@@ -1,99 +0,0 @@
|
||||
INSTALL for Lua 5.1
|
||||
|
||||
* Building Lua
|
||||
------------
|
||||
Lua is built in the src directory, but the build process can be
|
||||
controlled from the top-level Makefile.
|
||||
|
||||
Building Lua on Unix systems should be very easy. First do "make" and
|
||||
see if your platform is listed. If so, just do "make xxx", where xxx
|
||||
is your platform name. The platforms currently supported are:
|
||||
aix ansi bsd freebsd generic linux macosx mingw posix solaris
|
||||
|
||||
If your platform is not listed, try the closest one or posix, generic,
|
||||
ansi, in this order.
|
||||
|
||||
See below for customization instructions and for instructions on how
|
||||
to build with other Windows compilers.
|
||||
|
||||
If you want to check that Lua has been built correctly, do "make test"
|
||||
after building Lua. Also, have a look at the example programs in test.
|
||||
|
||||
* Installing Lua
|
||||
--------------
|
||||
Once you have built Lua, you may want to install it in an official
|
||||
place in your system. In this case, do "make install". The official
|
||||
place and the way to install files are defined in Makefile. You must
|
||||
have the right permissions to install files.
|
||||
|
||||
If you want to build and install Lua in one step, do "make xxx install",
|
||||
where xxx is your platform name.
|
||||
|
||||
If you want to install Lua locally, then do "make local". This will
|
||||
create directories bin, include, lib, man, and install Lua there as
|
||||
follows:
|
||||
|
||||
bin: lua luac
|
||||
include: lua.h luaconf.h lualib.h lauxlib.h lua.hpp
|
||||
lib: liblua.a
|
||||
man/man1: lua.1 luac.1
|
||||
|
||||
These are the only directories you need for development.
|
||||
|
||||
There are man pages for lua and luac, in both nroff and html, and a
|
||||
reference manual in html in doc, some sample code in test, and some
|
||||
useful stuff in etc. You don't need these directories for development.
|
||||
|
||||
If you want to install Lua locally, but in some other directory, do
|
||||
"make install INSTALL_TOP=xxx", where xxx is your chosen directory.
|
||||
|
||||
See below for instructions for Windows and other systems.
|
||||
|
||||
* Customization
|
||||
-------------
|
||||
Three things can be customized by editing a file:
|
||||
- Where and how to install Lua -- edit Makefile.
|
||||
- How to build Lua -- edit src/Makefile.
|
||||
- Lua features -- edit src/luaconf.h.
|
||||
|
||||
You don't actually need to edit the Makefiles because you may set the
|
||||
relevant variables when invoking make.
|
||||
|
||||
On the other hand, if you need to select some Lua features, you'll need
|
||||
to edit src/luaconf.h. The edited file will be the one installed, and
|
||||
it will be used by any Lua clients that you build, to ensure consistency.
|
||||
|
||||
We strongly recommend that you enable dynamic loading. This is done
|
||||
automatically for all platforms listed above that have this feature
|
||||
(and also Windows). See src/luaconf.h and also src/Makefile.
|
||||
|
||||
* Building Lua on Windows and other systems
|
||||
-----------------------------------------
|
||||
If you're not using the usual Unix tools, then the instructions for
|
||||
building Lua depend on the compiler you use. You'll need to create
|
||||
projects (or whatever your compiler uses) for building the library,
|
||||
the interpreter, and the compiler, as follows:
|
||||
|
||||
library: lapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c
|
||||
lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c
|
||||
ltable.c ltm.c lundump.c lvm.c lzio.c
|
||||
lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c loslib.c
|
||||
ltablib.c lstrlib.c loadlib.c linit.c
|
||||
|
||||
interpreter: library, lua.c
|
||||
|
||||
compiler: library, luac.c print.c
|
||||
|
||||
If you use Visual Studio .NET, you can use etc/luavs.bat in its
|
||||
"Command Prompt".
|
||||
|
||||
If all you want is to build the Lua interpreter, you may put all .c files
|
||||
in a single project, except for luac.c and print.c. Or just use etc/all.c.
|
||||
|
||||
To use Lua as a library in your own programs, you'll need to know how to
|
||||
create and use libraries with your compiler.
|
||||
|
||||
As mentioned above, you may edit luaconf.h to select some features before
|
||||
building Lua.
|
||||
|
||||
(end of INSTALL)
|
||||
Vendored
-128
@@ -1,128 +0,0 @@
|
||||
# makefile for installing Lua
|
||||
# see INSTALL for installation instructions
|
||||
# see src/Makefile and src/luaconf.h for further customization
|
||||
|
||||
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
|
||||
|
||||
# Your platform. See PLATS for possible values.
|
||||
PLAT= none
|
||||
|
||||
# Where to install. The installation starts in the src and doc directories,
|
||||
# so take care if INSTALL_TOP is not an absolute path.
|
||||
INSTALL_TOP= /usr/local
|
||||
INSTALL_BIN= $(INSTALL_TOP)/bin
|
||||
INSTALL_INC= $(INSTALL_TOP)/include
|
||||
INSTALL_LIB= $(INSTALL_TOP)/lib
|
||||
INSTALL_MAN= $(INSTALL_TOP)/man/man1
|
||||
#
|
||||
# You probably want to make INSTALL_LMOD and INSTALL_CMOD consistent with
|
||||
# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h (and also with etc/lua.pc).
|
||||
INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V
|
||||
INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V
|
||||
|
||||
# How to install. If your install program does not support "-p", then you
|
||||
# may have to run ranlib on the installed liblua.a (do "make ranlib").
|
||||
INSTALL= install -p
|
||||
INSTALL_EXEC= $(INSTALL) -m 0755
|
||||
INSTALL_DATA= $(INSTALL) -m 0644
|
||||
#
|
||||
# If you don't have install you can use cp instead.
|
||||
# INSTALL= cp -p
|
||||
# INSTALL_EXEC= $(INSTALL)
|
||||
# INSTALL_DATA= $(INSTALL)
|
||||
|
||||
# Utilities.
|
||||
MKDIR= mkdir -p
|
||||
RANLIB= ranlib
|
||||
|
||||
# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
|
||||
|
||||
# Convenience platforms targets.
|
||||
PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
|
||||
|
||||
# What to install.
|
||||
TO_BIN= lua luac
|
||||
TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp
|
||||
TO_LIB= liblua.a
|
||||
TO_MAN= lua.1 luac.1
|
||||
|
||||
# Lua version and release.
|
||||
V= 5.1
|
||||
R= 5.1.4
|
||||
|
||||
all: $(PLAT)
|
||||
|
||||
$(PLATS) clean:
|
||||
cd src && $(MAKE) $@
|
||||
|
||||
test: dummy
|
||||
src/lua test/hello.lua
|
||||
|
||||
install: dummy
|
||||
cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD)
|
||||
cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN)
|
||||
cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)
|
||||
cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)
|
||||
cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN)
|
||||
|
||||
ranlib:
|
||||
cd src && cd $(INSTALL_LIB) && $(RANLIB) $(TO_LIB)
|
||||
|
||||
local:
|
||||
$(MAKE) install INSTALL_TOP=..
|
||||
|
||||
none:
|
||||
@echo "Please do"
|
||||
@echo " make PLATFORM"
|
||||
@echo "where PLATFORM is one of these:"
|
||||
@echo " $(PLATS)"
|
||||
@echo "See INSTALL for complete instructions."
|
||||
|
||||
# make may get confused with test/ and INSTALL in a case-insensitive OS
|
||||
dummy:
|
||||
|
||||
# echo config parameters
|
||||
echo:
|
||||
@echo ""
|
||||
@echo "These are the parameters currently set in src/Makefile to build Lua $R:"
|
||||
@echo ""
|
||||
@cd src && $(MAKE) -s echo
|
||||
@echo ""
|
||||
@echo "These are the parameters currently set in Makefile to install Lua $R:"
|
||||
@echo ""
|
||||
@echo "PLAT = $(PLAT)"
|
||||
@echo "INSTALL_TOP = $(INSTALL_TOP)"
|
||||
@echo "INSTALL_BIN = $(INSTALL_BIN)"
|
||||
@echo "INSTALL_INC = $(INSTALL_INC)"
|
||||
@echo "INSTALL_LIB = $(INSTALL_LIB)"
|
||||
@echo "INSTALL_MAN = $(INSTALL_MAN)"
|
||||
@echo "INSTALL_LMOD = $(INSTALL_LMOD)"
|
||||
@echo "INSTALL_CMOD = $(INSTALL_CMOD)"
|
||||
@echo "INSTALL_EXEC = $(INSTALL_EXEC)"
|
||||
@echo "INSTALL_DATA = $(INSTALL_DATA)"
|
||||
@echo ""
|
||||
@echo "See also src/luaconf.h ."
|
||||
@echo ""
|
||||
|
||||
# echo private config parameters
|
||||
pecho:
|
||||
@echo "V = $(V)"
|
||||
@echo "R = $(R)"
|
||||
@echo "TO_BIN = $(TO_BIN)"
|
||||
@echo "TO_INC = $(TO_INC)"
|
||||
@echo "TO_LIB = $(TO_LIB)"
|
||||
@echo "TO_MAN = $(TO_MAN)"
|
||||
|
||||
# echo config parameters as Lua code
|
||||
# uncomment the last sed expression if you want nil instead of empty strings
|
||||
lecho:
|
||||
@echo "-- installation parameters for Lua $R"
|
||||
@echo "VERSION = '$V'"
|
||||
@echo "RELEASE = '$R'"
|
||||
@$(MAKE) echo | grep = | sed -e 's/= /= "/' -e 's/$$/"/' #-e 's/""/nil/'
|
||||
@echo "-- EOF"
|
||||
|
||||
# list targets that do not create files (but not all makes understand .PHONY)
|
||||
.PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho
|
||||
|
||||
# (end of Makefile)
|
||||
Vendored
-37
@@ -1,37 +0,0 @@
|
||||
README for Lua 5.1
|
||||
|
||||
See INSTALL for installation instructions.
|
||||
See HISTORY for a summary of changes since the last released version.
|
||||
|
||||
* What is Lua?
|
||||
------------
|
||||
Lua is a powerful, light-weight programming language designed for extending
|
||||
applications. Lua is also frequently used as a general-purpose, stand-alone
|
||||
language. Lua is free software.
|
||||
|
||||
For complete information, visit Lua's web site at http://www.lua.org/ .
|
||||
For an executive summary, see http://www.lua.org/about.html .
|
||||
|
||||
Lua has been used in many different projects around the world.
|
||||
For a short list, see http://www.lua.org/uses.html .
|
||||
|
||||
* Availability
|
||||
------------
|
||||
Lua is freely available for both academic and commercial purposes.
|
||||
See COPYRIGHT and http://www.lua.org/license.html for details.
|
||||
Lua can be downloaded at http://www.lua.org/download.html .
|
||||
|
||||
* Installation
|
||||
------------
|
||||
Lua is implemented in pure ANSI C, and compiles unmodified in all known
|
||||
platforms that have an ANSI C compiler. In most Unix-like platforms, simply
|
||||
do "make" with a suitable target. See INSTALL for detailed instructions.
|
||||
|
||||
* Origin
|
||||
------
|
||||
Lua is developed at Lua.org, a laboratory of the Department of Computer
|
||||
Science of PUC-Rio (the Pontifical Catholic University of Rio de Janeiro
|
||||
in Brazil).
|
||||
For more information about the authors, see http://www.lua.org/authors.html .
|
||||
|
||||
(end of README)
|
||||
Vendored
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 797 B |
Vendored
-499
@@ -1,499 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Lua 5.1 Reference Manual - contents</TITLE>
|
||||
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
|
||||
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-1">
|
||||
<STYLE TYPE="text/css">
|
||||
ul {
|
||||
list-style-type: none ;
|
||||
list-style-position: outside ;
|
||||
}
|
||||
</STYLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY>
|
||||
|
||||
<HR>
|
||||
<H1>
|
||||
<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="" BORDER=0></A>
|
||||
Lua 5.1 Reference Manual
|
||||
</H1>
|
||||
|
||||
This is an online version of
|
||||
<BLOCKQUOTE>
|
||||
<A HREF="http://www.amazon.com/exec/obidos/ASIN/8590379833/lua-indexmanual-20">
|
||||
<IMG SRC="cover.png" ALT="" TITLE="buy from Amazon" BORDER=1 ALIGN="left" HSPACE=12>
|
||||
</A>
|
||||
<B>Lua 5.1 Reference Manual</B>
|
||||
<BR>by R. Ierusalimschy, L. H. de Figueiredo, W. Celes
|
||||
<BR>Lua.org, August 2006
|
||||
<BR>ISBN 85-903798-3-3
|
||||
<BR><A HREF="http://www.amazon.com/exec/obidos/ASIN/8590379833/lua-indexmanual-20">
|
||||
<IMG SRC="amazon.gif" ALT="[Buy from Amazon]" BORDER=0></A>
|
||||
<BR CLEAR="all">
|
||||
</BLOCKQUOTE>
|
||||
<P>
|
||||
|
||||
Buy a copy of this book and
|
||||
<A HREF="http://www.lua.org/donations.html">help to support</A>
|
||||
the Lua project.
|
||||
<P>
|
||||
|
||||
The reference manual is the official definition of the Lua language.
|
||||
For a complete introduction to Lua programming, see the book
|
||||
<A HREF="http://www.lua.org/docs.html#books">Programming in Lua</A>.
|
||||
<P>
|
||||
|
||||
<A HREF="manual.html">start</A>
|
||||
·
|
||||
<A HREF="#contents">contents</A>
|
||||
·
|
||||
<A HREF="#index">index</A>
|
||||
·
|
||||
<A HREF="http://www.lua.org/manual/5.1/pt/">português</A>
|
||||
·
|
||||
<A HREF="http://www.lua.org/manual/5.1/es/">español</A>
|
||||
<HR>
|
||||
<SMALL>
|
||||
Copyright © 2006-2008 Lua.org, PUC-Rio.
|
||||
Freely available under the terms of the
|
||||
<a href="http://www.lua.org/license.html#5">Lua license</a>.
|
||||
</SMALL>
|
||||
<P>
|
||||
|
||||
<H2><A NAME="contents">Contents</A></H2>
|
||||
<UL style="padding: 0">
|
||||
<LI><A HREF="manual.html">1 - Introduction</A>
|
||||
<P>
|
||||
<LI><A HREF="manual.html#2">2 - The Language</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#2.1">2.1 - Lexical Conventions</A>
|
||||
<LI><A HREF="manual.html#2.2">2.2 - Values and Types</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#2.2.1">2.2.1 - Coercion</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#2.3">2.3 - Variables</A>
|
||||
<LI><A HREF="manual.html#2.4">2.4 - Statements</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#2.4.1">2.4.1 - Chunks</A>
|
||||
<LI><A HREF="manual.html#2.4.2">2.4.2 - Blocks</A>
|
||||
<LI><A HREF="manual.html#2.4.3">2.4.3 - Assignment</A>
|
||||
<LI><A HREF="manual.html#2.4.4">2.4.4 - Control Structures</A>
|
||||
<LI><A HREF="manual.html#2.4.5">2.4.5 - For Statement</A>
|
||||
<LI><A HREF="manual.html#2.4.6">2.4.6 - Function Calls as Statements</A>
|
||||
<LI><A HREF="manual.html#2.4.7">2.4.7 - Local Declarations</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#2.5">2.5 - Expressions</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#2.5.1">2.5.1 - Arithmetic Operators</A>
|
||||
<LI><A HREF="manual.html#2.5.2">2.5.2 - Relational Operators</A>
|
||||
<LI><A HREF="manual.html#2.5.3">2.5.3 - Logical Operators</A>
|
||||
<LI><A HREF="manual.html#2.5.4">2.5.4 - Concatenation</A>
|
||||
<LI><A HREF="manual.html#2.5.5">2.5.5 - The Length Operator</A>
|
||||
<LI><A HREF="manual.html#2.5.6">2.5.6 - Precedence</A>
|
||||
<LI><A HREF="manual.html#2.5.7">2.5.7 - Table Constructors</A>
|
||||
<LI><A HREF="manual.html#2.5.8">2.5.8 - Function Calls</A>
|
||||
<LI><A HREF="manual.html#2.5.9">2.5.9 - Function Definitions</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#2.6">2.6 - Visibility Rules</A>
|
||||
<LI><A HREF="manual.html#2.7">2.7 - Error Handling</A>
|
||||
<LI><A HREF="manual.html#2.8">2.8 - Metatables</A>
|
||||
<LI><A HREF="manual.html#2.9">2.9 - Environments</A>
|
||||
<LI><A HREF="manual.html#2.10">2.10 - Garbage Collection</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#2.10.1">2.10.1 - Garbage-Collection Metamethods</A>
|
||||
<LI><A HREF="manual.html#2.10.2">2.10.2 - Weak Tables</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#2.11">2.11 - Coroutines</A>
|
||||
</UL>
|
||||
<P>
|
||||
<LI><A HREF="manual.html#3">3 - The Application Program Interface</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#3.1">3.1 - The Stack</A>
|
||||
<LI><A HREF="manual.html#3.2">3.2 - Stack Size</A>
|
||||
<LI><A HREF="manual.html#3.3">3.3 - Pseudo-Indices</A>
|
||||
<LI><A HREF="manual.html#3.4">3.4 - C Closures</A>
|
||||
<LI><A HREF="manual.html#3.5">3.5 - Registry</A>
|
||||
<LI><A HREF="manual.html#3.6">3.6 - Error Handling in C</A>
|
||||
<LI><A HREF="manual.html#3.7">3.7 - Functions and Types</A>
|
||||
<LI><A HREF="manual.html#3.8">3.8 - The Debug Interface</A>
|
||||
</UL>
|
||||
<P>
|
||||
<LI><A HREF="manual.html#4">4 - The Auxiliary Library</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#4.1">4.1 - Functions and Types</A>
|
||||
</UL>
|
||||
<P>
|
||||
<LI><A HREF="manual.html#5">5 - Standard Libraries</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#5.1">5.1 - Basic Functions</A>
|
||||
<LI><A HREF="manual.html#5.2">5.2 - Coroutine Manipulation</A>
|
||||
<LI><A HREF="manual.html#5.3">5.3 - Modules</A>
|
||||
<LI><A HREF="manual.html#5.4">5.4 - String Manipulation</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#5.4.1">5.4.1 - Patterns</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#5.5">5.5 - Table Manipulation</A>
|
||||
<LI><A HREF="manual.html#5.6">5.6 - Mathematical Functions</A>
|
||||
<LI><A HREF="manual.html#5.7">5.7 - Input and Output Facilities</A>
|
||||
<LI><A HREF="manual.html#5.8">5.8 - Operating System Facilities</A>
|
||||
<LI><A HREF="manual.html#5.9">5.9 - The Debug Library</A>
|
||||
</UL>
|
||||
<P>
|
||||
<LI><A HREF="manual.html#6">6 - Lua Stand-alone</A>
|
||||
<P>
|
||||
<LI><A HREF="manual.html#7">7 - Incompatibilities with the Previous Version</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#7.1">7.1 - Changes in the Language</A>
|
||||
<LI><A HREF="manual.html#7.2">7.2 - Changes in the Libraries</A>
|
||||
<LI><A HREF="manual.html#7.3">7.3 - Changes in the API</A>
|
||||
</UL>
|
||||
<P>
|
||||
<LI><A HREF="manual.html#8">8 - The Complete Syntax of Lua</A>
|
||||
</UL>
|
||||
|
||||
<H2><A NAME="index">Index</A></H2>
|
||||
<TABLE WIDTH="100%">
|
||||
<TR VALIGN="top">
|
||||
<TD>
|
||||
<H3><A NAME="functions">Lua functions</A></H3>
|
||||
<A HREF="manual.html#pdf-_G">_G</A><BR>
|
||||
<A HREF="manual.html#pdf-_VERSION">_VERSION</A><BR>
|
||||
<A HREF="manual.html#pdf-assert">assert</A><BR>
|
||||
<A HREF="manual.html#pdf-collectgarbage">collectgarbage</A><BR>
|
||||
<A HREF="manual.html#pdf-dofile">dofile</A><BR>
|
||||
<A HREF="manual.html#pdf-error">error</A><BR>
|
||||
<A HREF="manual.html#pdf-getfenv">getfenv</A><BR>
|
||||
<A HREF="manual.html#pdf-getmetatable">getmetatable</A><BR>
|
||||
<A HREF="manual.html#pdf-ipairs">ipairs</A><BR>
|
||||
<A HREF="manual.html#pdf-load">load</A><BR>
|
||||
<A HREF="manual.html#pdf-loadfile">loadfile</A><BR>
|
||||
<A HREF="manual.html#pdf-loadstring">loadstring</A><BR>
|
||||
<A HREF="manual.html#pdf-module">module</A><BR>
|
||||
<A HREF="manual.html#pdf-next">next</A><BR>
|
||||
<A HREF="manual.html#pdf-pairs">pairs</A><BR>
|
||||
<A HREF="manual.html#pdf-pcall">pcall</A><BR>
|
||||
<A HREF="manual.html#pdf-print">print</A><BR>
|
||||
<A HREF="manual.html#pdf-rawequal">rawequal</A><BR>
|
||||
<A HREF="manual.html#pdf-rawget">rawget</A><BR>
|
||||
<A HREF="manual.html#pdf-rawset">rawset</A><BR>
|
||||
<A HREF="manual.html#pdf-require">require</A><BR>
|
||||
<A HREF="manual.html#pdf-select">select</A><BR>
|
||||
<A HREF="manual.html#pdf-setfenv">setfenv</A><BR>
|
||||
<A HREF="manual.html#pdf-setmetatable">setmetatable</A><BR>
|
||||
<A HREF="manual.html#pdf-tonumber">tonumber</A><BR>
|
||||
<A HREF="manual.html#pdf-tostring">tostring</A><BR>
|
||||
<A HREF="manual.html#pdf-type">type</A><BR>
|
||||
<A HREF="manual.html#pdf-unpack">unpack</A><BR>
|
||||
<A HREF="manual.html#pdf-xpcall">xpcall</A><BR>
|
||||
<P>
|
||||
|
||||
<A HREF="manual.html#pdf-coroutine.create">coroutine.create</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.resume">coroutine.resume</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.running">coroutine.running</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.status">coroutine.status</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.wrap">coroutine.wrap</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.yield">coroutine.yield</A><BR>
|
||||
<P>
|
||||
|
||||
<A HREF="manual.html#pdf-debug.debug">debug.debug</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getfenv">debug.getfenv</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.gethook">debug.gethook</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getinfo">debug.getinfo</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getlocal">debug.getlocal</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getmetatable">debug.getmetatable</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getregistry">debug.getregistry</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getupvalue">debug.getupvalue</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.setfenv">debug.setfenv</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.sethook">debug.sethook</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.setlocal">debug.setlocal</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.setmetatable">debug.setmetatable</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.setupvalue">debug.setupvalue</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.traceback">debug.traceback</A><BR>
|
||||
|
||||
</TD>
|
||||
<TD>
|
||||
<H3> </H3>
|
||||
<A HREF="manual.html#pdf-file:close">file:close</A><BR>
|
||||
<A HREF="manual.html#pdf-file:flush">file:flush</A><BR>
|
||||
<A HREF="manual.html#pdf-file:lines">file:lines</A><BR>
|
||||
<A HREF="manual.html#pdf-file:read">file:read</A><BR>
|
||||
<A HREF="manual.html#pdf-file:seek">file:seek</A><BR>
|
||||
<A HREF="manual.html#pdf-file:setvbuf">file:setvbuf</A><BR>
|
||||
<A HREF="manual.html#pdf-file:write">file:write</A><BR>
|
||||
<P>
|
||||
|
||||
<A HREF="manual.html#pdf-io.close">io.close</A><BR>
|
||||
<A HREF="manual.html#pdf-io.flush">io.flush</A><BR>
|
||||
<A HREF="manual.html#pdf-io.input">io.input</A><BR>
|
||||
<A HREF="manual.html#pdf-io.lines">io.lines</A><BR>
|
||||
<A HREF="manual.html#pdf-io.open">io.open</A><BR>
|
||||
<A HREF="manual.html#pdf-io.output">io.output</A><BR>
|
||||
<A HREF="manual.html#pdf-io.popen">io.popen</A><BR>
|
||||
<A HREF="manual.html#pdf-io.read">io.read</A><BR>
|
||||
<A HREF="manual.html#pdf-io.stderr">io.stderr</A><BR>
|
||||
<A HREF="manual.html#pdf-io.stdin">io.stdin</A><BR>
|
||||
<A HREF="manual.html#pdf-io.stdout">io.stdout</A><BR>
|
||||
<A HREF="manual.html#pdf-io.tmpfile">io.tmpfile</A><BR>
|
||||
<A HREF="manual.html#pdf-io.type">io.type</A><BR>
|
||||
<A HREF="manual.html#pdf-io.write">io.write</A><BR>
|
||||
<P>
|
||||
|
||||
<A HREF="manual.html#pdf-math.abs">math.abs</A><BR>
|
||||
<A HREF="manual.html#pdf-math.acos">math.acos</A><BR>
|
||||
<A HREF="manual.html#pdf-math.asin">math.asin</A><BR>
|
||||
<A HREF="manual.html#pdf-math.atan">math.atan</A><BR>
|
||||
<A HREF="manual.html#pdf-math.atan2">math.atan2</A><BR>
|
||||
<A HREF="manual.html#pdf-math.ceil">math.ceil</A><BR>
|
||||
<A HREF="manual.html#pdf-math.cos">math.cos</A><BR>
|
||||
<A HREF="manual.html#pdf-math.cosh">math.cosh</A><BR>
|
||||
<A HREF="manual.html#pdf-math.deg">math.deg</A><BR>
|
||||
<A HREF="manual.html#pdf-math.exp">math.exp</A><BR>
|
||||
<A HREF="manual.html#pdf-math.floor">math.floor</A><BR>
|
||||
<A HREF="manual.html#pdf-math.fmod">math.fmod</A><BR>
|
||||
<A HREF="manual.html#pdf-math.frexp">math.frexp</A><BR>
|
||||
<A HREF="manual.html#pdf-math.huge">math.huge</A><BR>
|
||||
<A HREF="manual.html#pdf-math.ldexp">math.ldexp</A><BR>
|
||||
<A HREF="manual.html#pdf-math.log">math.log</A><BR>
|
||||
<A HREF="manual.html#pdf-math.log10">math.log10</A><BR>
|
||||
<A HREF="manual.html#pdf-math.max">math.max</A><BR>
|
||||
<A HREF="manual.html#pdf-math.min">math.min</A><BR>
|
||||
<A HREF="manual.html#pdf-math.modf">math.modf</A><BR>
|
||||
<A HREF="manual.html#pdf-math.pi">math.pi</A><BR>
|
||||
<A HREF="manual.html#pdf-math.pow">math.pow</A><BR>
|
||||
<A HREF="manual.html#pdf-math.rad">math.rad</A><BR>
|
||||
<A HREF="manual.html#pdf-math.random">math.random</A><BR>
|
||||
<A HREF="manual.html#pdf-math.randomseed">math.randomseed</A><BR>
|
||||
<A HREF="manual.html#pdf-math.sin">math.sin</A><BR>
|
||||
<A HREF="manual.html#pdf-math.sinh">math.sinh</A><BR>
|
||||
<A HREF="manual.html#pdf-math.sqrt">math.sqrt</A><BR>
|
||||
<A HREF="manual.html#pdf-math.tan">math.tan</A><BR>
|
||||
<A HREF="manual.html#pdf-math.tanh">math.tanh</A><BR>
|
||||
<P>
|
||||
|
||||
<A HREF="manual.html#pdf-os.clock">os.clock</A><BR>
|
||||
<A HREF="manual.html#pdf-os.date">os.date</A><BR>
|
||||
<A HREF="manual.html#pdf-os.difftime">os.difftime</A><BR>
|
||||
<A HREF="manual.html#pdf-os.execute">os.execute</A><BR>
|
||||
<A HREF="manual.html#pdf-os.exit">os.exit</A><BR>
|
||||
<A HREF="manual.html#pdf-os.getenv">os.getenv</A><BR>
|
||||
<A HREF="manual.html#pdf-os.remove">os.remove</A><BR>
|
||||
<A HREF="manual.html#pdf-os.rename">os.rename</A><BR>
|
||||
<A HREF="manual.html#pdf-os.setlocale">os.setlocale</A><BR>
|
||||
<A HREF="manual.html#pdf-os.time">os.time</A><BR>
|
||||
<A HREF="manual.html#pdf-os.tmpname">os.tmpname</A><BR>
|
||||
<P>
|
||||
|
||||
<A HREF="manual.html#pdf-package.cpath">package.cpath</A><BR>
|
||||
<A HREF="manual.html#pdf-package.loaded">package.loaded</A><BR>
|
||||
<A HREF="manual.html#pdf-package.loaders">package.loaders</A><BR>
|
||||
<A HREF="manual.html#pdf-package.loadlib">package.loadlib</A><BR>
|
||||
<A HREF="manual.html#pdf-package.path">package.path</A><BR>
|
||||
<A HREF="manual.html#pdf-package.preload">package.preload</A><BR>
|
||||
<A HREF="manual.html#pdf-package.seeall">package.seeall</A><BR>
|
||||
<P>
|
||||
|
||||
<A HREF="manual.html#pdf-string.byte">string.byte</A><BR>
|
||||
<A HREF="manual.html#pdf-string.char">string.char</A><BR>
|
||||
<A HREF="manual.html#pdf-string.dump">string.dump</A><BR>
|
||||
<A HREF="manual.html#pdf-string.find">string.find</A><BR>
|
||||
<A HREF="manual.html#pdf-string.format">string.format</A><BR>
|
||||
<A HREF="manual.html#pdf-string.gmatch">string.gmatch</A><BR>
|
||||
<A HREF="manual.html#pdf-string.gsub">string.gsub</A><BR>
|
||||
<A HREF="manual.html#pdf-string.len">string.len</A><BR>
|
||||
<A HREF="manual.html#pdf-string.lower">string.lower</A><BR>
|
||||
<A HREF="manual.html#pdf-string.match">string.match</A><BR>
|
||||
<A HREF="manual.html#pdf-string.rep">string.rep</A><BR>
|
||||
<A HREF="manual.html#pdf-string.reverse">string.reverse</A><BR>
|
||||
<A HREF="manual.html#pdf-string.sub">string.sub</A><BR>
|
||||
<A HREF="manual.html#pdf-string.upper">string.upper</A><BR>
|
||||
<P>
|
||||
|
||||
<A HREF="manual.html#pdf-table.concat">table.concat</A><BR>
|
||||
<A HREF="manual.html#pdf-table.insert">table.insert</A><BR>
|
||||
<A HREF="manual.html#pdf-table.maxn">table.maxn</A><BR>
|
||||
<A HREF="manual.html#pdf-table.remove">table.remove</A><BR>
|
||||
<A HREF="manual.html#pdf-table.sort">table.sort</A><BR>
|
||||
|
||||
</TD>
|
||||
<TD>
|
||||
<H3>C API</H3>
|
||||
<A HREF="manual.html#lua_Alloc">lua_Alloc</A><BR>
|
||||
<A HREF="manual.html#lua_CFunction">lua_CFunction</A><BR>
|
||||
<A HREF="manual.html#lua_Debug">lua_Debug</A><BR>
|
||||
<A HREF="manual.html#lua_Hook">lua_Hook</A><BR>
|
||||
<A HREF="manual.html#lua_Integer">lua_Integer</A><BR>
|
||||
<A HREF="manual.html#lua_Number">lua_Number</A><BR>
|
||||
<A HREF="manual.html#lua_Reader">lua_Reader</A><BR>
|
||||
<A HREF="manual.html#lua_State">lua_State</A><BR>
|
||||
<A HREF="manual.html#lua_Writer">lua_Writer</A><BR>
|
||||
<P>
|
||||
|
||||
<A HREF="manual.html#lua_atpanic">lua_atpanic</A><BR>
|
||||
<A HREF="manual.html#lua_call">lua_call</A><BR>
|
||||
<A HREF="manual.html#lua_checkstack">lua_checkstack</A><BR>
|
||||
<A HREF="manual.html#lua_close">lua_close</A><BR>
|
||||
<A HREF="manual.html#lua_concat">lua_concat</A><BR>
|
||||
<A HREF="manual.html#lua_cpcall">lua_cpcall</A><BR>
|
||||
<A HREF="manual.html#lua_createtable">lua_createtable</A><BR>
|
||||
<A HREF="manual.html#lua_dump">lua_dump</A><BR>
|
||||
<A HREF="manual.html#lua_equal">lua_equal</A><BR>
|
||||
<A HREF="manual.html#lua_error">lua_error</A><BR>
|
||||
<A HREF="manual.html#lua_gc">lua_gc</A><BR>
|
||||
<A HREF="manual.html#lua_getallocf">lua_getallocf</A><BR>
|
||||
<A HREF="manual.html#lua_getfenv">lua_getfenv</A><BR>
|
||||
<A HREF="manual.html#lua_getfield">lua_getfield</A><BR>
|
||||
<A HREF="manual.html#lua_getglobal">lua_getglobal</A><BR>
|
||||
<A HREF="manual.html#lua_gethook">lua_gethook</A><BR>
|
||||
<A HREF="manual.html#lua_gethookcount">lua_gethookcount</A><BR>
|
||||
<A HREF="manual.html#lua_gethookmask">lua_gethookmask</A><BR>
|
||||
<A HREF="manual.html#lua_getinfo">lua_getinfo</A><BR>
|
||||
<A HREF="manual.html#lua_getlocal">lua_getlocal</A><BR>
|
||||
<A HREF="manual.html#lua_getmetatable">lua_getmetatable</A><BR>
|
||||
<A HREF="manual.html#lua_getstack">lua_getstack</A><BR>
|
||||
<A HREF="manual.html#lua_gettable">lua_gettable</A><BR>
|
||||
<A HREF="manual.html#lua_gettop">lua_gettop</A><BR>
|
||||
<A HREF="manual.html#lua_getupvalue">lua_getupvalue</A><BR>
|
||||
<A HREF="manual.html#lua_insert">lua_insert</A><BR>
|
||||
<A HREF="manual.html#lua_isboolean">lua_isboolean</A><BR>
|
||||
<A HREF="manual.html#lua_iscfunction">lua_iscfunction</A><BR>
|
||||
<A HREF="manual.html#lua_isfunction">lua_isfunction</A><BR>
|
||||
<A HREF="manual.html#lua_islightuserdata">lua_islightuserdata</A><BR>
|
||||
<A HREF="manual.html#lua_isnil">lua_isnil</A><BR>
|
||||
<A HREF="manual.html#lua_isnone">lua_isnone</A><BR>
|
||||
<A HREF="manual.html#lua_isnoneornil">lua_isnoneornil</A><BR>
|
||||
<A HREF="manual.html#lua_isnumber">lua_isnumber</A><BR>
|
||||
<A HREF="manual.html#lua_isstring">lua_isstring</A><BR>
|
||||
<A HREF="manual.html#lua_istable">lua_istable</A><BR>
|
||||
<A HREF="manual.html#lua_isthread">lua_isthread</A><BR>
|
||||
<A HREF="manual.html#lua_isuserdata">lua_isuserdata</A><BR>
|
||||
<A HREF="manual.html#lua_lessthan">lua_lessthan</A><BR>
|
||||
<A HREF="manual.html#lua_load">lua_load</A><BR>
|
||||
<A HREF="manual.html#lua_newstate">lua_newstate</A><BR>
|
||||
<A HREF="manual.html#lua_newtable">lua_newtable</A><BR>
|
||||
<A HREF="manual.html#lua_newthread">lua_newthread</A><BR>
|
||||
<A HREF="manual.html#lua_newuserdata">lua_newuserdata</A><BR>
|
||||
<A HREF="manual.html#lua_next">lua_next</A><BR>
|
||||
<A HREF="manual.html#lua_objlen">lua_objlen</A><BR>
|
||||
<A HREF="manual.html#lua_pcall">lua_pcall</A><BR>
|
||||
<A HREF="manual.html#lua_pop">lua_pop</A><BR>
|
||||
<A HREF="manual.html#lua_pushboolean">lua_pushboolean</A><BR>
|
||||
<A HREF="manual.html#lua_pushcclosure">lua_pushcclosure</A><BR>
|
||||
<A HREF="manual.html#lua_pushcfunction">lua_pushcfunction</A><BR>
|
||||
<A HREF="manual.html#lua_pushfstring">lua_pushfstring</A><BR>
|
||||
<A HREF="manual.html#lua_pushinteger">lua_pushinteger</A><BR>
|
||||
<A HREF="manual.html#lua_pushlightuserdata">lua_pushlightuserdata</A><BR>
|
||||
<A HREF="manual.html#lua_pushliteral">lua_pushliteral</A><BR>
|
||||
<A HREF="manual.html#lua_pushlstring">lua_pushlstring</A><BR>
|
||||
<A HREF="manual.html#lua_pushnil">lua_pushnil</A><BR>
|
||||
<A HREF="manual.html#lua_pushnumber">lua_pushnumber</A><BR>
|
||||
<A HREF="manual.html#lua_pushstring">lua_pushstring</A><BR>
|
||||
<A HREF="manual.html#lua_pushthread">lua_pushthread</A><BR>
|
||||
<A HREF="manual.html#lua_pushvalue">lua_pushvalue</A><BR>
|
||||
<A HREF="manual.html#lua_pushvfstring">lua_pushvfstring</A><BR>
|
||||
<A HREF="manual.html#lua_rawequal">lua_rawequal</A><BR>
|
||||
<A HREF="manual.html#lua_rawget">lua_rawget</A><BR>
|
||||
<A HREF="manual.html#lua_rawgeti">lua_rawgeti</A><BR>
|
||||
<A HREF="manual.html#lua_rawset">lua_rawset</A><BR>
|
||||
<A HREF="manual.html#lua_rawseti">lua_rawseti</A><BR>
|
||||
<A HREF="manual.html#lua_register">lua_register</A><BR>
|
||||
<A HREF="manual.html#lua_remove">lua_remove</A><BR>
|
||||
<A HREF="manual.html#lua_replace">lua_replace</A><BR>
|
||||
<A HREF="manual.html#lua_resume">lua_resume</A><BR>
|
||||
<A HREF="manual.html#lua_setallocf">lua_setallocf</A><BR>
|
||||
<A HREF="manual.html#lua_setfenv">lua_setfenv</A><BR>
|
||||
<A HREF="manual.html#lua_setfield">lua_setfield</A><BR>
|
||||
<A HREF="manual.html#lua_setglobal">lua_setglobal</A><BR>
|
||||
<A HREF="manual.html#lua_sethook">lua_sethook</A><BR>
|
||||
<A HREF="manual.html#lua_setlocal">lua_setlocal</A><BR>
|
||||
<A HREF="manual.html#lua_setmetatable">lua_setmetatable</A><BR>
|
||||
<A HREF="manual.html#lua_settable">lua_settable</A><BR>
|
||||
<A HREF="manual.html#lua_settop">lua_settop</A><BR>
|
||||
<A HREF="manual.html#lua_setupvalue">lua_setupvalue</A><BR>
|
||||
<A HREF="manual.html#lua_status">lua_status</A><BR>
|
||||
<A HREF="manual.html#lua_toboolean">lua_toboolean</A><BR>
|
||||
<A HREF="manual.html#lua_tocfunction">lua_tocfunction</A><BR>
|
||||
<A HREF="manual.html#lua_tointeger">lua_tointeger</A><BR>
|
||||
<A HREF="manual.html#lua_tolstring">lua_tolstring</A><BR>
|
||||
<A HREF="manual.html#lua_tonumber">lua_tonumber</A><BR>
|
||||
<A HREF="manual.html#lua_topointer">lua_topointer</A><BR>
|
||||
<A HREF="manual.html#lua_tostring">lua_tostring</A><BR>
|
||||
<A HREF="manual.html#lua_tothread">lua_tothread</A><BR>
|
||||
<A HREF="manual.html#lua_touserdata">lua_touserdata</A><BR>
|
||||
<A HREF="manual.html#lua_type">lua_type</A><BR>
|
||||
<A HREF="manual.html#lua_typename">lua_typename</A><BR>
|
||||
<A HREF="manual.html#lua_upvalueindex">lua_upvalueindex</A><BR>
|
||||
<A HREF="manual.html#lua_xmove">lua_xmove</A><BR>
|
||||
<A HREF="manual.html#lua_yield">lua_yield</A><BR>
|
||||
|
||||
</TD>
|
||||
<TD>
|
||||
<H3>auxiliary library</H3>
|
||||
<A HREF="manual.html#luaL_Buffer">luaL_Buffer</A><BR>
|
||||
<A HREF="manual.html#luaL_Reg">luaL_Reg</A><BR>
|
||||
<P>
|
||||
|
||||
<A HREF="manual.html#luaL_addchar">luaL_addchar</A><BR>
|
||||
<A HREF="manual.html#luaL_addlstring">luaL_addlstring</A><BR>
|
||||
<A HREF="manual.html#luaL_addsize">luaL_addsize</A><BR>
|
||||
<A HREF="manual.html#luaL_addstring">luaL_addstring</A><BR>
|
||||
<A HREF="manual.html#luaL_addvalue">luaL_addvalue</A><BR>
|
||||
<A HREF="manual.html#luaL_argcheck">luaL_argcheck</A><BR>
|
||||
<A HREF="manual.html#luaL_argerror">luaL_argerror</A><BR>
|
||||
<A HREF="manual.html#luaL_buffinit">luaL_buffinit</A><BR>
|
||||
<A HREF="manual.html#luaL_callmeta">luaL_callmeta</A><BR>
|
||||
<A HREF="manual.html#luaL_checkany">luaL_checkany</A><BR>
|
||||
<A HREF="manual.html#luaL_checkint">luaL_checkint</A><BR>
|
||||
<A HREF="manual.html#luaL_checkinteger">luaL_checkinteger</A><BR>
|
||||
<A HREF="manual.html#luaL_checklong">luaL_checklong</A><BR>
|
||||
<A HREF="manual.html#luaL_checklstring">luaL_checklstring</A><BR>
|
||||
<A HREF="manual.html#luaL_checknumber">luaL_checknumber</A><BR>
|
||||
<A HREF="manual.html#luaL_checkoption">luaL_checkoption</A><BR>
|
||||
<A HREF="manual.html#luaL_checkstack">luaL_checkstack</A><BR>
|
||||
<A HREF="manual.html#luaL_checkstring">luaL_checkstring</A><BR>
|
||||
<A HREF="manual.html#luaL_checktype">luaL_checktype</A><BR>
|
||||
<A HREF="manual.html#luaL_checkudata">luaL_checkudata</A><BR>
|
||||
<A HREF="manual.html#luaL_dofile">luaL_dofile</A><BR>
|
||||
<A HREF="manual.html#luaL_dostring">luaL_dostring</A><BR>
|
||||
<A HREF="manual.html#luaL_error">luaL_error</A><BR>
|
||||
<A HREF="manual.html#luaL_getmetafield">luaL_getmetafield</A><BR>
|
||||
<A HREF="manual.html#luaL_getmetatable">luaL_getmetatable</A><BR>
|
||||
<A HREF="manual.html#luaL_gsub">luaL_gsub</A><BR>
|
||||
<A HREF="manual.html#luaL_loadbuffer">luaL_loadbuffer</A><BR>
|
||||
<A HREF="manual.html#luaL_loadfile">luaL_loadfile</A><BR>
|
||||
<A HREF="manual.html#luaL_loadstring">luaL_loadstring</A><BR>
|
||||
<A HREF="manual.html#luaL_newmetatable">luaL_newmetatable</A><BR>
|
||||
<A HREF="manual.html#luaL_newstate">luaL_newstate</A><BR>
|
||||
<A HREF="manual.html#luaL_openlibs">luaL_openlibs</A><BR>
|
||||
<A HREF="manual.html#luaL_optint">luaL_optint</A><BR>
|
||||
<A HREF="manual.html#luaL_optinteger">luaL_optinteger</A><BR>
|
||||
<A HREF="manual.html#luaL_optlong">luaL_optlong</A><BR>
|
||||
<A HREF="manual.html#luaL_optlstring">luaL_optlstring</A><BR>
|
||||
<A HREF="manual.html#luaL_optnumber">luaL_optnumber</A><BR>
|
||||
<A HREF="manual.html#luaL_optstring">luaL_optstring</A><BR>
|
||||
<A HREF="manual.html#luaL_prepbuffer">luaL_prepbuffer</A><BR>
|
||||
<A HREF="manual.html#luaL_pushresult">luaL_pushresult</A><BR>
|
||||
<A HREF="manual.html#luaL_ref">luaL_ref</A><BR>
|
||||
<A HREF="manual.html#luaL_register">luaL_register</A><BR>
|
||||
<A HREF="manual.html#luaL_typename">luaL_typename</A><BR>
|
||||
<A HREF="manual.html#luaL_typerror">luaL_typerror</A><BR>
|
||||
<A HREF="manual.html#luaL_unref">luaL_unref</A><BR>
|
||||
<A HREF="manual.html#luaL_where">luaL_where</A><BR>
|
||||
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
<SMALL>
|
||||
Last update:
|
||||
Sat Jan 19 13:24:29 BRST 2008
|
||||
</SMALL>
|
||||
<!--
|
||||
Last change: revised for Lua 5.1.3
|
||||
-->
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
Vendored
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 3.2 KiB |
Vendored
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 4.1 KiB |
Vendored
-163
@@ -1,163 +0,0 @@
|
||||
.\" $Id: lua.man,v 1.11 2006/01/06 16:03:34 lhf Exp $
|
||||
.TH LUA 1 "$Date: 2006/01/06 16:03:34 $"
|
||||
.SH NAME
|
||||
lua \- Lua interpreter
|
||||
.SH SYNOPSIS
|
||||
.B lua
|
||||
[
|
||||
.I options
|
||||
]
|
||||
[
|
||||
.I script
|
||||
[
|
||||
.I args
|
||||
]
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B lua
|
||||
is the stand-alone Lua interpreter.
|
||||
It loads and executes Lua programs,
|
||||
either in textual source form or
|
||||
in precompiled binary form.
|
||||
(Precompiled binaries are output by
|
||||
.BR luac ,
|
||||
the Lua compiler.)
|
||||
.B lua
|
||||
can be used as a batch interpreter and also interactively.
|
||||
.LP
|
||||
The given
|
||||
.I options
|
||||
(see below)
|
||||
are executed and then
|
||||
the Lua program in file
|
||||
.I script
|
||||
is loaded and executed.
|
||||
The given
|
||||
.I args
|
||||
are available to
|
||||
.I script
|
||||
as strings in a global table named
|
||||
.BR arg .
|
||||
If these arguments contain spaces or other characters special to the shell,
|
||||
then they should be quoted
|
||||
(but note that the quotes will be removed by the shell).
|
||||
The arguments in
|
||||
.B arg
|
||||
start at 0,
|
||||
which contains the string
|
||||
.RI ' script '.
|
||||
The index of the last argument is stored in
|
||||
.BR arg.n .
|
||||
The arguments given in the command line before
|
||||
.IR script ,
|
||||
including the name of the interpreter,
|
||||
are available in negative indices in
|
||||
.BR arg .
|
||||
.LP
|
||||
At the very start,
|
||||
before even handling the command line,
|
||||
.B lua
|
||||
executes the contents of the environment variable
|
||||
.BR LUA_INIT ,
|
||||
if it is defined.
|
||||
If the value of
|
||||
.B LUA_INIT
|
||||
is of the form
|
||||
.RI '@ filename ',
|
||||
then
|
||||
.I filename
|
||||
is executed.
|
||||
Otherwise, the string is assumed to be a Lua statement and is executed.
|
||||
.LP
|
||||
Options start with
|
||||
.B '\-'
|
||||
and are described below.
|
||||
You can use
|
||||
.B "'\--'"
|
||||
to signal the end of options.
|
||||
.LP
|
||||
If no arguments are given,
|
||||
then
|
||||
.B "\-v \-i"
|
||||
is assumed when the standard input is a terminal;
|
||||
otherwise,
|
||||
.B "\-"
|
||||
is assumed.
|
||||
.LP
|
||||
In interactive mode,
|
||||
.B lua
|
||||
prompts the user,
|
||||
reads lines from the standard input,
|
||||
and executes them as they are read.
|
||||
If a line does not contain a complete statement,
|
||||
then a secondary prompt is displayed and
|
||||
lines are read until a complete statement is formed or
|
||||
a syntax error is found.
|
||||
So, one way to interrupt the reading of an incomplete statement is
|
||||
to force a syntax error:
|
||||
adding a
|
||||
.B ';'
|
||||
in the middle of a statement is a sure way of forcing a syntax error
|
||||
(except inside multiline strings and comments; these must be closed explicitly).
|
||||
If a line starts with
|
||||
.BR '=' ,
|
||||
then
|
||||
.B lua
|
||||
displays the values of all the expressions in the remainder of the
|
||||
line. The expressions must be separated by commas.
|
||||
The primary prompt is the value of the global variable
|
||||
.BR _PROMPT ,
|
||||
if this value is a string;
|
||||
otherwise, the default prompt is used.
|
||||
Similarly, the secondary prompt is the value of the global variable
|
||||
.BR _PROMPT2 .
|
||||
So,
|
||||
to change the prompts,
|
||||
set the corresponding variable to a string of your choice.
|
||||
You can do that after calling the interpreter
|
||||
or on the command line
|
||||
(but in this case you have to be careful with quotes
|
||||
if the prompt string contains a space; otherwise you may confuse the shell.)
|
||||
The default prompts are "> " and ">> ".
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-
|
||||
load and execute the standard input as a file,
|
||||
that is,
|
||||
not interactively,
|
||||
even when the standard input is a terminal.
|
||||
.TP
|
||||
.BI \-e " stat"
|
||||
execute statement
|
||||
.IR stat .
|
||||
You need to quote
|
||||
.I stat
|
||||
if it contains spaces, quotes,
|
||||
or other characters special to the shell.
|
||||
.TP
|
||||
.B \-i
|
||||
enter interactive mode after
|
||||
.I script
|
||||
is executed.
|
||||
.TP
|
||||
.BI \-l " name"
|
||||
call
|
||||
.BI require(' name ')
|
||||
before executing
|
||||
.IR script .
|
||||
Typically used to load libraries.
|
||||
.TP
|
||||
.B \-v
|
||||
show version information.
|
||||
.SH "SEE ALSO"
|
||||
.BR luac (1)
|
||||
.br
|
||||
http://www.lua.org/
|
||||
.SH DIAGNOSTICS
|
||||
Error messages should be self explanatory.
|
||||
.SH AUTHORS
|
||||
R. Ierusalimschy,
|
||||
L. H. de Figueiredo,
|
||||
and
|
||||
W. Celes
|
||||
.\" EOF
|
||||
Vendored
-41
@@ -1,41 +0,0 @@
|
||||
body {
|
||||
color: #000000 ;
|
||||
background-color: #FFFFFF ;
|
||||
font-family: sans-serif ;
|
||||
text-align: justify ;
|
||||
margin-right: 20px ;
|
||||
margin-left: 20px ;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-weight: normal ;
|
||||
font-style: italic ;
|
||||
}
|
||||
|
||||
a:link {
|
||||
color: #000080 ;
|
||||
background-color: inherit ;
|
||||
text-decoration: none ;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
background-color: inherit ;
|
||||
text-decoration: none ;
|
||||
}
|
||||
|
||||
a:link:hover, a:visited:hover {
|
||||
color: #000080 ;
|
||||
background-color: #E0E0FF ;
|
||||
}
|
||||
|
||||
a:link:active, a:visited:active {
|
||||
color: #FF0000 ;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0 ;
|
||||
height: 1px ;
|
||||
color: #a0a0a0 ;
|
||||
background-color: #a0a0a0 ;
|
||||
}
|
||||
|
||||
Vendored
-172
@@ -1,172 +0,0 @@
|
||||
<!-- $Id: lua.man,v 1.11 2006/01/06 16:03:34 lhf Exp $ -->
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>LUA man page</TITLE>
|
||||
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR="#FFFFFF">
|
||||
|
||||
<H2>NAME</H2>
|
||||
lua - Lua interpreter
|
||||
<H2>SYNOPSIS</H2>
|
||||
<B>lua</B>
|
||||
[
|
||||
<I>options</I>
|
||||
]
|
||||
[
|
||||
<I>script</I>
|
||||
[
|
||||
<I>args</I>
|
||||
]
|
||||
]
|
||||
<H2>DESCRIPTION</H2>
|
||||
<B>lua</B>
|
||||
is the stand-alone Lua interpreter.
|
||||
It loads and executes Lua programs,
|
||||
either in textual source form or
|
||||
in precompiled binary form.
|
||||
(Precompiled binaries are output by
|
||||
<B>luac</B>,
|
||||
the Lua compiler.)
|
||||
<B>lua</B>
|
||||
can be used as a batch interpreter and also interactively.
|
||||
<P>
|
||||
The given
|
||||
<I>options</I>
|
||||
(see below)
|
||||
are executed and then
|
||||
the Lua program in file
|
||||
<I>script</I>
|
||||
is loaded and executed.
|
||||
The given
|
||||
<I>args</I>
|
||||
are available to
|
||||
<I>script</I>
|
||||
as strings in a global table named
|
||||
<B>arg</B>.
|
||||
If these arguments contain spaces or other characters special to the shell,
|
||||
then they should be quoted
|
||||
(but note that the quotes will be removed by the shell).
|
||||
The arguments in
|
||||
<B>arg</B>
|
||||
start at 0,
|
||||
which contains the string
|
||||
'<I>script</I>'.
|
||||
The index of the last argument is stored in
|
||||
<B>arg.n</B>.
|
||||
The arguments given in the command line before
|
||||
<I>script</I>,
|
||||
including the name of the interpreter,
|
||||
are available in negative indices in
|
||||
<B>arg</B>.
|
||||
<P>
|
||||
At the very start,
|
||||
before even handling the command line,
|
||||
<B>lua</B>
|
||||
executes the contents of the environment variable
|
||||
<B>LUA_INIT</B>,
|
||||
if it is defined.
|
||||
If the value of
|
||||
<B>LUA_INIT</B>
|
||||
is of the form
|
||||
'@<I>filename</I>',
|
||||
then
|
||||
<I>filename</I>
|
||||
is executed.
|
||||
Otherwise, the string is assumed to be a Lua statement and is executed.
|
||||
<P>
|
||||
Options start with
|
||||
<B>'-'</B>
|
||||
and are described below.
|
||||
You can use
|
||||
<B>'--'</B>
|
||||
to signal the end of options.
|
||||
<P>
|
||||
If no arguments are given,
|
||||
then
|
||||
<B>"-v -i"</B>
|
||||
is assumed when the standard input is a terminal;
|
||||
otherwise,
|
||||
<B>"-"</B>
|
||||
is assumed.
|
||||
<P>
|
||||
In interactive mode,
|
||||
<B>lua</B>
|
||||
prompts the user,
|
||||
reads lines from the standard input,
|
||||
and executes them as they are read.
|
||||
If a line does not contain a complete statement,
|
||||
then a secondary prompt is displayed and
|
||||
lines are read until a complete statement is formed or
|
||||
a syntax error is found.
|
||||
So, one way to interrupt the reading of an incomplete statement is
|
||||
to force a syntax error:
|
||||
adding a
|
||||
<B>';'</B>
|
||||
in the middle of a statement is a sure way of forcing a syntax error
|
||||
(except inside multiline strings and comments; these must be closed explicitly).
|
||||
If a line starts with
|
||||
<B>'='</B>,
|
||||
then
|
||||
<B>lua</B>
|
||||
displays the values of all the expressions in the remainder of the
|
||||
line. The expressions must be separated by commas.
|
||||
The primary prompt is the value of the global variable
|
||||
<B>_PROMPT</B>,
|
||||
if this value is a string;
|
||||
otherwise, the default prompt is used.
|
||||
Similarly, the secondary prompt is the value of the global variable
|
||||
<B>_PROMPT2</B>.
|
||||
So,
|
||||
to change the prompts,
|
||||
set the corresponding variable to a string of your choice.
|
||||
You can do that after calling the interpreter
|
||||
or on the command line
|
||||
(but in this case you have to be careful with quotes
|
||||
if the prompt string contains a space; otherwise you may confuse the shell.)
|
||||
The default prompts are "> " and ">> ".
|
||||
<H2>OPTIONS</H2>
|
||||
<P>
|
||||
<B>-</B>
|
||||
load and execute the standard input as a file,
|
||||
that is,
|
||||
not interactively,
|
||||
even when the standard input is a terminal.
|
||||
<P>
|
||||
<B>-e </B><I>stat</I>
|
||||
execute statement
|
||||
<I>stat</I>.
|
||||
You need to quote
|
||||
<I>stat </I>
|
||||
if it contains spaces, quotes,
|
||||
or other characters special to the shell.
|
||||
<P>
|
||||
<B>-i</B>
|
||||
enter interactive mode after
|
||||
<I>script</I>
|
||||
is executed.
|
||||
<P>
|
||||
<B>-l </B><I>name</I>
|
||||
call
|
||||
<B>require</B>('<I>name</I>')
|
||||
before executing
|
||||
<I>script</I>.
|
||||
Typically used to load libraries.
|
||||
<P>
|
||||
<B>-v</B>
|
||||
show version information.
|
||||
<H2>SEE ALSO</H2>
|
||||
<B>luac</B>(1)
|
||||
<BR>
|
||||
<A HREF="http://www.lua.org/">http://www.lua.org/</A>
|
||||
<H2>DIAGNOSTICS</H2>
|
||||
Error messages should be self explanatory.
|
||||
<H2>AUTHORS</H2>
|
||||
R. Ierusalimschy,
|
||||
L. H. de Figueiredo,
|
||||
and
|
||||
W. Celes
|
||||
<!-- EOF -->
|
||||
</BODY>
|
||||
</HTML>
|
||||
Vendored
-136
@@ -1,136 +0,0 @@
|
||||
.\" $Id: luac.man,v 1.28 2006/01/06 16:03:34 lhf Exp $
|
||||
.TH LUAC 1 "$Date: 2006/01/06 16:03:34 $"
|
||||
.SH NAME
|
||||
luac \- Lua compiler
|
||||
.SH SYNOPSIS
|
||||
.B luac
|
||||
[
|
||||
.I options
|
||||
] [
|
||||
.I filenames
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B luac
|
||||
is the Lua compiler.
|
||||
It translates programs written in the Lua programming language
|
||||
into binary files that can be later loaded and executed.
|
||||
.LP
|
||||
The main advantages of precompiling chunks are:
|
||||
faster loading,
|
||||
protecting source code from accidental user changes,
|
||||
and
|
||||
off-line syntax checking.
|
||||
.LP
|
||||
Pre-compiling does not imply faster execution
|
||||
because in Lua chunks are always compiled into bytecodes before being executed.
|
||||
.B luac
|
||||
simply allows those bytecodes to be saved in a file for later execution.
|
||||
.LP
|
||||
Pre-compiled chunks are not necessarily smaller than the corresponding source.
|
||||
The main goal in pre-compiling is faster loading.
|
||||
.LP
|
||||
The binary files created by
|
||||
.B luac
|
||||
are portable only among architectures with the same word size and byte order.
|
||||
.LP
|
||||
.B luac
|
||||
produces a single output file containing the bytecodes
|
||||
for all source files given.
|
||||
By default,
|
||||
the output file is named
|
||||
.BR luac.out ,
|
||||
but you can change this with the
|
||||
.B \-o
|
||||
option.
|
||||
.LP
|
||||
In the command line,
|
||||
you can mix
|
||||
text files containing Lua source and
|
||||
binary files containing precompiled chunks.
|
||||
This is useful to combine several precompiled chunks,
|
||||
even from different (but compatible) platforms,
|
||||
into a single precompiled chunk.
|
||||
.LP
|
||||
You can use
|
||||
.B "'\-'"
|
||||
to indicate the standard input as a source file
|
||||
and
|
||||
.B "'\--'"
|
||||
to signal the end of options
|
||||
(that is,
|
||||
all remaining arguments will be treated as files even if they start with
|
||||
.BR "'\-'" ).
|
||||
.LP
|
||||
The internal format of the binary files produced by
|
||||
.B luac
|
||||
is likely to change when a new version of Lua is released.
|
||||
So,
|
||||
save the source files of all Lua programs that you precompile.
|
||||
.LP
|
||||
.SH OPTIONS
|
||||
Options must be separate.
|
||||
.TP
|
||||
.B \-l
|
||||
produce a listing of the compiled bytecode for Lua's virtual machine.
|
||||
Listing bytecodes is useful to learn about Lua's virtual machine.
|
||||
If no files are given, then
|
||||
.B luac
|
||||
loads
|
||||
.B luac.out
|
||||
and lists its contents.
|
||||
.TP
|
||||
.BI \-o " file"
|
||||
output to
|
||||
.IR file ,
|
||||
instead of the default
|
||||
.BR luac.out .
|
||||
(You can use
|
||||
.B "'\-'"
|
||||
for standard output,
|
||||
but not on platforms that open standard output in text mode.)
|
||||
The output file may be a source file because
|
||||
all files are loaded before the output file is written.
|
||||
Be careful not to overwrite precious files.
|
||||
.TP
|
||||
.B \-p
|
||||
load files but do not generate any output file.
|
||||
Used mainly for syntax checking and for testing precompiled chunks:
|
||||
corrupted files will probably generate errors when loaded.
|
||||
Lua always performs a thorough integrity test on precompiled chunks.
|
||||
Bytecode that passes this test is completely safe,
|
||||
in the sense that it will not break the interpreter.
|
||||
However,
|
||||
there is no guarantee that such code does anything sensible.
|
||||
(None can be given, because the halting problem is unsolvable.)
|
||||
If no files are given, then
|
||||
.B luac
|
||||
loads
|
||||
.B luac.out
|
||||
and tests its contents.
|
||||
No messages are displayed if the file passes the integrity test.
|
||||
.TP
|
||||
.B \-s
|
||||
strip debug information before writing the output file.
|
||||
This saves some space in very large chunks,
|
||||
but if errors occur when running a stripped chunk,
|
||||
then the error messages may not contain the full information they usually do.
|
||||
For instance,
|
||||
line numbers and names of local variables are lost.
|
||||
.TP
|
||||
.B \-v
|
||||
show version information.
|
||||
.SH FILES
|
||||
.TP 15
|
||||
.B luac.out
|
||||
default output file
|
||||
.SH "SEE ALSO"
|
||||
.BR lua (1)
|
||||
.br
|
||||
http://www.lua.org/
|
||||
.SH DIAGNOSTICS
|
||||
Error messages should be self explanatory.
|
||||
.SH AUTHORS
|
||||
L. H. de Figueiredo,
|
||||
R. Ierusalimschy and
|
||||
W. Celes
|
||||
.\" EOF
|
||||
Vendored
-145
@@ -1,145 +0,0 @@
|
||||
<!-- $Id: luac.man,v 1.28 2006/01/06 16:03:34 lhf Exp $ -->
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>LUAC man page</TITLE>
|
||||
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR="#FFFFFF">
|
||||
|
||||
<H2>NAME</H2>
|
||||
luac - Lua compiler
|
||||
<H2>SYNOPSIS</H2>
|
||||
<B>luac</B>
|
||||
[
|
||||
<I>options</I>
|
||||
] [
|
||||
<I>filenames</I>
|
||||
]
|
||||
<H2>DESCRIPTION</H2>
|
||||
<B>luac</B>
|
||||
is the Lua compiler.
|
||||
It translates programs written in the Lua programming language
|
||||
into binary files that can be later loaded and executed.
|
||||
<P>
|
||||
The main advantages of precompiling chunks are:
|
||||
faster loading,
|
||||
protecting source code from accidental user changes,
|
||||
and
|
||||
off-line syntax checking.
|
||||
<P>
|
||||
Precompiling does not imply faster execution
|
||||
because in Lua chunks are always compiled into bytecodes before being executed.
|
||||
<B>luac</B>
|
||||
simply allows those bytecodes to be saved in a file for later execution.
|
||||
<P>
|
||||
Precompiled chunks are not necessarily smaller than the corresponding source.
|
||||
The main goal in precompiling is faster loading.
|
||||
<P>
|
||||
The binary files created by
|
||||
<B>luac</B>
|
||||
are portable only among architectures with the same word size and byte order.
|
||||
<P>
|
||||
<B>luac</B>
|
||||
produces a single output file containing the bytecodes
|
||||
for all source files given.
|
||||
By default,
|
||||
the output file is named
|
||||
<B>luac.out</B>,
|
||||
but you can change this with the
|
||||
<B>-o</B>
|
||||
option.
|
||||
<P>
|
||||
In the command line,
|
||||
you can mix
|
||||
text files containing Lua source and
|
||||
binary files containing precompiled chunks.
|
||||
This is useful because several precompiled chunks,
|
||||
even from different (but compatible) platforms,
|
||||
can be combined into a single precompiled chunk.
|
||||
<P>
|
||||
You can use
|
||||
<B>'-'</B>
|
||||
to indicate the standard input as a source file
|
||||
and
|
||||
<B>'--'</B>
|
||||
to signal the end of options
|
||||
(that is,
|
||||
all remaining arguments will be treated as files even if they start with
|
||||
<B>'-'</B>).
|
||||
<P>
|
||||
The internal format of the binary files produced by
|
||||
<B>luac</B>
|
||||
is likely to change when a new version of Lua is released.
|
||||
So,
|
||||
save the source files of all Lua programs that you precompile.
|
||||
<P>
|
||||
<H2>OPTIONS</H2>
|
||||
Options must be separate.
|
||||
<P>
|
||||
<B>-l</B>
|
||||
produce a listing of the compiled bytecode for Lua's virtual machine.
|
||||
Listing bytecodes is useful to learn about Lua's virtual machine.
|
||||
If no files are given, then
|
||||
<B>luac</B>
|
||||
loads
|
||||
<B>luac.out</B>
|
||||
and lists its contents.
|
||||
<P>
|
||||
<B>-o </B><I>file</I>
|
||||
output to
|
||||
<I>file</I>,
|
||||
instead of the default
|
||||
<B>luac.out</B>.
|
||||
(You can use
|
||||
<B>'-'</B>
|
||||
for standard output,
|
||||
but not on platforms that open standard output in text mode.)
|
||||
The output file may be a source file because
|
||||
all files are loaded before the output file is written.
|
||||
Be careful not to overwrite precious files.
|
||||
<P>
|
||||
<B>-p</B>
|
||||
load files but do not generate any output file.
|
||||
Used mainly for syntax checking and for testing precompiled chunks:
|
||||
corrupted files will probably generate errors when loaded.
|
||||
Lua always performs a thorough integrity test on precompiled chunks.
|
||||
Bytecode that passes this test is completely safe,
|
||||
in the sense that it will not break the interpreter.
|
||||
However,
|
||||
there is no guarantee that such code does anything sensible.
|
||||
(None can be given, because the halting problem is unsolvable.)
|
||||
If no files are given, then
|
||||
<B>luac</B>
|
||||
loads
|
||||
<B>luac.out</B>
|
||||
and tests its contents.
|
||||
No messages are displayed if the file passes the integrity test.
|
||||
<P>
|
||||
<B>-s</B>
|
||||
strip debug information before writing the output file.
|
||||
This saves some space in very large chunks,
|
||||
but if errors occur when running a stripped chunk,
|
||||
then the error messages may not contain the full information they usually do.
|
||||
For instance,
|
||||
line numbers and names of local variables are lost.
|
||||
<P>
|
||||
<B>-v</B>
|
||||
show version information.
|
||||
<H2>FILES</H2>
|
||||
<P>
|
||||
<B>luac.out</B>
|
||||
default output file
|
||||
<H2>SEE ALSO</H2>
|
||||
<B>lua</B>(1)
|
||||
<BR>
|
||||
<A HREF="http://www.lua.org/">http://www.lua.org/</A>
|
||||
<H2>DIAGNOSTICS</H2>
|
||||
Error messages should be self explanatory.
|
||||
<H2>AUTHORS</H2>
|
||||
L. H. de Figueiredo,
|
||||
R. Ierusalimschy and
|
||||
W. Celes
|
||||
<!-- EOF -->
|
||||
</BODY>
|
||||
</HTML>
|
||||
Vendored
-13
@@ -1,13 +0,0 @@
|
||||
h3 code {
|
||||
font-family: inherit ;
|
||||
}
|
||||
|
||||
pre {
|
||||
font-size: 105% ;
|
||||
}
|
||||
|
||||
span.apii {
|
||||
float: right ;
|
||||
font-family: inherit ;
|
||||
}
|
||||
|
||||
Vendored
-8801
File diff suppressed because it is too large
Load Diff
Vendored
-40
@@ -1,40 +0,0 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Lua documentation</TITLE>
|
||||
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
|
||||
</HEAD>
|
||||
|
||||
<BODY>
|
||||
|
||||
<HR>
|
||||
<H1>
|
||||
<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua" BORDER=0></A>
|
||||
Documentation
|
||||
</H1>
|
||||
|
||||
This is the documentation included in the source distribution of Lua 5.1.4.
|
||||
|
||||
<UL>
|
||||
<LI><A HREF="contents.html">Reference manual</A>
|
||||
<LI><A HREF="lua.html">lua man page</A>
|
||||
<LI><A HREF="luac.html">luac man page</A>
|
||||
<LI><A HREF="../README">lua/README</A>
|
||||
<LI><A HREF="../etc/README">lua/etc/README</A>
|
||||
<LI><A HREF="../test/README">lua/test/README</A>
|
||||
</UL>
|
||||
|
||||
Lua's
|
||||
<A HREF="http://www.lua.org/">official web site</A>
|
||||
contains updated documentation,
|
||||
especially the
|
||||
<A HREF="http://www.lua.org/manual/5.1/">reference manual</A>.
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
<SMALL>
|
||||
Last update:
|
||||
Tue Aug 12 14:46:07 BRT 2008
|
||||
</SMALL>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
Vendored
-44
@@ -1,44 +0,0 @@
|
||||
# makefile for Lua etc
|
||||
|
||||
TOP= ..
|
||||
LIB= $(TOP)/src
|
||||
INC= $(TOP)/src
|
||||
BIN= $(TOP)/src
|
||||
SRC= $(TOP)/src
|
||||
TST= $(TOP)/test
|
||||
|
||||
CC= gcc
|
||||
CFLAGS= -O2 -Wall -I$(INC) $(MYCFLAGS)
|
||||
MYCFLAGS=
|
||||
MYLDFLAGS= -Wl,-E
|
||||
MYLIBS= -lm
|
||||
#MYLIBS= -lm -Wl,-E -ldl -lreadline -lhistory -lncurses
|
||||
RM= rm -f
|
||||
|
||||
default:
|
||||
@echo 'Please choose a target: min noparser one strict clean'
|
||||
|
||||
min: min.c
|
||||
$(CC) $(CFLAGS) $@.c -L$(LIB) -llua $(MYLIBS)
|
||||
echo 'print"Hello there!"' | ./a.out
|
||||
|
||||
noparser: noparser.o
|
||||
$(CC) noparser.o $(SRC)/lua.o -L$(LIB) -llua $(MYLIBS)
|
||||
$(BIN)/luac $(TST)/hello.lua
|
||||
-./a.out luac.out
|
||||
-./a.out -e'a=1'
|
||||
|
||||
one:
|
||||
$(CC) $(CFLAGS) all.c $(MYLIBS)
|
||||
./a.out $(TST)/hello.lua
|
||||
|
||||
strict:
|
||||
-$(BIN)/lua -e 'print(a);b=2'
|
||||
-$(BIN)/lua -lstrict -e 'print(a)'
|
||||
-$(BIN)/lua -e 'function f() b=2 end f()'
|
||||
-$(BIN)/lua -lstrict -e 'function f() b=2 end f()'
|
||||
|
||||
clean:
|
||||
$(RM) a.out core core.* *.o luac.out
|
||||
|
||||
.PHONY: default min noparser one strict clean
|
||||
Vendored
-37
@@ -1,37 +0,0 @@
|
||||
This directory contains some useful files and code.
|
||||
Unlike the code in ../src, everything here is in the public domain.
|
||||
|
||||
If any of the makes fail, you're probably not using the same libraries
|
||||
used to build Lua. Set MYLIBS in Makefile accordingly.
|
||||
|
||||
all.c
|
||||
Full Lua interpreter in a single file.
|
||||
Do "make one" for a demo.
|
||||
|
||||
lua.hpp
|
||||
Lua header files for C++ using 'extern "C"'.
|
||||
|
||||
lua.ico
|
||||
A Lua icon for Windows (and web sites: save as favicon.ico).
|
||||
Drawn by hand by Markus Gritsch <gritsch@iue.tuwien.ac.at>.
|
||||
|
||||
lua.pc
|
||||
pkg-config data for Lua
|
||||
|
||||
luavs.bat
|
||||
Script to build Lua under "Visual Studio .NET Command Prompt".
|
||||
Run it from the toplevel as etc\luavs.bat.
|
||||
|
||||
min.c
|
||||
A minimal Lua interpreter.
|
||||
Good for learning and for starting your own.
|
||||
Do "make min" for a demo.
|
||||
|
||||
noparser.c
|
||||
Linking with noparser.o avoids loading the parsing modules in lualib.a.
|
||||
Do "make noparser" for a demo.
|
||||
|
||||
strict.lua
|
||||
Traps uses of undeclared global variables.
|
||||
Do "make strict" for a demo.
|
||||
|
||||
Vendored
-38
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* all.c -- Lua core, libraries and interpreter in a single file
|
||||
*/
|
||||
|
||||
#define luaall_c
|
||||
|
||||
#include "lapi.c"
|
||||
#include "lcode.c"
|
||||
#include "ldebug.c"
|
||||
#include "ldo.c"
|
||||
#include "ldump.c"
|
||||
#include "lfunc.c"
|
||||
#include "lgc.c"
|
||||
#include "llex.c"
|
||||
#include "lmem.c"
|
||||
#include "lobject.c"
|
||||
#include "lopcodes.c"
|
||||
#include "lparser.c"
|
||||
#include "lstate.c"
|
||||
#include "lstring.c"
|
||||
#include "ltable.c"
|
||||
#include "ltm.c"
|
||||
#include "lundump.c"
|
||||
#include "lvm.c"
|
||||
#include "lzio.c"
|
||||
|
||||
#include "lauxlib.c"
|
||||
#include "lbaselib.c"
|
||||
#include "ldblib.c"
|
||||
#include "liolib.c"
|
||||
#include "linit.c"
|
||||
#include "lmathlib.c"
|
||||
#include "loadlib.c"
|
||||
#include "loslib.c"
|
||||
#include "lstrlib.c"
|
||||
#include "ltablib.c"
|
||||
|
||||
#include "lua.c"
|
||||
Vendored
-9
@@ -1,9 +0,0 @@
|
||||
// lua.hpp
|
||||
// Lua header files for C++
|
||||
// <<extern "C">> not supplied automatically because Lua also compiles as C++
|
||||
|
||||
extern "C" {
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
}
|
||||
Vendored
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
Vendored
-31
@@ -1,31 +0,0 @@
|
||||
# lua.pc -- pkg-config data for Lua
|
||||
|
||||
# vars from install Makefile
|
||||
|
||||
# grep '^V=' ../Makefile
|
||||
V= 5.1
|
||||
# grep '^R=' ../Makefile
|
||||
R= 5.1.4
|
||||
|
||||
# grep '^INSTALL_.*=' ../Makefile | sed 's/INSTALL_TOP/prefix/'
|
||||
prefix= /usr/local
|
||||
INSTALL_BIN= ${prefix}/bin
|
||||
INSTALL_INC= ${prefix}/include
|
||||
INSTALL_LIB= ${prefix}/lib
|
||||
INSTALL_MAN= ${prefix}/man/man1
|
||||
INSTALL_LMOD= ${prefix}/share/lua/${V}
|
||||
INSTALL_CMOD= ${prefix}/lib/lua/${V}
|
||||
|
||||
# canonical vars
|
||||
exec_prefix=${prefix}
|
||||
libdir=${exec_prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: Lua
|
||||
Description: An Extensible Extension Language
|
||||
Version: ${R}
|
||||
Requires:
|
||||
Libs: -L${libdir} -llua -lm
|
||||
Cflags: -I${includedir}
|
||||
|
||||
# (end of lua.pc)
|
||||
Vendored
-28
@@ -1,28 +0,0 @@
|
||||
@rem Script to build Lua under "Visual Studio .NET Command Prompt".
|
||||
@rem Do not run from this directory; run it from the toplevel: etc\luavs.bat .
|
||||
@rem It creates lua51.dll, lua51.lib, lua.exe, and luac.exe in src.
|
||||
@rem (contributed by David Manura and Mike Pall)
|
||||
|
||||
@setlocal
|
||||
@set MYCOMPILE=cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE
|
||||
@set MYLINK=link /nologo
|
||||
@set MYMT=mt /nologo
|
||||
|
||||
cd src
|
||||
%MYCOMPILE% /DLUA_BUILD_AS_DLL l*.c
|
||||
del lua.obj luac.obj
|
||||
%MYLINK% /DLL /out:lua51.dll l*.obj
|
||||
if exist lua51.dll.manifest^
|
||||
%MYMT% -manifest lua51.dll.manifest -outputresource:lua51.dll;2
|
||||
%MYCOMPILE% /DLUA_BUILD_AS_DLL lua.c
|
||||
%MYLINK% /out:lua.exe lua.obj lua51.lib
|
||||
if exist lua.exe.manifest^
|
||||
%MYMT% -manifest lua.exe.manifest -outputresource:lua.exe
|
||||
%MYCOMPILE% l*.c print.c
|
||||
del lua.obj linit.obj lbaselib.obj ldblib.obj liolib.obj lmathlib.obj^
|
||||
loslib.obj ltablib.obj lstrlib.obj loadlib.obj
|
||||
%MYLINK% /out:luac.exe *.obj
|
||||
if exist luac.exe.manifest^
|
||||
%MYMT% -manifest luac.exe.manifest -outputresource:luac.exe
|
||||
del *.obj *.manifest
|
||||
cd ..
|
||||
Vendored
-39
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* min.c -- a minimal Lua interpreter
|
||||
* loads stdin only with minimal error handling.
|
||||
* no interaction, and no standard library, only a "print" function.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
|
||||
static int print(lua_State *L)
|
||||
{
|
||||
int n=lua_gettop(L);
|
||||
int i;
|
||||
for (i=1; i<=n; i++)
|
||||
{
|
||||
if (i>1) printf("\t");
|
||||
if (lua_isstring(L,i))
|
||||
printf("%s",lua_tostring(L,i));
|
||||
else if (lua_isnil(L,i))
|
||||
printf("%s","nil");
|
||||
else if (lua_isboolean(L,i))
|
||||
printf("%s",lua_toboolean(L,i) ? "true" : "false");
|
||||
else
|
||||
printf("%s:%p",luaL_typename(L,i),lua_topointer(L,i));
|
||||
}
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
lua_State *L=lua_open();
|
||||
lua_register(L,"print",print);
|
||||
if (luaL_dofile(L,NULL)!=0) fprintf(stderr,"%s\n",lua_tostring(L,-1));
|
||||
lua_close(L);
|
||||
return 0;
|
||||
}
|
||||
Vendored
-50
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* The code below can be used to make a Lua core that does not contain the
|
||||
* parsing modules (lcode, llex, lparser), which represent 35% of the total core.
|
||||
* You'll only be able to load binary files and strings, precompiled with luac.
|
||||
* (Of course, you'll have to build luac with the original parsing modules!)
|
||||
*
|
||||
* To use this module, simply compile it ("make noparser" does that) and list
|
||||
* its object file before the Lua libraries. The linker should then not load
|
||||
* the parsing modules. To try it, do "make luab".
|
||||
*
|
||||
* If you also want to avoid the dump module (ldump.o), define NODUMP.
|
||||
* #define NODUMP
|
||||
*/
|
||||
|
||||
#define LUA_CORE
|
||||
|
||||
#include "llex.h"
|
||||
#include "lparser.h"
|
||||
#include "lzio.h"
|
||||
|
||||
LUAI_FUNC void luaX_init (lua_State *L) {
|
||||
UNUSED(L);
|
||||
}
|
||||
|
||||
LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
|
||||
UNUSED(z);
|
||||
UNUSED(buff);
|
||||
UNUSED(name);
|
||||
lua_pushliteral(L,"parser not loaded");
|
||||
lua_error(L);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef NODUMP
|
||||
#include "lundump.h"
|
||||
|
||||
LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) {
|
||||
UNUSED(f);
|
||||
UNUSED(w);
|
||||
UNUSED(data);
|
||||
UNUSED(strip);
|
||||
#if 1
|
||||
UNUSED(L);
|
||||
return 0;
|
||||
#else
|
||||
lua_pushliteral(L,"dumper not loaded");
|
||||
lua_error(L);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
Vendored
-41
@@ -1,41 +0,0 @@
|
||||
--
|
||||
-- strict.lua
|
||||
-- checks uses of undeclared global variables
|
||||
-- All global variables must be 'declared' through a regular assignment
|
||||
-- (even assigning nil will do) in a main chunk before being used
|
||||
-- anywhere or assigned to inside a function.
|
||||
--
|
||||
|
||||
local getinfo, error, rawset, rawget = debug.getinfo, error, rawset, rawget
|
||||
|
||||
local mt = getmetatable(_G)
|
||||
if mt == nil then
|
||||
mt = {}
|
||||
setmetatable(_G, mt)
|
||||
end
|
||||
|
||||
mt.__declared = {}
|
||||
|
||||
local function what ()
|
||||
local d = getinfo(3, "S")
|
||||
return d and d.what or "C"
|
||||
end
|
||||
|
||||
mt.__newindex = function (t, n, v)
|
||||
if not mt.__declared[n] then
|
||||
local w = what()
|
||||
if w ~= "main" and w ~= "C" then
|
||||
error("assign to undeclared variable '"..n.."'", 2)
|
||||
end
|
||||
mt.__declared[n] = true
|
||||
end
|
||||
rawset(t, n, v)
|
||||
end
|
||||
|
||||
mt.__index = function (t, n)
|
||||
if not mt.__declared[n] and what() ~= "C" then
|
||||
error("variable '"..n.."' is not declared", 2)
|
||||
end
|
||||
return rawget(t, n)
|
||||
end
|
||||
|
||||
Vendored
-182
@@ -1,182 +0,0 @@
|
||||
# makefile for building Lua
|
||||
# see ../INSTALL for installation instructions
|
||||
# see ../Makefile and luaconf.h for further customization
|
||||
|
||||
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
|
||||
|
||||
# Your platform. See PLATS for possible values.
|
||||
PLAT= none
|
||||
|
||||
CC= gcc
|
||||
CFLAGS= -O2 -Wall $(MYCFLAGS)
|
||||
AR= ar rcu
|
||||
RANLIB= ranlib
|
||||
RM= rm -f
|
||||
LIBS= -lm $(MYLIBS)
|
||||
|
||||
MYCFLAGS=
|
||||
MYLDFLAGS=
|
||||
MYLIBS=
|
||||
|
||||
# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
|
||||
|
||||
PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
|
||||
|
||||
LUA_A= liblua.a
|
||||
CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
|
||||
lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \
|
||||
lundump.o lvm.o lzio.o strbuf.o
|
||||
LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
|
||||
lstrlib.o loadlib.o linit.o lua_cjson.o lua_struct.o lua_cmsgpack.o
|
||||
|
||||
LUA_T= lua
|
||||
LUA_O= lua.o
|
||||
|
||||
LUAC_T= luac
|
||||
LUAC_O= luac.o print.o
|
||||
|
||||
ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O)
|
||||
ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
|
||||
ALL_A= $(LUA_A)
|
||||
|
||||
default: $(PLAT)
|
||||
|
||||
all: $(ALL_T)
|
||||
|
||||
o: $(ALL_O)
|
||||
|
||||
a: $(ALL_A)
|
||||
|
||||
$(LUA_A): $(CORE_O) $(LIB_O)
|
||||
$(AR) $@ $?
|
||||
$(RANLIB) $@
|
||||
|
||||
$(LUA_T): $(LUA_O) $(LUA_A)
|
||||
$(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
|
||||
|
||||
$(LUAC_T): $(LUAC_O) $(LUA_A)
|
||||
$(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)
|
||||
|
||||
clean:
|
||||
$(RM) $(ALL_T) $(ALL_O)
|
||||
|
||||
depend:
|
||||
@$(CC) $(CFLAGS) -MM l*.c print.c
|
||||
|
||||
echo:
|
||||
@echo "PLAT = $(PLAT)"
|
||||
@echo "CC = $(CC)"
|
||||
@echo "CFLAGS = $(CFLAGS)"
|
||||
@echo "AR = $(AR)"
|
||||
@echo "RANLIB = $(RANLIB)"
|
||||
@echo "RM = $(RM)"
|
||||
@echo "MYCFLAGS = $(MYCFLAGS)"
|
||||
@echo "MYLDFLAGS = $(MYLDFLAGS)"
|
||||
@echo "MYLIBS = $(MYLIBS)"
|
||||
|
||||
# convenience targets for popular platforms
|
||||
|
||||
none:
|
||||
@echo "Please choose a platform:"
|
||||
@echo " $(PLATS)"
|
||||
|
||||
aix:
|
||||
$(MAKE) all CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl" MYLDFLAGS="-brtl -bexpall"
|
||||
|
||||
ansi:
|
||||
$(MAKE) all MYCFLAGS=-DLUA_ANSI
|
||||
|
||||
bsd:
|
||||
$(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E"
|
||||
|
||||
freebsd:
|
||||
$(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" MYLIBS="-Wl,-E -lreadline"
|
||||
|
||||
generic:
|
||||
$(MAKE) all MYCFLAGS=
|
||||
|
||||
linux:
|
||||
$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
|
||||
|
||||
macosx:
|
||||
$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline"
|
||||
# use this on Mac OS X 10.3-
|
||||
# $(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX
|
||||
|
||||
mingw:
|
||||
$(MAKE) "LUA_A=lua51.dll" "LUA_T=lua.exe" \
|
||||
"AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \
|
||||
"MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" lua.exe
|
||||
$(MAKE) "LUAC_T=luac.exe" luac.exe
|
||||
|
||||
posix:
|
||||
$(MAKE) all MYCFLAGS=-DLUA_USE_POSIX
|
||||
|
||||
solaris:
|
||||
$(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl"
|
||||
|
||||
# list targets that do not create files (but not all makes understand .PHONY)
|
||||
.PHONY: all $(PLATS) default o a clean depend echo none
|
||||
|
||||
# DO NOT DELETE
|
||||
|
||||
lapi.o: lapi.c lua.h luaconf.h lapi.h lobject.h llimits.h ldebug.h \
|
||||
lstate.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h \
|
||||
lundump.h lvm.h
|
||||
lauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h
|
||||
lbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
lcode.o: lcode.c 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 \
|
||||
ltable.h
|
||||
ldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
ldebug.o: ldebug.c lua.h luaconf.h lapi.h lobject.h llimits.h lcode.h \
|
||||
llex.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 lvm.h
|
||||
ldo.o: ldo.c 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 lparser.h lstring.h \
|
||||
ltable.h lundump.h lvm.h
|
||||
ldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \
|
||||
lzio.h lmem.h lundump.h
|
||||
lfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h lmem.h \
|
||||
lstate.h ltm.h lzio.h
|
||||
lgc.o: lgc.c 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
|
||||
linit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h
|
||||
liolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
llex.o: llex.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h ltm.h \
|
||||
lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h
|
||||
lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
|
||||
ltm.h lzio.h lmem.h ldo.h
|
||||
loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \
|
||||
ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h
|
||||
lopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h
|
||||
loslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
lparser.o: lparser.c 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
|
||||
lstate.o: lstate.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
|
||||
ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h llex.h lstring.h ltable.h
|
||||
lstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \
|
||||
ltm.h lzio.h lstring.h lgc.h
|
||||
lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
|
||||
ltm.h lzio.h lmem.h ldo.h lgc.h ltable.h
|
||||
ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \
|
||||
lmem.h lstring.h lgc.h ltable.h
|
||||
lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
luac.o: luac.c lua.h luaconf.h lauxlib.h ldo.h lobject.h llimits.h \
|
||||
lstate.h ltm.h lzio.h lmem.h lfunc.h lopcodes.h lstring.h lgc.h \
|
||||
lundump.h
|
||||
lundump.o: lundump.c 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
|
||||
lvm.o: lvm.c 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
|
||||
lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \
|
||||
lzio.h
|
||||
print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \
|
||||
ltm.h lzio.h lmem.h lopcodes.h lundump.h
|
||||
|
||||
# (end of Makefile)
|
||||
Vendored
-1087
File diff suppressed because it is too large
Load Diff
Vendored
-16
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $
|
||||
** Auxiliary functions from Lua API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef lapi_h
|
||||
#define lapi_h
|
||||
|
||||
|
||||
#include "lobject.h"
|
||||
|
||||
|
||||
LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);
|
||||
|
||||
#endif
|
||||
Vendored
-652
@@ -1,652 +0,0 @@
|
||||
/*
|
||||
** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $
|
||||
** Auxiliary functions for building Lua libraries
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* This file uses only the official API of Lua.
|
||||
** Any function declared here could be written as an application function.
|
||||
*/
|
||||
|
||||
#define lauxlib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
|
||||
|
||||
#define FREELIST_REF 0 /* free list of references */
|
||||
|
||||
|
||||
/* convert a stack index to positive */
|
||||
#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \
|
||||
lua_gettop(L) + (i) + 1)
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Error-report functions
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
|
||||
lua_Debug ar;
|
||||
if (!lua_getstack(L, 0, &ar)) /* no stack frame? */
|
||||
return luaL_error(L, "bad argument #%d (%s)", narg, extramsg);
|
||||
lua_getinfo(L, "n", &ar);
|
||||
if (strcmp(ar.namewhat, "method") == 0) {
|
||||
narg--; /* do not count `self' */
|
||||
if (narg == 0) /* error is in the self argument itself? */
|
||||
return luaL_error(L, "calling " LUA_QS " on bad self (%s)",
|
||||
ar.name, extramsg);
|
||||
}
|
||||
if (ar.name == NULL)
|
||||
ar.name = "?";
|
||||
return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)",
|
||||
narg, ar.name, extramsg);
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) {
|
||||
const char *msg = lua_pushfstring(L, "%s expected, got %s",
|
||||
tname, luaL_typename(L, narg));
|
||||
return luaL_argerror(L, narg, msg);
|
||||
}
|
||||
|
||||
|
||||
static void tag_error (lua_State *L, int narg, int tag) {
|
||||
luaL_typerror(L, narg, lua_typename(L, tag));
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaL_where (lua_State *L, int level) {
|
||||
lua_Debug ar;
|
||||
if (lua_getstack(L, level, &ar)) { /* check function at level */
|
||||
lua_getinfo(L, "Sl", &ar); /* get info about it */
|
||||
if (ar.currentline > 0) { /* is there info? */
|
||||
lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
|
||||
return;
|
||||
}
|
||||
}
|
||||
lua_pushliteral(L, ""); /* else, no information available... */
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
luaL_where(L, 1);
|
||||
lua_pushvfstring(L, fmt, argp);
|
||||
va_end(argp);
|
||||
lua_concat(L, 2);
|
||||
return lua_error(L);
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,
|
||||
const char *const lst[]) {
|
||||
const char *name = (def) ? luaL_optstring(L, narg, def) :
|
||||
luaL_checkstring(L, narg);
|
||||
int i;
|
||||
for (i=0; lst[i]; i++)
|
||||
if (strcmp(lst[i], name) == 0)
|
||||
return i;
|
||||
return luaL_argerror(L, narg,
|
||||
lua_pushfstring(L, "invalid option " LUA_QS, name));
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */
|
||||
if (!lua_isnil(L, -1)) /* name already in use? */
|
||||
return 0; /* leave previous value on top, but return 0 */
|
||||
lua_pop(L, 1);
|
||||
lua_newtable(L); /* create metatable */
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
|
||||
void *p = lua_touserdata(L, ud);
|
||||
if (p != NULL) { /* value is a userdata? */
|
||||
if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
|
||||
if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
|
||||
lua_pop(L, 2); /* remove both metatables */
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
luaL_typerror(L, ud, tname); /* else error */
|
||||
return NULL; /* to avoid warnings */
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
|
||||
if (!lua_checkstack(L, space))
|
||||
luaL_error(L, "stack overflow (%s)", mes);
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {
|
||||
if (lua_type(L, narg) != t)
|
||||
tag_error(L, narg, t);
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaL_checkany (lua_State *L, int narg) {
|
||||
if (lua_type(L, narg) == LUA_TNONE)
|
||||
luaL_argerror(L, narg, "value expected");
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {
|
||||
const char *s = lua_tolstring(L, narg, len);
|
||||
if (!s) tag_error(L, narg, LUA_TSTRING);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API const char *luaL_optlstring (lua_State *L, int narg,
|
||||
const char *def, size_t *len) {
|
||||
if (lua_isnoneornil(L, narg)) {
|
||||
if (len)
|
||||
*len = (def ? strlen(def) : 0);
|
||||
return def;
|
||||
}
|
||||
else return luaL_checklstring(L, narg, len);
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
|
||||
lua_Number d = lua_tonumber(L, narg);
|
||||
if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
|
||||
tag_error(L, narg, LUA_TNUMBER);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {
|
||||
return luaL_opt(L, luaL_checknumber, narg, def);
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
|
||||
lua_Integer d = lua_tointeger(L, narg);
|
||||
if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
|
||||
tag_error(L, narg, LUA_TNUMBER);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,
|
||||
lua_Integer def) {
|
||||
return luaL_opt(L, luaL_checkinteger, narg, def);
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
|
||||
if (!lua_getmetatable(L, obj)) /* no metatable? */
|
||||
return 0;
|
||||
lua_pushstring(L, event);
|
||||
lua_rawget(L, -2);
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 2); /* remove metatable and metafield */
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
lua_remove(L, -2); /* remove only metatable */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
|
||||
obj = abs_index(L, obj);
|
||||
if (!luaL_getmetafield(L, obj, event)) /* no metafield? */
|
||||
return 0;
|
||||
lua_pushvalue(L, obj);
|
||||
lua_call(L, 1, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
|
||||
const luaL_Reg *l) {
|
||||
luaI_openlib(L, libname, l, 0);
|
||||
}
|
||||
|
||||
|
||||
static int libsize (const luaL_Reg *l) {
|
||||
int size = 0;
|
||||
for (; l->name; l++) size++;
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaI_openlib (lua_State *L, const char *libname,
|
||||
const luaL_Reg *l, int nup) {
|
||||
if (libname) {
|
||||
int size = libsize(l);
|
||||
/* check whether lib already exists */
|
||||
luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1);
|
||||
lua_getfield(L, -1, libname); /* get _LOADED[libname] */
|
||||
if (!lua_istable(L, -1)) { /* not found? */
|
||||
lua_pop(L, 1); /* remove previous result */
|
||||
/* try global variable (and create one if it does not exist) */
|
||||
if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)
|
||||
luaL_error(L, "name conflict for module " LUA_QS, libname);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */
|
||||
}
|
||||
lua_remove(L, -2); /* remove _LOADED table */
|
||||
lua_insert(L, -(nup+1)); /* move library table to below upvalues */
|
||||
}
|
||||
for (; l->name; l++) {
|
||||
int i;
|
||||
for (i=0; i<nup; i++) /* copy upvalues to the top */
|
||||
lua_pushvalue(L, -nup);
|
||||
lua_pushcclosure(L, l->func, nup);
|
||||
lua_setfield(L, -(nup+2), l->name);
|
||||
}
|
||||
lua_pop(L, nup); /* remove upvalues */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** getn-setn: size for arrays
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
#if defined(LUA_COMPAT_GETN)
|
||||
|
||||
static int checkint (lua_State *L, int topop) {
|
||||
int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1;
|
||||
lua_pop(L, topop);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
static void getsizes (lua_State *L) {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES");
|
||||
if (lua_isnil(L, -1)) { /* no `size' table? */
|
||||
lua_pop(L, 1); /* remove nil */
|
||||
lua_newtable(L); /* create it */
|
||||
lua_pushvalue(L, -1); /* `size' will be its own metatable */
|
||||
lua_setmetatable(L, -2);
|
||||
lua_pushliteral(L, "kv");
|
||||
lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaL_setn (lua_State *L, int t, int n) {
|
||||
t = abs_index(L, t);
|
||||
lua_pushliteral(L, "n");
|
||||
lua_rawget(L, t);
|
||||
if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */
|
||||
lua_pushliteral(L, "n"); /* use it */
|
||||
lua_pushinteger(L, n);
|
||||
lua_rawset(L, t);
|
||||
}
|
||||
else { /* use `sizes' */
|
||||
getsizes(L);
|
||||
lua_pushvalue(L, t);
|
||||
lua_pushinteger(L, n);
|
||||
lua_rawset(L, -3); /* sizes[t] = n */
|
||||
lua_pop(L, 1); /* remove `sizes' */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API int luaL_getn (lua_State *L, int t) {
|
||||
int n;
|
||||
t = abs_index(L, t);
|
||||
lua_pushliteral(L, "n"); /* try t.n */
|
||||
lua_rawget(L, t);
|
||||
if ((n = checkint(L, 1)) >= 0) return n;
|
||||
getsizes(L); /* else try sizes[t] */
|
||||
lua_pushvalue(L, t);
|
||||
lua_rawget(L, -2);
|
||||
if ((n = checkint(L, 2)) >= 0) return n;
|
||||
return (int)lua_objlen(L, t);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
|
||||
LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
|
||||
const char *r) {
|
||||
const char *wild;
|
||||
size_t l = strlen(p);
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
while ((wild = strstr(s, p)) != NULL) {
|
||||
luaL_addlstring(&b, s, wild - s); /* push prefix */
|
||||
luaL_addstring(&b, r); /* push replacement in place of pattern */
|
||||
s = wild + l; /* continue after `p' */
|
||||
}
|
||||
luaL_addstring(&b, s); /* push last suffix */
|
||||
luaL_pushresult(&b);
|
||||
return lua_tostring(L, -1);
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
|
||||
const char *fname, int szhint) {
|
||||
const char *e;
|
||||
lua_pushvalue(L, idx);
|
||||
do {
|
||||
e = strchr(fname, '.');
|
||||
if (e == NULL) e = fname + strlen(fname);
|
||||
lua_pushlstring(L, fname, e - fname);
|
||||
lua_rawget(L, -2);
|
||||
if (lua_isnil(L, -1)) { /* no such field? */
|
||||
lua_pop(L, 1); /* remove this nil */
|
||||
lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
|
||||
lua_pushlstring(L, fname, e - fname);
|
||||
lua_pushvalue(L, -2);
|
||||
lua_settable(L, -4); /* set new table into field */
|
||||
}
|
||||
else if (!lua_istable(L, -1)) { /* field has a non-table value? */
|
||||
lua_pop(L, 2); /* remove table and value */
|
||||
return fname; /* return problematic part of the name */
|
||||
}
|
||||
lua_remove(L, -2); /* remove previous table */
|
||||
fname = e + 1;
|
||||
} while (*e == '.');
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Generic Buffer manipulation
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
#define bufflen(B) ((B)->p - (B)->buffer)
|
||||
#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
|
||||
|
||||
#define LIMIT (LUA_MINSTACK/2)
|
||||
|
||||
|
||||
static int emptybuffer (luaL_Buffer *B) {
|
||||
size_t l = bufflen(B);
|
||||
if (l == 0) return 0; /* put nothing on stack */
|
||||
else {
|
||||
lua_pushlstring(B->L, B->buffer, l);
|
||||
B->p = B->buffer;
|
||||
B->lvl++;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void adjuststack (luaL_Buffer *B) {
|
||||
if (B->lvl > 1) {
|
||||
lua_State *L = B->L;
|
||||
int toget = 1; /* number of levels to concat */
|
||||
size_t toplen = lua_strlen(L, -1);
|
||||
do {
|
||||
size_t l = lua_strlen(L, -(toget+1));
|
||||
if (B->lvl - toget + 1 >= LIMIT || toplen > l) {
|
||||
toplen += l;
|
||||
toget++;
|
||||
}
|
||||
else break;
|
||||
} while (toget < B->lvl);
|
||||
lua_concat(L, toget);
|
||||
B->lvl = B->lvl - toget + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) {
|
||||
if (emptybuffer(B))
|
||||
adjuststack(B);
|
||||
return B->buffer;
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
|
||||
while (l--)
|
||||
luaL_addchar(B, *s++);
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
|
||||
luaL_addlstring(B, s, strlen(s));
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
|
||||
emptybuffer(B);
|
||||
lua_concat(B->L, B->lvl);
|
||||
B->lvl = 1;
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
|
||||
lua_State *L = B->L;
|
||||
size_t vl;
|
||||
const char *s = lua_tolstring(L, -1, &vl);
|
||||
if (vl <= bufffree(B)) { /* fit into buffer? */
|
||||
memcpy(B->p, s, vl); /* put it there */
|
||||
B->p += vl;
|
||||
lua_pop(L, 1); /* remove from stack */
|
||||
}
|
||||
else {
|
||||
if (emptybuffer(B))
|
||||
lua_insert(L, -2); /* put buffer before new value */
|
||||
B->lvl++; /* add new value into B stack */
|
||||
adjuststack(B);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
|
||||
B->L = L;
|
||||
B->p = B->buffer;
|
||||
B->lvl = 0;
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
LUALIB_API int luaL_ref (lua_State *L, int t) {
|
||||
int ref;
|
||||
t = abs_index(L, t);
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 1); /* remove from stack */
|
||||
return LUA_REFNIL; /* `nil' has a unique fixed reference */
|
||||
}
|
||||
lua_rawgeti(L, t, FREELIST_REF); /* get first free element */
|
||||
ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */
|
||||
lua_pop(L, 1); /* remove it from stack */
|
||||
if (ref != 0) { /* any free element? */
|
||||
lua_rawgeti(L, t, ref); /* remove it from list */
|
||||
lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */
|
||||
}
|
||||
else { /* no free elements */
|
||||
ref = (int)lua_objlen(L, t);
|
||||
ref++; /* create new reference */
|
||||
}
|
||||
lua_rawseti(L, t, ref);
|
||||
return ref;
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
|
||||
if (ref >= 0) {
|
||||
t = abs_index(L, t);
|
||||
lua_rawgeti(L, t, FREELIST_REF);
|
||||
lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */
|
||||
lua_pushinteger(L, ref);
|
||||
lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Load functions
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
typedef struct LoadF {
|
||||
int extraline;
|
||||
FILE *f;
|
||||
char buff[LUAL_BUFFERSIZE];
|
||||
} LoadF;
|
||||
|
||||
|
||||
static const char *getF (lua_State *L, void *ud, size_t *size) {
|
||||
LoadF *lf = (LoadF *)ud;
|
||||
(void)L;
|
||||
if (lf->extraline) {
|
||||
lf->extraline = 0;
|
||||
*size = 1;
|
||||
return "\n";
|
||||
}
|
||||
if (feof(lf->f)) return NULL;
|
||||
*size = fread(lf->buff, 1, sizeof(lf->buff), lf->f);
|
||||
return (*size > 0) ? lf->buff : NULL;
|
||||
}
|
||||
|
||||
|
||||
static int errfile (lua_State *L, const char *what, int fnameindex) {
|
||||
const char *serr = strerror(errno);
|
||||
const char *filename = lua_tostring(L, fnameindex) + 1;
|
||||
lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
|
||||
lua_remove(L, fnameindex);
|
||||
return LUA_ERRFILE;
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
|
||||
LoadF lf;
|
||||
int status, readstatus;
|
||||
int c;
|
||||
int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
|
||||
lf.extraline = 0;
|
||||
if (filename == NULL) {
|
||||
lua_pushliteral(L, "=stdin");
|
||||
lf.f = stdin;
|
||||
}
|
||||
else {
|
||||
lua_pushfstring(L, "@%s", filename);
|
||||
lf.f = fopen(filename, "r");
|
||||
if (lf.f == NULL) return errfile(L, "open", fnameindex);
|
||||
}
|
||||
c = getc(lf.f);
|
||||
if (c == '#') { /* Unix exec. file? */
|
||||
lf.extraline = 1;
|
||||
while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */
|
||||
if (c == '\n') c = getc(lf.f);
|
||||
}
|
||||
if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
|
||||
lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
|
||||
if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
|
||||
/* skip eventual `#!...' */
|
||||
while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;
|
||||
lf.extraline = 0;
|
||||
}
|
||||
ungetc(c, lf.f);
|
||||
status = lua_load(L, getF, &lf, lua_tostring(L, -1));
|
||||
readstatus = ferror(lf.f);
|
||||
if (filename) fclose(lf.f); /* close file (even in case of errors) */
|
||||
if (readstatus) {
|
||||
lua_settop(L, fnameindex); /* ignore results from `lua_load' */
|
||||
return errfile(L, "read", fnameindex);
|
||||
}
|
||||
lua_remove(L, fnameindex);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
typedef struct LoadS {
|
||||
const char *s;
|
||||
size_t size;
|
||||
} LoadS;
|
||||
|
||||
|
||||
static const char *getS (lua_State *L, void *ud, size_t *size) {
|
||||
LoadS *ls = (LoadS *)ud;
|
||||
(void)L;
|
||||
if (ls->size == 0) return NULL;
|
||||
*size = ls->size;
|
||||
ls->size = 0;
|
||||
return ls->s;
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
|
||||
const char *name) {
|
||||
LoadS ls;
|
||||
ls.s = buff;
|
||||
ls.size = size;
|
||||
return lua_load(L, getS, &ls, name);
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) {
|
||||
return luaL_loadbuffer(L, s, strlen(s), s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
|
||||
(void)ud;
|
||||
(void)osize;
|
||||
if (nsize == 0) {
|
||||
free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return realloc(ptr, nsize);
|
||||
}
|
||||
|
||||
|
||||
static int panic (lua_State *L) {
|
||||
(void)L; /* to avoid warnings */
|
||||
fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n",
|
||||
lua_tostring(L, -1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API lua_State *luaL_newstate (void) {
|
||||
lua_State *L = lua_newstate(l_alloc, NULL);
|
||||
if (L) lua_atpanic(L, &panic);
|
||||
return L;
|
||||
}
|
||||
|
||||
Vendored
-174
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $
|
||||
** Auxiliary functions for building Lua libraries
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#ifndef lauxlib_h
|
||||
#define lauxlib_h
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
|
||||
#if defined(LUA_COMPAT_GETN)
|
||||
LUALIB_API int (luaL_getn) (lua_State *L, int t);
|
||||
LUALIB_API void (luaL_setn) (lua_State *L, int t, int n);
|
||||
#else
|
||||
#define luaL_getn(L,i) ((int)lua_objlen(L, i))
|
||||
#define luaL_setn(L,i,j) ((void)0) /* no op! */
|
||||
#endif
|
||||
|
||||
#if defined(LUA_COMPAT_OPENLIB)
|
||||
#define luaI_openlib luaL_openlib
|
||||
#endif
|
||||
|
||||
|
||||
/* extra error code for `luaL_load' */
|
||||
#define LUA_ERRFILE (LUA_ERRERR+1)
|
||||
|
||||
|
||||
typedef struct luaL_Reg {
|
||||
const char *name;
|
||||
lua_CFunction func;
|
||||
} luaL_Reg;
|
||||
|
||||
|
||||
|
||||
LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname,
|
||||
const luaL_Reg *l, int nup);
|
||||
LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
|
||||
const luaL_Reg *l);
|
||||
LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);
|
||||
LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
|
||||
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,
|
||||
size_t *l);
|
||||
LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,
|
||||
const char *def, size_t *l);
|
||||
LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);
|
||||
LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);
|
||||
|
||||
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
|
||||
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
|
||||
lua_Integer def);
|
||||
|
||||
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
|
||||
LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
|
||||
LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
|
||||
|
||||
LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
|
||||
LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
|
||||
|
||||
LUALIB_API void (luaL_where) (lua_State *L, int lvl);
|
||||
LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
|
||||
|
||||
LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
|
||||
const char *const lst[]);
|
||||
|
||||
LUALIB_API int (luaL_ref) (lua_State *L, int t);
|
||||
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
|
||||
|
||||
LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);
|
||||
LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,
|
||||
const char *name);
|
||||
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
|
||||
|
||||
LUALIB_API lua_State *(luaL_newstate) (void);
|
||||
|
||||
|
||||
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
|
||||
const char *r);
|
||||
|
||||
LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
|
||||
const char *fname, int szhint);
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** ===============================================================
|
||||
** some useful macros
|
||||
** ===============================================================
|
||||
*/
|
||||
|
||||
#define luaL_argcheck(L, cond,numarg,extramsg) \
|
||||
((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
|
||||
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
|
||||
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
|
||||
#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
|
||||
#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
|
||||
#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
|
||||
#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
|
||||
|
||||
#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
|
||||
|
||||
#define luaL_dofile(L, fn) \
|
||||
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||
|
||||
#define luaL_dostring(L, s) \
|
||||
(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||
|
||||
#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
|
||||
|
||||
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Generic Buffer manipulation
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
|
||||
typedef struct luaL_Buffer {
|
||||
char *p; /* current position in buffer */
|
||||
int lvl; /* number of strings in the stack (level) */
|
||||
lua_State *L;
|
||||
char buffer[LUAL_BUFFERSIZE];
|
||||
} luaL_Buffer;
|
||||
|
||||
#define luaL_addchar(B,c) \
|
||||
((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
|
||||
(*(B)->p++ = (char)(c)))
|
||||
|
||||
/* compatibility only */
|
||||
#define luaL_putchar(B,c) luaL_addchar(B,c)
|
||||
|
||||
#define luaL_addsize(B,n) ((B)->p += (n))
|
||||
|
||||
LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
|
||||
LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B);
|
||||
LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
|
||||
LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
|
||||
LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
|
||||
LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
|
||||
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
/* compatibility with ref system */
|
||||
|
||||
/* pre-defined references */
|
||||
#define LUA_NOREF (-2)
|
||||
#define LUA_REFNIL (-1)
|
||||
|
||||
#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
|
||||
(lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))
|
||||
|
||||
#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref))
|
||||
|
||||
#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref))
|
||||
|
||||
|
||||
#define luaL_reg luaL_Reg
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Vendored
-653
@@ -1,653 +0,0 @@
|
||||
/*
|
||||
** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $
|
||||
** Basic library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define lbaselib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** If your system does not support `stdout', you can just remove this function.
|
||||
** If you need, you can define your own `print' function, following this
|
||||
** model but changing `fputs' to put the strings at a proper place
|
||||
** (a console window or a log file, for instance).
|
||||
*/
|
||||
static int luaB_print (lua_State *L) {
|
||||
int n = lua_gettop(L); /* number of arguments */
|
||||
int i;
|
||||
lua_getglobal(L, "tostring");
|
||||
for (i=1; i<=n; i++) {
|
||||
const char *s;
|
||||
lua_pushvalue(L, -1); /* function to be called */
|
||||
lua_pushvalue(L, i); /* value to print */
|
||||
lua_call(L, 1, 1);
|
||||
s = lua_tostring(L, -1); /* get result */
|
||||
if (s == NULL)
|
||||
return luaL_error(L, LUA_QL("tostring") " must return a string to "
|
||||
LUA_QL("print"));
|
||||
if (i>1) fputs("\t", stdout);
|
||||
fputs(s, stdout);
|
||||
lua_pop(L, 1); /* pop result */
|
||||
}
|
||||
fputs("\n", stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_tonumber (lua_State *L) {
|
||||
int base = luaL_optint(L, 2, 10);
|
||||
if (base == 10) { /* standard conversion */
|
||||
luaL_checkany(L, 1);
|
||||
if (lua_isnumber(L, 1)) {
|
||||
lua_pushnumber(L, lua_tonumber(L, 1));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const char *s1 = luaL_checkstring(L, 1);
|
||||
char *s2;
|
||||
unsigned long n;
|
||||
luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
|
||||
n = strtoul(s1, &s2, base);
|
||||
if (s1 != s2) { /* at least one valid digit? */
|
||||
while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */
|
||||
if (*s2 == '\0') { /* no invalid trailing characters? */
|
||||
lua_pushnumber(L, (lua_Number)n);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
lua_pushnil(L); /* else not a number */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_error (lua_State *L) {
|
||||
int level = luaL_optint(L, 2, 1);
|
||||
lua_settop(L, 1);
|
||||
if (lua_isstring(L, 1) && level > 0) { /* add extra information? */
|
||||
luaL_where(L, level);
|
||||
lua_pushvalue(L, 1);
|
||||
lua_concat(L, 2);
|
||||
}
|
||||
return lua_error(L);
|
||||
}
|
||||
|
||||
|
||||
static int luaB_getmetatable (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
if (!lua_getmetatable(L, 1)) {
|
||||
lua_pushnil(L);
|
||||
return 1; /* no metatable */
|
||||
}
|
||||
luaL_getmetafield(L, 1, "__metatable");
|
||||
return 1; /* returns either __metatable field (if present) or metatable */
|
||||
}
|
||||
|
||||
|
||||
static int luaB_setmetatable (lua_State *L) {
|
||||
int t = lua_type(L, 2);
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
|
||||
"nil or table expected");
|
||||
if (luaL_getmetafield(L, 1, "__metatable"))
|
||||
luaL_error(L, "cannot change a protected metatable");
|
||||
lua_settop(L, 2);
|
||||
lua_setmetatable(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void getfunc (lua_State *L, int opt) {
|
||||
if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
|
||||
else {
|
||||
lua_Debug ar;
|
||||
int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1);
|
||||
luaL_argcheck(L, level >= 0, 1, "level must be non-negative");
|
||||
if (lua_getstack(L, level, &ar) == 0)
|
||||
luaL_argerror(L, 1, "invalid level");
|
||||
lua_getinfo(L, "f", &ar);
|
||||
if (lua_isnil(L, -1))
|
||||
luaL_error(L, "no function environment for tail call at level %d",
|
||||
level);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_getfenv (lua_State *L) {
|
||||
getfunc(L, 1);
|
||||
if (lua_iscfunction(L, -1)) /* is a C function? */
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */
|
||||
else
|
||||
lua_getfenv(L, -1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_setfenv (lua_State *L) {
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
getfunc(L, 0);
|
||||
lua_pushvalue(L, 2);
|
||||
if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
|
||||
/* change environment of current thread */
|
||||
lua_pushthread(L);
|
||||
lua_insert(L, -2);
|
||||
lua_setfenv(L, -2);
|
||||
return 0;
|
||||
}
|
||||
else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)
|
||||
luaL_error(L,
|
||||
LUA_QL("setfenv") " cannot change environment of given object");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_rawequal (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
luaL_checkany(L, 2);
|
||||
lua_pushboolean(L, lua_rawequal(L, 1, 2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_rawget (lua_State *L) {
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
luaL_checkany(L, 2);
|
||||
lua_settop(L, 2);
|
||||
lua_rawget(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int luaB_rawset (lua_State *L) {
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
luaL_checkany(L, 2);
|
||||
luaL_checkany(L, 3);
|
||||
lua_settop(L, 3);
|
||||
lua_rawset(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_gcinfo (lua_State *L) {
|
||||
lua_pushinteger(L, lua_getgccount(L));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_collectgarbage (lua_State *L) {
|
||||
static const char *const opts[] = {"stop", "restart", "collect",
|
||||
"count", "step", "setpause", "setstepmul", NULL};
|
||||
static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
|
||||
LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};
|
||||
int o = luaL_checkoption(L, 1, "collect", opts);
|
||||
int ex = luaL_optint(L, 2, 0);
|
||||
int res = lua_gc(L, optsnum[o], ex);
|
||||
switch (optsnum[o]) {
|
||||
case LUA_GCCOUNT: {
|
||||
int b = lua_gc(L, LUA_GCCOUNTB, 0);
|
||||
lua_pushnumber(L, res + ((lua_Number)b/1024));
|
||||
return 1;
|
||||
}
|
||||
case LUA_GCSTEP: {
|
||||
lua_pushboolean(L, res);
|
||||
return 1;
|
||||
}
|
||||
default: {
|
||||
lua_pushnumber(L, res);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_type (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
lua_pushstring(L, luaL_typename(L, 1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_next (lua_State *L) {
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
lua_settop(L, 2); /* create a 2nd argument if there isn't one */
|
||||
if (lua_next(L, 1))
|
||||
return 2;
|
||||
else {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_pairs (lua_State *L) {
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
|
||||
lua_pushvalue(L, 1); /* state, */
|
||||
lua_pushnil(L); /* and initial value */
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
static int ipairsaux (lua_State *L) {
|
||||
int i = luaL_checkint(L, 2);
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
i++; /* next value */
|
||||
lua_pushinteger(L, i);
|
||||
lua_rawgeti(L, 1, i);
|
||||
return (lua_isnil(L, -1)) ? 0 : 2;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_ipairs (lua_State *L) {
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
|
||||
lua_pushvalue(L, 1); /* state, */
|
||||
lua_pushinteger(L, 0); /* and initial value */
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
static int load_aux (lua_State *L, int status) {
|
||||
if (status == 0) /* OK? */
|
||||
return 1;
|
||||
else {
|
||||
lua_pushnil(L);
|
||||
lua_insert(L, -2); /* put before error message */
|
||||
return 2; /* return nil plus error message */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_loadstring (lua_State *L) {
|
||||
size_t l;
|
||||
const char *s = luaL_checklstring(L, 1, &l);
|
||||
const char *chunkname = luaL_optstring(L, 2, s);
|
||||
return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));
|
||||
}
|
||||
|
||||
|
||||
static int luaB_loadfile (lua_State *L) {
|
||||
const char *fname = luaL_optstring(L, 1, NULL);
|
||||
return load_aux(L, luaL_loadfile(L, fname));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Reader for generic `load' function: `lua_load' uses the
|
||||
** stack for internal stuff, so the reader cannot change the
|
||||
** stack top. Instead, it keeps its resulting string in a
|
||||
** reserved slot inside the stack.
|
||||
*/
|
||||
static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
|
||||
(void)ud; /* to avoid warnings */
|
||||
luaL_checkstack(L, 2, "too many nested functions");
|
||||
lua_pushvalue(L, 1); /* get function */
|
||||
lua_call(L, 0, 1); /* call it */
|
||||
if (lua_isnil(L, -1)) {
|
||||
*size = 0;
|
||||
return NULL;
|
||||
}
|
||||
else if (lua_isstring(L, -1)) {
|
||||
lua_replace(L, 3); /* save string in a reserved stack slot */
|
||||
return lua_tolstring(L, 3, size);
|
||||
}
|
||||
else luaL_error(L, "reader function must return a string");
|
||||
return NULL; /* to avoid warnings */
|
||||
}
|
||||
|
||||
|
||||
static int luaB_load (lua_State *L) {
|
||||
int status;
|
||||
const char *cname = luaL_optstring(L, 2, "=(load)");
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||
lua_settop(L, 3); /* function, eventual name, plus one reserved slot */
|
||||
status = lua_load(L, generic_reader, NULL, cname);
|
||||
return load_aux(L, status);
|
||||
}
|
||||
|
||||
|
||||
static int luaB_dofile (lua_State *L) {
|
||||
const char *fname = luaL_optstring(L, 1, NULL);
|
||||
int n = lua_gettop(L);
|
||||
if (luaL_loadfile(L, fname) != 0) lua_error(L);
|
||||
lua_call(L, 0, LUA_MULTRET);
|
||||
return lua_gettop(L) - n;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_assert (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
if (!lua_toboolean(L, 1))
|
||||
return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
|
||||
return lua_gettop(L);
|
||||
}
|
||||
|
||||
|
||||
static int luaB_unpack (lua_State *L) {
|
||||
int i, e, n;
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
i = luaL_optint(L, 2, 1);
|
||||
e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
|
||||
if (i > e) return 0; /* empty range */
|
||||
n = e - i + 1; /* number of elements */
|
||||
if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */
|
||||
return luaL_error(L, "too many results to unpack");
|
||||
lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */
|
||||
while (i++ < e) /* push arg[i + 1...e] */
|
||||
lua_rawgeti(L, 1, i);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_select (lua_State *L) {
|
||||
int n = lua_gettop(L);
|
||||
if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
|
||||
lua_pushinteger(L, n-1);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
int i = luaL_checkint(L, 1);
|
||||
if (i < 0) i = n + i;
|
||||
else if (i > n) i = n;
|
||||
luaL_argcheck(L, 1 <= i, 1, "index out of range");
|
||||
return n - i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_pcall (lua_State *L) {
|
||||
int status;
|
||||
luaL_checkany(L, 1);
|
||||
status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);
|
||||
lua_pushboolean(L, (status == 0));
|
||||
lua_insert(L, 1);
|
||||
return lua_gettop(L); /* return status + all results */
|
||||
}
|
||||
|
||||
|
||||
static int luaB_xpcall (lua_State *L) {
|
||||
int status;
|
||||
luaL_checkany(L, 2);
|
||||
lua_settop(L, 2);
|
||||
lua_insert(L, 1); /* put error function under function to be called */
|
||||
status = lua_pcall(L, 0, LUA_MULTRET, 1);
|
||||
lua_pushboolean(L, (status == 0));
|
||||
lua_replace(L, 1);
|
||||
return lua_gettop(L); /* return status + all results */
|
||||
}
|
||||
|
||||
|
||||
static int luaB_tostring (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */
|
||||
return 1; /* use its value */
|
||||
switch (lua_type(L, 1)) {
|
||||
case LUA_TNUMBER:
|
||||
lua_pushstring(L, lua_tostring(L, 1));
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
lua_pushvalue(L, 1);
|
||||
break;
|
||||
case LUA_TBOOLEAN:
|
||||
lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
|
||||
break;
|
||||
case LUA_TNIL:
|
||||
lua_pushliteral(L, "nil");
|
||||
break;
|
||||
default:
|
||||
lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1));
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_newproxy (lua_State *L) {
|
||||
lua_settop(L, 1);
|
||||
lua_newuserdata(L, 0); /* create proxy */
|
||||
if (lua_toboolean(L, 1) == 0)
|
||||
return 1; /* no metatable */
|
||||
else if (lua_isboolean(L, 1)) {
|
||||
lua_newtable(L); /* create a new metatable `m' ... */
|
||||
lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */
|
||||
lua_pushboolean(L, 1);
|
||||
lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */
|
||||
}
|
||||
else {
|
||||
int validproxy = 0; /* to check if weaktable[metatable(u)] == true */
|
||||
if (lua_getmetatable(L, 1)) {
|
||||
lua_rawget(L, lua_upvalueindex(1));
|
||||
validproxy = lua_toboolean(L, -1);
|
||||
lua_pop(L, 1); /* remove value */
|
||||
}
|
||||
luaL_argcheck(L, validproxy, 1, "boolean or proxy expected");
|
||||
lua_getmetatable(L, 1); /* metatable is valid; get it */
|
||||
}
|
||||
lua_setmetatable(L, 2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg base_funcs[] = {
|
||||
{"assert", luaB_assert},
|
||||
{"collectgarbage", luaB_collectgarbage},
|
||||
{"dofile", luaB_dofile},
|
||||
{"error", luaB_error},
|
||||
{"gcinfo", luaB_gcinfo},
|
||||
{"getfenv", luaB_getfenv},
|
||||
{"getmetatable", luaB_getmetatable},
|
||||
{"loadfile", luaB_loadfile},
|
||||
{"load", luaB_load},
|
||||
{"loadstring", luaB_loadstring},
|
||||
{"next", luaB_next},
|
||||
{"pcall", luaB_pcall},
|
||||
{"print", luaB_print},
|
||||
{"rawequal", luaB_rawequal},
|
||||
{"rawget", luaB_rawget},
|
||||
{"rawset", luaB_rawset},
|
||||
{"select", luaB_select},
|
||||
{"setfenv", luaB_setfenv},
|
||||
{"setmetatable", luaB_setmetatable},
|
||||
{"tonumber", luaB_tonumber},
|
||||
{"tostring", luaB_tostring},
|
||||
{"type", luaB_type},
|
||||
{"unpack", luaB_unpack},
|
||||
{"xpcall", luaB_xpcall},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Coroutine library
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
#define CO_RUN 0 /* running */
|
||||
#define CO_SUS 1 /* suspended */
|
||||
#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */
|
||||
#define CO_DEAD 3
|
||||
|
||||
static const char *const statnames[] =
|
||||
{"running", "suspended", "normal", "dead"};
|
||||
|
||||
static int costatus (lua_State *L, lua_State *co) {
|
||||
if (L == co) return CO_RUN;
|
||||
switch (lua_status(co)) {
|
||||
case LUA_YIELD:
|
||||
return CO_SUS;
|
||||
case 0: {
|
||||
lua_Debug ar;
|
||||
if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */
|
||||
return CO_NOR; /* it is running */
|
||||
else if (lua_gettop(co) == 0)
|
||||
return CO_DEAD;
|
||||
else
|
||||
return CO_SUS; /* initial state */
|
||||
}
|
||||
default: /* some error occured */
|
||||
return CO_DEAD;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_costatus (lua_State *L) {
|
||||
lua_State *co = lua_tothread(L, 1);
|
||||
luaL_argcheck(L, co, 1, "coroutine expected");
|
||||
lua_pushstring(L, statnames[costatus(L, co)]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int auxresume (lua_State *L, lua_State *co, int narg) {
|
||||
int status = costatus(L, co);
|
||||
if (!lua_checkstack(co, narg))
|
||||
luaL_error(L, "too many arguments to resume");
|
||||
if (status != CO_SUS) {
|
||||
lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]);
|
||||
return -1; /* error flag */
|
||||
}
|
||||
lua_xmove(L, co, narg);
|
||||
lua_setlevel(L, co);
|
||||
status = lua_resume(co, narg);
|
||||
if (status == 0 || status == LUA_YIELD) {
|
||||
int nres = lua_gettop(co);
|
||||
if (!lua_checkstack(L, nres + 1))
|
||||
luaL_error(L, "too many results to resume");
|
||||
lua_xmove(co, L, nres); /* move yielded values */
|
||||
return nres;
|
||||
}
|
||||
else {
|
||||
lua_xmove(co, L, 1); /* move error message */
|
||||
return -1; /* error flag */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_coresume (lua_State *L) {
|
||||
lua_State *co = lua_tothread(L, 1);
|
||||
int r;
|
||||
luaL_argcheck(L, co, 1, "coroutine expected");
|
||||
r = auxresume(L, co, lua_gettop(L) - 1);
|
||||
if (r < 0) {
|
||||
lua_pushboolean(L, 0);
|
||||
lua_insert(L, -2);
|
||||
return 2; /* return false + error message */
|
||||
}
|
||||
else {
|
||||
lua_pushboolean(L, 1);
|
||||
lua_insert(L, -(r + 1));
|
||||
return r + 1; /* return true + `resume' returns */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_auxwrap (lua_State *L) {
|
||||
lua_State *co = lua_tothread(L, lua_upvalueindex(1));
|
||||
int r = auxresume(L, co, lua_gettop(L));
|
||||
if (r < 0) {
|
||||
if (lua_isstring(L, -1)) { /* error object is a string? */
|
||||
luaL_where(L, 1); /* add extra info */
|
||||
lua_insert(L, -2);
|
||||
lua_concat(L, 2);
|
||||
}
|
||||
lua_error(L); /* propagate error */
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_cocreate (lua_State *L) {
|
||||
lua_State *NL = lua_newthread(L);
|
||||
luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
|
||||
"Lua function expected");
|
||||
lua_pushvalue(L, 1); /* move function to top */
|
||||
lua_xmove(L, NL, 1); /* move function from L to NL */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_cowrap (lua_State *L) {
|
||||
luaB_cocreate(L);
|
||||
lua_pushcclosure(L, luaB_auxwrap, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_yield (lua_State *L) {
|
||||
return lua_yield(L, lua_gettop(L));
|
||||
}
|
||||
|
||||
|
||||
static int luaB_corunning (lua_State *L) {
|
||||
if (lua_pushthread(L))
|
||||
lua_pushnil(L); /* main thread is not a coroutine */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg co_funcs[] = {
|
||||
{"create", luaB_cocreate},
|
||||
{"resume", luaB_coresume},
|
||||
{"running", luaB_corunning},
|
||||
{"status", luaB_costatus},
|
||||
{"wrap", luaB_cowrap},
|
||||
{"yield", luaB_yield},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
static void auxopen (lua_State *L, const char *name,
|
||||
lua_CFunction f, lua_CFunction u) {
|
||||
lua_pushcfunction(L, u);
|
||||
lua_pushcclosure(L, f, 1);
|
||||
lua_setfield(L, -2, name);
|
||||
}
|
||||
|
||||
|
||||
static void base_open (lua_State *L) {
|
||||
/* set global _G */
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||
lua_setglobal(L, "_G");
|
||||
/* open lib into global table */
|
||||
luaL_register(L, "_G", base_funcs);
|
||||
lua_pushliteral(L, LUA_VERSION);
|
||||
lua_setglobal(L, "_VERSION"); /* set global _VERSION */
|
||||
/* `ipairs' and `pairs' need auxliliary functions as upvalues */
|
||||
auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
|
||||
auxopen(L, "pairs", luaB_pairs, luaB_next);
|
||||
/* `newproxy' needs a weaktable as upvalue */
|
||||
lua_createtable(L, 0, 1); /* new table `w' */
|
||||
lua_pushvalue(L, -1); /* `w' will be its own metatable */
|
||||
lua_setmetatable(L, -2);
|
||||
lua_pushliteral(L, "kv");
|
||||
lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */
|
||||
lua_pushcclosure(L, luaB_newproxy, 1);
|
||||
lua_setglobal(L, "newproxy"); /* set global `newproxy' */
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API int luaopen_base (lua_State *L) {
|
||||
base_open(L);
|
||||
luaL_register(L, LUA_COLIBNAME, co_funcs);
|
||||
return 2;
|
||||
}
|
||||
|
||||
Vendored
-839
@@ -1,839 +0,0 @@
|
||||
/*
|
||||
** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $
|
||||
** Code generator for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define lcode_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lcode.h"
|
||||
#include "ldebug.h"
|
||||
#include "ldo.h"
|
||||
#include "lgc.h"
|
||||
#include "llex.h"
|
||||
#include "lmem.h"
|
||||
#include "lobject.h"
|
||||
#include "lopcodes.h"
|
||||
#include "lparser.h"
|
||||
#include "ltable.h"
|
||||
|
||||
|
||||
#define hasjumps(e) ((e)->t != (e)->f)
|
||||
|
||||
|
||||
static int isnumeral(expdesc *e) {
|
||||
return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
|
||||
}
|
||||
|
||||
|
||||
void luaK_nil (FuncState *fs, int from, int n) {
|
||||
Instruction *previous;
|
||||
if (fs->pc > fs->lasttarget) { /* no jumps to current position? */
|
||||
if (fs->pc == 0) { /* function start? */
|
||||
if (from >= fs->nactvar)
|
||||
return; /* positions are already clean */
|
||||
}
|
||||
else {
|
||||
previous = &fs->f->code[fs->pc-1];
|
||||
if (GET_OPCODE(*previous) == OP_LOADNIL) {
|
||||
int pfrom = GETARG_A(*previous);
|
||||
int pto = GETARG_B(*previous);
|
||||
if (pfrom <= from && from <= pto+1) { /* can connect both? */
|
||||
if (from+n-1 > pto)
|
||||
SETARG_B(*previous, from+n-1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */
|
||||
}
|
||||
|
||||
|
||||
int luaK_jump (FuncState *fs) {
|
||||
int jpc = fs->jpc; /* save list of jumps to here */
|
||||
int j;
|
||||
fs->jpc = NO_JUMP;
|
||||
j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);
|
||||
luaK_concat(fs, &j, jpc); /* keep them on hold */
|
||||
return j;
|
||||
}
|
||||
|
||||
|
||||
void luaK_ret (FuncState *fs, int first, int nret) {
|
||||
luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
|
||||
}
|
||||
|
||||
|
||||
static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
|
||||
luaK_codeABC(fs, op, A, B, C);
|
||||
return luaK_jump(fs);
|
||||
}
|
||||
|
||||
|
||||
static void fixjump (FuncState *fs, int pc, int dest) {
|
||||
Instruction *jmp = &fs->f->code[pc];
|
||||
int offset = dest-(pc+1);
|
||||
lua_assert(dest != NO_JUMP);
|
||||
if (abs(offset) > MAXARG_sBx)
|
||||
luaX_syntaxerror(fs->ls, "control structure too long");
|
||||
SETARG_sBx(*jmp, offset);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** returns current `pc' and marks it as a jump target (to avoid wrong
|
||||
** optimizations with consecutive instructions not in the same basic block).
|
||||
*/
|
||||
int luaK_getlabel (FuncState *fs) {
|
||||
fs->lasttarget = fs->pc;
|
||||
return fs->pc;
|
||||
}
|
||||
|
||||
|
||||
static int getjump (FuncState *fs, int pc) {
|
||||
int offset = GETARG_sBx(fs->f->code[pc]);
|
||||
if (offset == NO_JUMP) /* point to itself represents end of list */
|
||||
return NO_JUMP; /* end of list */
|
||||
else
|
||||
return (pc+1)+offset; /* turn offset into absolute position */
|
||||
}
|
||||
|
||||
|
||||
static Instruction *getjumpcontrol (FuncState *fs, int pc) {
|
||||
Instruction *pi = &fs->f->code[pc];
|
||||
if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))
|
||||
return pi-1;
|
||||
else
|
||||
return pi;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** check whether list has any jump that do not produce a value
|
||||
** (or produce an inverted value)
|
||||
*/
|
||||
static int need_value (FuncState *fs, int list) {
|
||||
for (; list != NO_JUMP; list = getjump(fs, list)) {
|
||||
Instruction i = *getjumpcontrol(fs, list);
|
||||
if (GET_OPCODE(i) != OP_TESTSET) return 1;
|
||||
}
|
||||
return 0; /* not found */
|
||||
}
|
||||
|
||||
|
||||
static int patchtestreg (FuncState *fs, int node, int reg) {
|
||||
Instruction *i = getjumpcontrol(fs, node);
|
||||
if (GET_OPCODE(*i) != OP_TESTSET)
|
||||
return 0; /* cannot patch other instructions */
|
||||
if (reg != NO_REG && reg != GETARG_B(*i))
|
||||
SETARG_A(*i, reg);
|
||||
else /* no register to put value or register already has the value */
|
||||
*i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void removevalues (FuncState *fs, int list) {
|
||||
for (; list != NO_JUMP; list = getjump(fs, list))
|
||||
patchtestreg(fs, list, NO_REG);
|
||||
}
|
||||
|
||||
|
||||
static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
|
||||
int dtarget) {
|
||||
while (list != NO_JUMP) {
|
||||
int next = getjump(fs, list);
|
||||
if (patchtestreg(fs, list, reg))
|
||||
fixjump(fs, list, vtarget);
|
||||
else
|
||||
fixjump(fs, list, dtarget); /* jump to default target */
|
||||
list = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void dischargejpc (FuncState *fs) {
|
||||
patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
|
||||
fs->jpc = NO_JUMP;
|
||||
}
|
||||
|
||||
|
||||
void luaK_patchlist (FuncState *fs, int list, int target) {
|
||||
if (target == fs->pc)
|
||||
luaK_patchtohere(fs, list);
|
||||
else {
|
||||
lua_assert(target < fs->pc);
|
||||
patchlistaux(fs, list, target, NO_REG, target);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void luaK_patchtohere (FuncState *fs, int list) {
|
||||
luaK_getlabel(fs);
|
||||
luaK_concat(fs, &fs->jpc, list);
|
||||
}
|
||||
|
||||
|
||||
void luaK_concat (FuncState *fs, int *l1, int l2) {
|
||||
if (l2 == NO_JUMP) return;
|
||||
else if (*l1 == NO_JUMP)
|
||||
*l1 = l2;
|
||||
else {
|
||||
int list = *l1;
|
||||
int next;
|
||||
while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */
|
||||
list = next;
|
||||
fixjump(fs, list, l2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void luaK_checkstack (FuncState *fs, int n) {
|
||||
int newstack = fs->freereg + n;
|
||||
if (newstack > fs->f->maxstacksize) {
|
||||
if (newstack >= MAXSTACK)
|
||||
luaX_syntaxerror(fs->ls, "function or expression too complex");
|
||||
fs->f->maxstacksize = cast_byte(newstack);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void luaK_reserveregs (FuncState *fs, int n) {
|
||||
luaK_checkstack(fs, n);
|
||||
fs->freereg += n;
|
||||
}
|
||||
|
||||
|
||||
static void freereg (FuncState *fs, int reg) {
|
||||
if (!ISK(reg) && reg >= fs->nactvar) {
|
||||
fs->freereg--;
|
||||
lua_assert(reg == fs->freereg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void freeexp (FuncState *fs, expdesc *e) {
|
||||
if (e->k == VNONRELOC)
|
||||
freereg(fs, e->u.s.info);
|
||||
}
|
||||
|
||||
|
||||
static int addk (FuncState *fs, TValue *k, TValue *v) {
|
||||
lua_State *L = fs->L;
|
||||
TValue *idx = luaH_set(L, fs->h, k);
|
||||
Proto *f = fs->f;
|
||||
int oldsize = f->sizek;
|
||||
if (ttisnumber(idx)) {
|
||||
lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));
|
||||
return cast_int(nvalue(idx));
|
||||
}
|
||||
else { /* constant not found; create a new entry */
|
||||
setnvalue(idx, cast_num(fs->nk));
|
||||
luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
|
||||
MAXARG_Bx, "constant table overflow");
|
||||
while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
|
||||
setobj(L, &f->k[fs->nk], v);
|
||||
luaC_barrier(L, f, v);
|
||||
return fs->nk++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int luaK_stringK (FuncState *fs, TString *s) {
|
||||
TValue o;
|
||||
setsvalue(fs->L, &o, s);
|
||||
return addk(fs, &o, &o);
|
||||
}
|
||||
|
||||
|
||||
int luaK_numberK (FuncState *fs, lua_Number r) {
|
||||
TValue o;
|
||||
setnvalue(&o, r);
|
||||
return addk(fs, &o, &o);
|
||||
}
|
||||
|
||||
|
||||
static int boolK (FuncState *fs, int b) {
|
||||
TValue o;
|
||||
setbvalue(&o, b);
|
||||
return addk(fs, &o, &o);
|
||||
}
|
||||
|
||||
|
||||
static int nilK (FuncState *fs) {
|
||||
TValue k, v;
|
||||
setnilvalue(&v);
|
||||
/* cannot use nil as key; instead use table itself to represent nil */
|
||||
sethvalue(fs->L, &k, fs->h);
|
||||
return addk(fs, &k, &v);
|
||||
}
|
||||
|
||||
|
||||
void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
|
||||
if (e->k == VCALL) { /* expression is an open function call? */
|
||||
SETARG_C(getcode(fs, e), nresults+1);
|
||||
}
|
||||
else if (e->k == VVARARG) {
|
||||
SETARG_B(getcode(fs, e), nresults+1);
|
||||
SETARG_A(getcode(fs, e), fs->freereg);
|
||||
luaK_reserveregs(fs, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void luaK_setoneret (FuncState *fs, expdesc *e) {
|
||||
if (e->k == VCALL) { /* expression is an open function call? */
|
||||
e->k = VNONRELOC;
|
||||
e->u.s.info = GETARG_A(getcode(fs, e));
|
||||
}
|
||||
else if (e->k == VVARARG) {
|
||||
SETARG_B(getcode(fs, e), 2);
|
||||
e->k = VRELOCABLE; /* can relocate its simple result */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void luaK_dischargevars (FuncState *fs, expdesc *e) {
|
||||
switch (e->k) {
|
||||
case VLOCAL: {
|
||||
e->k = VNONRELOC;
|
||||
break;
|
||||
}
|
||||
case VUPVAL: {
|
||||
e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0);
|
||||
e->k = VRELOCABLE;
|
||||
break;
|
||||
}
|
||||
case VGLOBAL: {
|
||||
e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);
|
||||
e->k = VRELOCABLE;
|
||||
break;
|
||||
}
|
||||
case VINDEXED: {
|
||||
freereg(fs, e->u.s.aux);
|
||||
freereg(fs, e->u.s.info);
|
||||
e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux);
|
||||
e->k = VRELOCABLE;
|
||||
break;
|
||||
}
|
||||
case VVARARG:
|
||||
case VCALL: {
|
||||
luaK_setoneret(fs, e);
|
||||
break;
|
||||
}
|
||||
default: break; /* there is one value available (somewhere) */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int code_label (FuncState *fs, int A, int b, int jump) {
|
||||
luaK_getlabel(fs); /* those instructions may be jump targets */
|
||||
return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);
|
||||
}
|
||||
|
||||
|
||||
static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
|
||||
luaK_dischargevars(fs, e);
|
||||
switch (e->k) {
|
||||
case VNIL: {
|
||||
luaK_nil(fs, reg, 1);
|
||||
break;
|
||||
}
|
||||
case VFALSE: case VTRUE: {
|
||||
luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
|
||||
break;
|
||||
}
|
||||
case VK: {
|
||||
luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info);
|
||||
break;
|
||||
}
|
||||
case VKNUM: {
|
||||
luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
|
||||
break;
|
||||
}
|
||||
case VRELOCABLE: {
|
||||
Instruction *pc = &getcode(fs, e);
|
||||
SETARG_A(*pc, reg);
|
||||
break;
|
||||
}
|
||||
case VNONRELOC: {
|
||||
if (reg != e->u.s.info)
|
||||
luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
lua_assert(e->k == VVOID || e->k == VJMP);
|
||||
return; /* nothing to do... */
|
||||
}
|
||||
}
|
||||
e->u.s.info = reg;
|
||||
e->k = VNONRELOC;
|
||||
}
|
||||
|
||||
|
||||
static void discharge2anyreg (FuncState *fs, expdesc *e) {
|
||||
if (e->k != VNONRELOC) {
|
||||
luaK_reserveregs(fs, 1);
|
||||
discharge2reg(fs, e, fs->freereg-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void exp2reg (FuncState *fs, expdesc *e, int reg) {
|
||||
discharge2reg(fs, e, reg);
|
||||
if (e->k == VJMP)
|
||||
luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */
|
||||
if (hasjumps(e)) {
|
||||
int final; /* position after whole expression */
|
||||
int p_f = NO_JUMP; /* position of an eventual LOAD false */
|
||||
int p_t = NO_JUMP; /* position of an eventual LOAD true */
|
||||
if (need_value(fs, e->t) || need_value(fs, e->f)) {
|
||||
int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
|
||||
p_f = code_label(fs, reg, 0, 1);
|
||||
p_t = code_label(fs, reg, 1, 0);
|
||||
luaK_patchtohere(fs, fj);
|
||||
}
|
||||
final = luaK_getlabel(fs);
|
||||
patchlistaux(fs, e->f, final, reg, p_f);
|
||||
patchlistaux(fs, e->t, final, reg, p_t);
|
||||
}
|
||||
e->f = e->t = NO_JUMP;
|
||||
e->u.s.info = reg;
|
||||
e->k = VNONRELOC;
|
||||
}
|
||||
|
||||
|
||||
void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
|
||||
luaK_dischargevars(fs, e);
|
||||
freeexp(fs, e);
|
||||
luaK_reserveregs(fs, 1);
|
||||
exp2reg(fs, e, fs->freereg - 1);
|
||||
}
|
||||
|
||||
|
||||
int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
|
||||
luaK_dischargevars(fs, e);
|
||||
if (e->k == VNONRELOC) {
|
||||
if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */
|
||||
if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */
|
||||
exp2reg(fs, e, e->u.s.info); /* put value on it */
|
||||
return e->u.s.info;
|
||||
}
|
||||
}
|
||||
luaK_exp2nextreg(fs, e); /* default */
|
||||
return e->u.s.info;
|
||||
}
|
||||
|
||||
|
||||
void luaK_exp2val (FuncState *fs, expdesc *e) {
|
||||
if (hasjumps(e))
|
||||
luaK_exp2anyreg(fs, e);
|
||||
else
|
||||
luaK_dischargevars(fs, e);
|
||||
}
|
||||
|
||||
|
||||
int luaK_exp2RK (FuncState *fs, expdesc *e) {
|
||||
luaK_exp2val(fs, e);
|
||||
switch (e->k) {
|
||||
case VKNUM:
|
||||
case VTRUE:
|
||||
case VFALSE:
|
||||
case VNIL: {
|
||||
if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */
|
||||
e->u.s.info = (e->k == VNIL) ? nilK(fs) :
|
||||
(e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
|
||||
boolK(fs, (e->k == VTRUE));
|
||||
e->k = VK;
|
||||
return RKASK(e->u.s.info);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
case VK: {
|
||||
if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */
|
||||
return RKASK(e->u.s.info);
|
||||
else break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
/* not a constant in the right range: put it in a register */
|
||||
return luaK_exp2anyreg(fs, e);
|
||||
}
|
||||
|
||||
|
||||
void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
|
||||
switch (var->k) {
|
||||
case VLOCAL: {
|
||||
freeexp(fs, ex);
|
||||
exp2reg(fs, ex, var->u.s.info);
|
||||
return;
|
||||
}
|
||||
case VUPVAL: {
|
||||
int e = luaK_exp2anyreg(fs, ex);
|
||||
luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0);
|
||||
break;
|
||||
}
|
||||
case VGLOBAL: {
|
||||
int e = luaK_exp2anyreg(fs, ex);
|
||||
luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);
|
||||
break;
|
||||
}
|
||||
case VINDEXED: {
|
||||
int e = luaK_exp2RK(fs, ex);
|
||||
luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
lua_assert(0); /* invalid var kind to store */
|
||||
break;
|
||||
}
|
||||
}
|
||||
freeexp(fs, ex);
|
||||
}
|
||||
|
||||
|
||||
void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
|
||||
int func;
|
||||
luaK_exp2anyreg(fs, e);
|
||||
freeexp(fs, e);
|
||||
func = fs->freereg;
|
||||
luaK_reserveregs(fs, 2);
|
||||
luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));
|
||||
freeexp(fs, key);
|
||||
e->u.s.info = func;
|
||||
e->k = VNONRELOC;
|
||||
}
|
||||
|
||||
|
||||
static void invertjump (FuncState *fs, expdesc *e) {
|
||||
Instruction *pc = getjumpcontrol(fs, e->u.s.info);
|
||||
lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
|
||||
GET_OPCODE(*pc) != OP_TEST);
|
||||
SETARG_A(*pc, !(GETARG_A(*pc)));
|
||||
}
|
||||
|
||||
|
||||
static int jumponcond (FuncState *fs, expdesc *e, int cond) {
|
||||
if (e->k == VRELOCABLE) {
|
||||
Instruction ie = getcode(fs, e);
|
||||
if (GET_OPCODE(ie) == OP_NOT) {
|
||||
fs->pc--; /* remove previous OP_NOT */
|
||||
return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
|
||||
}
|
||||
/* else go through */
|
||||
}
|
||||
discharge2anyreg(fs, e);
|
||||
freeexp(fs, e);
|
||||
return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond);
|
||||
}
|
||||
|
||||
|
||||
void luaK_goiftrue (FuncState *fs, expdesc *e) {
|
||||
int pc; /* pc of last jump */
|
||||
luaK_dischargevars(fs, e);
|
||||
switch (e->k) {
|
||||
case VK: case VKNUM: case VTRUE: {
|
||||
pc = NO_JUMP; /* always true; do nothing */
|
||||
break;
|
||||
}
|
||||
case VFALSE: {
|
||||
pc = luaK_jump(fs); /* always jump */
|
||||
break;
|
||||
}
|
||||
case VJMP: {
|
||||
invertjump(fs, e);
|
||||
pc = e->u.s.info;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
pc = jumponcond(fs, e, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */
|
||||
luaK_patchtohere(fs, e->t);
|
||||
e->t = NO_JUMP;
|
||||
}
|
||||
|
||||
|
||||
static void luaK_goiffalse (FuncState *fs, expdesc *e) {
|
||||
int pc; /* pc of last jump */
|
||||
luaK_dischargevars(fs, e);
|
||||
switch (e->k) {
|
||||
case VNIL: case VFALSE: {
|
||||
pc = NO_JUMP; /* always false; do nothing */
|
||||
break;
|
||||
}
|
||||
case VTRUE: {
|
||||
pc = luaK_jump(fs); /* always jump */
|
||||
break;
|
||||
}
|
||||
case VJMP: {
|
||||
pc = e->u.s.info;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
pc = jumponcond(fs, e, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */
|
||||
luaK_patchtohere(fs, e->f);
|
||||
e->f = NO_JUMP;
|
||||
}
|
||||
|
||||
|
||||
static void codenot (FuncState *fs, expdesc *e) {
|
||||
luaK_dischargevars(fs, e);
|
||||
switch (e->k) {
|
||||
case VNIL: case VFALSE: {
|
||||
e->k = VTRUE;
|
||||
break;
|
||||
}
|
||||
case VK: case VKNUM: case VTRUE: {
|
||||
e->k = VFALSE;
|
||||
break;
|
||||
}
|
||||
case VJMP: {
|
||||
invertjump(fs, e);
|
||||
break;
|
||||
}
|
||||
case VRELOCABLE:
|
||||
case VNONRELOC: {
|
||||
discharge2anyreg(fs, e);
|
||||
freeexp(fs, e);
|
||||
e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0);
|
||||
e->k = VRELOCABLE;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
lua_assert(0); /* cannot happen */
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* interchange true and false lists */
|
||||
{ int temp = e->f; e->f = e->t; e->t = temp; }
|
||||
removevalues(fs, e->f);
|
||||
removevalues(fs, e->t);
|
||||
}
|
||||
|
||||
|
||||
void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
|
||||
t->u.s.aux = luaK_exp2RK(fs, k);
|
||||
t->k = VINDEXED;
|
||||
}
|
||||
|
||||
|
||||
static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
|
||||
lua_Number v1, v2, r;
|
||||
if (!isnumeral(e1) || !isnumeral(e2)) return 0;
|
||||
v1 = e1->u.nval;
|
||||
v2 = e2->u.nval;
|
||||
switch (op) {
|
||||
case OP_ADD: r = luai_numadd(v1, v2); break;
|
||||
case OP_SUB: r = luai_numsub(v1, v2); break;
|
||||
case OP_MUL: r = luai_nummul(v1, v2); break;
|
||||
case OP_DIV:
|
||||
if (v2 == 0) return 0; /* do not attempt to divide by 0 */
|
||||
r = luai_numdiv(v1, v2); break;
|
||||
case OP_MOD:
|
||||
if (v2 == 0) return 0; /* do not attempt to divide by 0 */
|
||||
r = luai_nummod(v1, v2); break;
|
||||
case OP_POW: r = luai_numpow(v1, v2); break;
|
||||
case OP_UNM: r = luai_numunm(v1); break;
|
||||
case OP_LEN: return 0; /* no constant folding for 'len' */
|
||||
default: lua_assert(0); r = 0; break;
|
||||
}
|
||||
if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */
|
||||
e1->u.nval = r;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
|
||||
if (constfolding(op, e1, e2))
|
||||
return;
|
||||
else {
|
||||
int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
|
||||
int o1 = luaK_exp2RK(fs, e1);
|
||||
if (o1 > o2) {
|
||||
freeexp(fs, e1);
|
||||
freeexp(fs, e2);
|
||||
}
|
||||
else {
|
||||
freeexp(fs, e2);
|
||||
freeexp(fs, e1);
|
||||
}
|
||||
e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);
|
||||
e1->k = VRELOCABLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
|
||||
expdesc *e2) {
|
||||
int o1 = luaK_exp2RK(fs, e1);
|
||||
int o2 = luaK_exp2RK(fs, e2);
|
||||
freeexp(fs, e2);
|
||||
freeexp(fs, e1);
|
||||
if (cond == 0 && op != OP_EQ) {
|
||||
int temp; /* exchange args to replace by `<' or `<=' */
|
||||
temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
|
||||
cond = 1;
|
||||
}
|
||||
e1->u.s.info = condjump(fs, op, cond, o1, o2);
|
||||
e1->k = VJMP;
|
||||
}
|
||||
|
||||
|
||||
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
|
||||
expdesc e2;
|
||||
e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
|
||||
switch (op) {
|
||||
case OPR_MINUS: {
|
||||
if (!isnumeral(e))
|
||||
luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */
|
||||
codearith(fs, OP_UNM, e, &e2);
|
||||
break;
|
||||
}
|
||||
case OPR_NOT: codenot(fs, e); break;
|
||||
case OPR_LEN: {
|
||||
luaK_exp2anyreg(fs, e); /* cannot operate on constants */
|
||||
codearith(fs, OP_LEN, e, &e2);
|
||||
break;
|
||||
}
|
||||
default: lua_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
|
||||
switch (op) {
|
||||
case OPR_AND: {
|
||||
luaK_goiftrue(fs, v);
|
||||
break;
|
||||
}
|
||||
case OPR_OR: {
|
||||
luaK_goiffalse(fs, v);
|
||||
break;
|
||||
}
|
||||
case OPR_CONCAT: {
|
||||
luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */
|
||||
break;
|
||||
}
|
||||
case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
|
||||
case OPR_MOD: case OPR_POW: {
|
||||
if (!isnumeral(v)) luaK_exp2RK(fs, v);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
luaK_exp2RK(fs, v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
|
||||
switch (op) {
|
||||
case OPR_AND: {
|
||||
lua_assert(e1->t == NO_JUMP); /* list must be closed */
|
||||
luaK_dischargevars(fs, e2);
|
||||
luaK_concat(fs, &e2->f, e1->f);
|
||||
*e1 = *e2;
|
||||
break;
|
||||
}
|
||||
case OPR_OR: {
|
||||
lua_assert(e1->f == NO_JUMP); /* list must be closed */
|
||||
luaK_dischargevars(fs, e2);
|
||||
luaK_concat(fs, &e2->t, e1->t);
|
||||
*e1 = *e2;
|
||||
break;
|
||||
}
|
||||
case OPR_CONCAT: {
|
||||
luaK_exp2val(fs, e2);
|
||||
if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
|
||||
lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1);
|
||||
freeexp(fs, e1);
|
||||
SETARG_B(getcode(fs, e2), e1->u.s.info);
|
||||
e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info;
|
||||
}
|
||||
else {
|
||||
luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */
|
||||
codearith(fs, OP_CONCAT, e1, e2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break;
|
||||
case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break;
|
||||
case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break;
|
||||
case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break;
|
||||
case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break;
|
||||
case OPR_POW: codearith(fs, OP_POW, e1, e2); break;
|
||||
case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break;
|
||||
case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break;
|
||||
case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break;
|
||||
case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break;
|
||||
case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break;
|
||||
case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break;
|
||||
default: lua_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void luaK_fixline (FuncState *fs, int line) {
|
||||
fs->f->lineinfo[fs->pc - 1] = line;
|
||||
}
|
||||
|
||||
|
||||
static int luaK_code (FuncState *fs, Instruction i, int line) {
|
||||
Proto *f = fs->f;
|
||||
dischargejpc(fs); /* `pc' will change */
|
||||
/* put new instruction in code array */
|
||||
luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,
|
||||
MAX_INT, "code size overflow");
|
||||
f->code[fs->pc] = i;
|
||||
/* save corresponding line information */
|
||||
luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
|
||||
MAX_INT, "code size overflow");
|
||||
f->lineinfo[fs->pc] = line;
|
||||
return fs->pc++;
|
||||
}
|
||||
|
||||
|
||||
int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
|
||||
lua_assert(getOpMode(o) == iABC);
|
||||
lua_assert(getBMode(o) != OpArgN || b == 0);
|
||||
lua_assert(getCMode(o) != OpArgN || c == 0);
|
||||
return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);
|
||||
}
|
||||
|
||||
|
||||
int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
|
||||
lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
|
||||
lua_assert(getCMode(o) == OpArgN);
|
||||
return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);
|
||||
}
|
||||
|
||||
|
||||
void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
|
||||
int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1;
|
||||
int b = (tostore == LUA_MULTRET) ? 0 : tostore;
|
||||
lua_assert(tostore != 0);
|
||||
if (c <= MAXARG_C)
|
||||
luaK_codeABC(fs, OP_SETLIST, base, b, c);
|
||||
else {
|
||||
luaK_codeABC(fs, OP_SETLIST, base, b, 0);
|
||||
luaK_code(fs, cast(Instruction, c), fs->ls->lastline);
|
||||
}
|
||||
fs->freereg = base + 1; /* free registers with list values */
|
||||
}
|
||||
|
||||
Vendored
-76
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $
|
||||
** Code generator for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef lcode_h
|
||||
#define lcode_h
|
||||
|
||||
#include "llex.h"
|
||||
#include "lobject.h"
|
||||
#include "lopcodes.h"
|
||||
#include "lparser.h"
|
||||
|
||||
|
||||
/*
|
||||
** Marks the end of a patch list. It is an invalid value both as an absolute
|
||||
** address, and as a list link (would link an element to itself).
|
||||
*/
|
||||
#define NO_JUMP (-1)
|
||||
|
||||
|
||||
/*
|
||||
** grep "ORDER OPR" if you change these enums
|
||||
*/
|
||||
typedef enum BinOpr {
|
||||
OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW,
|
||||
OPR_CONCAT,
|
||||
OPR_NE, OPR_EQ,
|
||||
OPR_LT, OPR_LE, OPR_GT, OPR_GE,
|
||||
OPR_AND, OPR_OR,
|
||||
OPR_NOBINOPR
|
||||
} BinOpr;
|
||||
|
||||
|
||||
typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
|
||||
|
||||
|
||||
#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info])
|
||||
|
||||
#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
|
||||
|
||||
#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET)
|
||||
|
||||
LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
|
||||
LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
|
||||
LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
|
||||
LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
|
||||
LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);
|
||||
LUAI_FUNC void luaK_checkstack (FuncState *fs, int n);
|
||||
LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);
|
||||
LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r);
|
||||
LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
|
||||
LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
|
||||
LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
|
||||
LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
|
||||
LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC int luaK_jump (FuncState *fs);
|
||||
LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);
|
||||
LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);
|
||||
LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
|
||||
LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);
|
||||
LUAI_FUNC int luaK_getlabel (FuncState *fs);
|
||||
LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v);
|
||||
LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
|
||||
LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2);
|
||||
LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
|
||||
|
||||
|
||||
#endif
|
||||
Vendored
-397
@@ -1,397 +0,0 @@
|
||||
/*
|
||||
** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $
|
||||
** Interface from Lua to its debug API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ldblib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
|
||||
|
||||
static int db_getregistry (lua_State *L) {
|
||||
lua_pushvalue(L, LUA_REGISTRYINDEX);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int db_getmetatable (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
if (!lua_getmetatable(L, 1)) {
|
||||
lua_pushnil(L); /* no metatable */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int db_setmetatable (lua_State *L) {
|
||||
int t = lua_type(L, 2);
|
||||
luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
|
||||
"nil or table expected");
|
||||
lua_settop(L, 2);
|
||||
lua_pushboolean(L, lua_setmetatable(L, 1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int db_getfenv (lua_State *L) {
|
||||
lua_getfenv(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int db_setfenv (lua_State *L) {
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
lua_settop(L, 2);
|
||||
if (lua_setfenv(L, 1) == 0)
|
||||
luaL_error(L, LUA_QL("setfenv")
|
||||
" cannot change environment of given object");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void settabss (lua_State *L, const char *i, const char *v) {
|
||||
lua_pushstring(L, v);
|
||||
lua_setfield(L, -2, i);
|
||||
}
|
||||
|
||||
|
||||
static void settabsi (lua_State *L, const char *i, int v) {
|
||||
lua_pushinteger(L, v);
|
||||
lua_setfield(L, -2, i);
|
||||
}
|
||||
|
||||
|
||||
static lua_State *getthread (lua_State *L, int *arg) {
|
||||
if (lua_isthread(L, 1)) {
|
||||
*arg = 1;
|
||||
return lua_tothread(L, 1);
|
||||
}
|
||||
else {
|
||||
*arg = 0;
|
||||
return L;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
|
||||
if (L == L1) {
|
||||
lua_pushvalue(L, -2);
|
||||
lua_remove(L, -3);
|
||||
}
|
||||
else
|
||||
lua_xmove(L1, L, 1);
|
||||
lua_setfield(L, -2, fname);
|
||||
}
|
||||
|
||||
|
||||
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, "flnSu");
|
||||
if (lua_isnumber(L, arg+1)) {
|
||||
if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
|
||||
lua_pushnil(L); /* level out of range */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (lua_isfunction(L, arg+1)) {
|
||||
lua_pushfstring(L, ">%s", options);
|
||||
options = lua_tostring(L, -1);
|
||||
lua_pushvalue(L, arg+1);
|
||||
lua_xmove(L, L1, 1);
|
||||
}
|
||||
else
|
||||
return luaL_argerror(L, arg+1, "function or level expected");
|
||||
if (!lua_getinfo(L1, options, &ar))
|
||||
return luaL_argerror(L, arg+2, "invalid option");
|
||||
lua_createtable(L, 0, 2);
|
||||
if (strchr(options, 'S')) {
|
||||
settabss(L, "source", ar.source);
|
||||
settabss(L, "short_src", ar.short_src);
|
||||
settabsi(L, "linedefined", ar.linedefined);
|
||||
settabsi(L, "lastlinedefined", ar.lastlinedefined);
|
||||
settabss(L, "what", ar.what);
|
||||
}
|
||||
if (strchr(options, 'l'))
|
||||
settabsi(L, "currentline", ar.currentline);
|
||||
if (strchr(options, 'u'))
|
||||
settabsi(L, "nups", ar.nups);
|
||||
if (strchr(options, 'n')) {
|
||||
settabss(L, "name", ar.name);
|
||||
settabss(L, "namewhat", ar.namewhat);
|
||||
}
|
||||
if (strchr(options, 'L'))
|
||||
treatstackoption(L, L1, "activelines");
|
||||
if (strchr(options, 'f'))
|
||||
treatstackoption(L, L1, "func");
|
||||
return 1; /* return table */
|
||||
}
|
||||
|
||||
|
||||
static int db_getlocal (lua_State *L) {
|
||||
int arg;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
lua_Debug ar;
|
||||
const char *name;
|
||||
if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
|
||||
return luaL_argerror(L, arg+1, "level out of range");
|
||||
name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2));
|
||||
if (name) {
|
||||
lua_xmove(L1, L, 1);
|
||||
lua_pushstring(L, name);
|
||||
lua_pushvalue(L, -2);
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int db_setlocal (lua_State *L) {
|
||||
int arg;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
lua_Debug ar;
|
||||
if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
|
||||
return luaL_argerror(L, arg+1, "level out of range");
|
||||
luaL_checkany(L, arg+3);
|
||||
lua_settop(L, arg+3);
|
||||
lua_xmove(L, L1, 1);
|
||||
lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int auxupvalue (lua_State *L, int get) {
|
||||
const char *name;
|
||||
int n = luaL_checkint(L, 2);
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||
if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */
|
||||
name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
|
||||
if (name == NULL) return 0;
|
||||
lua_pushstring(L, name);
|
||||
lua_insert(L, -(get+1));
|
||||
return get + 1;
|
||||
}
|
||||
|
||||
|
||||
static int db_getupvalue (lua_State *L) {
|
||||
return auxupvalue(L, 1);
|
||||
}
|
||||
|
||||
|
||||
static int db_setupvalue (lua_State *L) {
|
||||
luaL_checkany(L, 3);
|
||||
return auxupvalue(L, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char KEY_HOOK = 'h';
|
||||
|
||||
|
||||
static void hookf (lua_State *L, lua_Debug *ar) {
|
||||
static const char *const hooknames[] =
|
||||
{"call", "return", "line", "count", "tail return"};
|
||||
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_pushlightuserdata(L, L);
|
||||
lua_rawget(L, -2);
|
||||
if (lua_isfunction(L, -1)) {
|
||||
lua_pushstring(L, hooknames[(int)ar->event]);
|
||||
if (ar->currentline >= 0)
|
||||
lua_pushinteger(L, ar->currentline);
|
||||
else lua_pushnil(L);
|
||||
lua_assert(lua_getinfo(L, "lS", ar));
|
||||
lua_call(L, 2, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int makemask (const char *smask, int count) {
|
||||
int mask = 0;
|
||||
if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
|
||||
if (strchr(smask, 'r')) mask |= LUA_MASKRET;
|
||||
if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
|
||||
if (count > 0) mask |= LUA_MASKCOUNT;
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
static char *unmakemask (int mask, char *smask) {
|
||||
int i = 0;
|
||||
if (mask & LUA_MASKCALL) smask[i++] = 'c';
|
||||
if (mask & LUA_MASKRET) smask[i++] = 'r';
|
||||
if (mask & LUA_MASKLINE) smask[i++] = 'l';
|
||||
smask[i] = '\0';
|
||||
return smask;
|
||||
}
|
||||
|
||||
|
||||
static void gethooktable (lua_State *L) {
|
||||
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
if (!lua_istable(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
lua_createtable(L, 0, 1);
|
||||
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
|
||||
lua_pushvalue(L, -2);
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int db_sethook (lua_State *L) {
|
||||
int arg, mask, count;
|
||||
lua_Hook func;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
if (lua_isnoneornil(L, arg+1)) {
|
||||
lua_settop(L, arg+1);
|
||||
func = NULL; mask = 0; count = 0; /* turn off hooks */
|
||||
}
|
||||
else {
|
||||
const char *smask = luaL_checkstring(L, arg+2);
|
||||
luaL_checktype(L, arg+1, LUA_TFUNCTION);
|
||||
count = luaL_optint(L, arg+3, 0);
|
||||
func = hookf; mask = makemask(smask, count);
|
||||
}
|
||||
gethooktable(L);
|
||||
lua_pushlightuserdata(L, L1);
|
||||
lua_pushvalue(L, arg+1);
|
||||
lua_rawset(L, -3); /* set new hook */
|
||||
lua_pop(L, 1); /* remove hook table */
|
||||
lua_sethook(L1, func, mask, count); /* set hooks */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int db_gethook (lua_State *L) {
|
||||
int arg;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
char buff[5];
|
||||
int mask = lua_gethookmask(L1);
|
||||
lua_Hook hook = lua_gethook(L1);
|
||||
if (hook != NULL && hook != hookf) /* external hook? */
|
||||
lua_pushliteral(L, "external hook");
|
||||
else {
|
||||
gethooktable(L);
|
||||
lua_pushlightuserdata(L, L1);
|
||||
lua_rawget(L, -2); /* get hook */
|
||||
lua_remove(L, -2); /* remove hook table */
|
||||
}
|
||||
lua_pushstring(L, unmakemask(mask, buff));
|
||||
lua_pushinteger(L, lua_gethookcount(L1));
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
static int db_debug (lua_State *L) {
|
||||
for (;;) {
|
||||
char buffer[250];
|
||||
fputs("lua_debug> ", stderr);
|
||||
if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
|
||||
strcmp(buffer, "cont\n") == 0)
|
||||
return 0;
|
||||
if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
|
||||
lua_pcall(L, 0, 0, 0)) {
|
||||
fputs(lua_tostring(L, -1), stderr);
|
||||
fputs("\n", stderr);
|
||||
}
|
||||
lua_settop(L, 0); /* remove eventual returns */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define LEVELS1 12 /* size of the first part of the stack */
|
||||
#define LEVELS2 10 /* size of the second part of the stack */
|
||||
|
||||
static int db_errorfb (lua_State *L) {
|
||||
int level;
|
||||
int firstpart = 1; /* still before eventual `...' */
|
||||
int arg;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
lua_Debug ar;
|
||||
if (lua_isnumber(L, arg+2)) {
|
||||
level = (int)lua_tointeger(L, arg+2);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
else
|
||||
level = (L == L1) ? 1 : 0; /* level 0 may be this own function */
|
||||
if (lua_gettop(L) == arg)
|
||||
lua_pushliteral(L, "");
|
||||
else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */
|
||||
else lua_pushliteral(L, "\n");
|
||||
lua_pushliteral(L, "stack traceback:");
|
||||
while (lua_getstack(L1, level++, &ar)) {
|
||||
if (level > LEVELS1 && firstpart) {
|
||||
/* no more than `LEVELS2' more levels? */
|
||||
if (!lua_getstack(L1, level+LEVELS2, &ar))
|
||||
level--; /* keep going */
|
||||
else {
|
||||
lua_pushliteral(L, "\n\t..."); /* too many levels */
|
||||
while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */
|
||||
level++;
|
||||
}
|
||||
firstpart = 0;
|
||||
continue;
|
||||
}
|
||||
lua_pushliteral(L, "\n\t");
|
||||
lua_getinfo(L1, "Snl", &ar);
|
||||
lua_pushfstring(L, "%s:", ar.short_src);
|
||||
if (ar.currentline > 0)
|
||||
lua_pushfstring(L, "%d:", ar.currentline);
|
||||
if (*ar.namewhat != '\0') /* is there a name? */
|
||||
lua_pushfstring(L, " in function " LUA_QS, ar.name);
|
||||
else {
|
||||
if (*ar.what == 'm') /* main? */
|
||||
lua_pushfstring(L, " in main chunk");
|
||||
else if (*ar.what == 'C' || *ar.what == 't')
|
||||
lua_pushliteral(L, " ?"); /* C function or tail call */
|
||||
else
|
||||
lua_pushfstring(L, " in function <%s:%d>",
|
||||
ar.short_src, ar.linedefined);
|
||||
}
|
||||
lua_concat(L, lua_gettop(L) - arg);
|
||||
}
|
||||
lua_concat(L, lua_gettop(L) - arg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg dblib[] = {
|
||||
{"debug", db_debug},
|
||||
{"getfenv", db_getfenv},
|
||||
{"gethook", db_gethook},
|
||||
{"getinfo", db_getinfo},
|
||||
{"getlocal", db_getlocal},
|
||||
{"getregistry", db_getregistry},
|
||||
{"getmetatable", db_getmetatable},
|
||||
{"getupvalue", db_getupvalue},
|
||||
{"setfenv", db_setfenv},
|
||||
{"sethook", db_sethook},
|
||||
{"setlocal", db_setlocal},
|
||||
{"setmetatable", db_setmetatable},
|
||||
{"setupvalue", db_setupvalue},
|
||||
{"traceback", db_errorfb},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
LUALIB_API int luaopen_debug (lua_State *L) {
|
||||
luaL_register(L, LUA_DBLIBNAME, dblib);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Vendored
-638
@@ -1,638 +0,0 @@
|
||||
/*
|
||||
** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $
|
||||
** Debug Interface
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define ldebug_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lapi.h"
|
||||
#include "lcode.h"
|
||||
#include "ldebug.h"
|
||||
#include "ldo.h"
|
||||
#include "lfunc.h"
|
||||
#include "lobject.h"
|
||||
#include "lopcodes.h"
|
||||
#include "lstate.h"
|
||||
#include "lstring.h"
|
||||
#include "ltable.h"
|
||||
#include "ltm.h"
|
||||
#include "lvm.h"
|
||||
|
||||
|
||||
|
||||
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
|
||||
|
||||
|
||||
static int currentpc (lua_State *L, CallInfo *ci) {
|
||||
if (!isLua(ci)) return -1; /* function is not a Lua function? */
|
||||
if (ci == L->ci)
|
||||
ci->savedpc = L->savedpc;
|
||||
return pcRel(ci->savedpc, ci_func(ci)->l.p);
|
||||
}
|
||||
|
||||
|
||||
static int currentline (lua_State *L, CallInfo *ci) {
|
||||
int pc = currentpc(L, ci);
|
||||
if (pc < 0)
|
||||
return -1; /* only active lua functions have current-line information */
|
||||
else
|
||||
return getline(ci_func(ci)->l.p, pc);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** this function can be called asynchronous (e.g. during a signal)
|
||||
*/
|
||||
LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
|
||||
if (func == NULL || mask == 0) { /* turn off hooks? */
|
||||
mask = 0;
|
||||
func = NULL;
|
||||
}
|
||||
L->hook = func;
|
||||
L->basehookcount = count;
|
||||
resethookcount(L);
|
||||
L->hookmask = cast_byte(mask);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
LUA_API lua_Hook lua_gethook (lua_State *L) {
|
||||
return L->hook;
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_gethookmask (lua_State *L) {
|
||||
return L->hookmask;
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_gethookcount (lua_State *L) {
|
||||
return L->basehookcount;
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
|
||||
int status;
|
||||
CallInfo *ci;
|
||||
lua_lock(L);
|
||||
for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {
|
||||
level--;
|
||||
if (f_isLua(ci)) /* Lua function? */
|
||||
level -= ci->tailcalls; /* skip lost tail calls */
|
||||
}
|
||||
if (level == 0 && ci > L->base_ci) { /* level found? */
|
||||
status = 1;
|
||||
ar->i_ci = cast_int(ci - L->base_ci);
|
||||
}
|
||||
else if (level < 0) { /* level is of a lost tail call? */
|
||||
status = 1;
|
||||
ar->i_ci = 0;
|
||||
}
|
||||
else status = 0; /* no such level */
|
||||
lua_unlock(L);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static Proto *getluaproto (CallInfo *ci) {
|
||||
return (isLua(ci) ? ci_func(ci)->l.p : NULL);
|
||||
}
|
||||
|
||||
|
||||
static const char *findlocal (lua_State *L, CallInfo *ci, int n) {
|
||||
const char *name;
|
||||
Proto *fp = getluaproto(ci);
|
||||
if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL)
|
||||
return name; /* is a local variable in a Lua function */
|
||||
else {
|
||||
StkId limit = (ci == L->ci) ? L->top : (ci+1)->func;
|
||||
if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */
|
||||
return "(*temporary)";
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
|
||||
CallInfo *ci = L->base_ci + ar->i_ci;
|
||||
const char *name = findlocal(L, ci, n);
|
||||
lua_lock(L);
|
||||
if (name)
|
||||
luaA_pushobject(L, ci->base + (n - 1));
|
||||
lua_unlock(L);
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
|
||||
CallInfo *ci = L->base_ci + ar->i_ci;
|
||||
const char *name = findlocal(L, ci, n);
|
||||
lua_lock(L);
|
||||
if (name)
|
||||
setobjs2s(L, ci->base + (n - 1), L->top - 1);
|
||||
L->top--; /* pop value */
|
||||
lua_unlock(L);
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
static void funcinfo (lua_Debug *ar, Closure *cl) {
|
||||
if (cl->c.isC) {
|
||||
ar->source = "=[C]";
|
||||
ar->linedefined = -1;
|
||||
ar->lastlinedefined = -1;
|
||||
ar->what = "C";
|
||||
}
|
||||
else {
|
||||
ar->source = getstr(cl->l.p->source);
|
||||
ar->linedefined = cl->l.p->linedefined;
|
||||
ar->lastlinedefined = cl->l.p->lastlinedefined;
|
||||
ar->what = (ar->linedefined == 0) ? "main" : "Lua";
|
||||
}
|
||||
luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
|
||||
}
|
||||
|
||||
|
||||
static void info_tailcall (lua_Debug *ar) {
|
||||
ar->name = ar->namewhat = "";
|
||||
ar->what = "tail";
|
||||
ar->lastlinedefined = ar->linedefined = ar->currentline = -1;
|
||||
ar->source = "=(tail call)";
|
||||
luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
|
||||
ar->nups = 0;
|
||||
}
|
||||
|
||||
|
||||
static void collectvalidlines (lua_State *L, Closure *f) {
|
||||
if (f == NULL || f->c.isC) {
|
||||
setnilvalue(L->top);
|
||||
}
|
||||
else {
|
||||
Table *t = luaH_new(L, 0, 0);
|
||||
int *lineinfo = f->l.p->lineinfo;
|
||||
int i;
|
||||
for (i=0; i<f->l.p->sizelineinfo; i++)
|
||||
setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
|
||||
sethvalue(L, L->top, t);
|
||||
}
|
||||
incr_top(L);
|
||||
}
|
||||
|
||||
|
||||
static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
|
||||
Closure *f, CallInfo *ci) {
|
||||
int status = 1;
|
||||
if (f == NULL) {
|
||||
info_tailcall(ar);
|
||||
return status;
|
||||
}
|
||||
for (; *what; what++) {
|
||||
switch (*what) {
|
||||
case 'S': {
|
||||
funcinfo(ar, f);
|
||||
break;
|
||||
}
|
||||
case 'l': {
|
||||
ar->currentline = (ci) ? currentline(L, ci) : -1;
|
||||
break;
|
||||
}
|
||||
case 'u': {
|
||||
ar->nups = f->c.nupvalues;
|
||||
break;
|
||||
}
|
||||
case 'n': {
|
||||
ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL;
|
||||
if (ar->namewhat == NULL) {
|
||||
ar->namewhat = ""; /* not found */
|
||||
ar->name = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'L':
|
||||
case 'f': /* handled by lua_getinfo */
|
||||
break;
|
||||
default: status = 0; /* invalid option */
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
|
||||
int status;
|
||||
Closure *f = NULL;
|
||||
CallInfo *ci = NULL;
|
||||
lua_lock(L);
|
||||
if (*what == '>') {
|
||||
StkId func = L->top - 1;
|
||||
luai_apicheck(L, ttisfunction(func));
|
||||
what++; /* skip the '>' */
|
||||
f = clvalue(func);
|
||||
L->top--; /* pop function */
|
||||
}
|
||||
else if (ar->i_ci != 0) { /* no tail call? */
|
||||
ci = L->base_ci + ar->i_ci;
|
||||
lua_assert(ttisfunction(ci->func));
|
||||
f = clvalue(ci->func);
|
||||
}
|
||||
status = auxgetinfo(L, what, ar, f, ci);
|
||||
if (strchr(what, 'f')) {
|
||||
if (f == NULL) setnilvalue(L->top);
|
||||
else setclvalue(L, L->top, f);
|
||||
incr_top(L);
|
||||
}
|
||||
if (strchr(what, 'L'))
|
||||
collectvalidlines(L, f);
|
||||
lua_unlock(L);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Symbolic Execution and code checker
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
#define check(x) if (!(x)) return 0;
|
||||
|
||||
#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode)
|
||||
|
||||
#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize)
|
||||
|
||||
|
||||
|
||||
static int precheck (const Proto *pt) {
|
||||
check(pt->maxstacksize <= MAXSTACK);
|
||||
check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize);
|
||||
check(!(pt->is_vararg & VARARG_NEEDSARG) ||
|
||||
(pt->is_vararg & VARARG_HASARG));
|
||||
check(pt->sizeupvalues <= pt->nups);
|
||||
check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);
|
||||
check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1])
|
||||
|
||||
int luaG_checkopenop (Instruction i) {
|
||||
switch (GET_OPCODE(i)) {
|
||||
case OP_CALL:
|
||||
case OP_TAILCALL:
|
||||
case OP_RETURN:
|
||||
case OP_SETLIST: {
|
||||
check(GETARG_B(i) == 0);
|
||||
return 1;
|
||||
}
|
||||
default: return 0; /* invalid instruction after an open call */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) {
|
||||
switch (mode) {
|
||||
case OpArgN: check(r == 0); break;
|
||||
case OpArgU: break;
|
||||
case OpArgR: checkreg(pt, r); break;
|
||||
case OpArgK:
|
||||
check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static Instruction symbexec (const Proto *pt, int lastpc, int reg) {
|
||||
int pc;
|
||||
int last; /* stores position of last instruction that changed `reg' */
|
||||
last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */
|
||||
check(precheck(pt));
|
||||
for (pc = 0; pc < lastpc; pc++) {
|
||||
Instruction i = pt->code[pc];
|
||||
OpCode op = GET_OPCODE(i);
|
||||
int a = GETARG_A(i);
|
||||
int b = 0;
|
||||
int c = 0;
|
||||
check(op < NUM_OPCODES);
|
||||
checkreg(pt, a);
|
||||
switch (getOpMode(op)) {
|
||||
case iABC: {
|
||||
b = GETARG_B(i);
|
||||
c = GETARG_C(i);
|
||||
check(checkArgMode(pt, b, getBMode(op)));
|
||||
check(checkArgMode(pt, c, getCMode(op)));
|
||||
break;
|
||||
}
|
||||
case iABx: {
|
||||
b = GETARG_Bx(i);
|
||||
if (getBMode(op) == OpArgK) check(b < pt->sizek);
|
||||
break;
|
||||
}
|
||||
case iAsBx: {
|
||||
b = GETARG_sBx(i);
|
||||
if (getBMode(op) == OpArgR) {
|
||||
int dest = pc+1+b;
|
||||
check(0 <= dest && dest < pt->sizecode);
|
||||
if (dest > 0) {
|
||||
int j;
|
||||
/* check that it does not jump to a setlist count; this
|
||||
is tricky, because the count from a previous setlist may
|
||||
have the same value of an invalid setlist; so, we must
|
||||
go all the way back to the first of them (if any) */
|
||||
for (j = 0; j < dest; j++) {
|
||||
Instruction d = pt->code[dest-1-j];
|
||||
if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break;
|
||||
}
|
||||
/* if 'j' is even, previous value is not a setlist (even if
|
||||
it looks like one) */
|
||||
check((j&1) == 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (testAMode(op)) {
|
||||
if (a == reg) last = pc; /* change register `a' */
|
||||
}
|
||||
if (testTMode(op)) {
|
||||
check(pc+2 < pt->sizecode); /* check skip */
|
||||
check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);
|
||||
}
|
||||
switch (op) {
|
||||
case OP_LOADBOOL: {
|
||||
if (c == 1) { /* does it jump? */
|
||||
check(pc+2 < pt->sizecode); /* check its jump */
|
||||
check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST ||
|
||||
GETARG_C(pt->code[pc+1]) != 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_LOADNIL: {
|
||||
if (a <= reg && reg <= b)
|
||||
last = pc; /* set registers from `a' to `b' */
|
||||
break;
|
||||
}
|
||||
case OP_GETUPVAL:
|
||||
case OP_SETUPVAL: {
|
||||
check(b < pt->nups);
|
||||
break;
|
||||
}
|
||||
case OP_GETGLOBAL:
|
||||
case OP_SETGLOBAL: {
|
||||
check(ttisstring(&pt->k[b]));
|
||||
break;
|
||||
}
|
||||
case OP_SELF: {
|
||||
checkreg(pt, a+1);
|
||||
if (reg == a+1) last = pc;
|
||||
break;
|
||||
}
|
||||
case OP_CONCAT: {
|
||||
check(b < c); /* at least two operands */
|
||||
break;
|
||||
}
|
||||
case OP_TFORLOOP: {
|
||||
check(c >= 1); /* at least one result (control variable) */
|
||||
checkreg(pt, a+2+c); /* space for results */
|
||||
if (reg >= a+2) last = pc; /* affect all regs above its base */
|
||||
break;
|
||||
}
|
||||
case OP_FORLOOP:
|
||||
case OP_FORPREP:
|
||||
checkreg(pt, a+3);
|
||||
/* go through */
|
||||
case OP_JMP: {
|
||||
int dest = pc+1+b;
|
||||
/* not full check and jump is forward and do not skip `lastpc'? */
|
||||
if (reg != NO_REG && pc < dest && dest <= lastpc)
|
||||
pc += b; /* do the jump */
|
||||
break;
|
||||
}
|
||||
case OP_CALL:
|
||||
case OP_TAILCALL: {
|
||||
if (b != 0) {
|
||||
checkreg(pt, a+b-1);
|
||||
}
|
||||
c--; /* c = num. returns */
|
||||
if (c == LUA_MULTRET) {
|
||||
check(checkopenop(pt, pc));
|
||||
}
|
||||
else if (c != 0)
|
||||
checkreg(pt, a+c-1);
|
||||
if (reg >= a) last = pc; /* affect all registers above base */
|
||||
break;
|
||||
}
|
||||
case OP_RETURN: {
|
||||
b--; /* b = num. returns */
|
||||
if (b > 0) checkreg(pt, a+b-1);
|
||||
break;
|
||||
}
|
||||
case OP_SETLIST: {
|
||||
if (b > 0) checkreg(pt, a + b);
|
||||
if (c == 0) {
|
||||
pc++;
|
||||
check(pc < pt->sizecode - 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_CLOSURE: {
|
||||
int nup, j;
|
||||
check(b < pt->sizep);
|
||||
nup = pt->p[b]->nups;
|
||||
check(pc + nup < pt->sizecode);
|
||||
for (j = 1; j <= nup; j++) {
|
||||
OpCode op1 = GET_OPCODE(pt->code[pc + j]);
|
||||
check(op1 == OP_GETUPVAL || op1 == OP_MOVE);
|
||||
}
|
||||
if (reg != NO_REG) /* tracing? */
|
||||
pc += nup; /* do not 'execute' these pseudo-instructions */
|
||||
break;
|
||||
}
|
||||
case OP_VARARG: {
|
||||
check((pt->is_vararg & VARARG_ISVARARG) &&
|
||||
!(pt->is_vararg & VARARG_NEEDSARG));
|
||||
b--;
|
||||
if (b == LUA_MULTRET) check(checkopenop(pt, pc));
|
||||
checkreg(pt, a+b-1);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return pt->code[last];
|
||||
}
|
||||
|
||||
#undef check
|
||||
#undef checkjump
|
||||
#undef checkreg
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
int luaG_checkcode (const Proto *pt) {
|
||||
return (symbexec(pt, pt->sizecode, NO_REG) != 0);
|
||||
}
|
||||
|
||||
|
||||
static const char *kname (Proto *p, int c) {
|
||||
if (ISK(c) && ttisstring(&p->k[INDEXK(c)]))
|
||||
return svalue(&p->k[INDEXK(c)]);
|
||||
else
|
||||
return "?";
|
||||
}
|
||||
|
||||
|
||||
static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,
|
||||
const char **name) {
|
||||
if (isLua(ci)) { /* a Lua function? */
|
||||
Proto *p = ci_func(ci)->l.p;
|
||||
int pc = currentpc(L, ci);
|
||||
Instruction i;
|
||||
*name = luaF_getlocalname(p, stackpos+1, pc);
|
||||
if (*name) /* is a local? */
|
||||
return "local";
|
||||
i = symbexec(p, pc, stackpos); /* try symbolic execution */
|
||||
lua_assert(pc != -1);
|
||||
switch (GET_OPCODE(i)) {
|
||||
case OP_GETGLOBAL: {
|
||||
int g = GETARG_Bx(i); /* global index */
|
||||
lua_assert(ttisstring(&p->k[g]));
|
||||
*name = svalue(&p->k[g]);
|
||||
return "global";
|
||||
}
|
||||
case OP_MOVE: {
|
||||
int a = GETARG_A(i);
|
||||
int b = GETARG_B(i); /* move from `b' to `a' */
|
||||
if (b < a)
|
||||
return getobjname(L, ci, b, name); /* get name for `b' */
|
||||
break;
|
||||
}
|
||||
case OP_GETTABLE: {
|
||||
int k = GETARG_C(i); /* key index */
|
||||
*name = kname(p, k);
|
||||
return "field";
|
||||
}
|
||||
case OP_GETUPVAL: {
|
||||
int u = GETARG_B(i); /* upvalue index */
|
||||
*name = p->upvalues ? getstr(p->upvalues[u]) : "?";
|
||||
return "upvalue";
|
||||
}
|
||||
case OP_SELF: {
|
||||
int k = GETARG_C(i); /* key index */
|
||||
*name = kname(p, k);
|
||||
return "method";
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return NULL; /* no useful name found */
|
||||
}
|
||||
|
||||
|
||||
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
|
||||
Instruction i;
|
||||
if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1))
|
||||
return NULL; /* calling function is not Lua (or is unknown) */
|
||||
ci--; /* calling function */
|
||||
i = ci_func(ci)->l.p->code[currentpc(L, ci)];
|
||||
if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||
|
||||
GET_OPCODE(i) == OP_TFORLOOP)
|
||||
return getobjname(L, ci, GETARG_A(i), name);
|
||||
else
|
||||
return NULL; /* no useful name can be found */
|
||||
}
|
||||
|
||||
|
||||
/* only ANSI way to check whether a pointer points to an array */
|
||||
static int isinstack (CallInfo *ci, const TValue *o) {
|
||||
StkId p;
|
||||
for (p = ci->base; p < ci->top; p++)
|
||||
if (o == p) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
|
||||
const char *name = NULL;
|
||||
const char *t = luaT_typenames[ttype(o)];
|
||||
const char *kind = (isinstack(L->ci, o)) ?
|
||||
getobjname(L, L->ci, cast_int(o - L->base), &name) :
|
||||
NULL;
|
||||
if (kind)
|
||||
luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)",
|
||||
op, kind, name, t);
|
||||
else
|
||||
luaG_runerror(L, "attempt to %s a %s value", op, t);
|
||||
}
|
||||
|
||||
|
||||
void luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
|
||||
if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;
|
||||
lua_assert(!ttisstring(p1) && !ttisnumber(p1));
|
||||
luaG_typeerror(L, p1, "concatenate");
|
||||
}
|
||||
|
||||
|
||||
void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {
|
||||
TValue temp;
|
||||
if (luaV_tonumber(p1, &temp) == NULL)
|
||||
p2 = p1; /* first operand is wrong */
|
||||
luaG_typeerror(L, p2, "perform arithmetic on");
|
||||
}
|
||||
|
||||
|
||||
int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
|
||||
const char *t1 = luaT_typenames[ttype(p1)];
|
||||
const char *t2 = luaT_typenames[ttype(p2)];
|
||||
if (t1[2] == t2[2])
|
||||
luaG_runerror(L, "attempt to compare two %s values", t1);
|
||||
else
|
||||
luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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(L, ci);
|
||||
luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE);
|
||||
luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void luaG_errormsg (lua_State *L) {
|
||||
if (L->errfunc != 0) { /* is there an error handling function? */
|
||||
StkId errfunc = restorestack(L, L->errfunc);
|
||||
if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);
|
||||
setobjs2s(L, L->top, L->top - 1); /* move argument */
|
||||
setobjs2s(L, L->top - 1, errfunc); /* push function */
|
||||
incr_top(L);
|
||||
luaD_call(L, L->top - 2, 1); /* call it */
|
||||
}
|
||||
luaD_throw(L, LUA_ERRRUN);
|
||||
}
|
||||
|
||||
|
||||
void luaG_runerror (lua_State *L, const char *fmt, ...) {
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
addinfo(L, luaO_pushvfstring(L, fmt, argp));
|
||||
va_end(argp);
|
||||
luaG_errormsg(L);
|
||||
}
|
||||
|
||||
Vendored
-33
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $
|
||||
** Auxiliary functions from Debug Interface module
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef ldebug_h
|
||||
#define ldebug_h
|
||||
|
||||
|
||||
#include "lstate.h"
|
||||
|
||||
|
||||
#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1)
|
||||
|
||||
#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0)
|
||||
|
||||
#define resethookcount(L) (L->hookcount = L->basehookcount)
|
||||
|
||||
|
||||
LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o,
|
||||
const char *opname);
|
||||
LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2);
|
||||
LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1,
|
||||
const TValue *p2);
|
||||
LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1,
|
||||
const TValue *p2);
|
||||
LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...);
|
||||
LUAI_FUNC void luaG_errormsg (lua_State *L);
|
||||
LUAI_FUNC int luaG_checkcode (const Proto *pt);
|
||||
LUAI_FUNC int luaG_checkopenop (Instruction i);
|
||||
|
||||
#endif
|
||||
Vendored
-518
@@ -1,518 +0,0 @@
|
||||
/*
|
||||
** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $
|
||||
** Stack and Call structure of Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ldo_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "ldebug.h"
|
||||
#include "ldo.h"
|
||||
#include "lfunc.h"
|
||||
#include "lgc.h"
|
||||
#include "lmem.h"
|
||||
#include "lobject.h"
|
||||
#include "lopcodes.h"
|
||||
#include "lparser.h"
|
||||
#include "lstate.h"
|
||||
#include "lstring.h"
|
||||
#include "ltable.h"
|
||||
#include "ltm.h"
|
||||
#include "lundump.h"
|
||||
#include "lvm.h"
|
||||
#include "lzio.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Error-recovery functions
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
/* chain list of long jump buffers */
|
||||
struct lua_longjmp {
|
||||
struct lua_longjmp *previous;
|
||||
luai_jmpbuf b;
|
||||
volatile int status; /* error code */
|
||||
};
|
||||
|
||||
|
||||
void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
|
||||
switch (errcode) {
|
||||
case LUA_ERRMEM: {
|
||||
setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG));
|
||||
break;
|
||||
}
|
||||
case LUA_ERRERR: {
|
||||
setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
|
||||
break;
|
||||
}
|
||||
case LUA_ERRSYNTAX:
|
||||
case LUA_ERRRUN: {
|
||||
setobjs2s(L, oldtop, L->top - 1); /* error message on current top */
|
||||
break;
|
||||
}
|
||||
}
|
||||
L->top = oldtop + 1;
|
||||
}
|
||||
|
||||
|
||||
static void restore_stack_limit (lua_State *L) {
|
||||
lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
|
||||
if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */
|
||||
int inuse = cast_int(L->ci - L->base_ci);
|
||||
if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */
|
||||
luaD_reallocCI(L, LUAI_MAXCALLS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void resetstack (lua_State *L, int status) {
|
||||
L->ci = L->base_ci;
|
||||
L->base = L->ci->base;
|
||||
luaF_close(L, L->base); /* close eventual pending closures */
|
||||
luaD_seterrorobj(L, status, L->base);
|
||||
L->nCcalls = L->baseCcalls;
|
||||
L->allowhook = 1;
|
||||
restore_stack_limit(L);
|
||||
L->errfunc = 0;
|
||||
L->errorJmp = NULL;
|
||||
}
|
||||
|
||||
|
||||
void luaD_throw (lua_State *L, int errcode) {
|
||||
if (L->errorJmp) {
|
||||
L->errorJmp->status = errcode;
|
||||
LUAI_THROW(L, L->errorJmp);
|
||||
}
|
||||
else {
|
||||
L->status = cast_byte(errcode);
|
||||
if (G(L)->panic) {
|
||||
resetstack(L, errcode);
|
||||
lua_unlock(L);
|
||||
G(L)->panic(L);
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
|
||||
struct lua_longjmp lj;
|
||||
lj.status = 0;
|
||||
lj.previous = L->errorJmp; /* chain new error handler */
|
||||
L->errorJmp = &lj;
|
||||
LUAI_TRY(L, &lj,
|
||||
(*f)(L, ud);
|
||||
);
|
||||
L->errorJmp = lj.previous; /* restore old error handler */
|
||||
return lj.status;
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
static void correctstack (lua_State *L, TValue *oldstack) {
|
||||
CallInfo *ci;
|
||||
GCObject *up;
|
||||
L->top = (L->top - oldstack) + L->stack;
|
||||
for (up = L->openupval; up != NULL; up = up->gch.next)
|
||||
gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
|
||||
for (ci = L->base_ci; ci <= L->ci; ci++) {
|
||||
ci->top = (ci->top - oldstack) + L->stack;
|
||||
ci->base = (ci->base - oldstack) + L->stack;
|
||||
ci->func = (ci->func - oldstack) + L->stack;
|
||||
}
|
||||
L->base = (L->base - oldstack) + L->stack;
|
||||
}
|
||||
|
||||
|
||||
void luaD_reallocstack (lua_State *L, int newsize) {
|
||||
TValue *oldstack = L->stack;
|
||||
int realsize = newsize + 1 + EXTRA_STACK;
|
||||
lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);
|
||||
luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue);
|
||||
L->stacksize = realsize;
|
||||
L->stack_last = L->stack+newsize;
|
||||
correctstack(L, oldstack);
|
||||
}
|
||||
|
||||
|
||||
void luaD_reallocCI (lua_State *L, int newsize) {
|
||||
CallInfo *oldci = L->base_ci;
|
||||
luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
|
||||
L->size_ci = newsize;
|
||||
L->ci = (L->ci - oldci) + L->base_ci;
|
||||
L->end_ci = L->base_ci + L->size_ci - 1;
|
||||
}
|
||||
|
||||
|
||||
void luaD_growstack (lua_State *L, int n) {
|
||||
if (n <= L->stacksize) /* double size is enough? */
|
||||
luaD_reallocstack(L, 2*L->stacksize);
|
||||
else
|
||||
luaD_reallocstack(L, L->stacksize + n);
|
||||
}
|
||||
|
||||
|
||||
static CallInfo *growCI (lua_State *L) {
|
||||
if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */
|
||||
luaD_throw(L, LUA_ERRERR);
|
||||
else {
|
||||
luaD_reallocCI(L, 2*L->size_ci);
|
||||
if (L->size_ci > LUAI_MAXCALLS)
|
||||
luaG_runerror(L, "stack overflow");
|
||||
}
|
||||
return ++L->ci;
|
||||
}
|
||||
|
||||
|
||||
void luaD_callhook (lua_State *L, int event, int line) {
|
||||
lua_Hook hook = L->hook;
|
||||
if (hook && L->allowhook) {
|
||||
ptrdiff_t top = savestack(L, L->top);
|
||||
ptrdiff_t ci_top = savestack(L, L->ci->top);
|
||||
lua_Debug ar;
|
||||
ar.event = event;
|
||||
ar.currentline = line;
|
||||
if (event == LUA_HOOKTAILRET)
|
||||
ar.i_ci = 0; /* tail call; no debug information about it */
|
||||
else
|
||||
ar.i_ci = cast_int(L->ci - L->base_ci);
|
||||
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
|
||||
L->ci->top = L->top + LUA_MINSTACK;
|
||||
lua_assert(L->ci->top <= L->stack_last);
|
||||
L->allowhook = 0; /* cannot call hooks inside a hook */
|
||||
lua_unlock(L);
|
||||
(*hook)(L, &ar);
|
||||
lua_lock(L);
|
||||
lua_assert(!L->allowhook);
|
||||
L->allowhook = 1;
|
||||
L->ci->top = restorestack(L, ci_top);
|
||||
L->top = restorestack(L, top);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
|
||||
int i;
|
||||
int nfixargs = p->numparams;
|
||||
Table *htab = NULL;
|
||||
StkId base, fixed;
|
||||
for (; actual < nfixargs; ++actual)
|
||||
setnilvalue(L->top++);
|
||||
#if defined(LUA_COMPAT_VARARG)
|
||||
if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */
|
||||
int nvar = actual - nfixargs; /* number of extra arguments */
|
||||
lua_assert(p->is_vararg & VARARG_HASARG);
|
||||
luaC_checkGC(L);
|
||||
htab = luaH_new(L, nvar, 1); /* create `arg' table */
|
||||
for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
|
||||
setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
|
||||
/* store counter in field `n' */
|
||||
setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
|
||||
}
|
||||
#endif
|
||||
/* move fixed parameters to final position */
|
||||
fixed = L->top - actual; /* first fixed argument */
|
||||
base = L->top; /* final position of first argument */
|
||||
for (i=0; i<nfixargs; i++) {
|
||||
setobjs2s(L, L->top++, fixed+i);
|
||||
setnilvalue(fixed+i);
|
||||
}
|
||||
/* add `arg' parameter */
|
||||
if (htab) {
|
||||
sethvalue(L, L->top++, htab);
|
||||
lua_assert(iswhite(obj2gco(htab)));
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
|
||||
static StkId tryfuncTM (lua_State *L, StkId func) {
|
||||
const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);
|
||||
StkId p;
|
||||
ptrdiff_t funcr = savestack(L, func);
|
||||
if (!ttisfunction(tm))
|
||||
luaG_typeerror(L, func, "call");
|
||||
/* Open a hole inside the stack at `func' */
|
||||
for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);
|
||||
incr_top(L);
|
||||
func = restorestack(L, funcr); /* previous call may change stack */
|
||||
setobj2s(L, func, tm); /* tag method is the new function to be called */
|
||||
return func;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define inc_ci(L) \
|
||||
((L->ci == L->end_ci) ? growCI(L) : \
|
||||
(condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))
|
||||
|
||||
|
||||
int luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||
LClosure *cl;
|
||||
ptrdiff_t funcr;
|
||||
if (!ttisfunction(func)) /* `func' is not a function? */
|
||||
func = tryfuncTM(L, func); /* check the `function' tag method */
|
||||
funcr = savestack(L, func);
|
||||
cl = &clvalue(func)->l;
|
||||
L->ci->savedpc = L->savedpc;
|
||||
if (!cl->isC) { /* Lua function? prepare its call */
|
||||
CallInfo *ci;
|
||||
StkId st, base;
|
||||
Proto *p = cl->p;
|
||||
luaD_checkstack(L, p->maxstacksize);
|
||||
func = restorestack(L, funcr);
|
||||
if (!p->is_vararg) { /* no varargs? */
|
||||
base = func + 1;
|
||||
if (L->top > base + p->numparams)
|
||||
L->top = base + p->numparams;
|
||||
}
|
||||
else { /* vararg function */
|
||||
int nargs = cast_int(L->top - func) - 1;
|
||||
base = adjust_varargs(L, p, nargs);
|
||||
func = restorestack(L, funcr); /* previous call may change the stack */
|
||||
}
|
||||
ci = inc_ci(L); /* now `enter' new function */
|
||||
ci->func = func;
|
||||
L->base = ci->base = base;
|
||||
ci->top = L->base + p->maxstacksize;
|
||||
lua_assert(ci->top <= L->stack_last);
|
||||
L->savedpc = p->code; /* starting point */
|
||||
ci->tailcalls = 0;
|
||||
ci->nresults = nresults;
|
||||
for (st = L->top; st < ci->top; st++)
|
||||
setnilvalue(st);
|
||||
L->top = ci->top;
|
||||
if (L->hookmask & LUA_MASKCALL) {
|
||||
L->savedpc++; /* hooks assume 'pc' is already incremented */
|
||||
luaD_callhook(L, LUA_HOOKCALL, -1);
|
||||
L->savedpc--; /* correct 'pc' */
|
||||
}
|
||||
return PCRLUA;
|
||||
}
|
||||
else { /* if is a C function, call it */
|
||||
CallInfo *ci;
|
||||
int n;
|
||||
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
|
||||
ci = inc_ci(L); /* now `enter' new function */
|
||||
ci->func = restorestack(L, funcr);
|
||||
L->base = ci->base = ci->func + 1;
|
||||
ci->top = L->top + LUA_MINSTACK;
|
||||
lua_assert(ci->top <= L->stack_last);
|
||||
ci->nresults = nresults;
|
||||
if (L->hookmask & LUA_MASKCALL)
|
||||
luaD_callhook(L, LUA_HOOKCALL, -1);
|
||||
lua_unlock(L);
|
||||
n = (*curr_func(L)->c.f)(L); /* do the actual call */
|
||||
lua_lock(L);
|
||||
if (n < 0) /* yielding? */
|
||||
return PCRYIELD;
|
||||
else {
|
||||
luaD_poscall(L, L->top - n);
|
||||
return PCRC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static StkId callrethooks (lua_State *L, StkId firstResult) {
|
||||
ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */
|
||||
luaD_callhook(L, LUA_HOOKRET, -1);
|
||||
if (f_isLua(L->ci)) { /* Lua function? */
|
||||
while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */
|
||||
luaD_callhook(L, LUA_HOOKTAILRET, -1);
|
||||
}
|
||||
return restorestack(L, fr);
|
||||
}
|
||||
|
||||
|
||||
int luaD_poscall (lua_State *L, StkId firstResult) {
|
||||
StkId res;
|
||||
int wanted, i;
|
||||
CallInfo *ci;
|
||||
if (L->hookmask & LUA_MASKRET)
|
||||
firstResult = callrethooks(L, firstResult);
|
||||
ci = L->ci--;
|
||||
res = ci->func; /* res == final position of 1st result */
|
||||
wanted = ci->nresults;
|
||||
L->base = (ci - 1)->base; /* restore base */
|
||||
L->savedpc = (ci - 1)->savedpc; /* restore savedpc */
|
||||
/* move results to correct place */
|
||||
for (i = wanted; i != 0 && firstResult < L->top; i--)
|
||||
setobjs2s(L, res++, firstResult++);
|
||||
while (i-- > 0)
|
||||
setnilvalue(res++);
|
||||
L->top = res;
|
||||
return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Call a function (C or Lua). The function to be called is at *func.
|
||||
** The arguments are on the stack, right after the function.
|
||||
** When returns, all the results are on the stack, starting at the original
|
||||
** function position.
|
||||
*/
|
||||
void luaD_call (lua_State *L, StkId func, int nResults) {
|
||||
if (++L->nCcalls >= LUAI_MAXCCALLS) {
|
||||
if (L->nCcalls == LUAI_MAXCCALLS)
|
||||
luaG_runerror(L, "C stack overflow");
|
||||
else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
|
||||
luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
|
||||
}
|
||||
if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */
|
||||
luaV_execute(L, 1); /* call it */
|
||||
L->nCcalls--;
|
||||
luaC_checkGC(L);
|
||||
}
|
||||
|
||||
|
||||
static void resume (lua_State *L, void *ud) {
|
||||
StkId firstArg = cast(StkId, ud);
|
||||
CallInfo *ci = L->ci;
|
||||
if (L->status == 0) { /* start coroutine? */
|
||||
lua_assert(ci == L->base_ci && firstArg > L->base);
|
||||
if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA)
|
||||
return;
|
||||
}
|
||||
else { /* resuming from previous yield */
|
||||
lua_assert(L->status == LUA_YIELD);
|
||||
L->status = 0;
|
||||
if (!f_isLua(ci)) { /* `common' yield? */
|
||||
/* finish interrupted execution of `OP_CALL' */
|
||||
lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||
|
||||
GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL);
|
||||
if (luaD_poscall(L, firstArg)) /* complete it... */
|
||||
L->top = L->ci->top; /* and correct top if not multiple results */
|
||||
}
|
||||
else /* yielded inside a hook: just continue its execution */
|
||||
L->base = L->ci->base;
|
||||
}
|
||||
luaV_execute(L, cast_int(L->ci - L->base_ci));
|
||||
}
|
||||
|
||||
|
||||
static int resume_error (lua_State *L, const char *msg) {
|
||||
L->top = L->ci->base;
|
||||
setsvalue2s(L, L->top, luaS_new(L, msg));
|
||||
incr_top(L);
|
||||
lua_unlock(L);
|
||||
return LUA_ERRRUN;
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_resume (lua_State *L, int nargs) {
|
||||
int status;
|
||||
lua_lock(L);
|
||||
if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci))
|
||||
return resume_error(L, "cannot resume non-suspended coroutine");
|
||||
if (L->nCcalls >= LUAI_MAXCCALLS)
|
||||
return resume_error(L, "C stack overflow");
|
||||
luai_userstateresume(L, nargs);
|
||||
lua_assert(L->errfunc == 0);
|
||||
L->baseCcalls = ++L->nCcalls;
|
||||
status = luaD_rawrunprotected(L, resume, L->top - nargs);
|
||||
if (status != 0) { /* error? */
|
||||
L->status = cast_byte(status); /* mark thread as `dead' */
|
||||
luaD_seterrorobj(L, status, L->top);
|
||||
L->ci->top = L->top;
|
||||
}
|
||||
else {
|
||||
lua_assert(L->nCcalls == L->baseCcalls);
|
||||
status = L->status;
|
||||
}
|
||||
--L->nCcalls;
|
||||
lua_unlock(L);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_yield (lua_State *L, int nresults) {
|
||||
luai_userstateyield(L, nresults);
|
||||
lua_lock(L);
|
||||
if (L->nCcalls > L->baseCcalls)
|
||||
luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
|
||||
L->base = L->top - nresults; /* protect stack slots below */
|
||||
L->status = LUA_YIELD;
|
||||
lua_unlock(L);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int luaD_pcall (lua_State *L, Pfunc func, void *u,
|
||||
ptrdiff_t old_top, ptrdiff_t ef) {
|
||||
int status;
|
||||
unsigned short oldnCcalls = L->nCcalls;
|
||||
ptrdiff_t old_ci = saveci(L, L->ci);
|
||||
lu_byte old_allowhooks = L->allowhook;
|
||||
ptrdiff_t old_errfunc = L->errfunc;
|
||||
L->errfunc = ef;
|
||||
status = luaD_rawrunprotected(L, func, u);
|
||||
if (status != 0) { /* an error occurred? */
|
||||
StkId oldtop = restorestack(L, old_top);
|
||||
luaF_close(L, oldtop); /* close eventual pending closures */
|
||||
luaD_seterrorobj(L, status, oldtop);
|
||||
L->nCcalls = oldnCcalls;
|
||||
L->ci = restoreci(L, old_ci);
|
||||
L->base = L->ci->base;
|
||||
L->savedpc = L->ci->savedpc;
|
||||
L->allowhook = old_allowhooks;
|
||||
restore_stack_limit(L);
|
||||
}
|
||||
L->errfunc = old_errfunc;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Execute a protected parser.
|
||||
*/
|
||||
struct SParser { /* data to `f_parser' */
|
||||
ZIO *z;
|
||||
Mbuffer buff; /* buffer to be used by the scanner */
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static void f_parser (lua_State *L, void *ud) {
|
||||
int i;
|
||||
Proto *tf;
|
||||
Closure *cl;
|
||||
struct SParser *p = cast(struct SParser *, ud);
|
||||
int c = luaZ_lookahead(p->z);
|
||||
luaC_checkGC(L);
|
||||
tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
|
||||
&p->buff, p->name);
|
||||
cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
|
||||
cl->l.p = tf;
|
||||
for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */
|
||||
cl->l.upvals[i] = luaF_newupval(L);
|
||||
setclvalue(L, L->top, cl);
|
||||
incr_top(L);
|
||||
}
|
||||
|
||||
|
||||
int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {
|
||||
struct SParser p;
|
||||
int status;
|
||||
p.z = z; p.name = name;
|
||||
luaZ_initbuffer(L, &p.buff);
|
||||
status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
|
||||
luaZ_freebuffer(L, &p.buff);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
Vendored
-57
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $
|
||||
** Stack and Call structure of Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef ldo_h
|
||||
#define ldo_h
|
||||
|
||||
|
||||
#include "lobject.h"
|
||||
#include "lstate.h"
|
||||
#include "lzio.h"
|
||||
|
||||
|
||||
#define luaD_checkstack(L,n) \
|
||||
if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \
|
||||
luaD_growstack(L, n); \
|
||||
else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1));
|
||||
|
||||
|
||||
#define incr_top(L) {luaD_checkstack(L,1); L->top++;}
|
||||
|
||||
#define savestack(L,p) ((char *)(p) - (char *)L->stack)
|
||||
#define restorestack(L,n) ((TValue *)((char *)L->stack + (n)))
|
||||
|
||||
#define saveci(L,p) ((char *)(p) - (char *)L->base_ci)
|
||||
#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n)))
|
||||
|
||||
|
||||
/* results from luaD_precall */
|
||||
#define PCRLUA 0 /* initiated a call to a Lua function */
|
||||
#define PCRC 1 /* did a call to a C function */
|
||||
#define PCRYIELD 2 /* C funtion yielded */
|
||||
|
||||
|
||||
/* type of protected functions, to be ran by `runprotected' */
|
||||
typedef void (*Pfunc) (lua_State *L, void *ud);
|
||||
|
||||
LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name);
|
||||
LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line);
|
||||
LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);
|
||||
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
|
||||
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 void luaD_reallocCI (lua_State *L, int newsize);
|
||||
LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
|
||||
LUAI_FUNC void luaD_growstack (lua_State *L, int n);
|
||||
|
||||
LUAI_FUNC void luaD_throw (lua_State *L, int errcode);
|
||||
LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
|
||||
|
||||
LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
-164
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
|
||||
** save precompiled Lua chunks
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define ldump_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lobject.h"
|
||||
#include "lstate.h"
|
||||
#include "lundump.h"
|
||||
|
||||
typedef struct {
|
||||
lua_State* L;
|
||||
lua_Writer writer;
|
||||
void* data;
|
||||
int strip;
|
||||
int status;
|
||||
} DumpState;
|
||||
|
||||
#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D)
|
||||
#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D)
|
||||
|
||||
static void DumpBlock(const void* b, size_t size, DumpState* D)
|
||||
{
|
||||
if (D->status==0)
|
||||
{
|
||||
lua_unlock(D->L);
|
||||
D->status=(*D->writer)(D->L,b,size,D->data);
|
||||
lua_lock(D->L);
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpChar(int y, DumpState* D)
|
||||
{
|
||||
char x=(char)y;
|
||||
DumpVar(x,D);
|
||||
}
|
||||
|
||||
static void DumpInt(int x, DumpState* D)
|
||||
{
|
||||
DumpVar(x,D);
|
||||
}
|
||||
|
||||
static void DumpNumber(lua_Number x, DumpState* D)
|
||||
{
|
||||
DumpVar(x,D);
|
||||
}
|
||||
|
||||
static void DumpVector(const void* b, int n, size_t size, DumpState* D)
|
||||
{
|
||||
DumpInt(n,D);
|
||||
DumpMem(b,n,size,D);
|
||||
}
|
||||
|
||||
static void DumpString(const TString* s, DumpState* D)
|
||||
{
|
||||
if (s==NULL || getstr(s)==NULL)
|
||||
{
|
||||
size_t size=0;
|
||||
DumpVar(size,D);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t size=s->tsv.len+1; /* include trailing '\0' */
|
||||
DumpVar(size,D);
|
||||
DumpBlock(getstr(s),size,D);
|
||||
}
|
||||
}
|
||||
|
||||
#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D)
|
||||
|
||||
static void DumpFunction(const Proto* f, const TString* p, DumpState* D);
|
||||
|
||||
static void DumpConstants(const Proto* f, DumpState* D)
|
||||
{
|
||||
int i,n=f->sizek;
|
||||
DumpInt(n,D);
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
const TValue* o=&f->k[i];
|
||||
DumpChar(ttype(o),D);
|
||||
switch (ttype(o))
|
||||
{
|
||||
case LUA_TNIL:
|
||||
break;
|
||||
case LUA_TBOOLEAN:
|
||||
DumpChar(bvalue(o),D);
|
||||
break;
|
||||
case LUA_TNUMBER:
|
||||
DumpNumber(nvalue(o),D);
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
DumpString(rawtsvalue(o),D);
|
||||
break;
|
||||
default:
|
||||
lua_assert(0); /* cannot happen */
|
||||
break;
|
||||
}
|
||||
}
|
||||
n=f->sizep;
|
||||
DumpInt(n,D);
|
||||
for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D);
|
||||
}
|
||||
|
||||
static void DumpDebug(const Proto* f, DumpState* D)
|
||||
{
|
||||
int i,n;
|
||||
n= (D->strip) ? 0 : f->sizelineinfo;
|
||||
DumpVector(f->lineinfo,n,sizeof(int),D);
|
||||
n= (D->strip) ? 0 : f->sizelocvars;
|
||||
DumpInt(n,D);
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
DumpString(f->locvars[i].varname,D);
|
||||
DumpInt(f->locvars[i].startpc,D);
|
||||
DumpInt(f->locvars[i].endpc,D);
|
||||
}
|
||||
n= (D->strip) ? 0 : f->sizeupvalues;
|
||||
DumpInt(n,D);
|
||||
for (i=0; i<n; i++) DumpString(f->upvalues[i],D);
|
||||
}
|
||||
|
||||
static void DumpFunction(const Proto* f, const TString* p, DumpState* D)
|
||||
{
|
||||
DumpString((f->source==p || D->strip) ? NULL : f->source,D);
|
||||
DumpInt(f->linedefined,D);
|
||||
DumpInt(f->lastlinedefined,D);
|
||||
DumpChar(f->nups,D);
|
||||
DumpChar(f->numparams,D);
|
||||
DumpChar(f->is_vararg,D);
|
||||
DumpChar(f->maxstacksize,D);
|
||||
DumpCode(f,D);
|
||||
DumpConstants(f,D);
|
||||
DumpDebug(f,D);
|
||||
}
|
||||
|
||||
static void DumpHeader(DumpState* D)
|
||||
{
|
||||
char h[LUAC_HEADERSIZE];
|
||||
luaU_header(h);
|
||||
DumpBlock(h,LUAC_HEADERSIZE,D);
|
||||
}
|
||||
|
||||
/*
|
||||
** dump Lua function as precompiled chunk
|
||||
*/
|
||||
int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
|
||||
{
|
||||
DumpState D;
|
||||
D.L=L;
|
||||
D.writer=w;
|
||||
D.data=data;
|
||||
D.strip=strip;
|
||||
D.status=0;
|
||||
DumpHeader(&D);
|
||||
DumpFunction(f,NULL,&D);
|
||||
return D.status;
|
||||
}
|
||||
Vendored
-174
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $
|
||||
** Auxiliary functions to manipulate prototypes and closures
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define lfunc_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lfunc.h"
|
||||
#include "lgc.h"
|
||||
#include "lmem.h"
|
||||
#include "lobject.h"
|
||||
#include "lstate.h"
|
||||
|
||||
|
||||
|
||||
Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) {
|
||||
Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
|
||||
luaC_link(L, obj2gco(c), LUA_TFUNCTION);
|
||||
c->c.isC = 1;
|
||||
c->c.env = e;
|
||||
c->c.nupvalues = cast_byte(nelems);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) {
|
||||
Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
|
||||
luaC_link(L, obj2gco(c), LUA_TFUNCTION);
|
||||
c->l.isC = 0;
|
||||
c->l.env = e;
|
||||
c->l.nupvalues = cast_byte(nelems);
|
||||
while (nelems--) c->l.upvals[nelems] = NULL;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
UpVal *luaF_newupval (lua_State *L) {
|
||||
UpVal *uv = luaM_new(L, UpVal);
|
||||
luaC_link(L, obj2gco(uv), LUA_TUPVAL);
|
||||
uv->v = &uv->u.value;
|
||||
setnilvalue(uv->v);
|
||||
return uv;
|
||||
}
|
||||
|
||||
|
||||
UpVal *luaF_findupval (lua_State *L, StkId level) {
|
||||
global_State *g = G(L);
|
||||
GCObject **pp = &L->openupval;
|
||||
UpVal *p;
|
||||
UpVal *uv;
|
||||
while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) {
|
||||
lua_assert(p->v != &p->u.value);
|
||||
if (p->v == level) { /* found a corresponding upvalue? */
|
||||
if (isdead(g, obj2gco(p))) /* is it dead? */
|
||||
changewhite(obj2gco(p)); /* ressurect it */
|
||||
return p;
|
||||
}
|
||||
pp = &p->next;
|
||||
}
|
||||
uv = luaM_new(L, UpVal); /* not found: create a new one */
|
||||
uv->tt = LUA_TUPVAL;
|
||||
uv->marked = luaC_white(g);
|
||||
uv->v = level; /* current value lives in the stack */
|
||||
uv->next = *pp; /* chain it in the proper position */
|
||||
*pp = obj2gco(uv);
|
||||
uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */
|
||||
uv->u.l.next = g->uvhead.u.l.next;
|
||||
uv->u.l.next->u.l.prev = uv;
|
||||
g->uvhead.u.l.next = uv;
|
||||
lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
|
||||
return uv;
|
||||
}
|
||||
|
||||
|
||||
static void unlinkupval (UpVal *uv) {
|
||||
lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
|
||||
uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */
|
||||
uv->u.l.prev->u.l.next = uv->u.l.next;
|
||||
}
|
||||
|
||||
|
||||
void luaF_freeupval (lua_State *L, UpVal *uv) {
|
||||
if (uv->v != &uv->u.value) /* is it open? */
|
||||
unlinkupval(uv); /* remove from open list */
|
||||
luaM_free(L, uv); /* free upvalue */
|
||||
}
|
||||
|
||||
|
||||
void luaF_close (lua_State *L, StkId level) {
|
||||
UpVal *uv;
|
||||
global_State *g = G(L);
|
||||
while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) {
|
||||
GCObject *o = obj2gco(uv);
|
||||
lua_assert(!isblack(o) && uv->v != &uv->u.value);
|
||||
L->openupval = uv->next; /* remove from `open' list */
|
||||
if (isdead(g, o))
|
||||
luaF_freeupval(L, uv); /* free upvalue */
|
||||
else {
|
||||
unlinkupval(uv);
|
||||
setobj(L, &uv->u.value, uv->v);
|
||||
uv->v = &uv->u.value; /* now current value lives here */
|
||||
luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Proto *luaF_newproto (lua_State *L) {
|
||||
Proto *f = luaM_new(L, Proto);
|
||||
luaC_link(L, obj2gco(f), LUA_TPROTO);
|
||||
f->k = NULL;
|
||||
f->sizek = 0;
|
||||
f->p = NULL;
|
||||
f->sizep = 0;
|
||||
f->code = NULL;
|
||||
f->sizecode = 0;
|
||||
f->sizelineinfo = 0;
|
||||
f->sizeupvalues = 0;
|
||||
f->nups = 0;
|
||||
f->upvalues = NULL;
|
||||
f->numparams = 0;
|
||||
f->is_vararg = 0;
|
||||
f->maxstacksize = 0;
|
||||
f->lineinfo = NULL;
|
||||
f->sizelocvars = 0;
|
||||
f->locvars = NULL;
|
||||
f->linedefined = 0;
|
||||
f->lastlinedefined = 0;
|
||||
f->source = NULL;
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
void luaF_freeproto (lua_State *L, Proto *f) {
|
||||
luaM_freearray(L, f->code, f->sizecode, Instruction);
|
||||
luaM_freearray(L, f->p, f->sizep, Proto *);
|
||||
luaM_freearray(L, f->k, f->sizek, TValue);
|
||||
luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
|
||||
luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
|
||||
luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
|
||||
luaM_free(L, f);
|
||||
}
|
||||
|
||||
|
||||
void luaF_freeclosure (lua_State *L, Closure *c) {
|
||||
int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) :
|
||||
sizeLclosure(c->l.nupvalues);
|
||||
luaM_freemem(L, c, size);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Look for n-th local variable at line `line' in function `func'.
|
||||
** Returns NULL if not found.
|
||||
*/
|
||||
const char *luaF_getlocalname (const Proto *f, int local_number, int pc) {
|
||||
int i;
|
||||
for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) {
|
||||
if (pc < f->locvars[i].endpc) { /* is variable active? */
|
||||
local_number--;
|
||||
if (local_number == 0)
|
||||
return getstr(f->locvars[i].varname);
|
||||
}
|
||||
}
|
||||
return NULL; /* not found */
|
||||
}
|
||||
|
||||
Vendored
-34
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $
|
||||
** Auxiliary functions to manipulate prototypes and closures
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef lfunc_h
|
||||
#define lfunc_h
|
||||
|
||||
|
||||
#include "lobject.h"
|
||||
|
||||
|
||||
#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \
|
||||
cast(int, sizeof(TValue)*((n)-1)))
|
||||
|
||||
#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
|
||||
cast(int, sizeof(TValue *)*((n)-1)))
|
||||
|
||||
|
||||
LUAI_FUNC Proto *luaF_newproto (lua_State *L);
|
||||
LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);
|
||||
LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);
|
||||
LUAI_FUNC UpVal *luaF_newupval (lua_State *L);
|
||||
LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
|
||||
LUAI_FUNC void luaF_close (lua_State *L, StkId level);
|
||||
LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
|
||||
LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c);
|
||||
LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv);
|
||||
LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,
|
||||
int pc);
|
||||
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user