Compare commits
379 Commits
early-acce
...
amigaos
Author | SHA1 | Date |
---|---|---|
George Sokianos | c076098ad9 | |
George Sokianos | 5dd814e452 | |
George Sokianos | 43c8bd610f | |
George Sokianos | 6a78b47ae6 | |
George Sokianos | 2b1fd35298 | |
lprobert | fc6bb50460 | |
lprobert | 2aba6c4338 | |
Linus Probert | 39bc060a77 | |
Linus Probert | abef4ed9a6 | |
Linus Probert | 26c5448a30 | |
Linus Probert | 1a559741e2 | |
Linus Probert | 38207e03d1 | |
Linus Probert | e636ec1e53 | |
417e7d3cc8 | ||
Linus Probert | 4edeb17ddc | |
Linus Probert | de770ccc9f | |
Linus Probert | 8a347790c1 | |
Linus Probert | 5a9335576a | |
Linus Probert | b385f6e73a | |
Linus Probert | 4106a856fc | |
Linus Probert | 8221304df8 | |
Linus Probert | 4ceb82f171 | |
Linus Probert | 9e5e1d0a1e | |
Linus Probert | 6d323ca500 | |
Linus Probert | 9aefed0d00 | |
Linus Probert | f102e49daf | |
Linus Probert | 392edd843c | |
Boris Vanhoof | 6584981d10 | |
Boris Vanhoof | d2cf79710a | |
Boris Vanhoof | 78e9413188 | |
Linus Probert | af957eb662 | |
Linus Probert | 1d988d7f2f | |
Linus Probert | 68f4e152d3 | |
Linus Probert | 7f232beb32 | |
Linus Probert | 12aff9afad | |
Linus Probert | 2dc25c9b53 | |
Linus Probert | 5e67ca7ef7 | |
Linus Probert | cac3fea106 | |
Linus Probert | 9ed80acbee | |
Linus Probert | 05cbce0abc | |
Linus Probert | 6c135c6b9c | |
Linus Probert | fb031e2af3 | |
Linus Probert | b861e6e452 | |
Linus Probert | 046551ad6d | |
Linus Probert | 8fb1bbcc1e | |
Linus Probert | 35164a9876 | |
Linus Probert | dd3e84d70d | |
Linus Probert | 8f21e8bfb2 | |
Linus Probert | 2b743160aa | |
Linus Probert | 7ddaab816e | |
Linus Probert | 43ca8f4560 | |
Linus Probert | ef5cd4e244 | |
Linus Probert | b00e607dec | |
Linus Probert | 67e29d609d | |
Linus Probert | 81e7df1920 | |
Linus Probert | 18effa2416 | |
Linus Probert | c043ad09cf | |
Linus Probert | 223a3b00c1 | |
Linus Probert | 2ca78e2ec7 | |
Linus Probert | 0476d4d1bd | |
Linus Probert | 826cbe11ff | |
Linus Probert | fcc6527a93 | |
Linus Probert | b409b76eca | |
Andriy Svyryd | b0753901ec | |
Andriy Svyryd | 86e6f66b58 | |
Linus Probert | c0a4a4eb93 | |
Linus Probert | c917981bad | |
Linus Probert | c2b8fd40eb | |
Linus Probert | 7a59d15be0 | |
Linus Probert | c9fde8dde1 | |
Linus Probert | c4811ed073 | |
Linus Probert | eceb241162 | |
Linus Probert | cea891f87d | |
Linus Probert | 8e282304ad | |
Linus Probert | 53703f1761 | |
Linus Probert | ce182ad20f | |
Linus Probert | ebfe2715e0 | |
Linus Probert | 2ae6ada297 | |
Linus Probert | 18987e2c2a | |
Linus Probert | 59a1e81c6e | |
Linus Probert | 1065216b67 | |
Linus Probert | 68533f05b3 | |
Linus Probert | 38dc3deb2c | |
Linus Probert | beda4f6c7e | |
Linus Probert | e50d40fb1c | |
Linus Probert | 0983bd1bd2 | |
Linus Probert | 184b42ff5a | |
Linus Probert | e42e0243af | |
Linus Probert | 756afbae9d | |
Linus Probert | 40a20e936c | |
Linus Probert | af930f6b23 | |
Linus Probert | c4fd16d925 | |
Linus Probert | f840b28839 | |
Linus Probert | 7fbeaa3907 | |
Linus Probert | 3e43c30bcb | |
Linus Probert | fd3a625249 | |
Linus Probert | d749861477 | |
Linus Probert | 7ab5ece83b | |
Linus Probert | 8c9622d6bd | |
Linus Probert | af0c61684d | |
Linus Probert | 46fbdc1b3c | |
Linus Probert | b40c54a88d | |
Linus Probert | 8f20f36db7 | |
Linus Probert | 3ba33d8852 | |
Linus Probert | 447c1a773c | |
Linus Probert | 7e1dffb45e | |
Linus Probert | 6009aa17f1 | |
Linus Probert | 9b4a7b6cfc | |
Linus Probert | 63812fbe05 | |
Linus Probert | c6a022e2db | |
Linus Probert | 06ca6c3e1e | |
Linus Probert | bab5fd7980 | |
Linus Probert | 68f44090ed | |
Linus Probert | 959fae1730 | |
Linus Probert | ca41520c06 | |
Linus Probert | 88f4703d00 | |
Linus Probert | 486c1bb641 | |
Linus Probert | 206f95f3b6 | |
Linus Probert | 1c4e600dd4 | |
Linus Probert | 57a16888b8 | |
Linus Probert | 13ca11c70e | |
Linus Probert | 33efba87b5 | |
Linus Probert | 5d61a91139 | |
Linus Probert | 6542e4f1d0 | |
Linus Probert | 7b47c6a6bf | |
Linus Probert | 16d9035941 | |
Linus Probert | 4054c37caa | |
Linus Probert | ad227f1bed | |
Linus Probert | 37ba189e54 | |
Linus Probert | 645a02c99e | |
Linus Probert | 35b5d7a8c1 | |
Linus Probert | c3464eb37d | |
Linus Probert | fe18240060 | |
Linus Probert | e4555237ed | |
Linus Probert | 791dd7ecfd | |
Linus Probert | b08ef10e82 | |
Linus Probert | fffcac12c0 | |
Linus Probert | 1b440c248d | |
Linus Probert | a03aec7c46 | |
Linus Probert | 0de018f3be | |
Linus Probert | 3eeb4d05a9 | |
Linus Probert | 5f369da4e1 | |
Linus Probert | c98e6e6d05 | |
Linus Probert | 499f015db9 | |
Linus Probert | 9b9a0ca2a0 | |
Linus Probert | 926054b116 | |
Linus Probert | 49b7ebb923 | |
Linus Probert | ee4dd273b9 | |
Linus Probert | 5ee20c9c20 | |
Linus Probert | 563ebf9204 | |
Linus Probert | 3533d5ca58 | |
Linus Probert | 97b097af41 | |
Linus Probert | 685bf97467 | |
Linus Probert | cc375bba4e | |
Linus Probert | 1205856d00 | |
Linus Probert | d1efa8450d | |
Linus Probert | 2775780d5b | |
Linus Probert | 269b25ba86 | |
Linus Probert | 72c3817927 | |
Linus Probert | 1212b1a88a | |
Linus Probert | ce2a3482d1 | |
Linus Probert | bc9d37eb91 | |
Linus Probert | 3c7dcb5ea1 | |
Linus Probert | 57b57c5051 | |
Linus Probert | 4d01251d1f | |
Linus Probert | 9299087b44 | |
Linus Probert | cb2510cf77 | |
Linus Probert | 469134a5be | |
Linus Probert | 8ab527ca6a | |
Linus Probert | 8e39ff8346 | |
Linus Probert | cb6bd03b5e | |
Linus Probert | b0f2936d44 | |
Linus Probert | 76c2f90ce9 | |
Linus Probert | 823384161f | |
Linus Probert | c2eae7a9fe | |
Linus Probert | f53703dd88 | |
Linus Probert | 0f66b0f3d0 | |
Linus Probert | 7005239830 | |
Linus Probert | 7991e7c1ce | |
Linus Probert | aea9995c68 | |
Linus Probert | a38a21a344 | |
Linus Probert | deb4638847 | |
Linus Probert | 120f8d7ff6 | |
Linus Probert | 5985c3e7f6 | |
Linus Probert | 9968b377a5 | |
Linus Probert | 7e71fcc773 | |
Linus Probert | dd77f29e98 | |
Linus Probert | 51d7b679ef | |
Linus Probert | 97c95dacd4 | |
Linus Probert | f895fdb35e | |
Linus Probert | 1a0d806459 | |
Linus Probert | f5a1c2f48a | |
Linus Probert | d2fe3fce4c | |
Linus Probert | bcdc9c1aa7 | |
Linus Probert | 8d09e8a23b | |
Linus Probert | d034a69f44 | |
Linus Probert | 94ec8cfba1 | |
Linus Probert | 669a2fb029 | |
Linus Probert | a90321e377 | |
Linus Probert | 0730eb4c49 | |
Linus Probert | feed0e29fa | |
Linus Probert | 6e6f28dd8e | |
Linus Probert | fd8799f36b | |
Linus Probert | ee56143d0d | |
Linus Probert | f65bdd0f13 | |
Linus Probert | a803578bc0 | |
Linus Probert | 87925041fe | |
Linus Probert | da3ff1a222 | |
Linus Probert | 850aae34ee | |
Linus Probert | 423ff733af | |
Linus Probert | 2e0a88e5e3 | |
Linus Probert | 53151b6ee0 | |
Linus Probert | e6b5b761b0 | |
Linus Probert | 894e3ba551 | |
Linus Probert | c8900e8ddf | |
Linus Probert | 06d2da164a | |
Linus Probert | 3143236908 | |
Linus Probert | 7333d3d62d | |
Linus Probert | 70cc79fc9f | |
Linus Probert | bdbb10be04 | |
Linus Probert | 75660a5288 | |
Linus Probert | bb7f9effd3 | |
Linus Probert | 2919ebf97f | |
Linus Probert | c3b2b6f214 | |
Linus Probert | e526c037e8 | |
Linus Probert | e845195823 | |
Linus Probert | 0723f62559 | |
Linus Probert | a162646177 | |
Linus Probert | 60374c93ad | |
Linus Probert | 2b02ae569e | |
Linus Probert | a4cb234075 | |
Linus Probert | e59f04b525 | |
Linus Probert | 2d25e42b40 | |
Linus Probert | 5d1490b14e | |
Linus Probert | aefbd9586b | |
Linus Probert | c7c5346afc | |
Linus Probert | 97ad1ddd23 | |
Linus Probert | 0dcb658076 | |
Linus Probert | 961060901c | |
Linus Probert | ee5ed1421f | |
Linus Probert | b4fd2cb8b4 | |
Linus Probert | 742d6e2363 | |
Linus Probert | 90603b4ebe | |
Linus Probert | bc452a3fb6 | |
Linus Probert | 6811c42667 | |
Linus Probert | e796fffc7c | |
Linus Probert | 35c3be45e0 | |
Linus Probert | 3bbe9176b8 | |
Linus Probert | ae44d5c2bc | |
Linus Probert | c97688a690 | |
Linus Probert | 47082daac3 | |
Linus Probert | 3301437b8f | |
Linus Probert | 743e4a3bac | |
Linus Probert | 81ccf8a730 | |
Linus Probert | 083834d044 | |
Linus Probert | dc6b816a4a | |
Linus Probert | 87b2b9d2c9 | |
Linus Probert | 5648be4982 | |
Linus Probert | 6e3343aa3b | |
Linus Probert | 5d5170cb0b | |
Linus Probert | 899d2e5d76 | |
Linus Probert | 583a7d049d | |
Linus Probert | 60359d8e9c | |
Linus Probert | dbf9fe3931 | |
Linus Probert | 0fc1fed278 | |
Linus Probert | e1b3364d88 | |
Linus Probert | 620a7e3ed5 | |
Linus Probert | 983875d064 | |
Linus Probert | e293c21908 | |
Linus Probert | 0ca70c7376 | |
Linus Probert | c39f05d49e | |
Linus Probert | 02a4407eb4 | |
Linus Probert | f246c5751a | |
Linus Probert | 367be69852 | |
Linus Probert | 988b53a4fa | |
Linus Probert | 03b60f6140 | |
Linus Probert | cfbd8cea4d | |
Linus Probert | cc627dc0c3 | |
Linus Probert | 5043a86377 | |
Linus Probert | fe88d08c25 | |
Linus Probert | cb732a80ec | |
Linus Probert | 2316d24942 | |
Linus Probert | 2827d5ac0d | |
Linus Probert | 956a37c36e | |
Linus Probert | b3724afe49 | |
Linus Probert | c65d6907e5 | |
Linus Probert | c52f6c9f97 | |
Linus Probert | c3c249c2f8 | |
Linus Probert | c22d7612be | |
Linus Probert | ccf1ec979b | |
Linus Probert | 321dc4f3af | |
Linus Probert | f3ecd50b1a | |
Linus Probert | 9e6325905f | |
Linus Probert | 3ef3351933 | |
Linus Probert | a78e4090ee | |
Linus Probert | 3fe4c8eb27 | |
Linus Probert | 00a15d6a49 | |
Linus Probert | 7ee85ecdb0 | |
Linus Probert | e217140895 | |
Linus Probert | 1ee7b92be8 | |
Linus Probert | 9364fec157 | |
Linus Probert | e000580971 | |
Linus Probert | 280b073a8c | |
Linus Probert | a19a13e054 | |
Linus Probert | cb60a035dd | |
Linus Probert | 07d7d6e58b | |
Linus Probert | f4f874c3ed | |
Linus Probert | 6e7ce815fd | |
Linus Probert | 4a6422fc09 | |
Linus Probert | 37518c100d | |
Linus Probert | 9bcb398f94 | |
Linus Probert | 75292d7539 | |
Linus Probert | b962d55510 | |
Linus Probert | ad2d0af79b | |
Linus Probert | 57b7831a45 | |
Linus Probert | 89168de588 | |
Linus Probert | 81361bc459 | |
Linus Probert | 1dadb2d9a0 | |
Linus Probert | a6d96da067 | |
Linus Probert | b7189b3487 | |
Linus Probert | 3acedb93df | |
Linus Probert | 35d2e2ee12 | |
Linus Probert | ef0e418e96 | |
Linus Probert | 1972b5b1df | |
Linus Probert | 0ca64fb882 | |
Linus Probert | 26379535be | |
Linus Probert | 41a2b1b8f8 | |
Linus Probert | f667cdb4fe | |
Linus Probert | 0ae8849323 | |
Linus Probert | fbb63ba742 | |
Linus Probert | 4013449878 | |
Linus Probert | 0ab65c9989 | |
Linus Probert | e1c154fc1c | |
Linus Probert | 0f50d3b015 | |
Linus Probert | ee8274038f | |
Linus Probert | 5a8c1ece14 | |
Linus Probert | 5dc25c1e79 | |
Linus Probert | f9556cbf59 | |
Linus Probert | a75a0d9331 | |
Linus Probert | adb22fed8e | |
Linus Probert | 0d1836a8ba | |
Linus Probert | 7b54e93893 | |
Linus Probert | 316325b98d | |
Linus Probert | d36c1dd954 | |
Linus Probert | c7011efc30 | |
Linus Probert | 3697e9b0b6 | |
Linus Probert | d2ced6cef1 | |
Linus Probert | 412a30da0d | |
Linus Probert | 28b3980fe6 | |
Linus Probert | 76d78600cb | |
Linus Probert | 8cdc87c299 | |
Linus Probert | 30ab6af565 | |
Linus Probert | 78ea122123 | |
Linus Probert | 9ae383b34e | |
Linus Probert | c23927c4fa | |
Linus Probert | cc1ae5d99d | |
Linus Probert | f5a88fc10e | |
Linus Probert | 52913af237 | |
Linus Probert | 449cc362a0 | |
Linus Probert | f67aab0b37 | |
Linus Probert | 8c261fd59f | |
Linus Probert | 6326a64111 | |
Linus Probert | f1b0045829 | |
Linus Probert | ffe1736792 | |
Linus Probert | 9244da3b64 | |
Linus Probert | 8bf9329b8c | |
Linus Probert | 8c25693d6d | |
Linus Probert | bec9eb429d | |
Linus Probert | 43f021a997 | |
Linus Probert | dbc36aab9f | |
Linus Probert | c390c024f6 | |
Linus Probert | 9ef97c0897 | |
Linus Probert | 358c0c7ddc | |
Linus Probert | 5f754d551a | |
Linus Probert | 30058ea4e0 | |
Linus Probert | 6763ef0144 | |
Linus Probert | 854f2c0918 | |
Linus Probert | 549f47ae0b | |
Linus Probert | 3fabd039a4 |
|
@ -86,29 +86,29 @@ build_script:
|
|||
# Build
|
||||
- |-
|
||||
cmake --version
|
||||
cmake -DCMAKE_PREFIX_PATH="%PREFIX%" -DCMAKE_C_COMPILER=mingw32-gcc.exe -DCMAKE_MAKE_PROGRAM=mingw32-make.exe -G "MinGW Makefiles"
|
||||
cmake -DCMAKE_PREFIX_PATH="%PREFIX%" -DCMAKE_C_COMPILER=mingw32-gcc.exe -DCMAKE_MAKE_PROGRAM=mingw32-make.exe -G "MinGW Makefiles" .
|
||||
|
||||
- |-
|
||||
mingw32-make
|
||||
ctest -V
|
||||
mingw32-make package
|
||||
# mingw32-make package
|
||||
|
||||
artifacts:
|
||||
- path: package/breakhack-*.zip
|
||||
name: breakhack_zip
|
||||
# artifacts:
|
||||
# - path: package/breakhack-*.zip
|
||||
# name: breakhack_zip
|
||||
|
||||
- path: package/breakhack-*.exe
|
||||
name: breakhack_exe
|
||||
# - path: package/breakhack-*.exe
|
||||
# name: breakhack_exe
|
||||
|
||||
deploy:
|
||||
provider: GitHub
|
||||
description: 'Alpha pre-release'
|
||||
auth_token:
|
||||
secure: IlMEyGp0AuDI8/MkFAY2KpRr70c3p8eVEMdcqC1EcgyCCbvoMOppBQ0gY44ao0gq
|
||||
draft: false
|
||||
prerelease: true
|
||||
on:
|
||||
branch: master
|
||||
appveyor_repo_tag: true
|
||||
# deploy:
|
||||
# provider: GitHub
|
||||
# description: 'Alpha pre-release'
|
||||
# auth_token:
|
||||
# secure: IlMEyGp0AuDI8/MkFAY2KpRr70c3p8eVEMdcqC1EcgyCCbvoMOppBQ0gY44ao0gq
|
||||
# draft: false
|
||||
# prerelease: true
|
||||
# on:
|
||||
# branch: master
|
||||
# appveyor_repo_tag: true
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
-DDEBUG
|
||||
-I./build/config.h
|
||||
-DSTEAM_BUILD
|
||||
-I/usr/include/SDL2/
|
||||
-I/usr/include/lua5.2/
|
||||
-I/usr/include/physfs.h
|
||||
-include./_build/debug/config.h
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: LiquidityC
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- Version [e.g. 1.1.4]
|
||||
- OS: [e.g. Windows, Archlinux, Ubuntu]
|
||||
- Architecture: 32 or 64 bit?
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
|
@ -1,3 +1,5 @@
|
|||
/.vscode/
|
||||
/vscode_build/
|
||||
/CMakeSettings.json
|
||||
/_build/
|
||||
/*.dll
|
||||
|
@ -6,5 +8,14 @@
|
|||
/data.pack
|
||||
/.vs/
|
||||
/.data.db
|
||||
/steamworks_c_wrapper/_build
|
||||
/steamworks_c_wrapper/sdk
|
||||
*.swp
|
||||
*~
|
||||
/steam_appid.txt
|
||||
/*.so
|
||||
/breakhack*.run
|
||||
compile_commands.json
|
||||
*.o
|
||||
breakhack
|
||||
|
||||
|
|
29
.travis.yml
29
.travis.yml
|
@ -52,19 +52,18 @@ addons:
|
|||
build_command: "make"
|
||||
branch_pattern: coverity_scan
|
||||
|
||||
before_deploy:
|
||||
- make package
|
||||
# before_deploy:
|
||||
# - make package
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: "KeT/BC2ck2eqs1q4keoLe/Y9KIk+AR5shiAnA2oMQzbLWoZmxUx3Kol7rLPJ0Hfgb+aCpSpTM1njX6Kw7Nl8j4NrOkgadb3ZmfqRthFazzb93reRt+0dZZcurilHpWtMeteaZLWGWaG0j09xnI3CPPjmth6BB+/roGRsQyo1QKk0pZYsQD6ZKfGAUR1576dFyRzvsIrnfLd7rZVSNZ8HtPwN2rmSLD/cGxMCf+IafcBInPyv9p6bCoVLIDFnDdCr+kwBuSlGudT15EtDx3d9Abab3ZIS3NUpnXr2s0BmknCpyb59YsG9V0YXIQsIkwioEWiJskcAznXT/yB4XqDCq693b+0sxldsUVPw2JkMU+40V5ay2itH3SeP/LyXVFUARdWB+nn6avaFRVaZ1nHYP95CrBXC8JGB1bd7ejeEm9+cOvBOgvsZp71uRJ2OdEXN5Z3i373cyvWXPFHVbQRJS5l1dRBJR0sozYcPe8BMQ4Pv+xahFWIeyDAErUwJSiOf1Uv/x6PNxJaZTTZKCYGSRo6Ywb15bw4YnlOzDXllBxNg3IsJjJes1qFBJGR1eRMq/U9Ne+eHLk7cn2r7Fa77DtFsbONTDHftXDFHk46LDLF+HlL2wHIoTJVzLl/tXyBm3MJuaghGEvvZSwalWS3UnvMTQOBlDG0qC/ww6mlkv+Y="
|
||||
skip_cleanup: true
|
||||
file_glob: true
|
||||
file:
|
||||
- "package/breakhack*.tar.gz"
|
||||
- "package/breakhack*.tar.Z"
|
||||
on:
|
||||
tags: true
|
||||
condition: $CC = gcc
|
||||
condition: $BUILD_TYPE = Release
|
||||
# deploy:
|
||||
# provider: releases
|
||||
# api_key:
|
||||
# secure: "KeT/BC2ck2eqs1q4keoLe/Y9KIk+AR5shiAnA2oMQzbLWoZmxUx3Kol7rLPJ0Hfgb+aCpSpTM1njX6Kw7Nl8j4NrOkgadb3ZmfqRthFazzb93reRt+0dZZcurilHpWtMeteaZLWGWaG0j09xnI3CPPjmth6BB+/roGRsQyo1QKk0pZYsQD6ZKfGAUR1576dFyRzvsIrnfLd7rZVSNZ8HtPwN2rmSLD/cGxMCf+IafcBInPyv9p6bCoVLIDFnDdCr+kwBuSlGudT15EtDx3d9Abab3ZIS3NUpnXr2s0BmknCpyb59YsG9V0YXIQsIkwioEWiJskcAznXT/yB4XqDCq693b+0sxldsUVPw2JkMU+40V5ay2itH3SeP/LyXVFUARdWB+nn6avaFRVaZ1nHYP95CrBXC8JGB1bd7ejeEm9+cOvBOgvsZp71uRJ2OdEXN5Z3i373cyvWXPFHVbQRJS5l1dRBJR0sozYcPe8BMQ4Pv+xahFWIeyDAErUwJSiOf1Uv/x6PNxJaZTTZKCYGSRo6Ywb15bw4YnlOzDXllBxNg3IsJjJes1qFBJGR1eRMq/U9Ne+eHLk7cn2r7Fa77DtFsbONTDHftXDFHk46LDLF+HlL2wHIoTJVzLl/tXyBm3MJuaghGEvvZSwalWS3UnvMTQOBlDG0qC/ww6mlkv+Y="
|
||||
# skip_cleanup: true
|
||||
# file_glob: true
|
||||
# file:
|
||||
# - "package/breakhack*.tar.gz"
|
||||
# on:
|
||||
# tags: true
|
||||
# condition: $CC = gcc
|
||||
# condition: $BUILD_TYPE = Release
|
||||
|
|
7
.vimrc
7
.vimrc
|
@ -1,8 +1,9 @@
|
|||
nnoremap <F1> :Make<cr>
|
||||
nnoremap <F2> :Make lint test<cr>
|
||||
nnoremap <F3> :Termdebug _build/breakhack<cr>
|
||||
nnoremap <F4> :ter ++close ./_build/breakhack<cr>
|
||||
nnoremap <F3> :Termdebug _build/debug/breakhack<cr>
|
||||
nnoremap <F4> :ter ++close env LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./ ./_build/debug/breakhack<cr>
|
||||
|
||||
packadd termdebug
|
||||
let g:termdebug_wide = 1
|
||||
let g:syntastic_c_include_dirs = [ '_build', '/usr/include/SDL2' ]
|
||||
let g:syntastic_c_include_dirs = [ '_build/debug', '/usr/include/SDL2', 'steamworks_c_wrapper/src', 'physfs-3.0/src', 'bh_random/src', 'checksum/src' ]
|
||||
let g:syntastic_cpp_include_dirs = [ 'steamworks_c_wrapper/sdk/public/steam', 'bh_random/src' ]
|
||||
|
|
286
CMakeLists.txt
286
CMakeLists.txt
|
@ -5,10 +5,14 @@ SET(CMAKE_COLOR_MAKEFILE ON)
|
|||
project(breakhack C)
|
||||
|
||||
set(breakhack_GAME_TITLE "BreakHack")
|
||||
set(breakhack_MAJOR_VERSION 0)
|
||||
set(breakhack_MINOR_VERSION 1)
|
||||
set(breakhack_PATCH_VERSION 13)
|
||||
set(breakhack_RELEASE_TYPE "(early access)")
|
||||
set(breakhack_MAJOR_VERSION 4)
|
||||
set(breakhack_MINOR_VERSION 0)
|
||||
set(breakhack_PATCH_VERSION 3)
|
||||
set(breakhack_RELEASE_TYPE "")
|
||||
|
||||
# Checksums
|
||||
set(breakhack_STEAMAPI_DLL_CHECKSUM 0x18dba28)
|
||||
set(breakhack_STEAMAPI_SO_CHECKSUM 0x1f5786b)
|
||||
|
||||
include(FindLua)
|
||||
include(FindPhysFS)
|
||||
|
@ -25,12 +29,33 @@ configure_file(
|
|||
"${PROJECT_BINARY_DIR}/config.h"
|
||||
)
|
||||
|
||||
macro(set_option option value)
|
||||
set(${option} ${value} CACHE INTERNAL "" FORCE)
|
||||
endmacro()
|
||||
|
||||
if (EXISTS "${PROJECT_SOURCE_DIR}/steamworks_c_wrapper/sdk")
|
||||
MESSAGE ( STATUS "Steam SDK located, Steam build enabled")
|
||||
set(STEAM 1)
|
||||
else ()
|
||||
MESSAGE ( STATUS "Steam SDK not found, Steam build disabled")
|
||||
endif()
|
||||
|
||||
if (STEAM)
|
||||
add_subdirectory(steamworks_c_wrapper)
|
||||
endif()
|
||||
add_subdirectory(bh_random)
|
||||
add_subdirectory(checksum)
|
||||
|
||||
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(CLANG 1)
|
||||
elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
|
||||
set(GCC 1)
|
||||
endif()
|
||||
|
||||
if ("${CMAKE_GENERATOR}" STREQUAL "Ninja")
|
||||
set(NINJA 1)
|
||||
endif()
|
||||
|
||||
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
|
||||
set(OSX 1)
|
||||
endif()
|
||||
|
@ -52,24 +77,26 @@ endif()
|
|||
|
||||
IF ( MSVC )
|
||||
MESSAGE ( STATUS "Setting MSVC MT switches")
|
||||
SET (
|
||||
CMAKE_C_FLAGS_DEBUG
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} /MTd"
|
||||
CACHE STRING "MSVC MT flags " FORCE
|
||||
string (REPLACE
|
||||
"/MDd"
|
||||
"/MTd"
|
||||
CMAKE_C_FLAGS_DEBUG
|
||||
${CMAKE_C_FLAGS_DEBUG}
|
||||
)
|
||||
SET (
|
||||
CMAKE_C_FLAGS_RELEASE
|
||||
"${CMAKE_CXX_FLAGS_RELEASE} /MT"
|
||||
CACHE STRING "MSVC MT flags " FORCE
|
||||
string (REPLACE
|
||||
"/MDd"
|
||||
"/MTd"
|
||||
CMAKE_C_FLAGS_RELEASE
|
||||
${CMAKE_C_FLAGS_RELEASE}
|
||||
)
|
||||
ELSEIF ( WIN32 )
|
||||
SET (
|
||||
CMAKE_C_FLAGS_DEBUG
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} -mconsole"
|
||||
"${CMAKE_C_FLAGS_DEBUG} -mconsole"
|
||||
)
|
||||
SET (
|
||||
CMAKE_C_FLAGS_RELEASE
|
||||
"${CMAKE_CXX_FLAGS_RELEASE} -mwindows"
|
||||
"${CMAKE_C_FLAGS_RELEASE} -mwindows"
|
||||
)
|
||||
ENDIF ()
|
||||
IF ( GCC OR CLANG )
|
||||
|
@ -79,27 +106,40 @@ IF ( GCC OR CLANG )
|
|||
)
|
||||
ENDIF ( GCC OR CLANG )
|
||||
|
||||
if (NOT PHYSFS_FOUND OR WIN32)
|
||||
set(PHYSFS_BUILD_STATIC TRUE)
|
||||
set(PHYSFS_BUILD_SHARED FALSE)
|
||||
set(PHYSFS_BUILD_TEST FALSE)
|
||||
add_subdirectory(physfs-3.0.1)
|
||||
if (STEAM)
|
||||
include_directories(
|
||||
physfs-3.0.1/src
|
||||
)
|
||||
else ()
|
||||
include_directories(
|
||||
${PHYSFS_INCLUDE_DIR}
|
||||
)
|
||||
${STEAMWORKS_INCLUDE_DIR}
|
||||
steamworks_c_wrapper/src
|
||||
)
|
||||
endif ()
|
||||
|
||||
if (NOT LUA_FOUND OR STEAM)
|
||||
add_subdirectory(lua-5.3.5)
|
||||
include_directories(lua-5.3.5/src)
|
||||
set(LUA_LIBRARIES lua)
|
||||
set(LUA_INCLUDE_DIR lua-5.3.5/src)
|
||||
endif ()
|
||||
|
||||
if (NOT PHYSFS_FOUND OR STEAM)
|
||||
set_option(PHYSFS_BUILD_SHARED off)
|
||||
set_option(PHYSFS_BUILD_TEST off)
|
||||
add_subdirectory(physfs-3.0)
|
||||
include_directories(physfs-3.0/src)
|
||||
set(PHYSFS_LIBRARY physfs-static)
|
||||
set(PHYSFS_INCLUDE_DIR physfs-3.0/src)
|
||||
endif ()
|
||||
|
||||
include_directories(
|
||||
${PROJECT_BINARY_DIR}
|
||||
${LUA_INCLUDE_DIR}
|
||||
${SDL2_INCLUDE_DIR}
|
||||
${SDL2_IMAGE_INCLUDE_DIR}
|
||||
${SDL2_TTF_INCLUDE_DIR}
|
||||
${SDL2_MIXER_INCLUDE_DIR}
|
||||
${PHYSFS_INCLUDE_DIR}
|
||||
${LUA_INCLUDE_DIR}
|
||||
sqlite3
|
||||
bh_random/src
|
||||
checksum/src
|
||||
)
|
||||
|
||||
if (CMOCKA_FOUND)
|
||||
|
@ -122,92 +162,120 @@ if (NOT MSVC)
|
|||
endif (NOT MSVC)
|
||||
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG")
|
||||
if (STEAM)
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSTEAM_BUILD")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DSTEAM_BUILD")
|
||||
set(STEAM_SOURCES
|
||||
src/steam/steamworks_api_wrapper
|
||||
)
|
||||
else ()
|
||||
set(STEAM_SOURCES "")
|
||||
endif ()
|
||||
|
||||
if (MINGW)
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DMINGW")
|
||||
endif (MINGW)
|
||||
|
||||
if (NOT MSVC)
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D__FNAME__='\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'")
|
||||
else (NOT MSVC)
|
||||
else ()
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D__FNAME__=__FILE__")
|
||||
endif (NOT MSVC)
|
||||
endif ()
|
||||
|
||||
# PROGRAMS:
|
||||
add_executable(breakhack
|
||||
src/main
|
||||
src/texture
|
||||
src/screenresolution
|
||||
src/sprite
|
||||
src/util
|
||||
src/player
|
||||
src/map
|
||||
src/map_lua
|
||||
src/camera
|
||||
src/timer
|
||||
src/roommatrix
|
||||
src/position
|
||||
src/monster
|
||||
src/stats
|
||||
src/actiontext
|
||||
src/random
|
||||
src/linkedlist
|
||||
src/hashtable
|
||||
src/gui
|
||||
src/item
|
||||
src/item_builder
|
||||
src/pointer
|
||||
src/gui_button
|
||||
src/particle_engine
|
||||
src/menu
|
||||
src/collisions
|
||||
src/keyboard
|
||||
src/input
|
||||
src/mixer
|
||||
src/io_util
|
||||
src/physfsrwops
|
||||
src/skillbar
|
||||
src/texturecache
|
||||
src/skill
|
||||
src/projectile
|
||||
src/vector2d
|
||||
src/map_room_modifiers
|
||||
src/sqlite3
|
||||
src/db
|
||||
src/settings
|
||||
src/actiontextbuilder
|
||||
src/animation
|
||||
src/trap
|
||||
src/artifact
|
||||
src/screen
|
||||
src/hiscore
|
||||
src/object
|
||||
src/main.c
|
||||
src/texture.c
|
||||
src/screenresolution.c
|
||||
src/sprite.c
|
||||
src/sprite_util.c
|
||||
src/util.c
|
||||
src/event.c
|
||||
src/player.c
|
||||
src/save.c
|
||||
src/map.c
|
||||
src/map_lua.c
|
||||
src/camera.c
|
||||
src/timer.c
|
||||
src/roommatrix.c
|
||||
src/position.c
|
||||
src/monster.c
|
||||
src/stats.c
|
||||
src/actiontext.c
|
||||
src/random.c
|
||||
src/time.c
|
||||
src/linkedlist.c
|
||||
src/hashtable.c
|
||||
src/gui.c
|
||||
src/item.c
|
||||
src/item_builder.c
|
||||
src/pointer.c
|
||||
src/gui_button.c
|
||||
src/particle_engine.c
|
||||
src/particle_emitter.c
|
||||
src/menu.c
|
||||
src/collisions.c
|
||||
src/keyboard.c
|
||||
src/input.c
|
||||
src/mixer.c
|
||||
src/io_util.c
|
||||
src/physfsrwops.c
|
||||
src/skillbar.c
|
||||
src/texturecache.c
|
||||
src/skill.c
|
||||
src/projectile.c
|
||||
src/vector2d.c
|
||||
src/map_room_modifiers.c
|
||||
sqlite3/sqlite3.c
|
||||
src/db.c
|
||||
src/settings.c
|
||||
src/actiontextbuilder.c
|
||||
src/animation.c
|
||||
src/trap.c
|
||||
src/artifact.c
|
||||
src/screen.c
|
||||
src/hiscore.c
|
||||
src/object.c
|
||||
src/gui_util.c
|
||||
src/tooltip.c
|
||||
src/gamecontroller.c
|
||||
src/effect_util.c
|
||||
${STEAM_SOURCES}
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
source_group("Header files" REGULAR_EXPRESSION ".*\\.h")
|
||||
source_group("Source files" REGULAR_EXPRESSION ".*\\.c")
|
||||
endif ()
|
||||
|
||||
# Sqlite has some warnings that I we don't need to see
|
||||
set_source_files_properties(src/sqlite3.c COMPILE_FLAGS -w)
|
||||
set_source_files_properties(sqlite3/sqlite3.c COMPILE_FLAGS -w)
|
||||
|
||||
target_link_libraries(breakhack
|
||||
${CMAKE_DL_LIBS} # Sqlite needs DL libs
|
||||
${LUA_LIBRARY}
|
||||
${SDL2_LIBRARY}
|
||||
${SDL2MAIN_LIBRARY}
|
||||
${SDL2_IMAGE_LIBRARY}
|
||||
${SDL2_TTF_LIBRARY}
|
||||
${SDL2_MIXER_LIBRARY}
|
||||
${LUA_LIBRARIES}
|
||||
${PHYSFS_LIBRARY}
|
||||
bh_random
|
||||
checksum
|
||||
)
|
||||
|
||||
if (NOT PHYSFS_FOUND)
|
||||
if (STEAM)
|
||||
target_link_libraries(breakhack
|
||||
physfs-static
|
||||
)
|
||||
else ()
|
||||
target_link_libraries(breakhack
|
||||
${PHYSFS_LIBRARY}
|
||||
steamworks_c_wrapper
|
||||
)
|
||||
endif ()
|
||||
|
||||
if (MSVC)
|
||||
set_target_properties(breakhack PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
||||
set_target_properties(breakhack PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE /NODEFAULTLIB:MSVCRTD")
|
||||
set_target_properties(breakhack PROPERTIES COMPILE_DEFINITIONS_DEBUG "_CONSOLE")
|
||||
set_target_properties(breakhack PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE")
|
||||
set_target_properties(breakhack PROPERTIES COMPILE_DEFINITIONS_RELWITHDEBINFO "_CONSOLE")
|
||||
set_target_properties(breakhack PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
|
||||
set_target_properties(breakhack PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS /NODEFAULTLIB:MSVCRTD")
|
||||
set_target_properties(breakhack PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS")
|
||||
endif (MSVC)
|
||||
|
||||
|
@ -215,19 +283,19 @@ endif (MSVC)
|
|||
IF (CMOCKA_FOUND AND NOT OSX AND NOT CLANG)
|
||||
find_package(Threads REQUIRED)
|
||||
enable_testing()
|
||||
add_executable(test_util test/test_util src/util)
|
||||
add_executable(test_util test/test_util.c src/util.c)
|
||||
target_link_libraries(test_util ${CMOCKA_LIBRARY})
|
||||
add_test(test_util test_util)
|
||||
|
||||
add_executable(test_linkedlist test/test_linkedlist src/linkedlist src/util)
|
||||
add_executable(test_linkedlist test/test_linkedlist.c src/linkedlist.c src/util.c)
|
||||
target_link_libraries(test_linkedlist ${CMOCKA_LIBRARY})
|
||||
add_test(test_linkedlist test_linkedlist)
|
||||
|
||||
add_executable(test_hashtable test/test_hashtable src/hashtable src/util)
|
||||
add_executable(test_hashtable test/test_hashtable.c src/hashtable.c src/util.c)
|
||||
target_link_libraries(test_hashtable ${CMOCKA_LIBRARY})
|
||||
add_test(test_hashtable test_hashtable)
|
||||
|
||||
add_executable(test_input test/test_input src/input src/keyboard)
|
||||
add_executable(test_input test/test_input.c src/input.c src/keyboard.c)
|
||||
target_link_libraries(test_input
|
||||
${CMOCKA_LIBRARY}
|
||||
${SDL2_LIBRARY}
|
||||
|
@ -241,7 +309,7 @@ ENDIF ()
|
|||
# LINT:
|
||||
if (CPPCHECK_FOUND)
|
||||
add_custom_target(lint
|
||||
COMMAND ${CPPCHECK_EXECUTABLE} --force --language=c --template=gcc --error-exitcode=1 --quiet --enable=warning,style,performance,portability,information,missingInclude --suppress=*:src/sqlite3.? -isrc/sqlite3.c src/
|
||||
COMMAND ${CPPCHECK_EXECUTABLE} --force --language=c --template=gcc --error-exitcode=1 --quiet --suppress=missingInclude --enable=warning,style,performance,portability,information,missingInclude src/
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
COMMENT "Run cppcheck"
|
||||
)
|
||||
|
@ -268,22 +336,20 @@ if (NOT DEBUG_BUILD)
|
|||
"monstergen.lua"
|
||||
"trapgen.lua"
|
||||
"chestgen.lua"
|
||||
"layoutparser.lua"
|
||||
"pitlayouts.dat"
|
||||
"walllayouts.dat"
|
||||
"shoplayouts.dat"
|
||||
"lockedroomlayouts.dat"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data
|
||||
)
|
||||
if (WIN32 AND NOT MSVC)
|
||||
add_definitions(-mwindows)
|
||||
endif()
|
||||
else()
|
||||
if (WIN32)
|
||||
add_definitions(-mconsole)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
SET(CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT "Release")
|
||||
SET(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION ".")
|
||||
if (WIN32)
|
||||
SET(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS
|
||||
${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
|
||||
${CMAKE_SOURCE_DIR}/bin/libFLAC-8.dll
|
||||
${CMAKE_SOURCE_DIR}/bin/libfreetype-6.dll
|
||||
${CMAKE_SOURCE_DIR}/bin/libmodplug-1.dll
|
||||
|
@ -298,6 +364,20 @@ if (WIN32)
|
|||
${CMAKE_SOURCE_DIR}/bin/SDL2_ttf.dll
|
||||
${CMAKE_SOURCE_DIR}/bin/zlib1.dll
|
||||
)
|
||||
if (STEAM)
|
||||
SET(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS
|
||||
${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
|
||||
steamworks_c_wrapper/sdk/redistributable_bin/steam_api.dll
|
||||
)
|
||||
endif ()
|
||||
else (WIN32)
|
||||
if (STEAM)
|
||||
SET(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS
|
||||
${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
|
||||
steamworks_c_wrapper/sdk/redistributable_bin/linux64/libsteam_api.so
|
||||
build/linux/breakhack.run
|
||||
)
|
||||
endif ()
|
||||
endif (WIN32)
|
||||
include(InstallRequiredSystemLibraries)
|
||||
|
||||
|
@ -320,11 +400,19 @@ set(CPACK_PACKAGE_VERSION_MAJOR ${breakhack_MAJOR_VERSION})
|
|||
set(CPACK_PACKAGE_VERSION_MINOR ${breakhack_MINOR_VERSION})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${breakhack_PATCH_VERSION})
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "BreakHack")
|
||||
set(CPACK_PACKAGE_FILE_NAME "breakhack-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||
set(CPACK_PACKAGE_CHECKSUM "MD5")
|
||||
if (WIN32)
|
||||
set(CPACK_PACKAGE_FILE_NAME "breakhack-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}-win32")
|
||||
else ()
|
||||
set(CPACK_PACKAGE_FILE_NAME "breakhack-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||
endif ()
|
||||
if (STEAM)
|
||||
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF)
|
||||
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-steambuild")
|
||||
endif ()
|
||||
|
||||
if(UNIX)
|
||||
set(CPACK_GENERATOR STGZ TGZ TZ)
|
||||
set(CPACK_GENERATOR TGZ ZIP)
|
||||
set(CPACK_STRIP_FILES breakhack)
|
||||
set(CPACK_SOURCE_STRIP_FILES "")
|
||||
elseif(WIN32)
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at contact@oliveshark.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
24
CREDITS.md
24
CREDITS.md
|
@ -1,18 +1,20 @@
|
|||
- Game -
|
||||
--------
|
||||
Code: Linus Probert
|
||||
liquidityc.github.io
|
||||
@LiquidityC
|
||||
|
||||
Code: Linus Probert
|
||||
liquidityc.github.io
|
||||
@LiquidityC
|
||||
|
||||
- Graphics -
|
||||
------------
|
||||
Palette: DawnBringer
|
||||
Palette: DawnBringer
|
||||
|
||||
- Music and Sound -
|
||||
-------------------
|
||||
Music: Eric Matyas
|
||||
www.soundimage.org
|
||||
Sound: Eric Matyas
|
||||
www.soundimage.org
|
||||
ArtisticDuded
|
||||
opengameart.org/users/artisticdude
|
||||
Music: Eric Matyas
|
||||
www.soundimage.org
|
||||
|
||||
Sound: Eric Matyas
|
||||
www.soundimage.org
|
||||
|
||||
ArtisticDuded
|
||||
opengameart.org/users/artisticdude
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
Apart from basic compile tools (*GCC/Clang, Make*) you'll also need to install **sdl2, sdl2-image, sdl2-ttf, sdl2-mixer** (If on a debian based dist you need to install the *dev* packages).
|
||||
Optionally you can also install **cppcheck** and **physfs**
|
||||
|
||||
Once that is done run the following:
|
||||
```bash
|
||||
mkdir _build
|
||||
cd _build
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug .. # Build type flag is optional
|
||||
make
|
||||
```
|
|
@ -0,0 +1,16 @@
|
|||
Compile on Windows with Visual Studio
|
||||
-------------------------------------
|
||||
|
||||
1. Install [Visual Studio Community 2019](https://visualstudio.microsoft.com/vs/community/) with the "Desktop development with C++" workload
|
||||
2. Install [CMake](https://cmake.org/download/)
|
||||
3. Install [NSIS](https://nsis.sourceforge.io/Download)
|
||||
4. Download and unzip [SDL2-devel-2.x.x-VC.zip](https://www.libsdl.org/download-2.0.php), [SDL2_image-devel-2.x.x-VC.zip](https://www.libsdl.org/projects/SDL_image/), [SDL2_mixer-devel-2.x.x-VC.zip](https://www.libsdl.org/projects/SDL_mixer/), [SDL2_ttf-devel-2.x.x-VC.zip](https://www.libsdl.org/projects/SDL_ttf/)
|
||||
5. Open Developer Command Prompt for VS 2019 and run the following, substituting paths as appropriate:
|
||||
```batch
|
||||
SET SDL2DIR=C:\repos\breakhackBuild\SDL2-2.0.9
|
||||
SET SDL2MIXERDIR=C:\repos\breakhackBuild\SDL2_mixer-2.0.4
|
||||
SET SDL2_IMAGE=C:\repos\breakhackBuild\SDL2_image-2.0.4
|
||||
SET SDLTTFDIR=C:\repos\breakhackBuild\SDL2_ttf-2.0.15
|
||||
cmake -S C:\repos\breakhack -B C:\repos\breakhackBuild
|
||||
cmake --build C:\repos\breakhackBuild --target package --config Release
|
||||
```
|
41
Makefile
41
Makefile
|
@ -1,19 +1,50 @@
|
|||
all:
|
||||
@make -sC _build
|
||||
@make -sC _build/debug
|
||||
.PHONY: all
|
||||
|
||||
release:
|
||||
@make -sC _build/release
|
||||
.PHONY: release
|
||||
|
||||
clean:
|
||||
@make clean -sC _build
|
||||
@make -sC _build/debug clean
|
||||
@make -sC _build/release clean
|
||||
.PHONY: clean
|
||||
|
||||
test:
|
||||
@make test -sC _build
|
||||
@make -sC _build/debug test
|
||||
.PHONY: test
|
||||
|
||||
run: $(all)
|
||||
@./_build/breakhack
|
||||
@LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./ ./_build/debug/breakhack
|
||||
.PHONY: run
|
||||
|
||||
playtest: $(all)
|
||||
@LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./ ./_build/release/breakhack
|
||||
.PHONY: playtest
|
||||
|
||||
lint:
|
||||
@make lint -sC _build
|
||||
@make -sC _build/debug lint
|
||||
.PHONY: lint
|
||||
|
||||
package:
|
||||
@make -sC _build/release package
|
||||
.PHONY: package
|
||||
|
||||
setup:
|
||||
@mkdir -p _build/release
|
||||
@mkdir -p _build/debug
|
||||
@cd _build/debug/ && \
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=YES ../.. && \
|
||||
cd -
|
||||
@cd _build/debug/ && \
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ../.. && \
|
||||
cd -
|
||||
@ln -s _build/debug/compile_commands.json
|
||||
@echo "Setup complete"
|
||||
.PHONY: setup
|
||||
|
||||
teardown:
|
||||
@rm -rf _build
|
||||
@rm compile_commands.json
|
||||
.PHONY: teardown
|
||||
|
|
|
@ -0,0 +1,503 @@
|
|||
#
|
||||
# Project: breakhack
|
||||
#
|
||||
# Created on: 29-08-2022 21:00:37
|
||||
# by George Sokianos
|
||||
#
|
||||
|
||||
###################################################################
|
||||
##
|
||||
##//// Objects
|
||||
##
|
||||
###################################################################
|
||||
|
||||
breakhack_OBJ := \
|
||||
src/actiontext.o src/actiontextbuilder.o src/animation.o \
|
||||
src/artifact.o src/camera.o src/collisions.o \
|
||||
src/db.o src/effect_util.o src/event.o \
|
||||
src/gamecontroller.o src/gui_button.o src/gui.o \
|
||||
src/gui_util.o src/hashtable.o src/hiscore.o \
|
||||
src/input.o src/io_util.o src/item_builder.o \
|
||||
src/item.o src/keyboard.o src/linkedlist.o \
|
||||
src/main.o src/map.o src/map_lua.o \
|
||||
src/map_room_modifiers.o src/menu.o src/mixer.o \
|
||||
src/monster.o src/object.o src/particle_emitter.o \
|
||||
src/particle_engine.o src/physfsrwops.o src/player.o \
|
||||
src/pointer.o src/position.o src/projectile.o \
|
||||
src/random.o src/roommatrix.o src/save.o \
|
||||
src/screen.o src/screenresolution.o src/settings.o \
|
||||
src/skill.o src/skillbar.o src/sprite.o \
|
||||
src/sprite_util.o src/stats.o src/texture.o \
|
||||
src/texturecache.o src/time.o src/timer.o \
|
||||
src/tooltip.o src/trap.o src/util.o \
|
||||
src/vector2d.o bh_random/src/bh_random.o
|
||||
|
||||
|
||||
###################################################################
|
||||
##
|
||||
##//// Variables and Environment
|
||||
##
|
||||
###################################################################
|
||||
|
||||
CC := gcc:bin/gcc
|
||||
|
||||
INCPATH := -I. -I/sdk/local/newlib/include/SDL2 -Ibh_random/src \
|
||||
-I/sdk/local/common/include/lua53
|
||||
# -DDEBUG
|
||||
|
||||
CFLAGS := $(INCPATH) -Wall -Wwrite-strings -Wno-discarded-qualifiers
|
||||
# \
|
||||
# -g -gstabs
|
||||
# -ggdb -gdwarf-2
|
||||
|
||||
LFLAGS := -lauto -lSDL2_image -lSDL2_ttf -lfreetype -ltiff -lwebp -lpng -ljpeg \
|
||||
-llua53 -lsqlite3 -lz \
|
||||
-lSDL2_mixer -lmikmod -lmodplug -lFLAC -logg \
|
||||
-lSDL2 -lphysfs -lpthread -athread=native -lstdc++
|
||||
# \
|
||||
# -g -gstabs
|
||||
# -ggdb -gdwarf-2
|
||||
# -lunix
|
||||
|
||||
# -lenet -lcrypto -lSDL2_gl4es -lglu_gl4es -lgl4es -lopenal \
|
||||
###################################################################
|
||||
##
|
||||
##//// General rules
|
||||
##
|
||||
###################################################################
|
||||
|
||||
.PHONY: all all-before all-after clean clean-custom realclean
|
||||
|
||||
all: all-before breakhack all-after
|
||||
|
||||
all-before:
|
||||
# You can add rules here to execute before the project is built
|
||||
|
||||
all-after:
|
||||
# You can add rules here to execute after the project is built
|
||||
|
||||
clean: clean-custom
|
||||
@echo "Cleaning compiler objects..."
|
||||
@rm -f $(breakhack_OBJ)
|
||||
|
||||
realclean:
|
||||
@echo "Cleaning compiler objects and targets..."
|
||||
@rm -f $(breakhack_OBJ) breakhack
|
||||
|
||||
|
||||
###################################################################
|
||||
##
|
||||
##//// Targets
|
||||
##
|
||||
###################################################################
|
||||
|
||||
breakhack: $(breakhack_OBJ)
|
||||
@echo "Linking breakhack"
|
||||
@gcc:bin/gcc -o breakhack $(breakhack_OBJ) $(LFLAGS)
|
||||
@echo "Removing stale debug target: breakhack"
|
||||
@rm -f breakhack.debug
|
||||
|
||||
|
||||
###################################################################
|
||||
##
|
||||
##//// Standard rules
|
||||
##
|
||||
###################################################################
|
||||
|
||||
# A default rule to make all the objects listed below
|
||||
# because we are hiding compiler commands from the output
|
||||
|
||||
.c.o:
|
||||
@echo "Compiling $<"
|
||||
@$(CC) -c $< -o $*.o $(CFLAGS)
|
||||
|
||||
src/actiontext.o: src/actiontext.c src/actiontext.h \
|
||||
src/position.h src/sprite.h src/texture.h \
|
||||
src/camera.h src/roommatrix.h src/timer.h \
|
||||
src/vector2d.h src/util.h src/update_data.h \
|
||||
src/player.h src/stats.h src/skill.h \
|
||||
src/linkedlist.h src/input.h src/artifact.h \
|
||||
src/map.h src/defines.h src/monster.h \
|
||||
src/map_room_modifiers.h src/object.h src/doorlocktype.h
|
||||
|
||||
src/actiontextbuilder.o: src/actiontextbuilder.c src/actiontextbuilder.h src/actiontext.h \
|
||||
src/position.h src/sprite.h src/timer.h \
|
||||
src/vector2d.h src/camera.h src/update_data.h \
|
||||
src/player.h src/map.h src/roommatrix.h \
|
||||
src/gui.h src/util.h
|
||||
|
||||
src/animation.o: src/animation.c src/animation.h src/timer.h \
|
||||
src/camera.h src/position.h src/vector2d.h \
|
||||
src/sprite.h src/texture.h \
|
||||
src/dimension.h src/roommatrix.h src/defines.h \
|
||||
src/map_room_modifiers.h src/input.h
|
||||
|
||||
src/artifact.o: src/artifact.c src/artifact.h src/sprite.h \
|
||||
src/texture.h src/position.h src/camera.h \
|
||||
src/roommatrix.h src/timer.h \
|
||||
src/vector2d.h src/util.h src/texturecache.h \
|
||||
src/dimension.h src/particle_engine.h src/player.h \
|
||||
src/stats.h src/actiontext.h src/skill.h \
|
||||
src/linkedlist.h src/input.h src/random.h \
|
||||
|
||||
|
||||
src/camera.o: src/camera.c src/camera.h src/position.h \
|
||||
src/timer.h src/vector2d.h src/map.h \
|
||||
src/linkedlist.h src/sprite.h src/texture.h \
|
||||
src/roommatrix.h src/defines.h src/config.h \
|
||||
src/monster.h src/stats.h src/actiontext.h \
|
||||
src/player.h src/doorlocktype.h src/particle_emitter.h \
|
||||
src/skill.h src/input.h src/artifact.h \
|
||||
src/map_room_modifiers.h src/object.h src/util.h
|
||||
|
||||
src/collisions.o: src/collisions.c src/collisions.h
|
||||
|
||||
src/db.o: src/db.c src/db.h
|
||||
|
||||
src/effect_util.o: src/effect_util.c src/gui.h src/linkedlist.h \
|
||||
src/sprite.h src/texture.h src/position.h \
|
||||
src/camera.h src/roommatrix.h src/timer.h \
|
||||
src/vector2d.h src/player.h \
|
||||
src/stats.h src/actiontext.h src/skill.h \
|
||||
src/input.h src/artifact.h src/monster.h src/doorlocktype.h \
|
||||
src/particle_emitter.h src/dimension.h src/defines.h \
|
||||
src/config.h src/map_room_modifiers.h
|
||||
|
||||
src/event.o: src/event.c src/event.h src/player.h \
|
||||
src/sprite.h src/stats.h \
|
||||
src/actiontext.h src/camera.h src/skill.h \
|
||||
src/linkedlist.h src/input.h src/artifact.h
|
||||
|
||||
src/gamecontroller.o: src/gamecontroller.c src/gamecontroller.h
|
||||
|
||||
src/gui_button.o: src/gui_button.c src/util.h src/gui_button.h \
|
||||
src/pointer.h src/sprite.h src/camera.h \
|
||||
src/input.h src/texture.h src/position.h \
|
||||
src/roommatrix.h src/timer.h src/linkedlist.h \
|
||||
src/vector2d.h
|
||||
|
||||
src/gui.o: src/gui.c src/gui.h src/linkedlist.h \
|
||||
src/sprite.h src/texture.h src/position.h \
|
||||
src/camera.h src/roommatrix.h src/timer.h \
|
||||
src/vector2d.h src/player.h \
|
||||
src/stats.h src/actiontext.h src/skill.h \
|
||||
src/input.h src/artifact.h src/util.h \
|
||||
src/map.h \
|
||||
src/defines.h src/config.h src/monster.h \
|
||||
src/doorlocktype.h src/particle_emitter.h src/map_room_modifiers.h \
|
||||
src/object.h src/texturecache.h \
|
||||
src/dimension.h src/gui_util.h
|
||||
|
||||
src/gui_util.o: src/gui_util.c src/texturecache.h src/texture.h \
|
||||
src/dimension.h src/position.h \
|
||||
src/camera.h src/gui_util.h src/sprite.h \
|
||||
src/roommatrix.h src/timer.h
|
||||
|
||||
src/hashtable.o: src/hashtable.c src/hashtable.h src/defines.h \
|
||||
src/config.h
|
||||
|
||||
src/hiscore.o: src/hiscore.c src/hiscore.h src/linkedlist.h \
|
||||
src/player.h src/sprite.h \
|
||||
src/stats.h src/actiontext.h src/camera.h \
|
||||
src/skill.h src/input.h src/artifact.h \
|
||||
src/db.h
|
||||
|
||||
src/input.o: src/input.c src/input.h
|
||||
|
||||
src/io_util.o: src/io_util.c src/physfsrwops.h src/io_util.h
|
||||
|
||||
src/item_builder.o: src/item_builder.c src/item_builder.h \
|
||||
src/item.h src/sprite.h src/position.h \
|
||||
src/player.h src/camera.h src/linkedlist.h \
|
||||
src/texture.h src/dimension.h \
|
||||
src/timer.h src/vector2d.h src/util.h \
|
||||
src/gui.h src/roommatrix.h src/stats.h \
|
||||
src/actiontext.h src/skill.h src/input.h \
|
||||
src/artifact.h src/mixer.h src/gamestate.h \
|
||||
src/random.h src/texturecache.h src/defines.h \
|
||||
src/map_room_modifiers.h src/sprite_util.h src/map.h \
|
||||
src/config.h src/monster.h src/doorlocktype.h \
|
||||
src/particle_emitter.h
|
||||
|
||||
src/item.o: src/item.c src/item.h src/sprite.h \
|
||||
src/texture.h src/position.h src/camera.h \
|
||||
src/roommatrix.h src/timer.h src/player.h \
|
||||
src/stats.h src/actiontext.h \
|
||||
src/skill.h src/linkedlist.h src/input.h \
|
||||
src/artifact.h src/vector2d.h src/util.h \
|
||||
src/mixer.h src/gamestate.h src/gui.h \
|
||||
src/actiontextbuilder.h src/update_data.h
|
||||
|
||||
src/keyboard.o: src/keyboard.c src/keyboard.h src/defines.h \
|
||||
src/config.h
|
||||
|
||||
src/linkedlist.o: src/linkedlist.c src/linkedlist.h
|
||||
|
||||
src/main.o: src/main.c /sdk/local/newlib/include/SDL2/SDL_main.h \
|
||||
src/linkedlist.h src/player.h src/sprite.h \
|
||||
src/texture.h src/position.h src/camera.h \
|
||||
src/roommatrix.h src/timer.h src/stats.h \
|
||||
src/actiontext.h src/vector2d.h src/skill.h \
|
||||
src/input.h src/artifact.h src/screenresolution.h \
|
||||
src/dimension.h src/map.h src/defines.h \
|
||||
src/config.h src/monster.h src/doorlocktype.h \
|
||||
src/particle_emitter.h src/map_room_modifiers.h src/object.h \
|
||||
src/map_lua.h src/gamestate.h src/gui.h \
|
||||
src/util.h src/item_builder.h src/item.h \
|
||||
src/pointer.h src/gui_button.h src/particle_engine.h \
|
||||
src/menu.h src/keyboard.h \
|
||||
src/mixer.h src/random.h src/skillbar.h \
|
||||
src/texturecache.h src/update_data.h src/settings.h \
|
||||
src/actiontextbuilder.h src/screen.h src/hiscore.h \
|
||||
src/io_util.h src/tooltip.h src/gamecontroller.h \
|
||||
src/time.h src/sprite_util.h src/event.h \
|
||||
src/save.h src/steam/steamworks_api_wrapper.h src/defines.h
|
||||
|
||||
src/map.o: src/map.c src/map.h src/linkedlist.h \
|
||||
src/sprite.h src/texture.h src/position.h \
|
||||
src/camera.h src/roommatrix.h src/timer.h \
|
||||
src/vector2d.h src/defines.h src/config.h \
|
||||
src/monster.h src/stats.h src/actiontext.h \
|
||||
src/player.h src/doorlocktype.h src/particle_emitter.h \
|
||||
src/skill.h src/input.h src/artifact.h \
|
||||
src/map_room_modifiers.h src/object.h src/map_lua.h \
|
||||
src/util.h src/item.h src/item_builder.h \
|
||||
src/gui.h src/particle_engine.h src/dimension.h \
|
||||
src/update_data.h src/trap.h src/mixer.h
|
||||
|
||||
src/map_lua.o: src/map_lua.c src/map_lua.h src/map.h \
|
||||
src/linkedlist.h src/sprite.h \
|
||||
src/camera.h src/position.h src/timer.h \
|
||||
src/defines.h src/monster.h src/player.h \
|
||||
src/map_room_modifiers.h src/object.h src/doorlocktype.h \
|
||||
src/config.h src/util.h src/stats.h \
|
||||
src/io_util.h src/texturecache.h src/texture.h \
|
||||
src/dimension.h src/trap.h src/roommatrix.h \
|
||||
src/actiontext.h src/skill.h src/input.h \
|
||||
src/artifact.h src/update_data.h src/gui.h \
|
||||
src/vector2d.h src/item.h src/item_builder.h
|
||||
|
||||
src/map_room_modifiers.o: src/map_room_modifiers.c src/map_room_modifiers.h src/vector2d.h \
|
||||
src/player.h src/sprite.h src/texture.h \
|
||||
src/position.h src/camera.h src/roommatrix.h \
|
||||
src/timer.h src/stats.h src/actiontext.h \
|
||||
src/skill.h src/linkedlist.h src/input.h \
|
||||
src/artifact.h src/defines.h
|
||||
|
||||
src/menu.o: src/menu.c src/menu.h src/camera.h \
|
||||
src/position.h src/timer.h src/vector2d.h \
|
||||
src/linkedlist.h src/texture.h \
|
||||
src/dimension.h src/sprite.h src/roommatrix.h \
|
||||
src/util.h src/defines.h src/map_room_modifiers.h \
|
||||
src/input.h src/config.h src/gui_button.h \
|
||||
src/pointer.h src/keyboard.h src/mixer.h \
|
||||
src/gamestate.h src/collisions.h
|
||||
|
||||
src/mixer.o: src/mixer.c src/mixer.h src/gamestate.h \
|
||||
src/util.h src/io_util.h src/settings.h
|
||||
|
||||
src/monster.o: src/monster.c src/monster.h src/sprite.h \
|
||||
src/texture.h src/position.h src/camera.h \
|
||||
src/roommatrix.h src/timer.h src/stats.h \
|
||||
src/actiontext.h src/vector2d.h src/player.h \
|
||||
src/skill.h src/linkedlist.h src/input.h \
|
||||
src/artifact.h src/doorlocktype.h src/particle_emitter.h \
|
||||
src/dimension.h src/util.h src/random.h \
|
||||
src/gui.h src/item.h src/item_builder.h \
|
||||
src/map.h src/defines.h src/config.h \
|
||||
src/map_room_modifiers.h src/object.h src/particle_engine.h \
|
||||
src/update_data.h src/actiontextbuilder.h src/texturecache.h \
|
||||
src/trap.h src/mixer.h
|
||||
|
||||
src/object.o: src/object.c src/object.h src/camera.h \
|
||||
src/position.h src/timer.h src/vector2d.h \
|
||||
src/player.h src/sprite.h src/stats.h \
|
||||
src/actiontext.h src/skill.h src/linkedlist.h \
|
||||
src/input.h src/artifact.h src/texture.h \
|
||||
src/roommatrix.h src/util.h src/mixer.h \
|
||||
src/gamestate.h src/random.h src/texturecache.h
|
||||
|
||||
src/particle_emitter.o: src/particle_emitter.c src/particle_emitter.h src/timer.h \
|
||||
src/position.h src/dimension.h
|
||||
|
||||
src/particle_engine.o: src/particle_engine.c src/particle_engine.h src/position.h \
|
||||
src/dimension.h src/camera.h src/timer.h \
|
||||
src/vector2d.h src/linkedlist.h src/util.h \
|
||||
src/defines.h src/config.h
|
||||
|
||||
src/physfsrwops.o: src/physfsrwops.c src/physfsrwops.h
|
||||
|
||||
src/player.o: src/player.c src/player.h src/sprite.h \
|
||||
src/texture.h src/position.h src/camera.h \
|
||||
src/roommatrix.h src/timer.h src/stats.h \
|
||||
src/actiontext.h src/vector2d.h src/skill.h \
|
||||
src/linkedlist.h src/input.h src/artifact.h \
|
||||
src/monster.h src/doorlocktype.h src/particle_emitter.h \
|
||||
src/dimension.h src/util.h src/gui.h \
|
||||
src/item.h src/particle_engine.h src/keyboard.h \
|
||||
src/defines.h src/config.h src/mixer.h \
|
||||
src/gamestate.h src/random.h src/projectile.h \
|
||||
src/map_room_modifiers.h src/update_data.h src/map.h \
|
||||
src/texturecache.h src/actiontextbuilder.h \
|
||||
src/animation.h src/trap.h src/gamecontroller.h \
|
||||
src/event.h src/effect_util.h src/steam/steamworks_api_wrapper.h \
|
||||
src/defines.h
|
||||
|
||||
src/pointer.o: src/pointer.c src/pointer.h src/sprite.h \
|
||||
src/texture.h src/position.h src/camera.h \
|
||||
src/roommatrix.h src/timer.h src/vector2d.h \
|
||||
src/input.h src/util.h src/particle_engine.h
|
||||
|
||||
src/position.o: src/position.c src/position.h src/defines.h
|
||||
|
||||
src/projectile.o: src/projectile.c src/projectile.h src/sprite.h \
|
||||
src/texture.h src/position.h src/camera.h \
|
||||
src/roommatrix.h src/timer.h \
|
||||
src/vector2d.h src/defines.h src/map_room_modifiers.h \
|
||||
src/input.h src/update_data.h src/player.h \
|
||||
src/map.h src/gui.h src/config.h \
|
||||
src/util.h src/texturecache.h src/dimension.h \
|
||||
src/stats.h src/actiontext.h src/skill.h \
|
||||
src/linkedlist.h src/artifact.h src/monster.h \
|
||||
src/doorlocktype.h src/particle_emitter.h src/mixer.h \
|
||||
src/gamestate.h src/item_builder.h src/item.h \
|
||||
src/random.h src/object.h src/effect_util.h
|
||||
|
||||
src/random.o: src/random.c src/time.h src/random.h
|
||||
|
||||
src/roommatrix.o: src/roommatrix.c src/defines.h src/config.h \
|
||||
src/roommatrix.h src/position.h src/camera.h \
|
||||
src/timer.h src/vector2d.h \
|
||||
src/map_room_modifiers.h src/input.h src/util.h \
|
||||
src/map.h src/linkedlist.h src/sprite.h src/texture.h \
|
||||
src/monster.h src/stats.h src/actiontext.h \
|
||||
src/player.h src/doorlocktype.h src/particle_emitter.h \
|
||||
src/skill.h src/artifact.h src/object.h \
|
||||
src/item.h src/update_data.h src/gui.h
|
||||
|
||||
src/save.o: src/save.c src/save.h src/player.h \
|
||||
src/sprite.h src/stats.h \
|
||||
src/actiontext.h src/camera.h src/skill.h \
|
||||
src/linkedlist.h src/input.h src/artifact.h \
|
||||
src/db.h src/defines.h src/config.h
|
||||
|
||||
src/screen.o: src/screen.c src/screen.h src/texture.h \
|
||||
src/dimension.h \
|
||||
src/position.h src/camera.h src/linkedlist.h \
|
||||
src/sprite.h src/roommatrix.h src/timer.h \
|
||||
src/vector2d.h src/util.h src/hiscore.h \
|
||||
src/player.h src/stats.h src/actiontext.h \
|
||||
src/skill.h src/input.h
|
||||
|
||||
src/screenresolution.o: src/screenresolution.c src/defines.h src/config.h \
|
||||
src/util.h src/screenresolution.h
|
||||
|
||||
src/settings.o: src/settings.c src/settings.h src/util.h \
|
||||
src/defines.h src/config.h
|
||||
|
||||
src/skill.o: src/skill.c src/texturecache.h src/texture.h \
|
||||
src/dimension.h src/position.h \
|
||||
src/camera.h src/skill.h src/roommatrix.h \
|
||||
src/defines.h src/map_room_modifiers.h src/input.h \
|
||||
src/sprite.h src/timer.h src/vector2d.h \
|
||||
src/util.h src/player.h src/stats.h \
|
||||
src/actiontext.h src/linkedlist.h src/artifact.h \
|
||||
src/config.h src/monster.h src/doorlocktype.h \
|
||||
src/particle_emitter.h src/mixer.h src/gamestate.h \
|
||||
src/gui.h src/random.h src/particle_engine.h \
|
||||
src/projectile.h src/update_data.h src/map.h \
|
||||
src/item.h src/animation.h src/trap.h \
|
||||
src/tooltip.h src/actiontextbuilder.h
|
||||
|
||||
src/skillbar.o: src/skillbar.c src/defines.h src/config.h \
|
||||
src/skillbar.h src/linkedlist.h src/camera.h \
|
||||
src/position.h src/timer.h src/vector2d.h \
|
||||
src/player.h src/sprite.h src/stats.h \
|
||||
src/actiontext.h src/skill.h src/input.h \
|
||||
src/artifact.h src/texture.h \
|
||||
src/dimension.h src/util.h src/roommatrix.h \
|
||||
src/map_room_modifiers.h src/keyboard.h src/texturecache.h \
|
||||
src/particle_engine.h src/update_data.h src/map.h \
|
||||
src/monster.h src/object.h src/doorlocktype.h
|
||||
|
||||
src/sprite.o: src/sprite.c src/sprite.h src/texture.h \
|
||||
src/dimension.h \
|
||||
src/position.h src/camera.h src/timer.h \
|
||||
src/vector2d.h src/roommatrix.h src/defines.h \
|
||||
src/map_room_modifiers.h src/input.h src/util.h \
|
||||
src/update_data.h src/player.h src/stats.h \
|
||||
src/actiontext.h src/skill.h src/linkedlist.h \
|
||||
src/artifact.h src/map.h src/monster.h \
|
||||
src/object.h src/doorlocktype.h
|
||||
|
||||
src/sprite_util.o: src/sprite_util.c src/sprite_util.h src/sprite.h \
|
||||
src/texture.h src/position.h src/camera.h \
|
||||
src/roommatrix.h src/timer.h
|
||||
|
||||
src/stats.o: src/stats.c src/gui.h \
|
||||
src/linkedlist.h src/sprite.h src/texture.h \
|
||||
src/position.h src/camera.h src/roommatrix.h \
|
||||
src/timer.h src/vector2d.h src/player.h \
|
||||
src/stats.h src/actiontext.h src/skill.h \
|
||||
src/input.h src/artifact.h src/random.h \
|
||||
src/util.h src/defines.h
|
||||
|
||||
src/texture.o: src/texture.c src/texture.h \
|
||||
src/dimension.h src/position.h \
|
||||
src/camera.h src/timer.h src/vector2d.h \
|
||||
src/util.h
|
||||
|
||||
src/texturecache.o: src/texturecache.c src/texturecache.h \
|
||||
src/texture.h src/dimension.h \
|
||||
src/position.h src/camera.h src/hashtable.h \
|
||||
src/defines.h src/config.h src/util.h
|
||||
|
||||
src/time.o: src/time.c src/time.h
|
||||
|
||||
src/timer.o: src/timer.c src/util.h
|
||||
|
||||
src/tooltip.o: src/tooltip.c src/tooltip.h src/camera.h \
|
||||
src/position.h src/timer.h \
|
||||
src/vector2d.h src/sprite.h src/texture.h \
|
||||
src/roommatrix.h src/gui_util.h src/defines.h \
|
||||
src/config.h src/gui.h src/linkedlist.h \
|
||||
src/player.h src/stats.h src/actiontext.h \
|
||||
src/skill.h src/input.h src/artifact.h \
|
||||
src/texturecache.h
|
||||
|
||||
src/trap.o: src/trap.c src/trap.h \
|
||||
src/sprite.h src/texture.h src/position.h \
|
||||
src/camera.h src/roommatrix.h src/timer.h \
|
||||
src/player.h src/stats.h src/actiontext.h \
|
||||
src/skill.h src/linkedlist.h src/input.h \
|
||||
src/artifact.h src/update_data.h src/map.h \
|
||||
src/gui.h src/vector2d.h src/util.h \
|
||||
src/random.h
|
||||
|
||||
src/util.o: src/util.c src/time.h src/defines.h \
|
||||
src/config.h
|
||||
|
||||
src/vector2d.o: src/vector2d.c
|
||||
|
||||
bh_random/src/bh_random.o:
|
||||
@g++ -c bh_random/src/bh_random.cpp -o bh_random/src/bh_random.o $(CFLAGS)
|
||||
|
||||
|
||||
# prepare an archive for the program
|
||||
release:
|
||||
@echo "Creating release files..."
|
||||
@mkdir -p release/breakhack
|
||||
@cp -r release_files/* release/breakhack/
|
||||
@cp -r data release/breakhack/
|
||||
@cp -r assets release/breakhack/
|
||||
@cp breakhack release/breakhack/
|
||||
@strip release/breakhack/breakhack
|
||||
@cp README.md release/breakhack/
|
||||
@cp README_Amiga.md release/breakhack/
|
||||
@cp LICENSE.txt release/breakhack/
|
||||
@cp CREDITS.md release/breakhack/
|
||||
@echo "Creating release archive..."
|
||||
@lha -aeqr3 a breakhack-OS4.lha release/
|
||||
@echo "Clean release files..."
|
||||
@delete release ALL QUIET FORCE
|
||||
|
61
README.md
61
README.md
|
@ -1,8 +1,14 @@
|
|||
[![Build Status](https://travis-ci.org/LiquidityC/breakhack.svg?branch=master)](https://travis-ci.org/LiquidityC/breakhack)
|
||||
[![Build Status](https://ci.appveyor.com/api/projects/status/2nvna97cmm4cf535?svg=true)](https://ci.appveyor.com/project/LiquidityC/breakhack)
|
||||
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/fc02d56fa7194e61b2c7d260fd2e4186)](https://www.codacy.com/app/LiquidityC/breakhack?utm_source=github.com&utm_medium=referral&utm_content=LiquidityC/breakhack&utm_campaign=Badge_Grade)
|
||||
[![CodeFactor](https://www.codefactor.io/repository/github/liquidityc/breakhack/badge/master)](https://www.codefactor.io/repository/github/liquidityc/breakhack/overview/master)
|
||||
<!--[![Coverity Scan](https://scan.coverity.com/projects/15218/badge.svg)](https://scan.coverity.com/projects/liquidityc-breakhack)-->
|
||||
[![maintenance](https://img.shields.io/badge/maintenance-passively--maintained-orange)](https://img.shields.io/badge/maintenance-passively--maintained-orange)
|
||||
[![Build Status](https://travis-ci.org/Oliveshark/breakhack.svg?branch=master)](https://travis-ci.org/Oliveshark/breakhack)
|
||||
[![Build status](https://ci.appveyor.com/api/projects/status/2a18npdntkmlx3dc?svg=true)](https://ci.appveyor.com/project/LiquidityC/breakhack)
|
||||
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/fc02d56fa7194e61b2c7d260fd2e4186)](https://www.codacy.com/app/LiquidityC/breakhack?utm_source=github.com&utm_medium=referral&utm_content=Oliveshark/breakhack&utm_campaign=Badge_Grade)
|
||||
[![CodeFactor](https://www.codefactor.io/repository/github/oliveshark/breakhack/badge/dev)](https://www.codefactor.io/repository/github/oliveshark/breakhack/overview/master)
|
||||
<!--[![Coverity Scan](https://scan.coverity.com/projects/15218/badge.svg)](https://scan.coverity.com/projects/oliveshark-breakhack)-->
|
||||
[![GitHub issues](https://img.shields.io/github/issues/oliveshark/breakhack.svg)](https://github.com/oliveshark/breakhack/issues)
|
||||
[![GitHub closed issues](https://img.shields.io/github/issues-closed/oliveshark/breakhack.svg)](https://github.com/oliveshark/breakhack/issues)
|
||||
![GitHub (pre-)release](https://img.shields.io/github/release/oliveshark/breakhack/all.svg)
|
||||
[![Github All Releases](https://img.shields.io/github/downloads/oliveshark/breakhack/total.svg)](https://github.com/oliveshark/breakhack/releases)
|
||||
[![HitCount](http://hits.dwyl.io/oliveshark/breakhack.svg)](http://hits.dwyl.io/oliveshark/breakhack)
|
||||
|
||||
Something in the ways of a roguelike
|
||||
================================
|
||||
|
@ -19,26 +25,30 @@ I wanted to practice C and I'm comfortable using SDL2. The assets
|
|||
are graciously taken from the web. More info in the README in the
|
||||
assets folder.
|
||||
|
||||
Future
|
||||
Download
|
||||
--------
|
||||
This game is available in the [steam store](https://store.steampowered.com/app/931040/BreakHack/) (release Okt 2018).
|
||||
If you enjoy the game and want a properly installed, signed copy of the game with achievements and
|
||||
global highscores you are most welcome to purchase it there.
|
||||
If you feel like getting a free copy you can download and compile from here.
|
||||
|
||||
Issues
|
||||
------
|
||||
I'm planning on releaseing this game on Steam once I'm happy with it.
|
||||
Not to get rich, mostly because I think it will look nice on my resumé.
|
||||
the code will remain open source under GPLv3 even after a possible Steam
|
||||
release. So you'll still be able to download and compile it yourself if you
|
||||
can and want to.
|
||||
I'd prefer if issues could be handled here on github. Either check the list if your particular problem is reported
|
||||
otherwise create a new issue. Support questions can be submitted as issues as well, I haven't figured out how I want to
|
||||
work with support yet since I haven't received any questions.
|
||||
|
||||
License
|
||||
-------
|
||||
BreakHack is released under two different licenses.
|
||||
|
||||
- The source code is released under [GPLv3](https://github.com/oliveshark/breakhack/blob/master/LICENSE.txt)
|
||||
- The Steam release is released under the [Steam subscriber agreement](https://store.steampowered.com/subscriber_agreement/)
|
||||
|
||||
Compile
|
||||
-------
|
||||
Apart from basic compile tools (*GCC/Clang, Make*) you'll also need to install **lua, sdl2, sdl2-image, sdl2-ttf, sdl2-mixer** (If on a debian based dist you need to install the *dev* packages).
|
||||
Optionally you can also install **cppcheck** and **physfs**
|
||||
|
||||
Once that is done run the following:
|
||||
```bash
|
||||
mkdir _build
|
||||
cd _build
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug .. # Build type flag is optional
|
||||
make
|
||||
```
|
||||
* [Linux](LINUX_BUILD_INSTRUCTIONS.md)
|
||||
* [Windows (Visual Studio)](MSVC_BUILD_INSTRUCTIONS.md)
|
||||
|
||||
Contribute
|
||||
----------
|
||||
|
@ -46,7 +56,14 @@ Have an idea and able to implement it? Fork and send me a pull request and
|
|||
I'll check it out. If I like it I will add it. If it's a big thing I'll add
|
||||
your name to the credits list (once I add it in game).
|
||||
|
||||
If you do contribute something you should be aware that if your PR is merged
|
||||
into the master code-base your code will eventually make it out with the Steam version
|
||||
of the game. I don't make any revenue from those sales so don't expect any other compensation
|
||||
than a "I have code on Steam" feeling. Which is quite nice and also why I decided to release
|
||||
on Steam.
|
||||
|
||||
Links
|
||||
-----
|
||||
|
||||
- [https://liquidityc.itch.io/breakhack](https://liquidityc.itch.io/breakhack)
|
||||
- [Itch.io](https://store.steampowered.com/app/931040/BreakHack/)
|
||||
- [Steam](https://liquidityc.itch.io/breakhack)
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
# breakhack for AmigaOS 4.1 FE
|
||||
|
||||
breakhack is a small roguelike game for having some good time, while
|
||||
you wait for your amiga to compile or render a screen. It is developed
|
||||
by Linus Probert and you can find it for various platforms on Steam.
|
||||
|
||||
## Installation
|
||||
|
||||
Extract the archive wherever you want and run the *breakhack* binary.
|
||||
|
||||
## I would like to thank
|
||||
|
||||
- Linus Probert for creating this awesome game and open sourcing it
|
||||
- Capehill for his tireless work on SDL port for AmigaOS 4.1 FE
|
||||
- Roman "kas1e" Kargin and Nouvel "HunoPPC" Hugues for their help
|
||||
with libphysfs
|
||||
|
||||
## Known issues
|
||||
There are some issues with the Fullscreen graphics, depending which
|
||||
Renderer driver is used. I might fix them in the future.
|
||||
|
||||
## Support
|
||||
|
||||
If you enjoy what I am doing and would like to keep me up during the night,
|
||||
please consider to buy me a coffee at:
|
||||
https://ko-fi.com/walkero
|
||||
|
||||
## Known issues
|
||||
|
||||
You can find the known issues at
|
||||
https://git.walkero.gr/walkero/breakhack/issues
|
||||
|
||||
# Changelog
|
||||
|
||||
## [4.0.3r2] - 2023-07-04
|
||||
### Changed
|
||||
- Compiled with latest SDL 2.0.28 that has a better support for 16bit
|
||||
screens. Now it works under Qemu. Tested with Software rendering
|
||||
|
||||
### Fixed
|
||||
- Fixed the hiscore date. Now it is saved on UTC +8 years which is
|
||||
the Amiga epoch diff against the unix one. This doesn affect the
|
||||
old hi-scores though
|
||||
|
||||
## [4.0.3r1] - 2022-12-21
|
||||
### Added
|
||||
- First release for AmigaOS 4
|
||||
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 548 B |
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 321 B |
|
@ -0,0 +1,7 @@
|
|||
The image files contained in this folder are created by Linus Probert (author
|
||||
of BreakHack).
|
||||
|
||||
They are either modifications of the DanwLike tileset or completely original
|
||||
content. Feel free to use them as you please. The images that are combined
|
||||
from DawnLike assets should be handled under the same licensing rights as the
|
||||
original works. The others are completely unencumbered.
|
Binary file not shown.
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,29 @@
|
|||
cmake_minimum_required(VERSION 3.1)
|
||||
project(bh_random CXX)
|
||||
|
||||
add_definitions(-std=c++11)
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif ()
|
||||
|
||||
add_library(bh_random STATIC
|
||||
src/bh_random.cpp
|
||||
)
|
||||
|
||||
IF ( MSVC )
|
||||
MESSAGE ( STATUS "Setting MSVC MT switches")
|
||||
string (REPLACE
|
||||
"/MDd"
|
||||
"/MTd"
|
||||
CMAKE_C_FLAGS_DEBUG
|
||||
${CMAKE_C_FLAGS_DEBUG}
|
||||
)
|
||||
string (REPLACE
|
||||
"/MDd"
|
||||
"/MTd"
|
||||
CMAKE_C_FLAGS_RELEASE
|
||||
${CMAKE_C_FLAGS_RELEASE}
|
||||
)
|
||||
endif ()
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* BreakHack - A dungeone crawler RPG
|
||||
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <random>
|
||||
#include <climits>
|
||||
extern "C" {
|
||||
#include "bh_random.h"
|
||||
}
|
||||
|
||||
static std::mt19937 generator;
|
||||
static std::mt19937 map_generator;
|
||||
|
||||
extern "C" void
|
||||
bh_srand(unsigned int seed)
|
||||
{
|
||||
generator.seed(seed);
|
||||
}
|
||||
|
||||
|
||||
extern "C" unsigned int
|
||||
bh_rand(void)
|
||||
{
|
||||
return generator();
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
bh_map_srand(unsigned int seed)
|
||||
{
|
||||
map_generator.seed(seed);
|
||||
}
|
||||
|
||||
extern "C" unsigned int
|
||||
bh_map_rand(void)
|
||||
{
|
||||
return map_generator();
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* BreakHack - A dungeone crawler RPG
|
||||
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
void
|
||||
bh_srand(unsigned int);
|
||||
|
||||
unsigned int
|
||||
bh_rand(void);
|
||||
|
||||
void
|
||||
bh_map_srand(unsigned int);
|
||||
|
||||
unsigned int
|
||||
bh_map_rand(void);
|
|
@ -64,6 +64,14 @@
|
|||
# (To distribute this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(SDL2_ARCH_64 TRUE)
|
||||
set(SDL2_PROCESSOR_ARCH "x64")
|
||||
else()
|
||||
set(SDL2_ARCH_64 FALSE)
|
||||
set(SDL2_PROCESSOR_ARCH "x86")
|
||||
endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
|
||||
SET(SDL2_SEARCH_PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
|
@ -87,7 +95,7 @@ FIND_LIBRARY(SDL2_LIBRARY_TEMP
|
|||
NAMES SDL2
|
||||
HINTS
|
||||
$ENV{SDL2DIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATH_SUFFIXES lib64 lib lib/${SDL2_PROCESSOR_ARCH}
|
||||
PATHS ${SDL2_SEARCH_PATHS} ${SDL2_INCLUDE_DIR}/../..
|
||||
)
|
||||
|
||||
|
@ -101,7 +109,7 @@ IF(NOT SDL2_BUILDING_LIBRARY)
|
|||
NAMES SDL2main
|
||||
HINTS
|
||||
$ENV{SDL2DIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATH_SUFFIXES lib64 lib lib/${SDL2_PROCESSOR_ARCH}
|
||||
PATHS ${SDL2_SEARCH_PATHS}
|
||||
)
|
||||
ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
|
||||
|
|
|
@ -28,6 +28,14 @@
|
|||
# See the License for more information.
|
||||
#=============================================================================
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(SDL2_ARCH_64 TRUE)
|
||||
set(SDL2_PROCESSOR_ARCH "x64")
|
||||
else()
|
||||
set(SDL2_ARCH_64 FALSE)
|
||||
set(SDL2_PROCESSOR_ARCH "x86")
|
||||
endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
|
||||
if(NOT SDL2_TTF_INCLUDE_DIR AND SDL2TTF_INCLUDE_DIR)
|
||||
set(SDL2_TTF_INCLUDE_DIR ${SDL2TTF_INCLUDE_DIR} CACHE PATH "directory cache
|
||||
entry initialized from old variable name")
|
||||
|
@ -48,7 +56,7 @@ find_library(SDL2_TTF_LIBRARY
|
|||
HINTS
|
||||
ENV SDLTTFDIR
|
||||
ENV SDLDIR
|
||||
PATH_SUFFIXES lib
|
||||
PATH_SUFFIXES lib lib/${SDL2_PROCESSOR_ARCH}
|
||||
)
|
||||
|
||||
if(SDL2_TTF_INCLUDE_DIR AND EXISTS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h")
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./
|
||||
exec ./breakhack
|
|
@ -0,0 +1,20 @@
|
|||
f5a88fc Introduces texture blending
|
||||
52913af Completes #42 Add boss 2 & 3
|
||||
449cc36 Fixes some minor buggs
|
||||
f67aab0 Completes #43 Add win state
|
||||
8c261fd Added the undead monsters for level > 10
|
||||
6326a64 Begins #42 Add boss 2 & 3
|
||||
f1b0045 Introduces the "orc levels"
|
||||
ffe1736 Minor buggfixes and typos
|
||||
8bf9329 Version bump and badges
|
||||
8c25693 Moves sqlite3 files to separate dir
|
||||
bec9eb4 Fixed a typo in skill tooltip
|
||||
43f021a Created an FPS counter for debug mode
|
||||
dbc36aa Fixes #41, Minimap
|
||||
c390c02 Fixes #40, Prevent adjecant traps before lvl 4
|
||||
9ef97c0 Fixes #38, Artifact inventory
|
||||
358c0c7 Fixes #37 and #39 Adds tooltips to everything
|
||||
5f754d5 Merge branch 'master' into dev
|
||||
30058ea Creates gui_util and moves some code out from gui.c
|
||||
854f2c0 Prevent levels > 10 from crashing the game.
|
||||
549f47a Minor code fixes and a slight tweak to the blue color
|
|
@ -0,0 +1,5 @@
|
|||
6811c42 Patch version raised to
|
||||
e796fff Prepare release script for real versions
|
||||
ae44d5c Adds minimal Steam fiddling protection
|
||||
6e3343a License stuff and README updates
|
||||
899d2e5 Update to build env
|
|
@ -0,0 +1,8 @@
|
|||
0730eb4 Disable text input since this is on by default in SDL2.0
|
||||
7333d3d Update issue templates
|
||||
70cc79f Merge pull request #47 from Oliveshark/add-code-of-conduct-1
|
||||
bdbb10b Create CODE_OF_CONDUCT.md
|
||||
75660a5 Update to readme.
|
||||
5d1490b Another README badge fix
|
||||
aefbd95 Update readme to match new github url
|
||||
90603b4 Fix what my bad build script broke
|
|
@ -0,0 +1,93 @@
|
|||
cb6bd03 Patch version raised to 2
|
||||
b0f2936 Removes beta release type
|
||||
76c2f90 Fixes a compiler warning and arcade mode coverage
|
||||
8233841 Adds burst sound to eldritch blast
|
||||
c2eae7a Adds arcade game leaderboard
|
||||
f53703d Introduces arcade mode
|
||||
0f66b0f Adds the game type select menu
|
||||
7005239 Fixed commit msg in version script
|
||||
7991e7c Fixes COMPLETED state for quick games
|
||||
aea9995 Reduved stun from trip skill
|
||||
a38a21a Incorporates quickplay leaderboard
|
||||
deb4638 Fixes a bad help text
|
||||
120f8d7 Some tweaks to the rogue character
|
||||
5985c3e Fixed a bad pointer reset
|
||||
9968b37 Fixes another memory leak
|
||||
7e71fcc Build updates
|
||||
dd77f29 Fixes a typo
|
||||
51d7b67 Completed the QUICK_GAME mode
|
||||
97c95da Adds lua support for quick mode
|
||||
f895fdb Add a title to char select menu.
|
||||
1a0d806 Introduces menu option descriptions
|
||||
f5a1c2f Removes a memory leak
|
||||
d2fe3fc Fixes a codacy warning
|
||||
bcdc9c1 Update README.md
|
||||
8d09e8a Adds the new steam achievement and leaderboards
|
||||
d034a69 Finnished up with the rogue
|
||||
94ec8cf Removed bad options in .clang_complete
|
||||
669a2fb Merge branch 'master' into dev
|
||||
feed0e2 Completes crumbling rooms.
|
||||
6e6f28d Prevent tiles with chests from falling.
|
||||
fd8799f Prevent tiles with objects on them from falling.
|
||||
ee56143 Initial implementation of the falling tiles room modifier.
|
||||
f65bdd0 Add license header to gamecontroller files
|
||||
a803578 Fixes a gcc warning
|
||||
8792504 Adds the backstab skill icon
|
||||
da3ff1a Small thumbstick tweak
|
||||
850aae3 Adds controller haptics
|
||||
423ff73 Fixes a leak and begins restructure of controller code
|
||||
2e0a88e Switches the old MapTile texture system to use sprites instead
|
||||
53151b6 Adds the phase skill icon
|
||||
e6b5b76 Includes attempt to determine if PS3 controller aswell as PS4
|
||||
894e3ba Merge branch 'master' into dev
|
||||
c8900e8 Controller button rendering based on controller type
|
||||
06d2da1 Controllers are working
|
||||
3143236 Completely untested controller mappings.
|
||||
bb7f9ef A beginning to controller support
|
||||
2919ebf Adds controller button support for skillbar
|
||||
c3b2b6f Fixed a typo and made controller layout toggleable.
|
||||
e526c03 Completed the button implementation for the help tooltips
|
||||
e845195 Got this texture stuff working
|
||||
0723f62 New approach where we render button textures in tooltips.
|
||||
a162646 More font modifications
|
||||
60374c9 Font updates
|
||||
2b02ae5 An attempt to group files in msvc
|
||||
a4cb234 Re-aligned the credits file
|
||||
e59f04b Merge branch 'dev' into feature/phase-skill
|
||||
2d25e42 Merge branch 'master' into dev
|
||||
c7c5346 Completes testing of phase and fixes some errors
|
||||
97ad1dd Introduced the phase artifact
|
||||
0dcb658 Merge branch 'dev' into feature/phase-skill
|
||||
9610609 Attempt to bring the mouse menu click back
|
||||
ee5ed14 Implementd the skill. Still not tested.
|
||||
b4fd2cb Added the phase tooltip.
|
||||
742d6e2 Untested phase code. Needs more work
|
||||
35c3be4 Removed a type warning
|
||||
3bbe917 Merge branch 'master' into dev
|
||||
c97688a Incorporate artifacts in rogue skills
|
||||
47082da Build env changes
|
||||
3301437 Tuned the backstab skill slightly
|
||||
743e4a3 Implemented the backstab skill
|
||||
81ccf8a Fixed a windy room issue
|
||||
083834d Maint: Remove CI compiler warnings
|
||||
dc6b816 Add slash animation to trip skill
|
||||
87b2b9d Fix pits added to room
|
||||
5648be4 Merge branch 'master' into dev
|
||||
5d5170c Version bump for future release
|
||||
583a7d0 Fixes some minor bugs caused by coding without testing
|
||||
60359d8 Untested implementation of the TRIP skill
|
||||
dbf9fe3 Maint: Removed duplicate code
|
||||
0fc1fed Maint: Clean up monster.c
|
||||
e1b3364 Maint: Even more cleanup
|
||||
620a7e3 Maint: Less complex main
|
||||
983875d Maint: Cleaned up a complex function
|
||||
e293c21 Rogue preparation
|
||||
0ca70c7 Add the dagger skill to the rogue
|
||||
c39f05d Fixed the player menu
|
||||
02a4407 Got a bit further
|
||||
f246c57 Broken commit
|
||||
367be69 Buggfix: Prevent clip switching on falling sprite
|
||||
988b53a Outline the rogue skillset
|
||||
03b60f6 Merge branch 'master' into dev
|
||||
5043a86 Cleaned up main a bit and moved some code
|
||||
cb732a8 Adds possibility to push monsters into pits and traps.
|
|
@ -0,0 +1,2 @@
|
|||
8ab527c Makes monsters fall when the tile they are on falls
|
||||
8e39ff8 Fix releasenotes for v2.0.2
|
|
@ -0,0 +1,3 @@
|
|||
4d01251 Merge branch 'master' into dev
|
||||
9299087 Updates PhysicsFS to latest stable-3.0
|
||||
cb2510c Rename physfs folder
|
|
@ -0,0 +1,16 @@
|
|||
ee4dd27 Patch version raised to 1
|
||||
5ee20c9 Shifted to safer time functions and utc time
|
||||
563ebf9 Adds another build fix
|
||||
3533d5c Fixes build again
|
||||
97b097a Fixes builds
|
||||
685bf97 Makes the custom random generator deterministic across platforms
|
||||
cc375bb Implements control over lua random numbers
|
||||
1205856 Attempt att syncing random generation
|
||||
d1efa84 Create new leaderboards with attribute 'Descending'
|
||||
2775780 Makes weekly leaderboards creatable from app.
|
||||
269b25b Removes a mingw warning
|
||||
72c3817 Adds weekly challenge seed play and leaderboard saving
|
||||
1212b1a Weekly challenge option added to play menu
|
||||
ce2a348 Generate seeds from the core seed so that levels will look different.
|
||||
bc9d37e Connects the random seed through all the generators
|
||||
3c7dcb5 Begins new random impl
|
|
@ -0,0 +1,9 @@
|
|||
a03aec7 Handles the second mingw special case which I kept forgetting.
|
||||
0de018f Fix mingw preprocessor define from cmake
|
||||
3eeb4d0 Include mingw32 64bit in the exclusion
|
||||
5f369da Fixed preprocessor command for mingw
|
||||
c98e6e6 Fix wonky mingw errors in appveyor
|
||||
499f015 Only use gmtime_s for MSVC
|
||||
9b9a0ca Fixed bad include
|
||||
926054b Ensure that we have seed when making a map
|
||||
49b7ebb Include patch notes for v2.2.1
|
|
@ -0,0 +1,4 @@
|
|||
e455523 Update README.md
|
||||
791dd7e Removes cppcheck warning
|
||||
b08ef10 Code maintenance and cleanup
|
||||
fffcac1 Makes sure til effects and items apply after backstab
|
|
@ -0,0 +1 @@
|
|||
c3464eb Fixes a typo
|
|
@ -0,0 +1,60 @@
|
|||
c4811ed Fixes checksumtool output again
|
||||
eceb241 Removes useless text from checksumtool output
|
||||
cea891f Move checksum configuration to CMakeLists.txt and config.h
|
||||
8e28230 Fixes release notes
|
||||
53703f1 Patch version raised to 1
|
||||
ce182ad Updates checksums
|
||||
ebfe271 Fixes compile error and some graphical issues
|
||||
2ae6ada Completes locked room generation
|
||||
18987e2 Incomplete monster key fixes
|
||||
59a1e81 Implementation of keys. Completely untested
|
||||
1065216 Include all files in pack files
|
||||
68533f0 Remove memory leaks from map destruction
|
||||
38dc3de Merge branch 'dev' of github.com:liquidityc/breakhack into dev
|
||||
beda4f6 Reduces fairy frequency
|
||||
e50d40f Adds doors and greater chance of walls
|
||||
0983bd1 Fixes a weird issue with missing code
|
||||
184b42f Fixes door logic
|
||||
e42e024 Adds some door logic
|
||||
756afba Separates walls from regular tiles
|
||||
40a20e9 Adapts fopen/fopen_s to WIN32/GCC compile
|
||||
af930f6 Fixes win compiler warnings
|
||||
c4fd16d Updated dll checksums for windows build
|
||||
f840b28 Adds mediocre crack protection
|
||||
7fbeaa3 Introduced base structure for doors in maps
|
||||
3e43c30 Adds funny casting to avoid pedantic ISO C warning
|
||||
fd3a625 Adds monster bloodlust
|
||||
d749861 Make jumbled rooms more likely
|
||||
7ab5ece Nicer wall decorations on interior walls
|
||||
8c9622d Shopkeeper now has bodyguards next time you meet after kiling him
|
||||
af0c616 Adds juice
|
||||
46fbdc1 Fixed jumble layout logic
|
||||
b40c54a Layouts can now be jumbled with each other
|
||||
8f20f36 Lighting on wall layouts and aggro shopkeepers
|
||||
3ba33d8 Adds light tiles to layout files and a shopkeeper
|
||||
447c1a7 Monster shopkeeper logic
|
||||
7e1dffb Shops implemented
|
||||
6009aa1 Merge branch 'dev' into shops
|
||||
9b4a7b6 Removes crazy old bug that never presented itself before
|
||||
63812fb More wall layouts and cordinated walls
|
||||
c6a022e Moved text sprite logic to sprite_util
|
||||
06ca6c3 Not finnished yet, commit
|
||||
bab5fd7 Merge branch 'dev' into shops
|
||||
68f4409 Add amt sprite to all items where value != 0
|
||||
959fae1 Add value sprite to items.
|
||||
ca41520 Wall layouts added to regular build
|
||||
88f4703 Some more fence layouts
|
||||
486c1bb Merge branch 'dev' into shops
|
||||
206f95f Fences and walls in layout files
|
||||
1c4e600 Wall layout data
|
||||
57a1688 Merge branch 'dev' into shops
|
||||
13ca11c Begins refactoring of layout parser to accomodate more layout details
|
||||
33efba8 Merge branch 'dev' into shops
|
||||
5d61a91 Split pit layout logic into separate file
|
||||
6542e4f Moves item update to its own function
|
||||
7b47c6a Completes buyable items
|
||||
16d9035 Merge branch 'dev' into shops
|
||||
4054c37 Ignore vscode_build dir
|
||||
ad227f1 A start to "priced" items
|
||||
37ba189 Suppress cppcheck issues
|
||||
645a02c Ignore .vscode folder
|
|
@ -0,0 +1,6 @@
|
|||
c2b8fd4 Adds key pickup SFX
|
||||
7a59d15 Don't add walls to crumbling rooms before lvl 4
|
||||
c9fde8d Updated releasenotes
|
||||
c4811ed Fixes checksumtool output again
|
||||
eceb241 Removes useless text from checksumtool output
|
||||
cea891f Move checksum configuration to CMakeLists.txt and config.h
|
|
@ -0,0 +1,40 @@
|
|||
392edd8 Updates blink tooltip to include item pickups.
|
||||
6584981 remove unnecessary pickup
|
||||
d2cf797 Mage blink skill pickup items in the path #60
|
||||
78e9413 Fix : Missing with vampiric blow doesn't seem to trigger a 'Dodge' action text #59
|
||||
af957eb Disables mouse square rendering for all classes
|
||||
1d988d7 Fixes working explosions and artifacts
|
||||
68f4e15 Fixes returning daggers and resets erupt attack
|
||||
7f232be A beginning to the new exploding artifacts
|
||||
12aff9a Fixes erupt so it has a base push of 1
|
||||
2dc25c9 Adds the DAGGER_MAGNET artifact
|
||||
5e67ca7 Removes stun from backstab skill
|
||||
cac3fea Altered the vampiric blow icon slightly
|
||||
9ed80ac Removes erupt test code
|
||||
05cbce0 Adds vampiric blow icon
|
||||
6c135c6 Adds gui display for held keys
|
||||
fb031e2 Bumps version
|
||||
b861e6e Fixes SENTINEL monsters from ignoring forced fear
|
||||
046551a Changes ERUPT to cause fear instead of bleeding
|
||||
8fb1bbc Fixes bug with erupt pushing direction
|
||||
35164a9 Introduces vampiric blow
|
||||
dd3e84d Makes critical hits cause bleeding
|
||||
8f21e8b Prevents skill radius from impacting push back range
|
||||
2b74316 Updates erupt tooltip to mention push back
|
||||
7ddaab8 Make erupt always push back 1 tile without any artifacts
|
||||
43ca8f4 Fixes #58 - Game crash with AOE attacks
|
||||
ef5cd4e Adds PUSH_BACK and SKILL_RADIUS effects to erupt skill
|
||||
b00e607 Start with debug gold
|
||||
67e29d6 Added the SKILL_RADIUS artifact (not used yet)
|
||||
81e7df1 Adds skill icons for the two mage skills
|
||||
18effa2 Rogue backstab skill now triggers bleeding as well
|
||||
c043ad0 Implements the erupt skill
|
||||
223a3b0 Implements the blink skill
|
||||
2ca78e2 Adds monster bleed damage every turn
|
||||
0476d4d Introduces particle emitters on monsters
|
||||
826cbe1 A quick start to the Mage
|
||||
fcc6527 Minor fix
|
||||
b409b76 Improved build instruction structure
|
||||
b075390 React to PR feedback
|
||||
86e6f66 Adds Windows compilation instructions
|
||||
c0a4a4e Make ninja builds smoother
|
|
@ -0,0 +1,2 @@
|
|||
6d323ca Adds steam achievements and LB for the Mage class
|
||||
9aefed0 Adds an dev env setup script
|
|
@ -0,0 +1 @@
|
|||
4edeb17 Fixes cross save problems due to architecture differences
|
|
@ -0,0 +1 @@
|
|||
e636ec1 Don't delete saves from other architectures on death
|
|
@ -1,17 +1,19 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Get the current patch version
|
||||
LAST_VERSION=$(egrep -o 'breakhack_PATCH_VERSION [0-9]+' CMakeLists.txt | awk '{print $2}')
|
||||
NEXT_VERSION=$((LAST_VERSION + 1))
|
||||
MAJOR_VERSION=$(egrep -o 'breakhack_MAJOR_VERSION [0-9]+' CMakeLists.txt | awk '{print $2}')
|
||||
MINOR_VERSION=$(egrep -o 'breakhack_MINOR_VERSION [0-9]+' CMakeLists.txt | awk '{print $2}')
|
||||
LAST_PATCH_VERSION=$(egrep -o 'breakhack_PATCH_VERSION [0-9]+' CMakeLists.txt | awk '{print $2}')
|
||||
NEXT_PATCH_VERSION=$((LAST_PATCH_VERSION + 1))
|
||||
|
||||
LAST_TAG=early-access-v$LAST_VERSION
|
||||
NEXT_TAG=early-access-v$NEXT_VERSION
|
||||
LAST_TAG=v$MAJOR_VERSION.$MINOR_VERSION.$LAST_PATCH_VERSION
|
||||
NEXT_TAG=v$MAJOR_VERSION.$MINOR_VERSION.$NEXT_PATCH_VERSION
|
||||
|
||||
# Update the version and create release notes
|
||||
sed -i -e "s/breakhack_PATCH_VERSION [0-9]\+/breakhack_PATCH_VERSION $NEXT_VERSION/" CMakeLists.txt
|
||||
sed -i -e "s/breakhack_PATCH_VERSION [0-9]\+/breakhack_PATCH_VERSION $NEXT_PATCH_VERSION/" CMakeLists.txt
|
||||
git log --oneline $LAST_TAG..HEAD > build/releasenotes/$NEXT_TAG.txt
|
||||
git add build/releasenotes/$NEXT_TAG.txt
|
||||
git commit -a -m"Patch version raised to $NEXT_VERSION"
|
||||
git commit -a -m"Patch version raised to $NEXT_PATCH_VERSION"
|
||||
|
||||
# Create the tag
|
||||
git tag $NEXT_TAG
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
#!/bin/sh
|
||||
|
||||
mkdir -p _build/debug
|
||||
mkdir -p _build/release
|
||||
|
||||
cd _build/debug
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug ../..
|
||||
cd -
|
||||
|
||||
cd _build/release
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ../..
|
||||
cd -
|
|
@ -0,0 +1,33 @@
|
|||
cmake_minimum_required(VERSION 3.1)
|
||||
project(checksum C)
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif ()
|
||||
|
||||
|
||||
add_executable(checksumtool
|
||||
src/checksum.c
|
||||
)
|
||||
target_compile_definitions(checksumtool PUBLIC EXECUTABLE=1)
|
||||
|
||||
add_library(checksum
|
||||
src/checksum.c
|
||||
)
|
||||
|
||||
IF ( MSVC )
|
||||
MESSAGE ( STATUS "Setting MSVC MT switches")
|
||||
string (REPLACE
|
||||
"/MDd"
|
||||
"/MTd"
|
||||
CMAKE_C_FLAGS_DEBUG
|
||||
${CMAKE_C_FLAGS_DEBUG}
|
||||
)
|
||||
string (REPLACE
|
||||
"/MDd"
|
||||
"/MTd"
|
||||
CMAKE_C_FLAGS_RELEASE
|
||||
${CMAKE_C_FLAGS_RELEASE}
|
||||
)
|
||||
endif ()
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
** CHECKSUM.C - Compute the checksum of a file
|
||||
**
|
||||
** public somain demo by Bob Stout
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "checksum.h"
|
||||
|
||||
unsigned
|
||||
checksum(void *buffer, size_t len, unsigned int seed)
|
||||
{
|
||||
unsigned char *buf = (unsigned char *)buffer;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
seed += (unsigned int)(*buf++);
|
||||
return seed;
|
||||
}
|
||||
|
||||
unsigned
|
||||
checksum_fp(FILE *fp)
|
||||
{
|
||||
unsigned int seed = 0;
|
||||
char buf[4096];
|
||||
|
||||
size_t len;
|
||||
do {
|
||||
len = fread(buf, sizeof(char), sizeof(buf), fp);
|
||||
seed = checksum(buf, len, seed);
|
||||
} while (len > 0);
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
#ifdef EXECUTABLE
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
FILE *fp;
|
||||
const char *file;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("You need to provide an input file\n");
|
||||
printf("Example: %s <file>", argv[0]);
|
||||
}
|
||||
file = argv[1];
|
||||
|
||||
if (NULL == (fp = fopen(file, "rb")))
|
||||
{
|
||||
printf("Unable to open %s for reading\n", file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%#x\n", checksum_fp(fp));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* BreakHack - A dungeone crawler RPG
|
||||
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
unsigned
|
||||
checksum(void *buffer, size_t len, unsigned int seed);
|
||||
|
||||
unsigned
|
||||
checksum_fp(FILE *fp);
|
|
@ -1,6 +1,6 @@
|
|||
local room_builder = require "maproombuilder"
|
||||
local module = {}
|
||||
local random = math.random
|
||||
local random = map_random
|
||||
|
||||
local textures = {
|
||||
"Items/Chest0.png",
|
||||
|
|
|
@ -0,0 +1,406 @@
|
|||
local random = map_random
|
||||
local pits = {}
|
||||
local walls = {}
|
||||
local fences = {}
|
||||
local lights = {}
|
||||
local doors = {}
|
||||
local walldecor = {}
|
||||
local chest
|
||||
|
||||
local function readLayoutFile(file)
|
||||
local layoutfile = read_file(file)
|
||||
|
||||
local cleanData = ""
|
||||
for i=1, #layoutfile do
|
||||
local c = layoutfile:sub(i+1, i+1)
|
||||
if c ~= " " and c ~= "\n" and c ~= "\r" then
|
||||
cleanData = cleanData .. c
|
||||
end
|
||||
end
|
||||
|
||||
local matrix = {}
|
||||
for i=0, #cleanData-1 do
|
||||
local c = cleanData:sub(i, i)
|
||||
local col = i % 16
|
||||
local row = (i - col)/16
|
||||
local layout = 1 + (row - (row % 12))/12
|
||||
local row = row % 12
|
||||
if not matrix[layout] then matrix[layout] = {} end
|
||||
if not matrix[layout][col] then matrix[layout][col] = {} end
|
||||
matrix[layout][col][row] = c
|
||||
end
|
||||
|
||||
return matrix;
|
||||
end
|
||||
|
||||
local function has_value(list, char)
|
||||
for _, value in ipairs(list) do
|
||||
if value == char then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function getTileStateFor(matrix, i, j, c)
|
||||
local charList
|
||||
if type(c) == "string" then
|
||||
charList = { c }
|
||||
else
|
||||
charList = c
|
||||
end
|
||||
local above = has_value(charList, matrix[i][j-1])
|
||||
local below = has_value(charList, matrix[i][j+1])
|
||||
local left = has_value(charList, matrix[i-1][j])
|
||||
local right = has_value(charList, matrix[i+1][j])
|
||||
|
||||
local above_left = has_value(charList, matrix[i-1][j-1])
|
||||
local above_right = has_value(charList, matrix[i+1][j-1])
|
||||
local below_left = has_value(charList, matrix[i-1][j+1])
|
||||
local below_right = has_value(charList, matrix[i+1][j+1])
|
||||
|
||||
return above, below, left, right, above_left, above_right, below_left, below_right
|
||||
end
|
||||
|
||||
local function getRandomWallDecorFrom(wallDecorations)
|
||||
return wallDecorations[random(#wallDecorations)]
|
||||
end
|
||||
|
||||
local function setBlockTile(room, matrix, i, j, tiles, char, decor)
|
||||
local above, below, left, right, above_left, above_right, below_left, below_right = getTileStateFor(matrix, i, j, char);
|
||||
|
||||
room.decor[i][j] = nil
|
||||
local tile = nil
|
||||
local decorTile = nil
|
||||
if above and below and left and right then
|
||||
tile = tiles.cross
|
||||
elseif not above and below and left and right then
|
||||
tile = tiles.top_t
|
||||
elseif not below and above and left and right then
|
||||
tile = tiles.bottom_t
|
||||
decorTile = getRandomWallDecorFrom(walldecor.bottom_t)
|
||||
elseif not left and above and below and right then
|
||||
tile = tiles.left_t
|
||||
decorTile = getRandomWallDecorFrom(walldecor.left_t)
|
||||
elseif not right and above and below and left then
|
||||
tile = tiles.right_t
|
||||
decorTile = getRandomWallDecorFrom(walldecor.right_t)
|
||||
elseif not above and not left and right and below then
|
||||
tile = tiles.topleft
|
||||
decorTile = getRandomWallDecorFrom(walldecor.topleft)
|
||||
elseif not above and not right and left and below then
|
||||
tile = tiles.topright
|
||||
decorTile = getRandomWallDecorFrom(walldecor.topright)
|
||||
elseif not below and not left and above and right then
|
||||
tile = tiles.bottomleft
|
||||
decorTile = getRandomWallDecorFrom(walldecor.bottomleft)
|
||||
elseif not below and not right and above and left then
|
||||
tile = tiles.bottomright
|
||||
decorTile = getRandomWallDecorFrom(walldecor.bottomright)
|
||||
elseif not left and not right and below then
|
||||
tile = tiles.left
|
||||
decorTile = getRandomWallDecorFrom(walldecor.left)
|
||||
elseif not above and not below and (left or right) then
|
||||
tile = tiles.top
|
||||
decorTile = getRandomWallDecorFrom(walldecor.top)
|
||||
else
|
||||
tile = tiles.single
|
||||
decorTile = getRandomWallDecorFrom(walldecor.single)
|
||||
end
|
||||
|
||||
room.walls[i][j] = tile
|
||||
if random(8) == 1 and decor then
|
||||
room.decor[i][j] = decorTile
|
||||
end
|
||||
end
|
||||
|
||||
local function setPitTile(room, matrix, i, j)
|
||||
local above, below, left, right, above_left, above_right, below_left, below_right = getTileStateFor(matrix, i, j, "p");
|
||||
|
||||
room.decor[i][j] = nil
|
||||
if not above_left and not above_right and left and right and above then
|
||||
room.tiles[i][j] = pits.innermid
|
||||
elseif not above_left and left and above then
|
||||
room.tiles[i][j] = pits.innerleft
|
||||
elseif not above_right and right and above then
|
||||
room.tiles[i][j] = pits.innerright
|
||||
elseif not left and not above and not right then
|
||||
room.tiles[i][j] = pits.topcrevice
|
||||
elseif not left and not right then
|
||||
room.tiles[i][j] = pits.bottomcrevice
|
||||
elseif not left and not above then
|
||||
room.tiles[i][j] = pits.topleft
|
||||
elseif not right and not above then
|
||||
room.tiles[i][j] = pits.topright
|
||||
elseif not left then
|
||||
room.tiles[i][j] = pits.left
|
||||
elseif not right then
|
||||
room.tiles[i][j] = pits.right
|
||||
elseif not above then
|
||||
room.tiles[i][j] = pits.top
|
||||
else
|
||||
room.tiles[i][j] = pits.center
|
||||
end
|
||||
end
|
||||
|
||||
local function getDoor(matrix, i, j, topDoor, leftDoor)
|
||||
local above, below, left, right, above_left, above_right, below_left, below_right = getTileStateFor(matrix, i, j, { "#", "\"", "/"});
|
||||
if above and below then
|
||||
return leftDoor
|
||||
else
|
||||
return topDoor
|
||||
end
|
||||
end
|
||||
|
||||
local module = {}
|
||||
function module.load_textures(map, wall_xoffset, wall_yoffset)
|
||||
local t_pit0 = add_texture(map, "Objects/Pit0.png")
|
||||
local t_pit1 = add_texture(map, "Objects/Pit1.png")
|
||||
local t_wall = add_texture(map, "Objects/Wall.png")
|
||||
local t_fence = add_texture(map, "Objects/Fence.png")
|
||||
local t_decor0 = add_texture(map, "Objects/Decor0.png")
|
||||
local t_decor1 = add_texture(map, "Objects/Decor1.png")
|
||||
local t_door0 = add_texture(map, "Objects/Door0.png")
|
||||
local t_door1 = add_texture(map, "Objects/Door1.png")
|
||||
|
||||
local yo = (random(5) + random(3)) * (16 * 2)
|
||||
pits = {
|
||||
center = { t_pit0, t_pit1, 16, yo + 16, false, false, false, true },
|
||||
top = { t_pit0, t_pit1, 16, yo, false, false, false, true },
|
||||
left = { t_pit0, t_pit1, 0, yo + 16, false, false, false, true },
|
||||
right = { t_pit0, t_pit1, 32, yo + 16, false, false, false, true },
|
||||
topleft = { t_pit0, t_pit1, 0, yo, false, false, false, true },
|
||||
topright = { t_pit0, t_pit1, 32, yo, false, false, false, true },
|
||||
innerleft = { t_pit0, t_pit1, 80, yo, false, false, false, true },
|
||||
innermid = { t_pit0, t_pit1, 96, yo, false, false, false, true },
|
||||
innerright = { t_pit0, t_pit1, 112, yo, false, false, false, true },
|
||||
topcrevice = { t_pit0, t_pit1, 64, yo, false, false, false, true },
|
||||
bottomcrevice = { t_pit0, t_pit1, 64, yo + 16, false, false, false, true },
|
||||
}
|
||||
|
||||
local xo = wall_xoffset
|
||||
yo = wall_yoffset
|
||||
walls = {
|
||||
topleft = { t_wall, nil, xo + 0, yo, true },
|
||||
top = { t_wall, nil, xo + 16, yo, true },
|
||||
single = { t_wall, nil, xo + 16, yo + 16, true },
|
||||
topright = { t_wall, nil, xo + 32, yo, true },
|
||||
left = { t_wall, nil, xo + 0, yo + 16, true },
|
||||
bottomleft = { t_wall, nil, xo + 0, yo + 32, true },
|
||||
bottomright = { t_wall, nil, xo + 32, yo + 32, true },
|
||||
center = { t_wall, nil, xo + 48, yo, true },
|
||||
top_t = { t_wall, nil, xo + 64, yo, true },
|
||||
left_t = { t_wall, nil, xo + 48, yo + 16, true },
|
||||
cross = { t_wall, nil, xo + 64, yo + 16, true },
|
||||
right_t = { t_wall, nil, xo + 80, yo + 16, true },
|
||||
bottom_t = { t_wall, nil, xo + 64, yo + 32, true },
|
||||
}
|
||||
|
||||
yo = 48 * random(3)
|
||||
fences = {
|
||||
topleft = { t_fence, nil, 0, yo, true },
|
||||
top = { t_fence, nil, 16, yo, true },
|
||||
single = { t_fence, nil, 0, yo + 16, true },
|
||||
topright = { t_fence, nil, 32, yo, true },
|
||||
left = { t_fence, nil, 0, yo + 16, true },
|
||||
bottomleft = { t_fence, nil, 0, yo + 32, true },
|
||||
bottomright = { t_fence, nil, 32, yo + 32, true },
|
||||
center = { t_fence, nil, 48, yo, true },
|
||||
top_t = { t_fence, nil, 64, yo, true },
|
||||
left_t = { t_fence, nil, 48, yo + 16, true },
|
||||
cross = { t_fence, nil, 64, yo + 16, true },
|
||||
right_t = { t_fence, nil, 80, yo + 16, true },
|
||||
bottom_t = { t_fence, nil, 64, yo + 32, true },
|
||||
}
|
||||
|
||||
doors = {
|
||||
door_top_nolock = { t_door0, t_door1, 0, 0, true },
|
||||
door_left_nolock = { t_door0, t_door1, 16, 0, true },
|
||||
door_top_silverlock = { t_door0, t_door1, 32, 0, true, false, false, false, 1 },
|
||||
door_left_silverlock = { t_door0, t_door1, 48, 0, true, false, false, false, 1 },
|
||||
door_top_goldlock = { t_door0, t_door1, 64, 0, true, false, false, false, 2 },
|
||||
door_left_goldlock = { t_door0, t_door1, 80, 0, true, false, false, false, 2 },
|
||||
gate_top_nolock = { t_door0, t_door1, 0, 32, true },
|
||||
gate_left_nolock = { t_door0, t_door1, 16, 32, true },
|
||||
gate_top_silverlock = { t_door0, t_door1, 32, 32, true, false, false, false, 1 },
|
||||
gate_left_silverlock = { t_door0, t_door1, 48, 32, true, false, false, false, 1 },
|
||||
gate_top_goldlock = { t_door0, t_door1, 64, 32, true, false, false, false, 2 },
|
||||
gate_left_goldlock = { t_door0, t_door1, 80, 32, true, false, false, false, 2 },
|
||||
}
|
||||
|
||||
lights = {
|
||||
candle0 = { t_decor0, t_decor1, 3 * 16, 8 * 16, true, true },
|
||||
candle1 = { t_decor0, t_decor1, 1 * 16, 8 * 16, true, true },
|
||||
candle2 = { t_decor0, t_decor1, 5 * 16, 8 * 16, true, false },
|
||||
}
|
||||
|
||||
walldecor = {
|
||||
topleft = {
|
||||
{ t_decor0, nil, 2 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 6 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 7 * 16, 2 * 16, false },
|
||||
},
|
||||
top = {
|
||||
{ t_decor0, nil, 0 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 1 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 4 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 5 * 16, 2 * 16, false },
|
||||
},
|
||||
single = {
|
||||
{ t_decor0, nil, 0 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 1 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 4 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 5 * 16, 2 * 16, false },
|
||||
},
|
||||
topright = {
|
||||
{ t_decor0, nil, 3 * 16, 2 * 16, false },
|
||||
},
|
||||
left = {
|
||||
{ t_decor0, nil, 2 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 3 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 6 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 7 * 16, 2 * 16, false },
|
||||
},
|
||||
bottomleft = {
|
||||
{ t_decor0, nil, 0 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 1 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 2 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 4 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 5 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 6 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 7 * 16, 2 * 16, false },
|
||||
},
|
||||
bottomright = {
|
||||
{ t_decor0, nil, 0 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 1 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 3 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 4 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 5 * 16, 2 * 16, false },
|
||||
},
|
||||
left_t = {
|
||||
{ t_decor0, nil, 2 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 6 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 7 * 16, 2 * 16, false },
|
||||
},
|
||||
right_t = {
|
||||
{ t_decor0, nil, 3 * 16, 2 * 16, false },
|
||||
},
|
||||
bottom_t = {
|
||||
{ t_decor0, nil, 0 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 1 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 4 * 16, 2 * 16, false },
|
||||
{ t_decor0, nil, 5 * 16, 2 * 16, false },
|
||||
},
|
||||
}
|
||||
|
||||
chest = { "Items/Chest0.png", "Items/Chest1.png", 16, 0}
|
||||
end
|
||||
|
||||
function createJumbleLayout(matrix)
|
||||
local room1 = matrix[random(#matrix)]
|
||||
local room2 = matrix[random(#matrix)]
|
||||
local room3 = matrix[random(#matrix)]
|
||||
local room4 = matrix[random(#matrix)]
|
||||
|
||||
local room = {}
|
||||
for i=0,15 do
|
||||
for j=0,12 do
|
||||
if not room[i] then room[i] = {} end
|
||||
if not room[i][j] then room[i][j] = {} end
|
||||
if i < 7 then
|
||||
if j < 6 then
|
||||
room[i][j] = room1[i][j]
|
||||
else
|
||||
room[i][j] = room2[i][j]
|
||||
end
|
||||
else
|
||||
if j < 6 then
|
||||
room[i][j] = room3[i][j]
|
||||
else
|
||||
room[i][j] = room4[i][j]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return room
|
||||
end
|
||||
|
||||
function draw_layout_to_room(room, matrix, roomx, roomy)
|
||||
local wallTypes = {"#", "\"", "/", "d", "g", "S", "G"}
|
||||
|
||||
for i=2,13 do
|
||||
for j=2,10 do
|
||||
if matrix[i][j] == "p" then
|
||||
setPitTile(room, matrix, i, j);
|
||||
elseif matrix[i][j] == "#" then
|
||||
setBlockTile(room, matrix, i, j, walls, wallTypes, false)
|
||||
elseif matrix[i][j] == "\"" then
|
||||
setBlockTile(room, matrix, i, j, walls, wallTypes, false)
|
||||
room.decor[i][j] = lights.candle1
|
||||
elseif matrix[i][j] == "/" then
|
||||
setBlockTile(room, matrix, i, j, walls, wallTypes, false)
|
||||
if random(2) == 1 then
|
||||
room.decor[i][j] = lights.candle1
|
||||
else
|
||||
room.decor[i][j] = lights.candle2
|
||||
end
|
||||
elseif matrix[i][j] == "f" then
|
||||
setBlockTile(room, matrix, i, j, fences, "f", true)
|
||||
elseif matrix[i][j] == "a" then
|
||||
create_shop_artifact(map, (roomx*512) + i*32, (roomy * 384) + j*32)
|
||||
elseif matrix[i][j] == "l" then
|
||||
room.decor[i][j] = lights.candle0
|
||||
elseif matrix[i][j] == "c" then
|
||||
room.chests[i][j] = chest
|
||||
elseif matrix[i][j] == "d" then
|
||||
room.doors[i][j] = getDoor(matrix, i, j, doors.door_top_nolock, doors.door_left_nolock)
|
||||
elseif matrix[i][j] == "S" then
|
||||
room.doors[i][j] = getDoor(matrix, i, j, doors.door_top_silverlock, doors.door_left_silverlock)
|
||||
elseif matrix[i][j] == "G" then
|
||||
room.doors[i][j] = getDoor(matrix, i, j, doors.door_top_goldlock, doors.door_left_goldlock)
|
||||
elseif matrix[i][j] == "g" then
|
||||
room.doors[i][j] = getDoor(matrix, i, j, doors.gate_top_nolock, doors.gate_left_nolock)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function pickALayout(matrix)
|
||||
-- Chose a random layout
|
||||
if random(3) == 1 then
|
||||
return matrix[random(#matrix)]
|
||||
else
|
||||
return createJumbleLayout(matrix)
|
||||
end
|
||||
end
|
||||
|
||||
function module.add_walls_to_room(room)
|
||||
if random(2) == 1 then
|
||||
return false
|
||||
end
|
||||
|
||||
draw_layout_to_room(room, pickALayout(readLayoutFile("walllayouts.dat")))
|
||||
return true
|
||||
end
|
||||
|
||||
function module.add_pits_to_room(room)
|
||||
if CURRENT_LEVEL < 2 or random(5) ~= 1 then
|
||||
return false
|
||||
end
|
||||
|
||||
draw_layout_to_room(room, pickALayout(readLayoutFile("pitlayouts.dat")))
|
||||
return true
|
||||
end
|
||||
|
||||
function module.add_shop_layout(room, roomx, roomy)
|
||||
local matrix = readLayoutFile("shoplayouts.dat")
|
||||
draw_layout_to_room(room, matrix[random(#matrix)], roomx, roomy)
|
||||
return true
|
||||
end
|
||||
|
||||
function module.add_locked_room_layout(room, roomx, roomy)
|
||||
local matrix = readLayoutFile("lockedroomlayouts.dat")
|
||||
draw_layout_to_room(room, matrix[random(#matrix)], roomx, roomy)
|
||||
return true
|
||||
end
|
||||
|
||||
return module
|
|
@ -0,0 +1,90 @@
|
|||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++"#####G####"++
|
||||
++#-c--c--c--#++
|
||||
++#----------#++
|
||||
++#-c--c--c--#++
|
||||
++G----------G++
|
||||
++#-c--c--c--#++
|
||||
++#----------#++
|
||||
++"#####G####"++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++"#####S####"++
|
||||
++#-c--c--c--#++
|
||||
++#----------#++
|
||||
++#-c--c--c--#++
|
||||
++S----------S++
|
||||
++#-c--c--c--#++
|
||||
++#----------#++
|
||||
++"#####S####"++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++/####-#####/++
|
||||
++#--c#-#c---#++
|
||||
++S---#-#----G++
|
||||
++#####-######++
|
||||
++------------++
|
||||
++#####-######++
|
||||
++S--c#-#c---G++
|
||||
++/####-#####/++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++----#S#-----++
|
||||
++----#c#-----++
|
||||
++----#c#-----++
|
||||
++----#c#-----++
|
||||
++----###-----++
|
||||
++------------++
|
||||
++------------++
|
||||
++------------++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++------------++
|
||||
++------------++
|
||||
++------------++
|
||||
++---###S##---++
|
||||
++---#cccc#---++
|
||||
++---######---++
|
||||
++------------++
|
||||
++------------++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++----#G#-----++
|
||||
++----#c#-----++
|
||||
++----#c#-----++
|
||||
++----#c#-----++
|
||||
++----###-----++
|
||||
++------------++
|
||||
++------------++
|
||||
++------------++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++------------++
|
||||
++------------++
|
||||
++------------++
|
||||
++---###G##---++
|
||||
++---#cccc#---++
|
||||
++---######---++
|
||||
++------------++
|
||||
++------------++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
|
@ -5,8 +5,8 @@ local chest_gen = require "chestgen"
|
|||
|
||||
-- Setting up some functions
|
||||
local time = os.time
|
||||
local random = math.random
|
||||
local randomseed = math.randomseed
|
||||
local random = map_random
|
||||
local randomseed = map_randomseed
|
||||
|
||||
-- CONSTANTS
|
||||
local UP = 1
|
||||
|
@ -14,6 +14,8 @@ local LEFT = 2
|
|||
local RIGHT = 3
|
||||
local DOWN = 4
|
||||
|
||||
local lockedDoorsAdded = false
|
||||
|
||||
-- BEGIN FUNCTIONS
|
||||
local function matrix_coverage (matrix)
|
||||
local cov = 0
|
||||
|
@ -43,17 +45,30 @@ local function generate_path ()
|
|||
end
|
||||
|
||||
local cx, cy = 1, 1
|
||||
local seed = time();
|
||||
local seed = get_random_seed(CURRENT_LEVEL)
|
||||
info("Map generation seed: " .. seed)
|
||||
randomseed(seed)
|
||||
local direction = 0
|
||||
local lastDirection = 0
|
||||
local coridoor_count = 0
|
||||
local shopLevel = CURRENT_LEVEL % 4 == 0
|
||||
local bossLevel = CURRENT_LEVEL % 5 == 0
|
||||
local coverage = 9 + CURRENT_LEVEL
|
||||
if bossLevel then
|
||||
if QUICK_MODE then
|
||||
bossLevel = CURRENT_LEVEL % 3 == 0
|
||||
shopLevel = CURRENT_LEVEL % 2 == 0
|
||||
end
|
||||
local coverage = 8 + CURRENT_LEVEL
|
||||
if bossLevel or CURRENT_LEVEL == 1 then
|
||||
coverage = 5
|
||||
end
|
||||
if ARCADE_MODE then
|
||||
coverage = 40
|
||||
shopLevel = true
|
||||
end
|
||||
|
||||
if shopLevel then
|
||||
coverage = coverage + 1
|
||||
end
|
||||
|
||||
-- Create the first room
|
||||
map_matrix[cx][cy] = room_builder.create_empty_room()
|
||||
|
@ -61,15 +76,7 @@ local function generate_path ()
|
|||
while matrix_coverage(map_matrix) < coverage do
|
||||
local direction = random(4)
|
||||
|
||||
if lastDirection > 0 then
|
||||
if random(24) <= 6 then direction = lastDirection end
|
||||
end
|
||||
|
||||
while lastDirection == reverse_direction(direction) do
|
||||
direction = random(4)
|
||||
end
|
||||
|
||||
if coridoor_count < coverage/3 then
|
||||
if coridoor_count < coverage/2 then
|
||||
if random(3) == 1 and (cx > 1 or cy > 1) then
|
||||
map_matrix[cx][cy].type = "coridoor"
|
||||
coridoor_count = coridoor_count + 1
|
||||
|
@ -116,17 +123,33 @@ local function generate_path ()
|
|||
|
||||
local roomCount = 0
|
||||
local bossAdded = false
|
||||
local shopAdded = false
|
||||
|
||||
-- Build all the rooms
|
||||
for i=1,10 do
|
||||
for j=1,10 do
|
||||
room = map_matrix[i][j]
|
||||
if room then
|
||||
if roomCount > 4 and shopLevel and not shopAdded and not room.goal then
|
||||
room.type = "shop"
|
||||
shopAdded = true
|
||||
elseif random(8) == 1 and not room.goal then
|
||||
room.type = "locked"
|
||||
lockedDoorsAdded = true
|
||||
end
|
||||
roomCount = roomCount + 1
|
||||
room_builder.build_room(room)
|
||||
monster_gen.add_monsters_to_room(room, i-1, j-1)
|
||||
trap_gen.add_traps_to_room(room, i-1, j-1)
|
||||
chest_gen.add_chests_to_room(room, i-1, j-1)
|
||||
room_builder.build_room(room, i-1, j-1)
|
||||
if room.type ~= "shop" then
|
||||
monster_gen.add_monsters_to_room(room, i-1, j-1)
|
||||
trap_gen.add_traps_to_room(room, i-1, j-1)
|
||||
chest_gen.add_chests_to_room(room, i-1, j-1)
|
||||
else
|
||||
monster_gen.add_shopkeeper_to_room(room, i-1, j-1)
|
||||
if PlayerData.shopOwnerKiller then
|
||||
monster_gen.add_bodyguard_to_room(room, i-1, j-1)
|
||||
monster_gen.add_bodyguard_to_room(room, i-1, j-1)
|
||||
end
|
||||
end
|
||||
if roomCount > 3 and bossLevel and not bossAdded then
|
||||
bossAdded = true
|
||||
monster_gen.add_boss_to_room(room, i-1, j-1)
|
||||
|
@ -159,4 +182,8 @@ for i=1,10 do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
if lockedDoorsAdded then
|
||||
add_keybearers(map)
|
||||
end
|
||||
-- END SCRIPT
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
-- FUNCTIONS
|
||||
local random = math.random
|
||||
local random = map_random
|
||||
local layoutparser = require "layoutparser"
|
||||
|
||||
-- CONSTANTS
|
||||
local UP = 1
|
||||
|
@ -28,18 +29,10 @@ local wall = {
|
|||
horizontal = nil
|
||||
}
|
||||
|
||||
local pits = {
|
||||
center = nil,
|
||||
top = nil,
|
||||
left = nil,
|
||||
right = nil,
|
||||
topleft = nil,
|
||||
topright = nil,
|
||||
}
|
||||
|
||||
local special = { level_exit = nil }
|
||||
|
||||
local floorDecor = { }
|
||||
local blockingFloorDecor = { }
|
||||
local lightDecor = { }
|
||||
|
||||
local function load_decor_textures()
|
||||
|
@ -49,9 +42,9 @@ local function load_decor_textures()
|
|||
-- Skulls
|
||||
table.insert(floorDecor, { td0, td1, 0, 12 * 16, false, false })
|
||||
table.insert(floorDecor, { td0, td1, 32, 12 * 16, false, false })
|
||||
table.insert(floorDecor, { td0, td1, 64, 12 * 16, false, true })
|
||||
table.insert(floorDecor, { td0, td1, 0, 13 * 16, false, false })
|
||||
table.insert(floorDecor, { td0, td1, 32, 13 * 16, false, false })
|
||||
table.insert(floorDecor, { td0, td1, 64, 12 * 16, false, true })
|
||||
table.insert(floorDecor, { td0, td1, 64, 13 * 16, false, true })
|
||||
|
||||
-- Bones
|
||||
|
@ -60,42 +53,6 @@ local function load_decor_textures()
|
|||
table.insert(floorDecor, { td0, td1, 16, 13 * 16, false, false })
|
||||
table.insert(floorDecor, { td0, td1, 48, 13 * 16, false, false })
|
||||
|
||||
-- Urns
|
||||
--table.insert(floorDecor, { td0, td1, 0 * 16, 48, true, false })
|
||||
--table.insert(floorDecor, { td0, td1, 1 * 16, 48, true, false })
|
||||
--table.insert(floorDecor, { td0, td1, 2 * 16, 48, true, false })
|
||||
--table.insert(floorDecor, { td0, td1, 3 * 16, 48, true, false })
|
||||
--table.insert(floorDecor, { td0, td1, 4 * 16, 48, true, false })
|
||||
--table.insert(floorDecor, { td0, td1, 5 * 16, 48, true, false })
|
||||
--table.insert(floorDecor, { td0, td1, 6 * 16, 48, false, false })
|
||||
--table.insert(floorDecor, { td0, td1, 7 * 16, 48, false, false })
|
||||
|
||||
-- Racks
|
||||
--table.insert(floorDecor, { td0, td1, 0 * 16, 11 * 16, true, false })
|
||||
--table.insert(floorDecor, { td0, td1, 1 * 16, 11 * 16, true, false })
|
||||
--table.insert(floorDecor, { td0, td1, 2 * 16, 11 * 16, true, false })
|
||||
--table.insert(floorDecor, { td0, td1, 3 * 16, 11 * 16, true, false })
|
||||
--table.insert(floorDecor, { td0, td1, 4 * 16, 11 * 16, true, false })
|
||||
--table.insert(floorDecor, { td0, td1, 5 * 16, 11 * 16, true, false })
|
||||
--table.insert(floorDecor, { td0, td1, 6 * 16, 11 * 16, true, false })
|
||||
|
||||
-- Headstones
|
||||
table.insert(floorDecor, { td0, td1, 0 * 16, 17 * 16, true, false })
|
||||
table.insert(floorDecor, { td0, td1, 1 * 16, 17 * 16, true, false })
|
||||
table.insert(floorDecor, { td0, td1, 2 * 16, 17 * 16, true, false })
|
||||
table.insert(floorDecor, { td0, td1, 3 * 16, 17 * 16, true, false })
|
||||
table.insert(floorDecor, { td0, td1, 4 * 16, 17 * 16, true, false })
|
||||
table.insert(floorDecor, { td0, td1, 0 * 16, 18 * 16, true, false })
|
||||
table.insert(floorDecor, { td0, td1, 1 * 16, 18 * 16, true, false })
|
||||
table.insert(floorDecor, { td0, td1, 2 * 16, 18 * 16, true, false })
|
||||
table.insert(floorDecor, { td0, td1, 3 * 16, 18 * 16, true, false })
|
||||
table.insert(floorDecor, { td0, td1, 4 * 16, 18 * 16, true, false })
|
||||
|
||||
-- Altars
|
||||
table.insert(floorDecor, { td0, td1, 0 * 16, 20 * 16, true, false })
|
||||
table.insert(floorDecor, { td0, td1, 1 * 16, 20 * 16, true, false })
|
||||
table.insert(floorDecor, { td0, td1, 2 * 16, 20 * 16, true, false })
|
||||
|
||||
-- Webs
|
||||
--table.insert(floorDecor, { td0, td1, 0 * 16, 19 * 16, false })
|
||||
--table.insert(floorDecor, { td0, td1, 1 * 16, 19 * 16, false })
|
||||
|
@ -103,9 +60,47 @@ local function load_decor_textures()
|
|||
--table.insert(floorDecor, { td0, td1, 3 * 16, 19 * 16, false })
|
||||
--table.insert(floorDecor, { td0, td1, 4 * 16, 19 * 16, false })
|
||||
|
||||
-- Urns
|
||||
table.insert(floorDecor, { td0, td1, 6 * 16, 48, false, false })
|
||||
table.insert(floorDecor, { td0, td1, 7 * 16, 48, false, false })
|
||||
|
||||
-- Urns
|
||||
--table.insert(blockingFloorDecor, { td0, td1, 0 * 16, 48, true, false })
|
||||
--table.insert(blockingFloorDecor, { td0, td1, 1 * 16, 48, true, false })
|
||||
--table.insert(blockingFloorDecor, { td0, td1, 2 * 16, 48, true, false })
|
||||
--table.insert(blockingFloorDecor, { td0, td1, 3 * 16, 48, true, false })
|
||||
--table.insert(blockingFloorDecor, { td0, td1, 4 * 16, 48, true, false })
|
||||
--table.insert(blockingFloorDecor, { td0, td1, 5 * 16, 48, true, false })
|
||||
|
||||
-- Racks
|
||||
--table.insert(blockingFloorDecor, { td0, td1, 0 * 16, 11 * 16, true, false })
|
||||
--table.insert(blockingFloorDecor, { td0, td1, 1 * 16, 11 * 16, true, false })
|
||||
--table.insert(blockingFloorDecor, { td0, td1, 2 * 16, 11 * 16, true, false })
|
||||
--table.insert(blockingFloorDecor, { td0, td1, 3 * 16, 11 * 16, true, false })
|
||||
--table.insert(blockingFloorDecor, { td0, td1, 4 * 16, 11 * 16, true, false })
|
||||
--table.insert(blockingFloorDecor, { td0, td1, 5 * 16, 11 * 16, true, false })
|
||||
--table.insert(blockingFloorDecor, { td0, td1, 6 * 16, 11 * 16, true, false })
|
||||
|
||||
-- Headstones
|
||||
table.insert(blockingFloorDecor, { td0, td1, 0 * 16, 17 * 16, true, false })
|
||||
table.insert(blockingFloorDecor, { td0, td1, 1 * 16, 17 * 16, true, false })
|
||||
table.insert(blockingFloorDecor, { td0, td1, 2 * 16, 17 * 16, true, false })
|
||||
table.insert(blockingFloorDecor, { td0, td1, 3 * 16, 17 * 16, true, false })
|
||||
table.insert(blockingFloorDecor, { td0, td1, 4 * 16, 17 * 16, true, false })
|
||||
table.insert(blockingFloorDecor, { td0, td1, 0 * 16, 18 * 16, true, false })
|
||||
table.insert(blockingFloorDecor, { td0, td1, 1 * 16, 18 * 16, true, false })
|
||||
table.insert(blockingFloorDecor, { td0, td1, 2 * 16, 18 * 16, true, false })
|
||||
table.insert(blockingFloorDecor, { td0, td1, 3 * 16, 18 * 16, true, false })
|
||||
table.insert(blockingFloorDecor, { td0, td1, 4 * 16, 18 * 16, true, false })
|
||||
|
||||
-- Altars
|
||||
table.insert(blockingFloorDecor, { td0, td1, 0 * 16, 20 * 16, true, false })
|
||||
table.insert(blockingFloorDecor, { td0, td1, 1 * 16, 20 * 16, true, false })
|
||||
table.insert(blockingFloorDecor, { td0, td1, 2 * 16, 20 * 16, true, false })
|
||||
|
||||
-- Statues
|
||||
--table.insert(floorDecor, { td0, td1, 3 * 16, 20 * 16, true })
|
||||
--table.insert(floorDecor, { td0, td1, 4 * 16, 20 * 16, true })
|
||||
--table.insert(blockingFloorDecor, { td0, td1, 3 * 16, 20 * 16, true })
|
||||
--table.insert(blockingFloorDecor, { td0, td1, 4 * 16, 20 * 16, true })
|
||||
|
||||
lightDecor.candle0 = { td0, td1, 0, 8 * 16, false, true }
|
||||
lightDecor.candle1 = { td0, td1, 16, 8 * 16, false, true }
|
||||
|
@ -126,125 +121,98 @@ local function repack(data)
|
|||
isCollider = data[5] or false,
|
||||
isLightSource = data[6] or false,
|
||||
isLevelExit = data[7] or false,
|
||||
isLethal = data[8] or false
|
||||
isLethal = data[8] or false,
|
||||
lockType = data[9] or 0
|
||||
}
|
||||
end
|
||||
|
||||
local function add_random_decor_to_room(room)
|
||||
local decor_count = random(8)
|
||||
for i=1,decor_count do
|
||||
x = random(11) + 1
|
||||
y = random(8) + 1
|
||||
if not room.decor[x][y] then
|
||||
room.decor[x][y] = floorDecor[random(#floorDecor)]
|
||||
end
|
||||
end
|
||||
|
||||
if random(2) == 1 then
|
||||
room.decor[4][3] = lightDecor.candle2
|
||||
end
|
||||
if random(2) == 1 then
|
||||
room.decor[11][3] = lightDecor.candle2
|
||||
end
|
||||
if random(2) == 1 then
|
||||
room.decor[4][9] = lightDecor.candle2
|
||||
end
|
||||
if random(2) == 1 then
|
||||
room.decor[11][9] = lightDecor.candle2
|
||||
end
|
||||
local function room_tile_available(room, rx, ry)
|
||||
return not room.chests[rx][ry]
|
||||
and not room.traps[rx][ry]
|
||||
and not room.walls[rx][ry]
|
||||
and not room.doors[rx][ry]
|
||||
and not room.monsters[rx][ry]
|
||||
and not room.decor[rx][ry]
|
||||
and (room.tiles[rx][ry]
|
||||
and not room.tiles[rx][ry][5]
|
||||
and not room.tiles[rx][ry][7]
|
||||
and not room.tiles[rx][ry][8])
|
||||
end
|
||||
|
||||
local function add_pits_to_room(room)
|
||||
|
||||
if CURRENT_LEVEL < 3 then
|
||||
return
|
||||
elseif random(5) ~= 1 then
|
||||
return
|
||||
local function add_random_decor_to_room(room, blockingDecor)
|
||||
local decor_count = random(8)
|
||||
if blockingDecor then
|
||||
decor_count = random(4)
|
||||
end
|
||||
|
||||
local pitdata = read_file("pitlayouts.dat")
|
||||
|
||||
local cleanData = ""
|
||||
for i=1, #pitdata do
|
||||
local c = pitdata:sub(i+1, i+1)
|
||||
if c == "#" or c == "-" then
|
||||
cleanData = cleanData .. c
|
||||
for i=1,decor_count do
|
||||
local success = false
|
||||
while not success do
|
||||
x = random(11) + 1
|
||||
y = random(8) + 1
|
||||
if room_tile_available(room, x, y) then
|
||||
room.decor[x][y] = floorDecor[random(#floorDecor)]
|
||||
success = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local matrix = {}
|
||||
for i=0, #cleanData-1 do
|
||||
local c = cleanData:sub(i, i)
|
||||
local col = i % 16
|
||||
local row = (i - col)/16
|
||||
local layout = 1 + (row - (row % 12))/12
|
||||
local row = row % 12
|
||||
if not matrix[layout] then matrix[layout] = {} end
|
||||
if not matrix[layout][col] then matrix[layout][col] = {} end
|
||||
if c == "#" then
|
||||
matrix[layout][col][row] = true
|
||||
else
|
||||
matrix[layout][col][row] = false
|
||||
end
|
||||
end
|
||||
|
||||
-- Chose a random layout
|
||||
matrix = matrix[random(#matrix)]
|
||||
for i=2,13 do
|
||||
for j=2,10 do
|
||||
if matrix[i][j] then
|
||||
room.decor[i][j] = nil
|
||||
if not matrix[i-1][j-1] and not matrix[i+1][j-1] and matrix[i-1][j] and matrix[i+1][j] and matrix[i][j-1] then
|
||||
room.tiles[i][j] = pits.innermid
|
||||
elseif not matrix[i-1][j-1] and matrix[i-1][j] and matrix[i][j-1] then
|
||||
room.tiles[i][j] = pits.innerleft
|
||||
elseif not matrix[i+1][j-1] and matrix[i+1][j] and matrix[i][j-1] then
|
||||
room.tiles[i][j] = pits.innerright
|
||||
elseif not matrix[i-1][j] and not matrix[i][j-1] and not matrix[i+1][j] then
|
||||
room.tiles[i][j] = pits.topcrevice
|
||||
elseif not matrix[i-1][j] and not matrix[i+1][j] then
|
||||
room.tiles[i][j] = pits.bottomcrevice
|
||||
elseif not matrix[i-1][j] and not matrix[i][j-1] then
|
||||
room.tiles[i][j] = pits.topleft
|
||||
elseif not matrix[i+1][j] and not matrix[i][j-1] then
|
||||
room.tiles[i][j] = pits.topright
|
||||
elseif not matrix[i-1][j] then
|
||||
room.tiles[i][j] = pits.left
|
||||
elseif not matrix[i+1][j] then
|
||||
room.tiles[i][j] = pits.right
|
||||
elseif not matrix[i][j-1] then
|
||||
room.tiles[i][j] = pits.top
|
||||
else
|
||||
room.tiles[i][j] = pits.center
|
||||
if blockingDecor then
|
||||
decor_count = random(4)
|
||||
for i=1,decor_count do
|
||||
local success = false
|
||||
while not success do
|
||||
x = random(11) + 1
|
||||
y = random(8) + 1
|
||||
if room_tile_available(room, x, y) then
|
||||
room.decor[x][y] = blockingFloorDecor[random(#blockingFloorDecor)]
|
||||
success = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if blockingDecor then
|
||||
if random(2) == 1 and room_tile_available(room, 4, 3) then
|
||||
room.decor[4][3] = lightDecor.candle2
|
||||
end
|
||||
if random(2) == 1 and room_tile_available(room, 11, 3) then
|
||||
room.decor[11][3] = lightDecor.candle2
|
||||
end
|
||||
if random(2) == 1 and room_tile_available(room, 4, 9) then
|
||||
room.decor[4][9] = lightDecor.candle2
|
||||
end
|
||||
if random(2) == 1 and room_tile_available(room, 11, 9) then
|
||||
room.decor[11][9] = lightDecor.candle2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function add_tiles_to_room (room)
|
||||
local function add_tiles_to_room (room, singletile)
|
||||
for i=0,15 do
|
||||
for j=0,11 do
|
||||
if (i >= 1 and i <= 14 and j >= 1 and j <= 10) then
|
||||
if (i == 1 and j == 1) then
|
||||
room.tiles[i][j] = floor.topleft
|
||||
room.tiles[i][j] = singletile and floor.single or floor.topleft
|
||||
elseif (i == 14 and j == 1) then
|
||||
room.tiles[i][j] = floor.topright
|
||||
room.tiles[i][j] = singletile and floor.single or floor.topright
|
||||
elseif (i == 1 and j == 10) then
|
||||
room.tiles[i][j] = floor.bottomleft
|
||||
room.tiles[i][j] = singletile and floor.single or floor.bottomleft
|
||||
elseif (i == 14 and j == 10) then
|
||||
room.tiles[i][j] = floor.bottomright
|
||||
room.tiles[i][j] = singletile and floor.single or floor.bottomright
|
||||
elseif (i == 1) then
|
||||
room.tiles[i][j] = floor.left
|
||||
room.tiles[i][j] = singletile and floor.single or floor.left
|
||||
elseif (i == 14) then
|
||||
room.tiles[i][j] = floor.right
|
||||
room.tiles[i][j] = singletile and floor.single or floor.right
|
||||
elseif (j == 1) then
|
||||
room.tiles[i][j] = floor.top
|
||||
room.tiles[i][j] = singletile and floor.single or floor.top
|
||||
elseif (j == 10) then
|
||||
room.tiles[i][j] = floor.bottom
|
||||
room.tiles[i][j] = singletile and floor.single or floor.bottom
|
||||
else
|
||||
room.tiles[i][j] = floor.center
|
||||
room.tiles[i][j] = singletile and floor.single or floor.center
|
||||
end
|
||||
else
|
||||
room.tiles[i][j] = floor.single
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -254,17 +222,17 @@ local function add_walls_to_room (room)
|
|||
for i=0,15 do
|
||||
for j=0,11 do
|
||||
if (i == 0 and j == 0) then
|
||||
room.tiles[i][j] = wall.topleft
|
||||
room.walls[i][j] = wall.topleft
|
||||
elseif (i == 15 and j == 0) then
|
||||
room.tiles[i][j] = wall.topright
|
||||
room.walls[i][j] = wall.topright
|
||||
elseif (i == 0 and j == 11) then
|
||||
room.tiles[i][j] = wall.bottomleft
|
||||
room.walls[i][j] = wall.bottomleft
|
||||
elseif (i == 15 and j == 11) then
|
||||
room.tiles[i][j] = wall.bottomright
|
||||
room.walls[i][j] = wall.bottomright
|
||||
elseif (i == 0 or i == 15) then
|
||||
room.tiles[i][j] = wall.vertical
|
||||
room.walls[i][j] = wall.vertical
|
||||
elseif (j == 0 or j == 11) then
|
||||
room.tiles[i][j] = wall.horizontal
|
||||
room.walls[i][j] = wall.horizontal
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -272,10 +240,12 @@ end
|
|||
|
||||
local function build_vert_center_coridoor(room, offset)
|
||||
for i=0,4 do
|
||||
room.tiles[6][offset+i] = wall.vertical
|
||||
room.walls[6][offset+i] = wall.vertical
|
||||
room.tiles[7][offset+i] = floor.center
|
||||
room.tiles[8][offset+i] = floor.center
|
||||
room.tiles[9][offset+i] = wall.vertical
|
||||
room.walls[7][offset+i] = nil
|
||||
room.walls[8][offset+i] = nil
|
||||
room.walls[9][offset+i] = wall.vertical
|
||||
end
|
||||
if random(2) == 1 then
|
||||
room.decor[6][offset+2] = lightDecor.candle1
|
||||
|
@ -287,10 +257,12 @@ end
|
|||
|
||||
local function build_horiz_center_coridoor(room, offset)
|
||||
for i=0,6 do
|
||||
room.tiles[offset+i][4] = wall.horizontal
|
||||
room.walls[offset+i][4] = wall.horizontal
|
||||
room.tiles[offset+i][5] = floor.center
|
||||
room.tiles[offset+i][6] = floor.center
|
||||
room.tiles[offset+i][7] = wall.horizontal
|
||||
room.walls[offset+i][5] = nil
|
||||
room.walls[offset+i][6] = nil
|
||||
room.walls[offset+i][7] = wall.horizontal
|
||||
end
|
||||
if random(2) == 1 then
|
||||
room.decor[offset+3][4] = lightDecor.candle1
|
||||
|
@ -303,32 +275,32 @@ end
|
|||
local function build_center_corner_walls(room, exits)
|
||||
if exits.down then
|
||||
if exits.left then
|
||||
room.tiles[6][7] = wall.topright
|
||||
room.walls[6][7] = wall.topright
|
||||
end
|
||||
if exits.right then
|
||||
room.tiles[9][7] = wall.topleft
|
||||
room.walls[9][7] = wall.topleft
|
||||
end
|
||||
else
|
||||
if not exits.left then
|
||||
room.tiles[6][7] = wall.bottomleft
|
||||
room.walls[6][7] = wall.bottomleft
|
||||
end
|
||||
if not exits.right then
|
||||
room.tiles[9][7] = wall.bottomright
|
||||
room.walls[9][7] = wall.bottomright
|
||||
end
|
||||
end
|
||||
if exits.up then
|
||||
if exits.left then
|
||||
room.tiles[6][4] = wall.bottomright
|
||||
room.walls[6][4] = wall.bottomright
|
||||
end
|
||||
if exits.right then
|
||||
room.tiles[9][4] = wall.bottomleft
|
||||
room.walls[9][4] = wall.bottomleft
|
||||
end
|
||||
else
|
||||
if not exits.left then
|
||||
room.tiles[6][4] = wall.topleft
|
||||
room.walls[6][4] = wall.topleft
|
||||
end
|
||||
if not exits.right then
|
||||
room.tiles[9][4] = wall.topright
|
||||
room.walls[9][4] = wall.topright
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -336,25 +308,33 @@ end
|
|||
local function add_exits_to_room(room)
|
||||
for _,direction in ipairs(room.exits) do
|
||||
if direction == UP then
|
||||
room.tiles[6][0] = wall.bottomright
|
||||
room.walls[6][0] = wall.bottomright
|
||||
room.tiles[7][0] = floor.singleleft
|
||||
room.tiles[8][0] = floor.singleright
|
||||
room.tiles[9][0] = wall.bottomleft
|
||||
room.walls[7][0] = nil
|
||||
room.walls[8][0] = nil
|
||||
room.walls[9][0] = wall.bottomleft
|
||||
elseif direction == LEFT then
|
||||
room.tiles[0][4] = wall.bottomright
|
||||
room.walls[0][4] = wall.bottomright
|
||||
room.tiles[0][5] = floor.singletop
|
||||
room.tiles[0][6] = floor.singlebottom
|
||||
room.tiles[0][7] = wall.topright
|
||||
room.walls[0][5] = nil
|
||||
room.walls[0][6] = nil
|
||||
room.walls[0][7] = wall.topright
|
||||
elseif direction == RIGHT then
|
||||
room.tiles[15][4] = wall.bottomleft
|
||||
room.walls[15][4] = wall.bottomleft
|
||||
room.tiles[15][5] = floor.singletop
|
||||
room.tiles[15][6] = floor.singlebottom
|
||||
room.tiles[15][7] = wall.topleft
|
||||
room.walls[15][5] = nil
|
||||
room.walls[15][6] = nil
|
||||
room.walls[15][7] = wall.topleft
|
||||
elseif direction == DOWN then
|
||||
room.tiles[6][11] = wall.topright
|
||||
room.walls[6][11] = wall.topright
|
||||
room.tiles[7][11] = floor.singleleft
|
||||
room.tiles[8][11] = floor.singleright
|
||||
room.tiles[9][11] = wall.topleft
|
||||
room.walls[7][11] = nil
|
||||
room.walls[8][11] = nil
|
||||
room.walls[9][11] = wall.topleft
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -376,18 +356,19 @@ local function build_coridoor_room(room)
|
|||
end
|
||||
|
||||
-- Fill the center
|
||||
room.tiles[6][5] = wall.vertical
|
||||
room.tiles[6][6] = wall.vertical
|
||||
room.tiles[7][4] = wall.horizontal
|
||||
room.tiles[7][5] = floor.center
|
||||
room.tiles[7][6] = floor.center
|
||||
room.tiles[7][7] = wall.horizontal
|
||||
room.tiles[8][4] = wall.horizontal
|
||||
room.tiles[8][5] = floor.center
|
||||
room.tiles[8][6] = floor.center
|
||||
room.tiles[8][7] = wall.horizontal
|
||||
room.tiles[9][5] = wall.vertical
|
||||
room.tiles[9][6] = wall.vertical
|
||||
|
||||
room.walls[6][5] = wall.vertical
|
||||
room.walls[6][6] = wall.vertical
|
||||
room.walls[7][4] = wall.horizontal
|
||||
room.walls[7][7] = wall.horizontal
|
||||
room.walls[8][4] = wall.horizontal
|
||||
room.walls[8][7] = wall.horizontal
|
||||
room.walls[9][5] = wall.vertical
|
||||
room.walls[9][6] = wall.vertical
|
||||
|
||||
-- Build the coridoors
|
||||
if exits.down then build_vert_center_coridoor(room, 7) end
|
||||
|
@ -398,19 +379,8 @@ local function build_coridoor_room(room)
|
|||
build_center_corner_walls(room, exits)
|
||||
end
|
||||
|
||||
local function room_tile_available(room, rx, ry)
|
||||
return not room.chests[rx][ry]
|
||||
and not room.traps[rx][ry]
|
||||
and not room.monsters[rx][ry]
|
||||
and not room.decor[rx][ry]
|
||||
and (room.tiles[rx][ry]
|
||||
and not room.tiles[rx][ry][5]
|
||||
and not room.tiles[rx][ry][7]
|
||||
and not room.tiles[rx][ry][8])
|
||||
end
|
||||
|
||||
local function add_level_exit(room)
|
||||
success = false
|
||||
local success = false
|
||||
while not success do
|
||||
x = random(14)
|
||||
y = random(10)
|
||||
|
@ -421,24 +391,54 @@ local function add_level_exit(room)
|
|||
end
|
||||
end
|
||||
|
||||
local function build_normal_room(room)
|
||||
add_tiles_to_room(room)
|
||||
add_random_decor_to_room(room)
|
||||
local function build_shop_room(room, roomx, roomy)
|
||||
add_tiles_to_room(room, false)
|
||||
add_walls_to_room(room)
|
||||
add_exits_to_room(room)
|
||||
add_pits_to_room(room)
|
||||
layoutparser.add_shop_layout(room, roomx, roomy)
|
||||
return room
|
||||
end
|
||||
|
||||
local function build_locked_room(room, roomx, roomy)
|
||||
add_tiles_to_room(room, false)
|
||||
add_walls_to_room(room)
|
||||
add_exits_to_room(room)
|
||||
layoutparser.add_locked_room_layout(room, roomx, roomy)
|
||||
return room
|
||||
end
|
||||
|
||||
local function build_normal_room(room)
|
||||
local crumbling = (CURRENT_LEVEL > 3 or QUICK_MODE) and random(8) == 1
|
||||
local pitsAdded = false;
|
||||
local interiorWallsAdded = false
|
||||
|
||||
add_tiles_to_room(room, crumbling)
|
||||
add_walls_to_room(room)
|
||||
add_exits_to_room(room)
|
||||
|
||||
if not crumbling then
|
||||
pitsAdded = layoutparser.add_pits_to_room(room)
|
||||
end
|
||||
if not pitsAdded and (not crumbling or CURRENT_LEVEL > 3) then
|
||||
interiorWallsAdded = layoutparser.add_walls_to_room(room)
|
||||
end
|
||||
|
||||
add_random_decor_to_room(room, not interiorWallsAdded)
|
||||
|
||||
if room.goal then
|
||||
add_level_exit(room)
|
||||
end
|
||||
|
||||
if CURRENT_LEVEL > 3 and random(8) == 1 then
|
||||
if crumbling then
|
||||
room.modifier.type = "CRUMBLING"
|
||||
room.modifier.arg = ""
|
||||
elseif (CURRENT_LEVEL > 3 or QUICK_MODE) and random(8) == 1 then
|
||||
room.modifier.type = "FIRE"
|
||||
room.modifier.arg = ""
|
||||
elseif ((not pitsAdded and not crumbling and (CURRENT_LEVEL > 1 or QUICK_MODE)) or CURRENT_LEVEL > 3) and random(8) == 1 then
|
||||
directions = { "LEFT", "RIGHT", "UP", "DOWN" }
|
||||
room.modifier.type = "WINDY"
|
||||
room.modifier.arg = directions[random(#directions)]
|
||||
elseif CURRENT_LEVEL > 5 and random(8) == 1 then
|
||||
room.modifier.type = "FIRE"
|
||||
room.modifier.arg = ""
|
||||
end
|
||||
|
||||
return room
|
||||
|
@ -473,6 +473,8 @@ function module.create_empty_room()
|
|||
path_dir = 0,
|
||||
type = "room",
|
||||
tiles = {},
|
||||
walls = {},
|
||||
doors = {},
|
||||
decor = {},
|
||||
modifier = {
|
||||
type = nil,
|
||||
|
@ -484,12 +486,16 @@ function module.create_empty_room()
|
|||
}
|
||||
for i=0,15 do
|
||||
room.tiles[i] = {}
|
||||
room.walls[i] = {}
|
||||
room.doors[i] = {}
|
||||
room.decor[i] = {}
|
||||
room.monsters[i] = {}
|
||||
room.traps[i] = {}
|
||||
room.chests[i] = {}
|
||||
for j=0,11 do
|
||||
room.tiles[i][j] = nil
|
||||
room.walls[i][j] = nil
|
||||
room.doors[i][j] = nil
|
||||
room.decor[i][j] = nil
|
||||
room.monsters[i][j] = nil
|
||||
room.traps[i][j] = nil
|
||||
|
@ -499,11 +505,16 @@ function module.create_empty_room()
|
|||
return room
|
||||
end
|
||||
|
||||
function module.build_room(room)
|
||||
function module.build_room(room, roomx, roomy)
|
||||
if room.type == "coridoor" then
|
||||
build_coridoor_room(room)
|
||||
elseif room.type == "shop" then
|
||||
build_shop_room(room, roomx, roomy)
|
||||
elseif room.type == "locked" then
|
||||
build_locked_room(room, roomx, roomy)
|
||||
else
|
||||
build_normal_room(room)
|
||||
--build_locked_room(room, roomx, roomy)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -513,6 +524,12 @@ function module.load_room(map, room)
|
|||
if room.tiles[i][j] then
|
||||
add_tile(map, i, j, repack(room.tiles[i][j]))
|
||||
end
|
||||
if room.walls[i][j] then
|
||||
add_wall(map, i, j, repack(room.walls[i][j]))
|
||||
end
|
||||
if room.doors[i][j] then
|
||||
add_door(map, i, j, repack(room.doors[i][j]))
|
||||
end
|
||||
if room.decor[i][j] then
|
||||
add_decoration(map, i, j, repack(room.decor[i][j]))
|
||||
end
|
||||
|
@ -526,13 +543,16 @@ end
|
|||
function module.load_textures(map)
|
||||
t_floor = add_texture(map, "Objects/Floor.png")
|
||||
t_wall = add_texture(map, "Objects/Wall.png")
|
||||
t_pit0 = add_texture(map, "Objects/Pit0.png")
|
||||
t_pit1 = add_texture(map, "Objects/Pit1.png")
|
||||
|
||||
math.randomseed(os.time())
|
||||
local seed = get_random_seed(CURRENT_LEVEL);
|
||||
info("Map room random seed: " .. seed)
|
||||
map_randomseed(seed)
|
||||
|
||||
local xo = (random(3) - 1) * 112
|
||||
local yo = (random(8)) * 48
|
||||
|
||||
layoutparser.load_textures(map, xo, yo)
|
||||
|
||||
floor.center = { t_floor, -1, xo + 16, yo + 16, false }
|
||||
floor.top = { t_floor, -1, xo + 16, yo + 0, false }
|
||||
floor.bottom = { t_floor, -1, xo + 16, yo + 32, false }
|
||||
|
@ -546,19 +566,7 @@ function module.load_textures(map)
|
|||
floor.singlebottom = { t_floor, -1, xo + 48, yo + 32, false }
|
||||
floor.singleleft = { t_floor, -1, xo + 64, yo + 16, false }
|
||||
floor.singleright = { t_floor, -1, xo + 96, yo + 16, false }
|
||||
|
||||
local pit_yo = (random(5) + random(3)) * (16 * 2)
|
||||
pits.topleft = { t_pit0, t_pit1, 0, pit_yo, false, false, false, true }
|
||||
pits.top = { t_pit0, t_pit1, 16, pit_yo, false, false, false, true }
|
||||
pits.topright = { t_pit0, t_pit1, 32, pit_yo, false, false, false, true }
|
||||
pits.left = { t_pit0, t_pit1, 0, pit_yo + 16, false, false, false, true }
|
||||
pits.center = { t_pit0, t_pit1, 16, pit_yo + 16, false, false, false, true }
|
||||
pits.right = { t_pit0, t_pit1, 32, pit_yo + 16, false, false, false, true }
|
||||
pits.innerleft = { t_pit0, t_pit1, 80, pit_yo, false, false, false, true }
|
||||
pits.innermid = { t_pit0, t_pit1, 96, pit_yo, false, false, false, true }
|
||||
pits.innerright = { t_pit0, t_pit1, 112, pit_yo, false, false, false, true }
|
||||
pits.topcrevice = { t_pit0, t_pit1, 64, pit_yo, false, false, false, true }
|
||||
pits.bottomcrevice = { t_pit0, t_pit1, 64, pit_yo + 16, false, false, false, true }
|
||||
floor.single = { t_floor, -1, xo + 80, yo + 0, false }
|
||||
|
||||
wall.topleft = { t_wall, -1, xo + 0, yo + 0, true }
|
||||
wall.topright = { t_wall, -1, xo + 32, yo + 0, true }
|
||||
|
|
|
@ -9,7 +9,7 @@ room_builder.load_textures(map)
|
|||
|
||||
set_current_room(map, 0, 0)
|
||||
local room = room_builder.create_empty_room()
|
||||
room_builder.build_room(room)
|
||||
room_builder.build_room(room, 0, 0)
|
||||
room_builder.add_full_lighting(room)
|
||||
monster_gen.add_monsters_to_room(room, 0, 0)
|
||||
trap_gen.add_traps_to_room(room, 0, 0)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
local room_builder = require "maproombuilder"
|
||||
local module = {}
|
||||
local random = math.random
|
||||
local random = map_random
|
||||
|
||||
local texturePaths = {
|
||||
aquatic0 = "Characters/Aquatic0.png",
|
||||
|
@ -45,7 +45,9 @@ local behaviour = {
|
|||
guerilla = 3,
|
||||
coward = 4,
|
||||
sentinel = 5,
|
||||
fire_demon = 6
|
||||
fire_demon = 6,
|
||||
sorcerer = 7,
|
||||
assassin = 8
|
||||
}
|
||||
|
||||
local stats = {
|
||||
|
@ -84,20 +86,34 @@ local stats = {
|
|||
def = 0,
|
||||
speed = 1
|
||||
},
|
||||
orc = {
|
||||
hp = 20,
|
||||
dmg = 2,
|
||||
atk = 0,
|
||||
def = 0,
|
||||
speed = 1
|
||||
},
|
||||
boss = {
|
||||
hp = 60,
|
||||
dmg = 4,
|
||||
dmg = 3,
|
||||
atk = 1,
|
||||
def = 0,
|
||||
speed = 1
|
||||
},
|
||||
platino = {
|
||||
hp = 60,
|
||||
dmg = 60,
|
||||
atk = 60,
|
||||
def = 60,
|
||||
speed = 3
|
||||
}
|
||||
hp = 90,
|
||||
dmg = 1,
|
||||
atk = 0,
|
||||
def = 0,
|
||||
speed = 1
|
||||
},
|
||||
shopkeeper = {
|
||||
hp = 200,
|
||||
dmg = 10,
|
||||
atk = 2,
|
||||
def = 0,
|
||||
speed = 1
|
||||
},
|
||||
}
|
||||
|
||||
local function concat(table1, table2)
|
||||
|
@ -134,6 +150,16 @@ for i=1,#pests do
|
|||
pests[i] = concat({ texturePaths.pest0, texturePaths.pest1 }, pests[i])
|
||||
end
|
||||
|
||||
local avian = {
|
||||
{ stats.default, 0, 11*16, "A Small Brown Bat", behaviour.pacifist },
|
||||
{ stats.default, 16, 11*16, "A Big Brown Bat", behaviour.normal },
|
||||
{ stats.default, 32, 11*16, "A Vampire Bat", behaviour.guerilla },
|
||||
{ stats.default, 48, 11*16, "A Rabid Bat", behaviour.hostile },
|
||||
}
|
||||
for i=1,#avian do
|
||||
avian[i] = concat({ texturePaths.avian0, texturePaths.avian1 }, avian[i])
|
||||
end
|
||||
|
||||
local misc = {
|
||||
{ stats.misc, 0, 0, "A Giant Black Rat", behaviour.sentinel },
|
||||
{ stats.misc, 16, 0, "A Giant White Rat", behaviour.sentinel },
|
||||
|
@ -143,13 +169,45 @@ for i=1,#misc do
|
|||
misc[i] = concat({ texturePaths.misc0, texturePaths.misc1 }, misc[i])
|
||||
end
|
||||
|
||||
local undead = {
|
||||
-- UNDEAD
|
||||
local fairies = {
|
||||
{ stats.misc, 0, 48, "A Fairy", behaviour.pacifist },
|
||||
{ stats.misc, 16, 48, "A Fairy", behaviour.pacifist },
|
||||
{ stats.misc, 32, 48, "A Fairy", behaviour.pacifist },
|
||||
{ stats.misc, 48, 48, "A Fairy", behaviour.pacifist },
|
||||
{ stats.misc, 64, 48, "A Fairy", behaviour.pacifist },
|
||||
{ stats.misc, 80, 48, "A Fairy", behaviour.pacifist },
|
||||
}
|
||||
for i=1,#fairies do
|
||||
fairies[i] = concat({ texturePaths.humanoid0, texturePaths.humanoid1 }, fairies[i])
|
||||
end
|
||||
|
||||
local reanimated = {
|
||||
{ stats.undead, 0, 32, "A Skeleton", behaviour.normal },
|
||||
{ stats.undead, 48, 32, "A Black Skeleton", behaviour.normal },
|
||||
{ stats.undead, 64, 32, "A Zombie", behaviour.normal },
|
||||
{ stats.undead, 80, 32, "A Zombie", behaviour.normal }
|
||||
}
|
||||
for i=1,#reanimated do
|
||||
reanimated[i] = concat({ texturePaths.undead0, texturePaths.undead1 }, reanimated[i])
|
||||
end
|
||||
|
||||
local undead = {
|
||||
{ stats.undead, 5*16, 16, "A Mummy", behaviour.normal },
|
||||
{ stats.undead, 6*16, 16, "A Two Headed Mummy", behaviour.sentinel },
|
||||
{ stats.undead, 0*16, 32, "A Skeleton", behaviour.normal },
|
||||
{ stats.misc, 1*16, 32, "A Burning Skeleton", behaviour.fire_demon },
|
||||
{ stats.misc, 2*16, 32, "An Eldritch Skeleton", behaviour.sorcerer },
|
||||
{ stats.misc, 3*16, 32, "A Black Skeleton", behaviour.guerilla },
|
||||
{ stats.misc, 4*16, 32, "A Zombie", behaviour.coward },
|
||||
{ stats.misc, 5*16, 32, "A Pale Zombie", behaviour.coward },
|
||||
{ stats.misc, 7*16, 32, "A Scorched Zombie", behaviour.fire_demon },
|
||||
{ stats.undead, 0*16, 4*16, "A Whight", behaviour.coward },
|
||||
{ stats.undead, 1*16, 4*16, "A Ghast", behaviour.sentinel },
|
||||
{ stats.misc, 1*16, 4*16, "A Ghost", behaviour.guerilla },
|
||||
{ stats.misc, 0*16, 5*16, "A Spectre", behaviour.sentinel },
|
||||
{ stats.undead, 1*16, 5*16, "An Eldritch Spectre", behaviour.sorcerer },
|
||||
{ stats.undead, 2*16, 5*16, "A Scorched Spectre", behaviour.fire_demon },
|
||||
}
|
||||
for i=1,#undead do
|
||||
undead[i] = concat({ texturePaths.undead0, texturePaths.undead1 }, undead[i])
|
||||
end
|
||||
|
@ -188,22 +246,85 @@ for i=1,#demon do
|
|||
demon[i] = concat({ texturePaths.demon0, texturePaths.demon1 }, demon[i])
|
||||
end
|
||||
|
||||
local orcs = {
|
||||
{ stats.orc, 0, 4*16, "An Orc Guard", behaviour.normal },
|
||||
{ stats.orc, 16, 4*16, "An Orc Seargeant", behaviour.coward },
|
||||
{ stats.orc, 32, 4*16, "An Orc Militia", behaviour.hostile },
|
||||
{ stats.orc, 48, 4*16, "An Orc Sentry", behaviour.sentinel },
|
||||
{ stats.orc, 64, 4*16, "An Orc Brute", behaviour.guerilla },
|
||||
{ stats.orc, 80, 4*16, "An Orc Captain", behaviour.hostile },
|
||||
{ stats.orc, 96, 4*16, "An Orc Pyro", behaviour.fire_demon },
|
||||
}
|
||||
for i=1,#orcs do
|
||||
orcs[i] = concat({ texturePaths.humanoid0, texturePaths.humanoid1 }, orcs[i])
|
||||
end
|
||||
|
||||
local assassins = {
|
||||
{ stats.misc, 1*16, 6*16, "A Reaper", behaviour.assassin },
|
||||
{ stats.misc, 0*16, 7*16, "An Assassin", behaviour.assassin },
|
||||
{ stats.misc, 1*16, 7*16, "A Royal Assassin", behaviour.assassin },
|
||||
}
|
||||
for i=1,#assassins do
|
||||
assassins[i] = concat({ texturePaths.undead0, texturePaths.undead1 }, assassins[i])
|
||||
end
|
||||
|
||||
local bosses = {
|
||||
{ stats.boss, 16, 5*16, "The Hell Hound", behaviour.fire_demon, true }
|
||||
{ stats.boss, 16, 5*16, "The Hell Hound", behaviour.fire_demon, true },
|
||||
{ stats.boss, 16, 23*16, "The Cleric", behaviour.sorcerer, true },
|
||||
{ stats.boss, 16, 8*16, "The Shadow", behaviour.assassin, true },
|
||||
}
|
||||
bosses[1] = concat({ texturePaths.dog0, texturePaths.dog1 }, bosses[1])
|
||||
bosses[2] = concat({ texturePaths.humanoid0, texturePaths.humanoid1 }, bosses[2])
|
||||
bosses[3] = concat({ texturePaths.undead0, texturePaths.undead1 }, bosses[3])
|
||||
|
||||
local platino = {
|
||||
{
|
||||
local eastereggs = {
|
||||
{ stats.misc, 6*16, 1*16, "Linus, the Developer", behaviour.passive },
|
||||
{ stats.misc, 2*16, 3*16, "Lialynn, the Ranger", behaviour.passive },
|
||||
{ stats.misc, 4*16, 3*16, "Miniel, the Paladin", behaviour.passive },
|
||||
{ stats.misc, 2*16,12*16, "Feng, the Fighter", behaviour.passive },
|
||||
{ stats.misc, 0*16, 7*16, "Adnis, the Ranger", behaviour.passive },
|
||||
{ stats.misc, 7*16, 8*16, "Ti, the Mage", behaviour.passive },
|
||||
}
|
||||
for i=1,#eastereggs do
|
||||
eastereggs[i] = concat({ texturePaths.player0, texturePaths.player1 }, eastereggs[i])
|
||||
end
|
||||
|
||||
local shopkeeperBehaviour = behaviour.passive
|
||||
if PlayerData.shopOwnerKiller then
|
||||
shopkeeperBehaviour = behaviour.hostile
|
||||
end
|
||||
|
||||
local shopkeeper = {
|
||||
texturePaths.humanoid0,
|
||||
texturePaths.humanoid1,
|
||||
stats.shopkeeper,
|
||||
16,
|
||||
12*16,
|
||||
"The Trader",
|
||||
shopkeeperBehaviour
|
||||
}
|
||||
|
||||
local bodyguard = {
|
||||
texturePaths.humanoid0,
|
||||
texturePaths.humanoid1,
|
||||
stats.orc,
|
||||
32,
|
||||
12*16,
|
||||
"A Bodyguard",
|
||||
behaviour.hostile
|
||||
}
|
||||
|
||||
-- Add Platino
|
||||
table.insert(eastereggs, {
|
||||
texturePaths.reptile0,
|
||||
texturePaths.reptile1,
|
||||
stats.platino,
|
||||
48,
|
||||
12*16,
|
||||
"Platino",
|
||||
behaviour.sentinel
|
||||
}
|
||||
}
|
||||
behaviour.sentinel,
|
||||
true
|
||||
})
|
||||
|
||||
local function repack(data)
|
||||
return {
|
||||
|
@ -220,66 +341,81 @@ end
|
|||
|
||||
-- Begin script
|
||||
local enemies = {}
|
||||
if(CURRENT_LEVEL > 0 and CURRENT_LEVEL < 10) then
|
||||
if(CURRENT_LEVEL > 0) then
|
||||
if (CURRENT_LEVEL == 1) then
|
||||
enemies = concat(enemies, pests)
|
||||
enemies = concat(enemies, avian)
|
||||
enemies = concat(enemies, misc)
|
||||
enemies = concat(enemies, dogs)
|
||||
elseif (CURRENT_LEVEL > 5) then
|
||||
enemies = {}
|
||||
enemies = concat(enemies, demon)
|
||||
enemies = concat(enemies, undead)
|
||||
enemies = concat(enemies, reptile)
|
||||
enemies = concat(enemies, misc)
|
||||
elseif (CURRENT_LEVEL > 3) then
|
||||
elseif (CURRENT_LEVEL > 15 or (QUICK_MODE and CURRENT_LEVEL > 9)) then
|
||||
enemies = {}
|
||||
enemies = concat(enemies, undead)
|
||||
enemies = concat(enemies, reptile)
|
||||
enemies = concat(enemies, misc)
|
||||
enemies = concat(enemies, dogs)
|
||||
elseif (CURRENT_LEVEL > 2) then
|
||||
enemies = concat(enemies, orcs)
|
||||
enemies = concat(enemies, assassins)
|
||||
elseif (CURRENT_LEVEL > 10 or (QUICK_MODE and CURRENT_LEVEL > 6)) then
|
||||
enemies = {}
|
||||
enemies = concat(enemies, undead)
|
||||
enemies = concat(enemies, reptile)
|
||||
enemies = concat(enemies, misc)
|
||||
enemies = concat(enemies, dogs)
|
||||
enemies = concat(enemies, avian)
|
||||
elseif (CURRENT_LEVEL > 5 or (QUICK_MODE and CURRENT_LEVEL > 3)) then
|
||||
enemies = {}
|
||||
enemies = concat(enemies, orcs)
|
||||
enemies = concat(enemies, avian)
|
||||
elseif (CURRENT_LEVEL > 1) then
|
||||
enemies = {}
|
||||
enemies = concat(enemies, undead)
|
||||
enemies = concat(enemies, reanimated)
|
||||
enemies = concat(enemies, reptile)
|
||||
enemies = concat(enemies, avian)
|
||||
enemies = concat(enemies, misc)
|
||||
enemies = concat(enemies, dogs)
|
||||
end
|
||||
end
|
||||
|
||||
if random(100) == 1 then
|
||||
enemies = concat(enemies, platino)
|
||||
local addSpecialInLevel = random(100) == 1
|
||||
local addFairyToLevel = random(3) == 1;
|
||||
|
||||
local function add_monster_to_tile(room, roomx, roomy, rx, ry, monster)
|
||||
local x = (roomx * 512) + rx * 32
|
||||
local y = (roomy * 384) + ry * 32
|
||||
room.monsters[rx][ry] = {
|
||||
x,
|
||||
y,
|
||||
monster
|
||||
}
|
||||
end
|
||||
|
||||
function module.add_monsters_to_room(room, roomx, roomy)
|
||||
local addSpecial = addSpecialInLevel and random(2) == 1
|
||||
local addFairy = random(4) == 1
|
||||
local count = random(3)
|
||||
if (CURRENT_LEVEL > 3) then
|
||||
count = random(4)
|
||||
end
|
||||
count = count + 1
|
||||
local i = 0
|
||||
while i < count do
|
||||
local rx = random(13) + 1
|
||||
local ry = random(9) + 1
|
||||
if room_builder.is_tile_avilable(room, rx, ry) then
|
||||
local x = (roomx * 512) + rx * 32
|
||||
local y = (roomy * 384) + ry * 32
|
||||
room.monsters[rx][ry] = {
|
||||
x,
|
||||
y,
|
||||
enemies[random(#enemies)]
|
||||
}
|
||||
if addSpecial then
|
||||
addSpecialInLevel = false
|
||||
addSpecial = false
|
||||
add_monster_to_tile(room, roomx, roomy, rx, ry, eastereggs[random(#eastereggs)])
|
||||
elseif addFairyToLevel and addFairy then
|
||||
addFairyToLevel = false
|
||||
add_monster_to_tile(room, roomx, roomy, rx, ry, fairies[random(#fairies)])
|
||||
else
|
||||
add_monster_to_tile(room, roomx, roomy, rx, ry, enemies[random(#enemies)])
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function module.add_boss_to_room(room, roomx, roomy)
|
||||
local boss = bosses[1]
|
||||
local boss = bosses[CURRENT_LEVEL / 5]
|
||||
if QUICK_MODE then
|
||||
boss = bosses[CURRENT_LEVEL / 3]
|
||||
end
|
||||
local success = false
|
||||
while not success do
|
||||
local rx = random(13) + 1
|
||||
|
@ -297,6 +433,42 @@ function module.add_boss_to_room(room, roomx, roomy)
|
|||
end
|
||||
end
|
||||
|
||||
function module.add_shopkeeper_to_room(room, roomx, roomy)
|
||||
local success = false
|
||||
while not success do
|
||||
local rx = random(13) + 1
|
||||
local ry = random(9) + 1
|
||||
if room_builder.is_tile_avilable(room, rx, ry) then
|
||||
local x = (roomx * 512) + rx * 32
|
||||
local y = (roomy * 384) + ry * 32
|
||||
room.monsters[rx][ry] = {
|
||||
x,
|
||||
y,
|
||||
shopkeeper
|
||||
}
|
||||
success = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function module.add_bodyguard_to_room(room, roomx, roomy)
|
||||
local success = false
|
||||
while not success do
|
||||
local rx = random(13) + 1
|
||||
local ry = random(9) + 1
|
||||
if room_builder.is_tile_avilable(room, rx, ry) then
|
||||
local x = (roomx * 512) + rx * 32
|
||||
local y = (roomy * 384) + ry * 32
|
||||
room.monsters[rx][ry] = {
|
||||
x,
|
||||
y,
|
||||
bodyguard
|
||||
}
|
||||
success = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function module.load_monsters(map, monsters)
|
||||
for i=0,15 do
|
||||
for j=0,11 do
|
||||
|
@ -309,3 +481,4 @@ function module.load_monsters(map, monsters)
|
|||
end
|
||||
|
||||
return module
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
----------------
|
||||
----------------
|
||||
--##--------##--
|
||||
--##--####--##--
|
||||
-------##-------
|
||||
-------##-------
|
||||
-------##-------
|
||||
-------##-------
|
||||
--##--####--##--
|
||||
--##--------##--
|
||||
--pp--------pp--
|
||||
--pp--pppp--pp--
|
||||
-------pp-------
|
||||
-------pp-------
|
||||
-------pp-------
|
||||
-------pp-------
|
||||
--pp--pppp--pp--
|
||||
--pp--------pp--
|
||||
----------------
|
||||
----------------
|
||||
|
||||
|
@ -15,11 +15,11 @@
|
|||
----------------
|
||||
----------------
|
||||
----------------
|
||||
-----##-##------
|
||||
-----##-##------
|
||||
-----pp-pp------
|
||||
-----pp-pp------
|
||||
----------------
|
||||
-----##-##------
|
||||
-----##-##------
|
||||
-----pp-pp------
|
||||
-----pp-pp------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
|
@ -27,12 +27,12 @@
|
|||
----------------
|
||||
----------------
|
||||
----------------
|
||||
--############--
|
||||
--pppppppppppp--
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
--############--
|
||||
--pppppppppppp--
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
|
@ -40,77 +40,194 @@
|
|||
----------------
|
||||
----------------
|
||||
----------------
|
||||
--############--
|
||||
--pppppppppppp--
|
||||
----------------
|
||||
--############--
|
||||
--############--
|
||||
--pppppppppppp--
|
||||
--pppppppppppp--
|
||||
----------------
|
||||
--############--
|
||||
--pppppppppppp--
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
|
||||
----------------
|
||||
----------------
|
||||
--############--
|
||||
--############--
|
||||
--pppppppppppp--
|
||||
--pppppppppppp--
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
--############--
|
||||
--############--
|
||||
--pppppppppppp--
|
||||
--pppppppppppp--
|
||||
----------------
|
||||
----------------
|
||||
|
||||
----------------
|
||||
----------------
|
||||
-------#--------
|
||||
------###-------
|
||||
-------#--------
|
||||
------###-------
|
||||
------###-------
|
||||
-------#--------
|
||||
------###-------
|
||||
-------#--------
|
||||
-------p--------
|
||||
------ppp-------
|
||||
-------p--------
|
||||
------ppp-------
|
||||
------ppp-------
|
||||
-------p--------
|
||||
------ppp-------
|
||||
-------p--------
|
||||
----------------
|
||||
----------------
|
||||
|
||||
----------------
|
||||
----------------
|
||||
--############--
|
||||
--#----------#--
|
||||
--#----------#--
|
||||
--pppppppppppp--
|
||||
--p----------p--
|
||||
--p----------p--
|
||||
----------------
|
||||
----------------
|
||||
--#----------#--
|
||||
--#----------#--
|
||||
--############--
|
||||
--p----------p--
|
||||
--p----------p--
|
||||
--pppppppppppp--
|
||||
----------------
|
||||
----------------
|
||||
|
||||
----------------
|
||||
----------------
|
||||
--############--
|
||||
--#----------#--
|
||||
--#-########-#--
|
||||
----#-----------
|
||||
-----------#----
|
||||
--#-########-#--
|
||||
--#----------#--
|
||||
--############--
|
||||
--pppppppppppp--
|
||||
--p----------p--
|
||||
--p-pppppppp-p--
|
||||
----p-----------
|
||||
-----------p----
|
||||
--p-pppppppp-p--
|
||||
--p----------p--
|
||||
--pppppppppppp--
|
||||
----------------
|
||||
----------------
|
||||
|
||||
----------------
|
||||
----------------
|
||||
--############--
|
||||
--#----------#--
|
||||
--#-###-####-#--
|
||||
----###---##----
|
||||
----#####-##----
|
||||
--#-#####-##-#--
|
||||
--#----------#--
|
||||
--############--
|
||||
--pppppppppppp--
|
||||
--p----------p--
|
||||
--p-ppp-pppp-p--
|
||||
----ppp---pp----
|
||||
----ppppp-pp----
|
||||
--p-ppppp-pp-p--
|
||||
--p----------p--
|
||||
--pppppppppppp--
|
||||
----------------
|
||||
----------------
|
||||
|
||||
----------------
|
||||
----------------
|
||||
--pp--------pp--
|
||||
--pp--------pp--
|
||||
----------------
|
||||
-------pp-------
|
||||
-------pp-------
|
||||
--p----------p--
|
||||
--p----------p--
|
||||
--pppppppppppp--
|
||||
----------------
|
||||
----------------
|
||||
|
||||
----------------
|
||||
----------------
|
||||
--pp--------pp--
|
||||
--pp--------pp--
|
||||
----------------
|
||||
-------pp-------
|
||||
-------pp-------
|
||||
----------------
|
||||
--pp--------pp--
|
||||
--pp--------pp--
|
||||
----------------
|
||||
----------------
|
||||
|
||||
----------------
|
||||
----------------
|
||||
--pp--------pp--
|
||||
--pp--------pp--
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
--pp--------pp--
|
||||
--pp--------pp--
|
||||
----------------
|
||||
----------------
|
||||
|
||||
----------------
|
||||
----------------
|
||||
--pp---pp---pp--
|
||||
--pp---pp---pp--
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
----------------
|
||||
--pp---pp---pp--
|
||||
--pp---pp---pp--
|
||||
----------------
|
||||
----------------
|
||||
|
||||
----------------
|
||||
----------------
|
||||
--pp---pp---pp--
|
||||
--pp---pp---pp--
|
||||
----------------
|
||||
--pp---pp---pp--
|
||||
--pp---pp---pp--
|
||||
----------------
|
||||
--pp---pp---pp--
|
||||
--pp---pp---pp--
|
||||
----------------
|
||||
----------------
|
||||
|
||||
----------------
|
||||
----------------
|
||||
---p----p----p--
|
||||
--pp---pp---pp--
|
||||
----------------
|
||||
---p----p----p--
|
||||
--pp---pp---pp--
|
||||
----------------
|
||||
---p----p----p--
|
||||
--pp---pp---pp--
|
||||
----------------
|
||||
----------------
|
||||
|
||||
----------------
|
||||
----------------
|
||||
--pp---pp---pp--
|
||||
--p----------p--
|
||||
----------------
|
||||
--p----pp----p--
|
||||
--p----pp----p--
|
||||
----------------
|
||||
--p----------p--
|
||||
--pp---pp---pp--
|
||||
----------------
|
||||
----------------
|
||||
|
||||
----------------
|
||||
----------------
|
||||
--pp---pp---pp--
|
||||
--p----------p--
|
||||
----------------
|
||||
--p----------p--
|
||||
--p----------p--
|
||||
----------------
|
||||
--p----------p--
|
||||
--pp---pp---pp--
|
||||
----------------
|
||||
----------------
|
||||
|
||||
----------------
|
||||
----------------
|
||||
--pp---pp---pp--
|
||||
--p----------p--
|
||||
-----pp--pp-----
|
||||
--p--p----p--p--
|
||||
--p--p----p--p--
|
||||
-----pp--pp-----
|
||||
--p----------p--
|
||||
--pp---pp---pp--
|
||||
----------------
|
||||
----------------
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++##ffffffff##++
|
||||
++#"--------"#++
|
||||
++f---a--a---f++
|
||||
++-----------f++
|
||||
++-----------f++
|
||||
++f---a--a---f++
|
||||
++#"--------"#++
|
||||
++##ffffffff##++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++ffff----ffff++
|
||||
++fppf-a--fppf++
|
||||
++ffff--l-ffff++
|
||||
++------a-----++
|
||||
++------------++
|
||||
++ffff-a--ffff++
|
||||
++fppf-l--fppf++
|
||||
++ffff--a-ffff++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++###########"++
|
||||
++#----------#++
|
||||
++#-####"###-#++
|
||||
++--#aa--aa#-#++
|
||||
++--#--------#++
|
||||
++#-####"###-#++
|
||||
++#----------#++
|
||||
++"###########++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++--pppppppp--++
|
||||
++--pffffffp--++
|
||||
++--pfl--afp--++
|
||||
++-------afp--++
|
||||
++-------afp--++
|
||||
++--pfl--afp--++
|
||||
++--pffffffp--++
|
||||
++--pppppppp--++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++pppppppppppp++
|
||||
++ppffffffffpp++
|
||||
++fffa----afff++
|
||||
++------l-----++
|
||||
++-----l------++
|
||||
++fffa----afff++
|
||||
++ppffffffffpp++
|
||||
++pppppppppppp++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
|
@ -1,6 +1,6 @@
|
|||
local room_builder = require "maproombuilder"
|
||||
local module = {}
|
||||
local random = math.random
|
||||
local random = map_random
|
||||
|
||||
local textures = {
|
||||
"Objects/Trap1.png",
|
||||
|
@ -31,14 +31,33 @@ function module.add_traps_to_room(room)
|
|||
end
|
||||
|
||||
local count = random(4)
|
||||
local attempts = 0;
|
||||
local i = 0
|
||||
while i < count do
|
||||
local rx = random(13) + 1
|
||||
local ry = random(9) + 1
|
||||
if room_builder.is_tile_avilable(room, rx, ry) then
|
||||
room.traps[rx][ry] = traps[random(#traps)]
|
||||
i = i + 1
|
||||
if CURRENT_LEVEL < 4 then
|
||||
if room_builder.is_tile_avilable(room, rx, ry)
|
||||
and not room.traps[rx+1][ry]
|
||||
and not room.traps[rx-1][ry]
|
||||
and not room.traps[rx][ry+1]
|
||||
and not room.traps[rx][ry-1]
|
||||
and not room.traps[rx+1][ry+1]
|
||||
and not room.traps[rx+1][ry-1]
|
||||
and not room.traps[rx-1][ry+1]
|
||||
and not room.traps[rx-1][ry-1]
|
||||
then
|
||||
room.traps[rx][ry] = traps[random(#traps)]
|
||||
i = i + 1
|
||||
end
|
||||
else
|
||||
if room_builder.is_tile_avilable(room, rx, ry) then
|
||||
room.traps[rx][ry] = traps[random(#traps)]
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
attempts = attempts + 1
|
||||
if attempts > 100 then break end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++/#--------#/++
|
||||
++##--------##++
|
||||
++------------++
|
||||
++------------++
|
||||
++------------++
|
||||
++------------++
|
||||
++##--------##++
|
||||
++/#--------#/++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++#--#-#-#-#-#++
|
||||
++---c--------++
|
||||
++/-#-#-#-#--/++
|
||||
++-------c----++
|
||||
++/--#-#-#-#-/++
|
||||
++------------++
|
||||
++--#-#-#-#---++
|
||||
++#-########-#++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++############++
|
||||
++#----------#++
|
||||
++#-/#######-#++
|
||||
++--#------#-#++
|
||||
++--d--cc--d-#++
|
||||
++#-/#######-#++
|
||||
++#----------#++
|
||||
++############++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++/#--------#/++
|
||||
++##-ffffdf-##++
|
||||
++---f--c-f---++
|
||||
++---f----f---++
|
||||
++---f-c--f---++
|
||||
++---f----f---++
|
||||
++##-fdffff-##++
|
||||
++/#--------#/++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++/#ffffffff#/++
|
||||
++#----------#++
|
||||
++---######---++
|
||||
++---d----#---++
|
||||
++---#-cc-d---++
|
||||
++---######---++
|
||||
++#----------#++
|
||||
++/#ffffffff#/++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++/##########/++
|
||||
++d-----d----d++
|
||||
++#c----#---c#++
|
||||
++############++
|
||||
++#----#-----#++
|
||||
++#-c--d--c--#++
|
||||
++d----#-----d++
|
||||
++/##########/++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
||||
++/####-#####/++
|
||||
++#--c#-#c---#++
|
||||
++d---#-#----d++
|
||||
++#####-######++
|
||||
++------------++
|
||||
++#####-######++
|
||||
++d--c#-#c---d++
|
||||
++/####-#####/++
|
||||
++++++++++++++++
|
||||
++++++++++++++++
|
|
@ -0,0 +1,57 @@
|
|||
cmake_minimum_required (VERSION 3.2.0)
|
||||
|
||||
SET(CMAKE_COLOR_MAKEFILE ON)
|
||||
|
||||
project(lua C)
|
||||
|
||||
set(lua_MAJOR_VERSION 5)
|
||||
set(lua_MINOR_VERSION 3)
|
||||
set(lua_PATCH_VERSION 5)
|
||||
|
||||
if (NOT MSVC)
|
||||
add_definitions(-DLUA_USE_POSIX)
|
||||
endif ()
|
||||
|
||||
add_library(lua STATIC
|
||||
src/lapi.c
|
||||
src/lauxlib.c
|
||||
src/lbaselib.c
|
||||
src/lbitlib.c
|
||||
src/lcode.c
|
||||
src/lcorolib.c
|
||||
src/lctype.c
|
||||
src/ldblib.c
|
||||
src/ldebug.c
|
||||
src/ldo.c
|
||||
src/ldump.c
|
||||
src/lfunc.c
|
||||
src/lgc.c
|
||||
src/linit.c
|
||||
src/liolib.c
|
||||
src/llex.c
|
||||
src/lmathlib.c
|
||||
src/lmem.c
|
||||
src/loadlib.c
|
||||
src/lobject.c
|
||||
src/lopcodes.c
|
||||
src/loslib.c
|
||||
src/lparser.c
|
||||
src/lstate.c
|
||||
src/lstring.c
|
||||
src/lstrlib.c
|
||||
src/ltable.c
|
||||
src/ltablib.c
|
||||
src/ltm.c
|
||||
src/lua.c
|
||||
src/luac.c
|
||||
src/lundump.c
|
||||
src/lutf8lib.c
|
||||
src/lvm.c
|
||||
src/lzio.c
|
||||
)
|
||||
|
||||
if (NOT MSVC)
|
||||
target_link_libraries(lua
|
||||
-lm
|
||||
)
|
||||
endif ()
|
|
@ -0,0 +1,197 @@
|
|||
# Makefile for building Lua
|
||||
# See ../doc/readme.html for installation and customization instructions.
|
||||
|
||||
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
|
||||
|
||||
# Your platform. See PLATS for possible values.
|
||||
PLAT= none
|
||||
|
||||
CC= gcc -std=gnu99
|
||||
CFLAGS= -O2 -Wall -Wextra -DLUA_COMPAT_5_2 $(SYSCFLAGS) $(MYCFLAGS)
|
||||
LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS)
|
||||
LIBS= -lm $(SYSLIBS) $(MYLIBS)
|
||||
|
||||
AR= ar rcu
|
||||
RANLIB= ranlib
|
||||
RM= rm -f
|
||||
|
||||
SYSCFLAGS=
|
||||
SYSLDFLAGS=
|
||||
SYSLIBS=
|
||||
|
||||
MYCFLAGS=
|
||||
MYLDFLAGS=
|
||||
MYLIBS=
|
||||
MYOBJS=
|
||||
|
||||
# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
|
||||
|
||||
PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris
|
||||
|
||||
LUA_A= liblua.a
|
||||
CORE_O= lapi.o lcode.o lctype.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
|
||||
LIB_O= lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o \
|
||||
lmathlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o loadlib.o linit.o
|
||||
BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS)
|
||||
|
||||
LUA_T= lua
|
||||
LUA_O= lua.o
|
||||
|
||||
LUAC_T= luac
|
||||
LUAC_O= luac.o
|
||||
|
||||
ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O)
|
||||
ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
|
||||
ALL_A= $(LUA_A)
|
||||
|
||||
# Targets start here.
|
||||
default: $(PLAT)
|
||||
|
||||
all: $(ALL_T)
|
||||
|
||||
o: $(ALL_O)
|
||||
|
||||
a: $(ALL_A)
|
||||
|
||||
$(LUA_A): $(BASE_O)
|
||||
$(AR) $@ $(BASE_O)
|
||||
$(RANLIB) $@
|
||||
|
||||
$(LUA_T): $(LUA_O) $(LUA_A)
|
||||
$(CC) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
|
||||
|
||||
$(LUAC_T): $(LUAC_O) $(LUA_A)
|
||||
$(CC) -o $@ $(LDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)
|
||||
|
||||
clean:
|
||||
$(RM) $(ALL_T) $(ALL_O)
|
||||
|
||||
depend:
|
||||
@$(CC) $(CFLAGS) -MM l*.c
|
||||
|
||||
echo:
|
||||
@echo "PLAT= $(PLAT)"
|
||||
@echo "CC= $(CC)"
|
||||
@echo "CFLAGS= $(CFLAGS)"
|
||||
@echo "LDFLAGS= $(SYSLDFLAGS)"
|
||||
@echo "LIBS= $(LIBS)"
|
||||
@echo "AR= $(AR)"
|
||||
@echo "RANLIB= $(RANLIB)"
|
||||
@echo "RM= $(RM)"
|
||||
|
||||
# Convenience targets for popular platforms
|
||||
ALL= all
|
||||
|
||||
none:
|
||||
@echo "Please do 'make PLATFORM' where PLATFORM is one of these:"
|
||||
@echo " $(PLATS)"
|
||||
|
||||
aix:
|
||||
$(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall"
|
||||
|
||||
bsd:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E"
|
||||
|
||||
c89:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_C89" CC="gcc -std=c89"
|
||||
@echo ''
|
||||
@echo '*** C89 does not guarantee 64-bit integers for Lua.'
|
||||
@echo ''
|
||||
|
||||
|
||||
freebsd:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX -DLUA_USE_READLINE -I/usr/include/edit" SYSLIBS="-Wl,-E -ledit" CC="cc"
|
||||
|
||||
generic: $(ALL)
|
||||
|
||||
linux:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline"
|
||||
|
||||
macosx:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline"
|
||||
|
||||
mingw:
|
||||
$(MAKE) "LUA_A=lua53.dll" "LUA_T=lua.exe" \
|
||||
"AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \
|
||||
"SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe
|
||||
$(MAKE) "LUAC_T=luac.exe" luac.exe
|
||||
|
||||
posix:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX"
|
||||
|
||||
solaris:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN -D_REENTRANT" SYSLIBS="-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 lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
||||
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \
|
||||
ltable.h lundump.h lvm.h
|
||||
lauxlib.o: lauxlib.c lprefix.h lua.h luaconf.h lauxlib.h
|
||||
lbaselib.o: lbaselib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
lbitlib.o: lbitlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
lcode.o: lcode.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
|
||||
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
|
||||
ldo.h lgc.h lstring.h ltable.h lvm.h
|
||||
lcorolib.o: lcorolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
lctype.o: lctype.c lprefix.h lctype.h lua.h luaconf.h llimits.h
|
||||
ldblib.o: ldblib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
ldebug.o: ldebug.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
||||
lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \
|
||||
ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h
|
||||
ldo.o: ldo.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
||||
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \
|
||||
lparser.h lstring.h ltable.h lundump.h lvm.h
|
||||
ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.h \
|
||||
ltm.h lzio.h lmem.h lundump.h
|
||||
lfunc.o: lfunc.c lprefix.h lua.h luaconf.h lfunc.h lobject.h llimits.h \
|
||||
lgc.h lstate.h ltm.h lzio.h lmem.h
|
||||
lgc.o: lgc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h
|
||||
linit.o: linit.c lprefix.h lua.h luaconf.h lualib.h lauxlib.h
|
||||
liolib.o: liolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldebug.h \
|
||||
lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lgc.h llex.h lparser.h \
|
||||
lstring.h ltable.h
|
||||
lmathlib.o: lmathlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
lmem.o: lmem.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h
|
||||
loadlib.o: loadlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
lobject.o: lobject.c lprefix.h lua.h luaconf.h lctype.h llimits.h \
|
||||
ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \
|
||||
lvm.h
|
||||
lopcodes.o: lopcodes.c lprefix.h lopcodes.h llimits.h lua.h luaconf.h
|
||||
loslib.o: loslib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
lparser.o: lparser.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
|
||||
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
|
||||
ldo.h lfunc.h lstring.h lgc.h ltable.h
|
||||
lstate.o: lstate.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
||||
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \
|
||||
lstring.h ltable.h
|
||||
lstring.o: lstring.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
|
||||
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h
|
||||
lstrlib.o: lstrlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
ltable.o: ltable.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
|
||||
ltablib.o: ltablib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||
llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h ltable.h lvm.h
|
||||
lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
luac.o: luac.c lprefix.h lua.h luaconf.h lauxlib.h lobject.h llimits.h \
|
||||
lstate.h ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h
|
||||
lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
|
||||
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \
|
||||
lundump.h
|
||||
lutf8lib.o: lutf8lib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
lvm.o: lvm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \
|
||||
ltable.h lvm.h
|
||||
lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \
|
||||
lobject.h ltm.h lzio.h
|
||||
|
||||
# (end of Makefile)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
** $Id: lapi.h,v 2.9.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Auxiliary functions from Lua API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef lapi_h
|
||||
#define lapi_h
|
||||
|
||||
|
||||
#include "llimits.h"
|
||||
#include "lstate.h"
|
||||
|
||||
#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \
|
||||
"stack overflow");}
|
||||
|
||||
#define adjustresults(L,nres) \
|
||||
{ if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
|
||||
|
||||
#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \
|
||||
"not enough elements in the stack")
|
||||
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
** $Id: lauxlib.h,v 1.131.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Auxiliary functions for building Lua libraries
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#ifndef lauxlib_h
|
||||
#define lauxlib_h
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
|
||||
|
||||
/* extra error code for 'luaL_loadfilex' */
|
||||
#define LUA_ERRFILE (LUA_ERRERR+1)
|
||||
|
||||
|
||||
/* key, in the registry, for table of loaded modules */
|
||||
#define LUA_LOADED_TABLE "_LOADED"
|
||||
|
||||
|
||||
/* key, in the registry, for table of preloaded loaders */
|
||||
#define LUA_PRELOAD_TABLE "_PRELOAD"
|
||||
|
||||
|
||||
typedef struct luaL_Reg {
|
||||
const char *name;
|
||||
lua_CFunction func;
|
||||
} luaL_Reg;
|
||||
|
||||
|
||||
#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number))
|
||||
|
||||
LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz);
|
||||
#define luaL_checkversion(L) \
|
||||
luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES)
|
||||
|
||||
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 const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len);
|
||||
LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg);
|
||||
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg,
|
||||
size_t *l);
|
||||
LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg,
|
||||
const char *def, size_t *l);
|
||||
LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg);
|
||||
LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def);
|
||||
|
||||
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg);
|
||||
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg,
|
||||
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 arg, int t);
|
||||
LUALIB_API void (luaL_checkany) (lua_State *L, int arg);
|
||||
|
||||
LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
|
||||
LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname);
|
||||
LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, 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 arg, const char *def,
|
||||
const char *const lst[]);
|
||||
|
||||
LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname);
|
||||
LUALIB_API int (luaL_execresult) (lua_State *L, int stat);
|
||||
|
||||
/* predefined references */
|
||||
#define LUA_NOREF (-2)
|
||||
#define LUA_REFNIL (-1)
|
||||
|
||||
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_loadfilex) (lua_State *L, const char *filename,
|
||||
const char *mode);
|
||||
|
||||
#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL)
|
||||
|
||||
LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
|
||||
const char *name, const char *mode);
|
||||
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
|
||||
|
||||
LUALIB_API lua_State *(luaL_newstate) (void);
|
||||
|
||||
LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
|
||||
|
||||
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
|
||||
const char *r);
|
||||
|
||||
LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
|
||||
|
||||
LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname);
|
||||
|
||||
LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1,
|
||||
const char *msg, int level);
|
||||
|
||||
LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
|
||||
lua_CFunction openf, int glb);
|
||||
|
||||
/*
|
||||
** ===============================================================
|
||||
** some useful macros
|
||||
** ===============================================================
|
||||
*/
|
||||
|
||||
|
||||
#define luaL_newlibtable(L,l) \
|
||||
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
|
||||
|
||||
#define luaL_newlib(L,l) \
|
||||
(luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
|
||||
|
||||
#define luaL_argcheck(L, cond,arg,extramsg) \
|
||||
((void)((cond) || luaL_argerror(L, (arg), (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_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)))
|
||||
|
||||
#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL)
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Generic Buffer manipulation
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
typedef struct luaL_Buffer {
|
||||
char *b; /* buffer address */
|
||||
size_t size; /* buffer size */
|
||||
size_t n; /* number of characters in buffer */
|
||||
lua_State *L;
|
||||
char initb[LUAL_BUFFERSIZE]; /* initial buffer */
|
||||
} luaL_Buffer;
|
||||
|
||||
|
||||
#define luaL_addchar(B,c) \
|
||||
((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \
|
||||
((B)->b[(B)->n++] = (c)))
|
||||
|
||||
#define luaL_addsize(B,s) ((B)->n += (s))
|
||||
|
||||
LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
|
||||
LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz);
|
||||
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);
|
||||
LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz);
|
||||
LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz);
|
||||
|
||||
#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE)
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** File handles for IO library
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and
|
||||
** initial structure 'luaL_Stream' (it may contain other fields
|
||||
** after that initial structure).
|
||||
*/
|
||||
|
||||
#define LUA_FILEHANDLE "FILE*"
|
||||
|
||||
|
||||
typedef struct luaL_Stream {
|
||||
FILE *f; /* stream (NULL for incompletely created streams) */
|
||||
lua_CFunction closef; /* to close stream (NULL for closed streams) */
|
||||
} luaL_Stream;
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
|
||||
/* compatibility with old module system */
|
||||
#if defined(LUA_COMPAT_MODULE)
|
||||
|
||||
LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname,
|
||||
int sizehint);
|
||||
LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname,
|
||||
const luaL_Reg *l, int nup);
|
||||
|
||||
#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** {==================================================================
|
||||
** "Abstraction Layer" for basic report of messages and errors
|
||||
** ===================================================================
|
||||
*/
|
||||
|
||||
/* print a string */
|
||||
#if !defined(lua_writestring)
|
||||
#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout)
|
||||
#endif
|
||||
|
||||
/* print a newline and flush the output */
|
||||
#if !defined(lua_writeline)
|
||||
#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout))
|
||||
#endif
|
||||
|
||||
/* print an error message */
|
||||
#if !defined(lua_writestringerror)
|
||||
#define lua_writestringerror(s,p) \
|
||||
(fprintf(stderr, (s), (p)), fflush(stderr))
|
||||
#endif
|
||||
|
||||
/* }================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
** {============================================================
|
||||
** Compatibility with deprecated conversions
|
||||
** =============================================================
|
||||
*/
|
||||
#if defined(LUA_COMPAT_APIINTCASTS)
|
||||
|
||||
#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a))
|
||||
#define luaL_optunsigned(L,a,d) \
|
||||
((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d)))
|
||||
|
||||
#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)))
|
||||
|
||||
#endif
|
||||
/* }============================================================ */
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,498 @@
|
|||
/*
|
||||
** $Id: lbaselib.c,v 1.314.1.1 2017/04/19 17:39:34 roberto Exp $
|
||||
** Basic library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define lbaselib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
|
||||
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;
|
||||
size_t l;
|
||||
lua_pushvalue(L, -1); /* function to be called */
|
||||
lua_pushvalue(L, i); /* value to print */
|
||||
lua_call(L, 1, 1);
|
||||
s = lua_tolstring(L, -1, &l); /* get result */
|
||||
if (s == NULL)
|
||||
return luaL_error(L, "'tostring' must return a string to 'print'");
|
||||
if (i>1) lua_writestring("\t", 1);
|
||||
lua_writestring(s, l);
|
||||
lua_pop(L, 1); /* pop result */
|
||||
}
|
||||
lua_writeline();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define SPACECHARS " \f\n\r\t\v"
|
||||
|
||||
static const char *b_str2int (const char *s, int base, lua_Integer *pn) {
|
||||
lua_Unsigned n = 0;
|
||||
int neg = 0;
|
||||
s += strspn(s, SPACECHARS); /* skip initial spaces */
|
||||
if (*s == '-') { s++; neg = 1; } /* handle signal */
|
||||
else if (*s == '+') s++;
|
||||
if (!isalnum((unsigned char)*s)) /* no digit? */
|
||||
return NULL;
|
||||
do {
|
||||
int digit = (isdigit((unsigned char)*s)) ? *s - '0'
|
||||
: (toupper((unsigned char)*s) - 'A') + 10;
|
||||
if (digit >= base) return NULL; /* invalid numeral */
|
||||
n = n * base + digit;
|
||||
s++;
|
||||
} while (isalnum((unsigned char)*s));
|
||||
s += strspn(s, SPACECHARS); /* skip trailing spaces */
|
||||
*pn = (lua_Integer)((neg) ? (0u - n) : n);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_tonumber (lua_State *L) {
|
||||
if (lua_isnoneornil(L, 2)) { /* standard conversion? */
|
||||
luaL_checkany(L, 1);
|
||||
if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */
|
||||
lua_settop(L, 1); /* yes; return it */
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
size_t l;
|
||||
const char *s = lua_tolstring(L, 1, &l);
|
||||
if (s != NULL && lua_stringtonumber(L, s) == l + 1)
|
||||
return 1; /* successful conversion to number */
|
||||
/* else not a number */
|
||||
}
|
||||
}
|
||||
else {
|
||||
size_t l;
|
||||
const char *s;
|
||||
lua_Integer n = 0; /* to avoid warnings */
|
||||
lua_Integer base = luaL_checkinteger(L, 2);
|
||||
luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */
|
||||
s = lua_tolstring(L, 1, &l);
|
||||
luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
|
||||
if (b_str2int(s, (int)base, &n) == s + l) {
|
||||
lua_pushinteger(L, n);
|
||||
return 1;
|
||||
} /* else not a number */
|
||||
} /* else not a number */
|
||||
lua_pushnil(L); /* not a number */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_error (lua_State *L) {
|
||||
int level = (int)luaL_optinteger(L, 2, 1);
|
||||
lua_settop(L, 1);
|
||||
if (lua_type(L, 1) == LUA_TSTRING && level > 0) {
|
||||
luaL_where(L, level); /* add extra information */
|
||||
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") != LUA_TNIL)
|
||||
return luaL_error(L, "cannot change a protected metatable");
|
||||
lua_settop(L, 2);
|
||||
lua_setmetatable(L, 1);
|
||||
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_rawlen (lua_State *L) {
|
||||
int t = lua_type(L, 1);
|
||||
luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1,
|
||||
"table or string expected");
|
||||
lua_pushinteger(L, lua_rawlen(L, 1));
|
||||
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_collectgarbage (lua_State *L) {
|
||||
static const char *const opts[] = {"stop", "restart", "collect",
|
||||
"count", "step", "setpause", "setstepmul",
|
||||
"isrunning", NULL};
|
||||
static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
|
||||
LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL,
|
||||
LUA_GCISRUNNING};
|
||||
int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
|
||||
int ex = (int)luaL_optinteger(L, 2, 0);
|
||||
int res = lua_gc(L, o, ex);
|
||||
switch (o) {
|
||||
case LUA_GCCOUNT: {
|
||||
int b = lua_gc(L, LUA_GCCOUNTB, 0);
|
||||
lua_pushnumber(L, (lua_Number)res + ((lua_Number)b/1024));
|
||||
return 1;
|
||||
}
|
||||
case LUA_GCSTEP: case LUA_GCISRUNNING: {
|
||||
lua_pushboolean(L, res);
|
||||
return 1;
|
||||
}
|
||||
default: {
|
||||
lua_pushinteger(L, res);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_type (lua_State *L) {
|
||||
int t = lua_type(L, 1);
|
||||
luaL_argcheck(L, t != LUA_TNONE, 1, "value expected");
|
||||
lua_pushstring(L, lua_typename(L, t));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int pairsmeta (lua_State *L, const char *method, int iszero,
|
||||
lua_CFunction iter) {
|
||||
luaL_checkany(L, 1);
|
||||
if (luaL_getmetafield(L, 1, method) == LUA_TNIL) { /* no metamethod? */
|
||||
lua_pushcfunction(L, iter); /* will return generator, */
|
||||
lua_pushvalue(L, 1); /* state, */
|
||||
if (iszero) lua_pushinteger(L, 0); /* and initial value */
|
||||
else lua_pushnil(L);
|
||||
}
|
||||
else {
|
||||
lua_pushvalue(L, 1); /* argument 'self' to metamethod */
|
||||
lua_call(L, 1, 3); /* get 3 values from metamethod */
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
return pairsmeta(L, "__pairs", 0, luaB_next);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Traversal function for 'ipairs'
|
||||
*/
|
||||
static int ipairsaux (lua_State *L) {
|
||||
lua_Integer i = luaL_checkinteger(L, 2) + 1;
|
||||
lua_pushinteger(L, i);
|
||||
return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** 'ipairs' function. Returns 'ipairsaux', given "table", 0.
|
||||
** (The given "table" may not be a table.)
|
||||
*/
|
||||
static int luaB_ipairs (lua_State *L) {
|
||||
#if defined(LUA_COMPAT_IPAIRS)
|
||||
return pairsmeta(L, "__ipairs", 1, ipairsaux);
|
||||
#else
|
||||
luaL_checkany(L, 1);
|
||||
lua_pushcfunction(L, ipairsaux); /* iteration function */
|
||||
lua_pushvalue(L, 1); /* state */
|
||||
lua_pushinteger(L, 0); /* initial value */
|
||||
return 3;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int load_aux (lua_State *L, int status, int envidx) {
|
||||
if (status == LUA_OK) {
|
||||
if (envidx != 0) { /* 'env' parameter? */
|
||||
lua_pushvalue(L, envidx); /* environment for loaded function */
|
||||
if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */
|
||||
lua_pop(L, 1); /* remove 'env' if not used by previous call */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else { /* error (message is on top of the stack) */
|
||||
lua_pushnil(L);
|
||||
lua_insert(L, -2); /* put before error message */
|
||||
return 2; /* return nil plus error message */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_loadfile (lua_State *L) {
|
||||
const char *fname = luaL_optstring(L, 1, NULL);
|
||||
const char *mode = luaL_optstring(L, 2, NULL);
|
||||
int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */
|
||||
int status = luaL_loadfilex(L, fname, mode);
|
||||
return load_aux(L, status, env);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Generic Read function
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
** reserved slot, above all arguments, to hold a copy of the returned
|
||||
** string to avoid it being collected while parsed. 'load' has four
|
||||
** optional arguments (chunk, source name, mode, and environment).
|
||||
*/
|
||||
#define RESERVEDSLOT 5
|
||||
|
||||
|
||||
/*
|
||||
** 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); /* not used */
|
||||
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)) {
|
||||
lua_pop(L, 1); /* pop result */
|
||||
*size = 0;
|
||||
return NULL;
|
||||
}
|
||||
else if (!lua_isstring(L, -1))
|
||||
luaL_error(L, "reader function must return a string");
|
||||
lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */
|
||||
return lua_tolstring(L, RESERVEDSLOT, size);
|
||||
}
|
||||
|
||||
|
||||
static int luaB_load (lua_State *L) {
|
||||
int status;
|
||||
size_t l;
|
||||
const char *s = lua_tolstring(L, 1, &l);
|
||||
const char *mode = luaL_optstring(L, 3, "bt");
|
||||
int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */
|
||||
if (s != NULL) { /* loading a string? */
|
||||
const char *chunkname = luaL_optstring(L, 2, s);
|
||||
status = luaL_loadbufferx(L, s, l, chunkname, mode);
|
||||
}
|
||||
else { /* loading from a reader function */
|
||||
const char *chunkname = luaL_optstring(L, 2, "=(load)");
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||
lua_settop(L, RESERVEDSLOT); /* create reserved slot */
|
||||
status = lua_load(L, generic_reader, NULL, chunkname, mode);
|
||||
}
|
||||
return load_aux(L, status, env);
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
static int dofilecont (lua_State *L, int d1, lua_KContext d2) {
|
||||
(void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */
|
||||
return lua_gettop(L) - 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_dofile (lua_State *L) {
|
||||
const char *fname = luaL_optstring(L, 1, NULL);
|
||||
lua_settop(L, 1);
|
||||
if (luaL_loadfile(L, fname) != LUA_OK)
|
||||
return lua_error(L);
|
||||
lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
|
||||
return dofilecont(L, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
static int luaB_assert (lua_State *L) {
|
||||
if (lua_toboolean(L, 1)) /* condition is true? */
|
||||
return lua_gettop(L); /* return all arguments */
|
||||
else { /* error */
|
||||
luaL_checkany(L, 1); /* there must be a condition */
|
||||
lua_remove(L, 1); /* remove it */
|
||||
lua_pushliteral(L, "assertion failed!"); /* default message */
|
||||
lua_settop(L, 1); /* leave only message (default if no other one) */
|
||||
return luaB_error(L); /* call 'error' */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 {
|
||||
lua_Integer i = luaL_checkinteger(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 - (int)i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Continuation function for 'pcall' and 'xpcall'. Both functions
|
||||
** already pushed a 'true' before doing the call, so in case of success
|
||||
** 'finishpcall' only has to return everything in the stack minus
|
||||
** 'extra' values (where 'extra' is exactly the number of items to be
|
||||
** ignored).
|
||||
*/
|
||||
static int finishpcall (lua_State *L, int status, lua_KContext extra) {
|
||||
if (status != LUA_OK && status != LUA_YIELD) { /* error? */
|
||||
lua_pushboolean(L, 0); /* first result (false) */
|
||||
lua_pushvalue(L, -2); /* error message */
|
||||
return 2; /* return false, msg */
|
||||
}
|
||||
else
|
||||
return lua_gettop(L) - (int)extra; /* return all results */
|
||||
}
|
||||
|
||||
|
||||
static int luaB_pcall (lua_State *L) {
|
||||
int status;
|
||||
luaL_checkany(L, 1);
|
||||
lua_pushboolean(L, 1); /* first result if no errors */
|
||||
lua_insert(L, 1); /* put it in place */
|
||||
status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall);
|
||||
return finishpcall(L, status, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Do a protected call with error handling. After 'lua_rotate', the
|
||||
** stack will have <f, err, true, f, [args...]>; so, the function passes
|
||||
** 2 to 'finishpcall' to skip the 2 first values when returning results.
|
||||
*/
|
||||
static int luaB_xpcall (lua_State *L) {
|
||||
int status;
|
||||
int n = lua_gettop(L);
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */
|
||||
lua_pushboolean(L, 1); /* first result */
|
||||
lua_pushvalue(L, 1); /* function */
|
||||
lua_rotate(L, 3, 2); /* move them below function's arguments */
|
||||
status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall);
|
||||
return finishpcall(L, status, 2);
|
||||
}
|
||||
|
||||
|
||||
static int luaB_tostring (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
luaL_tolstring(L, 1, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg base_funcs[] = {
|
||||
{"assert", luaB_assert},
|
||||
{"collectgarbage", luaB_collectgarbage},
|
||||
{"dofile", luaB_dofile},
|
||||
{"error", luaB_error},
|
||||
{"getmetatable", luaB_getmetatable},
|
||||
{"ipairs", luaB_ipairs},
|
||||
{"loadfile", luaB_loadfile},
|
||||
{"load", luaB_load},
|
||||
#if defined(LUA_COMPAT_LOADSTRING)
|
||||
{"loadstring", luaB_load},
|
||||
#endif
|
||||
{"next", luaB_next},
|
||||
{"pairs", luaB_pairs},
|
||||
{"pcall", luaB_pcall},
|
||||
{"print", luaB_print},
|
||||
{"rawequal", luaB_rawequal},
|
||||
{"rawlen", luaB_rawlen},
|
||||
{"rawget", luaB_rawget},
|
||||
{"rawset", luaB_rawset},
|
||||
{"select", luaB_select},
|
||||
{"setmetatable", luaB_setmetatable},
|
||||
{"tonumber", luaB_tonumber},
|
||||
{"tostring", luaB_tostring},
|
||||
{"type", luaB_type},
|
||||
{"xpcall", luaB_xpcall},
|
||||
/* placeholders */
|
||||
{"_G", NULL},
|
||||
{"_VERSION", NULL},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
LUAMOD_API int luaopen_base (lua_State *L) {
|
||||
/* open lib into global table */
|
||||
lua_pushglobaltable(L);
|
||||
luaL_setfuncs(L, base_funcs, 0);
|
||||
/* set global _G */
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -2, "_G");
|
||||
/* set global _VERSION */
|
||||
lua_pushliteral(L, LUA_VERSION);
|
||||
lua_setfield(L, -2, "_VERSION");
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
** $Id: lbitlib.c,v 1.30.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Standard library for bitwise operations
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define lbitlib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
|
||||
#if defined(LUA_COMPAT_BITLIB) /* { */
|
||||
|
||||
|
||||
#define pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n))
|
||||
#define checkunsigned(L,i) ((lua_Unsigned)luaL_checkinteger(L,i))
|
||||
|
||||
|
||||
/* number of bits to consider in a number */
|
||||
#if !defined(LUA_NBITS)
|
||||
#define LUA_NBITS 32
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** a lua_Unsigned with its first LUA_NBITS bits equal to 1. (Shift must
|
||||
** be made in two parts to avoid problems when LUA_NBITS is equal to the
|
||||
** number of bits in a lua_Unsigned.)
|
||||
*/
|
||||
#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1))
|
||||
|
||||
|
||||
/* macro to trim extra bits */
|
||||
#define trim(x) ((x) & ALLONES)
|
||||
|
||||
|
||||
/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */
|
||||
#define mask(n) (~((ALLONES << 1) << ((n) - 1)))
|
||||
|
||||
|
||||
|
||||
static lua_Unsigned andaux (lua_State *L) {
|
||||
int i, n = lua_gettop(L);
|
||||
lua_Unsigned r = ~(lua_Unsigned)0;
|
||||
for (i = 1; i <= n; i++)
|
||||
r &= checkunsigned(L, i);
|
||||
return trim(r);
|
||||
}
|
||||
|
||||
|
||||
static int b_and (lua_State *L) {
|
||||
lua_Unsigned r = andaux(L);
|
||||
pushunsigned(L, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_test (lua_State *L) {
|
||||
lua_Unsigned r = andaux(L);
|
||||
lua_pushboolean(L, r != 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_or (lua_State *L) {
|
||||
int i, n = lua_gettop(L);
|
||||
lua_Unsigned r = 0;
|
||||
for (i = 1; i <= n; i++)
|
||||
r |= checkunsigned(L, i);
|
||||
pushunsigned(L, trim(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_xor (lua_State *L) {
|
||||
int i, n = lua_gettop(L);
|
||||
lua_Unsigned r = 0;
|
||||
for (i = 1; i <= n; i++)
|
||||
r ^= checkunsigned(L, i);
|
||||
pushunsigned(L, trim(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_not (lua_State *L) {
|
||||
lua_Unsigned r = ~checkunsigned(L, 1);
|
||||
pushunsigned(L, trim(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_shift (lua_State *L, lua_Unsigned r, lua_Integer i) {
|
||||
if (i < 0) { /* shift right? */
|
||||
i = -i;
|
||||
r = trim(r);
|
||||
if (i >= LUA_NBITS) r = 0;
|
||||
else r >>= i;
|
||||
}
|
||||
else { /* shift left */
|
||||
if (i >= LUA_NBITS) r = 0;
|
||||
else r <<= i;
|
||||
r = trim(r);
|
||||
}
|
||||
pushunsigned(L, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_lshift (lua_State *L) {
|
||||
return b_shift(L, checkunsigned(L, 1), luaL_checkinteger(L, 2));
|
||||
}
|
||||
|
||||
|
||||
static int b_rshift (lua_State *L) {
|
||||
return b_shift(L, checkunsigned(L, 1), -luaL_checkinteger(L, 2));
|
||||
}
|
||||
|
||||
|
||||
static int b_arshift (lua_State *L) {
|
||||
lua_Unsigned r = checkunsigned(L, 1);
|
||||
lua_Integer i = luaL_checkinteger(L, 2);
|
||||
if (i < 0 || !(r & ((lua_Unsigned)1 << (LUA_NBITS - 1))))
|
||||
return b_shift(L, r, -i);
|
||||
else { /* arithmetic shift for 'negative' number */
|
||||
if (i >= LUA_NBITS) r = ALLONES;
|
||||
else
|
||||
r = trim((r >> i) | ~(trim(~(lua_Unsigned)0) >> i)); /* add signal bit */
|
||||
pushunsigned(L, r);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int b_rot (lua_State *L, lua_Integer d) {
|
||||
lua_Unsigned r = checkunsigned(L, 1);
|
||||
int i = d & (LUA_NBITS - 1); /* i = d % NBITS */
|
||||
r = trim(r);
|
||||
if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */
|
||||
r = (r << i) | (r >> (LUA_NBITS - i));
|
||||
pushunsigned(L, trim(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_lrot (lua_State *L) {
|
||||
return b_rot(L, luaL_checkinteger(L, 2));
|
||||
}
|
||||
|
||||
|
||||
static int b_rrot (lua_State *L) {
|
||||
return b_rot(L, -luaL_checkinteger(L, 2));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** get field and width arguments for field-manipulation functions,
|
||||
** checking whether they are valid.
|
||||
** ('luaL_error' called without 'return' to avoid later warnings about
|
||||
** 'width' being used uninitialized.)
|
||||
*/
|
||||
static int fieldargs (lua_State *L, int farg, int *width) {
|
||||
lua_Integer f = luaL_checkinteger(L, farg);
|
||||
lua_Integer w = luaL_optinteger(L, farg + 1, 1);
|
||||
luaL_argcheck(L, 0 <= f, farg, "field cannot be negative");
|
||||
luaL_argcheck(L, 0 < w, farg + 1, "width must be positive");
|
||||
if (f + w > LUA_NBITS)
|
||||
luaL_error(L, "trying to access non-existent bits");
|
||||
*width = (int)w;
|
||||
return (int)f;
|
||||
}
|
||||
|
||||
|
||||
static int b_extract (lua_State *L) {
|
||||
int w;
|
||||
lua_Unsigned r = trim(checkunsigned(L, 1));
|
||||
int f = fieldargs(L, 2, &w);
|
||||
r = (r >> f) & mask(w);
|
||||
pushunsigned(L, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_replace (lua_State *L) {
|
||||
int w;
|
||||
lua_Unsigned r = trim(checkunsigned(L, 1));
|
||||
lua_Unsigned v = trim(checkunsigned(L, 2));
|
||||
int f = fieldargs(L, 3, &w);
|
||||
lua_Unsigned m = mask(w);
|
||||
r = (r & ~(m << f)) | ((v & m) << f);
|
||||
pushunsigned(L, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg bitlib[] = {
|
||||
{"arshift", b_arshift},
|
||||
{"band", b_and},
|
||||
{"bnot", b_not},
|
||||
{"bor", b_or},
|
||||
{"bxor", b_xor},
|
||||
{"btest", b_test},
|
||||
{"extract", b_extract},
|
||||
{"lrotate", b_lrot},
|
||||
{"lshift", b_lshift},
|
||||
{"replace", b_replace},
|
||||
{"rrotate", b_rrot},
|
||||
{"rshift", b_rshift},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
|
||||
LUAMOD_API int luaopen_bit32 (lua_State *L) {
|
||||
luaL_newlib(L, bitlib);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#else /* }{ */
|
||||
|
||||
|
||||
LUAMOD_API int luaopen_bit32 (lua_State *L) {
|
||||
return luaL_error(L, "library 'bit32' has been deprecated");
|
||||
}
|
||||
|
||||
#endif /* } */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
** $Id: lcode.h,v 1.64.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Code generator for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#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 (ORDER OP)
|
||||
*/
|
||||
typedef enum BinOpr {
|
||||
OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW,
|
||||
OPR_DIV,
|
||||
OPR_IDIV,
|
||||
OPR_BAND, OPR_BOR, OPR_BXOR,
|
||||
OPR_SHL, OPR_SHR,
|
||||
OPR_CONCAT,
|
||||
OPR_EQ, OPR_LT, OPR_LE,
|
||||
OPR_NE, OPR_GT, OPR_GE,
|
||||
OPR_AND, OPR_OR,
|
||||
OPR_NOBINOPR
|
||||
} BinOpr;
|
||||
|
||||
|
||||
typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
|
||||
|
||||
|
||||
/* get (pointer to) instruction of given 'expdesc' */
|
||||
#define getinstruction(fs,e) ((fs)->f->code[(e)->u.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)
|
||||
|
||||
#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t)
|
||||
|
||||
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 int luaK_codek (FuncState *fs, int reg, int k);
|
||||
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_intK (FuncState *fs, lua_Integer n);
|
||||
LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC void luaK_exp2anyregup (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_goiffalse (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_patchclose (FuncState *fs, int list, int level);
|
||||
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, int line);
|
||||
LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
|
||||
LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1,
|
||||
expdesc *v2, int line);
|
||||
LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
** $Id: lcorolib.c,v 1.10.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Coroutine Library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define lcorolib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
|
||||
static lua_State *getco (lua_State *L) {
|
||||
lua_State *co = lua_tothread(L, 1);
|
||||
luaL_argcheck(L, co, 1, "thread expected");
|
||||
return co;
|
||||
}
|
||||
|
||||
|
||||
static int auxresume (lua_State *L, lua_State *co, int narg) {
|
||||
int status;
|
||||
if (!lua_checkstack(co, narg)) {
|
||||
lua_pushliteral(L, "too many arguments to resume");
|
||||
return -1; /* error flag */
|
||||
}
|
||||
if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) {
|
||||
lua_pushliteral(L, "cannot resume dead coroutine");
|
||||
return -1; /* error flag */
|
||||
}
|
||||
lua_xmove(L, co, narg);
|
||||
status = lua_resume(co, L, narg);
|
||||
if (status == LUA_OK || status == LUA_YIELD) {
|
||||
int nres = lua_gettop(co);
|
||||
if (!lua_checkstack(L, nres + 1)) {
|
||||
lua_pop(co, nres); /* remove results anyway */
|
||||
lua_pushliteral(L, "too many results to resume");
|
||||
return -1; /* error flag */
|
||||
}
|
||||
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 = getco(L);
|
||||
int r;
|
||||
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_type(L, -1) == LUA_TSTRING) { /* error object is a string? */
|
||||
luaL_where(L, 1); /* add extra info */
|
||||
lua_insert(L, -2);
|
||||
lua_concat(L, 2);
|
||||
}
|
||||
return lua_error(L); /* propagate error */
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_cocreate (lua_State *L) {
|
||||
lua_State *NL;
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||
NL = lua_newthread(L);
|
||||
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_costatus (lua_State *L) {
|
||||
lua_State *co = getco(L);
|
||||
if (L == co) lua_pushliteral(L, "running");
|
||||
else {
|
||||
switch (lua_status(co)) {
|
||||
case LUA_YIELD:
|
||||
lua_pushliteral(L, "suspended");
|
||||
break;
|
||||
case LUA_OK: {
|
||||
lua_Debug ar;
|
||||
if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */
|
||||
lua_pushliteral(L, "normal"); /* it is running */
|
||||
else if (lua_gettop(co) == 0)
|
||||
lua_pushliteral(L, "dead");
|
||||
else
|
||||
lua_pushliteral(L, "suspended"); /* initial state */
|
||||
break;
|
||||
}
|
||||
default: /* some error occurred */
|
||||
lua_pushliteral(L, "dead");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_yieldable (lua_State *L) {
|
||||
lua_pushboolean(L, lua_isyieldable(L));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_corunning (lua_State *L) {
|
||||
int ismain = lua_pushthread(L);
|
||||
lua_pushboolean(L, ismain);
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg co_funcs[] = {
|
||||
{"create", luaB_cocreate},
|
||||
{"resume", luaB_coresume},
|
||||
{"running", luaB_corunning},
|
||||
{"status", luaB_costatus},
|
||||
{"wrap", luaB_cowrap},
|
||||
{"yield", luaB_yield},
|
||||
{"isyieldable", luaB_yieldable},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
|
||||
LUAMOD_API int luaopen_coroutine (lua_State *L) {
|
||||
luaL_newlib(L, co_funcs);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
** $Id: lctype.c,v 1.12.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** 'ctype' functions for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define lctype_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include "lctype.h"
|
||||
|
||||
#if !LUA_USE_CTYPE /* { */
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = {
|
||||
0x00, /* EOZ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */
|
||||
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */
|
||||
0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */
|
||||
0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05,
|
||||
0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */
|
||||
0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
#endif /* } */
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
** $Id: lctype.h,v 1.12.1.1 2013/04/12 18:48:47 roberto Exp $
|
||||
** 'ctype' functions for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef lctype_h
|
||||
#define lctype_h
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
|
||||
/*
|
||||
** WARNING: the functions defined here do not necessarily correspond
|
||||
** to the similar functions in the standard C ctype.h. They are
|
||||
** optimized for the specific needs of Lua
|
||||
*/
|
||||
|
||||
#if !defined(LUA_USE_CTYPE)
|
||||
|
||||
#if 'A' == 65 && '0' == 48
|
||||
/* ASCII case: can use its own tables; faster and fixed */
|
||||
#define LUA_USE_CTYPE 0
|
||||
#else
|
||||
/* must use standard C ctype */
|
||||
#define LUA_USE_CTYPE 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if !LUA_USE_CTYPE /* { */
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "llimits.h"
|
||||
|
||||
|
||||
#define ALPHABIT 0
|
||||
#define DIGITBIT 1
|
||||
#define PRINTBIT 2
|
||||
#define SPACEBIT 3
|
||||
#define XDIGITBIT 4
|
||||
|
||||
|
||||
#define MASK(B) (1 << (B))
|
||||
|
||||
|
||||
/*
|
||||
** add 1 to char to allow index -1 (EOZ)
|
||||
*/
|
||||
#define testprop(c,p) (luai_ctype_[(c)+1] & (p))
|
||||
|
||||
/*
|
||||
** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_'
|
||||
*/
|
||||
#define lislalpha(c) testprop(c, MASK(ALPHABIT))
|
||||
#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT)))
|
||||
#define lisdigit(c) testprop(c, MASK(DIGITBIT))
|
||||
#define lisspace(c) testprop(c, MASK(SPACEBIT))
|
||||
#define lisprint(c) testprop(c, MASK(PRINTBIT))
|
||||
#define lisxdigit(c) testprop(c, MASK(XDIGITBIT))
|
||||
|
||||
/*
|
||||
** this 'ltolower' only works for alphabetic characters
|
||||
*/
|
||||
#define ltolower(c) ((c) | ('A' ^ 'a'))
|
||||
|
||||
|
||||
/* two more entries for 0 and -1 (EOZ) */
|
||||
LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2];
|
||||
|
||||
|
||||
#else /* }{ */
|
||||
|
||||
/*
|
||||
** use standard C ctypes
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
#define lislalpha(c) (isalpha(c) || (c) == '_')
|
||||
#define lislalnum(c) (isalnum(c) || (c) == '_')
|
||||
#define lisdigit(c) (isdigit(c))
|
||||
#define lisspace(c) (isspace(c))
|
||||
#define lisprint(c) (isprint(c))
|
||||
#define lisxdigit(c) (isxdigit(c))
|
||||
|
||||
#define ltolower(c) (tolower(c))
|
||||
|
||||
#endif /* } */
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,456 @@
|
|||
/*
|
||||
** $Id: ldblib.c,v 1.151.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Interface from Lua to its debug API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define ldblib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
|
||||
/*
|
||||
** The hook table at registry[&HOOKKEY] maps threads to their current
|
||||
** hook function. (We only need the unique address of 'HOOKKEY'.)
|
||||
*/
|
||||
static const int HOOKKEY = 0;
|
||||
|
||||
|
||||
/*
|
||||
** If L1 != L, L1 can be in any state, and therefore there are no
|
||||
** guarantees about its stack space; any push in L1 must be
|
||||
** checked.
|
||||
*/
|
||||
static void checkstack (lua_State *L, lua_State *L1, int n) {
|
||||
if (L != L1 && !lua_checkstack(L1, n))
|
||||
luaL_error(L, "stack overflow");
|
||||
}
|
||||
|
||||
|
||||
static int db_getregistry (lua_State *L) {
|
||||
lua_pushvalue(L, LUA_REGISTRYINDEX);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
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_setmetatable(L, 1);
|
||||
return 1; /* return 1st argument */
|
||||
}
|
||||
|
||||
|
||||
static int db_getuservalue (lua_State *L) {
|
||||
if (lua_type(L, 1) != LUA_TUSERDATA)
|
||||
lua_pushnil(L);
|
||||
else
|
||||
lua_getuservalue(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int db_setuservalue (lua_State *L) {
|
||||
luaL_checktype(L, 1, LUA_TUSERDATA);
|
||||
luaL_checkany(L, 2);
|
||||
lua_settop(L, 2);
|
||||
lua_setuservalue(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Auxiliary function used by several library functions: check for
|
||||
** an optional thread as function's first argument and set 'arg' with
|
||||
** 1 if this argument is present (so that functions can skip it to
|
||||
** access their other arguments)
|
||||
*/
|
||||
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; /* function will operate over current thread */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Variations of 'lua_settable', used by 'db_getinfo' to put results
|
||||
** from 'lua_getinfo' into result table. Key is always a string;
|
||||
** value can be a string, an int, or a boolean.
|
||||
*/
|
||||
static void settabss (lua_State *L, const char *k, const char *v) {
|
||||
lua_pushstring(L, v);
|
||||
lua_setfield(L, -2, k);
|
||||
}
|
||||
|
||||
static void settabsi (lua_State *L, const char *k, int v) {
|
||||
lua_pushinteger(L, v);
|
||||
lua_setfield(L, -2, k);
|
||||
}
|
||||
|
||||
static void settabsb (lua_State *L, const char *k, int v) {
|
||||
lua_pushboolean(L, v);
|
||||
lua_setfield(L, -2, k);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** In function 'db_getinfo', the call to 'lua_getinfo' may push
|
||||
** results on the stack; later it creates the result table to put
|
||||
** these objects. Function 'treatstackoption' puts the result from
|
||||
** 'lua_getinfo' on top of the result table so that it can call
|
||||
** 'lua_setfield'.
|
||||
*/
|
||||
static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
|
||||
if (L == L1)
|
||||
lua_rotate(L, -2, 1); /* exchange object and table */
|
||||
else
|
||||
lua_xmove(L1, L, 1); /* move object to the "main" stack */
|
||||
lua_setfield(L, -2, fname); /* put object into table */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Calls 'lua_getinfo' and collects all results in a new table.
|
||||
** L1 needs stack space for an optional input (function) plus
|
||||
** two optional outputs (function and line table) from function
|
||||
** 'lua_getinfo'.
|
||||
*/
|
||||
static int db_getinfo (lua_State *L) {
|
||||
lua_Debug ar;
|
||||
int arg;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
const char *options = luaL_optstring(L, arg+2, "flnStu");
|
||||
checkstack(L, L1, 3);
|
||||
if (lua_isfunction(L, arg + 1)) { /* info about a function? */
|
||||
options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */
|
||||
lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */
|
||||
lua_xmove(L, L1, 1);
|
||||
}
|
||||
else { /* stack level */
|
||||
if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) {
|
||||
lua_pushnil(L); /* level out of range */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!lua_getinfo(L1, options, &ar))
|
||||
return luaL_argerror(L, arg+2, "invalid option");
|
||||
lua_newtable(L); /* table to collect results */
|
||||
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);
|
||||
settabsi(L, "nparams", ar.nparams);
|
||||
settabsb(L, "isvararg", ar.isvararg);
|
||||
}
|
||||
if (strchr(options, 'n')) {
|
||||
settabss(L, "name", ar.name);
|
||||
settabss(L, "namewhat", ar.namewhat);
|
||||
}
|
||||
if (strchr(options, 't'))
|
||||
settabsb(L, "istailcall", ar.istailcall);
|
||||
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;
|
||||
int nvar = (int)luaL_checkinteger(L, arg + 2); /* local-variable index */
|
||||
if (lua_isfunction(L, arg + 1)) { /* function argument? */
|
||||
lua_pushvalue(L, arg + 1); /* push function */
|
||||
lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */
|
||||
return 1; /* return only name (there is no value) */
|
||||
}
|
||||
else { /* stack-level argument */
|
||||
int level = (int)luaL_checkinteger(L, arg + 1);
|
||||
if (!lua_getstack(L1, level, &ar)) /* out of range? */
|
||||
return luaL_argerror(L, arg+1, "level out of range");
|
||||
checkstack(L, L1, 1);
|
||||
name = lua_getlocal(L1, &ar, nvar);
|
||||
if (name) {
|
||||
lua_xmove(L1, L, 1); /* move local value */
|
||||
lua_pushstring(L, name); /* push name */
|
||||
lua_rotate(L, -2, 1); /* re-order */
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
lua_pushnil(L); /* no name (nor value) */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int db_setlocal (lua_State *L) {
|
||||
int arg;
|
||||
const char *name;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
lua_Debug ar;
|
||||
int level = (int)luaL_checkinteger(L, arg + 1);
|
||||
int nvar = (int)luaL_checkinteger(L, arg + 2);
|
||||
if (!lua_getstack(L1, level, &ar)) /* out of range? */
|
||||
return luaL_argerror(L, arg+1, "level out of range");
|
||||
luaL_checkany(L, arg+3);
|
||||
lua_settop(L, arg+3);
|
||||
checkstack(L, L1, 1);
|
||||
lua_xmove(L, L1, 1);
|
||||
name = lua_setlocal(L1, &ar, nvar);
|
||||
if (name == NULL)
|
||||
lua_pop(L1, 1); /* pop value (if not popped by 'lua_setlocal') */
|
||||
lua_pushstring(L, name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** get (if 'get' is true) or set an upvalue from a closure
|
||||
*/
|
||||
static int auxupvalue (lua_State *L, int get) {
|
||||
const char *name;
|
||||
int n = (int)luaL_checkinteger(L, 2); /* upvalue index */
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION); /* closure */
|
||||
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)); /* no-op if get is false */
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Check whether a given upvalue from a given closure exists and
|
||||
** returns its index
|
||||
*/
|
||||
static int checkupval (lua_State *L, int argf, int argnup) {
|
||||
int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */
|
||||
luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */
|
||||
luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup,
|
||||
"invalid upvalue index");
|
||||
return nup;
|
||||
}
|
||||
|
||||
|
||||
static int db_upvalueid (lua_State *L) {
|
||||
int n = checkupval(L, 1, 2);
|
||||
lua_pushlightuserdata(L, lua_upvalueid(L, 1, n));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int db_upvaluejoin (lua_State *L) {
|
||||
int n1 = checkupval(L, 1, 2);
|
||||
int n2 = checkupval(L, 3, 4);
|
||||
luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected");
|
||||
luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected");
|
||||
lua_upvaluejoin(L, 1, n1, 3, n2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Call hook function registered at hook table for the current
|
||||
** thread (if there is one)
|
||||
*/
|
||||
static void hookf (lua_State *L, lua_Debug *ar) {
|
||||
static const char *const hooknames[] =
|
||||
{"call", "return", "line", "count", "tail call"};
|
||||
lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY);
|
||||
lua_pushthread(L);
|
||||
if (lua_rawget(L, -2) == LUA_TFUNCTION) { /* is there a hook function? */
|
||||
lua_pushstring(L, hooknames[(int)ar->event]); /* push event name */
|
||||
if (ar->currentline >= 0)
|
||||
lua_pushinteger(L, ar->currentline); /* push current line */
|
||||
else lua_pushnil(L);
|
||||
lua_assert(lua_getinfo(L, "lS", ar));
|
||||
lua_call(L, 2, 0); /* call hook function */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Convert a string mask (for 'sethook') into a bit mask
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Convert a bit mask (for 'gethook') into a string 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 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)) { /* no hook? */
|
||||
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 = (int)luaL_optinteger(L, arg + 3, 0);
|
||||
func = hookf; mask = makemask(smask, count);
|
||||
}
|
||||
if (lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY) == LUA_TNIL) {
|
||||
lua_createtable(L, 0, 2); /* create a hook table */
|
||||
lua_pushvalue(L, -1);
|
||||
lua_rawsetp(L, LUA_REGISTRYINDEX, &HOOKKEY); /* set it in position */
|
||||
lua_pushstring(L, "k");
|
||||
lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */
|
||||
}
|
||||
checkstack(L, L1, 1);
|
||||
lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */
|
||||
lua_pushvalue(L, arg + 1); /* value (hook function) */
|
||||
lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */
|
||||
lua_sethook(L1, func, mask, count);
|
||||
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) /* no hook? */
|
||||
lua_pushnil(L);
|
||||
else if (hook != hookf) /* external hook? */
|
||||
lua_pushliteral(L, "external hook");
|
||||
else { /* hook table must exist */
|
||||
lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY);
|
||||
checkstack(L, L1, 1);
|
||||
lua_pushthread(L1); lua_xmove(L1, L, 1);
|
||||
lua_rawget(L, -2); /* 1st result = hooktable[L1] */
|
||||
lua_remove(L, -2); /* remove hook table */
|
||||
}
|
||||
lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */
|
||||
lua_pushinteger(L, lua_gethookcount(L1)); /* 3rd result = count */
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
static int db_debug (lua_State *L) {
|
||||
for (;;) {
|
||||
char buffer[250];
|
||||
lua_writestringerror("%s", "lua_debug> ");
|
||||
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))
|
||||
lua_writestringerror("%s\n", lua_tostring(L, -1));
|
||||
lua_settop(L, 0); /* remove eventual returns */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int db_traceback (lua_State *L) {
|
||||
int arg;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
const char *msg = lua_tostring(L, arg + 1);
|
||||
if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */
|
||||
lua_pushvalue(L, arg + 1); /* return it untouched */
|
||||
else {
|
||||
int level = (int)luaL_optinteger(L, arg + 2, (L == L1) ? 1 : 0);
|
||||
luaL_traceback(L, L1, msg, level);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg dblib[] = {
|
||||
{"debug", db_debug},
|
||||
{"getuservalue", db_getuservalue},
|
||||
{"gethook", db_gethook},
|
||||
{"getinfo", db_getinfo},
|
||||
{"getlocal", db_getlocal},
|
||||
{"getregistry", db_getregistry},
|
||||
{"getmetatable", db_getmetatable},
|
||||
{"getupvalue", db_getupvalue},
|
||||
{"upvaluejoin", db_upvaluejoin},
|
||||
{"upvalueid", db_upvalueid},
|
||||
{"setuservalue", db_setuservalue},
|
||||
{"sethook", db_sethook},
|
||||
{"setlocal", db_setlocal},
|
||||
{"setmetatable", db_setmetatable},
|
||||
{"setupvalue", db_setupvalue},
|
||||
{"traceback", db_traceback},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
LUAMOD_API int luaopen_debug (lua_State *L) {
|
||||
luaL_newlib(L, dblib);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,699 @@
|
|||
/*
|
||||
** $Id: ldebug.c,v 2.121.1.2 2017/07/10 17:21:50 roberto Exp $
|
||||
** Debug Interface
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define ldebug_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#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"
|
||||
|
||||
|
||||
|
||||
#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL)
|
||||
|
||||
|
||||
/* Active Lua function (given call info) */
|
||||
#define ci_func(ci) (clLvalue((ci)->func))
|
||||
|
||||
|
||||
static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
|
||||
const char **name);
|
||||
|
||||
|
||||
static int currentpc (CallInfo *ci) {
|
||||
lua_assert(isLua(ci));
|
||||
return pcRel(ci->u.l.savedpc, ci_func(ci)->p);
|
||||
}
|
||||
|
||||
|
||||
static int currentline (CallInfo *ci) {
|
||||
return getfuncline(ci_func(ci)->p, currentpc(ci));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** If function yielded, its 'func' can be in the 'extra' field. The
|
||||
** next function restores 'func' to its correct value for debugging
|
||||
** purposes. (It exchanges 'func' and 'extra'; so, when called again,
|
||||
** after debugging, it also "re-restores" ** 'func' to its altered value.
|
||||
*/
|
||||
static void swapextra (lua_State *L) {
|
||||
if (L->status == LUA_YIELD) {
|
||||
CallInfo *ci = L->ci; /* get function that yielded */
|
||||
StkId temp = ci->func; /* exchange its 'func' and 'extra' values */
|
||||
ci->func = restorestack(L, ci->extra);
|
||||
ci->extra = savestack(L, temp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** This function can be called asynchronously (e.g. during a signal).
|
||||
** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by
|
||||
** 'resethookcount') are for debug only, and it is no problem if they
|
||||
** get arbitrary values (causes at most one wrong hook call). 'hookmask'
|
||||
** is an atomic value. We assume that pointers are atomic too (e.g., gcc
|
||||
** ensures that for all platforms where it runs). Moreover, 'hook' is
|
||||
** always checked before being called (see 'luaD_hook').
|
||||
*/
|
||||
LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
|
||||
if (func == NULL || mask == 0) { /* turn off hooks? */
|
||||
mask = 0;
|
||||
func = NULL;
|
||||
}
|
||||
if (isLua(L->ci))
|
||||
L->oldpc = L->ci->u.l.savedpc;
|
||||
L->hook = func;
|
||||
L->basehookcount = count;
|
||||
resethookcount(L);
|
||||
L->hookmask = cast_byte(mask);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
if (level < 0) return 0; /* invalid (negative) level */
|
||||
lua_lock(L);
|
||||
for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous)
|
||||
level--;
|
||||
if (level == 0 && ci != &L->base_ci) { /* level found? */
|
||||
status = 1;
|
||||
ar->i_ci = ci;
|
||||
}
|
||||
else status = 0; /* no such level */
|
||||
lua_unlock(L);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static const char *upvalname (Proto *p, int uv) {
|
||||
TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name);
|
||||
if (s == NULL) return "?";
|
||||
else return getstr(s);
|
||||
}
|
||||
|
||||
|
||||
static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
|
||||
int nparams = clLvalue(ci->func)->p->numparams;
|
||||
if (n >= cast_int(ci->u.l.base - ci->func) - nparams)
|
||||
return NULL; /* no such vararg */
|
||||
else {
|
||||
*pos = ci->func + nparams + n;
|
||||
return "(*vararg)"; /* generic name for any vararg */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char *findlocal (lua_State *L, CallInfo *ci, int n,
|
||||
StkId *pos) {
|
||||
const char *name = NULL;
|
||||
StkId base;
|
||||
if (isLua(ci)) {
|
||||
if (n < 0) /* access to vararg values? */
|
||||
return findvararg(ci, -n, pos);
|
||||
else {
|
||||
base = ci->u.l.base;
|
||||
name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci));
|
||||
}
|
||||
}
|
||||
else
|
||||
base = ci->func + 1;
|
||||
if (name == NULL) { /* no 'standard' name? */
|
||||
StkId limit = (ci == L->ci) ? L->top : ci->next->func;
|
||||
if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */
|
||||
name = "(*temporary)"; /* generic name for any valid slot */
|
||||
else
|
||||
return NULL; /* no name */
|
||||
}
|
||||
*pos = base + (n - 1);
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
|
||||
const char *name;
|
||||
lua_lock(L);
|
||||
swapextra(L);
|
||||
if (ar == NULL) { /* information about non-active function? */
|
||||
if (!isLfunction(L->top - 1)) /* not a Lua function? */
|
||||
name = NULL;
|
||||
else /* consider live variables at function start (parameters) */
|
||||
name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0);
|
||||
}
|
||||
else { /* active function; get information through 'ar' */
|
||||
StkId pos = NULL; /* to avoid warnings */
|
||||
name = findlocal(L, ar->i_ci, n, &pos);
|
||||
if (name) {
|
||||
setobj2s(L, L->top, pos);
|
||||
api_incr_top(L);
|
||||
}
|
||||
}
|
||||
swapextra(L);
|
||||
lua_unlock(L);
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
|
||||
StkId pos = NULL; /* to avoid warnings */
|
||||
const char *name;
|
||||
lua_lock(L);
|
||||
swapextra(L);
|
||||
name = findlocal(L, ar->i_ci, n, &pos);
|
||||
if (name) {
|
||||
setobjs2s(L, pos, L->top - 1);
|
||||
L->top--; /* pop value */
|
||||
}
|
||||
swapextra(L);
|
||||
lua_unlock(L);
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
static void funcinfo (lua_Debug *ar, Closure *cl) {
|
||||
if (noLuaClosure(cl)) {
|
||||
ar->source = "=[C]";
|
||||
ar->linedefined = -1;
|
||||
ar->lastlinedefined = -1;
|
||||
ar->what = "C";
|
||||
}
|
||||
else {
|
||||
Proto *p = cl->l.p;
|
||||
ar->source = p->source ? getstr(p->source) : "=?";
|
||||
ar->linedefined = p->linedefined;
|
||||
ar->lastlinedefined = p->lastlinedefined;
|
||||
ar->what = (ar->linedefined == 0) ? "main" : "Lua";
|
||||
}
|
||||
luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
|
||||
}
|
||||
|
||||
|
||||
static void collectvalidlines (lua_State *L, Closure *f) {
|
||||
if (noLuaClosure(f)) {
|
||||
setnilvalue(L->top);
|
||||
api_incr_top(L);
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
TValue v;
|
||||
int *lineinfo = f->l.p->lineinfo;
|
||||
Table *t = luaH_new(L); /* new table to store active lines */
|
||||
sethvalue(L, L->top, t); /* push it on stack */
|
||||
api_incr_top(L);
|
||||
setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */
|
||||
for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */
|
||||
luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
|
||||
if (ci == NULL) /* no 'ci'? */
|
||||
return NULL; /* no info */
|
||||
else if (ci->callstatus & CIST_FIN) { /* is this a finalizer? */
|
||||
*name = "__gc";
|
||||
return "metamethod"; /* report it as such */
|
||||
}
|
||||
/* calling function is a known Lua function? */
|
||||
else if (!(ci->callstatus & CIST_TAIL) && isLua(ci->previous))
|
||||
return funcnamefromcode(L, ci->previous, name);
|
||||
else return NULL; /* no way to find a name */
|
||||
}
|
||||
|
||||
|
||||
static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
|
||||
Closure *f, CallInfo *ci) {
|
||||
int status = 1;
|
||||
for (; *what; what++) {
|
||||
switch (*what) {
|
||||
case 'S': {
|
||||
funcinfo(ar, f);
|
||||
break;
|
||||
}
|
||||
case 'l': {
|
||||
ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1;
|
||||
break;
|
||||
}
|
||||
case 'u': {
|
||||
ar->nups = (f == NULL) ? 0 : f->c.nupvalues;
|
||||
if (noLuaClosure(f)) {
|
||||
ar->isvararg = 1;
|
||||
ar->nparams = 0;
|
||||
}
|
||||
else {
|
||||
ar->isvararg = f->l.p->is_vararg;
|
||||
ar->nparams = f->l.p->numparams;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 't': {
|
||||
ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0;
|
||||
break;
|
||||
}
|
||||
case 'n': {
|
||||
ar->namewhat = getfuncname(L, ci, &ar->name);
|
||||
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 *cl;
|
||||
CallInfo *ci;
|
||||
StkId func;
|
||||
lua_lock(L);
|
||||
swapextra(L);
|
||||
if (*what == '>') {
|
||||
ci = NULL;
|
||||
func = L->top - 1;
|
||||
api_check(L, ttisfunction(func), "function expected");
|
||||
what++; /* skip the '>' */
|
||||
L->top--; /* pop function */
|
||||
}
|
||||
else {
|
||||
ci = ar->i_ci;
|
||||
func = ci->func;
|
||||
lua_assert(ttisfunction(ci->func));
|
||||
}
|
||||
cl = ttisclosure(func) ? clvalue(func) : NULL;
|
||||
status = auxgetinfo(L, what, ar, cl, ci);
|
||||
if (strchr(what, 'f')) {
|
||||
setobjs2s(L, L->top, func);
|
||||
api_incr_top(L);
|
||||
}
|
||||
swapextra(L); /* correct before option 'L', which can raise a mem. error */
|
||||
if (strchr(what, 'L'))
|
||||
collectvalidlines(L, cl);
|
||||
lua_unlock(L);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Symbolic Execution
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
static const char *getobjname (Proto *p, int lastpc, int reg,
|
||||
const char **name);
|
||||
|
||||
|
||||
/*
|
||||
** find a "name" for the RK value 'c'
|
||||
*/
|
||||
static void kname (Proto *p, int pc, int c, const char **name) {
|
||||
if (ISK(c)) { /* is 'c' a constant? */
|
||||
TValue *kvalue = &p->k[INDEXK(c)];
|
||||
if (ttisstring(kvalue)) { /* literal constant? */
|
||||
*name = svalue(kvalue); /* it is its own name */
|
||||
return;
|
||||
}
|
||||
/* else no reasonable name found */
|
||||
}
|
||||
else { /* 'c' is a register */
|
||||
const char *what = getobjname(p, pc, c, name); /* search for 'c' */
|
||||
if (what && *what == 'c') { /* found a constant name? */
|
||||
return; /* 'name' already filled */
|
||||
}
|
||||
/* else no reasonable name found */
|
||||
}
|
||||
*name = "?"; /* no reasonable name found */
|
||||
}
|
||||
|
||||
|
||||
static int filterpc (int pc, int jmptarget) {
|
||||
if (pc < jmptarget) /* is code conditional (inside a jump)? */
|
||||
return -1; /* cannot know who sets that register */
|
||||
else return pc; /* current position sets that register */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** try to find last instruction before 'lastpc' that modified register 'reg'
|
||||
*/
|
||||
static int findsetreg (Proto *p, int lastpc, int reg) {
|
||||
int pc;
|
||||
int setreg = -1; /* keep last instruction that changed 'reg' */
|
||||
int jmptarget = 0; /* any code before this address is conditional */
|
||||
for (pc = 0; pc < lastpc; pc++) {
|
||||
Instruction i = p->code[pc];
|
||||
OpCode op = GET_OPCODE(i);
|
||||
int a = GETARG_A(i);
|
||||
switch (op) {
|
||||
case OP_LOADNIL: {
|
||||
int b = GETARG_B(i);
|
||||
if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */
|
||||
setreg = filterpc(pc, jmptarget);
|
||||
break;
|
||||
}
|
||||
case OP_TFORCALL: {
|
||||
if (reg >= a + 2) /* affect all regs above its base */
|
||||
setreg = filterpc(pc, jmptarget);
|
||||
break;
|
||||
}
|
||||
case OP_CALL:
|
||||
case OP_TAILCALL: {
|
||||
if (reg >= a) /* affect all registers above base */
|
||||
setreg = filterpc(pc, jmptarget);
|
||||
break;
|
||||
}
|
||||
case OP_JMP: {
|
||||
int b = GETARG_sBx(i);
|
||||
int dest = pc + 1 + b;
|
||||
/* jump is forward and do not skip 'lastpc'? */
|
||||
if (pc < dest && dest <= lastpc) {
|
||||
if (dest > jmptarget)
|
||||
jmptarget = dest; /* update 'jmptarget' */
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (testAMode(op) && reg == a) /* any instruction that set A */
|
||||
setreg = filterpc(pc, jmptarget);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return setreg;
|
||||
}
|
||||
|
||||
|
||||
static const char *getobjname (Proto *p, int lastpc, int reg,
|
||||
const char **name) {
|
||||
int pc;
|
||||
*name = luaF_getlocalname(p, reg + 1, lastpc);
|
||||
if (*name) /* is a local? */
|
||||
return "local";
|
||||
/* else try symbolic execution */
|
||||
pc = findsetreg(p, lastpc, reg);
|
||||
if (pc != -1) { /* could find instruction? */
|
||||
Instruction i = p->code[pc];
|
||||
OpCode op = GET_OPCODE(i);
|
||||
switch (op) {
|
||||
case OP_MOVE: {
|
||||
int b = GETARG_B(i); /* move from 'b' to 'a' */
|
||||
if (b < GETARG_A(i))
|
||||
return getobjname(p, pc, b, name); /* get name for 'b' */
|
||||
break;
|
||||
}
|
||||
case OP_GETTABUP:
|
||||
case OP_GETTABLE: {
|
||||
int k = GETARG_C(i); /* key index */
|
||||
int t = GETARG_B(i); /* table index */
|
||||
const char *vn = (op == OP_GETTABLE) /* name of indexed variable */
|
||||
? luaF_getlocalname(p, t + 1, pc)
|
||||
: upvalname(p, t);
|
||||
kname(p, pc, k, name);
|
||||
return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field";
|
||||
}
|
||||
case OP_GETUPVAL: {
|
||||
*name = upvalname(p, GETARG_B(i));
|
||||
return "upvalue";
|
||||
}
|
||||
case OP_LOADK:
|
||||
case OP_LOADKX: {
|
||||
int b = (op == OP_LOADK) ? GETARG_Bx(i)
|
||||
: GETARG_Ax(p->code[pc + 1]);
|
||||
if (ttisstring(&p->k[b])) {
|
||||
*name = svalue(&p->k[b]);
|
||||
return "constant";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_SELF: {
|
||||
int k = GETARG_C(i); /* key index */
|
||||
kname(p, pc, k, name);
|
||||
return "method";
|
||||
}
|
||||
default: break; /* go through to return NULL */
|
||||
}
|
||||
}
|
||||
return NULL; /* could not find reasonable name */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Try to find a name for a function based on the code that called it.
|
||||
** (Only works when function was called by a Lua function.)
|
||||
** Returns what the name is (e.g., "for iterator", "method",
|
||||
** "metamethod") and sets '*name' to point to the name.
|
||||
*/
|
||||
static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
|
||||
const char **name) {
|
||||
TMS tm = (TMS)0; /* (initial value avoids warnings) */
|
||||
Proto *p = ci_func(ci)->p; /* calling function */
|
||||
int pc = currentpc(ci); /* calling instruction index */
|
||||
Instruction i = p->code[pc]; /* calling instruction */
|
||||
if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */
|
||||
*name = "?";
|
||||
return "hook";
|
||||
}
|
||||
switch (GET_OPCODE(i)) {
|
||||
case OP_CALL:
|
||||
case OP_TAILCALL:
|
||||
return getobjname(p, pc, GETARG_A(i), name); /* get function name */
|
||||
case OP_TFORCALL: { /* for iterator */
|
||||
*name = "for iterator";
|
||||
return "for iterator";
|
||||
}
|
||||
/* other instructions can do calls through metamethods */
|
||||
case OP_SELF: case OP_GETTABUP: case OP_GETTABLE:
|
||||
tm = TM_INDEX;
|
||||
break;
|
||||
case OP_SETTABUP: case OP_SETTABLE:
|
||||
tm = TM_NEWINDEX;
|
||||
break;
|
||||
case OP_ADD: case OP_SUB: case OP_MUL: case OP_MOD:
|
||||
case OP_POW: case OP_DIV: case OP_IDIV: case OP_BAND:
|
||||
case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: {
|
||||
int offset = cast_int(GET_OPCODE(i)) - cast_int(OP_ADD); /* ORDER OP */
|
||||
tm = cast(TMS, offset + cast_int(TM_ADD)); /* ORDER TM */
|
||||
break;
|
||||
}
|
||||
case OP_UNM: tm = TM_UNM; break;
|
||||
case OP_BNOT: tm = TM_BNOT; break;
|
||||
case OP_LEN: tm = TM_LEN; break;
|
||||
case OP_CONCAT: tm = TM_CONCAT; break;
|
||||
case OP_EQ: tm = TM_EQ; break;
|
||||
case OP_LT: tm = TM_LT; break;
|
||||
case OP_LE: tm = TM_LE; break;
|
||||
default:
|
||||
return NULL; /* cannot find a reasonable name */
|
||||
}
|
||||
*name = getstr(G(L)->tmname[tm]);
|
||||
return "metamethod";
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** The subtraction of two potentially unrelated pointers is
|
||||
** not ISO C, but it should not crash a program; the subsequent
|
||||
** checks are ISO C and ensure a correct result.
|
||||
*/
|
||||
static int isinstack (CallInfo *ci, const TValue *o) {
|
||||
ptrdiff_t i = o - ci->u.l.base;
|
||||
return (0 <= i && i < (ci->top - ci->u.l.base) && ci->u.l.base + i == o);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Checks whether value 'o' came from an upvalue. (That can only happen
|
||||
** with instructions OP_GETTABUP/OP_SETTABUP, which operate directly on
|
||||
** upvalues.)
|
||||
*/
|
||||
static const char *getupvalname (CallInfo *ci, const TValue *o,
|
||||
const char **name) {
|
||||
LClosure *c = ci_func(ci);
|
||||
int i;
|
||||
for (i = 0; i < c->nupvalues; i++) {
|
||||
if (c->upvals[i]->v == o) {
|
||||
*name = upvalname(c->p, i);
|
||||
return "upvalue";
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static const char *varinfo (lua_State *L, const TValue *o) {
|
||||
const char *name = NULL; /* to avoid warnings */
|
||||
CallInfo *ci = L->ci;
|
||||
const char *kind = NULL;
|
||||
if (isLua(ci)) {
|
||||
kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */
|
||||
if (!kind && isinstack(ci, o)) /* no? try a register */
|
||||
kind = getobjname(ci_func(ci)->p, currentpc(ci),
|
||||
cast_int(o - ci->u.l.base), &name);
|
||||
}
|
||||
return (kind) ? luaO_pushfstring(L, " (%s '%s')", kind, name) : "";
|
||||
}
|
||||
|
||||
|
||||
l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
|
||||
const char *t = luaT_objtypename(L, o);
|
||||
luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o));
|
||||
}
|
||||
|
||||
|
||||
l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) {
|
||||
if (ttisstring(p1) || cvt2str(p1)) p1 = p2;
|
||||
luaG_typeerror(L, p1, "concatenate");
|
||||
}
|
||||
|
||||
|
||||
l_noret luaG_opinterror (lua_State *L, const TValue *p1,
|
||||
const TValue *p2, const char *msg) {
|
||||
lua_Number temp;
|
||||
if (!tonumber(p1, &temp)) /* first operand is wrong? */
|
||||
p2 = p1; /* now second is wrong */
|
||||
luaG_typeerror(L, p2, msg);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Error when both values are convertible to numbers, but not to integers
|
||||
*/
|
||||
l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) {
|
||||
lua_Integer temp;
|
||||
if (!tointeger(p1, &temp))
|
||||
p2 = p1;
|
||||
luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2));
|
||||
}
|
||||
|
||||
|
||||
l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
|
||||
const char *t1 = luaT_objtypename(L, p1);
|
||||
const char *t2 = luaT_objtypename(L, p2);
|
||||
if (strcmp(t1, t2) == 0)
|
||||
luaG_runerror(L, "attempt to compare two %s values", t1);
|
||||
else
|
||||
luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
|
||||
}
|
||||
|
||||
|
||||
/* add src:line information to 'msg' */
|
||||
const char *luaG_addinfo (lua_State *L, const char *msg, TString *src,
|
||||
int line) {
|
||||
char buff[LUA_IDSIZE];
|
||||
if (src)
|
||||
luaO_chunkid(buff, getstr(src), LUA_IDSIZE);
|
||||
else { /* no source available; use "?" instead */
|
||||
buff[0] = '?'; buff[1] = '\0';
|
||||
}
|
||||
return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
|
||||
}
|
||||
|
||||
|
||||
l_noret luaG_errormsg (lua_State *L) {
|
||||
if (L->errfunc != 0) { /* is there an error handling function? */
|
||||
StkId errfunc = restorestack(L, L->errfunc);
|
||||
setobjs2s(L, L->top, L->top - 1); /* move argument */
|
||||
setobjs2s(L, L->top - 1, errfunc); /* push function */
|
||||
L->top++; /* assume EXTRA_STACK */
|
||||
luaD_callnoyield(L, L->top - 2, 1); /* call it */
|
||||
}
|
||||
luaD_throw(L, LUA_ERRRUN);
|
||||
}
|
||||
|
||||
|
||||
l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
|
||||
CallInfo *ci = L->ci;
|
||||
const char *msg;
|
||||
va_list argp;
|
||||
luaC_checkGC(L); /* error message uses memory */
|
||||
va_start(argp, fmt);
|
||||
msg = luaO_pushvfstring(L, fmt, argp); /* format message */
|
||||
va_end(argp);
|
||||
if (isLua(ci)) /* if Lua function, add source:line information */
|
||||
luaG_addinfo(L, msg, ci_func(ci)->p->source, currentline(ci));
|
||||
luaG_errormsg(L);
|
||||
}
|
||||
|
||||
|
||||
void luaG_traceexec (lua_State *L) {
|
||||
CallInfo *ci = L->ci;
|
||||
lu_byte mask = L->hookmask;
|
||||
int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT));
|
||||
if (counthook)
|
||||
resethookcount(L); /* reset count */
|
||||
else if (!(mask & LUA_MASKLINE))
|
||||
return; /* no line hook and count != 0; nothing to be done */
|
||||
if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */
|
||||
ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */
|
||||
return; /* do not call hook again (VM yielded, so it did not move) */
|
||||
}
|
||||
if (counthook)
|
||||
luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */
|
||||
if (mask & LUA_MASKLINE) {
|
||||
Proto *p = ci_func(ci)->p;
|
||||
int npc = pcRel(ci->u.l.savedpc, p);
|
||||
int newline = getfuncline(p, npc);
|
||||
if (npc == 0 || /* call linehook when enter a new function, */
|
||||
ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */
|
||||
newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */
|
||||
luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */
|
||||
}
|
||||
L->oldpc = ci->u.l.savedpc;
|
||||
if (L->status == LUA_YIELD) { /* did hook yield? */
|
||||
if (counthook)
|
||||
L->hookcount = 1; /* undo decrement to zero */
|
||||
ci->u.l.savedpc--; /* undo increment (resume will increment it again) */
|
||||
ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */
|
||||
ci->func = L->top - 1; /* protect stack below results */
|
||||
luaD_throw(L, LUA_YIELD);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
** $Id: ldebug.h,v 2.14.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Auxiliary functions from Debug Interface module
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef ldebug_h
|
||||
#define ldebug_h
|
||||
|
||||
|
||||
#include "lstate.h"
|
||||
|
||||
|
||||
#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1)
|
||||
|
||||
#define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : -1)
|
||||
|
||||
#define resethookcount(L) (L->hookcount = L->basehookcount)
|
||||
|
||||
|
||||
LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
|
||||
const char *opname);
|
||||
LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1,
|
||||
const TValue *p2);
|
||||
LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1,
|
||||
const TValue *p2,
|
||||
const char *msg);
|
||||
LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1,
|
||||
const TValue *p2);
|
||||
LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1,
|
||||
const TValue *p2);
|
||||
LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...);
|
||||
LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg,
|
||||
TString *src, int line);
|
||||
LUAI_FUNC l_noret luaG_errormsg (lua_State *L);
|
||||
LUAI_FUNC void luaG_traceexec (lua_State *L);
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,802 @@
|
|||
/*
|
||||
** $Id: ldo.c,v 2.157.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Stack and Call structure of Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define ldo_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lapi.h"
|
||||
#include "ldebug.h"
|
||||
#include "ldo.h"
|
||||
#include "lfunc.h"
|
||||
#include "lgc.h"
|
||||
#include "lmem.h"
|
||||
#include "lobject.h"
|
||||
#include "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"
|
||||
|
||||
|
||||
|
||||
#define errorstatus(s) ((s) > LUA_YIELD)
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Error-recovery functions
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By
|
||||
** default, Lua handles errors with exceptions when compiling as
|
||||
** C++ code, with _longjmp/_setjmp when asked to use them, and with
|
||||
** longjmp/setjmp otherwise.
|
||||
*/
|
||||
#if !defined(LUAI_THROW) /* { */
|
||||
|
||||
#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) /* { */
|
||||
|
||||
/* C++ exceptions */
|
||||
#define LUAI_THROW(L,c) throw(c)
|
||||
#define LUAI_TRY(L,c,a) \
|
||||
try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; }
|
||||
#define luai_jmpbuf int /* dummy variable */
|
||||
|
||||
#elif defined(LUA_USE_POSIX) /* }{ */
|
||||
|
||||
/* in POSIX, try _longjmp/_setjmp (more efficient) */
|
||||
#define LUAI_THROW(L,c) _longjmp((c)->b, 1)
|
||||
#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a }
|
||||
#define luai_jmpbuf jmp_buf
|
||||
|
||||
#else /* }{ */
|
||||
|
||||
/* ISO C handling with long jumps */
|
||||
#define LUAI_THROW(L,c) longjmp((c)->b, 1)
|
||||
#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a }
|
||||
#define luai_jmpbuf jmp_buf
|
||||
|
||||
#endif /* } */
|
||||
|
||||
#endif /* } */
|
||||
|
||||
|
||||
|
||||
/* chain list of long jump buffers */
|
||||
struct lua_longjmp {
|
||||
struct lua_longjmp *previous;
|
||||
luai_jmpbuf b;
|
||||
volatile int status; /* error code */
|
||||
};
|
||||
|
||||
|
||||
static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
|
||||
switch (errcode) {
|
||||
case LUA_ERRMEM: { /* memory error? */
|
||||
setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */
|
||||
break;
|
||||
}
|
||||
case LUA_ERRERR: {
|
||||
setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
setobjs2s(L, oldtop, L->top - 1); /* error message on current top */
|
||||
break;
|
||||
}
|
||||
}
|
||||
L->top = oldtop + 1;
|
||||
}
|
||||
|
||||
|
||||
l_noret luaD_throw (lua_State *L, int errcode) {
|
||||
if (L->errorJmp) { /* thread has an error handler? */
|
||||
L->errorJmp->status = errcode; /* set status */
|
||||
LUAI_THROW(L, L->errorJmp); /* jump to it */
|
||||
}
|
||||
else { /* thread has no error handler */
|
||||
global_State *g = G(L);
|
||||
L->status = cast_byte(errcode); /* mark it as dead */
|
||||
if (g->mainthread->errorJmp) { /* main thread has a handler? */
|
||||
setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */
|
||||
luaD_throw(g->mainthread, errcode); /* re-throw in main thread */
|
||||
}
|
||||
else { /* no handler at all; abort */
|
||||
if (g->panic) { /* panic function? */
|
||||
seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */
|
||||
if (L->ci->top < L->top)
|
||||
L->ci->top = L->top; /* pushing msg. can break this invariant */
|
||||
lua_unlock(L);
|
||||
g->panic(L); /* call panic function (last chance to jump out) */
|
||||
}
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
|
||||
unsigned short oldnCcalls = L->nCcalls;
|
||||
struct lua_longjmp lj;
|
||||
lj.status = LUA_OK;
|
||||
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 */
|
||||
L->nCcalls = oldnCcalls;
|
||||
return lj.status;
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
/*
|
||||
** {==================================================================
|
||||
** Stack reallocation
|
||||
** ===================================================================
|
||||
*/
|
||||
static void correctstack (lua_State *L, TValue *oldstack) {
|
||||
CallInfo *ci;
|
||||
UpVal *up;
|
||||
L->top = (L->top - oldstack) + L->stack;
|
||||
for (up = L->openupval; up != NULL; up = up->u.open.next)
|
||||
up->v = (up->v - oldstack) + L->stack;
|
||||
for (ci = L->ci; ci != NULL; ci = ci->previous) {
|
||||
ci->top = (ci->top - oldstack) + L->stack;
|
||||
ci->func = (ci->func - oldstack) + L->stack;
|
||||
if (isLua(ci))
|
||||
ci->u.l.base = (ci->u.l.base - oldstack) + L->stack;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* some space for error handling */
|
||||
#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200)
|
||||
|
||||
|
||||
void luaD_reallocstack (lua_State *L, int newsize) {
|
||||
TValue *oldstack = L->stack;
|
||||
int lim = L->stacksize;
|
||||
lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
|
||||
lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK);
|
||||
luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue);
|
||||
for (; lim < newsize; lim++)
|
||||
setnilvalue(L->stack + lim); /* erase new segment */
|
||||
L->stacksize = newsize;
|
||||
L->stack_last = L->stack + newsize - EXTRA_STACK;
|
||||
correctstack(L, oldstack);
|
||||
}
|
||||
|
||||
|
||||
void luaD_growstack (lua_State *L, int n) {
|
||||
int size = L->stacksize;
|
||||
if (size > LUAI_MAXSTACK) /* error after extra size? */
|
||||
luaD_throw(L, LUA_ERRERR);
|
||||
else {
|
||||
int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK;
|
||||
int newsize = 2 * size;
|
||||
if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK;
|
||||
if (newsize < needed) newsize = needed;
|
||||
if (newsize > LUAI_MAXSTACK) { /* stack overflow? */
|
||||
luaD_reallocstack(L, ERRORSTACKSIZE);
|
||||
luaG_runerror(L, "stack overflow");
|
||||
}
|
||||
else
|
||||
luaD_reallocstack(L, newsize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int stackinuse (lua_State *L) {
|
||||
CallInfo *ci;
|
||||
StkId lim = L->top;
|
||||
for (ci = L->ci; ci != NULL; ci = ci->previous) {
|
||||
if (lim < ci->top) lim = ci->top;
|
||||
}
|
||||
lua_assert(lim <= L->stack_last);
|
||||
return cast_int(lim - L->stack) + 1; /* part of stack in use */
|
||||
}
|
||||
|
||||
|
||||
void luaD_shrinkstack (lua_State *L) {
|
||||
int inuse = stackinuse(L);
|
||||
int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK;
|
||||
if (goodsize > LUAI_MAXSTACK)
|
||||
goodsize = LUAI_MAXSTACK; /* respect stack limit */
|
||||
if (L->stacksize > LUAI_MAXSTACK) /* had been handling stack overflow? */
|
||||
luaE_freeCI(L); /* free all CIs (list grew because of an error) */
|
||||
else
|
||||
luaE_shrinkCI(L); /* shrink list */
|
||||
/* if thread is currently not handling a stack overflow and its
|
||||
good size is smaller than current size, shrink its stack */
|
||||
if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) &&
|
||||
goodsize < L->stacksize)
|
||||
luaD_reallocstack(L, goodsize);
|
||||
else /* don't change stack */
|
||||
condmovestack(L,{},{}); /* (change only for debugging) */
|
||||
}
|
||||
|
||||
|
||||
void luaD_inctop (lua_State *L) {
|
||||
luaD_checkstack(L, 1);
|
||||
L->top++;
|
||||
}
|
||||
|
||||
/* }================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
** Call a hook for the given event. Make sure there is a hook to be
|
||||
** called. (Both 'L->hook' and 'L->hookmask', which triggers this
|
||||
** function, can be changed asynchronously by signals.)
|
||||
*/
|
||||
void luaD_hook (lua_State *L, int event, int line) {
|
||||
lua_Hook hook = L->hook;
|
||||
if (hook && L->allowhook) { /* make sure there is a hook */
|
||||
CallInfo *ci = L->ci;
|
||||
ptrdiff_t top = savestack(L, L->top);
|
||||
ptrdiff_t ci_top = savestack(L, ci->top);
|
||||
lua_Debug ar;
|
||||
ar.event = event;
|
||||
ar.currentline = line;
|
||||
ar.i_ci = ci;
|
||||
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
|
||||
ci->top = L->top + LUA_MINSTACK;
|
||||
lua_assert(ci->top <= L->stack_last);
|
||||
L->allowhook = 0; /* cannot call hooks inside a hook */
|
||||
ci->callstatus |= CIST_HOOKED;
|
||||
lua_unlock(L);
|
||||
(*hook)(L, &ar);
|
||||
lua_lock(L);
|
||||
lua_assert(!L->allowhook);
|
||||
L->allowhook = 1;
|
||||
ci->top = restorestack(L, ci_top);
|
||||
L->top = restorestack(L, top);
|
||||
ci->callstatus &= ~CIST_HOOKED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void callhook (lua_State *L, CallInfo *ci) {
|
||||
int hook = LUA_HOOKCALL;
|
||||
ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */
|
||||
if (isLua(ci->previous) &&
|
||||
GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) {
|
||||
ci->callstatus |= CIST_TAIL;
|
||||
hook = LUA_HOOKTAILCALL;
|
||||
}
|
||||
luaD_hook(L, hook, -1);
|
||||
ci->u.l.savedpc--; /* correct 'pc' */
|
||||
}
|
||||
|
||||
|
||||
static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
|
||||
int i;
|
||||
int nfixargs = p->numparams;
|
||||
StkId base, fixed;
|
||||
/* 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 < actual; i++) {
|
||||
setobjs2s(L, L->top++, fixed + i);
|
||||
setnilvalue(fixed + i); /* erase original copy (for GC) */
|
||||
}
|
||||
for (; i < nfixargs; i++)
|
||||
setnilvalue(L->top++); /* complete missing arguments */
|
||||
return base;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Check whether __call metafield of 'func' is a function. If so, put
|
||||
** it in stack below original 'func' so that 'luaD_precall' can call
|
||||
** it. Raise an error if __call metafield is not a function.
|
||||
*/
|
||||
static void tryfuncTM (lua_State *L, StkId func) {
|
||||
const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);
|
||||
StkId p;
|
||||
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);
|
||||
L->top++; /* slot ensured by caller */
|
||||
setobj2s(L, func, tm); /* tag method is the new function to be called */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'.
|
||||
** Handle most typical cases (zero results for commands, one result for
|
||||
** expressions, multiple results for tail calls/single parameters)
|
||||
** separated.
|
||||
*/
|
||||
static int moveresults (lua_State *L, const TValue *firstResult, StkId res,
|
||||
int nres, int wanted) {
|
||||
switch (wanted) { /* handle typical cases separately */
|
||||
case 0: break; /* nothing to move */
|
||||
case 1: { /* one result needed */
|
||||
if (nres == 0) /* no results? */
|
||||
firstResult = luaO_nilobject; /* adjust with nil */
|
||||
setobjs2s(L, res, firstResult); /* move it to proper place */
|
||||
break;
|
||||
}
|
||||
case LUA_MULTRET: {
|
||||
int i;
|
||||
for (i = 0; i < nres; i++) /* move all results to correct place */
|
||||
setobjs2s(L, res + i, firstResult + i);
|
||||
L->top = res + nres;
|
||||
return 0; /* wanted == LUA_MULTRET */
|
||||
}
|
||||
default: {
|
||||
int i;
|
||||
if (wanted <= nres) { /* enough results? */
|
||||
for (i = 0; i < wanted; i++) /* move wanted results to correct place */
|
||||
setobjs2s(L, res + i, firstResult + i);
|
||||
}
|
||||
else { /* not enough results; use all of them plus nils */
|
||||
for (i = 0; i < nres; i++) /* move all results to correct place */
|
||||
setobjs2s(L, res + i, firstResult + i);
|
||||
for (; i < wanted; i++) /* complete wanted number of results */
|
||||
setnilvalue(res + i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
L->top = res + wanted; /* top points after the last result */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Finishes a function call: calls hook if necessary, removes CallInfo,
|
||||
** moves current number of results to proper place; returns 0 iff call
|
||||
** wanted multiple (variable number of) results.
|
||||
*/
|
||||
int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) {
|
||||
StkId res;
|
||||
int wanted = ci->nresults;
|
||||
if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) {
|
||||
if (L->hookmask & LUA_MASKRET) {
|
||||
ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */
|
||||
luaD_hook(L, LUA_HOOKRET, -1);
|
||||
firstResult = restorestack(L, fr);
|
||||
}
|
||||
L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */
|
||||
}
|
||||
res = ci->func; /* res == final position of 1st result */
|
||||
L->ci = ci->previous; /* back to caller */
|
||||
/* move results to proper place */
|
||||
return moveresults(L, firstResult, res, nres, wanted);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L)))
|
||||
|
||||
|
||||
/* macro to check stack size, preserving 'p' */
|
||||
#define checkstackp(L,n,p) \
|
||||
luaD_checkstackaux(L, n, \
|
||||
ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \
|
||||
luaC_checkGC(L), /* stack grow uses memory */ \
|
||||
p = restorestack(L, t__)) /* 'pos' part: restore 'p' */
|
||||
|
||||
|
||||
/*
|
||||
** Prepares a function call: checks the stack, creates a new CallInfo
|
||||
** entry, fills in the relevant information, calls hook if needed.
|
||||
** If function is a C function, does the call, too. (Otherwise, leave
|
||||
** the execution ('luaV_execute') to the caller, to allow stackless
|
||||
** calls.) Returns true iff function has been executed (C function).
|
||||
*/
|
||||
int luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||
lua_CFunction f;
|
||||
CallInfo *ci;
|
||||
switch (ttype(func)) {
|
||||
case LUA_TCCL: /* C closure */
|
||||
f = clCvalue(func)->f;
|
||||
goto Cfunc;
|
||||
case LUA_TLCF: /* light C function */
|
||||
f = fvalue(func);
|
||||
Cfunc: {
|
||||
int n; /* number of returns */
|
||||
checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
|
||||
ci = next_ci(L); /* now 'enter' new function */
|
||||
ci->nresults = nresults;
|
||||
ci->func = func;
|
||||
ci->top = L->top + LUA_MINSTACK;
|
||||
lua_assert(ci->top <= L->stack_last);
|
||||
ci->callstatus = 0;
|
||||
if (L->hookmask & LUA_MASKCALL)
|
||||
luaD_hook(L, LUA_HOOKCALL, -1);
|
||||
lua_unlock(L);
|
||||
n = (*f)(L); /* do the actual call */
|
||||
lua_lock(L);
|
||||
api_checknelems(L, n);
|
||||
luaD_poscall(L, ci, L->top - n, n);
|
||||
return 1;
|
||||
}
|
||||
case LUA_TLCL: { /* Lua function: prepare its call */
|
||||
StkId base;
|
||||
Proto *p = clLvalue(func)->p;
|
||||
int n = cast_int(L->top - func) - 1; /* number of real arguments */
|
||||
int fsize = p->maxstacksize; /* frame size */
|
||||
checkstackp(L, fsize, func);
|
||||
if (p->is_vararg)
|
||||
base = adjust_varargs(L, p, n);
|
||||
else { /* non vararg function */
|
||||
for (; n < p->numparams; n++)
|
||||
setnilvalue(L->top++); /* complete missing arguments */
|
||||
base = func + 1;
|
||||
}
|
||||
ci = next_ci(L); /* now 'enter' new function */
|
||||
ci->nresults = nresults;
|
||||
ci->func = func;
|
||||
ci->u.l.base = base;
|
||||
L->top = ci->top = base + fsize;
|
||||
lua_assert(ci->top <= L->stack_last);
|
||||
ci->u.l.savedpc = p->code; /* starting point */
|
||||
ci->callstatus = CIST_LUA;
|
||||
if (L->hookmask & LUA_MASKCALL)
|
||||
callhook(L, ci);
|
||||
return 0;
|
||||
}
|
||||
default: { /* not a function */
|
||||
checkstackp(L, 1, func); /* ensure space for metamethod */
|
||||
tryfuncTM(L, func); /* try to get '__call' metamethod */
|
||||
return luaD_precall(L, func, nresults); /* now it must be a function */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Check appropriate error for stack overflow ("regular" overflow or
|
||||
** overflow while handling stack overflow). If 'nCalls' is larger than
|
||||
** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but
|
||||
** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to
|
||||
** allow overflow handling to work)
|
||||
*/
|
||||
static void stackerror (lua_State *L) {
|
||||
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 */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** 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)
|
||||
stackerror(L);
|
||||
if (!luaD_precall(L, func, nResults)) /* is a Lua function? */
|
||||
luaV_execute(L); /* call it */
|
||||
L->nCcalls--;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Similar to 'luaD_call', but does not allow yields during the call
|
||||
*/
|
||||
void luaD_callnoyield (lua_State *L, StkId func, int nResults) {
|
||||
L->nny++;
|
||||
luaD_call(L, func, nResults);
|
||||
L->nny--;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Completes the execution of an interrupted C function, calling its
|
||||
** continuation function.
|
||||
*/
|
||||
static void finishCcall (lua_State *L, int status) {
|
||||
CallInfo *ci = L->ci;
|
||||
int n;
|
||||
/* must have a continuation and must be able to call it */
|
||||
lua_assert(ci->u.c.k != NULL && L->nny == 0);
|
||||
/* error status can only happen in a protected call */
|
||||
lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD);
|
||||
if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */
|
||||
ci->callstatus &= ~CIST_YPCALL; /* continuation is also inside it */
|
||||
L->errfunc = ci->u.c.old_errfunc; /* with the same error function */
|
||||
}
|
||||
/* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already
|
||||
handled */
|
||||
adjustresults(L, ci->nresults);
|
||||
lua_unlock(L);
|
||||
n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */
|
||||
lua_lock(L);
|
||||
api_checknelems(L, n);
|
||||
luaD_poscall(L, ci, L->top - n, n); /* finish 'luaD_precall' */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Executes "full continuation" (everything in the stack) of a
|
||||
** previously interrupted coroutine until the stack is empty (or another
|
||||
** interruption long-jumps out of the loop). If the coroutine is
|
||||
** recovering from an error, 'ud' points to the error status, which must
|
||||
** be passed to the first continuation function (otherwise the default
|
||||
** status is LUA_YIELD).
|
||||
*/
|
||||
static void unroll (lua_State *L, void *ud) {
|
||||
if (ud != NULL) /* error status? */
|
||||
finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */
|
||||
while (L->ci != &L->base_ci) { /* something in the stack */
|
||||
if (!isLua(L->ci)) /* C function? */
|
||||
finishCcall(L, LUA_YIELD); /* complete its execution */
|
||||
else { /* Lua function */
|
||||
luaV_finishOp(L); /* finish interrupted instruction */
|
||||
luaV_execute(L); /* execute down to higher C 'boundary' */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Try to find a suspended protected call (a "recover point") for the
|
||||
** given thread.
|
||||
*/
|
||||
static CallInfo *findpcall (lua_State *L) {
|
||||
CallInfo *ci;
|
||||
for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */
|
||||
if (ci->callstatus & CIST_YPCALL)
|
||||
return ci;
|
||||
}
|
||||
return NULL; /* no pending pcall */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Recovers from an error in a coroutine. Finds a recover point (if
|
||||
** there is one) and completes the execution of the interrupted
|
||||
** 'luaD_pcall'. If there is no recover point, returns zero.
|
||||
*/
|
||||
static int recover (lua_State *L, int status) {
|
||||
StkId oldtop;
|
||||
CallInfo *ci = findpcall(L);
|
||||
if (ci == NULL) return 0; /* no recovery point */
|
||||
/* "finish" luaD_pcall */
|
||||
oldtop = restorestack(L, ci->extra);
|
||||
luaF_close(L, oldtop);
|
||||
seterrorobj(L, status, oldtop);
|
||||
L->ci = ci;
|
||||
L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */
|
||||
L->nny = 0; /* should be zero to be yieldable */
|
||||
luaD_shrinkstack(L);
|
||||
L->errfunc = ci->u.c.old_errfunc;
|
||||
return 1; /* continue running the coroutine */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Signal an error in the call to 'lua_resume', not in the execution
|
||||
** of the coroutine itself. (Such errors should not be handled by any
|
||||
** coroutine error handler and should not kill the coroutine.)
|
||||
*/
|
||||
static int resume_error (lua_State *L, const char *msg, int narg) {
|
||||
L->top -= narg; /* remove args from the stack */
|
||||
setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
return LUA_ERRRUN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Do the work for 'lua_resume' in protected mode. Most of the work
|
||||
** depends on the status of the coroutine: initial state, suspended
|
||||
** inside a hook, or regularly suspended (optionally with a continuation
|
||||
** function), plus erroneous cases: non-suspended coroutine or dead
|
||||
** coroutine.
|
||||
*/
|
||||
static void resume (lua_State *L, void *ud) {
|
||||
int n = *(cast(int*, ud)); /* number of arguments */
|
||||
StkId firstArg = L->top - n; /* first argument */
|
||||
CallInfo *ci = L->ci;
|
||||
if (L->status == LUA_OK) { /* starting a coroutine? */
|
||||
if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */
|
||||
luaV_execute(L); /* call it */
|
||||
}
|
||||
else { /* resuming from previous yield */
|
||||
lua_assert(L->status == LUA_YIELD);
|
||||
L->status = LUA_OK; /* mark that it is running (again) */
|
||||
ci->func = restorestack(L, ci->extra);
|
||||
if (isLua(ci)) /* yielded inside a hook? */
|
||||
luaV_execute(L); /* just continue running Lua code */
|
||||
else { /* 'common' yield */
|
||||
if (ci->u.c.k != NULL) { /* does it have a continuation function? */
|
||||
lua_unlock(L);
|
||||
n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */
|
||||
lua_lock(L);
|
||||
api_checknelems(L, n);
|
||||
firstArg = L->top - n; /* yield results come from continuation */
|
||||
}
|
||||
luaD_poscall(L, ci, firstArg, n); /* finish 'luaD_precall' */
|
||||
}
|
||||
unroll(L, NULL); /* run continuation */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
|
||||
int status;
|
||||
unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */
|
||||
lua_lock(L);
|
||||
if (L->status == LUA_OK) { /* may be starting a coroutine */
|
||||
if (L->ci != &L->base_ci) /* not in base level? */
|
||||
return resume_error(L, "cannot resume non-suspended coroutine", nargs);
|
||||
}
|
||||
else if (L->status != LUA_YIELD)
|
||||
return resume_error(L, "cannot resume dead coroutine", nargs);
|
||||
L->nCcalls = (from) ? from->nCcalls + 1 : 1;
|
||||
if (L->nCcalls >= LUAI_MAXCCALLS)
|
||||
return resume_error(L, "C stack overflow", nargs);
|
||||
luai_userstateresume(L, nargs);
|
||||
L->nny = 0; /* allow yields */
|
||||
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
|
||||
status = luaD_rawrunprotected(L, resume, &nargs);
|
||||
if (status == -1) /* error calling 'lua_resume'? */
|
||||
status = LUA_ERRRUN;
|
||||
else { /* continue running after recoverable errors */
|
||||
while (errorstatus(status) && recover(L, status)) {
|
||||
/* unroll continuation */
|
||||
status = luaD_rawrunprotected(L, unroll, &status);
|
||||
}
|
||||
if (errorstatus(status)) { /* unrecoverable error? */
|
||||
L->status = cast_byte(status); /* mark thread as 'dead' */
|
||||
seterrorobj(L, status, L->top); /* push error message */
|
||||
L->ci->top = L->top;
|
||||
}
|
||||
else lua_assert(status == L->status); /* normal end or yield */
|
||||
}
|
||||
L->nny = oldnny; /* restore 'nny' */
|
||||
L->nCcalls--;
|
||||
lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0));
|
||||
lua_unlock(L);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_isyieldable (lua_State *L) {
|
||||
return (L->nny == 0);
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx,
|
||||
lua_KFunction k) {
|
||||
CallInfo *ci = L->ci;
|
||||
luai_userstateyield(L, nresults);
|
||||
lua_lock(L);
|
||||
api_checknelems(L, nresults);
|
||||
if (L->nny > 0) {
|
||||
if (L != G(L)->mainthread)
|
||||
luaG_runerror(L, "attempt to yield across a C-call boundary");
|
||||
else
|
||||
luaG_runerror(L, "attempt to yield from outside a coroutine");
|
||||
}
|
||||
L->status = LUA_YIELD;
|
||||
ci->extra = savestack(L, ci->func); /* save current 'func' */
|
||||
if (isLua(ci)) { /* inside a hook? */
|
||||
api_check(L, k == NULL, "hooks cannot continue after yielding");
|
||||
}
|
||||
else {
|
||||
if ((ci->u.c.k = k) != NULL) /* is there a continuation? */
|
||||
ci->u.c.ctx = ctx; /* save context */
|
||||
ci->func = L->top - nresults - 1; /* protect stack below results */
|
||||
luaD_throw(L, LUA_YIELD);
|
||||
}
|
||||
lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */
|
||||
lua_unlock(L);
|
||||
return 0; /* return to 'luaD_hook' */
|
||||
}
|
||||
|
||||
|
||||
int luaD_pcall (lua_State *L, Pfunc func, void *u,
|
||||
ptrdiff_t old_top, ptrdiff_t ef) {
|
||||
int status;
|
||||
CallInfo *old_ci = L->ci;
|
||||
lu_byte old_allowhooks = L->allowhook;
|
||||
unsigned short old_nny = L->nny;
|
||||
ptrdiff_t old_errfunc = L->errfunc;
|
||||
L->errfunc = ef;
|
||||
status = luaD_rawrunprotected(L, func, u);
|
||||
if (status != LUA_OK) { /* an error occurred? */
|
||||
StkId oldtop = restorestack(L, old_top);
|
||||
luaF_close(L, oldtop); /* close possible pending closures */
|
||||
seterrorobj(L, status, oldtop);
|
||||
L->ci = old_ci;
|
||||
L->allowhook = old_allowhooks;
|
||||
L->nny = old_nny;
|
||||
luaD_shrinkstack(L);
|
||||
}
|
||||
L->errfunc = old_errfunc;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Execute a protected parser.
|
||||
*/
|
||||
struct SParser { /* data to 'f_parser' */
|
||||
ZIO *z;
|
||||
Mbuffer buff; /* dynamic structure used by the scanner */
|
||||
Dyndata dyd; /* dynamic structures used by the parser */
|
||||
const char *mode;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
|
||||
static void checkmode (lua_State *L, const char *mode, const char *x) {
|
||||
if (mode && strchr(mode, x[0]) == NULL) {
|
||||
luaO_pushfstring(L,
|
||||
"attempt to load a %s chunk (mode is '%s')", x, mode);
|
||||
luaD_throw(L, LUA_ERRSYNTAX);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void f_parser (lua_State *L, void *ud) {
|
||||
LClosure *cl;
|
||||
struct SParser *p = cast(struct SParser *, ud);
|
||||
int c = zgetc(p->z); /* read first character */
|
||||
if (c == LUA_SIGNATURE[0]) {
|
||||
checkmode(L, p->mode, "binary");
|
||||
cl = luaU_undump(L, p->z, p->name);
|
||||
}
|
||||
else {
|
||||
checkmode(L, p->mode, "text");
|
||||
cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
|
||||
}
|
||||
lua_assert(cl->nupvalues == cl->p->sizeupvalues);
|
||||
luaF_initupvals(L, cl);
|
||||
}
|
||||
|
||||
|
||||
int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
|
||||
const char *mode) {
|
||||
struct SParser p;
|
||||
int status;
|
||||
L->nny++; /* cannot yield during parsing */
|
||||
p.z = z; p.name = name; p.mode = mode;
|
||||
p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0;
|
||||
p.dyd.gt.arr = NULL; p.dyd.gt.size = 0;
|
||||
p.dyd.label.arr = NULL; p.dyd.label.size = 0;
|
||||
luaZ_initbuffer(L, &p.buff);
|
||||
status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
|
||||
luaZ_freebuffer(L, &p.buff);
|
||||
luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size);
|
||||
luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size);
|
||||
luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size);
|
||||
L->nny--;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
** $Id: ldo.h,v 2.29.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Stack and Call structure of Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef ldo_h
|
||||
#define ldo_h
|
||||
|
||||
|
||||
#include "lobject.h"
|
||||
#include "lstate.h"
|
||||
#include "lzio.h"
|
||||
|
||||
|
||||
/*
|
||||
** Macro to check stack size and grow stack if needed. Parameters
|
||||
** 'pre'/'pos' allow the macro to preserve a pointer into the
|
||||
** stack across reallocations, doing the work only when needed.
|
||||
** 'condmovestack' is used in heavy tests to force a stack reallocation
|
||||
** at every check.
|
||||
*/
|
||||
#define luaD_checkstackaux(L,n,pre,pos) \
|
||||
if (L->stack_last - L->top <= (n)) \
|
||||
{ pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); }
|
||||
|
||||
/* In general, 'pre'/'pos' are empty (nothing to save) */
|
||||
#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0)
|
||||
|
||||
|
||||
|
||||
#define savestack(L,p) ((char *)(p) - (char *)L->stack)
|
||||
#define restorestack(L,n) ((TValue *)((char *)L->stack + (n)))
|
||||
|
||||
|
||||
/* 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,
|
||||
const char *mode);
|
||||
LUAI_FUNC void luaD_hook (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 void luaD_callnoyield (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, CallInfo *ci, StkId firstResult,
|
||||
int nres);
|
||||
LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
|
||||
LUAI_FUNC void luaD_growstack (lua_State *L, int n);
|
||||
LUAI_FUNC void luaD_shrinkstack (lua_State *L);
|
||||
LUAI_FUNC void luaD_inctop (lua_State *L);
|
||||
|
||||
LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode);
|
||||
LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
** $Id: ldump.c,v 2.37.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** save precompiled Lua chunks
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define ldump_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#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;
|
||||
|
||||
|
||||
/*
|
||||
** All high-level dumps go through DumpVector; you can change it to
|
||||
** change the endianness of the result
|
||||
*/
|
||||
#define DumpVector(v,n,D) DumpBlock(v,(n)*sizeof((v)[0]),D)
|
||||
|
||||
#define DumpLiteral(s,D) DumpBlock(s, sizeof(s) - sizeof(char), D)
|
||||
|
||||
|
||||
static void DumpBlock (const void *b, size_t size, DumpState *D) {
|
||||
if (D->status == 0 && size > 0) {
|
||||
lua_unlock(D->L);
|
||||
D->status = (*D->writer)(D->L, b, size, D->data);
|
||||
lua_lock(D->L);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define DumpVar(x,D) DumpVector(&x,1,D)
|
||||
|
||||
|
||||
static void DumpByte (int y, DumpState *D) {
|
||||
lu_byte x = (lu_byte)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 DumpInteger (lua_Integer x, DumpState *D) {
|
||||
DumpVar(x, D);
|
||||
}
|
||||
|
||||
|
||||
static void DumpString (const TString *s, DumpState *D) {
|
||||
if (s == NULL)
|
||||
DumpByte(0, D);
|
||||
else {
|
||||
size_t size = tsslen(s) + 1; /* include trailing '\0' */
|
||||
const char *str = getstr(s);
|
||||
if (size < 0xFF)
|
||||
DumpByte(cast_int(size), D);
|
||||
else {
|
||||
DumpByte(0xFF, D);
|
||||
DumpVar(size, D);
|
||||
}
|
||||
DumpVector(str, size - 1, D); /* no need to save '\0' */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void DumpCode (const Proto *f, DumpState *D) {
|
||||
DumpInt(f->sizecode, D);
|
||||
DumpVector(f->code, f->sizecode, D);
|
||||
}
|
||||
|
||||
|
||||
static void DumpFunction(const Proto *f, TString *psource, DumpState *D);
|
||||
|
||||
static void DumpConstants (const Proto *f, DumpState *D) {
|
||||
int i;
|
||||
int n = f->sizek;
|
||||
DumpInt(n, D);
|
||||
for (i = 0; i < n; i++) {
|
||||
const TValue *o = &f->k[i];
|
||||
DumpByte(ttype(o), D);
|
||||
switch (ttype(o)) {
|
||||
case LUA_TNIL:
|
||||
break;
|
||||
case LUA_TBOOLEAN:
|
||||
DumpByte(bvalue(o), D);
|
||||
break;
|
||||
case LUA_TNUMFLT:
|
||||
DumpNumber(fltvalue(o), D);
|
||||
break;
|
||||
case LUA_TNUMINT:
|
||||
DumpInteger(ivalue(o), D);
|
||||
break;
|
||||
case LUA_TSHRSTR:
|
||||
case LUA_TLNGSTR:
|
||||
DumpString(tsvalue(o), D);
|
||||
break;
|
||||
default:
|
||||
lua_assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void DumpProtos (const Proto *f, DumpState *D) {
|
||||
int i;
|
||||
int n = f->sizep;
|
||||
DumpInt(n, D);
|
||||
for (i = 0; i < n; i++)
|
||||
DumpFunction(f->p[i], f->source, D);
|
||||
}
|
||||
|
||||
|
||||
static void DumpUpvalues (const Proto *f, DumpState *D) {
|
||||
int i, n = f->sizeupvalues;
|
||||
DumpInt(n, D);
|
||||
for (i = 0; i < n; i++) {
|
||||
DumpByte(f->upvalues[i].instack, D);
|
||||
DumpByte(f->upvalues[i].idx, D);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void DumpDebug (const Proto *f, DumpState *D) {
|
||||
int i, n;
|
||||
n = (D->strip) ? 0 : f->sizelineinfo;
|
||||
DumpInt(n, D);
|
||||
DumpVector(f->lineinfo, n, 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].name, D);
|
||||
}
|
||||
|
||||
|
||||
static void DumpFunction (const Proto *f, TString *psource, DumpState *D) {
|
||||
if (D->strip || f->source == psource)
|
||||
DumpString(NULL, D); /* no debug info or same source as its parent */
|
||||
else
|
||||
DumpString(f->source, D);
|
||||
DumpInt(f->linedefined, D);
|
||||
DumpInt(f->lastlinedefined, D);
|
||||
DumpByte(f->numparams, D);
|
||||
DumpByte(f->is_vararg, D);
|
||||
DumpByte(f->maxstacksize, D);
|
||||
DumpCode(f, D);
|
||||
DumpConstants(f, D);
|
||||
DumpUpvalues(f, D);
|
||||
DumpProtos(f, D);
|
||||
DumpDebug(f, D);
|
||||
}
|
||||
|
||||
|
||||
static void DumpHeader (DumpState *D) {
|
||||
DumpLiteral(LUA_SIGNATURE, D);
|
||||
DumpByte(LUAC_VERSION, D);
|
||||
DumpByte(LUAC_FORMAT, D);
|
||||
DumpLiteral(LUAC_DATA, D);
|
||||
DumpByte(sizeof(int), D);
|
||||
DumpByte(sizeof(size_t), D);
|
||||
DumpByte(sizeof(Instruction), D);
|
||||
DumpByte(sizeof(lua_Integer), D);
|
||||
DumpByte(sizeof(lua_Number), D);
|
||||
DumpInteger(LUAC_INT, D);
|
||||
DumpNumber(LUAC_NUM, 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);
|
||||
DumpByte(f->sizeupvalues, &D);
|
||||
DumpFunction(f, NULL, &D);
|
||||
return D.status;
|
||||
}
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
** $Id: lfunc.c,v 2.45.1.1 2017/04/19 17:39:34 roberto Exp $
|
||||
** Auxiliary functions to manipulate prototypes and closures
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define lfunc_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lfunc.h"
|
||||
#include "lgc.h"
|
||||
#include "lmem.h"
|
||||
#include "lobject.h"
|
||||
#include "lstate.h"
|
||||
|
||||
|
||||
|
||||
CClosure *luaF_newCclosure (lua_State *L, int n) {
|
||||
GCObject *o = luaC_newobj(L, LUA_TCCL, sizeCclosure(n));
|
||||
CClosure *c = gco2ccl(o);
|
||||
c->nupvalues = cast_byte(n);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
LClosure *luaF_newLclosure (lua_State *L, int n) {
|
||||
GCObject *o = luaC_newobj(L, LUA_TLCL, sizeLclosure(n));
|
||||
LClosure *c = gco2lcl(o);
|
||||
c->p = NULL;
|
||||
c->nupvalues = cast_byte(n);
|
||||
while (n--) c->upvals[n] = NULL;
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
** fill a closure with new closed upvalues
|
||||
*/
|
||||
void luaF_initupvals (lua_State *L, LClosure *cl) {
|
||||
int i;
|
||||
for (i = 0; i < cl->nupvalues; i++) {
|
||||
UpVal *uv = luaM_new(L, UpVal);
|
||||
uv->refcount = 1;
|
||||
uv->v = &uv->u.value; /* make it closed */
|
||||
setnilvalue(uv->v);
|
||||
cl->upvals[i] = uv;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UpVal *luaF_findupval (lua_State *L, StkId level) {
|
||||
UpVal **pp = &L->openupval;
|
||||
UpVal *p;
|
||||
UpVal *uv;
|
||||
lua_assert(isintwups(L) || L->openupval == NULL);
|
||||
while (*pp != NULL && (p = *pp)->v >= level) {
|
||||
lua_assert(upisopen(p));
|
||||
if (p->v == level) /* found a corresponding upvalue? */
|
||||
return p; /* return it */
|
||||
pp = &p->u.open.next;
|
||||
}
|
||||
/* not found: create a new upvalue */
|
||||
uv = luaM_new(L, UpVal);
|
||||
uv->refcount = 0;
|
||||
uv->u.open.next = *pp; /* link it to list of open upvalues */
|
||||
uv->u.open.touched = 1;
|
||||
*pp = uv;
|
||||
uv->v = level; /* current value lives in the stack */
|
||||
if (!isintwups(L)) { /* thread not in list of threads with upvalues? */
|
||||
L->twups = G(L)->twups; /* link it to the list */
|
||||
G(L)->twups = L;
|
||||
}
|
||||
return uv;
|
||||
}
|
||||
|
||||
|
||||
void luaF_close (lua_State *L, StkId level) {
|
||||
UpVal *uv;
|
||||
while (L->openupval != NULL && (uv = L->openupval)->v >= level) {
|
||||
lua_assert(upisopen(uv));
|
||||
L->openupval = uv->u.open.next; /* remove from 'open' list */
|
||||
if (uv->refcount == 0) /* no references? */
|
||||
luaM_free(L, uv); /* free upvalue */
|
||||
else {
|
||||
setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */
|
||||
uv->v = &uv->u.value; /* now current value lives here */
|
||||
luaC_upvalbarrier(L, uv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Proto *luaF_newproto (lua_State *L) {
|
||||
GCObject *o = luaC_newobj(L, LUA_TPROTO, sizeof(Proto));
|
||||
Proto *f = gco2p(o);
|
||||
f->k = NULL;
|
||||
f->sizek = 0;
|
||||
f->p = NULL;
|
||||
f->sizep = 0;
|
||||
f->code = NULL;
|
||||
f->cache = NULL;
|
||||
f->sizecode = 0;
|
||||
f->lineinfo = NULL;
|
||||
f->sizelineinfo = 0;
|
||||
f->upvalues = NULL;
|
||||
f->sizeupvalues = 0;
|
||||
f->numparams = 0;
|
||||
f->is_vararg = 0;
|
||||
f->maxstacksize = 0;
|
||||
f->locvars = NULL;
|
||||
f->sizelocvars = 0;
|
||||
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);
|
||||
luaM_freearray(L, f->p, f->sizep);
|
||||
luaM_freearray(L, f->k, f->sizek);
|
||||
luaM_freearray(L, f->lineinfo, f->sizelineinfo);
|
||||
luaM_freearray(L, f->locvars, f->sizelocvars);
|
||||
luaM_freearray(L, f->upvalues, f->sizeupvalues);
|
||||
luaM_free(L, f);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** 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 */
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
** $Id: lfunc.h,v 2.15.1.1 2017/04/19 17:39:34 roberto Exp $
|
||||
** Auxiliary functions to manipulate prototypes and closures
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#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)))
|
||||
|
||||
|
||||
/* test whether thread is in 'twups' list */
|
||||
#define isintwups(L) (L->twups != L)
|
||||
|
||||
|
||||
/*
|
||||
** maximum number of upvalues in a closure (both C and Lua). (Value
|
||||
** must fit in a VM register.)
|
||||
*/
|
||||
#define MAXUPVAL 255
|
||||
|
||||
|
||||
/*
|
||||
** Upvalues for Lua closures
|
||||
*/
|
||||
struct UpVal {
|
||||
TValue *v; /* points to stack or to its own value */
|
||||
lu_mem refcount; /* reference counter */
|
||||
union {
|
||||
struct { /* (when open) */
|
||||
UpVal *next; /* linked list */
|
||||
int touched; /* mark to avoid cycles with dead threads */
|
||||
} open;
|
||||
TValue value; /* the value (when closed) */
|
||||
} u;
|
||||
};
|
||||
|
||||
#define upisopen(up) ((up)->v != &(up)->u.value)
|
||||
|
||||
|
||||
LUAI_FUNC Proto *luaF_newproto (lua_State *L);
|
||||
LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems);
|
||||
LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems);
|
||||
LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl);
|
||||
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 const char *luaF_getlocalname (const Proto *func, int local_number,
|
||||
int pc);
|
||||
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
** $Id: lgc.h,v 2.91.1.1 2017/04/19 17:39:34 roberto Exp $
|
||||
** Garbage Collector
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef lgc_h
|
||||
#define lgc_h
|
||||
|
||||
|
||||
#include "lobject.h"
|
||||
#include "lstate.h"
|
||||
|
||||
/*
|
||||
** Collectable objects may have one of three colors: white, which
|
||||
** means the object is not marked; gray, which means the
|
||||
** object is marked, but its references may be not marked; and
|
||||
** black, which means that the object and all its references are marked.
|
||||
** The main invariant of the garbage collector, while marking objects,
|
||||
** is that a black object can never point to a white one. Moreover,
|
||||
** any gray object must be in a "gray list" (gray, grayagain, weak,
|
||||
** allweak, ephemeron) so that it can be visited again before finishing
|
||||
** the collection cycle. These lists have no meaning when the invariant
|
||||
** is not being enforced (e.g., sweep phase).
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* how much to allocate before next GC step */
|
||||
#if !defined(GCSTEPSIZE)
|
||||
/* ~100 small strings */
|
||||
#define GCSTEPSIZE (cast_int(100 * sizeof(TString)))
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Possible states of the Garbage Collector
|
||||
*/
|
||||
#define GCSpropagate 0
|
||||
#define GCSatomic 1
|
||||
#define GCSswpallgc 2
|
||||
#define GCSswpfinobj 3
|
||||
#define GCSswptobefnz 4
|
||||
#define GCSswpend 5
|
||||
#define GCScallfin 6
|
||||
#define GCSpause 7
|
||||
|
||||
|
||||
#define issweepphase(g) \
|
||||
(GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend)
|
||||
|
||||
|
||||
/*
|
||||
** macro to tell when main invariant (white objects cannot point to black
|
||||
** ones) must be kept. During a collection, the sweep
|
||||
** phase may break the invariant, as objects turned white may point to
|
||||
** still-black objects. The invariant is restored when sweep ends and
|
||||
** all objects are white again.
|
||||
*/
|
||||
|
||||
#define keepinvariant(g) ((g)->gcstate <= GCSatomic)
|
||||
|
||||
|
||||
/*
|
||||
** some useful bit tricks
|
||||
*/
|
||||
#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m)))
|
||||
#define setbits(x,m) ((x) |= (m))
|
||||
#define testbits(x,m) ((x) & (m))
|
||||
#define bitmask(b) (1<<(b))
|
||||
#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2))
|
||||
#define l_setbit(x,b) setbits(x, bitmask(b))
|
||||
#define resetbit(x,b) resetbits(x, bitmask(b))
|
||||
#define testbit(x,b) testbits(x, bitmask(b))
|
||||
|
||||
|
||||
/* Layout for bit use in 'marked' field: */
|
||||
#define WHITE0BIT 0 /* object is white (type 0) */
|
||||
#define WHITE1BIT 1 /* object is white (type 1) */
|
||||
#define BLACKBIT 2 /* object is black */
|
||||
#define FINALIZEDBIT 3 /* object has been marked for finalization */
|
||||
/* bit 7 is currently used by tests (luaL_checkmemory) */
|
||||
|
||||
#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
|
||||
|
||||
|
||||
#define iswhite(x) testbits((x)->marked, WHITEBITS)
|
||||
#define isblack(x) testbit((x)->marked, BLACKBIT)
|
||||
#define isgray(x) /* neither white nor black */ \
|
||||
(!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT)))
|
||||
|
||||
#define tofinalize(x) testbit((x)->marked, FINALIZEDBIT)
|
||||
|
||||
#define otherwhite(g) ((g)->currentwhite ^ WHITEBITS)
|
||||
#define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow)))
|
||||
#define isdead(g,v) isdeadm(otherwhite(g), (v)->marked)
|
||||
|
||||
#define changewhite(x) ((x)->marked ^= WHITEBITS)
|
||||
#define gray2black(x) l_setbit((x)->marked, BLACKBIT)
|
||||
|
||||
#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
|
||||
|
||||
|
||||
/*
|
||||
** Does one step of collection when debt becomes positive. 'pre'/'pos'
|
||||
** allows some adjustments to be done only when needed. macro
|
||||
** 'condchangemem' is used only for heavy tests (forcing a full
|
||||
** GC cycle on every opportunity)
|
||||
*/
|
||||
#define luaC_condGC(L,pre,pos) \
|
||||
{ if (G(L)->GCdebt > 0) { pre; luaC_step(L); pos;}; \
|
||||
condchangemem(L,pre,pos); }
|
||||
|
||||
/* more often than not, 'pre'/'pos' are empty */
|
||||
#define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0)
|
||||
|
||||
|
||||
#define luaC_barrier(L,p,v) ( \
|
||||
(iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \
|
||||
luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0))
|
||||
|
||||
#define luaC_barrierback(L,p,v) ( \
|
||||
(iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \
|
||||
luaC_barrierback_(L,p) : cast_void(0))
|
||||
|
||||
#define luaC_objbarrier(L,p,o) ( \
|
||||
(isblack(p) && iswhite(o)) ? \
|
||||
luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0))
|
||||
|
||||
#define luaC_upvalbarrier(L,uv) ( \
|
||||
(iscollectable((uv)->v) && !upisopen(uv)) ? \
|
||||
luaC_upvalbarrier_(L,uv) : cast_void(0))
|
||||
|
||||
LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o);
|
||||
LUAI_FUNC void luaC_freeallobjects (lua_State *L);
|
||||
LUAI_FUNC void luaC_step (lua_State *L);
|
||||
LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask);
|
||||
LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency);
|
||||
LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz);
|
||||
LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v);
|
||||
LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o);
|
||||
LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv);
|
||||
LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt);
|
||||
LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv);
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
** $Id: linit.c,v 1.39.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Initialization of libraries for lua.c and other clients
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#define linit_c
|
||||
#define LUA_LIB
|
||||
|
||||
/*
|
||||
** If you embed Lua in your program and need to open the standard
|
||||
** libraries, call luaL_openlibs in your program. If you need a
|
||||
** different set of libraries, copy this file to your project and edit
|
||||
** it to suit your needs.
|
||||
**
|
||||
** You can also *preload* libraries, so that a later 'require' can
|
||||
** open the library, which is already linked to the application.
|
||||
** For that, do the following code:
|
||||
**
|
||||
** luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
|
||||
** lua_pushcfunction(L, luaopen_modname);
|
||||
** lua_setfield(L, -2, modname);
|
||||
** lua_pop(L, 1); // remove PRELOAD table
|
||||
*/
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
|
||||
|
||||
/*
|
||||
** these libs are loaded by lua.c and are readily available to any Lua
|
||||
** program
|
||||
*/
|
||||
static const luaL_Reg loadedlibs[] = {
|
||||
{"_G", luaopen_base},
|
||||
{LUA_LOADLIBNAME, luaopen_package},
|
||||
{LUA_COLIBNAME, luaopen_coroutine},
|
||||
{LUA_TABLIBNAME, luaopen_table},
|
||||
{LUA_IOLIBNAME, luaopen_io},
|
||||
{LUA_OSLIBNAME, luaopen_os},
|
||||
{LUA_STRLIBNAME, luaopen_string},
|
||||
{LUA_MATHLIBNAME, luaopen_math},
|
||||
{LUA_UTF8LIBNAME, luaopen_utf8},
|
||||
{LUA_DBLIBNAME, luaopen_debug},
|
||||
#if defined(LUA_COMPAT_BITLIB)
|
||||
{LUA_BITLIBNAME, luaopen_bit32},
|
||||
#endif
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
LUALIB_API void luaL_openlibs (lua_State *L) {
|
||||
const luaL_Reg *lib;
|
||||
/* "require" functions from 'loadedlibs' and set results to global table */
|
||||
for (lib = loadedlibs; lib->func; lib++) {
|
||||
luaL_requiref(L, lib->name, lib->func, 1);
|
||||
lua_pop(L, 1); /* remove lib */
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,776 @@
|
|||
/*
|
||||
** $Id: liolib.c,v 2.151.1.1 2017/04/19 17:29:57 roberto Exp $
|
||||
** Standard I/O (and system) library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define liolib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Change this macro to accept other modes for 'fopen' besides
|
||||
** the standard ones.
|
||||
*/
|
||||
#if !defined(l_checkmode)
|
||||
|
||||
/* accepted extensions to 'mode' in 'fopen' */
|
||||
#if !defined(L_MODEEXT)
|
||||
#define L_MODEEXT "b"
|
||||
#endif
|
||||
|
||||
/* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */
|
||||
static int l_checkmode (const char *mode) {
|
||||
return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL &&
|
||||
(*mode != '+' || (++mode, 1)) && /* skip if char is '+' */
|
||||
(strspn(mode, L_MODEEXT) == strlen(mode))); /* check extensions */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** l_popen spawns a new process connected to the current
|
||||
** one through the file streams.
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
#if !defined(l_popen) /* { */
|
||||
|
||||
#if defined(LUA_USE_POSIX) /* { */
|
||||
|
||||
#define l_popen(L,c,m) (fflush(NULL), popen(c,m))
|
||||
#define l_pclose(L,file) (pclose(file))
|
||||
|
||||
#elif defined(LUA_USE_WINDOWS) /* }{ */
|
||||
|
||||
#define l_popen(L,c,m) (_popen(c,m))
|
||||
#define l_pclose(L,file) (_pclose(file))
|
||||
|
||||
#else /* }{ */
|
||||
|
||||
/* ISO C definitions */
|
||||
#define l_popen(L,c,m) \
|
||||
((void)((void)c, m), \
|
||||
luaL_error(L, "'popen' not supported"), \
|
||||
(FILE*)0)
|
||||
#define l_pclose(L,file) ((void)L, (void)file, -1)
|
||||
|
||||
#endif /* } */
|
||||
|
||||
#endif /* } */
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
#if !defined(l_getc) /* { */
|
||||
|
||||
#if defined(LUA_USE_POSIX)
|
||||
#define l_getc(f) getc_unlocked(f)
|
||||
#define l_lockfile(f) flockfile(f)
|
||||
#define l_unlockfile(f) funlockfile(f)
|
||||
#else
|
||||
#define l_getc(f) getc(f)
|
||||
#define l_lockfile(f) ((void)0)
|
||||
#define l_unlockfile(f) ((void)0)
|
||||
#endif
|
||||
|
||||
#endif /* } */
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** l_fseek: configuration for longer offsets
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
#if !defined(l_fseek) /* { */
|
||||
|
||||
#if defined(LUA_USE_POSIX) /* { */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#define l_fseek(f,o,w) fseeko(f,o,w)
|
||||
#define l_ftell(f) ftello(f)
|
||||
#define l_seeknum off_t
|
||||
|
||||
#elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \
|
||||
&& defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */
|
||||
|
||||
/* Windows (but not DDK) and Visual C++ 2005 or higher */
|
||||
#define l_fseek(f,o,w) _fseeki64(f,o,w)
|
||||
#define l_ftell(f) _ftelli64(f)
|
||||
#define l_seeknum __int64
|
||||
|
||||
#else /* }{ */
|
||||
|
||||
/* ISO C definitions */
|
||||
#define l_fseek(f,o,w) fseek(f,o,w)
|
||||
#define l_ftell(f) ftell(f)
|
||||
#define l_seeknum long
|
||||
|
||||
#endif /* } */
|
||||
|
||||
#endif /* } */
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
#define IO_PREFIX "_IO_"
|
||||
#define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1)
|
||||
#define IO_INPUT (IO_PREFIX "input")
|
||||
#define IO_OUTPUT (IO_PREFIX "output")
|
||||
|
||||
|
||||
typedef luaL_Stream LStream;
|
||||
|
||||
|
||||
#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
|
||||
|
||||
#define isclosed(p) ((p)->closef == NULL)
|
||||
|
||||
|
||||
static int io_type (lua_State *L) {
|
||||
LStream *p;
|
||||
luaL_checkany(L, 1);
|
||||
p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
|
||||
if (p == NULL)
|
||||
lua_pushnil(L); /* not a file */
|
||||
else if (isclosed(p))
|
||||
lua_pushliteral(L, "closed file");
|
||||
else
|
||||
lua_pushliteral(L, "file");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int f_tostring (lua_State *L) {
|
||||
LStream *p = tolstream(L);
|
||||
if (isclosed(p))
|
||||
lua_pushliteral(L, "file (closed)");
|
||||
else
|
||||
lua_pushfstring(L, "file (%p)", p->f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static FILE *tofile (lua_State *L) {
|
||||
LStream *p = tolstream(L);
|
||||
if (isclosed(p))
|
||||
luaL_error(L, "attempt to use a closed file");
|
||||
lua_assert(p->f);
|
||||
return p->f;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** When creating file handles, always creates a 'closed' file handle
|
||||
** before opening the actual file; so, if there is a memory error, the
|
||||
** handle is in a consistent state.
|
||||
*/
|
||||
static LStream *newprefile (lua_State *L) {
|
||||
LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream));
|
||||
p->closef = NULL; /* mark file handle as 'closed' */
|
||||
luaL_setmetatable(L, LUA_FILEHANDLE);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Calls the 'close' function from a file handle. The 'volatile' avoids
|
||||
** a bug in some versions of the Clang compiler (e.g., clang 3.0 for
|
||||
** 32 bits).
|
||||
*/
|
||||
static int aux_close (lua_State *L) {
|
||||
LStream *p = tolstream(L);
|
||||
volatile lua_CFunction cf = p->closef;
|
||||
p->closef = NULL; /* mark stream as closed */
|
||||
return (*cf)(L); /* close it */
|
||||
}
|
||||
|
||||
|
||||
static int f_close (lua_State *L) {
|
||||
tofile(L); /* make sure argument is an open stream */
|
||||
return aux_close(L);
|
||||
}
|
||||
|
||||
|
||||
static int io_close (lua_State *L) {
|
||||
if (lua_isnone(L, 1)) /* no argument? */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */
|
||||
return f_close(L);
|
||||
}
|
||||
|
||||
|
||||
static int f_gc (lua_State *L) {
|
||||
LStream *p = tolstream(L);
|
||||
if (!isclosed(p) && p->f != NULL)
|
||||
aux_close(L); /* ignore closed and incompletely open files */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** function to close regular files
|
||||
*/
|
||||
static int io_fclose (lua_State *L) {
|
||||
LStream *p = tolstream(L);
|
||||
int res = fclose(p->f);
|
||||
return luaL_fileresult(L, (res == 0), NULL);
|
||||
}
|
||||
|
||||
|
||||
static LStream *newfile (lua_State *L) {
|
||||
LStream *p = newprefile(L);
|
||||
p->f = NULL;
|
||||
p->closef = &io_fclose;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static void opencheck (lua_State *L, const char *fname, const char *mode) {
|
||||
LStream *p = newfile(L);
|
||||
p->f = fopen(fname, mode);
|
||||
if (p->f == NULL)
|
||||
luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno));
|
||||
}
|
||||
|
||||
|
||||
static int io_open (lua_State *L) {
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
const char *mode = luaL_optstring(L, 2, "r");
|
||||
LStream *p = newfile(L);
|
||||
const char *md = mode; /* to traverse/check mode */
|
||||
luaL_argcheck(L, l_checkmode(md), 2, "invalid mode");
|
||||
p->f = fopen(filename, mode);
|
||||
return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** function to close 'popen' files
|
||||
*/
|
||||
static int io_pclose (lua_State *L) {
|
||||
LStream *p = tolstream(L);
|
||||
return luaL_execresult(L, l_pclose(L, p->f));
|
||||
}
|
||||
|
||||
|
||||
static int io_popen (lua_State *L) {
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
const char *mode = luaL_optstring(L, 2, "r");
|
||||
LStream *p = newprefile(L);
|
||||
p->f = l_popen(L, filename, mode);
|
||||
p->closef = &io_pclose;
|
||||
return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
|
||||
}
|
||||
|
||||
|
||||
static int io_tmpfile (lua_State *L) {
|
||||
LStream *p = newfile(L);
|
||||
p->f = tmpfile();
|
||||
return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
|
||||
}
|
||||
|
||||
|
||||
static FILE *getiofile (lua_State *L, const char *findex) {
|
||||
LStream *p;
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, findex);
|
||||
p = (LStream *)lua_touserdata(L, -1);
|
||||
if (isclosed(p))
|
||||
luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN);
|
||||
return p->f;
|
||||
}
|
||||
|
||||
|
||||
static int g_iofile (lua_State *L, const char *f, const char *mode) {
|
||||
if (!lua_isnoneornil(L, 1)) {
|
||||
const char *filename = lua_tostring(L, 1);
|
||||
if (filename)
|
||||
opencheck(L, filename, mode);
|
||||
else {
|
||||
tofile(L); /* check that it's a valid file handle */
|
||||
lua_pushvalue(L, 1);
|
||||
}
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, f);
|
||||
}
|
||||
/* return current value */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int io_input (lua_State *L) {
|
||||
return g_iofile(L, IO_INPUT, "r");
|
||||
}
|
||||
|
||||
|
||||
static int io_output (lua_State *L) {
|
||||
return g_iofile(L, IO_OUTPUT, "w");
|
||||
}
|
||||
|
||||
|
||||
static int io_readline (lua_State *L);
|
||||
|
||||
|
||||
/*
|
||||
** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit
|
||||
** in the limit for upvalues of a closure)
|
||||
*/
|
||||
#define MAXARGLINE 250
|
||||
|
||||
static void aux_lines (lua_State *L, int toclose) {
|
||||
int n = lua_gettop(L) - 1; /* number of arguments to read */
|
||||
luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments");
|
||||
lua_pushinteger(L, n); /* number of arguments to read */
|
||||
lua_pushboolean(L, toclose); /* close/not close file when finished */
|
||||
lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */
|
||||
lua_pushcclosure(L, io_readline, 3 + n);
|
||||
}
|
||||
|
||||
|
||||
static int f_lines (lua_State *L) {
|
||||
tofile(L); /* check that it's a valid file handle */
|
||||
aux_lines(L, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int io_lines (lua_State *L) {
|
||||
int toclose;
|
||||
if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */
|
||||
if (lua_isnil(L, 1)) { /* no file name? */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */
|
||||
lua_replace(L, 1); /* put it at index 1 */
|
||||
tofile(L); /* check that it's a valid file handle */
|
||||
toclose = 0; /* do not close it after iteration */
|
||||
}
|
||||
else { /* open a new file */
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
opencheck(L, filename, "r");
|
||||
lua_replace(L, 1); /* put file at index 1 */
|
||||
toclose = 1; /* close it after iteration */
|
||||
}
|
||||
aux_lines(L, toclose);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** READ
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
/* maximum length of a numeral */
|
||||
#if !defined (L_MAXLENNUM)
|
||||
#define L_MAXLENNUM 200
|
||||
#endif
|
||||
|
||||
|
||||
/* auxiliary structure used by 'read_number' */
|
||||
typedef struct {
|
||||
FILE *f; /* file being read */
|
||||
int c; /* current character (look ahead) */
|
||||
int n; /* number of elements in buffer 'buff' */
|
||||
char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */
|
||||
} RN;
|
||||
|
||||
|
||||
/*
|
||||
** Add current char to buffer (if not out of space) and read next one
|
||||
*/
|
||||
static int nextc (RN *rn) {
|
||||
if (rn->n >= L_MAXLENNUM) { /* buffer overflow? */
|
||||
rn->buff[0] = '\0'; /* invalidate result */
|
||||
return 0; /* fail */
|
||||
}
|
||||
else {
|
||||
rn->buff[rn->n++] = rn->c; /* save current char */
|
||||
rn->c = l_getc(rn->f); /* read next one */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Accept current char if it is in 'set' (of size 2)
|
||||
*/
|
||||
static int test2 (RN *rn, const char *set) {
|
||||
if (rn->c == set[0] || rn->c == set[1])
|
||||
return nextc(rn);
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Read a sequence of (hex)digits
|
||||
*/
|
||||
static int readdigits (RN *rn, int hex) {
|
||||
int count = 0;
|
||||
while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn))
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Read a number: first reads a valid prefix of a numeral into a buffer.
|
||||
** Then it calls 'lua_stringtonumber' to check whether the format is
|
||||
** correct and to convert it to a Lua number
|
||||
*/
|
||||
static int read_number (lua_State *L, FILE *f) {
|
||||
RN rn;
|
||||
int count = 0;
|
||||
int hex = 0;
|
||||
char decp[2];
|
||||
rn.f = f; rn.n = 0;
|
||||
decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */
|
||||
decp[1] = '.'; /* always accept a dot */
|
||||
l_lockfile(rn.f);
|
||||
do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */
|
||||
test2(&rn, "-+"); /* optional signal */
|
||||
if (test2(&rn, "00")) {
|
||||
if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */
|
||||
else count = 1; /* count initial '0' as a valid digit */
|
||||
}
|
||||
count += readdigits(&rn, hex); /* integral part */
|
||||
if (test2(&rn, decp)) /* decimal point? */
|
||||
count += readdigits(&rn, hex); /* fractional part */
|
||||
if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) { /* exponent mark? */
|
||||
test2(&rn, "-+"); /* exponent signal */
|
||||
readdigits(&rn, 0); /* exponent digits */
|
||||
}
|
||||
ungetc(rn.c, rn.f); /* unread look-ahead char */
|
||||
l_unlockfile(rn.f);
|
||||
rn.buff[rn.n] = '\0'; /* finish string */
|
||||
if (lua_stringtonumber(L, rn.buff)) /* is this a valid number? */
|
||||
return 1; /* ok */
|
||||
else { /* invalid format */
|
||||
lua_pushnil(L); /* "result" to be removed */
|
||||
return 0; /* read fails */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int test_eof (lua_State *L, FILE *f) {
|
||||
int c = getc(f);
|
||||
ungetc(c, f); /* no-op when c == EOF */
|
||||
lua_pushliteral(L, "");
|
||||
return (c != EOF);
|
||||
}
|
||||
|
||||
|
||||
static int read_line (lua_State *L, FILE *f, int chop) {
|
||||
luaL_Buffer b;
|
||||
int c = '\0';
|
||||
luaL_buffinit(L, &b);
|
||||
while (c != EOF && c != '\n') { /* repeat until end of line */
|
||||
char *buff = luaL_prepbuffer(&b); /* preallocate buffer */
|
||||
int i = 0;
|
||||
l_lockfile(f); /* no memory errors can happen inside the lock */
|
||||
while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n')
|
||||
buff[i++] = c;
|
||||
l_unlockfile(f);
|
||||
luaL_addsize(&b, i);
|
||||
}
|
||||
if (!chop && c == '\n') /* want a newline and have one? */
|
||||
luaL_addchar(&b, c); /* add ending newline to result */
|
||||
luaL_pushresult(&b); /* close buffer */
|
||||
/* return ok if read something (either a newline or something else) */
|
||||
return (c == '\n' || lua_rawlen(L, -1) > 0);
|
||||
}
|
||||
|
||||
|
||||
static void read_all (lua_State *L, FILE *f) {
|
||||
size_t nr;
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
do { /* read file in chunks of LUAL_BUFFERSIZE bytes */
|
||||
char *p = luaL_prepbuffer(&b);
|
||||
nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f);
|
||||
luaL_addsize(&b, nr);
|
||||
} while (nr == LUAL_BUFFERSIZE);
|
||||
luaL_pushresult(&b); /* close buffer */
|
||||
}
|
||||
|
||||
|
||||
static int read_chars (lua_State *L, FILE *f, size_t n) {
|
||||
size_t nr; /* number of chars actually read */
|
||||
char *p;
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */
|
||||
nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */
|
||||
luaL_addsize(&b, nr);
|
||||
luaL_pushresult(&b); /* close buffer */
|
||||
return (nr > 0); /* true iff read something */
|
||||
}
|
||||
|
||||
|
||||
static int g_read (lua_State *L, FILE *f, int first) {
|
||||
int nargs = lua_gettop(L) - 1;
|
||||
int success;
|
||||
int n;
|
||||
clearerr(f);
|
||||
if (nargs == 0) { /* no arguments? */
|
||||
success = read_line(L, f, 1);
|
||||
n = first+1; /* to return 1 result */
|
||||
}
|
||||
else { /* ensure stack space for all results and for auxlib's buffer */
|
||||
luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
|
||||
success = 1;
|
||||
for (n = first; nargs-- && success; n++) {
|
||||
if (lua_type(L, n) == LUA_TNUMBER) {
|
||||
size_t l = (size_t)luaL_checkinteger(L, n);
|
||||
success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
|
||||
}
|
||||
else {
|
||||
const char *p = luaL_checkstring(L, n);
|
||||
if (*p == '*') p++; /* skip optional '*' (for compatibility) */
|
||||
switch (*p) {
|
||||
case 'n': /* number */
|
||||
success = read_number(L, f);
|
||||
break;
|
||||
case 'l': /* line */
|
||||
success = read_line(L, f, 1);
|
||||
break;
|
||||
case 'L': /* line with end-of-line */
|
||||
success = read_line(L, f, 0);
|
||||
break;
|
||||
case 'a': /* file */
|
||||
read_all(L, f); /* read entire file */
|
||||
success = 1; /* always success */
|
||||
break;
|
||||
default:
|
||||
return luaL_argerror(L, n, "invalid format");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ferror(f))
|
||||
return luaL_fileresult(L, 0, NULL);
|
||||
if (!success) {
|
||||
lua_pop(L, 1); /* remove last result */
|
||||
lua_pushnil(L); /* push nil instead */
|
||||
}
|
||||
return n - first;
|
||||
}
|
||||
|
||||
|
||||
static int io_read (lua_State *L) {
|
||||
return g_read(L, getiofile(L, IO_INPUT), 1);
|
||||
}
|
||||
|
||||
|
||||
static int f_read (lua_State *L) {
|
||||
return g_read(L, tofile(L), 2);
|
||||
}
|
||||
|
||||
|
||||
static int io_readline (lua_State *L) {
|
||||
LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1));
|
||||
int i;
|
||||
int n = (int)lua_tointeger(L, lua_upvalueindex(2));
|
||||
if (isclosed(p)) /* file is already closed? */
|
||||
return luaL_error(L, "file is already closed");
|
||||
lua_settop(L , 1);
|
||||
luaL_checkstack(L, n, "too many arguments");
|
||||
for (i = 1; i <= n; i++) /* push arguments to 'g_read' */
|
||||
lua_pushvalue(L, lua_upvalueindex(3 + i));
|
||||
n = g_read(L, p->f, 2); /* 'n' is number of results */
|
||||
lua_assert(n > 0); /* should return at least a nil */
|
||||
if (lua_toboolean(L, -n)) /* read at least one value? */
|
||||
return n; /* return them */
|
||||
else { /* first result is nil: EOF or error */
|
||||
if (n > 1) { /* is there error information? */
|
||||
/* 2nd result is error message */
|
||||
return luaL_error(L, "%s", lua_tostring(L, -n + 1));
|
||||
}
|
||||
if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */
|
||||
lua_settop(L, 0);
|
||||
lua_pushvalue(L, lua_upvalueindex(1));
|
||||
aux_close(L); /* close it */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
static int g_write (lua_State *L, FILE *f, int arg) {
|
||||
int nargs = lua_gettop(L) - arg;
|
||||
int status = 1;
|
||||
for (; nargs--; arg++) {
|
||||
if (lua_type(L, arg) == LUA_TNUMBER) {
|
||||
/* optimization: could be done exactly as for strings */
|
||||
int len = lua_isinteger(L, arg)
|
||||
? fprintf(f, LUA_INTEGER_FMT,
|
||||
(LUAI_UACINT)lua_tointeger(L, arg))
|
||||
: fprintf(f, LUA_NUMBER_FMT,
|
||||
(LUAI_UACNUMBER)lua_tonumber(L, arg));
|
||||
status = status && (len > 0);
|
||||
}
|
||||
else {
|
||||
size_t l;
|
||||
const char *s = luaL_checklstring(L, arg, &l);
|
||||
status = status && (fwrite(s, sizeof(char), l, f) == l);
|
||||
}
|
||||
}
|
||||
if (status) return 1; /* file handle already on stack top */
|
||||
else return luaL_fileresult(L, status, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int io_write (lua_State *L) {
|
||||
return g_write(L, getiofile(L, IO_OUTPUT), 1);
|
||||
}
|
||||
|
||||
|
||||
static int f_write (lua_State *L) {
|
||||
FILE *f = tofile(L);
|
||||
lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */
|
||||
return g_write(L, f, 2);
|
||||
}
|
||||
|
||||
|
||||
static int f_seek (lua_State *L) {
|
||||
static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
|
||||
static const char *const modenames[] = {"set", "cur", "end", NULL};
|
||||
FILE *f = tofile(L);
|
||||
int op = luaL_checkoption(L, 2, "cur", modenames);
|
||||
lua_Integer p3 = luaL_optinteger(L, 3, 0);
|
||||
l_seeknum offset = (l_seeknum)p3;
|
||||
luaL_argcheck(L, (lua_Integer)offset == p3, 3,
|
||||
"not an integer in proper range");
|
||||
op = l_fseek(f, offset, mode[op]);
|
||||
if (op)
|
||||
return luaL_fileresult(L, 0, NULL); /* error */
|
||||
else {
|
||||
lua_pushinteger(L, (lua_Integer)l_ftell(f));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int f_setvbuf (lua_State *L) {
|
||||
static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
|
||||
static const char *const modenames[] = {"no", "full", "line", NULL};
|
||||
FILE *f = tofile(L);
|
||||
int op = luaL_checkoption(L, 2, NULL, modenames);
|
||||
lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
|
||||
int res = setvbuf(f, NULL, mode[op], (size_t)sz);
|
||||
return luaL_fileresult(L, res == 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int io_flush (lua_State *L) {
|
||||
return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int f_flush (lua_State *L) {
|
||||
return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** functions for 'io' library
|
||||
*/
|
||||
static const luaL_Reg iolib[] = {
|
||||
{"close", io_close},
|
||||
{"flush", io_flush},
|
||||
{"input", io_input},
|
||||
{"lines", io_lines},
|
||||
{"open", io_open},
|
||||
{"output", io_output},
|
||||
{"popen", io_popen},
|
||||
{"read", io_read},
|
||||
{"tmpfile", io_tmpfile},
|
||||
{"type", io_type},
|
||||
{"write", io_write},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** methods for file handles
|
||||
*/
|
||||
static const luaL_Reg flib[] = {
|
||||
{"close", f_close},
|
||||
{"flush", f_flush},
|
||||
{"lines", f_lines},
|
||||
{"read", f_read},
|
||||
{"seek", f_seek},
|
||||
{"setvbuf", f_setvbuf},
|
||||
{"write", f_write},
|
||||
{"__gc", f_gc},
|
||||
{"__tostring", f_tostring},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
static void createmeta (lua_State *L) {
|
||||
luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
|
||||
lua_pushvalue(L, -1); /* push metatable */
|
||||
lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
|
||||
luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */
|
||||
lua_pop(L, 1); /* pop new metatable */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** function to (not) close the standard files stdin, stdout, and stderr
|
||||
*/
|
||||
static int io_noclose (lua_State *L) {
|
||||
LStream *p = tolstream(L);
|
||||
p->closef = &io_noclose; /* keep file opened */
|
||||
lua_pushnil(L);
|
||||
lua_pushliteral(L, "cannot close standard file");
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
static void createstdfile (lua_State *L, FILE *f, const char *k,
|
||||
const char *fname) {
|
||||
LStream *p = newprefile(L);
|
||||
p->f = f;
|
||||
p->closef = &io_noclose;
|
||||
if (k != NULL) {
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */
|
||||
}
|
||||
lua_setfield(L, -2, fname); /* add file to module */
|
||||
}
|
||||
|
||||
|
||||
LUAMOD_API int luaopen_io (lua_State *L) {
|
||||
luaL_newlib(L, iolib); /* new module */
|
||||
createmeta(L);
|
||||
/* create (and set) default files */
|
||||
createstdfile(L, stdin, IO_INPUT, "stdin");
|
||||
createstdfile(L, stdout, IO_OUTPUT, "stdout");
|
||||
createstdfile(L, stderr, NULL, "stderr");
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,565 @@
|
|||
/*
|
||||
** $Id: llex.c,v 2.96.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Lexical Analyzer
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define llex_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lctype.h"
|
||||
#include "ldebug.h"
|
||||
#include "ldo.h"
|
||||
#include "lgc.h"
|
||||
#include "llex.h"
|
||||
#include "lobject.h"
|
||||
#include "lparser.h"
|
||||
#include "lstate.h"
|
||||
#include "lstring.h"
|
||||
#include "ltable.h"
|
||||
#include "lzio.h"
|
||||
|
||||
|
||||
|
||||
#define next(ls) (ls->current = zgetc(ls->z))
|
||||
|
||||
|
||||
|
||||
#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r')
|
||||
|
||||
|
||||
/* ORDER RESERVED */
|
||||
static const char *const luaX_tokens [] = {
|
||||
"and", "break", "do", "else", "elseif",
|
||||
"end", "false", "for", "function", "goto", "if",
|
||||
"in", "local", "nil", "not", "or", "repeat",
|
||||
"return", "then", "true", "until", "while",
|
||||
"//", "..", "...", "==", ">=", "<=", "~=",
|
||||
"<<", ">>", "::", "<eof>",
|
||||
"<number>", "<integer>", "<name>", "<string>"
|
||||
};
|
||||
|
||||
|
||||
#define save_and_next(ls) (save(ls, ls->current), next(ls))
|
||||
|
||||
|
||||
static l_noret lexerror (LexState *ls, const char *msg, int token);
|
||||
|
||||
|
||||
static void save (LexState *ls, int c) {
|
||||
Mbuffer *b = ls->buff;
|
||||
if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) {
|
||||
size_t newsize;
|
||||
if (luaZ_sizebuffer(b) >= MAX_SIZE/2)
|
||||
lexerror(ls, "lexical element too long", 0);
|
||||
newsize = luaZ_sizebuffer(b) * 2;
|
||||
luaZ_resizebuffer(ls->L, b, newsize);
|
||||
}
|
||||
b->buffer[luaZ_bufflen(b)++] = cast(char, c);
|
||||
}
|
||||
|
||||
|
||||
void luaX_init (lua_State *L) {
|
||||
int i;
|
||||
TString *e = luaS_newliteral(L, LUA_ENV); /* create env name */
|
||||
luaC_fix(L, obj2gco(e)); /* never collect this name */
|
||||
for (i=0; i<NUM_RESERVED; i++) {
|
||||
TString *ts = luaS_new(L, luaX_tokens[i]);
|
||||
luaC_fix(L, obj2gco(ts)); /* reserved words are never collected */
|
||||
ts->extra = cast_byte(i+1); /* reserved word */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char *luaX_token2str (LexState *ls, int token) {
|
||||
if (token < FIRST_RESERVED) { /* single-byte symbols? */
|
||||
lua_assert(token == cast_uchar(token));
|
||||
return luaO_pushfstring(ls->L, "'%c'", token);
|
||||
}
|
||||
else {
|
||||
const char *s = luaX_tokens[token - FIRST_RESERVED];
|
||||
if (token < TK_EOS) /* fixed format (symbols and reserved words)? */
|
||||
return luaO_pushfstring(ls->L, "'%s'", s);
|
||||
else /* names, strings, and numerals */
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char *txtToken (LexState *ls, int token) {
|
||||
switch (token) {
|
||||
case TK_NAME: case TK_STRING:
|
||||
case TK_FLT: case TK_INT:
|
||||
save(ls, '\0');
|
||||
return luaO_pushfstring(ls->L, "'%s'", luaZ_buffer(ls->buff));
|
||||
default:
|
||||
return luaX_token2str(ls, token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static l_noret lexerror (LexState *ls, const char *msg, int token) {
|
||||
msg = luaG_addinfo(ls->L, msg, ls->source, ls->linenumber);
|
||||
if (token)
|
||||
luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token));
|
||||
luaD_throw(ls->L, LUA_ERRSYNTAX);
|
||||
}
|
||||
|
||||
|
||||
l_noret luaX_syntaxerror (LexState *ls, const char *msg) {
|
||||
lexerror(ls, msg, ls->t.token);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** creates a new string and anchors it in scanner's table so that
|
||||
** it will not be collected until the end of the compilation
|
||||
** (by that time it should be anchored somewhere)
|
||||
*/
|
||||
TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
|
||||
lua_State *L = ls->L;
|
||||
TValue *o; /* entry for 'str' */
|
||||
TString *ts = luaS_newlstr(L, str, l); /* create new string */
|
||||
setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */
|
||||
o = luaH_set(L, ls->h, L->top - 1);
|
||||
if (ttisnil(o)) { /* not in use yet? */
|
||||
/* boolean value does not need GC barrier;
|
||||
table has no metatable, so it does not need to invalidate cache */
|
||||
setbvalue(o, 1); /* t[string] = true */
|
||||
luaC_checkGC(L);
|
||||
}
|
||||
else { /* string already present */
|
||||
ts = tsvalue(keyfromval(o)); /* re-use value previously stored */
|
||||
}
|
||||
L->top--; /* remove string from stack */
|
||||
return ts;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** increment line number and skips newline sequence (any of
|
||||
** \n, \r, \n\r, or \r\n)
|
||||
*/
|
||||
static void inclinenumber (LexState *ls) {
|
||||
int old = ls->current;
|
||||
lua_assert(currIsNewline(ls));
|
||||
next(ls); /* skip '\n' or '\r' */
|
||||
if (currIsNewline(ls) && ls->current != old)
|
||||
next(ls); /* skip '\n\r' or '\r\n' */
|
||||
if (++ls->linenumber >= MAX_INT)
|
||||
lexerror(ls, "chunk has too many lines", 0);
|
||||
}
|
||||
|
||||
|
||||
void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source,
|
||||
int firstchar) {
|
||||
ls->t.token = 0;
|
||||
ls->L = L;
|
||||
ls->current = firstchar;
|
||||
ls->lookahead.token = TK_EOS; /* no look-ahead token */
|
||||
ls->z = z;
|
||||
ls->fs = NULL;
|
||||
ls->linenumber = 1;
|
||||
ls->lastline = 1;
|
||||
ls->source = source;
|
||||
ls->envn = luaS_newliteral(L, LUA_ENV); /* get env name */
|
||||
luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** =======================================================
|
||||
** LEXICAL ANALYZER
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
static int check_next1 (LexState *ls, int c) {
|
||||
if (ls->current == c) {
|
||||
next(ls);
|
||||
return 1;
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Check whether current char is in set 'set' (with two chars) and
|
||||
** saves it
|
||||
*/
|
||||
static int check_next2 (LexState *ls, const char *set) {
|
||||
lua_assert(set[2] == '\0');
|
||||
if (ls->current == set[0] || ls->current == set[1]) {
|
||||
save_and_next(ls);
|
||||
return 1;
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
||||
/* LUA_NUMBER */
|
||||
/*
|
||||
** this function is quite liberal in what it accepts, as 'luaO_str2num'
|
||||
** will reject ill-formed numerals.
|
||||
*/
|
||||
static int read_numeral (LexState *ls, SemInfo *seminfo) {
|
||||
TValue obj;
|
||||
const char *expo = "Ee";
|
||||
int first = ls->current;
|
||||
lua_assert(lisdigit(ls->current));
|
||||
save_and_next(ls);
|
||||
if (first == '0' && check_next2(ls, "xX")) /* hexadecimal? */
|
||||
expo = "Pp";
|
||||
for (;;) {
|
||||
if (check_next2(ls, expo)) /* exponent part? */
|
||||
check_next2(ls, "-+"); /* optional exponent sign */
|
||||
if (lisxdigit(ls->current))
|
||||
save_and_next(ls);
|
||||
else if (ls->current == '.')
|
||||
save_and_next(ls);
|
||||
else break;
|
||||
}
|
||||
save(ls, '\0');
|
||||
if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0) /* format error? */
|
||||
lexerror(ls, "malformed number", TK_FLT);
|
||||
if (ttisinteger(&obj)) {
|
||||
seminfo->i = ivalue(&obj);
|
||||
return TK_INT;
|
||||
}
|
||||
else {
|
||||
lua_assert(ttisfloat(&obj));
|
||||
seminfo->r = fltvalue(&obj);
|
||||
return TK_FLT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** skip a sequence '[=*[' or ']=*]'; if sequence is well formed, return
|
||||
** its number of '='s; otherwise, return a negative number (-1 iff there
|
||||
** are no '='s after initial bracket)
|
||||
*/
|
||||
static int skip_sep (LexState *ls) {
|
||||
int count = 0;
|
||||
int s = ls->current;
|
||||
lua_assert(s == '[' || s == ']');
|
||||
save_and_next(ls);
|
||||
while (ls->current == '=') {
|
||||
save_and_next(ls);
|
||||
count++;
|
||||
}
|
||||
return (ls->current == s) ? count : (-count) - 1;
|
||||
}
|
||||
|
||||
|
||||
static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
|
||||
int line = ls->linenumber; /* initial line (for error message) */
|
||||
save_and_next(ls); /* skip 2nd '[' */
|
||||
if (currIsNewline(ls)) /* string starts with a newline? */
|
||||
inclinenumber(ls); /* skip it */
|
||||
for (;;) {
|
||||
switch (ls->current) {
|
||||
case EOZ: { /* error */
|
||||
const char *what = (seminfo ? "string" : "comment");
|
||||
const char *msg = luaO_pushfstring(ls->L,
|
||||
"unfinished long %s (starting at line %d)", what, line);
|
||||
lexerror(ls, msg, TK_EOS);
|
||||
break; /* to avoid warnings */
|
||||
}
|
||||
case ']': {
|
||||
if (skip_sep(ls) == sep) {
|
||||
save_and_next(ls); /* skip 2nd ']' */
|
||||
goto endloop;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '\n': case '\r': {
|
||||
save(ls, '\n');
|
||||
inclinenumber(ls);
|
||||
if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (seminfo) save_and_next(ls);
|
||||
else next(ls);
|
||||
}
|
||||
}
|
||||
} endloop:
|
||||
if (seminfo)
|
||||
seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),
|
||||
luaZ_bufflen(ls->buff) - 2*(2 + sep));
|
||||
}
|
||||
|
||||
|
||||
static void esccheck (LexState *ls, int c, const char *msg) {
|
||||
if (!c) {
|
||||
if (ls->current != EOZ)
|
||||
save_and_next(ls); /* add current to buffer for error message */
|
||||
lexerror(ls, msg, TK_STRING);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int gethexa (LexState *ls) {
|
||||
save_and_next(ls);
|
||||
esccheck (ls, lisxdigit(ls->current), "hexadecimal digit expected");
|
||||
return luaO_hexavalue(ls->current);
|
||||
}
|
||||
|
||||
|
||||
static int readhexaesc (LexState *ls) {
|
||||
int r = gethexa(ls);
|
||||
r = (r << 4) + gethexa(ls);
|
||||
luaZ_buffremove(ls->buff, 2); /* remove saved chars from buffer */
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static unsigned long readutf8esc (LexState *ls) {
|
||||
unsigned long r;
|
||||
int i = 4; /* chars to be removed: '\', 'u', '{', and first digit */
|
||||
save_and_next(ls); /* skip 'u' */
|
||||
esccheck(ls, ls->current == '{', "missing '{'");
|
||||
r = gethexa(ls); /* must have at least one digit */
|
||||
while ((save_and_next(ls), lisxdigit(ls->current))) {
|
||||
i++;
|
||||
r = (r << 4) + luaO_hexavalue(ls->current);
|
||||
esccheck(ls, r <= 0x10FFFF, "UTF-8 value too large");
|
||||
}
|
||||
esccheck(ls, ls->current == '}', "missing '}'");
|
||||
next(ls); /* skip '}' */
|
||||
luaZ_buffremove(ls->buff, i); /* remove saved chars from buffer */
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static void utf8esc (LexState *ls) {
|
||||
char buff[UTF8BUFFSZ];
|
||||
int n = luaO_utf8esc(buff, readutf8esc(ls));
|
||||
for (; n > 0; n--) /* add 'buff' to string */
|
||||
save(ls, buff[UTF8BUFFSZ - n]);
|
||||
}
|
||||
|
||||
|
||||
static int readdecesc (LexState *ls) {
|
||||
int i;
|
||||
int r = 0; /* result accumulator */
|
||||
for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */
|
||||
r = 10*r + ls->current - '0';
|
||||
save_and_next(ls);
|
||||
}
|
||||
esccheck(ls, r <= UCHAR_MAX, "decimal escape too large");
|
||||
luaZ_buffremove(ls->buff, i); /* remove read digits from buffer */
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static void read_string (LexState *ls, int del, SemInfo *seminfo) {
|
||||
save_and_next(ls); /* keep delimiter (for error messages) */
|
||||
while (ls->current != del) {
|
||||
switch (ls->current) {
|
||||
case EOZ:
|
||||
lexerror(ls, "unfinished string", TK_EOS);
|
||||
break; /* to avoid warnings */
|
||||
case '\n':
|
||||
case '\r':
|
||||
lexerror(ls, "unfinished string", TK_STRING);
|
||||
break; /* to avoid warnings */
|
||||
case '\\': { /* escape sequences */
|
||||
int c; /* final character to be saved */
|
||||
save_and_next(ls); /* keep '\\' for error messages */
|
||||
switch (ls->current) {
|
||||
case 'a': c = '\a'; goto read_save;
|
||||
case 'b': c = '\b'; goto read_save;
|
||||
case 'f': c = '\f'; goto read_save;
|
||||
case 'n': c = '\n'; goto read_save;
|
||||
case 'r': c = '\r'; goto read_save;
|
||||
case 't': c = '\t'; goto read_save;
|
||||
case 'v': c = '\v'; goto read_save;
|
||||
case 'x': c = readhexaesc(ls); goto read_save;
|
||||
case 'u': utf8esc(ls); goto no_save;
|
||||
case '\n': case '\r':
|
||||
inclinenumber(ls); c = '\n'; goto only_save;
|
||||
case '\\': case '\"': case '\'':
|
||||
c = ls->current; goto read_save;
|
||||
case EOZ: goto no_save; /* will raise an error next loop */
|
||||
case 'z': { /* zap following span of spaces */
|
||||
luaZ_buffremove(ls->buff, 1); /* remove '\\' */
|
||||
next(ls); /* skip the 'z' */
|
||||
while (lisspace(ls->current)) {
|
||||
if (currIsNewline(ls)) inclinenumber(ls);
|
||||
else next(ls);
|
||||
}
|
||||
goto no_save;
|
||||
}
|
||||
default: {
|
||||
esccheck(ls, lisdigit(ls->current), "invalid escape sequence");
|
||||
c = readdecesc(ls); /* digital escape '\ddd' */
|
||||
goto only_save;
|
||||
}
|
||||
}
|
||||
read_save:
|
||||
next(ls);
|
||||
/* go through */
|
||||
only_save:
|
||||
luaZ_buffremove(ls->buff, 1); /* remove '\\' */
|
||||
save(ls, c);
|
||||
/* go through */
|
||||
no_save: break;
|
||||
}
|
||||
default:
|
||||
save_and_next(ls);
|
||||
}
|
||||
}
|
||||
save_and_next(ls); /* skip delimiter */
|
||||
seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1,
|
||||
luaZ_bufflen(ls->buff) - 2);
|
||||
}
|
||||
|
||||
|
||||
static int llex (LexState *ls, SemInfo *seminfo) {
|
||||
luaZ_resetbuffer(ls->buff);
|
||||
for (;;) {
|
||||
switch (ls->current) {
|
||||
case '\n': case '\r': { /* line breaks */
|
||||
inclinenumber(ls);
|
||||
break;
|
||||
}
|
||||
case ' ': case '\f': case '\t': case '\v': { /* spaces */
|
||||
next(ls);
|
||||
break;
|
||||
}
|
||||
case '-': { /* '-' or '--' (comment) */
|
||||
next(ls);
|
||||
if (ls->current != '-') return '-';
|
||||
/* else is a comment */
|
||||
next(ls);
|
||||
if (ls->current == '[') { /* long comment? */
|
||||
int sep = skip_sep(ls);
|
||||
luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */
|
||||
if (sep >= 0) {
|
||||
read_long_string(ls, NULL, sep); /* skip long comment */
|
||||
luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* else short comment */
|
||||
while (!currIsNewline(ls) && ls->current != EOZ)
|
||||
next(ls); /* skip until end of line (or end of file) */
|
||||
break;
|
||||
}
|
||||
case '[': { /* long string or simply '[' */
|
||||
int sep = skip_sep(ls);
|
||||
if (sep >= 0) {
|
||||
read_long_string(ls, seminfo, sep);
|
||||
return TK_STRING;
|
||||
}
|
||||
else if (sep != -1) /* '[=...' missing second bracket */
|
||||
lexerror(ls, "invalid long string delimiter", TK_STRING);
|
||||
return '[';
|
||||
}
|
||||
case '=': {
|
||||
next(ls);
|
||||
if (check_next1(ls, '=')) return TK_EQ;
|
||||
else return '=';
|
||||
}
|
||||
case '<': {
|
||||
next(ls);
|
||||
if (check_next1(ls, '=')) return TK_LE;
|
||||
else if (check_next1(ls, '<')) return TK_SHL;
|
||||
else return '<';
|
||||
}
|
||||
case '>': {
|
||||
next(ls);
|
||||
if (check_next1(ls, '=')) return TK_GE;
|
||||
else if (check_next1(ls, '>')) return TK_SHR;
|
||||
else return '>';
|
||||
}
|
||||
case '/': {
|
||||
next(ls);
|
||||
if (check_next1(ls, '/')) return TK_IDIV;
|
||||
else return '/';
|
||||
}
|
||||
case '~': {
|
||||
next(ls);
|
||||
if (check_next1(ls, '=')) return TK_NE;
|
||||
else return '~';
|
||||
}
|
||||
case ':': {
|
||||
next(ls);
|
||||
if (check_next1(ls, ':')) return TK_DBCOLON;
|
||||
else return ':';
|
||||
}
|
||||
case '"': case '\'': { /* short literal strings */
|
||||
read_string(ls, ls->current, seminfo);
|
||||
return TK_STRING;
|
||||
}
|
||||
case '.': { /* '.', '..', '...', or number */
|
||||
save_and_next(ls);
|
||||
if (check_next1(ls, '.')) {
|
||||
if (check_next1(ls, '.'))
|
||||
return TK_DOTS; /* '...' */
|
||||
else return TK_CONCAT; /* '..' */
|
||||
}
|
||||
else if (!lisdigit(ls->current)) return '.';
|
||||
else return read_numeral(ls, seminfo);
|
||||
}
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9': {
|
||||
return read_numeral(ls, seminfo);
|
||||
}
|
||||
case EOZ: {
|
||||
return TK_EOS;
|
||||
}
|
||||
default: {
|
||||
if (lislalpha(ls->current)) { /* identifier or reserved word? */
|
||||
TString *ts;
|
||||
do {
|
||||
save_and_next(ls);
|
||||
} while (lislalnum(ls->current));
|
||||
ts = luaX_newstring(ls, luaZ_buffer(ls->buff),
|
||||
luaZ_bufflen(ls->buff));
|
||||
seminfo->ts = ts;
|
||||
if (isreserved(ts)) /* reserved word? */
|
||||
return ts->extra - 1 + FIRST_RESERVED;
|
||||
else {
|
||||
return TK_NAME;
|
||||
}
|
||||
}
|
||||
else { /* single-char tokens (+ - / ...) */
|
||||
int c = ls->current;
|
||||
next(ls);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void luaX_next (LexState *ls) {
|
||||
ls->lastline = ls->linenumber;
|
||||
if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */
|
||||
ls->t = ls->lookahead; /* use this one */
|
||||
ls->lookahead.token = TK_EOS; /* and discharge it */
|
||||
}
|
||||
else
|
||||
ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */
|
||||
}
|
||||
|
||||
|
||||
int luaX_lookahead (LexState *ls) {
|
||||
lua_assert(ls->lookahead.token == TK_EOS);
|
||||
ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);
|
||||
return ls->lookahead.token;
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
** $Id: llex.h,v 1.79.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Lexical Analyzer
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef llex_h
|
||||
#define llex_h
|
||||
|
||||
#include "lobject.h"
|
||||
#include "lzio.h"
|
||||
|
||||
|
||||
#define FIRST_RESERVED 257
|
||||
|
||||
|
||||
#if !defined(LUA_ENV)
|
||||
#define LUA_ENV "_ENV"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* WARNING: if you change the order of this enumeration,
|
||||
* grep "ORDER RESERVED"
|
||||
*/
|
||||
enum RESERVED {
|
||||
/* terminal symbols denoted by reserved words */
|
||||
TK_AND = FIRST_RESERVED, TK_BREAK,
|
||||
TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
|
||||
TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
|
||||
TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
|
||||
/* other terminal symbols */
|
||||
TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,
|
||||
TK_SHL, TK_SHR,
|
||||
TK_DBCOLON, TK_EOS,
|
||||
TK_FLT, TK_INT, TK_NAME, TK_STRING
|
||||
};
|
||||
|
||||
/* number of reserved words */
|
||||
#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1))
|
||||
|
||||
|
||||
typedef union {
|
||||
lua_Number r;
|
||||
lua_Integer i;
|
||||
TString *ts;
|
||||
} SemInfo; /* semantics information */
|
||||
|
||||
|
||||
typedef struct Token {
|
||||
int token;
|
||||
SemInfo seminfo;
|
||||
} Token;
|
||||
|
||||
|
||||
/* state of the lexer plus state of the parser when shared by all
|
||||
functions */
|
||||
typedef struct LexState {
|
||||
int current; /* current character (charint) */
|
||||
int linenumber; /* input line counter */
|
||||
int lastline; /* line of last token 'consumed' */
|
||||
Token t; /* current token */
|
||||
Token lookahead; /* look ahead token */
|
||||
struct FuncState *fs; /* current function (parser) */
|
||||
struct lua_State *L;
|
||||
ZIO *z; /* input stream */
|
||||
Mbuffer *buff; /* buffer for tokens */
|
||||
Table *h; /* to avoid collection/reuse strings */
|
||||
struct Dyndata *dyd; /* dynamic structures used by the parser */
|
||||
TString *source; /* current source name */
|
||||
TString *envn; /* environment variable name */
|
||||
} LexState;
|
||||
|
||||
|
||||
LUAI_FUNC void luaX_init (lua_State *L);
|
||||
LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z,
|
||||
TString *source, int firstchar);
|
||||
LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l);
|
||||
LUAI_FUNC void luaX_next (LexState *ls);
|
||||
LUAI_FUNC int luaX_lookahead (LexState *ls);
|
||||
LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s);
|
||||
LUAI_FUNC const char *luaX_token2str (LexState *ls, int token);
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,323 @@
|
|||
/*
|
||||
** $Id: llimits.h,v 1.141.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Limits, basic types, and some other 'installation-dependent' definitions
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef llimits_h
|
||||
#define llimits_h
|
||||
|
||||
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
/*
|
||||
** 'lu_mem' and 'l_mem' are unsigned/signed integers big enough to count
|
||||
** the total memory used by Lua (in bytes). Usually, 'size_t' and
|
||||
** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines.
|
||||
*/
|
||||
#if defined(LUAI_MEM) /* { external definitions? */
|
||||
typedef LUAI_UMEM lu_mem;
|
||||
typedef LUAI_MEM l_mem;
|
||||
#elif LUAI_BITSINT >= 32 /* }{ */
|
||||
typedef size_t lu_mem;
|
||||
typedef ptrdiff_t l_mem;
|
||||
#else /* 16-bit ints */ /* }{ */
|
||||
typedef unsigned long lu_mem;
|
||||
typedef long l_mem;
|
||||
#endif /* } */
|
||||
|
||||
|
||||
/* chars used as small naturals (so that 'char' is reserved for characters) */
|
||||
typedef unsigned char lu_byte;
|
||||
|
||||
|
||||
/* maximum value for size_t */
|
||||
#define MAX_SIZET ((size_t)(~(size_t)0))
|
||||
|
||||
/* maximum size visible for Lua (must be representable in a lua_Integer */
|
||||
#define MAX_SIZE (sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \
|
||||
: (size_t)(LUA_MAXINTEGER))
|
||||
|
||||
|
||||
#define MAX_LUMEM ((lu_mem)(~(lu_mem)0))
|
||||
|
||||
#define MAX_LMEM ((l_mem)(MAX_LUMEM >> 1))
|
||||
|
||||
|
||||
#define MAX_INT INT_MAX /* maximum value of an int */
|
||||
|
||||
|
||||
/*
|
||||
** conversion of pointer to unsigned integer:
|
||||
** this is for hashing only; there is no problem if the integer
|
||||
** cannot hold the whole pointer value
|
||||
*/
|
||||
#define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX))
|
||||
|
||||
|
||||
|
||||
/* type to ensure maximum alignment */
|
||||
#if defined(LUAI_USER_ALIGNMENT_T)
|
||||
typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;
|
||||
#else
|
||||
typedef union {
|
||||
lua_Number n;
|
||||
double u;
|
||||
void *s;
|
||||
lua_Integer i;
|
||||
long l;
|
||||
} L_Umaxalign;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* types of 'usual argument conversions' for lua_Number and lua_Integer */
|
||||
typedef LUAI_UACNUMBER l_uacNumber;
|
||||
typedef LUAI_UACINT l_uacInt;
|
||||
|
||||
|
||||
/* internal assertions for in-house debugging */
|
||||
#if defined(lua_assert)
|
||||
#define check_exp(c,e) (lua_assert(c), (e))
|
||||
/* to avoid problems with conditions too long */
|
||||
#define lua_longassert(c) ((c) ? (void)0 : lua_assert(0))
|
||||
#else
|
||||
#define lua_assert(c) ((void)0)
|
||||
#define check_exp(c,e) (e)
|
||||
#define lua_longassert(c) ((void)0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** assertion for checking API calls
|
||||
*/
|
||||
#if !defined(luai_apicheck)
|
||||
#define luai_apicheck(l,e) lua_assert(e)
|
||||
#endif
|
||||
|
||||
#define api_check(l,e,msg) luai_apicheck(l,(e) && msg)
|
||||
|
||||
|
||||
/* macro to avoid warnings about unused variables */
|
||||
#if !defined(UNUSED)
|
||||
#define UNUSED(x) ((void)(x))
|
||||
#endif
|
||||
|
||||
|
||||
/* type casts (a macro highlights casts in the code) */
|
||||
#define cast(t, exp) ((t)(exp))
|
||||
|
||||
#define cast_void(i) cast(void, (i))
|
||||
#define cast_byte(i) cast(lu_byte, (i))
|
||||
#define cast_num(i) cast(lua_Number, (i))
|
||||
#define cast_int(i) cast(int, (i))
|
||||
#define cast_uchar(i) cast(unsigned char, (i))
|
||||
|
||||
|
||||
/* cast a signed lua_Integer to lua_Unsigned */
|
||||
#if !defined(l_castS2U)
|
||||
#define l_castS2U(i) ((lua_Unsigned)(i))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** cast a lua_Unsigned to a signed lua_Integer; this cast is
|
||||
** not strict ISO C, but two-complement architectures should
|
||||
** work fine.
|
||||
*/
|
||||
#if !defined(l_castU2S)
|
||||
#define l_castU2S(i) ((lua_Integer)(i))
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** non-return type
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
#define l_noret void __attribute__((noreturn))
|
||||
#elif defined(_MSC_VER) && _MSC_VER >= 1200
|
||||
#define l_noret void __declspec(noreturn)
|
||||
#else
|
||||
#define l_noret void
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** maximum depth for nested C calls and syntactical nested non-terminals
|
||||
** in a program. (Value must fit in an unsigned short int.)
|
||||
*/
|
||||
#if !defined(LUAI_MAXCCALLS)
|
||||
#define LUAI_MAXCCALLS 200
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** type for virtual-machine instructions;
|
||||
** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
|
||||
*/
|
||||
#if LUAI_BITSINT >= 32
|
||||
typedef unsigned int Instruction;
|
||||
#else
|
||||
typedef unsigned long Instruction;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Maximum length for short strings, that is, strings that are
|
||||
** internalized. (Cannot be smaller than reserved words or tags for
|
||||
** metamethods, as these strings must be internalized;
|
||||
** #("function") = 8, #("__newindex") = 10.)
|
||||
*/
|
||||
#if !defined(LUAI_MAXSHORTLEN)
|
||||
#define LUAI_MAXSHORTLEN 40
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Initial size for the string table (must be power of 2).
|
||||
** The Lua core alone registers ~50 strings (reserved words +
|
||||
** metaevent keys + a few others). Libraries would typically add
|
||||
** a few dozens more.
|
||||
*/
|
||||
#if !defined(MINSTRTABSIZE)
|
||||
#define MINSTRTABSIZE 128
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Size of cache for strings in the API. 'N' is the number of
|
||||
** sets (better be a prime) and "M" is the size of each set (M == 1
|
||||
** makes a direct cache.)
|
||||
*/
|
||||
#if !defined(STRCACHE_N)
|
||||
#define STRCACHE_N 53
|
||||
#define STRCACHE_M 2
|
||||
#endif
|
||||
|
||||
|
||||
/* minimum size for string buffer */
|
||||
#if !defined(LUA_MINBUFFER)
|
||||
#define LUA_MINBUFFER 32
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** macros that are executed whenever program enters the Lua core
|
||||
** ('lua_lock') and leaves the core ('lua_unlock')
|
||||
*/
|
||||
#if !defined(lua_lock)
|
||||
#define lua_lock(L) ((void) 0)
|
||||
#define lua_unlock(L) ((void) 0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** macro executed during Lua functions at points where the
|
||||
** function can yield.
|
||||
*/
|
||||
#if !defined(luai_threadyield)
|
||||
#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** these macros allow user-specific actions on threads when you defined
|
||||
** LUAI_EXTRASPACE and need to do something extra when a thread is
|
||||
** created/deleted/resumed/yielded.
|
||||
*/
|
||||
#if !defined(luai_userstateopen)
|
||||
#define luai_userstateopen(L) ((void)L)
|
||||
#endif
|
||||
|
||||
#if !defined(luai_userstateclose)
|
||||
#define luai_userstateclose(L) ((void)L)
|
||||
#endif
|
||||
|
||||
#if !defined(luai_userstatethread)
|
||||
#define luai_userstatethread(L,L1) ((void)L)
|
||||
#endif
|
||||
|
||||
#if !defined(luai_userstatefree)
|
||||
#define luai_userstatefree(L,L1) ((void)L)
|
||||
#endif
|
||||
|
||||
#if !defined(luai_userstateresume)
|
||||
#define luai_userstateresume(L,n) ((void)L)
|
||||
#endif
|
||||
|
||||
#if !defined(luai_userstateyield)
|
||||
#define luai_userstateyield(L,n) ((void)L)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** The luai_num* macros define the primitive operations over numbers.
|
||||
*/
|
||||
|
||||
/* floor division (defined as 'floor(a/b)') */
|
||||
#if !defined(luai_numidiv)
|
||||
#define luai_numidiv(L,a,b) ((void)L, l_floor(luai_numdiv(L,a,b)))
|
||||
#endif
|
||||
|
||||
/* float division */
|
||||
#if !defined(luai_numdiv)
|
||||
#define luai_numdiv(L,a,b) ((a)/(b))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** modulo: defined as 'a - floor(a/b)*b'; this definition gives NaN when
|
||||
** 'b' is huge, but the result should be 'a'. 'fmod' gives the result of
|
||||
** 'a - trunc(a/b)*b', and therefore must be corrected when 'trunc(a/b)
|
||||
** ~= floor(a/b)'. That happens when the division has a non-integer
|
||||
** negative result, which is equivalent to the test below.
|
||||
*/
|
||||
#if !defined(luai_nummod)
|
||||
#define luai_nummod(L,a,b,m) \
|
||||
{ (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); }
|
||||
#endif
|
||||
|
||||
/* exponentiation */
|
||||
#if !defined(luai_numpow)
|
||||
#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b))
|
||||
#endif
|
||||
|
||||
/* the others are quite standard operations */
|
||||
#if !defined(luai_numadd)
|
||||
#define luai_numadd(L,a,b) ((a)+(b))
|
||||
#define luai_numsub(L,a,b) ((a)-(b))
|
||||
#define luai_nummul(L,a,b) ((a)*(b))
|
||||
#define luai_numunm(L,a) (-(a))
|
||||
#define luai_numeq(a,b) ((a)==(b))
|
||||
#define luai_numlt(a,b) ((a)<(b))
|
||||
#define luai_numle(a,b) ((a)<=(b))
|
||||
#define luai_numisnan(a) (!luai_numeq((a), (a)))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** macro to control inclusion of some hard tests on stack reallocation
|
||||
*/
|
||||
#if !defined(HARDSTACKTESTS)
|
||||
#define condmovestack(L,pre,pos) ((void)0)
|
||||
#else
|
||||
/* realloc stack keeping its size */
|
||||
#define condmovestack(L,pre,pos) \
|
||||
{ int sz_ = (L)->stacksize; pre; luaD_reallocstack((L), sz_); pos; }
|
||||
#endif
|
||||
|
||||
#if !defined(HARDMEMTESTS)
|
||||
#define condchangemem(L,pre,pos) ((void)0)
|
||||
#else
|
||||
#define condchangemem(L,pre,pos) \
|
||||
{ if (G(L)->gcrunning) { pre; luaC_fullgc(L, 0); pos; } }
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,410 @@
|
|||
/*
|
||||
** $Id: lmathlib.c,v 1.119.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Standard mathematical library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define lmathlib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
|
||||
#undef PI
|
||||
#define PI (l_mathop(3.141592653589793238462643383279502884))
|
||||
|
||||
|
||||
#if !defined(l_rand) /* { */
|
||||
#if defined(LUA_USE_POSIX)
|
||||
#define l_rand() random()
|
||||
#define l_srand(x) srandom(x)
|
||||
#define L_RANDMAX 2147483647 /* (2^31 - 1), following POSIX */
|
||||
#else
|
||||
#define l_rand() rand()
|
||||
#define l_srand(x) srand(x)
|
||||
#define L_RANDMAX RAND_MAX
|
||||
#endif
|
||||
#endif /* } */
|
||||
|
||||
|
||||
static int math_abs (lua_State *L) {
|
||||
if (lua_isinteger(L, 1)) {
|
||||
lua_Integer n = lua_tointeger(L, 1);
|
||||
if (n < 0) n = (lua_Integer)(0u - (lua_Unsigned)n);
|
||||
lua_pushinteger(L, n);
|
||||
}
|
||||
else
|
||||
lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_sin (lua_State *L) {
|
||||
lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_cos (lua_State *L) {
|
||||
lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_tan (lua_State *L) {
|
||||
lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_asin (lua_State *L) {
|
||||
lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_acos (lua_State *L) {
|
||||
lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_atan (lua_State *L) {
|
||||
lua_Number y = luaL_checknumber(L, 1);
|
||||
lua_Number x = luaL_optnumber(L, 2, 1);
|
||||
lua_pushnumber(L, l_mathop(atan2)(y, x));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int math_toint (lua_State *L) {
|
||||
int valid;
|
||||
lua_Integer n = lua_tointegerx(L, 1, &valid);
|
||||
if (valid)
|
||||
lua_pushinteger(L, n);
|
||||
else {
|
||||
luaL_checkany(L, 1);
|
||||
lua_pushnil(L); /* value is not convertible to integer */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void pushnumint (lua_State *L, lua_Number d) {
|
||||
lua_Integer n;
|
||||
if (lua_numbertointeger(d, &n)) /* does 'd' fit in an integer? */
|
||||
lua_pushinteger(L, n); /* result is integer */
|
||||
else
|
||||
lua_pushnumber(L, d); /* result is float */
|
||||
}
|
||||
|
||||
|
||||
static int math_floor (lua_State *L) {
|
||||
if (lua_isinteger(L, 1))
|
||||
lua_settop(L, 1); /* integer is its own floor */
|
||||
else {
|
||||
lua_Number d = l_mathop(floor)(luaL_checknumber(L, 1));
|
||||
pushnumint(L, d);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int math_ceil (lua_State *L) {
|
||||
if (lua_isinteger(L, 1))
|
||||
lua_settop(L, 1); /* integer is its own ceil */
|
||||
else {
|
||||
lua_Number d = l_mathop(ceil)(luaL_checknumber(L, 1));
|
||||
pushnumint(L, d);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int math_fmod (lua_State *L) {
|
||||
if (lua_isinteger(L, 1) && lua_isinteger(L, 2)) {
|
||||
lua_Integer d = lua_tointeger(L, 2);
|
||||
if ((lua_Unsigned)d + 1u <= 1u) { /* special cases: -1 or 0 */
|
||||
luaL_argcheck(L, d != 0, 2, "zero");
|
||||
lua_pushinteger(L, 0); /* avoid overflow with 0x80000... / -1 */
|
||||
}
|
||||
else
|
||||
lua_pushinteger(L, lua_tointeger(L, 1) % d);
|
||||
}
|
||||
else
|
||||
lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1),
|
||||
luaL_checknumber(L, 2)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** next function does not use 'modf', avoiding problems with 'double*'
|
||||
** (which is not compatible with 'float*') when lua_Number is not
|
||||
** 'double'.
|
||||
*/
|
||||
static int math_modf (lua_State *L) {
|
||||
if (lua_isinteger(L ,1)) {
|
||||
lua_settop(L, 1); /* number is its own integer part */
|
||||
lua_pushnumber(L, 0); /* no fractional part */
|
||||
}
|
||||
else {
|
||||
lua_Number n = luaL_checknumber(L, 1);
|
||||
/* integer part (rounds toward zero) */
|
||||
lua_Number ip = (n < 0) ? l_mathop(ceil)(n) : l_mathop(floor)(n);
|
||||
pushnumint(L, ip);
|
||||
/* fractional part (test needed for inf/-inf) */
|
||||
lua_pushnumber(L, (n == ip) ? l_mathop(0.0) : (n - ip));
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
static int math_sqrt (lua_State *L) {
|
||||
lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int math_ult (lua_State *L) {
|
||||
lua_Integer a = luaL_checkinteger(L, 1);
|
||||
lua_Integer b = luaL_checkinteger(L, 2);
|
||||
lua_pushboolean(L, (lua_Unsigned)a < (lua_Unsigned)b);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_log (lua_State *L) {
|
||||
lua_Number x = luaL_checknumber(L, 1);
|
||||
lua_Number res;
|
||||
if (lua_isnoneornil(L, 2))
|
||||
res = l_mathop(log)(x);
|
||||
else {
|
||||
lua_Number base = luaL_checknumber(L, 2);
|
||||
#if !defined(LUA_USE_C89)
|
||||
if (base == l_mathop(2.0))
|
||||
res = l_mathop(log2)(x); else
|
||||
#endif
|
||||
if (base == l_mathop(10.0))
|
||||
res = l_mathop(log10)(x);
|
||||
else
|
||||
res = l_mathop(log)(x)/l_mathop(log)(base);
|
||||
}
|
||||
lua_pushnumber(L, res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_exp (lua_State *L) {
|
||||
lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_deg (lua_State *L) {
|
||||
lua_pushnumber(L, luaL_checknumber(L, 1) * (l_mathop(180.0) / PI));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_rad (lua_State *L) {
|
||||
lua_pushnumber(L, luaL_checknumber(L, 1) * (PI / l_mathop(180.0)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int math_min (lua_State *L) {
|
||||
int n = lua_gettop(L); /* number of arguments */
|
||||
int imin = 1; /* index of current minimum value */
|
||||
int i;
|
||||
luaL_argcheck(L, n >= 1, 1, "value expected");
|
||||
for (i = 2; i <= n; i++) {
|
||||
if (lua_compare(L, i, imin, LUA_OPLT))
|
||||
imin = i;
|
||||
}
|
||||
lua_pushvalue(L, imin);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int math_max (lua_State *L) {
|
||||
int n = lua_gettop(L); /* number of arguments */
|
||||
int imax = 1; /* index of current maximum value */
|
||||
int i;
|
||||
luaL_argcheck(L, n >= 1, 1, "value expected");
|
||||
for (i = 2; i <= n; i++) {
|
||||
if (lua_compare(L, imax, i, LUA_OPLT))
|
||||
imax = i;
|
||||
}
|
||||
lua_pushvalue(L, imax);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function uses 'double' (instead of 'lua_Number') to ensure that
|
||||
** all bits from 'l_rand' can be represented, and that 'RANDMAX + 1.0'
|
||||
** will keep full precision (ensuring that 'r' is always less than 1.0.)
|
||||
*/
|
||||
static int math_random (lua_State *L) {
|
||||
lua_Integer low, up;
|
||||
double r = (double)l_rand() * (1.0 / ((double)L_RANDMAX + 1.0));
|
||||
switch (lua_gettop(L)) { /* check number of arguments */
|
||||
case 0: { /* no arguments */
|
||||
lua_pushnumber(L, (lua_Number)r); /* Number between 0 and 1 */
|
||||
return 1;
|
||||
}
|
||||
case 1: { /* only upper limit */
|
||||
low = 1;
|
||||
up = luaL_checkinteger(L, 1);
|
||||
break;
|
||||
}
|
||||
case 2: { /* lower and upper limits */
|
||||
low = luaL_checkinteger(L, 1);
|
||||
up = luaL_checkinteger(L, 2);
|
||||
break;
|
||||
}
|
||||
default: return luaL_error(L, "wrong number of arguments");
|
||||
}
|
||||
/* random integer in the interval [low, up] */
|
||||
luaL_argcheck(L, low <= up, 1, "interval is empty");
|
||||
luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1,
|
||||
"interval too large");
|
||||
r *= (double)(up - low) + 1.0;
|
||||
lua_pushinteger(L, (lua_Integer)r + low);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int math_randomseed (lua_State *L) {
|
||||
l_srand((unsigned int)(lua_Integer)luaL_checknumber(L, 1));
|
||||
(void)l_rand(); /* discard first value to avoid undesirable correlations */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int math_type (lua_State *L) {
|
||||
if (lua_type(L, 1) == LUA_TNUMBER) {
|
||||
if (lua_isinteger(L, 1))
|
||||
lua_pushliteral(L, "integer");
|
||||
else
|
||||
lua_pushliteral(L, "float");
|
||||
}
|
||||
else {
|
||||
luaL_checkany(L, 1);
|
||||
lua_pushnil(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** {==================================================================
|
||||
** Deprecated functions (for compatibility only)
|
||||
** ===================================================================
|
||||
*/
|
||||
#if defined(LUA_COMPAT_MATHLIB)
|
||||
|
||||
static int math_cosh (lua_State *L) {
|
||||
lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_sinh (lua_State *L) {
|
||||
lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_tanh (lua_State *L) {
|
||||
lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_pow (lua_State *L) {
|
||||
lua_Number x = luaL_checknumber(L, 1);
|
||||
lua_Number y = luaL_checknumber(L, 2);
|
||||
lua_pushnumber(L, l_mathop(pow)(x, y));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_frexp (lua_State *L) {
|
||||
int e;
|
||||
lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e));
|
||||
lua_pushinteger(L, e);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int math_ldexp (lua_State *L) {
|
||||
lua_Number x = luaL_checknumber(L, 1);
|
||||
int ep = (int)luaL_checkinteger(L, 2);
|
||||
lua_pushnumber(L, l_mathop(ldexp)(x, ep));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int math_log10 (lua_State *L) {
|
||||
lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* }================================================================== */
|
||||
|
||||
|
||||
|
||||
static const luaL_Reg mathlib[] = {
|
||||
{"abs", math_abs},
|
||||
{"acos", math_acos},
|
||||
{"asin", math_asin},
|
||||
{"atan", math_atan},
|
||||
{"ceil", math_ceil},
|
||||
{"cos", math_cos},
|
||||
{"deg", math_deg},
|
||||
{"exp", math_exp},
|
||||
{"tointeger", math_toint},
|
||||
{"floor", math_floor},
|
||||
{"fmod", math_fmod},
|
||||
{"ult", math_ult},
|
||||
{"log", math_log},
|
||||
{"max", math_max},
|
||||
{"min", math_min},
|
||||
{"modf", math_modf},
|
||||
{"rad", math_rad},
|
||||
{"random", math_random},
|
||||
{"randomseed", math_randomseed},
|
||||
{"sin", math_sin},
|
||||
{"sqrt", math_sqrt},
|
||||
{"tan", math_tan},
|
||||
{"type", math_type},
|
||||
#if defined(LUA_COMPAT_MATHLIB)
|
||||
{"atan2", math_atan},
|
||||
{"cosh", math_cosh},
|
||||
{"sinh", math_sinh},
|
||||
{"tanh", math_tanh},
|
||||
{"pow", math_pow},
|
||||
{"frexp", math_frexp},
|
||||
{"ldexp", math_ldexp},
|
||||
{"log10", math_log10},
|
||||
#endif
|
||||
/* placeholders */
|
||||
{"pi", NULL},
|
||||
{"huge", NULL},
|
||||
{"maxinteger", NULL},
|
||||
{"mininteger", NULL},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Open math library
|
||||
*/
|
||||
LUAMOD_API int luaopen_math (lua_State *L) {
|
||||
luaL_newlib(L, mathlib);
|
||||
lua_pushnumber(L, PI);
|
||||
lua_setfield(L, -2, "pi");
|
||||
lua_pushnumber(L, (lua_Number)HUGE_VAL);
|
||||
lua_setfield(L, -2, "huge");
|
||||
lua_pushinteger(L, LUA_MAXINTEGER);
|
||||
lua_setfield(L, -2, "maxinteger");
|
||||
lua_pushinteger(L, LUA_MININTEGER);
|
||||
lua_setfield(L, -2, "mininteger");
|
||||
return 1;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue