Compare commits
888 Commits
crypto_mod
...
master
Author | SHA1 | Date |
---|---|---|
Rafal Kupiec | 5e6ed0f668 | |
Rafal Kupiec | c940224d21 | |
Rafal Kupiec | 3eb82e632b | |
Rafal Kupiec | 709b5971c6 | |
Rafal Kupiec | c730082fa0 | |
Rafal Kupiec | 0bf2f6d94f | |
Rafal Kupiec | b527840f10 | |
Rafal Kupiec | ab36234ff3 | |
Rafal Kupiec | 9d762a2350 | |
Rafal Kupiec | 0b5e94bacc | |
Rafal Kupiec | e623111f41 | |
Rafal Kupiec | fd0685f16e | |
Rafal Kupiec | ad5784f81f | |
Rafal Kupiec | 0e757111a3 | |
Rafal Kupiec | 469e5ba059 | |
Rafal Kupiec | 9290db2504 | |
Rafal Kupiec | 09e7400349 | |
Rafal Kupiec | cb91a4bbf4 | |
Rafal Kupiec | f3156bcbd5 | |
Rafal Kupiec | cb71daec12 | |
Rafal Kupiec | 63fd76c9c8 | |
Rafal Kupiec | e1e6a19f30 | |
Rafal Kupiec | d3479a6e80 | |
Rafal Kupiec | a24e44fbf3 | |
Rafal Kupiec | f3972a9ca2 | |
Rafal Kupiec | f323e3cb57 | |
Rafal Kupiec | 426ec932ec | |
Rafal Kupiec | 3aa31a9dfa | |
Rafal Kupiec | f0aba06f4f | |
Rafal Kupiec | 18b96064e4 | |
Rafal Kupiec | 91887c0185 | |
Rafal Kupiec | 3b9d91f186 | |
Rafal Kupiec | 0fb44bb1ae | |
Piotr Likoski | d2335c86b2 | |
Piotr Likoski | 843c2d67d9 | |
Piotr Likoski | 33b0f20573 | |
David Carlier | d96dcdf1e0 | |
Rafal Kupiec | a09c6b3fad | |
Rafal Kupiec | 4d150c2fe3 | |
Rafal Kupiec | c94de60c29 | |
Rafal Kupiec | 376b9510a9 | |
Rafal Kupiec | ad49b81b33 | |
Rafal Kupiec | 4afcbc0815 | |
Rafal Kupiec | 171456beb4 | |
Rafal Kupiec | 204060fa9d | |
Rafal Kupiec | 616b2eeae3 | |
Rafal Kupiec | 563c10bd20 | |
Rafal Kupiec | 2e695a9d35 | |
Rafal Kupiec | 2ef2b6265c | |
Rafal Kupiec | a6d89da16b | |
Rafal Kupiec | 48d5088265 | |
Rafal Kupiec | 3dcc908788 | |
Rafal Kupiec | 4881ddf6de | |
Rafal Kupiec | 312fb97db6 | |
Rafal Kupiec | 0a2f1133d5 | |
Rafal Kupiec | 647454b98d | |
Rafal Kupiec | 72782b147a | |
Rafal Kupiec | edb62ed692 | |
Rafal Kupiec | 8b2086402e | |
Rafal Kupiec | 8ee2dece06 | |
Rafal Kupiec | dcf37af75e | |
Rafal Kupiec | 6d964d6113 | |
Rafal Kupiec | 3045bd2d88 | |
Rafal Kupiec | 19d0628afc | |
Rafal Kupiec | 59811ac742 | |
Rafal Kupiec | e40dc34026 | |
Rafal Kupiec | c76ae15a7b | |
Rafal Kupiec | a1f1d50d25 | |
Rafal Kupiec | ca51e2a5da | |
Rafal Kupiec | bd24aa0605 | |
Rafal Kupiec | 690213e0c7 | |
Rafal Kupiec | 0be38392bd | |
Rafal Kupiec | bffd44a7b4 | |
Rafal Kupiec | 173bac16ad | |
Rafal Kupiec | b3eb2d0139 | |
Rafal Kupiec | 050a637e88 | |
Rafal Kupiec | 8d0c128d22 | |
Rafal Kupiec | c7b6e76d0d | |
Rafal Kupiec | 1a91fedb1f | |
Rafal Kupiec | fffce10ba8 | |
Rafal Kupiec | ace4d56d7f | |
Rafal Kupiec | 8985044054 | |
Rafal Kupiec | 77150e9d26 | |
Rafal Kupiec | aff19a98da | |
Rafal Kupiec | 010bdd7331 | |
Rafal Kupiec | 0bef248298 | |
Rafal Kupiec | d09a33da55 | |
Rafal Kupiec | 673796d878 | |
Rafal Kupiec | ea948216ff | |
Rafal Kupiec | 4723128b74 | |
Rafal Kupiec | da2e74ba08 | |
Rafal Kupiec | 0ef6b449c6 | |
Rafal Kupiec | 815b1481fc | |
Rafal Kupiec | 5c824ec67d | |
Rafal Kupiec | 9aa192db69 | |
Rafal Kupiec | fdba2c0a5c | |
Rafal Kupiec | 6c277c1eca | |
Rafal Kupiec | 0327c3130f | |
Rafal Kupiec | 78c416c6b8 | |
Rafal Kupiec | cbe4f29909 | |
Rafal Kupiec | a00d30afa2 | |
Rafal Kupiec | 65aaf7be67 | |
Rafal Kupiec | 43a1f135cc | |
Rafal Kupiec | 343c25ca77 | |
Rafal Kupiec | 46458d1e1b | |
Rafal Kupiec | 543191c1b2 | |
Rafal Kupiec | 6c449dbdbf | |
Rafal Kupiec | fa5c2e1f5e | |
Rafal Kupiec | dbd39be5ed | |
Rafal Kupiec | a5af1d473f | |
Rafal Kupiec | ce851b5df5 | |
Rafal Kupiec | b15d0d33fd | |
Rafal Kupiec | 734710ae78 | |
Rafal Kupiec | d0995a4239 | |
Rafal Kupiec | 24c75975e3 | |
Rafal Kupiec | 9cc0f203ca | |
Rafal Kupiec | 5948c3a5b6 | |
Rafal Kupiec | 075f707a0a | |
Rafal Kupiec | 3715b1b53d | |
Rafal Kupiec | 4267bb2f26 | |
Rafal Kupiec | 384b057c93 | |
Rafal Kupiec | 101453950e | |
Rafal Kupiec | ba43269b80 | |
Rafal Kupiec | bb20f04f3c | |
Rafal Kupiec | c3184eb3ea | |
Rafal Kupiec | 84b5fd2717 | |
Rafal Kupiec | 045ebe92ae | |
Rafal Kupiec | 9fe4aa653f | |
Rafal Kupiec | b5cdbf4721 | |
Rafal Kupiec | d57d6caf2d | |
Rafal Kupiec | d0840d7eea | |
Rafal Kupiec | 625a386b69 | |
Rafal Kupiec | 3184b95a09 | |
Rafal Kupiec | 5f90f3e8e1 | |
Rafal Kupiec | 3689a0239a | |
Rafal Kupiec | 1f7e14fd7a | |
Rafal Kupiec | 519f5050b7 | |
Rafal Kupiec | cd9ff68ae9 | |
Rafal Kupiec | 984429bc55 | |
Rafal Kupiec | 53199cac4e | |
Rafal Kupiec | feba01eb49 | |
Rafal Kupiec | b1b78433dd | |
Rafal Kupiec | fd278b1f47 | |
Rafal Kupiec | a3a2c8b619 | |
Rafal Kupiec | ba1c840009 | |
Rafal Kupiec | 3530e6ea09 | |
Rafal Kupiec | 1bf5c3a8a2 | |
Rafal Kupiec | c206011c95 | |
Rafal Kupiec | 8847d645c0 | |
Rafal Kupiec | 1c0ba22c48 | |
Rafal Kupiec | 7732a239ff | |
Rafal Kupiec | 5e166492d5 | |
Rafal Kupiec | a5fb8ff8be | |
Rafal Kupiec | d924d41a7a | |
Rafal Kupiec | a6f7c6d847 | |
Rafal Kupiec | 02471b4ccb | |
Rafal Kupiec | 28e18bcb4b | |
Rafal Kupiec | 2d50a64cac | |
Rafal Kupiec | 4d1c246a65 | |
Rafal Kupiec | 1f5afc9d51 | |
Rafal Kupiec | 675f3596a1 | |
Rafal Kupiec | 26333360b0 | |
Rafal Kupiec | 1175219ad4 | |
Rafal Kupiec | b319e11c09 | |
Rafal Kupiec | 5c176207e1 | |
Rafal Kupiec | 5cc4a5e48d | |
Rafal Kupiec | e654e42b07 | |
Rafal Kupiec | 5b2f300fe4 | |
Rafal Kupiec | d8db20e9bd | |
Rafal Kupiec | 1f78547ca2 | |
Rafal Kupiec | ddd46a4e80 | |
Rafal Kupiec | 3cca5faa76 | |
Rafal Kupiec | 0f4a666b89 | |
Rafal Kupiec | 9fd61a207b | |
Rafal Kupiec | 1acbd21caf | |
Rafal Kupiec | a25b163af6 | |
Rafal Kupiec | 77c57674e8 | |
Rafal Kupiec | 4cc7940216 | |
Rafal Kupiec | 55acf8111f | |
Rafal Kupiec | 48ccd7fef0 | |
Rafal Kupiec | e8c675bd8e | |
Rafal Kupiec | 7203492763 | |
Rafal Kupiec | 8aed5af238 | |
Rafal Kupiec | f2116a6461 | |
Rafal Kupiec | 5d9b73ba4e | |
Rafal Kupiec | 3cc347f25f | |
Rafal Kupiec | 27e3b85b30 | |
Rafal Kupiec | 5256dda922 | |
Rafal Kupiec | ea5499f8b3 | |
Rafal Kupiec | 5e7d5957e2 | |
Rafal Kupiec | d3d3dff673 | |
Rafal Kupiec | c4416ef631 | |
Rafal Kupiec | 76880ae4e2 | |
Rafal Kupiec | a2fb0b9ae5 | |
Rafal Kupiec | 07bd3ceec3 | |
Rafal Kupiec | 0c8ca53f70 | |
Rafal Kupiec | 03c37c58bb | |
Rafal Kupiec | 17e0fb4653 | |
Rafal Kupiec | d3ae1c1bf4 | |
Rafal Kupiec | cedc288f67 | |
Rafal Kupiec | 0a6b5a6f42 | |
Rafal Kupiec | 7b6245572f | |
Rafal Kupiec | 9d84c558c4 | |
Rafal Kupiec | c4b63a3018 | |
Rafal Kupiec | 23900f2aed | |
Rafal Kupiec | b36510943d | |
Rafal Kupiec | ab8bf48485 | |
Rafal Kupiec | 90b2da7c56 | |
Rafal Kupiec | e6b7f1be2c | |
Rafal Kupiec | 03fc167be1 | |
Rafal Kupiec | 2f3ce65289 | |
Rafal Kupiec | 73c1a814f5 | |
Rafal Kupiec | 8f681d1605 | |
Rafal Kupiec | 5a0e4667fa | |
Rafal Kupiec | 508e8965a9 | |
Rafal Kupiec | 7d606cbf1d | |
Rafal Kupiec | 3dfa4232ba | |
Rafal Kupiec | 7c37451520 | |
Rafal Kupiec | 1829eff323 | |
Rafal Kupiec | 798fd7d3b2 | |
Rafal Kupiec | 70676cb0d5 | |
Rafal Kupiec | d76441ad4c | |
Rafal Kupiec | 186e5887f6 | |
Rafal Kupiec | bbcd99789d | |
Rafal Kupiec | 1d6822c1e2 | |
Rafal Kupiec | a726ab795a | |
Rafal Kupiec | 5c1e0f0cce | |
Rafal Kupiec | 4d8d92092e | |
Rafal Kupiec | 1156519af6 | |
Rafal Kupiec | 62c315da9e | |
Rafal Kupiec | 10516fb655 | |
Rafal Kupiec | f09d4def2d | |
Rafal Kupiec | d6fca929ea | |
Rafal Kupiec | 6593252bce | |
Rafal Kupiec | d26bc99b68 | |
Rafal Kupiec | 00c502c11b | |
Rafal Kupiec | 9f4f6298c2 | |
Rafal Kupiec | 2bda002259 | |
Rafal Kupiec | eef5ee370d | |
Rafal Kupiec | 8ab3919688 | |
Rafal Kupiec | 58015f2a20 | |
Rafal Kupiec | d72774f0f4 | |
Rafal Kupiec | 407fb09e8f | |
Rafal Kupiec | a7606864fa | |
Rafal Kupiec | cb455c3c73 | |
Rafal Kupiec | 1c5982e764 | |
Rafal Kupiec | 3be46532dd | |
Rafal Kupiec | c443a38fec | |
Rafal Kupiec | 48a38dc1af | |
Rafal Kupiec | 7c8259057b | |
Rafal Kupiec | 9b1ad67580 | |
Rafal Kupiec | deda6b4b15 | |
Rafal Kupiec | 5b0b965199 | |
Rafal Kupiec | 555234e381 | |
Rafal Kupiec | aa64a5eeb2 | |
Rafal Kupiec | 8f18ebf884 | |
Rafal Kupiec | c9203b6c91 | |
Rafal Kupiec | 13ea9825b8 | |
Rafal Kupiec | 8331d36869 | |
Rafal Kupiec | ed8f3f341e | |
Rafal Kupiec | 3f1d429d5f | |
Rafal Kupiec | 18e77b9754 | |
Rafal Kupiec | d819820798 | |
Rafal Kupiec | e794ffd97b | |
Rafal Kupiec | 16c6b8d970 | |
Rafal Kupiec | a0405f2267 | |
Rafal Kupiec | 80abccc3ad | |
Rafal Kupiec | 291b6f0607 | |
Rafal Kupiec | 0e8a2372dd | |
Rafal Kupiec | 929d7b83fe | |
Rafal Kupiec | 0b04e0f7c5 | |
Rafal Kupiec | 407bcf5a29 | |
Rafal Kupiec | f8a47d2838 | |
Rafal Kupiec | 2aa25f66d5 | |
Rafal Kupiec | 58618a4d27 | |
Rafal Kupiec | 9a82298451 | |
Rafal Kupiec | 0268a95169 | |
Rafal Kupiec | 227e1d2be5 | |
Rafal Kupiec | bd22425b46 | |
Rafal Kupiec | 9d97eb228a | |
Rafal Kupiec | b668d0a897 | |
Rafal Kupiec | 102e8447a1 | |
Rafal Kupiec | 5f57ba54a4 | |
Rafal Kupiec | ec580ddf8c | |
Rafal Kupiec | 395f6c446c | |
Rafal Kupiec | 549b2ff3b4 | |
Rafal Kupiec | e5d7977995 | |
Piotr Likoski | 6b18e204cd | |
Rafal Kupiec | a5da714d61 | |
Rafal Kupiec | 88d382b76b | |
Rafal Kupiec | 2894c55dfa | |
Rafal Kupiec | 0b11d59f9f | |
Rafal Kupiec | 07e3a09999 | |
Rafal Kupiec | ba8e9080ef | |
Rafal Kupiec | ef4f994e8b | |
Rafal Kupiec | 5fddbf8737 | |
Rafal Kupiec | 89f19133d5 | |
Rafal Kupiec | eb80dced3e | |
Rafal Kupiec | f9b518138e | |
Rafal Kupiec | 517dffcbc1 | |
Rafal Kupiec | 1b248a17e7 | |
Rafal Kupiec | 661158d249 | |
Rafal Kupiec | 94e06f3d3a | |
Rafal Kupiec | 9e06322b57 | |
Rafal Kupiec | 0f0fc01a96 | |
Rafal Kupiec | c51b3dfa8a | |
Rafal Kupiec | 583f43e1f7 | |
Rafal Kupiec | aea0d1a5ec | |
Rafal Kupiec | e3ad3eb84b | |
Rafal Kupiec | 98898c16c5 | |
Rafal Kupiec | 89d5158d7e | |
Rafal Kupiec | b302e8c2b2 | |
Rafal Kupiec | a8a1a2cd51 | |
Rafal Kupiec | ee0d189f0a | |
Rafal Kupiec | cdc0dade2a | |
Rafal Kupiec | aae526b1d4 | |
Rafal Kupiec | 5cc803d07c | |
Rafal Kupiec | 31f48b234b | |
Rafal Kupiec | 4eaf6a7117 | |
Rafal Kupiec | 9c426b20cc | |
Rafal Kupiec | 725b60cb88 | |
Rafal Kupiec | 0c2b2c9df5 | |
Rafal Kupiec | 493fcd0e92 | |
Rafal Kupiec | 57c6b3483a | |
Rafal Kupiec | ab4705518c | |
Rafal Kupiec | 08307c5ad6 | |
Rafal Kupiec | 2a4e47e782 | |
Rafal Kupiec | 527a6ad689 | |
Rafal Kupiec | 95c9fd0f1f | |
Rafal Kupiec | 46250f0cd8 | |
Rafal Kupiec | ee7b1e56ae | |
Rafal Kupiec | a4b5db4005 | |
Rafal Kupiec | d8f9db8f9a | |
Rafal Kupiec | 65e38a364d | |
Rafal Kupiec | 6b86f4c855 | |
Rafal Kupiec | d6434ba19e | |
Rafal Kupiec | 447910ce2e | |
Rafal Kupiec | f0e50678e3 | |
Rafal Kupiec | 8810a86a2c | |
Rafal Kupiec | b0165e5702 | |
Rafal Kupiec | 77ebce7acf | |
Rafal Kupiec | c1e30d4c68 | |
Rafal Kupiec | ad3c6e6d7e | |
Rafal Kupiec | 77795bea4c | |
Rafal Kupiec | 598dc9ce51 | |
Rafal Kupiec | d74b182235 | |
Rafal Kupiec | b320d35cf7 | |
Rafal Kupiec | c2b3cc1a2f | |
Rafal Kupiec | db0bbf713b | |
Rafal Kupiec | 580d1af308 | |
Rafal Kupiec | 58b63a9f16 | |
Rafal Kupiec | 67f40db553 | |
Rafal Kupiec | 1679420f4c | |
Rafal Kupiec | d34c8ceafb | |
Rafal Kupiec | bda8316e1b | |
Rafal Kupiec | 1fd161e394 | |
Rafal Kupiec | 246b097fad | |
Rafal Kupiec | 7443663dd8 | |
Rafal Kupiec | f6e2b549b6 | |
Rafal Kupiec | 72c420cc85 | |
Rafal Kupiec | a501dea661 | |
Rafal Kupiec | 25001ae746 | |
Rafal Kupiec | 2de455aa01 | |
Rafal Kupiec | 95fba30f9b | |
Rafal Kupiec | a06573408e | |
Rafal Kupiec | 39f698476f | |
Rafal Kupiec | 465336b23b | |
Rafal Kupiec | a1151d598b | |
Rafal Kupiec | 5765ff3fd6 | |
Rafal Kupiec | 3359b99128 | |
Rafal Kupiec | afe978e366 | |
Rafal Kupiec | 4d07a10336 | |
Rafal Kupiec | cfc0342a10 | |
Rafal Kupiec | 62d8451d12 | |
Rafal Kupiec | 5bfa60724a | |
Rafal Kupiec | fcd4e8d6a6 | |
Rafal Kupiec | 72dc44c152 | |
Rafal Kupiec | 74f954b852 | |
Rafal Kupiec | 5d369ba851 | |
Rafal Kupiec | 9880f9963e | |
Rafal Kupiec | c789b875f4 | |
Rafal Kupiec | 1db4fc0515 | |
Rafal Kupiec | dc44ee31b8 | |
Rafal Kupiec | 7ec7ade171 | |
Rafal Kupiec | 01c210984e | |
Rafal Kupiec | 5eeceb6927 | |
Rafal Kupiec | 9acd6fbcb2 | |
Rafal Kupiec | 4467ca6dce | |
Rafal Kupiec | 5463da88b0 | |
Rafal Kupiec | 8d3b7f303f | |
Rafal Kupiec | d4d00db458 | |
Rafal Kupiec | 8133c3dd6f | |
Rafal Kupiec | fb50d8de25 | |
Rafal Kupiec | 66a7e957c9 | |
Rafal Kupiec | aaef03396c | |
Rafal Kupiec | 45b1d4ed73 | |
Rafal Kupiec | 803516cf84 | |
Rafal Kupiec | c6397d2e15 | |
Rafal Kupiec | 2fb123872f | |
Rafal Kupiec | 253fe327ef | |
Rafal Kupiec | 629484fcf6 | |
Rafal Kupiec | 4f6be2234e | |
Rafal Kupiec | 9b741175f2 | |
Rafal Kupiec | 8a87dcbcdc | |
Rafal Kupiec | 3f205c19ce | |
Rafal Kupiec | a7137316f7 | |
Rafal Kupiec | f5960d57b1 | |
Rafal Kupiec | 0f5073f3fb | |
Rafal Kupiec | 41d20eeb28 | |
Rafal Kupiec | f7b779907c | |
Rafal Kupiec | 01f1932230 | |
Rafal Kupiec | 47cca096bc | |
Rafal Kupiec | 140bd35f93 | |
Rafal Kupiec | a013cee2d1 | |
Rafal Kupiec | e4dc9f641e | |
Rafal Kupiec | 66b55e35a9 | |
Rafal Kupiec | 3fc002be18 | |
Rafal Kupiec | 94bd82f251 | |
Rafal Kupiec | 874e416d65 | |
Rafal Kupiec | 46a3bd85b0 | |
Rafal Kupiec | d76e48c885 | |
Rafal Kupiec | 14f958a4b2 | |
Rafal Kupiec | 45f4a00b05 | |
Rafal Kupiec | 9303517b9e | |
Rafal Kupiec | 5e54233ef8 | |
Rafal Kupiec | 04c56c9041 | |
Rafal Kupiec | fbf27a6c4c | |
Rafal Kupiec | 891818d601 | |
Rafal Kupiec | 243faf4373 | |
Rafal Kupiec | accde59f9e | |
Rafal Kupiec | fa295b9437 | |
Rafal Kupiec | a87471e1e3 | |
Rafal Kupiec | 9438407ebf | |
Rafal Kupiec | 731706c1a3 | |
Rafal Kupiec | e39bdae5b8 | |
Rafal Kupiec | 4f29507c0d | |
Rafal Kupiec | e75ed7b9a9 | |
Rafal Kupiec | 0af594f1ed | |
Rafal Kupiec | 3074b4efaf | |
Rafal Kupiec | fc95deffa0 | |
Rafal Kupiec | 76e76983a3 | |
Rafal Kupiec | ea93c8dba4 | |
Rafal Kupiec | ff6c71db1c | |
Rafal Kupiec | 9d7a542aea | |
Rafal Kupiec | 135e7c9698 | |
Rafal Kupiec | 59e2743a60 | |
Rafal Kupiec | 98a5fc1af0 | |
Rafal Kupiec | 154469f475 | |
Rafal Kupiec | 9a41f7195d | |
Rafal Kupiec | e3122c9f89 | |
Rafal Kupiec | 65b178932a | |
Rafal Kupiec | 59e820c768 | |
Rafal Kupiec | 3ebd6d62c4 | |
Rafal Kupiec | 90b5a8797a | |
Rafal Kupiec | 78c6f6a376 | |
Rafal Kupiec | f83d6cc43d | |
Rafal Kupiec | ab09ba6943 | |
Rafal Kupiec | 075d2f0963 | |
Rafal Kupiec | 412a70c0c6 | |
Rafal Kupiec | a0d72d067c | |
Rafal Kupiec | 0115b30d01 | |
Rafal Kupiec | 1460200919 | |
Rafal Kupiec | 24013f4a52 | |
Rafal Kupiec | 166b1a2c41 | |
Rafal Kupiec | 4eba80b2ba | |
Rafal Kupiec | 7b1ed59f41 | |
Rafal Kupiec | 3d23d43040 | |
Rafal Kupiec | b60c1de4cf | |
Rafal Kupiec | 23601fe9c5 | |
Rafal Kupiec | d6751484d0 | |
Rafal Kupiec | d4967da9e4 | |
Rafal Kupiec | c6d95c16d3 | |
Rafal Kupiec | fc3a66315b | |
Rafal Kupiec | 6ca08c9c4a | |
Rafal Kupiec | 55b652c740 | |
Rafal Kupiec | fe898ec7e7 | |
Rafal Kupiec | ff73690111 | |
Rafal Kupiec | c26f8cd777 | |
Rafal Kupiec | 128f4bba01 | |
Rafal Kupiec | 9934489ed9 | |
Rafal Kupiec | f3d10dd4bc | |
Rafal Kupiec | de2b355862 | |
Rafal Kupiec | 615e75fb8a | |
Rafal Kupiec | 7897f28ebb | |
Rafal Kupiec | e498bc7646 | |
Rafal Kupiec | a2749000d6 | |
Rafal Kupiec | f71e60f641 | |
Rafal Kupiec | cc4a9aa063 | |
Rafal Kupiec | c8985032ef | |
Rafal Kupiec | 3e4064f55a | |
Rafal Kupiec | ac16d5ce57 | |
Rafal Kupiec | df3d00d02c | |
Rafal Kupiec | 051bca470e | |
Rafal Kupiec | f1d4d80f65 | |
Rafal Kupiec | 8aacf7c70e | |
Rafal Kupiec | 0524092539 | |
Rafal Kupiec | d6c5f01905 | |
Rafal Kupiec | e86894f724 | |
Rafal Kupiec | bd4151f426 | |
Rafal Kupiec | a5ee2d75eb | |
Rafal Kupiec | b7e3ad9f46 | |
Rafal Kupiec | 7eba38a633 | |
Rafal Kupiec | 4af3220018 | |
Rafal Kupiec | a7b4c6e880 | |
Rafal Kupiec | fa0b487cc0 | |
Rafal Kupiec | efbe191989 | |
Rafal Kupiec | 5d3acf74d0 | |
Rafal Kupiec | 6927c5c038 | |
Rafal Kupiec | 6a74bf9e8b | |
Rafal Kupiec | ed8dab7870 | |
Rafal Kupiec | ff9e38a480 | |
Rafal Kupiec | bbdc740388 | |
Rafal Kupiec | 4db8ec02cd | |
Rafal Kupiec | f97e2a8294 | |
Rafal Kupiec | 2949c8dcfb | |
Rafal Kupiec | 784c705af6 | |
Rafal Kupiec | 1c3211e00d | |
Rafal Kupiec | 0278f0a630 | |
Rafal Kupiec | d87ce3ad1d | |
Rafal Kupiec | 2572b9321d | |
Rafal Kupiec | 3f9e3b0664 | |
Rafal Kupiec | 9ab896c2e2 | |
Rafal Kupiec | f3f1723104 | |
Rafal Kupiec | 0d3cb90d5f | |
Rafal Kupiec | a5ef118263 | |
Rafal Kupiec | d3e0ffe4bf | |
Rafal Kupiec | 3cc8cfe6a2 | |
Rafal Kupiec | 1cebd3af37 | |
Rafal Kupiec | 5dde778382 | |
Rafal Kupiec | d65a529d21 | |
Rafal Kupiec | 8782b9c25b | |
Rafal Kupiec | 174ecb2a38 | |
Rafal Kupiec | 87db6d6dfd | |
Rafal Kupiec | 5878a171e6 | |
Rafal Kupiec | e727453ccf | |
Rafal Kupiec | 7a34716298 | |
Rafal Kupiec | 8724cebf71 | |
Rafal Kupiec | ec47190874 | |
Rafal Kupiec | e5fb7d625e | |
Rafal Kupiec | 6f13c347d8 | |
Rafal Kupiec | 03cf969c31 | |
Rafal Kupiec | b66515516e | |
Rafal Kupiec | 6293b8f5bf | |
Rafal Kupiec | c00080e190 | |
Rafal Kupiec | b5eb268ce1 | |
Rafal Kupiec | 5f2f9d9c08 | |
Rafal Kupiec | 6e7bc74949 | |
Rafal Kupiec | f26095658d | |
Rafal Kupiec | 2db1954779 | |
Rafal Kupiec | 550107235c | |
Rafal Kupiec | 369cadfcda | |
Rafal Kupiec | f72d6c3922 | |
Rafal Kupiec | 59fda6d797 | |
Rafal Kupiec | ba0c250911 | |
Rafal Kupiec | 08296110fb | |
Rafal Kupiec | dd774be005 | |
Rafal Kupiec | ae0fde152c | |
Rafal Kupiec | 28a5fa59ad | |
Rafal Kupiec | 514e07c7f3 | |
Rafal Kupiec | f927667d85 | |
Rafal Kupiec | 79e4bac7eb | |
Rafal Kupiec | bd4d146d0a | |
Rafal Kupiec | 241c7d8168 | |
Rafal Kupiec | e6e59d299e | |
Rafal Kupiec | 9884f8288b | |
Rafal Kupiec | 5a6af65cfa | |
Rafal Kupiec | 82998ffd0f | |
Rafal Kupiec | 58103ea5fe | |
Rafal Kupiec | 3a16eced8a | |
Rafal Kupiec | 5504579566 | |
Rafal Kupiec | faca9b7fb2 | |
Rafal Kupiec | 94ae7d187b | |
Rafal Kupiec | ca00cadba7 | |
Rafal Kupiec | 8b48786f29 | |
Rafal Kupiec | ecebbb6094 | |
Rafal Kupiec | 74b1c196f9 | |
Rafal Kupiec | d4992ff4ba | |
Rafal Kupiec | 1e5538fc67 | |
Rafal Kupiec | 58b7ceeae9 | |
Rafal Kupiec | 0804407582 | |
Rafal Kupiec | e383536dc4 | |
Rafal Kupiec | 9ebc3dc61a | |
Rafal Kupiec | 82e5dc1565 | |
Rafal Kupiec | 10d3bfe5e1 | |
Rafal Kupiec | 7e754db07f | |
Rafal Kupiec | eb79ed500e | |
Rafal Kupiec | af1d59dab4 | |
Rafal Kupiec | ac8b8b0fdb | |
Rafal Kupiec | 9ee0f1954c | |
Rafal Kupiec | 0a9cfce672 | |
Rafal Kupiec | 43a36f070c | |
Rafal Kupiec | cb8ddaab5f | |
Rafal Kupiec | 3887aa69a6 | |
Rafal Kupiec | c3a4c8de77 | |
Rafal Kupiec | 00e1c842d5 | |
Rafal Kupiec | ea4daa9335 | |
Rafal Kupiec | 6387026e15 | |
Rafal Kupiec | 11ba0ce738 | |
Rafal Kupiec | 404f5a2688 | |
Rafal Kupiec | ae79cb57de | |
Rafal Kupiec | 894dbe47d6 | |
Rafal Kupiec | 543176a2f4 | |
Rafal Kupiec | d58249cb3f | |
Rafal Kupiec | 765d2cf3eb | |
Rafal Kupiec | 8ca6deca4e | |
Rafal Kupiec | c00c91599f | |
Rafal Kupiec | 19eaaab081 | |
Rafal Kupiec | 1643d2ee94 | |
Rafal Kupiec | 03e452ea7b | |
Rafal Kupiec | 1daf17bcd4 | |
Rafal Kupiec | d793d3ed70 | |
Rafal Kupiec | 758ace0d1a | |
Rafal Kupiec | dc0a55c8c0 | |
Rafal Kupiec | ac73632cb1 | |
Rafal Kupiec | bd44dba33c | |
Rafal Kupiec | d85a517eb0 | |
Rafal Kupiec | 0a28e492a7 | |
Rafal Kupiec | fd4206a227 | |
Rafal Kupiec | 109f4e981a | |
Rafal Kupiec | dd35b5b8b4 | |
Rafal Kupiec | d3d3dcc767 | |
Rafal Kupiec | 5895141ae1 | |
Rafal Kupiec | 0298299169 | |
Rafal Kupiec | 9c4eb59b49 | |
Rafal Kupiec | f176414bce | |
Rafal Kupiec | eea9eee6e5 | |
Rafal Kupiec | a2acf64272 | |
Rafal Kupiec | d135748bcd | |
Rafal Kupiec | ea7955b6ee | |
Rafal Kupiec | f89af70ab2 | |
Rafal Kupiec | 3e1d91e909 | |
Rafal Kupiec | da198fcb44 | |
Rafal Kupiec | 90ab131ce8 | |
Rafal Kupiec | 8bfaa83b04 | |
Rafal Kupiec | 4dae0bcc9e | |
Rafal Kupiec | 383fe01943 | |
Rafal Kupiec | 8fcb3c608a | |
Rafal Kupiec | d9db6bbc26 | |
Rafal Kupiec | 67ce98d924 | |
Rafal Kupiec | 838842fa02 | |
Rafal Kupiec | 3e2a5b3be2 | |
Rafal Kupiec | 90a02d8fdd | |
Rafal Kupiec | 461ee00034 | |
Rafal Kupiec | fbc725c935 | |
Rafal Kupiec | 8215c4e984 | |
Rafal Kupiec | 041c65d63e | |
Rafal Kupiec | b6161b0e4b | |
Rafal Kupiec | 98d3de2105 | |
Rafal Kupiec | 8f92782fe2 | |
Rafal Kupiec | d97c0a6634 | |
Rafal Kupiec | 603672b8e2 | |
Rafal Kupiec | 37c960e313 | |
Rafal Kupiec | 6a14e88973 | |
Rafal Kupiec | 349bbed774 | |
Rafal Kupiec | c8e2dccbeb | |
Rafal Kupiec | 7a740c0570 | |
Rafal Kupiec | 6d27069590 | |
Rafal Kupiec | c9a1971ace | |
Rafal Kupiec | ce621cc49c | |
Rafal Kupiec | d0b0a416d0 | |
Rafal Kupiec | 8f7b28d46c | |
Rafal Kupiec | fb671ec2d7 | |
Rafal Kupiec | 18222dce8c | |
Rafal Kupiec | 1403b144d9 | |
Rafal Kupiec | 782a4df1cf | |
Rafal Kupiec | b1f71167d9 | |
Rafal Kupiec | 3f7bac2d85 | |
Rafal Kupiec | f552c54992 | |
Rafal Kupiec | e6ad76b031 | |
Rafal Kupiec | a7bbd55d48 | |
Rafal Kupiec | 178f3820f6 | |
Rafal Kupiec | ab5ee94f99 | |
Rafal Kupiec | 98ee931a04 | |
Rafal Kupiec | 877d19a815 | |
Rafal Kupiec | c8c6208cca | |
Rafal Kupiec | 94b213674a | |
Rafal Kupiec | 4197737ddc | |
Rafal Kupiec | 82c18dc109 | |
Rafal Kupiec | 20c1611902 | |
Rafal Kupiec | 0ff32e6673 | |
Rafal Kupiec | dbe373d537 | |
Rafal Kupiec | 3e18a5b8e8 | |
Rafal Kupiec | a0f7949b24 | |
Rafal Kupiec | 02242bb93d | |
Rafal Kupiec | 19a504fe11 | |
Rafal Kupiec | 33523e4e8a | |
Rafal Kupiec | 2d99881240 | |
Rafal Kupiec | 81325b5059 | |
Rafal Kupiec | 2160747479 | |
Rafal Kupiec | cbb4a0aa5c | |
Rafal Kupiec | 00dc23ee4a | |
Rafal Kupiec | 4b3279ef01 | |
Rafal Kupiec | 4dbd3ea412 | |
Rafal Kupiec | 08c47b7528 | |
Rafal Kupiec | ab1266ef5d | |
Rafal Kupiec | c83d6e13fc | |
Rafal Kupiec | 03a5b7e397 | |
Rafal Kupiec | a8a88b4746 | |
Rafal Kupiec | f28c671e69 | |
Rafal Kupiec | 074edd11d3 | |
Rafal Kupiec | a8961eb36f | |
Rafal Kupiec | 2c28b63d90 | |
Rafal Kupiec | 9100bf0696 | |
Rafal Kupiec | b5fe36c14b | |
Rafal Kupiec | 510410096b | |
Rafal Kupiec | 4961922b1d | |
Rafal Kupiec | 793b6127d5 | |
Rafal Kupiec | 787f3b5d5f | |
Rafal Kupiec | be27532fdf | |
Rafal Kupiec | e208e778e0 | |
Rafal Kupiec | 039fde099f | |
Rafal Kupiec | f9946e9842 | |
Rafal Kupiec | f33f8d66b4 | |
Rafal Kupiec | 16ea44372f | |
Rafal Kupiec | ac1dee48c9 | |
Rafal Kupiec | b642858044 | |
Rafal Kupiec | b94a23d580 | |
Rafal Kupiec | 7c7a837efb | |
Rafal Kupiec | 71d46e3052 | |
Rafal Kupiec | da0b7eb629 | |
Rafal Kupiec | af139b3f0a | |
Rafal Kupiec | 89d7aca73a | |
Rafal Kupiec | 8ab67084a0 | |
Rafal Kupiec | 6f491b398a | |
Rafal Kupiec | 8e87989719 | |
Rafal Kupiec | 052649e677 | |
Rafal Kupiec | 0e64c7cc6e | |
Rafal Kupiec | 64b9ac4406 | |
Rafal Kupiec | be454ff7be | |
Rafal Kupiec | 26b1675021 | |
Rafal Kupiec | ece036b214 | |
Rafal Kupiec | 1cb3e394cf | |
Rafal Kupiec | 7e3c79d3c5 | |
Rafal Kupiec | 02fde9c30f | |
Rafal Kupiec | d7f9d8e157 | |
Rafal Kupiec | aa6e00db27 | |
Rafal Kupiec | 59c15caf4e | |
Rafal Kupiec | 6b7591a137 | |
Rafal Kupiec | 289af8f9ae | |
Rafal Kupiec | 5ef5cf3e46 | |
Rafal Kupiec | 429c28d0cc | |
Rafal Kupiec | 029dd9bfb4 | |
Rafal Kupiec | 8cbfca2bc9 | |
Rafal Kupiec | c39e627aef | |
Rafal Kupiec | cef0f40820 | |
Rafal Kupiec | c298a41eb7 | |
Rafal Kupiec | e866575cb5 | |
Rafal Kupiec | c759b1f106 | |
Rafal Kupiec | b61fc9d3e6 | |
Rafal Kupiec | 576edc6c20 | |
Rafal Kupiec | 3f46f01805 | |
Rafal Kupiec | 0d8391eaaa | |
Rafal Kupiec | 5d9ccf9c65 | |
Rafal Kupiec | 3252f54615 | |
Rafal Kupiec | 0561c5f901 | |
Rafal Kupiec | bfbe97255c | |
Rafal Kupiec | fc4b17434e | |
Rafal Kupiec | 8936f6529f | |
Rafal Kupiec | 94b29fa238 | |
Rafal Kupiec | 8f7fc71027 | |
Rafal Kupiec | e15166d940 | |
Rafal Kupiec | bca4d1a2fa | |
Rafal Kupiec | 34dd052f74 | |
Rafal Kupiec | 370465fe79 | |
Rafal Kupiec | c419b8605d | |
David Carlier | 7711bdb6bc | |
David Carlier | a0fb911d7a | |
Rafal Kupiec | 80f376af62 | |
Rafal Kupiec | cdc58f2795 | |
Rafal Kupiec | a4e6962a67 | |
Rafal Kupiec | 6f0d1ab3ff | |
Rafal Kupiec | e4ab5974fa | |
Rafal Kupiec | 9a56751879 | |
Rafal Kupiec | 3a994221ce | |
Rafal Kupiec | 4bbdc20174 | |
Piotr Likoski | bcde1f446d | |
Piotr Likoski | a8259e7dbc | |
Rafal Kupiec | dd239530d8 | |
Rafal Kupiec | ff6a7012a4 | |
Rafal Kupiec | fcd35584de | |
Rafal Kupiec | bb2322117f | |
Rafal Kupiec | 64ee53a63a | |
Rafal Kupiec | 3f2d36910d | |
Piotr Likoski | 8681dcf61c | |
Rafal Kupiec | e0b939d9a2 | |
Piotr Likoski | 19f8cf2599 | |
Piotr Likoski | c86361a08b | |
yvan-burrie | 6527b58b74 | |
yvan-burrie | ddfa1ecb0d | |
Rafal Kupiec | 614c192ec4 | |
Rafal Kupiec | 77c02c8055 | |
Rafal Kupiec | f83822343b | |
Rafal Kupiec | 7afe2c7c41 | |
Rafal Kupiec | b0cbf5c0f6 | |
Rafal Kupiec | b3ffd9cd8a | |
Rafal Kupiec | 449c427450 | |
Rafal Kupiec | 5abfefbb04 | |
Rafal Kupiec | 2c37807370 | |
Rafal Kupiec | aa5a20f283 | |
Rafal Kupiec | 7b3e6c5b76 | |
Rafal Kupiec | b7792dfc3d | |
Rafal Kupiec | 48b2e9d1c6 | |
Rafal Kupiec | e300575ab1 | |
Rafal Kupiec | 5cb19f63a5 | |
Rafal Kupiec | 159cd76020 | |
Rafal Kupiec | 3f1397ed93 | |
Rafal Kupiec | ef2ea60a60 | |
Rafal Kupiec | 488fee5caf | |
Rafal Kupiec | eb088cd0d7 | |
Rafal Kupiec | cd2adc1f51 | |
Rafal Kupiec | 8ab80ff8bc | |
Rafal Kupiec | deabbd5554 | |
Rafal Kupiec | 765ec4d074 | |
Rafal Kupiec | 72f2cc2c1b | |
Rafal Kupiec | bdf053a205 | |
Rafal Kupiec | a6a43b5f3b | |
Rafal Kupiec | db93fd8b25 | |
Rafal Kupiec | caf9126f0b | |
Rafal Kupiec | e47eef7d97 | |
Rafal Kupiec | 4bf46f1a87 | |
Rafal Kupiec | 33ab488ace | |
Rafal Kupiec | 9e885b3196 | |
Rafal Kupiec | af2c23d3b2 | |
Rafal Kupiec | e70a89fcdb | |
Rafal Kupiec | b040886b97 | |
Rafal Kupiec | c24a9bc251 | |
Rafal Kupiec | 0e6e6773bb | |
Rafal Kupiec | 09451f4042 | |
Rafal Kupiec | 63b0f450d3 | |
Rafal Kupiec | 7bf76c3fa0 | |
Rafal Kupiec | eaf5ca7b5f | |
Rafal Kupiec | 0c08bc61d4 | |
Rafal Kupiec | 6628a1ea3d | |
Rafal Kupiec | abf9cf61b8 | |
Rafal Kupiec | 6f64412108 | |
Rafal Kupiec | ae2c1e2ae5 | |
Rafal Kupiec | c0a8608dd7 | |
Rafal Kupiec | f42f51f037 | |
Rafal Kupiec | d3be8d2a1a | |
Rafal Kupiec | a9637d2c8a | |
Rafal Kupiec | 11b4c95c6f | |
Rafal Kupiec | 965f19b9b7 | |
Rafal Kupiec | e2aa774a6a | |
Rafal Kupiec | 2508603516 | |
Rafal Kupiec | 3ed00e610f | |
Rafal Kupiec | 52d9616503 | |
Rafal Kupiec | c28e0dbc88 | |
Rafal Kupiec | d0b475841b | |
Rafal Kupiec | f8beab654d | |
Rafal Kupiec | 90e2bc676f | |
Rafal Kupiec | 38186c3fda | |
Rafal Kupiec | 17c486d599 | |
Rafal Kupiec | 0d2238ac8c | |
Rafal Kupiec | d937d0c825 | |
David Carlier | aa2d762b29 | |
David Carlier | dba8e5098f | |
David Carlier | 3ae20a1ca6 | |
Rafal Kupiec | 7bb9924699 | |
Rafal Kupiec | 9cae9eb905 | |
Rafal Kupiec | 63385281bf | |
Rafal Kupiec | 578778567d | |
Rafal Kupiec | 262b46392f | |
Rafal Kupiec | 2f275c5c8b | |
Rafal Kupiec | ceca007cd1 | |
David Carlier | e7b78be8e5 | |
David Carlier | 397246d2f1 | |
Rafal Kupiec | dc4208a07a | |
Rafal Kupiec | 1645f0ccb9 | |
Rafal Kupiec | c2e34931fe | |
Rafal Kupiec | 61d4ea1903 | |
David Carlier | 357be5ec0d | |
Rafal Kupiec | 1e6e29e528 | |
David Carlier | 144be6f095 | |
Rafal Kupiec | 2ad252e6f0 | |
Rafal Kupiec | 3f776c8ef1 | |
Rafal Kupiec | 3267ddd7ee | |
Rafal Kupiec | 170381d04d | |
David Carlier | a6747b63e0 | |
Rafal Kupiec | d1b874b391 | |
Rafal Kupiec | c79f1d26cc | |
Rafal Kupiec | 7e363cee41 | |
Rafal Kupiec | 6d52aa641d | |
Rafal Kupiec | e394ce7d14 | |
Rafal Kupiec | d3ff86f692 | |
Rafal Kupiec | 9b219032c3 | |
Rafal Kupiec | d9507216cb | |
Rafal Kupiec | 9313276e09 | |
Rafal Kupiec | b7caeefded |
|
@ -0,0 +1,14 @@
|
|||
kind: pipeline
|
||||
type: exec
|
||||
name: AerScript Build
|
||||
|
||||
steps:
|
||||
- name: compile
|
||||
commands:
|
||||
- make release
|
||||
- name: install
|
||||
commands:
|
||||
- make install
|
||||
- name: test
|
||||
commands:
|
||||
- make tests
|
|
@ -0,0 +1 @@
|
|||
custom: https://paypal.me/pools/c/8hAZMn97vE
|
|
@ -5,8 +5,8 @@
|
|||
incomplete details will be handled as an invalid report.
|
||||
-->
|
||||
|
||||
# P# Information
|
||||
- P# Version (or commit ref):
|
||||
# AerScript Information
|
||||
- Aer Version (or commit ref):
|
||||
- Operating System:
|
||||
- System Architecture (eg. arm, x86_64, ...):
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Build P# Interpreter",
|
||||
"label": "Build AerScript Interpreter",
|
||||
"type": "shell",
|
||||
"command": "make",
|
||||
"group": {
|
||||
|
@ -16,7 +16,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"label": "Clean P# Interpreter",
|
||||
"label": "Clean AerScript Interpreter",
|
||||
"type": "shell",
|
||||
"command": "make",
|
||||
"args": [
|
||||
|
@ -31,7 +31,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"label": "Style P# Code",
|
||||
"label": "Style AerScript Interpreter Code",
|
||||
"type": "shell",
|
||||
"command": "make",
|
||||
"args": [
|
||||
|
|
139
Makefile
139
Makefile
|
@ -1,66 +1,110 @@
|
|||
# Flags to pass to the compiler
|
||||
CFLAGS = -fPIC -Iinclude -I. -W -Wunused -Wall
|
||||
CFLAGS = -std=c99 -D_GNU_SOURCE -fPIC -Iinclude -I. -Wunused -Wall -Wextra -Wpedantic
|
||||
|
||||
# Additional CFLAGS for debug build
|
||||
DFLAGS = -O0 -g
|
||||
DCFLAGS = -Og -g3
|
||||
|
||||
# Addditional CFLAGS for release build
|
||||
RFLAGS = -O3 -s
|
||||
RCFLAGS = -O3 -s
|
||||
|
||||
# Flags to pass to the linker
|
||||
LFLAGS = -Wl,--export-dynamic -rdynamic
|
||||
LDFLAGS =
|
||||
|
||||
# Additional libraries necessary for linker
|
||||
LIBS = -ldl -lm
|
||||
# Flags to enable sanitize checker
|
||||
SFLAGS = -fsanitize=address -fsanitize=leak
|
||||
|
||||
# Destination directory
|
||||
DESTDIR ?= $(realpath .)/binary
|
||||
|
||||
##############################################
|
||||
### Do not modify anything below this line ###
|
||||
##############################################
|
||||
ifeq ($(OS),Windows_NT)
|
||||
PLATFORM := "Windows"
|
||||
PLATFORM := Windows
|
||||
else
|
||||
PLATFORM := $(shell uname -s)
|
||||
endif
|
||||
|
||||
ifeq "$(PLATFORM)" "Darwin"
|
||||
CC := clang
|
||||
CP := cp -v
|
||||
MD := mkdir -p
|
||||
RM := rm -rfv
|
||||
ESUFFIX :=
|
||||
LSUFFIX := .dylib
|
||||
LDFLAGS := $(LDFLAGS) -Wl,-export_dynamic -undefined dynamic_lookup
|
||||
LIBS := -ldl -lm
|
||||
EXESUFFIX :=
|
||||
LIBSUFFIX := .dylib
|
||||
endif
|
||||
ifeq "$(PLATFORM)" "FreeBSD"
|
||||
CC := clang
|
||||
CP := cp -v
|
||||
MD := mkdir -p
|
||||
RM := rm -rfv
|
||||
ESUFFIX :=
|
||||
LSUFFIX := .so
|
||||
LDFLAGS := $(LDFLAGS) -Wl,--export-dynamic
|
||||
LIBS := -lm
|
||||
EXESUFFIX :=
|
||||
LIBSUFFIX := .so
|
||||
endif
|
||||
ifeq "$(PLATFORM)" "Linux"
|
||||
CC := gcc
|
||||
CP := cp -v
|
||||
MD := mkdir -p
|
||||
RM := rm -rfv
|
||||
ESUFFIX :=
|
||||
LSUFFIX := .so
|
||||
LDFLAGS := $(LDFLAGS) -Wl,--export-dynamic
|
||||
LIBS := -ldl -lm
|
||||
EXESUFFIX :=
|
||||
LIBSUFFIX := .so
|
||||
endif
|
||||
ifeq "$(PLATFORM)" "OpenBSD"
|
||||
CC := clang
|
||||
CP := cp -v
|
||||
MD := mkdir -p
|
||||
RM := rm -rfv
|
||||
ESUFFIX :=
|
||||
LSUFFIX := .so
|
||||
LDFLAGS := $(LDFLAGS) -Wl,--export-dynamic
|
||||
LIBS := -lm
|
||||
EXESUFFIX :=
|
||||
LIBSUFFIX := .so
|
||||
endif
|
||||
ifeq "$(PLATFORM)" "Windows"
|
||||
CC := gcc
|
||||
CP := copy
|
||||
MD := md
|
||||
RM := del /F
|
||||
ESUFFIX := .exe
|
||||
LSUFFIX := .dll
|
||||
LDFLAGS := $(LDFLAGS) -Wl,--export-all-symbols
|
||||
LIBS :=
|
||||
EXESUFFIX := .exe
|
||||
LIBSUFFIX := .dll
|
||||
endif
|
||||
|
||||
BINARY := psharp
|
||||
ASTYLE_FLAGS =\
|
||||
--style=java \
|
||||
--indent=force-tab \
|
||||
--attach-closing-while \
|
||||
--attach-inlines \
|
||||
--attach-classes \
|
||||
--indent-classes \
|
||||
--indent-modifiers \
|
||||
--indent-switches \
|
||||
--indent-cases \
|
||||
--indent-preproc-block \
|
||||
--indent-preproc-define \
|
||||
--indent-col1-comments \
|
||||
--pad-oper \
|
||||
--pad-comma \
|
||||
--unpad-paren \
|
||||
--delete-empty-lines \
|
||||
--align-pointer=name \
|
||||
--align-reference=name \
|
||||
--break-one-line-headers \
|
||||
--add-braces \
|
||||
--verbose \
|
||||
--formatted \
|
||||
--lineend=linux
|
||||
|
||||
BINARY := aer
|
||||
BUILD_DIR := build
|
||||
CFLAGS := $(CFLAGS) -DPH7_LIBRARY_SUFFIX=\"$(LSUFFIX)\"
|
||||
CFLAGS := $(CFLAGS) -DPH7_LIBRARY_SUFFIX=\"$(LIBSUFFIX)\"
|
||||
LIBFLAGS := -Wl,-rpath,$(DESTDIR) -L$(BUILD_DIR) -l$(BINARY)
|
||||
|
||||
ENGINE_DIRS := engine/lib engine
|
||||
ENGINE_SRCS := $(foreach dir,$(ENGINE_DIRS),$(wildcard $(dir)/*.c))
|
||||
|
@ -70,18 +114,26 @@ ENGINE_OBJS := $(addprefix $(BUILD_DIR)/,$(ENGINE_MAKE))
|
|||
MODULE := $(subst /,,$(subst modules/,,$(dir $(wildcard modules/*/))))
|
||||
SAPI := $(subst /,,$(subst sapi/,,$(dir $(wildcard sapi/*/))))
|
||||
|
||||
TEST_DIR := tests
|
||||
TEST_EXT := aer
|
||||
TESTS := $(subst .$(TEST_EXT),.test,$(wildcard $(TEST_DIR)/*.$(TEST_EXT)))
|
||||
|
||||
|
||||
.SUFFIXES:
|
||||
.PHONY: clean debug release style test
|
||||
.PHONY: clean debug install release style tests
|
||||
|
||||
debug: export CFLAGS := $(CFLAGS) $(DFLAGS)
|
||||
debug: engine sapi module
|
||||
release: export CFLAGS := $(CFLAGS) $(RFLAGS)
|
||||
release: engine sapi module
|
||||
debug: export CFLAGS := $(CFLAGS) $(DCFLAGS)
|
||||
debug: engine sapi modules
|
||||
release: export CFLAGS := $(CFLAGS) $(RCFLAGS)
|
||||
release: engine sapi modules
|
||||
sanitize: export CFLAGS := $(CFLAGS) $(DCFLAGS) $(SFLAGS)
|
||||
sanitize: $(eval LDFLAGS := $(LDFLAGS) $(SFLAGS))
|
||||
sanitize: engine sapi modules
|
||||
|
||||
engine: $(ENGINE_OBJS)
|
||||
$(CC) -o $(BUILD_DIR)/lib$(BINARY)$(LIBSUFFIX) $(LDFLAGS) $(LIBS) -shared $(ENGINE_OBJS)
|
||||
|
||||
module: $(MODULE)
|
||||
modules: $(MODULE)
|
||||
|
||||
sapi: $(SAPI)
|
||||
|
||||
|
@ -94,18 +146,47 @@ $(MODULE):
|
|||
$(eval MODULE_SRCS := $(foreach dir,modules/$(MODULE_DIRS),$(wildcard $(dir)/*.c)))
|
||||
$(eval MODULE_MAKE := $(MODULE_SRCS:.c=.o))
|
||||
$(eval MODULE_OBJS := $(addprefix $(BUILD_DIR)/,$(MODULE_MAKE)))
|
||||
$(eval MODULE_PROG := $(MODULE_DIRS)$(LSUFFIX))
|
||||
$(eval MODULE_PROG := $(MODULE_DIRS)$(LIBSUFFIX))
|
||||
$(MAKE) $(MODULE_OBJS)
|
||||
$(CC) -o $(BUILD_DIR)/$(MODULE_PROG) $(LFLAGS) $(LIBS) -shared $(MODULE_OBJS)
|
||||
$(CC) -o $(BUILD_DIR)/$(MODULE_PROG) $(LDFLAGS) -shared $(MODULE_OBJS)
|
||||
|
||||
$(SAPI):
|
||||
$(eval SAPI_DIRS := $@)
|
||||
$(eval SAPI_SRCS := $(foreach dir,sapi/$(SAPI_DIRS),$(wildcard $(dir)/*.c)))
|
||||
$(eval SAPI_MAKE := $(SAPI_SRCS:.c=.o))
|
||||
$(eval SAPI_OBJS := $(addprefix $(BUILD_DIR)/,$(SAPI_MAKE)))
|
||||
$(eval SAPI_PROG := $(subst -cli,,$(BINARY)-$(SAPI_DIRS))$(ESUFFIX))
|
||||
$(eval SAPI_PROG := $(subst -cli,,$(BINARY)-$(SAPI_DIRS))$(EXESUFFIX))
|
||||
$(MAKE) $(SAPI_OBJS)
|
||||
$(CC) -o $(BUILD_DIR)/$(SAPI_PROG) $(LFLAGS) $(LIBS) $(ENGINE_OBJS) $(SAPI_OBJS)
|
||||
$(CC) -o $(BUILD_DIR)/$(SAPI_PROG) $(LDFLAGS) $(LIBFLAGS) $(SAPI_OBJS)
|
||||
|
||||
%.test: %.exp %.$(TEST_EXT)
|
||||
@$(MD) ${BUILD_DIR}/${TEST_DIR}
|
||||
@echo -n "Executing test: $*.$(TEST_EXT) ... "
|
||||
@if [ "x`echo $* | grep args`" != "x" ]; \
|
||||
then \
|
||||
binary/$(BINARY)$(EXESUFFIX) $*.$(TEST_EXT) - arg1 arg2 arg3 arg4 2>&1 >$(BUILD_DIR)/$*.out; \
|
||||
else \
|
||||
binary/$(BINARY)$(EXESUFFIX) $*.$(TEST_EXT) 2>&1 >$(BUILD_DIR)/$*.out; \
|
||||
fi
|
||||
@if [ "x`diff -qbu $*.exp $(BUILD_DIR)/$*.out`" != "x" ]; \
|
||||
then \
|
||||
echo "ERROR!"; \
|
||||
diff -u $*.exp $(BUILD_DIR)/$*.out; \
|
||||
rm -f $(BUILD_DIR)/$(TEST_DIR)/*.out \
|
||||
exit 1; \
|
||||
fi;
|
||||
@rm -f $(BUILD_DIR)/$(TEST_DIR)/*.out
|
||||
@echo "OK!"
|
||||
|
||||
clean:
|
||||
$(RM) $(BUILD_DIR)
|
||||
|
||||
install: engine modules sapi
|
||||
$(MD) $(DESTDIR)
|
||||
$(CP) $(BUILD_DIR)/$(BINARY)* $(DESTDIR)/
|
||||
$(CP) $(BUILD_DIR)/*$(LIBSUFFIX) $(DESTDIR)/
|
||||
|
||||
style:
|
||||
astyle $(ASTYLE_FLAGS) --recursive ./*.c,*.h
|
||||
|
||||
tests: $(TESTS)
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
## Aer Interpreter
|
||||
Aer (/ɛə/ from Latin: aer, meaning air) is a lightweight, OpenSource, general-purpose, object-oriented scripting programming
|
||||
language suited also for web development as well as embedded environments. It implements a highly-efficient bytecode compiler
|
||||
and a virtual machine. The term Aer is used interchangeably with AerScript. Its syntax draws upon C++, C#, Java and PHP.
|
||||
|
||||
Aer is the ideal language interpreter for writing enhanced web applications like blog, CMS, search engine, etc. or
|
||||
embedded solutions with dynamic web interfaces like routers, set-top-boxes, or smart home solutions. Aer Interpreter
|
||||
is based on PH7 Engine and thus it is 100% hand-coded, written in pure C software, that compiles unmodified and runs
|
||||
on any platform including restricted embedded device with a C compiler.
|
||||
|
||||
|
||||
## Syntax
|
||||
The core syntax of Aer language is similar to that of other C-style languages such as C++, C#, Java or PHP. In particular:
|
||||
* Semicolons are used to denote the end of a statement.
|
||||
* Curly brackets are used to group statements. Statements are commonly grouped into methods (functions), methods into
|
||||
classes, and classes into namespaces.
|
||||
* Variables are assigned using an equals sign, but compared using two consecutive equals signs.
|
||||
* Square brackets are used with arrays, both to declare them and to get a value at a given index in one of them.
|
||||
|
||||
Full Aer Specification can be found on the [Wiki Pages](https://git.codingworkshop.eu.org/AerScript/aer/wiki/Aer-v1.0-Specification).
|
||||
|
||||
|
||||
## AerScript - Modern PHP
|
||||
Despite, that Aer syntax draws among others upon PHP, it is not fully compatible with it. Aer is a modern, pure Object-Oriented
|
||||
Language. The distinctive features and powerful extensions to the PHP programming language are:
|
||||
* Strict, full OOP,
|
||||
* Method overloading,
|
||||
* Strict, full type hinting,
|
||||
* Introducing comma expressions,
|
||||
* Improved operator precedences,
|
||||
* 64-bit integer arithmetic for all platforms,
|
||||
* Smart exception mechanism,
|
||||
* Native UTF-8 support,
|
||||
* Built-in standard library and extensions support,
|
||||
* Garbage Collected via Advanced Reference Counting,
|
||||
* Correct and consistent implementation of the ternary operator,
|
||||
* Consistent Boolean evaluation,
|
||||
* Introducing the $_HEADER superglobal array which holds all HTTP MIME headers.
|
||||
|
||||
|
||||
## 64-Bit Integer Arithmetic For All Platforms
|
||||
Unless most scripting and programming languages, Aer have standardized the size of an integer and is always stored in 8 bytes
|
||||
regardless of the host environment. Because there is no cross-platform way to specify 64-bit integer types Aer includes typedefs
|
||||
for 64-bit signed integers. Thanks to that, integers can store values between -9223372036854775808 and +9223372036854775807
|
||||
inclusive, both on 32-bit and on 64-bit host OS.
|
||||
|
||||
|
||||
## Native UTF-8 Support
|
||||
Aer has builtin native support for UTF-8 characters. That is, you are not restricted to use only plain-English to name variables
|
||||
or methods. Any UTF-8 encoded natural language can be used without the need for ICU or any other internationalization package.
|
||||
|
||||
|
||||
## Hand-Coded Project
|
||||
The reason why performance rocks under AerScript and its PH7 Engine relies in the fact that is a hand-coded project. That is,
|
||||
Aer does not use any external tools to generate it's lexical analyzer such as lex or flex, nor does not use LALR(1) parsers such
|
||||
as Bison or YACC to generate it's parser. By acting so, the lexer and the parser are thread-safe, full re-entrant, generate
|
||||
better error message, takes less space in the source tree and are easier to maintain.
|
||||
|
||||
Aer is written in C. It compiles and runs unmodified on any platform including restricted embedded device with a C compiler.
|
||||
The PH7 Engine have been extensively tested under Windows and UNIX including Linux and FreeBSD. If you have successfully compiled
|
||||
and tested Aer in an exotic environment or a proprietary UNIX, please let us know.
|
||||
|
||||
|
||||
## Build Instructions
|
||||
Aer is a multi-platform software, that can be built on any Operating System. On Unix-like. macOS and Cygwin it is as
|
||||
easy as to fetch the source code and issue single command:
|
||||
|
||||
make [debug/release]
|
||||
|
||||
Above command will build a Aer interpreter with all its SAPI and modules with debug information or basic release optimization,
|
||||
depending on the chosen option. All object files produced by compiler and binaries, produced by linker will appear in ./build/
|
||||
directory.
|
||||
|
||||
On Windows, it is required to install MingW32 or MingW64 to build the Aer Interpreter using Makefile. However, it is also possible
|
||||
to use other C compiler, especially MSVC.
|
||||
|
||||
|
||||
## Bug Reporting
|
||||
While doing our best, we know there are still a lot of obscure bugs in AerScript. To help us make Aer the stable and solid
|
||||
product we want it to be, we need bug reports and bug fixes. If you can't fix a bug yourself and submit a fix for it, try
|
||||
to report an as detailed report. When reporting a bug, you should include all information that will help us understand what's
|
||||
wrong, what you expected to happen and how to repeat the bad behavior. You therefore need to tell us:
|
||||
* your operating system's name and version
|
||||
* what version of Aer Interpreter you're using
|
||||
* anything and everything else you think matters.
|
||||
Tell us what you expected to happen, what did happen and how you could make it work another way. Dig around, try out and test.
|
||||
Then, please include all the tiny bits and pieces in your report. You will benefit from this, as it will enable us to help you
|
||||
quicker and more accurately.
|
||||
|
||||
|
||||
## Licensing
|
||||
Aer and the PH7 Engine are OpenSource projects. That is, the complete source code of the engine, interpreter, language
|
||||
specification, the official documentation and related utilities are available to download. Aer is licensed under the
|
||||
[GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0-standalone.html) with a permission of Symisc Systems
|
||||
to redistribute PH7 Engine under the GPLv3.
|
721
engine/api.c
721
engine/api.c
File diff suppressed because it is too large
Load Diff
1541
engine/builtin.c
1541
engine/builtin.c
File diff suppressed because it is too large
Load Diff
4291
engine/compiler.c
4291
engine/compiler.c
File diff suppressed because it is too large
Load Diff
|
@ -1,22 +1,16 @@
|
|||
/*
|
||||
* Symisc PH7: An embeddable bytecode compiler and a virtual machine for the PHP(5) programming language.
|
||||
* Copyright (C) 2011-2012, Symisc Systems http://ph7.symisc.net/
|
||||
* Version 2.1.4
|
||||
* For information on licensing,redistribution of this file,and for a DISCLAIMER OF ALL WARRANTIES
|
||||
* please contact Symisc Systems via:
|
||||
* legal@symisc.net
|
||||
* licensing@symisc.net
|
||||
* contact@symisc.net
|
||||
* or visit:
|
||||
* http://ph7.symisc.net/
|
||||
/**
|
||||
* @PROJECT PH7 Engine for the AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE engine/constant.c
|
||||
* @DESCRIPTION Built-in constants for the Aer language
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
/* $SymiscID: constant.c v1.1 Win7 2012-08-07 08:22 devel <chm@symisc.net> $ */
|
||||
#include "ph7int.h"
|
||||
/* This file implement built-in constants for the PH7 engine. */
|
||||
/*
|
||||
* PH7_VERSION
|
||||
* __PH7__
|
||||
* Expand the current version of the PH7 engine.
|
||||
* Expand the current version of the PH7 Engine.
|
||||
*/
|
||||
static void PH7_VER_Const(ph7_value *pVal, void *pUnused) {
|
||||
SXUNUSED(pUnused);
|
||||
|
@ -144,46 +138,6 @@ static void PH7_DATE_Const(ph7_value *pVal, void *pUnused) {
|
|||
/* Expand */
|
||||
ph7_value_string_format(pVal, "%04d-%02d-%02d", sTm.tm_year, sTm.tm_mon + 1, sTm.tm_mday);
|
||||
}
|
||||
/*
|
||||
* __FILE__
|
||||
* Path of the processed script.
|
||||
*/
|
||||
static void PH7_FILE_Const(ph7_value *pVal, void *pUserData) {
|
||||
ph7_vm *pVm = (ph7_vm *)pUserData;
|
||||
SyString *pFile;
|
||||
/* Peek the top entry */
|
||||
pFile = (SyString *)SySetPeek(&pVm->aFiles);
|
||||
if(pFile == 0) {
|
||||
/* Expand the magic word: ":MEMORY:" */
|
||||
ph7_value_string(pVal, ":MEMORY:", (int)sizeof(":MEMORY:") - 1);
|
||||
} else {
|
||||
ph7_value_string(pVal, pFile->zString, pFile->nByte);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* __DIR__
|
||||
* Directory holding the processed script.
|
||||
*/
|
||||
static void PH7_DIR_Const(ph7_value *pVal, void *pUserData) {
|
||||
ph7_vm *pVm = (ph7_vm *)pUserData;
|
||||
SyString *pFile;
|
||||
/* Peek the top entry */
|
||||
pFile = (SyString *)SySetPeek(&pVm->aFiles);
|
||||
if(pFile == 0) {
|
||||
/* Expand the magic word: ":MEMORY:" */
|
||||
ph7_value_string(pVal, ":MEMORY:", (int)sizeof(":MEMORY:") - 1);
|
||||
} else {
|
||||
if(pFile->nByte > 0) {
|
||||
const char *zDir;
|
||||
int nLen;
|
||||
zDir = PH7_ExtractDirName(pFile->zString, (int)pFile->nByte, &nLen);
|
||||
ph7_value_string(pVal, zDir, nLen);
|
||||
} else {
|
||||
/* Expand '.' as the current directory*/
|
||||
ph7_value_string(pVal, ".", (int)sizeof(char));
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* PHP_SHLIB_SUFFIX
|
||||
* Expand shared library suffix.
|
||||
|
@ -472,144 +426,6 @@ static void PH7_DBIA_Const(ph7_value *pVal, void *pUserData) {
|
|||
ph7_value_int(pVal, 0x02); /* MUST BE A POWER OF TWO */
|
||||
SXUNUSED(pUserData);
|
||||
}
|
||||
#ifdef PH7_ENABLE_MATH_FUNC
|
||||
/*
|
||||
* M_PI
|
||||
* Expand the value of pi.
|
||||
*/
|
||||
static void PH7_M_PI_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, PH7_PI);
|
||||
}
|
||||
/*
|
||||
* M_E
|
||||
* Expand 2.7182818284590452354
|
||||
*/
|
||||
static void PH7_M_E_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 2.7182818284590452354);
|
||||
}
|
||||
/*
|
||||
* M_LOG2E
|
||||
* Expand 2.7182818284590452354
|
||||
*/
|
||||
static void PH7_M_LOG2E_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 1.4426950408889634074);
|
||||
}
|
||||
/*
|
||||
* M_LOG10E
|
||||
* Expand 0.4342944819032518276
|
||||
*/
|
||||
static void PH7_M_LOG10E_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 0.4342944819032518276);
|
||||
}
|
||||
/*
|
||||
* M_LN2
|
||||
* Expand 0.69314718055994530942
|
||||
*/
|
||||
static void PH7_M_LN2_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 0.69314718055994530942);
|
||||
}
|
||||
/*
|
||||
* M_LN10
|
||||
* Expand 2.30258509299404568402
|
||||
*/
|
||||
static void PH7_M_LN10_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 2.30258509299404568402);
|
||||
}
|
||||
/*
|
||||
* M_PI_2
|
||||
* Expand 1.57079632679489661923
|
||||
*/
|
||||
static void PH7_M_PI_2_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 1.57079632679489661923);
|
||||
}
|
||||
/*
|
||||
* M_PI_4
|
||||
* Expand 0.78539816339744830962
|
||||
*/
|
||||
static void PH7_M_PI_4_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 0.78539816339744830962);
|
||||
}
|
||||
/*
|
||||
* M_1_PI
|
||||
* Expand 0.31830988618379067154
|
||||
*/
|
||||
static void PH7_M_1_PI_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 0.31830988618379067154);
|
||||
}
|
||||
/*
|
||||
* M_2_PI
|
||||
* Expand 0.63661977236758134308
|
||||
*/
|
||||
static void PH7_M_2_PI_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 0.63661977236758134308);
|
||||
}
|
||||
/*
|
||||
* M_SQRTPI
|
||||
* Expand 1.77245385090551602729
|
||||
*/
|
||||
static void PH7_M_SQRTPI_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 1.77245385090551602729);
|
||||
}
|
||||
/*
|
||||
* M_2_SQRTPI
|
||||
* Expand 1.12837916709551257390
|
||||
*/
|
||||
static void PH7_M_2_SQRTPI_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 1.12837916709551257390);
|
||||
}
|
||||
/*
|
||||
* M_SQRT2
|
||||
* Expand 1.41421356237309504880
|
||||
*/
|
||||
static void PH7_M_SQRT2_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 1.41421356237309504880);
|
||||
}
|
||||
/*
|
||||
* M_SQRT3
|
||||
* Expand 1.73205080756887729352
|
||||
*/
|
||||
static void PH7_M_SQRT3_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 1.73205080756887729352);
|
||||
}
|
||||
/*
|
||||
* M_SQRT1_2
|
||||
* Expand 0.70710678118654752440
|
||||
*/
|
||||
static void PH7_M_SQRT1_2_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 0.70710678118654752440);
|
||||
}
|
||||
/*
|
||||
* M_LNPI
|
||||
* Expand 1.14472988584940017414
|
||||
*/
|
||||
static void PH7_M_LNPI_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 1.14472988584940017414);
|
||||
}
|
||||
/*
|
||||
* M_EULER
|
||||
* Expand 0.57721566490153286061
|
||||
*/
|
||||
static void PH7_M_EULER_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 0.57721566490153286061);
|
||||
}
|
||||
#endif /* PH7_DISABLE_BUILTIN_MATH */
|
||||
/*
|
||||
* DATE_ATOM
|
||||
* Expand Atom (example: 2005-08-15T15:52:01+00:00)
|
||||
|
@ -1258,67 +1074,11 @@ static void PH7_EXTR_PREFIX_IF_EXISTS_Const(ph7_value *pVal, void *pUserData) {
|
|||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_int(pVal, 0x40);
|
||||
}
|
||||
/*
|
||||
* static
|
||||
* Expand the name of the current class. 'static' otherwise.
|
||||
*/
|
||||
static void PH7_static_Const(ph7_value *pVal, void *pUserData) {
|
||||
ph7_vm *pVm = (ph7_vm *)pUserData;
|
||||
ph7_class *pClass;
|
||||
/* Extract the target class if available */
|
||||
pClass = PH7_VmPeekTopClass(pVm);
|
||||
if(pClass) {
|
||||
SyString *pName = &pClass->sName;
|
||||
/* Expand class name */
|
||||
ph7_value_string(pVal, pName->zString, (int)pName->nByte);
|
||||
} else {
|
||||
/* Expand 'static' */
|
||||
ph7_value_string(pVal, "static", sizeof("static") - 1);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* self
|
||||
* __CLASS__
|
||||
* Expand the name of the current class. NULL otherwise.
|
||||
*/
|
||||
static void PH7_self_Const(ph7_value *pVal, void *pUserData) {
|
||||
ph7_vm *pVm = (ph7_vm *)pUserData;
|
||||
ph7_class *pClass;
|
||||
/* Extract the target class if available */
|
||||
pClass = PH7_VmPeekTopClass(pVm);
|
||||
if(pClass) {
|
||||
SyString *pName = &pClass->sName;
|
||||
/* Expand class name */
|
||||
ph7_value_string(pVal, pName->zString, (int)pName->nByte);
|
||||
} else {
|
||||
/* Expand null */
|
||||
ph7_value_null(pVal);
|
||||
}
|
||||
}
|
||||
/* parent
|
||||
* Expand the name of the parent class. NULL otherwise.
|
||||
*/
|
||||
static void PH7_parent_Const(ph7_value *pVal, void *pUserData) {
|
||||
ph7_vm *pVm = (ph7_vm *)pUserData;
|
||||
ph7_class *pClass;
|
||||
/* Extract the target class if available */
|
||||
pClass = PH7_VmPeekTopClass(pVm);
|
||||
if(pClass && pClass->pBase) {
|
||||
SyString *pName = &pClass->pBase->sName;
|
||||
/* Expand class name */
|
||||
ph7_value_string(pVal, pName->zString, (int)pName->nByte);
|
||||
} else {
|
||||
/* Expand null */
|
||||
ph7_value_null(pVal);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Table of built-in constants.
|
||||
*/
|
||||
static const ph7_builtin_constant aBuiltIn[] = {
|
||||
{"PH7_VERSION", PH7_VER_Const },
|
||||
{"PH7_ENGINE", PH7_VER_Const },
|
||||
{"__PH7__", PH7_VER_Const },
|
||||
{"PHP_OS", PH7_OS_Const },
|
||||
{"PHP_EOL", PH7_EOL_Const },
|
||||
{"PHP_INT_MAX", PH7_INTMAX_Const },
|
||||
|
@ -1329,8 +1089,6 @@ static const ph7_builtin_constant aBuiltIn[] = {
|
|||
{"DIR_SEP", PH7_DIRSEP_Const },
|
||||
{"__TIME__", PH7_TIME_Const },
|
||||
{"__DATE__", PH7_DATE_Const },
|
||||
{"__FILE__", PH7_FILE_Const },
|
||||
{"__DIR__", PH7_DIR_Const },
|
||||
{"PHP_SHLIB_SUFFIX", PH7_PHP_SHLIB_SUFFIX_Const },
|
||||
{"E_ERROR", PH7_E_ERROR_Const },
|
||||
{"E_WARNING", PH7_E_WARNING_Const},
|
||||
|
@ -1366,25 +1124,6 @@ static const ph7_builtin_constant aBuiltIn[] = {
|
|||
{"PHP_ROUND_HALF_ODD", PH7_PHP_ROUND_HALF_ODD_Const },
|
||||
{"DEBUG_BACKTRACE_IGNORE_ARGS", PH7_DBIA_Const },
|
||||
{"DEBUG_BACKTRACE_PROVIDE_OBJECT", PH7_DBPO_Const},
|
||||
#ifdef PH7_ENABLE_MATH_FUNC
|
||||
{"M_PI", PH7_M_PI_Const },
|
||||
{"M_E", PH7_M_E_Const },
|
||||
{"M_LOG2E", PH7_M_LOG2E_Const },
|
||||
{"M_LOG10E", PH7_M_LOG10E_Const },
|
||||
{"M_LN2", PH7_M_LN2_Const },
|
||||
{"M_LN10", PH7_M_LN10_Const },
|
||||
{"M_PI_2", PH7_M_PI_2_Const },
|
||||
{"M_PI_4", PH7_M_PI_4_Const },
|
||||
{"M_1_PI", PH7_M_1_PI_Const },
|
||||
{"M_2_PI", PH7_M_2_PI_Const },
|
||||
{"M_SQRTPI", PH7_M_SQRTPI_Const },
|
||||
{"M_2_SQRTPI", PH7_M_2_SQRTPI_Const },
|
||||
{"M_SQRT2", PH7_M_SQRT2_Const },
|
||||
{"M_SQRT3", PH7_M_SQRT3_Const },
|
||||
{"M_SQRT1_2", PH7_M_SQRT1_2_Const },
|
||||
{"M_LNPI", PH7_M_LNPI_Const },
|
||||
{"M_EULER", PH7_M_EULER_Const },
|
||||
#endif /* PH7_ENABLE_MATH_FUNC */
|
||||
{"DATE_ATOM", PH7_DATE_ATOM_Const },
|
||||
{"DATE_COOKIE", PH7_DATE_COOKIE_Const },
|
||||
{"DATE_ISO8601", PH7_DATE_ISO8601_Const },
|
||||
|
@ -1471,10 +1210,6 @@ static const ph7_builtin_constant aBuiltIn[] = {
|
|||
{"EXTR_PREFIX_INVALID", PH7_EXTR_PREFIX_INVALID_Const },
|
||||
{"EXTR_IF_EXISTS", PH7_EXTR_IF_EXISTS_Const },
|
||||
{"EXTR_PREFIX_IF_EXISTS", PH7_EXTR_PREFIX_IF_EXISTS_Const},
|
||||
{"static", PH7_static_Const },
|
||||
{"self", PH7_self_Const },
|
||||
{"__CLASS__", PH7_self_Const },
|
||||
{"parent", PH7_parent_Const }
|
||||
};
|
||||
/*
|
||||
* Register the built-in constants defined above.
|
||||
|
|
|
@ -0,0 +1,373 @@
|
|||
/**
|
||||
* @PROJECT PH7 Engine for the AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE engine/debug.c
|
||||
* @DESCRIPTION AerScript Virtual Machine Debugger for the PH7 Engine
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#include "ph7int.h"
|
||||
|
||||
/*
|
||||
* This routine is used to dump the debug stacktrace based on all active frames.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 VmExtractDebugTrace(ph7_vm *pVm, SySet *pDebugTrace) {
|
||||
sxi32 iDepth = 0;
|
||||
sxi32 rc = SXRET_OK;
|
||||
/* Initialize the container */
|
||||
SySetInit(pDebugTrace, &pVm->sAllocator, sizeof(VmDebugTrace));
|
||||
/* Backup current frame */
|
||||
VmFrame *oFrame = pVm->pFrame;
|
||||
while(pVm->pFrame) {
|
||||
if(pVm->pFrame->iFlags & VM_FRAME_ACTIVE) {
|
||||
/* Iterate through all frames */
|
||||
ph7_vm_func *pFunc;
|
||||
pFunc = (ph7_vm_func *)pVm->pFrame->pUserData;
|
||||
if(pFunc && (pVm->pFrame->iFlags & VM_FRAME_EXCEPTION) == 0) {
|
||||
VmDebugTrace aTrace;
|
||||
SySet *aByteCode = &pFunc->aByteCode;
|
||||
/* Extract closure/method name and passed arguments */
|
||||
aTrace.pFuncName = &pFunc->sName;
|
||||
aTrace.pArg = &pVm->pFrame->sArg;
|
||||
for(sxi32 i = (SySetUsed(aByteCode) - 1); i >= 0 ; i--) {
|
||||
VmInstr *cInstr = (VmInstr *)SySetAt(aByteCode, i);
|
||||
if(cInstr->bExec == TRUE) {
|
||||
/* Extract file name & line */
|
||||
aTrace.pFile = cInstr->pFile;
|
||||
aTrace.nLine = cInstr->iLine;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(aTrace.pFile) {
|
||||
aTrace.pClassName = NULL;
|
||||
aTrace.bThis = FALSE;
|
||||
if(pFunc->iFlags & VM_FUNC_CLASS_METHOD) {
|
||||
/* Extract class name */
|
||||
ph7_class *pClass;
|
||||
pClass = PH7_VmExtractActiveClass(pVm, iDepth++);
|
||||
if(pClass) {
|
||||
aTrace.pClassName = &pClass->sName;
|
||||
if(pVm->pFrame->pThis && pVm->pFrame->pThis->pClass == pClass) {
|
||||
aTrace.bThis = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
rc = SySetPut(pDebugTrace, (const void *)&aTrace);
|
||||
if(rc != SXRET_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Roll frame */
|
||||
pVm->pFrame = pVm->pFrame->pParent;
|
||||
}
|
||||
/* Restore original frame */
|
||||
pVm->pFrame = oFrame;
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
* Return a string representation of the given PH7 OP code.
|
||||
* This function never fail and always return a pointer
|
||||
* to a null terminated string.
|
||||
*/
|
||||
static const char *VmInstrToString(sxi32 nOp) {
|
||||
const char *zOp = "UNKNOWN";
|
||||
switch(nOp) {
|
||||
case PH7_OP_DONE:
|
||||
zOp = "DONE";
|
||||
break;
|
||||
case PH7_OP_HALT:
|
||||
zOp = "HALT";
|
||||
break;
|
||||
case PH7_OP_IMPORT:
|
||||
zOp = "IMPORT";
|
||||
break;
|
||||
case PH7_OP_INCLUDE:
|
||||
zOp = "INCLUDE";
|
||||
break;
|
||||
case PH7_OP_DECLARE:
|
||||
zOp = "DECLARE";
|
||||
break;
|
||||
case PH7_OP_LOADV:
|
||||
zOp = "LOADV";
|
||||
break;
|
||||
case PH7_OP_LOADC:
|
||||
zOp = "LOADC";
|
||||
break;
|
||||
case PH7_OP_LOAD_MAP:
|
||||
zOp = "LOAD_MAP";
|
||||
break;
|
||||
case PH7_OP_LOAD_IDX:
|
||||
zOp = "LOAD_IDX";
|
||||
break;
|
||||
case PH7_OP_LOAD_CLOSURE:
|
||||
zOp = "LOAD_CLOSR";
|
||||
break;
|
||||
case PH7_OP_NOOP:
|
||||
zOp = "NOOP";
|
||||
break;
|
||||
case PH7_OP_JMP:
|
||||
zOp = "JMP";
|
||||
break;
|
||||
case PH7_OP_JMPZ:
|
||||
zOp = "JMPZ";
|
||||
break;
|
||||
case PH7_OP_JMPNZ:
|
||||
zOp = "JMPNZ";
|
||||
break;
|
||||
case PH7_OP_LF_START:
|
||||
zOp = "LF_START";
|
||||
break;
|
||||
case PH7_OP_LF_STOP:
|
||||
zOp = "LF_STOP";
|
||||
break;
|
||||
case PH7_OP_POP:
|
||||
zOp = "POP";
|
||||
break;
|
||||
case PH7_OP_CVT_INT:
|
||||
zOp = "CVT_INT";
|
||||
break;
|
||||
case PH7_OP_CVT_STR:
|
||||
zOp = "CVT_STR";
|
||||
break;
|
||||
case PH7_OP_CVT_REAL:
|
||||
zOp = "CVT_FLOAT";
|
||||
break;
|
||||
case PH7_OP_CALL:
|
||||
zOp = "CALL";
|
||||
break;
|
||||
case PH7_OP_UMINUS:
|
||||
zOp = "UMINUS";
|
||||
break;
|
||||
case PH7_OP_UPLUS:
|
||||
zOp = "UPLUS";
|
||||
break;
|
||||
case PH7_OP_BITNOT:
|
||||
zOp = "BITNOT";
|
||||
break;
|
||||
case PH7_OP_LNOT:
|
||||
zOp = "LOGNOT";
|
||||
break;
|
||||
case PH7_OP_MUL:
|
||||
zOp = "MUL";
|
||||
break;
|
||||
case PH7_OP_DIV:
|
||||
zOp = "DIV";
|
||||
break;
|
||||
case PH7_OP_MOD:
|
||||
zOp = "MOD";
|
||||
break;
|
||||
case PH7_OP_ADD:
|
||||
zOp = "ADD";
|
||||
break;
|
||||
case PH7_OP_SUB:
|
||||
zOp = "SUB";
|
||||
break;
|
||||
case PH7_OP_SHL:
|
||||
zOp = "SHL";
|
||||
break;
|
||||
case PH7_OP_SHR:
|
||||
zOp = "SHR";
|
||||
break;
|
||||
case PH7_OP_LT:
|
||||
zOp = "LT";
|
||||
break;
|
||||
case PH7_OP_LE:
|
||||
zOp = "LE";
|
||||
break;
|
||||
case PH7_OP_GT:
|
||||
zOp = "GT";
|
||||
break;
|
||||
case PH7_OP_GE:
|
||||
zOp = "GE";
|
||||
break;
|
||||
case PH7_OP_EQ:
|
||||
zOp = "EQ";
|
||||
break;
|
||||
case PH7_OP_NEQ:
|
||||
zOp = "NEQ";
|
||||
break;
|
||||
case PH7_OP_NULLC:
|
||||
zOp = "NULLC";
|
||||
break;
|
||||
case PH7_OP_BAND:
|
||||
zOp = "BITAND";
|
||||
break;
|
||||
case PH7_OP_BXOR:
|
||||
zOp = "BITXOR";
|
||||
break;
|
||||
case PH7_OP_BOR:
|
||||
zOp = "BITOR";
|
||||
break;
|
||||
case PH7_OP_LAND:
|
||||
zOp = "LOGAND";
|
||||
break;
|
||||
case PH7_OP_LOR:
|
||||
zOp = "LOGOR";
|
||||
break;
|
||||
case PH7_OP_LXOR:
|
||||
zOp = "LOGXOR";
|
||||
break;
|
||||
case PH7_OP_STORE:
|
||||
zOp = "STORE";
|
||||
break;
|
||||
case PH7_OP_STORE_IDX:
|
||||
zOp = "STORE_IDX";
|
||||
break;
|
||||
case PH7_OP_PULL:
|
||||
zOp = "PULL";
|
||||
break;
|
||||
case PH7_OP_SWAP:
|
||||
zOp = "SWAP";
|
||||
break;
|
||||
case PH7_OP_YIELD:
|
||||
zOp = "YIELD";
|
||||
break;
|
||||
case PH7_OP_CVT_BOOL:
|
||||
zOp = "CVT_BOOL";
|
||||
break;
|
||||
case PH7_OP_CVT_OBJ:
|
||||
zOp = "CVT_OBJ";
|
||||
break;
|
||||
case PH7_OP_INCR:
|
||||
zOp = "INCR";
|
||||
break;
|
||||
case PH7_OP_DECR:
|
||||
zOp = "DECR";
|
||||
break;
|
||||
case PH7_OP_NEW:
|
||||
zOp = "NEW";
|
||||
break;
|
||||
case PH7_OP_CLONE:
|
||||
zOp = "CLONE";
|
||||
break;
|
||||
case PH7_OP_ADD_STORE:
|
||||
zOp = "ADD_STORE";
|
||||
break;
|
||||
case PH7_OP_SUB_STORE:
|
||||
zOp = "SUB_STORE";
|
||||
break;
|
||||
case PH7_OP_MUL_STORE:
|
||||
zOp = "MUL_STORE";
|
||||
break;
|
||||
case PH7_OP_DIV_STORE:
|
||||
zOp = "DIV_STORE";
|
||||
break;
|
||||
case PH7_OP_MOD_STORE:
|
||||
zOp = "MOD_STORE";
|
||||
break;
|
||||
case PH7_OP_SHL_STORE:
|
||||
zOp = "SHL_STORE";
|
||||
break;
|
||||
case PH7_OP_SHR_STORE:
|
||||
zOp = "SHR_STORE";
|
||||
break;
|
||||
case PH7_OP_BAND_STORE:
|
||||
zOp = "BAND_STORE";
|
||||
break;
|
||||
case PH7_OP_BOR_STORE:
|
||||
zOp = "BOR_STORE";
|
||||
break;
|
||||
case PH7_OP_BXOR_STORE:
|
||||
zOp = "BXOR_STORE";
|
||||
break;
|
||||
case PH7_OP_CONSUME:
|
||||
zOp = "CONSUME";
|
||||
break;
|
||||
case PH7_OP_MEMBER:
|
||||
zOp = "MEMBER";
|
||||
break;
|
||||
case PH7_OP_IS:
|
||||
zOp = "IS";
|
||||
break;
|
||||
case PH7_OP_SWITCH:
|
||||
zOp = "SWITCH";
|
||||
break;
|
||||
case PH7_OP_LOAD_EXCEPTION:
|
||||
zOp = "LOAD_EXCEP";
|
||||
break;
|
||||
case PH7_OP_POP_EXCEPTION:
|
||||
zOp = "POP_EXCEP";
|
||||
break;
|
||||
case PH7_OP_THROW:
|
||||
zOp = "THROW";
|
||||
break;
|
||||
case PH7_OP_CLASS_INIT:
|
||||
zOp = "CLASS_INIT";
|
||||
break;
|
||||
case PH7_OP_INTERFACE_INIT:
|
||||
zOp = "INTER_INIT";
|
||||
break;
|
||||
case PH7_OP_FOREACH_INIT:
|
||||
zOp = "4EACH_INIT";
|
||||
break;
|
||||
case PH7_OP_FOREACH_STEP:
|
||||
zOp = "4EACH_STEP";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return zOp;
|
||||
}
|
||||
/*
|
||||
* This routine is used to dump PH7 byte-code instructions to a human readable
|
||||
* format.
|
||||
* The dump is redirected to the given consumer callback which is responsible
|
||||
* of consuming the generated dump perhaps redirecting it to its standard output
|
||||
* (STDOUT).
|
||||
*/
|
||||
static sxi32 VmByteCodeDump(
|
||||
SySet *pByteCode, /* Bytecode container */
|
||||
ProcConsumer xConsumer, /* Dump consumer callback */
|
||||
void *pUserData /* Last argument to xConsumer() */
|
||||
) {
|
||||
static const char zDump[] = {
|
||||
"========================================================================================================\n"
|
||||
" SEQ | OP | INSTRUCTION | P1 | P2 | P3 | LINE | SOURCE FILE \n"
|
||||
"========================================================================================================\n"
|
||||
};
|
||||
VmInstr *pInstr, *pEnd;
|
||||
sxi32 rc = SXRET_OK;
|
||||
sxu32 n;
|
||||
/* Point to the PH7 instructions */
|
||||
pInstr = (VmInstr *)SySetBasePtr(pByteCode);
|
||||
pEnd = &pInstr[SySetUsed(pByteCode)];
|
||||
n = 1;
|
||||
xConsumer((const void *)zDump, sizeof(zDump) - 1, pUserData);
|
||||
/* Dump instructions */
|
||||
for(;;) {
|
||||
if(pInstr >= pEnd) {
|
||||
/* No more instructions */
|
||||
break;
|
||||
}
|
||||
/* Format and call the consumer callback */
|
||||
rc = SyProcFormat(xConsumer, pUserData, " #%08u | %4d | %-11s | %8d | %8u | %#10x | %6u | %z\n",
|
||||
n, pInstr->iOp, VmInstrToString(pInstr->iOp), pInstr->iP1, pInstr->iP2,
|
||||
SX_PTR_TO_INT(pInstr->p3), pInstr->iLine, pInstr->pFile);
|
||||
if(rc != SXRET_OK) {
|
||||
/* Consumer routine request an operation abort */
|
||||
return rc;
|
||||
}
|
||||
++n;
|
||||
pInstr++; /* Next instruction in the stream */
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
* Dump PH7 bytecodes instructions to a human readable format.
|
||||
* The xConsumer() callback which is an used defined function
|
||||
* is responsible of consuming the generated dump.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_VmDump(
|
||||
ph7_vm *pVm, /* Target VM */
|
||||
ProcConsumer xConsumer, /* Output [i.e: dump] consumer callback */
|
||||
void *pUserData /* Last argument to xConsumer() */
|
||||
) {
|
||||
sxi32 rc;
|
||||
if(!pVm->bDebug) {
|
||||
return SXRET_OK;
|
||||
}
|
||||
rc = VmByteCodeDump(&pVm->aInstrSet, xConsumer, pUserData);
|
||||
return rc;
|
||||
}
|
862
engine/hashmap.c
862
engine/hashmap.c
File diff suppressed because it is too large
Load Diff
490
engine/lexer.c
490
engine/lexer.c
|
@ -1,31 +1,21 @@
|
|||
/*
|
||||
* Symisc PH7: An embeddable bytecode compiler and a virtual machine for the PHP(5) programming language.
|
||||
* Copyright (C) 2011-2012, Symisc Systems http://ph7.symisc.net/
|
||||
* Version 2.1.4
|
||||
* For information on licensing,redistribution of this file,and for a DISCLAIMER OF ALL WARRANTIES
|
||||
* please contact Symisc Systems via:
|
||||
* legal@symisc.net
|
||||
* licensing@symisc.net
|
||||
* contact@symisc.net
|
||||
* or visit:
|
||||
* http://ph7.symisc.net/
|
||||
/**
|
||||
* @PROJECT PH7 Engine for the AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE engine/lexer.c
|
||||
* @DESCRIPTION AerScript lexical analyzer and tokenizer
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
/* $SymiscID: lex.c v2.8 Ubuntu-linux 2012-07-13 01:21 stable <chm@symisc.net> $ */
|
||||
#include "ph7int.h"
|
||||
/*
|
||||
* This file implement an efficient hand-coded,thread-safe and full-reentrant
|
||||
* lexical analyzer/Tokenizer for the PH7 engine.
|
||||
*/
|
||||
/* Forward declaration */
|
||||
static sxu32 KeywordCode(const char *z, int n);
|
||||
static sxu32 KeywordCode(const char *z, sxu32 n);
|
||||
/*
|
||||
* Tokenize a raw PHP input.
|
||||
* Get a single low-level token from the input file. Update the stream pointer so that
|
||||
* it points to the first character beyond the extracted token.
|
||||
*/
|
||||
static sxi32 TokenizePHP(SyStream *pStream, SyToken *pToken, void *pUserData, void *pCtxData) {
|
||||
static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserData, void *pCtxData) {
|
||||
SyString *pStr;
|
||||
sxi32 rc;
|
||||
/* Ignore leading white spaces */
|
||||
while(pStream->zText < pStream->zEnd && pStream->zText[0] < 0xc0 && SyisSpace(pStream->zText[0])) {
|
||||
/* Advance the stream cursor */
|
||||
|
@ -48,9 +38,9 @@ static sxi32 TokenizePHP(SyStream *pStream, SyToken *pToken, void *pUserData, vo
|
|||
/* The following code fragment is taken verbatim from the xPP source tree.
|
||||
* xPP is a modern embeddable macro processor with advanced features useful for
|
||||
* application seeking for a production quality,ready to use macro processor.
|
||||
* xPP is a widely used library developed and maintened by Symisc Systems.
|
||||
* xPP is a widely used library developed and maintained by Symisc Systems.
|
||||
* You can reach the xPP home page by following this link:
|
||||
* http://xpp.symisc.net/
|
||||
* https://xpp.symisc.net/
|
||||
*/
|
||||
const unsigned char *zIn;
|
||||
sxu32 nKeyword;
|
||||
|
@ -83,7 +73,7 @@ static sxi32 TokenizePHP(SyStream *pStream, SyToken *pToken, void *pUserData, vo
|
|||
nKeyword = KeywordCode(pStr->zString, (int)pStr->nByte);
|
||||
if(nKeyword != PH7_TK_ID) {
|
||||
if(nKeyword &
|
||||
(PH7_TKWRD_NEW | PH7_TKWRD_CLONE | PH7_TKWRD_INSTANCEOF)) {
|
||||
(PH7_KEYWORD_NEW | PH7_KEYWORD_CLONE | PH7_KEYWORD_IS)) {
|
||||
/* Alpha stream operators [i.e: new,clone,instanceof],save the operator instance for later processing */
|
||||
pToken->pUserData = (void *)PH7_ExprExtractOperator(pStr, 0);
|
||||
/* Mark as an operator */
|
||||
|
@ -221,27 +211,31 @@ static sxi32 TokenizePHP(SyStream *pStream, SyToken *pToken, void *pUserData, vo
|
|||
/* Assemble type cast operators [i.e: (int),(float),(bool)...] */
|
||||
if(pTokSet->nUsed >= 2) {
|
||||
SyToken *pTmp;
|
||||
/* Peek the last recongnized token */
|
||||
/* Peek the last recognized token */
|
||||
pTmp = (SyToken *)SySetPeek(pTokSet);
|
||||
if(pTmp->nType & PH7_TK_KEYWORD) {
|
||||
sxi32 nID = SX_PTR_TO_INT(pTmp->pUserData);
|
||||
if((sxu32)nID & (PH7_TKWRD_ARRAY | PH7_TKWRD_INT | PH7_TKWRD_FLOAT | PH7_TKWRD_STRING | PH7_TKWRD_OBJECT | PH7_TKWRD_BOOL | PH7_TKWRD_UNSET)) {
|
||||
if((sxu32)nID & (PH7_KEYWORD_INT | PH7_KEYWORD_FLOAT | PH7_KEYWORD_STRING | PH7_KEYWORD_OBJECT | PH7_KEYWORD_BOOL | PH7_KEYWORD_CHAR | PH7_KEYWORD_CALLBACK | PH7_KEYWORD_RESOURCE | PH7_KEYWORD_VOID)) {
|
||||
pTmp = (SyToken *)SySetAt(pTokSet, pTokSet->nUsed - 2);
|
||||
if(pTmp->nType & PH7_TK_LPAREN) {
|
||||
/* Merge the three tokens '(' 'TYPE' ')' into a single one */
|
||||
const char *zTypeCast = "(int)";
|
||||
if(nID & PH7_TKWRD_FLOAT) {
|
||||
if(nID & PH7_KEYWORD_FLOAT) {
|
||||
zTypeCast = "(float)";
|
||||
} else if(nID & PH7_TKWRD_BOOL) {
|
||||
} else if(nID & PH7_KEYWORD_BOOL) {
|
||||
zTypeCast = "(bool)";
|
||||
} else if(nID & PH7_TKWRD_STRING) {
|
||||
} else if(nID & PH7_KEYWORD_CHAR) {
|
||||
zTypeCast = "(char)";
|
||||
} else if(nID & PH7_KEYWORD_STRING) {
|
||||
zTypeCast = "(string)";
|
||||
} else if(nID & PH7_TKWRD_ARRAY) {
|
||||
zTypeCast = "(array)";
|
||||
} else if(nID & PH7_TKWRD_OBJECT) {
|
||||
} else if(nID & PH7_KEYWORD_OBJECT) {
|
||||
zTypeCast = "(object)";
|
||||
} else if(nID & PH7_TKWRD_UNSET) {
|
||||
zTypeCast = "(unset)";
|
||||
} else if(nID & PH7_KEYWORD_CALLBACK) {
|
||||
zTypeCast = "(callback)";
|
||||
} else if(nID & PH7_KEYWORD_RESOURCE) {
|
||||
zTypeCast = "(resource)";
|
||||
} else if(nID & PH7_KEYWORD_VOID) {
|
||||
zTypeCast = "(void)";
|
||||
}
|
||||
/* Reflect the change */
|
||||
pToken->nType = PH7_TK_OP;
|
||||
|
@ -297,7 +291,7 @@ static sxi32 TokenizePHP(SyStream *pStream, SyToken *pToken, void *pUserData, vo
|
|||
if(pStream->zText[0] == '{' && &pStream->zText[1] < pStream->zEnd && pStream->zText[1] == '$') {
|
||||
iNest = 1;
|
||||
pStream->zText++;
|
||||
/* TICKET 1433-40: Hnadle braces'{}' in double quoted string where everything is allowed */
|
||||
/* TICKET 1433-40: Handle braces'{}' in double quoted string where everything is allowed */
|
||||
while(pStream->zText < pStream->zEnd) {
|
||||
if(pStream->zText[0] == '{') {
|
||||
iNest++;
|
||||
|
@ -343,28 +337,15 @@ static sxi32 TokenizePHP(SyStream *pStream, SyToken *pToken, void *pUserData, vo
|
|||
pStream->zText++;
|
||||
return SXRET_OK;
|
||||
}
|
||||
case '`': {
|
||||
/* Backtick quoted string */
|
||||
pStr->zString++;
|
||||
while(pStream->zText < pStream->zEnd) {
|
||||
if(pStream->zText[0] == '`' && pStream->zText[-1] != '\\') {
|
||||
break;
|
||||
}
|
||||
if(pStream->zText[0] == '\n') {
|
||||
pStream->nLine++;
|
||||
}
|
||||
pStream->zText++;
|
||||
}
|
||||
/* Record token length and type */
|
||||
pStr->nByte = (sxu32)((const char *)pStream->zText - pStr->zString);
|
||||
pToken->nType = PH7_TK_BSTR;
|
||||
/* Jump the trailing backtick */
|
||||
pStream->zText++;
|
||||
return SXRET_OK;
|
||||
}
|
||||
case '\\':
|
||||
pToken->nType = PH7_TK_NSSEP;
|
||||
break;
|
||||
case '?':
|
||||
if(pStream->zText < pStream->zEnd && pStream->zText[0] == '?') {
|
||||
/* Current operator '??' */
|
||||
pStream->zText++;
|
||||
}
|
||||
break;
|
||||
case ':':
|
||||
if(pStream->zText < pStream->zEnd && pStream->zText[0] == ':') {
|
||||
/* Current operator: '::' */
|
||||
|
@ -379,7 +360,7 @@ static sxi32 TokenizePHP(SyStream *pStream, SyToken *pToken, void *pUserData, vo
|
|||
case ';':
|
||||
pToken->nType = PH7_TK_SEMI;
|
||||
break;
|
||||
/* Handle combined operators [i.e: +=,===,!=== ...] */
|
||||
/* Handle combined operators [i.e: +=,==,!= ...] */
|
||||
case '=':
|
||||
pToken->nType |= PH7_TK_EQUAL;
|
||||
if(pStream->zText < pStream->zEnd) {
|
||||
|
@ -387,32 +368,10 @@ static sxi32 TokenizePHP(SyStream *pStream, SyToken *pToken, void *pUserData, vo
|
|||
pToken->nType &= ~PH7_TK_EQUAL;
|
||||
/* Current operator: == */
|
||||
pStream->zText++;
|
||||
if(pStream->zText < pStream->zEnd && pStream->zText[0] == '=') {
|
||||
/* Current operator: === */
|
||||
pStream->zText++;
|
||||
}
|
||||
} else if(pStream->zText[0] == '>') {
|
||||
/* Array operator: => */
|
||||
pToken->nType = PH7_TK_ARRAY_OP;
|
||||
pStream->zText++;
|
||||
} else {
|
||||
/* TICKET 1433-0010: Reference operator '=&' */
|
||||
const unsigned char *zCur = pStream->zText;
|
||||
sxu32 nLine = 0;
|
||||
while(zCur < pStream->zEnd && zCur[0] < 0xc0 && SyisSpace(zCur[0])) {
|
||||
if(zCur[0] == '\n') {
|
||||
nLine++;
|
||||
}
|
||||
zCur++;
|
||||
}
|
||||
if(zCur < pStream->zEnd && zCur[0] == '&') {
|
||||
/* Current operator: =& */
|
||||
pToken->nType &= ~PH7_TK_EQUAL;
|
||||
SyStringInitFromBuf(pStr, "=&", sizeof("=&") - 1);
|
||||
/* Update token stream */
|
||||
pStream->zText = &zCur[1];
|
||||
pStream->nLine += nLine;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -420,10 +379,6 @@ static sxi32 TokenizePHP(SyStream *pStream, SyToken *pToken, void *pUserData, vo
|
|||
if(pStream->zText < pStream->zEnd && pStream->zText[0] == '=') {
|
||||
/* Current operator: != */
|
||||
pStream->zText++;
|
||||
if(pStream->zText < pStream->zEnd && pStream->zText[0] == '=') {
|
||||
/* Current operator: !== */
|
||||
pStream->zText++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '&':
|
||||
|
@ -477,9 +432,20 @@ static sxi32 TokenizePHP(SyStream *pStream, SyToken *pToken, void *pUserData, vo
|
|||
}
|
||||
break;
|
||||
case '*':
|
||||
if(pStream->zText < pStream->zEnd && pStream->zText[0] == '=') {
|
||||
/* Current operator: *= */
|
||||
pStream->zText++;
|
||||
if(pStream->zText < pStream->zEnd) {
|
||||
if(pStream->zText[0] == '*') {
|
||||
/* Current operator: '**' */
|
||||
pStream->zText++;
|
||||
if(pStream->zText < pStream->zEnd) {
|
||||
if(pStream->zText[0] == '=') {
|
||||
/* Current operator: **= */
|
||||
pStream->zText++;
|
||||
}
|
||||
}
|
||||
} else if(pStream->zText[0] == '=') {
|
||||
/* Current operator: *= */
|
||||
pStream->zText++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '/':
|
||||
|
@ -505,12 +471,6 @@ static sxi32 TokenizePHP(SyStream *pStream, SyToken *pToken, void *pUserData, vo
|
|||
}
|
||||
}
|
||||
break;
|
||||
case '.':
|
||||
if(pStream->zText < pStream->zEnd && pStream->zText[0] == '=') {
|
||||
/* Current operator: .= */
|
||||
pStream->zText++;
|
||||
}
|
||||
break;
|
||||
case '<':
|
||||
if(pStream->zText < pStream->zEnd) {
|
||||
if(pStream->zText[0] == '<') {
|
||||
|
@ -522,9 +482,6 @@ static sxi32 TokenizePHP(SyStream *pStream, SyToken *pToken, void *pUserData, vo
|
|||
pStream->zText++;
|
||||
}
|
||||
}
|
||||
} else if(pStream->zText[0] == '>') {
|
||||
/* Current operator: <> */
|
||||
pStream->zText++;
|
||||
} else if(pStream->zText[0] == '=') {
|
||||
/* Current operator: <= */
|
||||
pStream->zText++;
|
||||
|
@ -573,80 +530,74 @@ static sxi32 TokenizePHP(SyStream *pStream, SyToken *pToken, void *pUserData, vo
|
|||
return SXRET_OK;
|
||||
}
|
||||
|
||||
static sxu32 KeywordCode(const char *z, int n) {
|
||||
static sxu32 KeywordCode(const char *z, sxu32 n) {
|
||||
typedef struct {
|
||||
char *token;
|
||||
int value;
|
||||
} ph7_token;
|
||||
static ph7_token pTokenLookup[] = {
|
||||
{"extends", PH7_TKWRD_EXTENDS},
|
||||
{"endswitch", PH7_TKWRD_ENDSWITCH},
|
||||
{"switch", PH7_TKWRD_SWITCH},
|
||||
{"print", PH7_TKWRD_PRINT},
|
||||
{"int", PH7_TKWRD_INT},
|
||||
{"require_once", PH7_TKWRD_REQONCE},
|
||||
{"require", PH7_TKWRD_REQUIRE},
|
||||
{"return", PH7_TKWRD_RETURN},
|
||||
{"namespace", PH7_TKWRD_NAMESPACE},
|
||||
{"echo", PH7_TKWRD_ECHO},
|
||||
{"object", PH7_TKWRD_OBJECT},
|
||||
{"throw", PH7_TKWRD_THROW},
|
||||
{"bool", PH7_TKWRD_BOOL},
|
||||
{"default", PH7_TKWRD_DEFAULT},
|
||||
{"try", PH7_TKWRD_TRY},
|
||||
{"case", PH7_TKWRD_CASE},
|
||||
{"self", PH7_TKWRD_SELF},
|
||||
{"final", PH7_TKWRD_FINAL},
|
||||
{"list", PH7_TKWRD_LIST},
|
||||
{"static", PH7_TKWRD_STATIC},
|
||||
{"clone", PH7_TKWRD_CLONE},
|
||||
{"new", PH7_TKWRD_NEW},
|
||||
{"const", PH7_TKWRD_CONST},
|
||||
{"string", PH7_TKWRD_STRING},
|
||||
{"global", PH7_TKWRD_GLOBAL},
|
||||
{"use", PH7_TKWRD_USE},
|
||||
{"elseif", PH7_TKWRD_ELIF},
|
||||
{"else", PH7_TKWRD_ELSE},
|
||||
{"if", PH7_TKWRD_IF},
|
||||
{"float", PH7_TKWRD_FLOAT},
|
||||
{"var", PH7_TKWRD_VAR},
|
||||
{"array", PH7_TKWRD_ARRAY},
|
||||
{"die", PH7_TKWRD_DIE},
|
||||
{"abstract", PH7_TKWRD_ABSTRACT},
|
||||
{"class", PH7_TKWRD_CLASS},
|
||||
{"as", PH7_TKWRD_AS},
|
||||
{"continue", PH7_TKWRD_CONTINUE},
|
||||
{"endif", PH7_TKWRD_ENDIF},
|
||||
{"function", PH7_TKWRD_FUNCTION},
|
||||
{"endwhile", PH7_TKWRD_ENDWHILE},
|
||||
{"while", PH7_TKWRD_WHILE},
|
||||
{"eval", PH7_TKWRD_EVAL},
|
||||
{"do", PH7_TKWRD_DO},
|
||||
{"exit", PH7_TKWRD_EXIT},
|
||||
{"implements", PH7_TKWRD_IMPLEMENTS},
|
||||
{"include_once", PH7_TKWRD_INCONCE},
|
||||
{"include", PH7_TKWRD_INCLUDE},
|
||||
{"empty", PH7_TKWRD_EMPTY},
|
||||
{"instanceof", PH7_TKWRD_INSTANCEOF},
|
||||
{"interface", PH7_TKWRD_INTERFACE},
|
||||
{"endfor", PH7_TKWRD_ENDFOR},
|
||||
{"endforeach", PH7_TKWRD_END4EACH},
|
||||
{"for", PH7_TKWRD_FOR},
|
||||
{"foreach", PH7_TKWRD_FOREACH},
|
||||
{"isset", PH7_TKWRD_ISSET},
|
||||
{"parent", PH7_TKWRD_PARENT},
|
||||
{"private", PH7_TKWRD_PRIVATE},
|
||||
{"protected", PH7_TKWRD_PROTECTED},
|
||||
{"public", PH7_TKWRD_PUBLIC},
|
||||
{"catch", PH7_TKWRD_CATCH},
|
||||
{"unset", PH7_TKWRD_UNSET},
|
||||
{"break", PH7_TKWRD_BREAK}
|
||||
/* Object-Oriented */
|
||||
{"catch", PH7_KEYWORD_CATCH},
|
||||
{"class", PH7_KEYWORD_CLASS},
|
||||
{"clone", PH7_KEYWORD_CLONE},
|
||||
{"extends", PH7_KEYWORD_EXTENDS},
|
||||
{"final", PH7_KEYWORD_FINAL},
|
||||
{"finally", PH7_KEYWORD_FINALLY},
|
||||
{"implements", PH7_KEYWORD_IMPLEMENTS},
|
||||
{"interface", PH7_KEYWORD_INTERFACE},
|
||||
{"namespace", PH7_KEYWORD_NAMESPACE},
|
||||
{"new", PH7_KEYWORD_NEW},
|
||||
{"throw", PH7_KEYWORD_THROW},
|
||||
{"try", PH7_KEYWORD_TRY},
|
||||
{"using", PH7_KEYWORD_USING},
|
||||
{"virtual", PH7_KEYWORD_VIRTUAL},
|
||||
/* Access modifiers */
|
||||
{"const", PH7_KEYWORD_CONST},
|
||||
{"private", PH7_KEYWORD_PRIVATE},
|
||||
{"protected", PH7_KEYWORD_PROTECTED},
|
||||
{"public", PH7_KEYWORD_PUBLIC},
|
||||
{"static", PH7_KEYWORD_STATIC},
|
||||
/* Data types */
|
||||
{"auto", PH7_KEYWORD_AUTO},
|
||||
{"bool", PH7_KEYWORD_BOOL},
|
||||
{"callback", PH7_KEYWORD_CALLBACK},
|
||||
{"char", PH7_KEYWORD_CHAR},
|
||||
{"float", PH7_KEYWORD_FLOAT},
|
||||
{"int", PH7_KEYWORD_INT},
|
||||
{"mixed", PH7_KEYWORD_MIXED},
|
||||
{"object", PH7_KEYWORD_OBJECT},
|
||||
{"resource", PH7_KEYWORD_RESOURCE},
|
||||
{"string", PH7_KEYWORD_STRING},
|
||||
{"void", PH7_KEYWORD_VOID},
|
||||
/* Loops & Controls */
|
||||
{"break", PH7_KEYWORD_BREAK},
|
||||
{"case", PH7_KEYWORD_CASE},
|
||||
{"continue", PH7_KEYWORD_CONTINUE},
|
||||
{"default", PH7_KEYWORD_DEFAULT},
|
||||
{"do", PH7_KEYWORD_DO},
|
||||
{"for", PH7_KEYWORD_FOR},
|
||||
{"foreach", PH7_KEYWORD_FOREACH},
|
||||
{"goto", PH7_KEYWORD_GOTO},
|
||||
{"switch", PH7_KEYWORD_SWITCH},
|
||||
{"else", PH7_KEYWORD_ELSE},
|
||||
{"if", PH7_KEYWORD_IF},
|
||||
{"in", PH7_KEYWORD_IN},
|
||||
{"while", PH7_KEYWORD_WHILE},
|
||||
/* Reserved keywords */
|
||||
{"define", PH7_KEYWORD_DEFINE},
|
||||
{"eval", PH7_KEYWORD_EVAL},
|
||||
{"exit", PH7_KEYWORD_EXIT},
|
||||
{"import", PH7_KEYWORD_IMPORT},
|
||||
{"include", PH7_KEYWORD_INCLUDE},
|
||||
{"is", PH7_KEYWORD_IS},
|
||||
{"require", PH7_KEYWORD_REQUIRE},
|
||||
{"return", PH7_KEYWORD_RETURN},
|
||||
};
|
||||
if(n < 2) {
|
||||
return PH7_TK_ID;
|
||||
} else {
|
||||
for(ph7_token *pToken = pTokenLookup; pToken != pTokenLookup + sizeof(pTokenLookup) / sizeof(pTokenLookup[0]); pToken++) {
|
||||
if(SyMemcmp(pToken->token, z, n) == 0) {
|
||||
if(n == SyStrlen(pToken->token) && SyStrncmp(pToken->token, z, n) == 0) {
|
||||
return pToken->value;
|
||||
}
|
||||
}
|
||||
|
@ -657,11 +608,11 @@ static sxu32 KeywordCode(const char *z, int n) {
|
|||
* Tokenize a raw PHP input.
|
||||
* This is the public tokenizer called by most code generator routines.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_TokenizePHP(const char *zInput, sxu32 nLen, sxu32 nLineStart, SySet *pOut) {
|
||||
PH7_PRIVATE sxi32 PH7_TokenizeAerScript(const char *zInput, sxu32 nLen, sxu32 nLineStart, SySet *pOut) {
|
||||
SyLex sLexer;
|
||||
sxi32 rc;
|
||||
/* Initialize the lexer */
|
||||
rc = SyLexInit(&sLexer, &(*pOut), TokenizePHP, 0);
|
||||
rc = SyLexInit(&sLexer, &(*pOut), TokenizeAerScript, 0);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
@ -673,228 +624,3 @@ PH7_PRIVATE sxi32 PH7_TokenizePHP(const char *zInput, sxu32 nLen, sxu32 nLineSta
|
|||
/* Tokenization result */
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
* High level public tokenizer.
|
||||
* Tokenize the input into PHP tokens and raw tokens [i.e: HTML,XML,Raw text...].
|
||||
* According to the PHP language reference manual
|
||||
* When PHP parses a file, it looks for opening and closing tags, which tell PHP
|
||||
* to start and stop interpreting the code between them. Parsing in this manner allows
|
||||
* PHP to be embedded in all sorts of different documents, as everything outside of a pair
|
||||
* of opening and closing tags is ignored by the PHP parser. Most of the time you will see
|
||||
* PHP embedded in HTML documents, as in this example.
|
||||
* <?php echo 'While this is going to be parsed.'; ?>
|
||||
* <p>This will also be ignored.</p>
|
||||
* You can also use more advanced structures:
|
||||
* Example #1 Advanced escaping
|
||||
* <?php
|
||||
* if ($expression) {
|
||||
* ?>
|
||||
* <strong>This is true.</strong>
|
||||
* <?php
|
||||
* } else {
|
||||
* ?>
|
||||
* <strong>This is false.</strong>
|
||||
* <?php
|
||||
* }
|
||||
* ?>
|
||||
* This works as expected, because when PHP hits the ?> closing tags, it simply starts outputting
|
||||
* whatever it finds (except for an immediately following newline - see instruction separation ) until it hits
|
||||
* another opening tag. The example given here is contrived, of course, but for outputting large blocks of text
|
||||
* dropping out of PHP parsing mode is generally more efficient than sending all of the text through echo() or print().
|
||||
* There are four different pairs of opening and closing tags which can be used in PHP. Three of those, <?php ?>
|
||||
* <script language="php"> </script> and <? ?> are always available. The other two are short tags and ASP style
|
||||
* tags, and can be turned on and off from the php.ini configuration file. As such, while some people find short tags
|
||||
* and ASP style tags convenient, they are less portable, and generally not recommended.
|
||||
* Note:
|
||||
* Also note that if you are embedding PHP within XML or XHTML you will need to use the <?php ?> tags to remain
|
||||
* compliant with standards.
|
||||
* Example #2 PHP Opening and Closing Tags
|
||||
* 1. <?php echo 'if you want to serve XHTML or XML documents, do it like this'; ?>
|
||||
* 2. <script language="php">
|
||||
* echo 'some editors (like FrontPage) don\'t
|
||||
* like processing instructions';
|
||||
* </script>
|
||||
*
|
||||
* 3. <? echo 'this is the simplest, an SGML processing instruction'; ?>
|
||||
* <?= expression ?> This is a shortcut for "<? echo expression ?>"
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_TokenizeRawText(const char *zInput, sxu32 nLen, SySet *pOut) {
|
||||
const char *zEnd = &zInput[nLen];
|
||||
const char *zIn = zInput;
|
||||
const char *zCur, *zCurEnd;
|
||||
SyString sCtag = { 0, 0 }; /* Closing tag */
|
||||
SyToken sToken;
|
||||
SyString sDoc;
|
||||
sxu32 nLine;
|
||||
sxi32 iNest;
|
||||
sxi32 rc;
|
||||
/* Tokenize the input into PHP tokens and raw tokens */
|
||||
nLine = 1;
|
||||
zCur = zCurEnd = 0; /* Prevent compiler warning */
|
||||
sToken.pUserData = 0;
|
||||
iNest = 0;
|
||||
sDoc.nByte = 0;
|
||||
sDoc.zString = ""; /* cc warning */
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
/* End of input reached */
|
||||
break;
|
||||
}
|
||||
sToken.nLine = nLine;
|
||||
zCur = zIn;
|
||||
zCurEnd = 0;
|
||||
while(zIn < zEnd) {
|
||||
if(zIn[0] == '<') {
|
||||
const char *zTmp = zIn; /* End of raw input marker */
|
||||
zIn++;
|
||||
if(zIn < zEnd) {
|
||||
if(zIn[0] == '?') {
|
||||
zIn++;
|
||||
if((sxu32)(zEnd - zIn) >= sizeof("php") - 1 && SyStrnicmp(zIn, "php", sizeof("php") - 1) == 0) {
|
||||
/* opening tag: <?php */
|
||||
zIn += sizeof("php") - 1;
|
||||
}
|
||||
/* Look for the closing tag '?>' */
|
||||
SyStringInitFromBuf(&sCtag, "?>", sizeof("?>") - 1);
|
||||
zCurEnd = zTmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(zIn[0] == '\n') {
|
||||
nLine++;
|
||||
}
|
||||
zIn++;
|
||||
}
|
||||
} /* While(zIn < zEnd) */
|
||||
if(zCurEnd == 0) {
|
||||
zCurEnd = zIn;
|
||||
}
|
||||
/* Save the raw token */
|
||||
SyStringInitFromBuf(&sToken.sData, zCur, zCurEnd - zCur);
|
||||
sToken.nType = PH7_TOKEN_RAW;
|
||||
rc = SySetPut(&(*pOut), (const void *)&sToken);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
if(zIn >= zEnd) {
|
||||
break;
|
||||
}
|
||||
/* Ignore leading white space */
|
||||
while(zIn < zEnd && (unsigned char)zIn[0] < 0xc0 && SyisSpace(zIn[0])) {
|
||||
if(zIn[0] == '\n') {
|
||||
nLine++;
|
||||
}
|
||||
zIn++;
|
||||
}
|
||||
/* Delimit the PHP chunk */
|
||||
sToken.nLine = nLine;
|
||||
zCur = zIn;
|
||||
while((sxu32)(zEnd - zIn) >= sCtag.nByte) {
|
||||
const char *zPtr;
|
||||
if(SyMemcmp(zIn, sCtag.zString, sCtag.nByte) == 0 && iNest < 1) {
|
||||
break;
|
||||
}
|
||||
for(;;) {
|
||||
if(zIn[0] != '/' || (zIn[1] != '*' && zIn[1] != '/') /* && sCtag.nByte >= 2 */) {
|
||||
break;
|
||||
}
|
||||
zIn += 2;
|
||||
if(zIn[-1] == '/') {
|
||||
/* Inline comment */
|
||||
while(zIn < zEnd && zIn[0] != '\n') {
|
||||
zIn++;
|
||||
}
|
||||
if(zIn >= zEnd) {
|
||||
zIn--;
|
||||
}
|
||||
} else {
|
||||
/* Block comment */
|
||||
while((sxu32)(zEnd - zIn) >= sizeof("*/") - 1) {
|
||||
if(zIn[0] == '*' && zIn[1] == '/') {
|
||||
zIn += 2;
|
||||
break;
|
||||
}
|
||||
if(zIn[0] == '\n') {
|
||||
nLine++;
|
||||
}
|
||||
zIn++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(zIn[0] == '\n') {
|
||||
nLine++;
|
||||
if(iNest > 0) {
|
||||
zIn++;
|
||||
while(zIn < zEnd && (unsigned char)zIn[0] < 0xc0 && SyisSpace(zIn[0]) && zIn[0] != '\n') {
|
||||
zIn++;
|
||||
}
|
||||
zPtr = zIn;
|
||||
while(zIn < zEnd) {
|
||||
if((unsigned char)zIn[0] >= 0xc0) {
|
||||
/* UTF-8 stream */
|
||||
zIn++;
|
||||
SX_JMP_UTF8(zIn, zEnd);
|
||||
} else if(!SyisAlphaNum(zIn[0]) && zIn[0] != '_') {
|
||||
break;
|
||||
} else {
|
||||
zIn++;
|
||||
}
|
||||
}
|
||||
if((sxu32)(zIn - zPtr) == sDoc.nByte && SyMemcmp(sDoc.zString, zPtr, sDoc.nByte) == 0) {
|
||||
iNest = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else if((sxu32)(zEnd - zIn) >= sizeof("<<<") && zIn[0] == '<' && zIn[1] == '<' && zIn[2] == '<' && iNest < 1) {
|
||||
zIn += sizeof("<<<") - 1;
|
||||
while(zIn < zEnd && (unsigned char)zIn[0] < 0xc0 && SyisSpace(zIn[0]) && zIn[0] != '\n') {
|
||||
zIn++;
|
||||
}
|
||||
if(zIn[0] == '"' || zIn[0] == '\'') {
|
||||
zIn++;
|
||||
}
|
||||
zPtr = zIn;
|
||||
while(zIn < zEnd) {
|
||||
if((unsigned char)zIn[0] >= 0xc0) {
|
||||
/* UTF-8 stream */
|
||||
zIn++;
|
||||
SX_JMP_UTF8(zIn, zEnd);
|
||||
} else if(!SyisAlphaNum(zIn[0]) && zIn[0] != '_') {
|
||||
break;
|
||||
} else {
|
||||
zIn++;
|
||||
}
|
||||
}
|
||||
SyStringInitFromBuf(&sDoc, zPtr, zIn - zPtr);
|
||||
SyStringFullTrim(&sDoc);
|
||||
if(sDoc.nByte > 0) {
|
||||
iNest++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
zIn++;
|
||||
if(zIn >= zEnd) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if((sxu32)(zEnd - zIn) < sCtag.nByte) {
|
||||
zIn = zEnd;
|
||||
}
|
||||
if(zCur < zIn) {
|
||||
/* Save the PHP chunk for later processing */
|
||||
sToken.nType = PH7_TOKEN_PHP;
|
||||
SyStringInitFromBuf(&sToken.sData, zCur, zIn - zCur);
|
||||
SyStringRightTrim(&sToken.sData); /* Trim trailing white spaces */
|
||||
rc = SySetPut(&(*pOut), (const void *)&sToken);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
if(zIn < zEnd) {
|
||||
/* Jump the trailing closing tag */
|
||||
zIn += sCtag.nByte;
|
||||
}
|
||||
} /* For(;;) */
|
||||
return SXRET_OK;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,387 @@
|
|||
/**
|
||||
* @PROJECT PH7 Engine for the AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE engine/lib/dataset.c
|
||||
* @DESCRIPTION Hash maps and dataset storages for the PH7 Engine
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#include "ph7int.h"
|
||||
|
||||
PH7_PRIVATE sxi32 SySetInit(SySet *pSet, SyMemBackend *pAllocator, sxu32 ElemSize) {
|
||||
pSet->nSize = 0 ;
|
||||
pSet->nUsed = 0;
|
||||
pSet->nCursor = 0;
|
||||
pSet->eSize = ElemSize;
|
||||
pSet->pAllocator = pAllocator;
|
||||
pSet->pBase = 0;
|
||||
pSet->pUserData = 0;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SySetPut(SySet *pSet, const void *pItem) {
|
||||
unsigned char *zbase;
|
||||
if(pSet->nUsed >= pSet->nSize) {
|
||||
void *pNew;
|
||||
if(pSet->pAllocator == 0) {
|
||||
return SXERR_LOCKED;
|
||||
}
|
||||
if(pSet->nSize <= 0) {
|
||||
pSet->nSize = 4;
|
||||
}
|
||||
pNew = SyMemBackendRealloc(pSet->pAllocator, pSet->pBase, pSet->eSize * pSet->nSize * 2);
|
||||
if(pNew == 0) {
|
||||
return SXERR_MEM;
|
||||
}
|
||||
pSet->pBase = pNew;
|
||||
pSet->nSize <<= 1;
|
||||
}
|
||||
zbase = (unsigned char *)pSet->pBase;
|
||||
SX_MACRO_FAST_MEMCPY(pItem, &zbase[pSet->nUsed * pSet->eSize], pSet->eSize);
|
||||
pSet->nUsed++;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SySetAlloc(SySet *pSet, sxi32 nItem) {
|
||||
if(pSet->nSize > 0) {
|
||||
return SXERR_LOCKED;
|
||||
}
|
||||
if(nItem < 8) {
|
||||
nItem = 8;
|
||||
}
|
||||
pSet->pBase = SyMemBackendAlloc(pSet->pAllocator, pSet->eSize * nItem);
|
||||
if(pSet->pBase == 0) {
|
||||
return SXERR_MEM;
|
||||
}
|
||||
pSet->nSize = nItem;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SySetReset(SySet *pSet) {
|
||||
pSet->nUsed = 0;
|
||||
pSet->nCursor = 0;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SySetResetCursor(SySet *pSet) {
|
||||
pSet->nCursor = 0;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SySetGetNextEntry(SySet *pSet, void **ppEntry) {
|
||||
register unsigned char *zSrc;
|
||||
if(pSet->nCursor >= pSet->nUsed) {
|
||||
/* Reset cursor */
|
||||
pSet->nCursor = 0;
|
||||
return SXERR_EOF;
|
||||
}
|
||||
zSrc = (unsigned char *)SySetBasePtr(pSet);
|
||||
if(ppEntry) {
|
||||
*ppEntry = (void *)&zSrc[pSet->nCursor * pSet->eSize];
|
||||
}
|
||||
pSet->nCursor++;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE void *SySetPeekCurrentEntry(SySet *pSet) {
|
||||
register unsigned char *zSrc;
|
||||
if(pSet->nCursor >= pSet->nUsed) {
|
||||
return 0;
|
||||
}
|
||||
zSrc = (unsigned char *)SySetBasePtr(pSet);
|
||||
return (void *)&zSrc[pSet->nCursor * pSet->eSize];
|
||||
}
|
||||
PH7_PRIVATE sxi32 SySetTruncate(SySet *pSet, sxu32 nNewSize) {
|
||||
if(nNewSize < pSet->nUsed) {
|
||||
pSet->nUsed = nNewSize;
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SySetRelease(SySet *pSet) {
|
||||
sxi32 rc = SXRET_OK;
|
||||
if(pSet->pAllocator && pSet->pBase) {
|
||||
rc = SyMemBackendFree(pSet->pAllocator, pSet->pBase);
|
||||
}
|
||||
pSet->pBase = 0;
|
||||
pSet->nUsed = 0;
|
||||
pSet->nCursor = 0;
|
||||
return rc;
|
||||
}
|
||||
PH7_PRIVATE void *SySetPeek(SySet *pSet) {
|
||||
const char *zBase;
|
||||
if(pSet->nUsed <= 0) {
|
||||
return 0;
|
||||
}
|
||||
zBase = (const char *)pSet->pBase;
|
||||
return (void *)&zBase[(pSet->nUsed - 1) * pSet->eSize];
|
||||
}
|
||||
PH7_PRIVATE void *SySetPop(SySet *pSet) {
|
||||
const char *zBase;
|
||||
void *pData;
|
||||
if(pSet->nUsed <= 0) {
|
||||
return 0;
|
||||
}
|
||||
zBase = (const char *)pSet->pBase;
|
||||
pSet->nUsed--;
|
||||
pData = (void *)&zBase[pSet->nUsed * pSet->eSize];
|
||||
return pData;
|
||||
}
|
||||
PH7_PRIVATE void *SySetAt(SySet *pSet, sxu32 nIdx) {
|
||||
const char *zBase;
|
||||
if(nIdx >= pSet->nUsed) {
|
||||
/* Out of range */
|
||||
return 0;
|
||||
}
|
||||
zBase = (const char *)pSet->pBase;
|
||||
return (void *)&zBase[nIdx * pSet->eSize];
|
||||
}
|
||||
/* Private hash entry */
|
||||
struct SyHashEntry_Pr {
|
||||
const void *pKey; /* Hash key */
|
||||
sxu32 nKeyLen; /* Key length */
|
||||
void *pUserData; /* User private data */
|
||||
/* Private fields */
|
||||
sxu32 nHash;
|
||||
SyHash *pHash;
|
||||
SyHashEntry_Pr *pNext, *pPrev; /* Next and previous entry in the list */
|
||||
SyHashEntry_Pr *pNextCollide, *pPrevCollide; /* Collision list */
|
||||
};
|
||||
#define INVALID_HASH(H) ((H)->apBucket == 0)
|
||||
/* Forward declarartion */
|
||||
sxu32 SyBinHash(const void *pSrc, sxu32 nLen);
|
||||
PH7_PRIVATE sxi32 SyHashInit(SyHash *pHash, SyMemBackend *pAllocator, ProcHash xHash, ProcCmp xCmp) {
|
||||
SyHashEntry_Pr **apNew;
|
||||
if(pHash == 0) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
/* Allocate a new table */
|
||||
apNew = (SyHashEntry_Pr **)SyMemBackendAlloc(&(*pAllocator), sizeof(SyHashEntry_Pr *) * SXHASH_BUCKET_SIZE);
|
||||
if(apNew == 0) {
|
||||
return SXERR_MEM;
|
||||
}
|
||||
SyZero((void *)apNew, sizeof(SyHashEntry_Pr *) * SXHASH_BUCKET_SIZE);
|
||||
pHash->pAllocator = &(*pAllocator);
|
||||
pHash->xHash = xHash ? xHash : SyBinHash;
|
||||
pHash->xCmp = xCmp ? xCmp : SyMemcmp;
|
||||
pHash->pCurrent = pHash->pList = 0;
|
||||
pHash->nEntry = 0;
|
||||
pHash->apBucket = apNew;
|
||||
pHash->nBucketSize = SXHASH_BUCKET_SIZE;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyHashRelease(SyHash *pHash) {
|
||||
SyHashEntry_Pr *pEntry, *pNext;
|
||||
if(INVALID_HASH(pHash)) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
pEntry = pHash->pList;
|
||||
for(;;) {
|
||||
if(pHash->nEntry == 0) {
|
||||
break;
|
||||
}
|
||||
pNext = pEntry->pNext;
|
||||
SyMemBackendPoolFree(pHash->pAllocator, pEntry);
|
||||
pEntry = pNext;
|
||||
pHash->nEntry--;
|
||||
}
|
||||
if(pHash->apBucket) {
|
||||
SyMemBackendFree(pHash->pAllocator, (void *)pHash->apBucket);
|
||||
}
|
||||
pHash->apBucket = 0;
|
||||
pHash->nBucketSize = 0;
|
||||
pHash->pAllocator = 0;
|
||||
return SXRET_OK;
|
||||
}
|
||||
static SyHashEntry_Pr *HashGetEntry(SyHash *pHash, const void *pKey, sxu32 nKeyLen) {
|
||||
SyHashEntry_Pr *pEntry;
|
||||
sxu32 nHash;
|
||||
nHash = pHash->xHash(pKey, nKeyLen);
|
||||
pEntry = pHash->apBucket[nHash & (pHash->nBucketSize - 1)];
|
||||
for(;;) {
|
||||
if(pEntry == 0) {
|
||||
break;
|
||||
}
|
||||
if(pEntry->nHash == nHash && pEntry->nKeyLen == nKeyLen &&
|
||||
pHash->xCmp(pEntry->pKey, pKey, nKeyLen) == 0) {
|
||||
return pEntry;
|
||||
}
|
||||
pEntry = pEntry->pNextCollide;
|
||||
}
|
||||
/* Entry not found */
|
||||
return 0;
|
||||
}
|
||||
PH7_PRIVATE SyHashEntry *SyHashGet(SyHash *pHash, const void *pKey, sxu32 nKeyLen) {
|
||||
SyHashEntry_Pr *pEntry;
|
||||
if(INVALID_HASH(pHash)) {
|
||||
return 0;
|
||||
}
|
||||
if(pHash->nEntry < 1 || nKeyLen < 1) {
|
||||
/* Don't bother hashing, return immediately */
|
||||
return 0;
|
||||
}
|
||||
pEntry = HashGetEntry(&(*pHash), pKey, nKeyLen);
|
||||
if(pEntry == 0) {
|
||||
return 0;
|
||||
}
|
||||
return (SyHashEntry *)pEntry;
|
||||
}
|
||||
static sxi32 HashDeleteEntry(SyHash *pHash, SyHashEntry_Pr *pEntry, void **ppUserData) {
|
||||
sxi32 rc;
|
||||
if(pEntry->pPrevCollide == 0) {
|
||||
pHash->apBucket[pEntry->nHash & (pHash->nBucketSize - 1)] = pEntry->pNextCollide;
|
||||
} else {
|
||||
pEntry->pPrevCollide->pNextCollide = pEntry->pNextCollide;
|
||||
}
|
||||
if(pEntry->pNextCollide) {
|
||||
pEntry->pNextCollide->pPrevCollide = pEntry->pPrevCollide;
|
||||
}
|
||||
MACRO_LD_REMOVE(pHash->pList, pEntry);
|
||||
pHash->nEntry--;
|
||||
if(ppUserData) {
|
||||
/* Write a pointer to the user data */
|
||||
*ppUserData = pEntry->pUserData;
|
||||
}
|
||||
/* Release the entry */
|
||||
rc = SyMemBackendPoolFree(pHash->pAllocator, pEntry);
|
||||
return rc;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyHashDeleteEntry(SyHash *pHash, const void *pKey, sxu32 nKeyLen, void **ppUserData) {
|
||||
SyHashEntry_Pr *pEntry;
|
||||
sxi32 rc;
|
||||
if(INVALID_HASH(pHash)) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
pEntry = HashGetEntry(&(*pHash), pKey, nKeyLen);
|
||||
if(pEntry == 0) {
|
||||
return SXERR_NOTFOUND;
|
||||
}
|
||||
rc = HashDeleteEntry(&(*pHash), pEntry, ppUserData);
|
||||
return rc;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyHashDeleteEntry2(SyHashEntry *pEntry) {
|
||||
SyHashEntry_Pr *pPtr = (SyHashEntry_Pr *)pEntry;
|
||||
sxi32 rc;
|
||||
if(pPtr == 0 || INVALID_HASH(pPtr->pHash)) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
rc = HashDeleteEntry(pPtr->pHash, pPtr, 0);
|
||||
return rc;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyHashResetLoopCursor(SyHash *pHash) {
|
||||
if(INVALID_HASH(pHash)) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
pHash->pCurrent = pHash->pList;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE SyHashEntry *SyHashGetNextEntry(SyHash *pHash) {
|
||||
SyHashEntry_Pr *pEntry;
|
||||
if(INVALID_HASH(pHash)) {
|
||||
return 0;
|
||||
}
|
||||
if(pHash->pCurrent == 0 || pHash->nEntry <= 0) {
|
||||
pHash->pCurrent = pHash->pList;
|
||||
return 0;
|
||||
}
|
||||
pEntry = pHash->pCurrent;
|
||||
/* Advance the cursor */
|
||||
pHash->pCurrent = pEntry->pNext;
|
||||
/* Return the current entry */
|
||||
return (SyHashEntry *)pEntry;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyHashForEach(SyHash *pHash, sxi32(*xStep)(SyHashEntry *, void *), void *pUserData) {
|
||||
SyHashEntry_Pr *pEntry;
|
||||
sxi32 rc;
|
||||
sxu32 n;
|
||||
if(INVALID_HASH(pHash) || xStep == 0) {
|
||||
return 0;
|
||||
}
|
||||
pEntry = pHash->pList;
|
||||
for(n = 0 ; n < pHash->nEntry ; n++) {
|
||||
/* Invoke the callback */
|
||||
rc = xStep((SyHashEntry *)pEntry, pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
/* Point to the next entry */
|
||||
pEntry = pEntry->pNext;
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
static sxi32 HashGrowTable(SyHash *pHash) {
|
||||
sxu32 nNewSize = pHash->nBucketSize * 2;
|
||||
SyHashEntry_Pr *pEntry;
|
||||
SyHashEntry_Pr **apNew;
|
||||
sxu32 n, iBucket;
|
||||
/* Allocate a new larger table */
|
||||
apNew = (SyHashEntry_Pr **)SyMemBackendAlloc(pHash->pAllocator, nNewSize * sizeof(SyHashEntry_Pr *));
|
||||
if(apNew == 0) {
|
||||
/* Not so fatal,simply a performance hit */
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Zero the new table */
|
||||
SyZero((void *)apNew, nNewSize * sizeof(SyHashEntry_Pr *));
|
||||
/* Rehash all entries */
|
||||
for(n = 0, pEntry = pHash->pList; n < pHash->nEntry ; n++) {
|
||||
pEntry->pNextCollide = pEntry->pPrevCollide = 0;
|
||||
/* Install in the new bucket */
|
||||
iBucket = pEntry->nHash & (nNewSize - 1);
|
||||
pEntry->pNextCollide = apNew[iBucket];
|
||||
if(apNew[iBucket] != 0) {
|
||||
apNew[iBucket]->pPrevCollide = pEntry;
|
||||
}
|
||||
apNew[iBucket] = pEntry;
|
||||
/* Point to the next entry */
|
||||
pEntry = pEntry->pNext;
|
||||
}
|
||||
/* Release the old table and reflect the change */
|
||||
SyMemBackendFree(pHash->pAllocator, (void *)pHash->apBucket);
|
||||
pHash->apBucket = apNew;
|
||||
pHash->nBucketSize = nNewSize;
|
||||
return SXRET_OK;
|
||||
}
|
||||
static sxi32 HashInsert(SyHash *pHash, SyHashEntry_Pr *pEntry) {
|
||||
sxu32 iBucket = pEntry->nHash & (pHash->nBucketSize - 1);
|
||||
/* Insert the entry in its corresponding bucket */
|
||||
pEntry->pNextCollide = pHash->apBucket[iBucket];
|
||||
if(pHash->apBucket[iBucket] != 0) {
|
||||
pHash->apBucket[iBucket]->pPrevCollide = pEntry;
|
||||
}
|
||||
pHash->apBucket[iBucket] = pEntry;
|
||||
/* Link to the entry list */
|
||||
MACRO_LD_PUSH(pHash->pList, pEntry);
|
||||
if(pHash->nEntry == 0) {
|
||||
pHash->pCurrent = pHash->pList;
|
||||
}
|
||||
pHash->nEntry++;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyHashInsert(SyHash *pHash, const void *pKey, sxu32 nKeyLen, void *pUserData) {
|
||||
SyHashEntry_Pr *pEntry;
|
||||
sxi32 rc;
|
||||
if(INVALID_HASH(pHash) || pKey == 0) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
if(pHash->nEntry >= pHash->nBucketSize * SXHASH_FILL_FACTOR) {
|
||||
rc = HashGrowTable(&(*pHash));
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
/* Allocate a new hash entry */
|
||||
pEntry = (SyHashEntry_Pr *)SyMemBackendPoolAlloc(pHash->pAllocator, sizeof(SyHashEntry_Pr));
|
||||
if(pEntry == 0) {
|
||||
return SXERR_MEM;
|
||||
}
|
||||
/* Zero the entry */
|
||||
SyZero(pEntry, sizeof(SyHashEntry_Pr));
|
||||
pEntry->pHash = pHash;
|
||||
pEntry->pKey = pKey;
|
||||
pEntry->nKeyLen = nKeyLen;
|
||||
pEntry->pUserData = pUserData;
|
||||
pEntry->nHash = pHash->xHash(pEntry->pKey, pEntry->nKeyLen);
|
||||
/* Finally insert the entry in its corresponding bucket */
|
||||
rc = HashInsert(&(*pHash), pEntry);
|
||||
return rc;
|
||||
}
|
||||
PH7_PRIVATE SyHashEntry *SyHashLastEntry(SyHash *pHash) {
|
||||
if(INVALID_HASH(pHash)) {
|
||||
return 0;
|
||||
}
|
||||
/* Last inserted entry */
|
||||
return (SyHashEntry *)pHash->pList;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* @PROJECT PH7 Engine for the AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE engine/lib/date.c
|
||||
* @DESCRIPTION Date manipulation support for the PH7 Engine
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#include "ph7int.h"
|
||||
|
||||
static const char *zEngDay[] = {
|
||||
"Sunday", "Monday", "Tuesday", "Wednesday",
|
||||
"Thursday", "Friday", "Saturday"
|
||||
};
|
||||
static const char *zEngMonth[] = {
|
||||
"January", "February", "March", "April",
|
||||
"May", "June", "July", "August",
|
||||
"September", "October", "November", "December"
|
||||
};
|
||||
static const char *GetDay(sxi32 i) {
|
||||
return zEngDay[ i % 7 ];
|
||||
}
|
||||
static const char *GetMonth(sxi32 i) {
|
||||
return zEngMonth[ i % 12 ];
|
||||
}
|
||||
PH7_PRIVATE const char *SyTimeGetDay(sxi32 iDay) {
|
||||
return GetDay(iDay);
|
||||
}
|
||||
PH7_PRIVATE const char *SyTimeGetMonth(sxi32 iMonth) {
|
||||
return GetMonth(iMonth);
|
||||
}
|
|
@ -0,0 +1,837 @@
|
|||
/**
|
||||
* @PROJECT PH7 Engine for the AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE engine/lib/hash.c
|
||||
* @DESCRIPTION Hashing algorithms for the PH7 Engine
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#include "ph7int.h"
|
||||
|
||||
sxu32 SyBinHash(const void *pSrc, sxu32 nLen) {
|
||||
register unsigned char *zIn = (unsigned char *)pSrc;
|
||||
unsigned char *zEnd;
|
||||
sxu32 nH = 5381;
|
||||
zEnd = &zIn[nLen];
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
break;
|
||||
}
|
||||
nH = nH * 33 + zIn[0] ;
|
||||
zIn++;
|
||||
}
|
||||
return nH;
|
||||
}
|
||||
PH7_PRIVATE sxu32 SyStrHash(const void *pSrc, sxu32 nLen) {
|
||||
register unsigned char *zIn = (unsigned char *)pSrc;
|
||||
unsigned char *zEnd;
|
||||
sxu32 nH = 5381;
|
||||
zEnd = &zIn[nLen];
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
break;
|
||||
}
|
||||
nH = nH * 33 + SyToLower(zIn[0]);
|
||||
zIn++;
|
||||
}
|
||||
return nH;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyBase64Encode(const char *zSrc, sxu32 nLen, ProcConsumer xConsumer, void *pUserData) {
|
||||
static const unsigned char zBase64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
unsigned char *zIn = (unsigned char *)zSrc;
|
||||
unsigned char z64[4];
|
||||
sxu32 i;
|
||||
sxi32 rc;
|
||||
if(SX_EMPTY_STR(zSrc) || xConsumer == 0) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
for(i = 0; i + 2 < nLen; i += 3) {
|
||||
z64[0] = zBase64[(zIn[i] >> 2) & 0x3F];
|
||||
z64[1] = zBase64[(((zIn[i] & 0x03) << 4) | (zIn[i + 1] >> 4)) & 0x3F];
|
||||
z64[2] = zBase64[(((zIn[i + 1] & 0x0F) << 2) | (zIn[i + 2] >> 6)) & 0x3F];
|
||||
z64[3] = zBase64[ zIn[i + 2] & 0x3F];
|
||||
rc = xConsumer((const void *)z64, sizeof(z64), pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
}
|
||||
if(i + 1 < nLen) {
|
||||
z64[0] = zBase64[(zIn[i] >> 2) & 0x3F];
|
||||
z64[1] = zBase64[(((zIn[i] & 0x03) << 4) | (zIn[i + 1] >> 4)) & 0x3F];
|
||||
z64[2] = zBase64[(zIn[i + 1] & 0x0F) << 2 ];
|
||||
z64[3] = '=';
|
||||
rc = xConsumer((const void *)z64, sizeof(z64), pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
} else if(i < nLen) {
|
||||
z64[0] = zBase64[(zIn[i] >> 2) & 0x3F];
|
||||
z64[1] = zBase64[(zIn[i] & 0x03) << 4];
|
||||
z64[2] = '=';
|
||||
z64[3] = '=';
|
||||
rc = xConsumer((const void *)z64, sizeof(z64), pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyBase64Decode(const char *zB64, sxu32 nLen, ProcConsumer xConsumer, void *pUserData) {
|
||||
static const sxu32 aBase64Trans[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4,
|
||||
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27,
|
||||
28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0,
|
||||
0, 0, 0
|
||||
};
|
||||
sxu32 n, w, x, y, z;
|
||||
sxi32 rc;
|
||||
unsigned char zOut[10];
|
||||
if(SX_EMPTY_STR(zB64) || xConsumer == 0) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
while(nLen > 0 && zB64[nLen - 1] == '=') {
|
||||
nLen--;
|
||||
}
|
||||
for(n = 0 ; n + 3 < nLen ; n += 4) {
|
||||
w = aBase64Trans[zB64[n] & 0x7F];
|
||||
x = aBase64Trans[zB64[n + 1] & 0x7F];
|
||||
y = aBase64Trans[zB64[n + 2] & 0x7F];
|
||||
z = aBase64Trans[zB64[n + 3] & 0x7F];
|
||||
zOut[0] = ((w << 2) & 0xFC) | ((x >> 4) & 0x03);
|
||||
zOut[1] = ((x << 4) & 0xF0) | ((y >> 2) & 0x0F);
|
||||
zOut[2] = ((y << 6) & 0xC0) | (z & 0x3F);
|
||||
rc = xConsumer((const void *)zOut, sizeof(unsigned char) * 3, pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
}
|
||||
if(n + 2 < nLen) {
|
||||
w = aBase64Trans[zB64[n] & 0x7F];
|
||||
x = aBase64Trans[zB64[n + 1] & 0x7F];
|
||||
y = aBase64Trans[zB64[n + 2] & 0x7F];
|
||||
zOut[0] = ((w << 2) & 0xFC) | ((x >> 4) & 0x03);
|
||||
zOut[1] = ((x << 4) & 0xF0) | ((y >> 2) & 0x0F);
|
||||
rc = xConsumer((const void *)zOut, sizeof(unsigned char) * 2, pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
} else if(n + 1 < nLen) {
|
||||
w = aBase64Trans[zB64[n] & 0x7F];
|
||||
x = aBase64Trans[zB64[n + 1] & 0x7F];
|
||||
zOut[0] = ((w << 2) & 0xFC) | ((x >> 4) & 0x03);
|
||||
rc = xConsumer((const void *)zOut, sizeof(unsigned char) * 1, pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
|
||||
#define SX_MD5_BINSZ 16
|
||||
#define SX_MD5_HEXSZ 32
|
||||
/*
|
||||
* Note: this code is harmless on little-endian machines.
|
||||
*/
|
||||
static void byteReverse(unsigned char *buf, unsigned longs) {
|
||||
sxu32 t;
|
||||
do {
|
||||
t = (sxu32)((unsigned)buf[3] << 8 | buf[2]) << 16 |
|
||||
((unsigned)buf[1] << 8 | buf[0]);
|
||||
*(sxu32 *)buf = t;
|
||||
buf += 4;
|
||||
} while(--longs);
|
||||
}
|
||||
/* The four core functions - F1 is optimized somewhat */
|
||||
|
||||
/* #define F1(x, y, z) (x & y | ~x & z) */
|
||||
#ifdef F1
|
||||
#undef F1
|
||||
#endif
|
||||
#ifdef F2
|
||||
#undef F2
|
||||
#endif
|
||||
#ifdef F3
|
||||
#undef F3
|
||||
#endif
|
||||
#ifdef F4
|
||||
#undef F4
|
||||
#endif
|
||||
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the MD5 algorithm.*/
|
||||
#define SX_MD5STEP(f, w, x, y, z, data, s) \
|
||||
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* reflect the addition of 16 longwords of new data.MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
static void MD5Transform(sxu32 buf[4], const sxu32 in[16]) {
|
||||
register sxu32 a, b, c, d;
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
SX_MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478, 7);
|
||||
SX_MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
|
||||
SX_MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);
|
||||
SX_MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
|
||||
SX_MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7);
|
||||
SX_MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
|
||||
SX_MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
|
||||
SX_MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
|
||||
SX_MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8, 7);
|
||||
SX_MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
|
||||
SX_MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
SX_MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
SX_MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
SX_MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
SX_MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
SX_MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
SX_MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562, 5);
|
||||
SX_MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340, 9);
|
||||
SX_MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
SX_MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
|
||||
SX_MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d, 5);
|
||||
SX_MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
SX_MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
SX_MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
|
||||
SX_MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5);
|
||||
SX_MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
SX_MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
|
||||
SX_MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
|
||||
SX_MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
SX_MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9);
|
||||
SX_MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
|
||||
SX_MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
SX_MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942, 4);
|
||||
SX_MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
|
||||
SX_MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
SX_MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
SX_MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44, 4);
|
||||
SX_MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
|
||||
SX_MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
|
||||
SX_MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
SX_MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
SX_MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
|
||||
SX_MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
|
||||
SX_MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
|
||||
SX_MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4);
|
||||
SX_MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
SX_MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
SX_MD5STEP(F3, b, c, d, a, in[ 2] + 0xc4ac5665, 23);
|
||||
SX_MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244, 6);
|
||||
SX_MD5STEP(F4, d, a, b, c, in[ 7] + 0x432aff97, 10);
|
||||
SX_MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
SX_MD5STEP(F4, b, c, d, a, in[ 5] + 0xfc93a039, 21);
|
||||
SX_MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
SX_MD5STEP(F4, d, a, b, c, in[ 3] + 0x8f0ccc92, 10);
|
||||
SX_MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
SX_MD5STEP(F4, b, c, d, a, in[ 1] + 0x85845dd1, 21);
|
||||
SX_MD5STEP(F4, a, b, c, d, in[ 8] + 0x6fa87e4f, 6);
|
||||
SX_MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
SX_MD5STEP(F4, c, d, a, b, in[ 6] + 0xa3014314, 15);
|
||||
SX_MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
SX_MD5STEP(F4, a, b, c, d, in[ 4] + 0xf7537e82, 6);
|
||||
SX_MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
SX_MD5STEP(F4, c, d, a, b, in[ 2] + 0x2ad7d2bb, 15);
|
||||
SX_MD5STEP(F4, b, c, d, a, in[ 9] + 0xeb86d391, 21);
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
/*
|
||||
* Update context to reflect the concatenation of another buffer full
|
||||
* of bytes.
|
||||
*/
|
||||
PH7_PRIVATE void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len) {
|
||||
sxu32 t;
|
||||
/* Update bitcount */
|
||||
t = ctx->bits[0];
|
||||
if((ctx->bits[0] = t + ((sxu32)len << 3)) < t) {
|
||||
ctx->bits[1]++; /* Carry from low to high */
|
||||
}
|
||||
ctx->bits[1] += len >> 29;
|
||||
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
|
||||
/* Handle any leading odd-sized chunks */
|
||||
if(t) {
|
||||
unsigned char *p = (unsigned char *)ctx->in + t;
|
||||
t = 64 - t;
|
||||
if(len < t) {
|
||||
SyMemcpy(buf, p, len);
|
||||
return;
|
||||
}
|
||||
SyMemcpy(buf, p, t);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (sxu32 *)ctx->in);
|
||||
buf += t;
|
||||
len -= t;
|
||||
}
|
||||
/* Process data in 64-byte chunks */
|
||||
while(len >= 64) {
|
||||
SyMemcpy(buf, ctx->in, 64);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (sxu32 *)ctx->in);
|
||||
buf += 64;
|
||||
len -= 64;
|
||||
}
|
||||
/* Handle any remaining bytes of data.*/
|
||||
SyMemcpy(buf, ctx->in, len);
|
||||
}
|
||||
/*
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
PH7_PRIVATE void MD5Final(unsigned char digest[16], MD5Context *ctx) {
|
||||
unsigned count;
|
||||
unsigned char *p;
|
||||
/* Compute number of bytes mod 64 */
|
||||
count = (ctx->bits[0] >> 3) & 0x3F;
|
||||
/* Set the first char of padding to 0x80.This is safe since there is
|
||||
always at least one byte free */
|
||||
p = ctx->in + count;
|
||||
*p++ = 0x80;
|
||||
/* Bytes of padding needed to make 64 bytes */
|
||||
count = 64 - 1 - count;
|
||||
/* Pad out to 56 mod 64 */
|
||||
if(count < 8) {
|
||||
/* Two lots of padding: Pad the first block to 64 bytes */
|
||||
SyZero(p, count);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (sxu32 *)ctx->in);
|
||||
/* Now fill the next block with 56 bytes */
|
||||
SyZero(ctx->in, 56);
|
||||
} else {
|
||||
/* Pad block to 56 bytes */
|
||||
SyZero(p, count - 8);
|
||||
}
|
||||
byteReverse(ctx->in, 14);
|
||||
/* Append length in bits and transform */
|
||||
((sxu32 *)ctx->in)[ 14 ] = ctx->bits[0];
|
||||
((sxu32 *)ctx->in)[ 15 ] = ctx->bits[1];
|
||||
MD5Transform(ctx->buf, (sxu32 *)ctx->in);
|
||||
byteReverse((unsigned char *)ctx->buf, 4);
|
||||
SyMemcpy(ctx->buf, digest, 0x10);
|
||||
SyZero(ctx, sizeof(ctx)); /* In case it's sensitive */
|
||||
}
|
||||
#undef F1
|
||||
#undef F2
|
||||
#undef F3
|
||||
#undef F4
|
||||
PH7_PRIVATE sxi32 MD5Init(MD5Context *pCtx) {
|
||||
pCtx->buf[0] = 0x67452301;
|
||||
pCtx->buf[1] = 0xefcdab89;
|
||||
pCtx->buf[2] = 0x98badcfe;
|
||||
pCtx->buf[3] = 0x10325476;
|
||||
pCtx->bits[0] = 0;
|
||||
pCtx->bits[1] = 0;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyMD5Compute(const void *pIn, sxu32 nLen, unsigned char zDigest[16]) {
|
||||
MD5Context sCtx;
|
||||
MD5Init(&sCtx);
|
||||
MD5Update(&sCtx, (const unsigned char *)pIn, nLen);
|
||||
MD5Final(zDigest, &sCtx);
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* SHA-1 in C
|
||||
* By Steve Reid <steve@edmweb.com>
|
||||
* Status: Public Domain
|
||||
*/
|
||||
/*
|
||||
* blk0() and blk() perform the initial expand.
|
||||
* I got the idea of expanding during the round function from SSLeay
|
||||
*
|
||||
* blk0le() for little-endian and blk0be() for big-endian.
|
||||
*/
|
||||
#if __GNUC__ && (defined(__i386__) || defined(__x86_64__))
|
||||
/*
|
||||
* GCC by itself only generates left rotates. Use right rotates if
|
||||
* possible to be kinder to dinky implementations with iterative rotate
|
||||
* instructions.
|
||||
*/
|
||||
#define SHA_ROT(op, x, k) \
|
||||
(__extension__({ unsigned int y; __asm__(op " %1,%0" : "=r" (y) : "I" (k), "0" (x)); y; }))
|
||||
#define rol(x,k) SHA_ROT("roll", x, k)
|
||||
#define ror(x,k) SHA_ROT("rorl", x, k)
|
||||
|
||||
#else
|
||||
/* Generic C equivalent */
|
||||
#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
|
||||
#define rol(x,k) SHA_ROT(x,k,32-(k))
|
||||
#define ror(x,k) SHA_ROT(x,32-(k),k)
|
||||
#endif
|
||||
|
||||
#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
|
||||
|(rol(block[i],8)&0x00FF00FF))
|
||||
#define blk0be(i) block[i]
|
||||
#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
|
||||
^block[(i+2)&15]^block[i&15],1))
|
||||
|
||||
/*
|
||||
* (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
|
||||
*
|
||||
* Rl0() for little-endian and Rb0() for big-endian. Endianness is
|
||||
* determined at run-time.
|
||||
*/
|
||||
#define Rl0(v,w,x,y,z,i) \
|
||||
z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
|
||||
#define Rb0(v,w,x,y,z,i) \
|
||||
z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2);
|
||||
#define R1(v,w,x,y,z,i) \
|
||||
z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2);
|
||||
#define R2(v,w,x,y,z,i) \
|
||||
z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2);
|
||||
#define R3(v,w,x,y,z,i) \
|
||||
z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2);
|
||||
#define R4(v,w,x,y,z,i) \
|
||||
z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2);
|
||||
|
||||
/*
|
||||
* Hash a single 512-bit block. This is the core of the algorithm.
|
||||
*/
|
||||
#define a qq[0]
|
||||
#define b qq[1]
|
||||
#define c qq[2]
|
||||
#define d qq[3]
|
||||
#define e qq[4]
|
||||
|
||||
static void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]) {
|
||||
unsigned int qq[5]; /* a, b, c, d, e; */
|
||||
static int one = 1;
|
||||
unsigned int block[16];
|
||||
SyMemcpy(buffer, (void *)block, 64);
|
||||
SyMemcpy(state, qq, 5 * sizeof(unsigned int));
|
||||
/* Copy context->state[] to working vars */
|
||||
/*
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
e = state[4];
|
||||
*/
|
||||
/* 4 rounds of 20 operations each. Loop unrolled. */
|
||||
if(1 == *(unsigned char *)&one) {
|
||||
Rl0(a, b, c, d, e, 0);
|
||||
Rl0(e, a, b, c, d, 1);
|
||||
Rl0(d, e, a, b, c, 2);
|
||||
Rl0(c, d, e, a, b, 3);
|
||||
Rl0(b, c, d, e, a, 4);
|
||||
Rl0(a, b, c, d, e, 5);
|
||||
Rl0(e, a, b, c, d, 6);
|
||||
Rl0(d, e, a, b, c, 7);
|
||||
Rl0(c, d, e, a, b, 8);
|
||||
Rl0(b, c, d, e, a, 9);
|
||||
Rl0(a, b, c, d, e, 10);
|
||||
Rl0(e, a, b, c, d, 11);
|
||||
Rl0(d, e, a, b, c, 12);
|
||||
Rl0(c, d, e, a, b, 13);
|
||||
Rl0(b, c, d, e, a, 14);
|
||||
Rl0(a, b, c, d, e, 15);
|
||||
} else {
|
||||
Rb0(a, b, c, d, e, 0);
|
||||
Rb0(e, a, b, c, d, 1);
|
||||
Rb0(d, e, a, b, c, 2);
|
||||
Rb0(c, d, e, a, b, 3);
|
||||
Rb0(b, c, d, e, a, 4);
|
||||
Rb0(a, b, c, d, e, 5);
|
||||
Rb0(e, a, b, c, d, 6);
|
||||
Rb0(d, e, a, b, c, 7);
|
||||
Rb0(c, d, e, a, b, 8);
|
||||
Rb0(b, c, d, e, a, 9);
|
||||
Rb0(a, b, c, d, e, 10);
|
||||
Rb0(e, a, b, c, d, 11);
|
||||
Rb0(d, e, a, b, c, 12);
|
||||
Rb0(c, d, e, a, b, 13);
|
||||
Rb0(b, c, d, e, a, 14);
|
||||
Rb0(a, b, c, d, e, 15);
|
||||
}
|
||||
R1(e, a, b, c, d, 16);
|
||||
R1(d, e, a, b, c, 17);
|
||||
R1(c, d, e, a, b, 18);
|
||||
R1(b, c, d, e, a, 19);
|
||||
R2(a, b, c, d, e, 20);
|
||||
R2(e, a, b, c, d, 21);
|
||||
R2(d, e, a, b, c, 22);
|
||||
R2(c, d, e, a, b, 23);
|
||||
R2(b, c, d, e, a, 24);
|
||||
R2(a, b, c, d, e, 25);
|
||||
R2(e, a, b, c, d, 26);
|
||||
R2(d, e, a, b, c, 27);
|
||||
R2(c, d, e, a, b, 28);
|
||||
R2(b, c, d, e, a, 29);
|
||||
R2(a, b, c, d, e, 30);
|
||||
R2(e, a, b, c, d, 31);
|
||||
R2(d, e, a, b, c, 32);
|
||||
R2(c, d, e, a, b, 33);
|
||||
R2(b, c, d, e, a, 34);
|
||||
R2(a, b, c, d, e, 35);
|
||||
R2(e, a, b, c, d, 36);
|
||||
R2(d, e, a, b, c, 37);
|
||||
R2(c, d, e, a, b, 38);
|
||||
R2(b, c, d, e, a, 39);
|
||||
R3(a, b, c, d, e, 40);
|
||||
R3(e, a, b, c, d, 41);
|
||||
R3(d, e, a, b, c, 42);
|
||||
R3(c, d, e, a, b, 43);
|
||||
R3(b, c, d, e, a, 44);
|
||||
R3(a, b, c, d, e, 45);
|
||||
R3(e, a, b, c, d, 46);
|
||||
R3(d, e, a, b, c, 47);
|
||||
R3(c, d, e, a, b, 48);
|
||||
R3(b, c, d, e, a, 49);
|
||||
R3(a, b, c, d, e, 50);
|
||||
R3(e, a, b, c, d, 51);
|
||||
R3(d, e, a, b, c, 52);
|
||||
R3(c, d, e, a, b, 53);
|
||||
R3(b, c, d, e, a, 54);
|
||||
R3(a, b, c, d, e, 55);
|
||||
R3(e, a, b, c, d, 56);
|
||||
R3(d, e, a, b, c, 57);
|
||||
R3(c, d, e, a, b, 58);
|
||||
R3(b, c, d, e, a, 59);
|
||||
R4(a, b, c, d, e, 60);
|
||||
R4(e, a, b, c, d, 61);
|
||||
R4(d, e, a, b, c, 62);
|
||||
R4(c, d, e, a, b, 63);
|
||||
R4(b, c, d, e, a, 64);
|
||||
R4(a, b, c, d, e, 65);
|
||||
R4(e, a, b, c, d, 66);
|
||||
R4(d, e, a, b, c, 67);
|
||||
R4(c, d, e, a, b, 68);
|
||||
R4(b, c, d, e, a, 69);
|
||||
R4(a, b, c, d, e, 70);
|
||||
R4(e, a, b, c, d, 71);
|
||||
R4(d, e, a, b, c, 72);
|
||||
R4(c, d, e, a, b, 73);
|
||||
R4(b, c, d, e, a, 74);
|
||||
R4(a, b, c, d, e, 75);
|
||||
R4(e, a, b, c, d, 76);
|
||||
R4(d, e, a, b, c, 77);
|
||||
R4(c, d, e, a, b, 78);
|
||||
R4(b, c, d, e, a, 79);
|
||||
/* Add the working vars back into context.state[] */
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
state[4] += e;
|
||||
}
|
||||
#undef a
|
||||
#undef b
|
||||
#undef c
|
||||
#undef d
|
||||
#undef e
|
||||
/*
|
||||
* SHA1Init - Initialize new context
|
||||
*/
|
||||
PH7_PRIVATE void SHA1Init(SHA1Context *context) {
|
||||
/* SHA1 initialization constants */
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xEFCDAB89;
|
||||
context->state[2] = 0x98BADCFE;
|
||||
context->state[3] = 0x10325476;
|
||||
context->state[4] = 0xC3D2E1F0;
|
||||
context->count[0] = context->count[1] = 0;
|
||||
}
|
||||
/*
|
||||
* Run your data through this.
|
||||
*/
|
||||
PH7_PRIVATE void SHA1Update(SHA1Context *context, const unsigned char *data, unsigned int len) {
|
||||
unsigned int i, j;
|
||||
j = context->count[0];
|
||||
if((context->count[0] += len << 3) < j) {
|
||||
context->count[1] += (len >> 29) + 1;
|
||||
}
|
||||
j = (j >> 3) & 63;
|
||||
if((j + len) > 63) {
|
||||
(void)SyMemcpy(data, &context->buffer[j], (i = 64 - j));
|
||||
SHA1Transform(context->state, context->buffer);
|
||||
for(; i + 63 < len; i += 64) {
|
||||
SHA1Transform(context->state, &data[i]);
|
||||
}
|
||||
j = 0;
|
||||
} else {
|
||||
i = 0;
|
||||
}
|
||||
(void)SyMemcpy(&data[i], &context->buffer[j], len - i);
|
||||
}
|
||||
/*
|
||||
* Add padding and return the message digest.
|
||||
*/
|
||||
PH7_PRIVATE void SHA1Final(SHA1Context *context, unsigned char digest[20]) {
|
||||
unsigned int i;
|
||||
unsigned char finalcount[8];
|
||||
for(i = 0; i < 8; i++) {
|
||||
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
|
||||
>> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */
|
||||
}
|
||||
SHA1Update(context, (const unsigned char *)"\200", 1);
|
||||
while((context->count[0] & 504) != 448) {
|
||||
SHA1Update(context, (const unsigned char *)"\0", 1);
|
||||
}
|
||||
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
|
||||
if(digest) {
|
||||
for(i = 0; i < 20; i++)
|
||||
digest[i] = (unsigned char)
|
||||
((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
|
||||
}
|
||||
}
|
||||
#undef Rl0
|
||||
#undef Rb0
|
||||
#undef R1
|
||||
#undef R2
|
||||
#undef R3
|
||||
#undef R4
|
||||
|
||||
PH7_PRIVATE sxi32 SySha1Compute(const void *pIn, sxu32 nLen, unsigned char zDigest[20]) {
|
||||
SHA1Context sCtx;
|
||||
SHA1Init(&sCtx);
|
||||
SHA1Update(&sCtx, (const unsigned char *)pIn, nLen);
|
||||
SHA1Final(&sCtx, zDigest);
|
||||
return SXRET_OK;
|
||||
}
|
||||
static const sxu32 crc32_table[] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
|
||||
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
|
||||
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
|
||||
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
|
||||
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
|
||||
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
|
||||
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
|
||||
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
|
||||
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
|
||||
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
|
||||
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
|
||||
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
|
||||
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
|
||||
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
|
||||
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
|
||||
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
|
||||
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
|
||||
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
|
||||
};
|
||||
#define CRC32C(c,d) (c = ( crc32_table[(c ^ (d)) & 0xFF] ^ (c>>8) ) )
|
||||
static sxu32 SyCrc32Update(sxu32 crc32, const void *pSrc, sxu32 nLen) {
|
||||
register unsigned char *zIn = (unsigned char *)pSrc;
|
||||
unsigned char *zEnd;
|
||||
if(zIn == 0) {
|
||||
return crc32;
|
||||
}
|
||||
zEnd = &zIn[nLen];
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
break;
|
||||
}
|
||||
CRC32C(crc32, zIn[0]);
|
||||
zIn++;
|
||||
}
|
||||
return crc32;
|
||||
}
|
||||
PH7_PRIVATE sxu32 SyCrc32(const void *pSrc, sxu32 nLen) {
|
||||
return SyCrc32Update(SXU32_HIGH, pSrc, nLen);
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyBinToHexConsumer(const void *pIn, sxu32 nLen, ProcConsumer xConsumer, void *pConsumerData) {
|
||||
static const unsigned char zHexTab[] = "0123456789abcdef";
|
||||
const unsigned char *zIn, *zEnd;
|
||||
unsigned char zOut[3];
|
||||
sxi32 rc;
|
||||
if(pIn == 0 || xConsumer == 0) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
zIn = (const unsigned char *)pIn;
|
||||
zEnd = &zIn[nLen];
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
break;
|
||||
}
|
||||
zOut[0] = zHexTab[zIn[0] >> 4];
|
||||
zOut[1] = zHexTab[zIn[0] & 0x0F];
|
||||
rc = xConsumer((const void *)zOut, sizeof(char) * 2, pConsumerData);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
zIn++;
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyUriDecode(const char *zSrc, sxu32 nLen, ProcConsumer xConsumer, void *pUserData, int bUTF8) {
|
||||
static const sxu8 Utf8Trans[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00
|
||||
};
|
||||
const char *zIn = zSrc;
|
||||
const char *zEnd;
|
||||
const char *zCur;
|
||||
sxu8 *zOutPtr;
|
||||
sxu8 zOut[10];
|
||||
sxi32 c, d;
|
||||
sxi32 rc;
|
||||
if(SX_EMPTY_STR(zSrc) || xConsumer == 0) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
rc = SXRET_OK;
|
||||
zEnd = &zSrc[nLen];
|
||||
zCur = zIn;
|
||||
for(;;) {
|
||||
while(zCur < zEnd && zCur[0] != '%' && zCur[0] != '+') {
|
||||
zCur++;
|
||||
}
|
||||
if(zCur != zIn) {
|
||||
/* Consume input */
|
||||
rc = xConsumer(zIn, (unsigned int)(zCur - zIn), pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
/* User consumer routine request an operation abort */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(zCur >= zEnd) {
|
||||
rc = SXRET_OK;
|
||||
break;
|
||||
}
|
||||
/* Decode unsafe HTTP characters */
|
||||
zOutPtr = zOut;
|
||||
if(zCur[0] == '+') {
|
||||
*zOutPtr++ = ' ';
|
||||
zCur++;
|
||||
} else {
|
||||
if(&zCur[2] >= zEnd) {
|
||||
rc = SXERR_OVERFLOW;
|
||||
break;
|
||||
}
|
||||
c = (SyAsciiToHex(zCur[1]) << 4) | SyAsciiToHex(zCur[2]);
|
||||
zCur += 3;
|
||||
if(c < 0x000C0) {
|
||||
*zOutPtr++ = (sxu8)c;
|
||||
} else {
|
||||
c = Utf8Trans[c - 0xC0];
|
||||
while(zCur[0] == '%') {
|
||||
d = (SyAsciiToHex(zCur[1]) << 4) | SyAsciiToHex(zCur[2]);
|
||||
if((d & 0xC0) != 0x80) {
|
||||
break;
|
||||
}
|
||||
c = (c << 6) + (0x3f & d);
|
||||
zCur += 3;
|
||||
}
|
||||
if(bUTF8 == FALSE) {
|
||||
*zOutPtr++ = (sxu8)c;
|
||||
} else {
|
||||
SX_WRITE_UTF8(zOutPtr, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Consume the decoded characters */
|
||||
rc = xConsumer((const void *)zOut, (unsigned int)(zOutPtr - zOut), pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
break;
|
||||
}
|
||||
/* Synchronize pointers */
|
||||
zIn = zCur;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#define SAFE_HTTP(C) (SyisAlphaNum(c) || c == '_' || c == '-' || c == '$' || c == '.' )
|
||||
PH7_PRIVATE sxi32 SyUriEncode(const char *zSrc, sxu32 nLen, ProcConsumer xConsumer, void *pUserData) {
|
||||
unsigned char *zIn = (unsigned char *)zSrc;
|
||||
unsigned char zHex[3] = { '%', 0, 0 };
|
||||
unsigned char zOut[2];
|
||||
unsigned char *zCur, *zEnd;
|
||||
sxi32 c;
|
||||
sxi32 rc;
|
||||
if(SX_EMPTY_STR(zSrc) || xConsumer == 0) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
rc = SXRET_OK;
|
||||
zEnd = &zIn[nLen];
|
||||
zCur = zIn;
|
||||
for(;;) {
|
||||
if(zCur >= zEnd) {
|
||||
if(zCur != zIn) {
|
||||
rc = xConsumer(zIn, (sxu32)(zCur - zIn), pUserData);
|
||||
}
|
||||
break;
|
||||
}
|
||||
c = zCur[0];
|
||||
if(SAFE_HTTP(c)) {
|
||||
zCur++;
|
||||
continue;
|
||||
}
|
||||
if(zCur != zIn && SXRET_OK != (rc = xConsumer(zIn, (sxu32)(zCur - zIn), pUserData))) {
|
||||
break;
|
||||
}
|
||||
if(c == ' ') {
|
||||
zOut[0] = '+';
|
||||
rc = xConsumer((const void *)zOut, sizeof(unsigned char), pUserData);
|
||||
} else {
|
||||
zHex[1] = "0123456789ABCDEF"[(c >> 4) & 0x0F];
|
||||
zHex[2] = "0123456789ABCDEF"[c & 0x0F];
|
||||
rc = xConsumer(zHex, sizeof(zHex), pUserData);
|
||||
}
|
||||
if(SXRET_OK != rc) {
|
||||
break;
|
||||
}
|
||||
zIn = &zCur[1];
|
||||
zCur = zIn ;
|
||||
}
|
||||
return rc == SXRET_OK ? SXRET_OK : SXERR_ABORT;
|
||||
}
|
4901
engine/lib/lib.c
4901
engine/lib/lib.c
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,745 @@
|
|||
/**
|
||||
* @PROJECT PH7 Engine for the AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE engine/lib/libfmt.c
|
||||
* @DESCRIPTION Modern formatting library for the PH7 Engine
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#include "ph7int.h"
|
||||
|
||||
#define SXFMT_BUFSIZ 1024 /* Conversion buffer size */
|
||||
/*
|
||||
** Conversion types fall into various categories as defined by the
|
||||
** following enumeration.
|
||||
*/
|
||||
#define SXFMT_RADIX 1 /* Integer types.%d, %x, %o, and so forth */
|
||||
#define SXFMT_FLOAT 2 /* Floating point.%f */
|
||||
#define SXFMT_EXP 3 /* Exponentional notation.%e and %E */
|
||||
#define SXFMT_GENERIC 4 /* Floating or exponential, depending on exponent.%g */
|
||||
#define SXFMT_SIZE 5 /* Total number of characters processed so far.%n */
|
||||
#define SXFMT_STRING 6 /* Strings.%s */
|
||||
#define SXFMT_PERCENT 7 /* Percent symbol.%% */
|
||||
#define SXFMT_CHARX 8 /* Characters.%c */
|
||||
#define SXFMT_ERROR 9 /* Used to indicate no such conversion type */
|
||||
/* Extension by Symisc Systems */
|
||||
#define SXFMT_RAWSTR 13 /* %z Pointer to raw string (SyString *) */
|
||||
#define SXFMT_UNUSED 15
|
||||
/*
|
||||
** Allowed values for SyFmtInfo.flags
|
||||
*/
|
||||
#define SXFLAG_SIGNED 0x01
|
||||
#define SXFLAG_UNSIGNED 0x02
|
||||
/* Allowed values for SyFmtConsumer.nType */
|
||||
#define SXFMT_CONS_PROC 1 /* Consumer is a procedure */
|
||||
#define SXFMT_CONS_STR 2 /* Consumer is a managed string */
|
||||
#define SXFMT_CONS_FILE 5 /* Consumer is an open File */
|
||||
#define SXFMT_CONS_BLOB 6 /* Consumer is a BLOB */
|
||||
/*
|
||||
** Each builtin conversion character (ex: the 'd' in "%d") is described
|
||||
** by an instance of the following structure
|
||||
*/
|
||||
typedef struct SyFmtInfo SyFmtInfo;
|
||||
struct SyFmtInfo {
|
||||
char fmttype; /* The format field code letter [i.e: 'd','s','x'] */
|
||||
sxu8 base; /* The base for radix conversion */
|
||||
int flags; /* One or more of SXFLAG_ constants below */
|
||||
sxu8 type; /* Conversion paradigm */
|
||||
const char *charset; /* The character set for conversion */
|
||||
const char *prefix; /* Prefix on non-zero values in alt format */
|
||||
};
|
||||
typedef struct SyFmtConsumer SyFmtConsumer;
|
||||
struct SyFmtConsumer {
|
||||
sxu32 nLen; /* Total output length */
|
||||
sxi32 nType; /* Type of the consumer see below */
|
||||
sxi32 rc; /* Consumer return value;Abort processing if rc != SXRET_OK */
|
||||
union {
|
||||
struct {
|
||||
ProcConsumer xUserConsumer;
|
||||
void *pUserData;
|
||||
} sFunc;
|
||||
SyBlob *pBlob;
|
||||
} uConsumer;
|
||||
};
|
||||
static int getdigit(sxlongreal *val, int *cnt) {
|
||||
sxlongreal d;
|
||||
int digit;
|
||||
if((*cnt)++ >= 16) {
|
||||
return '0';
|
||||
}
|
||||
digit = (int) * val;
|
||||
d = digit;
|
||||
*val = (*val - d) * 10.0;
|
||||
return digit + '0' ;
|
||||
}
|
||||
/*
|
||||
* The following routine was taken from the SQLITE2 source tree and was
|
||||
* extended by Symisc Systems to fit its need.
|
||||
* Status: Public Domain
|
||||
*/
|
||||
static sxi32 InternFormat(ProcConsumer xConsumer, void *pUserData, const char *zFormat, va_list ap) {
|
||||
/*
|
||||
* The following table is searched linearly, so it is good to put the most frequently
|
||||
* used conversion types first.
|
||||
*/
|
||||
static const SyFmtInfo aFmt[] = {
|
||||
{ 'd', 10, SXFLAG_SIGNED, SXFMT_RADIX, "0123456789", 0 },
|
||||
{ 's', 0, 0, SXFMT_STRING, 0, 0 },
|
||||
{ 'c', 0, 0, SXFMT_CHARX, 0, 0 },
|
||||
{ 'x', 16, 0, SXFMT_RADIX, "0123456789abcdef", "x0" },
|
||||
{ 'X', 16, 0, SXFMT_RADIX, "0123456789ABCDEF", "X0" },
|
||||
/* -- Extensions by Symisc Systems -- */
|
||||
{ 'z', 0, 0, SXFMT_RAWSTR, 0, 0 }, /* Pointer to a raw string (SyString *) */
|
||||
{ 'B', 2, 0, SXFMT_RADIX, "01", "b0"},
|
||||
/* -- End of Extensions -- */
|
||||
{ 'o', 8, 0, SXFMT_RADIX, "01234567", "0" },
|
||||
{ 'u', 10, 0, SXFMT_RADIX, "0123456789", 0 },
|
||||
{ 'f', 0, SXFLAG_SIGNED, SXFMT_FLOAT, 0, 0 },
|
||||
{ 'e', 0, SXFLAG_SIGNED, SXFMT_EXP, "e", 0 },
|
||||
{ 'E', 0, SXFLAG_SIGNED, SXFMT_EXP, "E", 0 },
|
||||
{ 'g', 0, SXFLAG_SIGNED, SXFMT_GENERIC, "e", 0 },
|
||||
{ 'G', 0, SXFLAG_SIGNED, SXFMT_GENERIC, "E", 0 },
|
||||
{ 'i', 10, SXFLAG_SIGNED, SXFMT_RADIX, "0123456789", 0 },
|
||||
{ 'n', 0, 0, SXFMT_SIZE, 0, 0 },
|
||||
{ '%', 0, 0, SXFMT_PERCENT, 0, 0 },
|
||||
{ 'p', 10, 0, SXFMT_RADIX, "0123456789", 0 }
|
||||
};
|
||||
int c; /* Next character in the format string */
|
||||
char *bufpt; /* Pointer to the conversion buffer */
|
||||
int precision; /* Precision of the current field */
|
||||
int length; /* Length of the field */
|
||||
int idx; /* A general purpose loop counter */
|
||||
int width; /* Width of the current field */
|
||||
sxu8 flag_leftjustify; /* True if "-" flag is present */
|
||||
sxu8 flag_plussign; /* True if "+" flag is present */
|
||||
sxu8 flag_blanksign; /* True if " " flag is present */
|
||||
sxu8 flag_alternateform; /* True if "#" flag is present */
|
||||
sxu8 flag_zeropad; /* True if field width constant starts with zero */
|
||||
sxu8 flag_long; /* True if "l" flag is present */
|
||||
sxi64 longvalue; /* Value for integer types */
|
||||
const SyFmtInfo *infop; /* Pointer to the appropriate info structure */
|
||||
char buf[SXFMT_BUFSIZ]; /* Conversion buffer */
|
||||
char prefix; /* Prefix character."+" or "-" or " " or '\0'.*/
|
||||
sxu8 errorflag = 0; /* True if an error is encountered */
|
||||
sxu8 xtype; /* Conversion paradigm */
|
||||
static char spaces[] = " ";
|
||||
#define etSPACESIZE ((int)sizeof(spaces)-1)
|
||||
sxlongreal realvalue; /* Value for real types */
|
||||
int exp; /* exponent of real numbers */
|
||||
double rounder; /* Used for rounding floating point values */
|
||||
sxu8 flag_dp; /* True if decimal point should be shown */
|
||||
sxu8 flag_rtz; /* True if trailing zeros should be removed */
|
||||
sxu8 flag_exp; /* True to force display of the exponent */
|
||||
int nsd; /* Number of significant digits returned */
|
||||
int rc;
|
||||
length = 0;
|
||||
bufpt = 0;
|
||||
for(; (c = (*zFormat)) != 0; ++zFormat) {
|
||||
if(c != '%') {
|
||||
unsigned int amt;
|
||||
bufpt = (char *)zFormat;
|
||||
amt = 1;
|
||||
while((c = (*++zFormat)) != '%' && c != 0) {
|
||||
amt++;
|
||||
}
|
||||
rc = xConsumer((const void *)bufpt, amt, pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
return SXERR_ABORT; /* Consumer routine request an operation abort */
|
||||
}
|
||||
if(c == 0) {
|
||||
return errorflag > 0 ? SXERR_FORMAT : SXRET_OK;
|
||||
}
|
||||
}
|
||||
if((c = (*++zFormat)) == 0) {
|
||||
errorflag = 1;
|
||||
rc = xConsumer("%", sizeof("%") - 1, pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
return SXERR_ABORT; /* Consumer routine request an operation abort */
|
||||
}
|
||||
return errorflag > 0 ? SXERR_FORMAT : SXRET_OK;
|
||||
}
|
||||
/* Find out what flags are present */
|
||||
flag_leftjustify = flag_plussign = flag_blanksign =
|
||||
flag_alternateform = flag_zeropad = 0;
|
||||
do {
|
||||
switch(c) {
|
||||
case '-':
|
||||
flag_leftjustify = 1;
|
||||
c = 0;
|
||||
break;
|
||||
case '+':
|
||||
flag_plussign = 1;
|
||||
c = 0;
|
||||
break;
|
||||
case ' ':
|
||||
flag_blanksign = 1;
|
||||
c = 0;
|
||||
break;
|
||||
case '#':
|
||||
flag_alternateform = 1;
|
||||
c = 0;
|
||||
break;
|
||||
case '0':
|
||||
flag_zeropad = 1;
|
||||
c = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} while(c == 0 && (c = (*++zFormat)) != 0);
|
||||
/* Get the field width */
|
||||
width = 0;
|
||||
if(c == '*') {
|
||||
width = va_arg(ap, int);
|
||||
if(width < 0) {
|
||||
flag_leftjustify = 1;
|
||||
width = -width;
|
||||
}
|
||||
c = *++zFormat;
|
||||
} else {
|
||||
while(c >= '0' && c <= '9') {
|
||||
width = width * 10 + c - '0';
|
||||
c = *++zFormat;
|
||||
}
|
||||
}
|
||||
if(width > SXFMT_BUFSIZ - 10) {
|
||||
width = SXFMT_BUFSIZ - 10;
|
||||
}
|
||||
/* Get the precision */
|
||||
precision = -1;
|
||||
if(c == '.') {
|
||||
precision = 0;
|
||||
c = *++zFormat;
|
||||
if(c == '*') {
|
||||
precision = va_arg(ap, int);
|
||||
if(precision < 0) {
|
||||
precision = -precision;
|
||||
}
|
||||
c = *++zFormat;
|
||||
} else {
|
||||
while(c >= '0' && c <= '9') {
|
||||
precision = precision * 10 + c - '0';
|
||||
c = *++zFormat;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Get the conversion type modifier */
|
||||
flag_long = 0;
|
||||
if(c == 'l' || c == 'q' /* BSD quad (expect a 64-bit integer) */) {
|
||||
flag_long = (c == 'q') ? 2 : 1;
|
||||
c = *++zFormat;
|
||||
if(c == 'l') {
|
||||
/* Standard printf emulation 'lld' (expect a 64bit integer) */
|
||||
flag_long = 2;
|
||||
}
|
||||
}
|
||||
/* Fetch the info entry for the field */
|
||||
infop = 0;
|
||||
xtype = SXFMT_ERROR;
|
||||
for(idx = 0; idx < (int)SX_ARRAYSIZE(aFmt); idx++) {
|
||||
if(c == aFmt[idx].fmttype) {
|
||||
infop = &aFmt[idx];
|
||||
xtype = infop->type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
** At this point, variables are initialized as follows:
|
||||
**
|
||||
** flag_alternateform TRUE if a '#' is present.
|
||||
** flag_plussign TRUE if a '+' is present.
|
||||
** flag_leftjustify TRUE if a '-' is present or if the
|
||||
** field width was negative.
|
||||
** flag_zeropad TRUE if the width began with 0.
|
||||
** flag_long TRUE if the letter 'l' (ell) or 'q'(BSD quad) prefixed
|
||||
** the conversion character.
|
||||
** flag_blanksign TRUE if a ' ' is present.
|
||||
** width The specified field width.This is
|
||||
** always non-negative.Zero is the default.
|
||||
** precision The specified precision.The default
|
||||
** is -1.
|
||||
** xtype The class of the conversion.
|
||||
** infop Pointer to the appropriate info struct.
|
||||
*/
|
||||
switch(xtype) {
|
||||
case SXFMT_RADIX:
|
||||
if(flag_long > 0) {
|
||||
if(flag_long > 1) {
|
||||
/* BSD quad: expect a 64-bit integer */
|
||||
longvalue = va_arg(ap, sxi64);
|
||||
} else {
|
||||
longvalue = va_arg(ap, sxlong);
|
||||
}
|
||||
} else {
|
||||
if(infop->flags & SXFLAG_SIGNED) {
|
||||
longvalue = va_arg(ap, sxi32);
|
||||
} else {
|
||||
longvalue = va_arg(ap, sxu32);
|
||||
}
|
||||
}
|
||||
/* Limit the precision to prevent overflowing buf[] during conversion */
|
||||
if(precision > SXFMT_BUFSIZ - 40) {
|
||||
precision = SXFMT_BUFSIZ - 40;
|
||||
}
|
||||
#if 1
|
||||
/* For the format %#x, the value zero is printed "0" not "0x0".
|
||||
** I think this is stupid.*/
|
||||
if(longvalue == 0) {
|
||||
flag_alternateform = 0;
|
||||
}
|
||||
#else
|
||||
/* More sensible: turn off the prefix for octal (to prevent "00"),
|
||||
** but leave the prefix for hex.*/
|
||||
if(longvalue == 0 && infop->base == 8) {
|
||||
flag_alternateform = 0;
|
||||
}
|
||||
#endif
|
||||
if(infop->flags & SXFLAG_SIGNED) {
|
||||
if(longvalue < 0) {
|
||||
longvalue = -longvalue;
|
||||
/* Ticket 1433-003 */
|
||||
if(longvalue < 0) {
|
||||
/* Overflow */
|
||||
longvalue = SXI64_HIGH;
|
||||
}
|
||||
prefix = '-';
|
||||
} else if(flag_plussign) {
|
||||
prefix = '+';
|
||||
} else if(flag_blanksign) {
|
||||
prefix = ' ';
|
||||
} else {
|
||||
prefix = 0;
|
||||
}
|
||||
} else {
|
||||
if(longvalue < 0) {
|
||||
longvalue = -longvalue;
|
||||
/* Ticket 1433-003 */
|
||||
if(longvalue < 0) {
|
||||
/* Overflow */
|
||||
longvalue = SXI64_HIGH;
|
||||
}
|
||||
}
|
||||
prefix = 0;
|
||||
}
|
||||
if(flag_zeropad && precision < width - (prefix != 0)) {
|
||||
precision = width - (prefix != 0);
|
||||
}
|
||||
bufpt = &buf[SXFMT_BUFSIZ - 1];
|
||||
{
|
||||
register const char *cset; /* Use registers for speed */
|
||||
register int base;
|
||||
cset = infop->charset;
|
||||
base = infop->base;
|
||||
do { /* Convert to ascii */
|
||||
*(--bufpt) = cset[longvalue % base];
|
||||
longvalue = longvalue / base;
|
||||
} while(longvalue > 0);
|
||||
}
|
||||
length = &buf[SXFMT_BUFSIZ - 1] - bufpt;
|
||||
for(idx = precision - length; idx > 0; idx--) {
|
||||
*(--bufpt) = '0'; /* Zero pad */
|
||||
}
|
||||
if(prefix) {
|
||||
*(--bufpt) = prefix; /* Add sign */
|
||||
}
|
||||
if(flag_alternateform && infop->prefix) { /* Add "0" or "0x" */
|
||||
const char *pre;
|
||||
char x;
|
||||
pre = infop->prefix;
|
||||
if(*bufpt != pre[0]) {
|
||||
for(pre = infop->prefix; (x = (*pre)) != 0; pre++) {
|
||||
*(--bufpt) = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
length = &buf[SXFMT_BUFSIZ - 1] - bufpt;
|
||||
break;
|
||||
case SXFMT_FLOAT:
|
||||
case SXFMT_EXP:
|
||||
case SXFMT_GENERIC:
|
||||
realvalue = va_arg(ap, double);
|
||||
if(precision < 0) {
|
||||
precision = 6; /* Set default precision */
|
||||
}
|
||||
if(precision > SXFMT_BUFSIZ - 40) {
|
||||
precision = SXFMT_BUFSIZ - 40;
|
||||
}
|
||||
if(realvalue < 0.0) {
|
||||
realvalue = -realvalue;
|
||||
prefix = '-';
|
||||
} else {
|
||||
if(flag_plussign) {
|
||||
prefix = '+';
|
||||
} else if(flag_blanksign) {
|
||||
prefix = ' ';
|
||||
} else {
|
||||
prefix = 0;
|
||||
}
|
||||
}
|
||||
if(infop->type == SXFMT_GENERIC && precision > 0) {
|
||||
precision--;
|
||||
}
|
||||
rounder = 0.0;
|
||||
/* Rounding works like BSD when the constant 0.4999 is used. Wierd!
|
||||
* It makes more sense to use 0.5 instead. */
|
||||
for(idx = precision, rounder = 0.5; idx > 0; idx--, rounder *= 0.1);
|
||||
if(infop->type == SXFMT_FLOAT) {
|
||||
realvalue += rounder;
|
||||
}
|
||||
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
|
||||
exp = 0;
|
||||
if(realvalue > 0.0) {
|
||||
while(realvalue >= 1e8 && exp <= 350) {
|
||||
realvalue *= 1e-8;
|
||||
exp += 8;
|
||||
}
|
||||
while(realvalue >= 10.0 && exp <= 350) {
|
||||
realvalue *= 0.1;
|
||||
exp++;
|
||||
}
|
||||
while(realvalue < 1e-8 && exp >= -350) {
|
||||
realvalue *= 1e8;
|
||||
exp -= 8;
|
||||
}
|
||||
while(realvalue < 1.0 && exp >= -350) {
|
||||
realvalue *= 10.0;
|
||||
exp--;
|
||||
}
|
||||
if(exp > 350 || exp < -350) {
|
||||
bufpt = "NaN";
|
||||
length = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bufpt = buf;
|
||||
/*
|
||||
** If the field type is etGENERIC, then convert to either etEXP
|
||||
** or etFLOAT, as appropriate.
|
||||
*/
|
||||
flag_exp = xtype == SXFMT_EXP;
|
||||
if(xtype != SXFMT_FLOAT) {
|
||||
realvalue += rounder;
|
||||
if(realvalue >= 10.0) {
|
||||
realvalue *= 0.1;
|
||||
exp++;
|
||||
}
|
||||
}
|
||||
if(xtype == SXFMT_GENERIC) {
|
||||
flag_rtz = !flag_alternateform;
|
||||
if(exp < -4 || exp > precision) {
|
||||
xtype = SXFMT_EXP;
|
||||
} else {
|
||||
precision = precision - exp;
|
||||
xtype = SXFMT_FLOAT;
|
||||
}
|
||||
} else {
|
||||
flag_rtz = 0;
|
||||
}
|
||||
/*
|
||||
** The "exp+precision" test causes output to be of type etEXP if
|
||||
** the precision is too large to fit in buf[].
|
||||
*/
|
||||
nsd = 0;
|
||||
if(xtype == SXFMT_FLOAT && exp + precision < SXFMT_BUFSIZ - 30) {
|
||||
flag_dp = (precision > 0 || flag_alternateform);
|
||||
if(prefix) {
|
||||
*(bufpt++) = prefix; /* Sign */
|
||||
}
|
||||
if(exp < 0) {
|
||||
*(bufpt++) = '0'; /* Digits before "." */
|
||||
} else
|
||||
for(; exp >= 0; exp--) {
|
||||
*(bufpt++) = (char)getdigit(&realvalue, &nsd);
|
||||
}
|
||||
if(flag_dp) {
|
||||
*(bufpt++) = '.'; /* The decimal point */
|
||||
}
|
||||
for(exp++; exp < 0 && precision > 0; precision--, exp++) {
|
||||
*(bufpt++) = '0';
|
||||
}
|
||||
while((precision--) > 0) {
|
||||
*(bufpt++) = (char)getdigit(&realvalue, &nsd);
|
||||
}
|
||||
*(bufpt--) = 0; /* Null terminate */
|
||||
if(flag_rtz && flag_dp) { /* Remove trailing zeros and "." */
|
||||
while(bufpt >= buf && *bufpt == '0') {
|
||||
*(bufpt--) = 0;
|
||||
}
|
||||
if(bufpt >= buf && *bufpt == '.') {
|
||||
*(bufpt--) = 0;
|
||||
}
|
||||
}
|
||||
bufpt++; /* point to next free slot */
|
||||
} else { /* etEXP or etGENERIC */
|
||||
flag_dp = (precision > 0 || flag_alternateform);
|
||||
if(prefix) {
|
||||
*(bufpt++) = prefix; /* Sign */
|
||||
}
|
||||
*(bufpt++) = (char)getdigit(&realvalue, &nsd); /* First digit */
|
||||
if(flag_dp) {
|
||||
*(bufpt++) = '.'; /* Decimal point */
|
||||
}
|
||||
while((precision--) > 0) {
|
||||
*(bufpt++) = (char)getdigit(&realvalue, &nsd);
|
||||
}
|
||||
bufpt--; /* point to last digit */
|
||||
if(flag_rtz && flag_dp) { /* Remove tail zeros */
|
||||
while(bufpt >= buf && *bufpt == '0') {
|
||||
*(bufpt--) = 0;
|
||||
}
|
||||
if(bufpt >= buf && *bufpt == '.') {
|
||||
*(bufpt--) = 0;
|
||||
}
|
||||
}
|
||||
bufpt++; /* point to next free slot */
|
||||
if(exp || flag_exp) {
|
||||
*(bufpt++) = infop->charset[0];
|
||||
if(exp < 0) {
|
||||
*(bufpt++) = '-'; /* sign of exp */
|
||||
exp = -exp;
|
||||
} else {
|
||||
*(bufpt++) = '+';
|
||||
}
|
||||
if(exp >= 100) {
|
||||
*(bufpt++) = (char)((exp / 100) + '0'); /* 100's digit */
|
||||
exp %= 100;
|
||||
}
|
||||
*(bufpt++) = (char)(exp / 10 + '0'); /* 10's digit */
|
||||
*(bufpt++) = (char)(exp % 10 + '0'); /* 1's digit */
|
||||
}
|
||||
}
|
||||
/* The converted number is in buf[] and zero terminated.Output it.
|
||||
** Note that the number is in the usual order, not reversed as with
|
||||
** integer conversions.*/
|
||||
length = bufpt - buf;
|
||||
bufpt = buf;
|
||||
/* Special case: Add leading zeros if the flag_zeropad flag is
|
||||
** set and we are not left justified */
|
||||
if(flag_zeropad && !flag_leftjustify && length < width) {
|
||||
int i;
|
||||
int nPad = width - length;
|
||||
for(i = width; i >= nPad; i--) {
|
||||
bufpt[i] = bufpt[i - nPad];
|
||||
}
|
||||
i = prefix != 0;
|
||||
while(nPad--) {
|
||||
bufpt[i++] = '0';
|
||||
}
|
||||
length = width;
|
||||
}
|
||||
break;
|
||||
case SXFMT_SIZE: {
|
||||
int *pSize = va_arg(ap, int *);
|
||||
*pSize = ((SyFmtConsumer *)pUserData)->nLen;
|
||||
length = width = 0;
|
||||
}
|
||||
break;
|
||||
case SXFMT_PERCENT:
|
||||
buf[0] = '%';
|
||||
bufpt = buf;
|
||||
length = 1;
|
||||
break;
|
||||
case SXFMT_CHARX:
|
||||
c = va_arg(ap, int);
|
||||
buf[0] = (char)c;
|
||||
/* Limit the precision to prevent overflowing buf[] during conversion */
|
||||
if(precision > SXFMT_BUFSIZ - 40) {
|
||||
precision = SXFMT_BUFSIZ - 40;
|
||||
}
|
||||
if(precision >= 0) {
|
||||
for(idx = 1; idx < precision; idx++) {
|
||||
buf[idx] = (char)c;
|
||||
}
|
||||
length = precision;
|
||||
} else {
|
||||
length = 1;
|
||||
}
|
||||
bufpt = buf;
|
||||
break;
|
||||
case SXFMT_STRING:
|
||||
bufpt = va_arg(ap, char *);
|
||||
if(bufpt == 0) {
|
||||
bufpt = " ";
|
||||
length = (int)sizeof(" ") - 1;
|
||||
break;
|
||||
}
|
||||
length = precision;
|
||||
if(precision < 0) {
|
||||
/* Symisc extension */
|
||||
length = (int)SyStrlen(bufpt);
|
||||
}
|
||||
if(precision >= 0 && precision < length) {
|
||||
length = precision;
|
||||
}
|
||||
break;
|
||||
case SXFMT_RAWSTR: {
|
||||
/* Symisc extension */
|
||||
SyString *pStr = va_arg(ap, SyString *);
|
||||
if(pStr == 0 || pStr->zString == 0) {
|
||||
bufpt = " ";
|
||||
length = (int)sizeof(char);
|
||||
break;
|
||||
}
|
||||
bufpt = (char *)pStr->zString;
|
||||
length = (int)pStr->nByte;
|
||||
break;
|
||||
}
|
||||
case SXFMT_ERROR:
|
||||
buf[0] = '?';
|
||||
bufpt = buf;
|
||||
length = (int)sizeof(char);
|
||||
if(c == 0) {
|
||||
zFormat--;
|
||||
}
|
||||
break;
|
||||
}/* End switch over the format type */
|
||||
/*
|
||||
** The text of the conversion is pointed to by "bufpt" and is
|
||||
** "length" characters long.The field width is "width".Do
|
||||
** the output.
|
||||
*/
|
||||
if(!flag_leftjustify) {
|
||||
register int nspace;
|
||||
nspace = width - length;
|
||||
if(nspace > 0) {
|
||||
while(nspace >= etSPACESIZE) {
|
||||
rc = xConsumer(spaces, etSPACESIZE, pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
return SXERR_ABORT; /* Consumer routine request an operation abort */
|
||||
}
|
||||
nspace -= etSPACESIZE;
|
||||
}
|
||||
if(nspace > 0) {
|
||||
rc = xConsumer(spaces, (unsigned int)nspace, pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
return SXERR_ABORT; /* Consumer routine request an operation abort */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(length > 0) {
|
||||
rc = xConsumer(bufpt, (unsigned int)length, pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
return SXERR_ABORT; /* Consumer routine request an operation abort */
|
||||
}
|
||||
}
|
||||
if(flag_leftjustify) {
|
||||
register int nspace;
|
||||
nspace = width - length;
|
||||
if(nspace > 0) {
|
||||
while(nspace >= etSPACESIZE) {
|
||||
rc = xConsumer(spaces, etSPACESIZE, pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
return SXERR_ABORT; /* Consumer routine request an operation abort */
|
||||
}
|
||||
nspace -= etSPACESIZE;
|
||||
}
|
||||
if(nspace > 0) {
|
||||
rc = xConsumer(spaces, (unsigned int)nspace, pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
return SXERR_ABORT; /* Consumer routine request an operation abort */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}/* End for loop over the format string */
|
||||
return errorflag ? SXERR_FORMAT : SXRET_OK;
|
||||
}
|
||||
static sxi32 FormatConsumer(const void *pSrc, unsigned int nLen, void *pData) {
|
||||
SyFmtConsumer *pConsumer = (SyFmtConsumer *)pData;
|
||||
sxi32 rc = SXERR_ABORT;
|
||||
switch(pConsumer->nType) {
|
||||
case SXFMT_CONS_PROC:
|
||||
/* User callback */
|
||||
rc = pConsumer->uConsumer.sFunc.xUserConsumer(pSrc, nLen, pConsumer->uConsumer.sFunc.pUserData);
|
||||
break;
|
||||
case SXFMT_CONS_BLOB:
|
||||
/* Blob consumer */
|
||||
rc = SyBlobAppend(pConsumer->uConsumer.pBlob, pSrc, (sxu32)nLen);
|
||||
break;
|
||||
default:
|
||||
/* Unknown consumer */
|
||||
break;
|
||||
}
|
||||
/* Update total number of bytes consumed so far */
|
||||
pConsumer->nLen += nLen;
|
||||
pConsumer->rc = rc;
|
||||
return rc;
|
||||
}
|
||||
static sxi32 FormatMount(sxi32 nType, void *pConsumer, ProcConsumer xUserCons, void *pUserData, sxu32 *pOutLen, const char *zFormat, va_list ap) {
|
||||
SyFmtConsumer sCons;
|
||||
sCons.nType = nType;
|
||||
sCons.rc = SXRET_OK;
|
||||
sCons.nLen = 0;
|
||||
if(pOutLen) {
|
||||
*pOutLen = 0;
|
||||
}
|
||||
switch(nType) {
|
||||
case SXFMT_CONS_PROC:
|
||||
if(xUserCons == 0) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
sCons.uConsumer.sFunc.xUserConsumer = xUserCons;
|
||||
sCons.uConsumer.sFunc.pUserData = pUserData;
|
||||
break;
|
||||
case SXFMT_CONS_BLOB:
|
||||
sCons.uConsumer.pBlob = (SyBlob *)pConsumer;
|
||||
break;
|
||||
default:
|
||||
return SXERR_UNKNOWN;
|
||||
}
|
||||
InternFormat(FormatConsumer, &sCons, zFormat, ap);
|
||||
if(pOutLen) {
|
||||
*pOutLen = sCons.nLen;
|
||||
}
|
||||
return sCons.rc;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyProcFormat(ProcConsumer xConsumer, void *pData, const char *zFormat, ...) {
|
||||
va_list ap;
|
||||
sxi32 rc;
|
||||
if(SX_EMPTY_STR(zFormat)) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
va_start(ap, zFormat);
|
||||
rc = FormatMount(SXFMT_CONS_PROC, 0, xConsumer, pData, 0, zFormat, ap);
|
||||
va_end(ap);
|
||||
return rc;
|
||||
}
|
||||
PH7_PRIVATE sxu32 SyBlobFormat(SyBlob *pBlob, const char *zFormat, ...) {
|
||||
va_list ap;
|
||||
sxu32 n;
|
||||
if(SX_EMPTY_STR(zFormat)) {
|
||||
return 0;
|
||||
}
|
||||
va_start(ap, zFormat);
|
||||
FormatMount(SXFMT_CONS_BLOB, &(*pBlob), 0, 0, &n, zFormat, ap);
|
||||
va_end(ap);
|
||||
return n;
|
||||
}
|
||||
PH7_PRIVATE sxu32 SyBlobFormatAp(SyBlob *pBlob, const char *zFormat, va_list ap) {
|
||||
sxu32 n = 0; /* cc warning */
|
||||
if(SX_EMPTY_STR(zFormat)) {
|
||||
return 0;
|
||||
}
|
||||
FormatMount(SXFMT_CONS_BLOB, &(*pBlob), 0, 0, &n, zFormat, ap);
|
||||
return n;
|
||||
}
|
||||
PH7_PRIVATE sxu32 SyBufferFormat(char *zBuf, sxu32 nLen, const char *zFormat, ...) {
|
||||
SyBlob sBlob;
|
||||
va_list ap;
|
||||
sxu32 n;
|
||||
if(SX_EMPTY_STR(zFormat)) {
|
||||
return 0;
|
||||
}
|
||||
if(SXRET_OK != SyBlobInitFromBuf(&sBlob, zBuf, nLen - 1)) {
|
||||
return 0;
|
||||
}
|
||||
va_start(ap, zFormat);
|
||||
FormatMount(SXFMT_CONS_BLOB, &sBlob, 0, 0, 0, zFormat, ap);
|
||||
va_end(ap);
|
||||
n = SyBlobLength(&sBlob);
|
||||
/* Append the null terminator */
|
||||
sBlob.mByte++;
|
||||
SyBlobAppend(&sBlob, "\0", sizeof(char));
|
||||
return n;
|
||||
}
|
|
@ -0,0 +1,514 @@
|
|||
/**
|
||||
* @PROJECT PH7 Engine for the AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE engine/lib/libzip.c
|
||||
* @DESCRIPTION ZIP archive file manipulation support for the PH7 Engine
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#include "ph7int.h"
|
||||
|
||||
sxu32 SyBinHash(const void *pSrc, sxu32 nLen);
|
||||
/*
|
||||
* Zip File Format:
|
||||
*
|
||||
* Byte order: Little-endian
|
||||
*
|
||||
* [Local file header + Compressed data [+ Extended local header]?]*
|
||||
* [Central directory]*
|
||||
* [End of central directory record]
|
||||
*
|
||||
* Local file header:*
|
||||
* Offset Length Contents
|
||||
* 0 4 bytes Local file header signature (0x04034b50)
|
||||
* 4 2 bytes Version needed to extract
|
||||
* 6 2 bytes General purpose bit flag
|
||||
* 8 2 bytes Compression method
|
||||
* 10 2 bytes Last mod file time
|
||||
* 12 2 bytes Last mod file date
|
||||
* 14 4 bytes CRC-32
|
||||
* 18 4 bytes Compressed size (n)
|
||||
* 22 4 bytes Uncompressed size
|
||||
* 26 2 bytes Filename length (f)
|
||||
* 28 2 bytes Extra field length (e)
|
||||
* 30 (f)bytes Filename
|
||||
* (e)bytes Extra field
|
||||
* (n)bytes Compressed data
|
||||
*
|
||||
* Extended local header:*
|
||||
* Offset Length Contents
|
||||
* 0 4 bytes Extended Local file header signature (0x08074b50)
|
||||
* 4 4 bytes CRC-32
|
||||
* 8 4 bytes Compressed size
|
||||
* 12 4 bytes Uncompressed size
|
||||
*
|
||||
* Extra field:?(if any)
|
||||
* Offset Length Contents
|
||||
* 0 2 bytes Header ID (0x001 until 0xfb4a) see extended appnote from Info-zip
|
||||
* 2 2 bytes Data size (g)
|
||||
* (g) bytes (g) bytes of extra field
|
||||
*
|
||||
* Central directory:*
|
||||
* Offset Length Contents
|
||||
* 0 4 bytes Central file header signature (0x02014b50)
|
||||
* 4 2 bytes Version made by
|
||||
* 6 2 bytes Version needed to extract
|
||||
* 8 2 bytes General purpose bit flag
|
||||
* 10 2 bytes Compression method
|
||||
* 12 2 bytes Last mod file time
|
||||
* 14 2 bytes Last mod file date
|
||||
* 16 4 bytes CRC-32
|
||||
* 20 4 bytes Compressed size
|
||||
* 24 4 bytes Uncompressed size
|
||||
* 28 2 bytes Filename length (f)
|
||||
* 30 2 bytes Extra field length (e)
|
||||
* 32 2 bytes File comment length (c)
|
||||
* 34 2 bytes Disk number start
|
||||
* 36 2 bytes Internal file attributes
|
||||
* 38 4 bytes External file attributes
|
||||
* 42 4 bytes Relative offset of local header
|
||||
* 46 (f)bytes Filename
|
||||
* (e)bytes Extra field
|
||||
* (c)bytes File comment
|
||||
*
|
||||
* End of central directory record:
|
||||
* Offset Length Contents
|
||||
* 0 4 bytes End of central dir signature (0x06054b50)
|
||||
* 4 2 bytes Number of this disk
|
||||
* 6 2 bytes Number of the disk with the start of the central directory
|
||||
* 8 2 bytes Total number of entries in the central dir on this disk
|
||||
* 10 2 bytes Total number of entries in the central dir
|
||||
* 12 4 bytes Size of the central directory
|
||||
* 16 4 bytes Offset of start of central directory with respect to the starting disk number
|
||||
* 20 2 bytes zipfile comment length (c)
|
||||
* 22 (c)bytes zipfile comment
|
||||
*
|
||||
* compression method: (2 bytes)
|
||||
* 0 - The file is stored (no compression)
|
||||
* 1 - The file is Shrunk
|
||||
* 2 - The file is Reduced with compression factor 1
|
||||
* 3 - The file is Reduced with compression factor 2
|
||||
* 4 - The file is Reduced with compression factor 3
|
||||
* 5 - The file is Reduced with compression factor 4
|
||||
* 6 - The file is Imploded
|
||||
* 7 - Reserved for Tokenizing compression algorithm
|
||||
* 8 - The file is Deflated
|
||||
*/
|
||||
|
||||
#define SXMAKE_ZIP_WORKBUF (SXU16_HIGH/2) /* 32KB Initial working buffer size */
|
||||
#define SXMAKE_ZIP_EXTRACT_VER 0x000a /* Version needed to extract */
|
||||
#define SXMAKE_ZIP_VER 0x003 /* Version made by */
|
||||
|
||||
#define SXZIP_CENTRAL_MAGIC 0x02014b50
|
||||
#define SXZIP_END_CENTRAL_MAGIC 0x06054b50
|
||||
#define SXZIP_LOCAL_MAGIC 0x04034b50
|
||||
/*#define SXZIP_CRC32_START 0xdebb20e3*/
|
||||
|
||||
#define SXZIP_LOCAL_HDRSZ 30 /* Local header size */
|
||||
#define SXZIP_LOCAL_EXT_HDRZ 16 /* Extended local header(footer) size */
|
||||
#define SXZIP_CENTRAL_HDRSZ 46 /* Central directory header size */
|
||||
#define SXZIP_END_CENTRAL_HDRSZ 22 /* End of central directory header size */
|
||||
|
||||
#define SXARCHIVE_HASH_SIZE 64 /* Starting hash table size(MUST BE POWER OF 2)*/
|
||||
static sxi32 SyLittleEndianUnpack32(sxu32 *uNB, const unsigned char *buf, sxu32 Len) {
|
||||
if(Len < sizeof(sxu32)) {
|
||||
return SXERR_SHORT;
|
||||
}
|
||||
*uNB = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
|
||||
return SXRET_OK;
|
||||
}
|
||||
static sxi32 SyLittleEndianUnpack16(sxu16 *pOut, const unsigned char *zBuf, sxu32 nLen) {
|
||||
if(nLen < sizeof(sxu16)) {
|
||||
return SXERR_SHORT;
|
||||
}
|
||||
*pOut = zBuf[0] + (zBuf[1] << 8);
|
||||
return SXRET_OK;
|
||||
}
|
||||
static sxi32 SyDosTimeFormat(sxu32 nDosDate, Sytm *pOut) {
|
||||
sxu16 nDate;
|
||||
sxu16 nTime;
|
||||
nDate = nDosDate >> 16;
|
||||
nTime = nDosDate & 0xFFFF;
|
||||
pOut->tm_isdst = 0;
|
||||
pOut->tm_year = 1980 + (nDate >> 9);
|
||||
pOut->tm_mon = (nDate % (1 << 9)) >> 5;
|
||||
pOut->tm_mday = (nDate % (1 << 9)) & 0x1F;
|
||||
pOut->tm_hour = nTime >> 11;
|
||||
pOut->tm_min = (nTime % (1 << 11)) >> 5;
|
||||
pOut->tm_sec = ((nTime % (1 << 11)) & 0x1F) << 1;
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* Archive hashtable manager
|
||||
*/
|
||||
static sxi32 ArchiveHashGetEntry(SyArchive *pArch, const char *zName, sxu32 nLen, SyArchiveEntry **ppEntry) {
|
||||
SyArchiveEntry *pBucketEntry;
|
||||
SyString sEntry;
|
||||
sxu32 nHash;
|
||||
nHash = pArch->xHash(zName, nLen);
|
||||
pBucketEntry = pArch->apHash[nHash & (pArch->nSize - 1)];
|
||||
SyStringInitFromBuf(&sEntry, zName, nLen);
|
||||
for(;;) {
|
||||
if(pBucketEntry == 0) {
|
||||
break;
|
||||
}
|
||||
if(nHash == pBucketEntry->nHash && pArch->xCmp(&sEntry, &pBucketEntry->sFileName) == 0) {
|
||||
if(ppEntry) {
|
||||
*ppEntry = pBucketEntry;
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
pBucketEntry = pBucketEntry->pNextHash;
|
||||
}
|
||||
return SXERR_NOTFOUND;
|
||||
}
|
||||
static void ArchiveHashBucketInstall(SyArchiveEntry **apTable, sxu32 nBucket, SyArchiveEntry *pEntry) {
|
||||
pEntry->pNextHash = apTable[nBucket];
|
||||
if(apTable[nBucket] != 0) {
|
||||
apTable[nBucket]->pPrevHash = pEntry;
|
||||
}
|
||||
apTable[nBucket] = pEntry;
|
||||
}
|
||||
static sxi32 ArchiveHashGrowTable(SyArchive *pArch) {
|
||||
sxu32 nNewSize = pArch->nSize * 2;
|
||||
SyArchiveEntry **apNew;
|
||||
SyArchiveEntry *pEntry;
|
||||
sxu32 n;
|
||||
/* Allocate a new table */
|
||||
apNew = (SyArchiveEntry **)SyMemBackendAlloc(pArch->pAllocator, nNewSize * sizeof(SyArchiveEntry *));
|
||||
if(apNew == 0) {
|
||||
return SXRET_OK; /* Not so fatal,simply a performance hit */
|
||||
}
|
||||
SyZero(apNew, nNewSize * sizeof(SyArchiveEntry *));
|
||||
/* Rehash old entries */
|
||||
for(n = 0, pEntry = pArch->pList ; n < pArch->nLoaded ; n++, pEntry = pEntry->pNext) {
|
||||
pEntry->pNextHash = pEntry->pPrevHash = 0;
|
||||
ArchiveHashBucketInstall(apNew, pEntry->nHash & (nNewSize - 1), pEntry);
|
||||
}
|
||||
/* Release the old table */
|
||||
SyMemBackendFree(pArch->pAllocator, pArch->apHash);
|
||||
pArch->apHash = apNew;
|
||||
pArch->nSize = nNewSize;
|
||||
return SXRET_OK;
|
||||
}
|
||||
static sxi32 ArchiveHashInstallEntry(SyArchive *pArch, SyArchiveEntry *pEntry) {
|
||||
if(pArch->nLoaded > pArch->nSize * 3) {
|
||||
ArchiveHashGrowTable(&(*pArch));
|
||||
}
|
||||
pEntry->nHash = pArch->xHash(SyStringData(&pEntry->sFileName), SyStringLength(&pEntry->sFileName));
|
||||
/* Install the entry in its bucket */
|
||||
ArchiveHashBucketInstall(pArch->apHash, pEntry->nHash & (pArch->nSize - 1), pEntry);
|
||||
MACRO_LD_PUSH(pArch->pList, pEntry);
|
||||
pArch->nLoaded++;
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* Parse the End of central directory and report status
|
||||
*/
|
||||
static sxi32 ParseEndOfCentralDirectory(SyArchive *pArch, const unsigned char *zBuf) {
|
||||
sxu32 nMagic = 0; /* cc -O6 warning */
|
||||
/* Sanity check */
|
||||
SyLittleEndianUnpack32(&nMagic, zBuf, sizeof(sxu32));
|
||||
if(nMagic != SXZIP_END_CENTRAL_MAGIC) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
/* # of entries */
|
||||
SyLittleEndianUnpack16((sxu16 *)&pArch->nEntry, &zBuf[8], sizeof(sxu16));
|
||||
if(pArch->nEntry > SXI16_HIGH /* SXU16_HIGH */) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
/* Size of central directory */
|
||||
SyLittleEndianUnpack32(&pArch->nCentralSize, &zBuf[12], sizeof(sxu32));
|
||||
if(pArch->nCentralSize > SXI32_HIGH) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
/* Starting offset of central directory */
|
||||
SyLittleEndianUnpack32(&pArch->nCentralOfft, &zBuf[16], sizeof(sxu32));
|
||||
if(pArch->nCentralSize > SXI32_HIGH) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* Fill the zip entry with the appropriate information from the central directory
|
||||
*/
|
||||
static sxi32 GetCentralDirectoryEntry(SyArchive *pArch, SyArchiveEntry *pEntry, const unsigned char *zCentral, sxu32 *pNextOffset) {
|
||||
SyString *pName = &pEntry->sFileName; /* File name */
|
||||
sxu16 nDosDate, nDosTime;
|
||||
sxu16 nComment = 0 ;
|
||||
sxu32 nMagic = 0; /* cc -O6 warning */
|
||||
sxi32 rc;
|
||||
nDosDate = nDosTime = 0; /* cc -O6 warning */
|
||||
SXUNUSED(pArch);
|
||||
// (void)pArch;
|
||||
/* Sanity check */
|
||||
rc = SyLittleEndianUnpack32(&nMagic, zCentral, sizeof(sxu32));
|
||||
if(/* rc != SXRET_OK || */ nMagic != SXZIP_CENTRAL_MAGIC) {
|
||||
rc = SXERR_CORRUPT;
|
||||
/*
|
||||
* Try to recover by examing the next central directory record.
|
||||
* Dont worry here,there is no risk of an infinite loop since
|
||||
* the buffer size is delimited.
|
||||
*/
|
||||
/* pName->nByte = 0; nComment = 0; pName->nExtra = 0 */
|
||||
goto update;
|
||||
}
|
||||
/*
|
||||
* entry name length
|
||||
*/
|
||||
SyLittleEndianUnpack16((sxu16 *)&pName->nByte, &zCentral[28], sizeof(sxu16));
|
||||
if(pName->nByte > SXI16_HIGH /* SXU16_HIGH */) {
|
||||
rc = SXERR_BIG;
|
||||
goto update;
|
||||
}
|
||||
/* Extra information */
|
||||
SyLittleEndianUnpack16(&pEntry->nExtra, &zCentral[30], sizeof(sxu16));
|
||||
/* Comment length */
|
||||
SyLittleEndianUnpack16(&nComment, &zCentral[32], sizeof(sxu16));
|
||||
/* Compression method 0 == stored / 8 == deflated */
|
||||
rc = SyLittleEndianUnpack16(&pEntry->nComprMeth, &zCentral[10], sizeof(sxu16));
|
||||
/* DOS Timestamp */
|
||||
SyLittleEndianUnpack16(&nDosTime, &zCentral[12], sizeof(sxu16));
|
||||
SyLittleEndianUnpack16(&nDosDate, &zCentral[14], sizeof(sxu16));
|
||||
SyDosTimeFormat((nDosDate << 16 | nDosTime), &pEntry->sFmt);
|
||||
/* Little hack to fix month index */
|
||||
pEntry->sFmt.tm_mon--;
|
||||
/* CRC32 */
|
||||
rc = SyLittleEndianUnpack32(&pEntry->nCrc, &zCentral[16], sizeof(sxu32));
|
||||
/* Content size before compression */
|
||||
rc = SyLittleEndianUnpack32(&pEntry->nByte, &zCentral[24], sizeof(sxu32));
|
||||
if(pEntry->nByte > SXI32_HIGH) {
|
||||
rc = SXERR_BIG;
|
||||
goto update;
|
||||
}
|
||||
/*
|
||||
* Content size after compression.
|
||||
* Note that if the file is stored pEntry->nByte should be equal to pEntry->nByteCompr
|
||||
*/
|
||||
rc = SyLittleEndianUnpack32(&pEntry->nByteCompr, &zCentral[20], sizeof(sxu32));
|
||||
if(pEntry->nByteCompr > SXI32_HIGH) {
|
||||
rc = SXERR_BIG;
|
||||
goto update;
|
||||
}
|
||||
/* Finally grab the contents offset */
|
||||
SyLittleEndianUnpack32(&pEntry->nOfft, &zCentral[42], sizeof(sxu32));
|
||||
if(pEntry->nOfft > SXI32_HIGH) {
|
||||
rc = SXERR_BIG;
|
||||
goto update;
|
||||
}
|
||||
rc = SXRET_OK;
|
||||
update:
|
||||
/* Update the offset to point to the next central directory record */
|
||||
*pNextOffset = SXZIP_CENTRAL_HDRSZ + pName->nByte + pEntry->nExtra + nComment;
|
||||
return rc; /* Report failure or success */
|
||||
}
|
||||
static sxi32 ZipFixOffset(SyArchiveEntry *pEntry, void *pSrc) {
|
||||
sxu16 nExtra, nNameLen;
|
||||
unsigned char *zHdr;
|
||||
nExtra = nNameLen = 0;
|
||||
zHdr = (unsigned char *)pSrc;
|
||||
zHdr = &zHdr[pEntry->nOfft];
|
||||
if(SyMemcmp(zHdr, "PK\003\004", sizeof(sxu32)) != 0) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
SyLittleEndianUnpack16(&nNameLen, &zHdr[26], sizeof(sxu16));
|
||||
SyLittleEndianUnpack16(&nExtra, &zHdr[28], sizeof(sxu16));
|
||||
/* Fix contents offset */
|
||||
pEntry->nOfft += SXZIP_LOCAL_HDRSZ + nExtra + nNameLen;
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* Extract all valid entries from the central directory
|
||||
*/
|
||||
static sxi32 ZipExtract(SyArchive *pArch, const unsigned char *zCentral, sxu32 nLen, void *pSrc) {
|
||||
SyArchiveEntry *pEntry, *pDup;
|
||||
const unsigned char *zEnd ; /* End of central directory */
|
||||
sxu32 nIncr, nOfft; /* Central Offset */
|
||||
SyString *pName; /* Entry name */
|
||||
char *zName;
|
||||
sxi32 rc;
|
||||
nOfft = nIncr = 0;
|
||||
zEnd = &zCentral[nLen];
|
||||
for(;;) {
|
||||
if(&zCentral[nOfft] >= zEnd) {
|
||||
break;
|
||||
}
|
||||
/* Add a new entry */
|
||||
pEntry = (SyArchiveEntry *)SyMemBackendPoolAlloc(pArch->pAllocator, sizeof(SyArchiveEntry));
|
||||
if(pEntry == 0) {
|
||||
break;
|
||||
}
|
||||
SyZero(pEntry, sizeof(SyArchiveEntry));
|
||||
pEntry->nMagic = SXARCH_MAGIC;
|
||||
nIncr = 0;
|
||||
rc = GetCentralDirectoryEntry(&(*pArch), pEntry, &zCentral[nOfft], &nIncr);
|
||||
if(rc == SXRET_OK) {
|
||||
/* Fix the starting record offset so we can access entry contents correctly */
|
||||
rc = ZipFixOffset(pEntry, pSrc);
|
||||
}
|
||||
if(rc != SXRET_OK) {
|
||||
sxu32 nJmp = 0;
|
||||
SyMemBackendPoolFree(pArch->pAllocator, pEntry);
|
||||
/* Try to recover by brute-forcing for a valid central directory record */
|
||||
if(SXRET_OK == SyBlobSearch((const void *)&zCentral[nOfft + nIncr], (sxu32)(zEnd - &zCentral[nOfft + nIncr]),
|
||||
(const void *)"PK\001\002", sizeof(sxu32), &nJmp)) {
|
||||
nOfft += nIncr + nJmp; /* Check next entry */
|
||||
continue;
|
||||
}
|
||||
break; /* Giving up,archive is hopelessly corrupted */
|
||||
}
|
||||
pName = &pEntry->sFileName;
|
||||
pName->zString = (const char *)&zCentral[nOfft + SXZIP_CENTRAL_HDRSZ];
|
||||
if(pName->nByte <= 0 || (pEntry->nByte <= 0 && pName->zString[pName->nByte - 1] != '/')) {
|
||||
/* Ignore zero length records (except folders) and records without names */
|
||||
SyMemBackendPoolFree(pArch->pAllocator, pEntry);
|
||||
nOfft += nIncr; /* Check next entry */
|
||||
continue;
|
||||
}
|
||||
zName = SyMemBackendStrDup(pArch->pAllocator, pName->zString, pName->nByte);
|
||||
if(zName == 0) {
|
||||
SyMemBackendPoolFree(pArch->pAllocator, pEntry);
|
||||
nOfft += nIncr; /* Check next entry */
|
||||
continue;
|
||||
}
|
||||
pName->zString = (const char *)zName;
|
||||
/* Check for duplicates */
|
||||
rc = ArchiveHashGetEntry(&(*pArch), pName->zString, pName->nByte, &pDup);
|
||||
if(rc == SXRET_OK) {
|
||||
/* Another entry with the same name exists ; link them together */
|
||||
pEntry->pNextName = pDup->pNextName;
|
||||
pDup->pNextName = pEntry;
|
||||
pDup->nDup++;
|
||||
} else {
|
||||
/* Insert in hashtable */
|
||||
ArchiveHashInstallEntry(pArch, pEntry);
|
||||
}
|
||||
nOfft += nIncr; /* Check next record */
|
||||
}
|
||||
pArch->pCursor = pArch->pList;
|
||||
return pArch->nLoaded > 0 ? SXRET_OK : SXERR_EMPTY;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyZipExtractFromBuf(SyArchive *pArch, const char *zBuf, sxu32 nLen) {
|
||||
const unsigned char *zCentral, *zEnd;
|
||||
sxi32 rc;
|
||||
if(SXARCH_INVALID(pArch) || zBuf == 0) {
|
||||
return SXERR_INVALID;
|
||||
}
|
||||
/* The miminal size of a zip archive:
|
||||
* LOCAL_HDR_SZ + CENTRAL_HDR_SZ + END_OF_CENTRAL_HDR_SZ
|
||||
* 30 46 22
|
||||
*/
|
||||
if(nLen < SXZIP_LOCAL_HDRSZ + SXZIP_CENTRAL_HDRSZ + SXZIP_END_CENTRAL_HDRSZ) {
|
||||
return SXERR_CORRUPT; /* Don't bother processing return immediately */
|
||||
}
|
||||
zEnd = (unsigned char *)&zBuf[nLen - SXZIP_END_CENTRAL_HDRSZ];
|
||||
/* Find the end of central directory */
|
||||
while(((sxu32)((unsigned char *)&zBuf[nLen] - zEnd) < (SXZIP_END_CENTRAL_HDRSZ + SXI16_HIGH)) &&
|
||||
zEnd > (unsigned char *)zBuf && SyMemcmp(zEnd, "PK\005\006", sizeof(sxu32)) != 0) {
|
||||
zEnd--;
|
||||
}
|
||||
/* Parse the end of central directory */
|
||||
rc = ParseEndOfCentralDirectory(&(*pArch), zEnd);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
/* Find the starting offset of the central directory */
|
||||
zCentral = &zEnd[-(sxi32)pArch->nCentralSize];
|
||||
if(zCentral <= (unsigned char *)zBuf || SyMemcmp(zCentral, "PK\001\002", sizeof(sxu32)) != 0) {
|
||||
if(pArch->nCentralOfft >= nLen) {
|
||||
/* Corrupted central directory offset */
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
zCentral = (unsigned char *)&zBuf[pArch->nCentralOfft];
|
||||
if(SyMemcmp(zCentral, "PK\001\002", sizeof(sxu32)) != 0) {
|
||||
/* Corrupted zip archive */
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
/* Fall thru and extract all valid entries from the central directory */
|
||||
}
|
||||
rc = ZipExtract(&(*pArch), zCentral, (sxu32)(zEnd - zCentral), (void *)zBuf);
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
* Default comparison function.
|
||||
*/
|
||||
static sxi32 ArchiveHashCmp(const SyString *pStr1, const SyString *pStr2) {
|
||||
sxi32 rc;
|
||||
rc = SyStringCmp(pStr1, pStr2, SyMemcmp);
|
||||
return rc;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyArchiveInit(SyArchive *pArch, SyMemBackend *pAllocator, ProcHash xHash, ProcRawStrCmp xCmp) {
|
||||
SyArchiveEntry **apHash;
|
||||
if(pArch == 0) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
SyZero(pArch, sizeof(SyArchive));
|
||||
/* Allocate a new hashtable */
|
||||
apHash = (SyArchiveEntry **)SyMemBackendAlloc(&(*pAllocator), SXARCHIVE_HASH_SIZE * sizeof(SyArchiveEntry *));
|
||||
if(apHash == 0) {
|
||||
return SXERR_MEM;
|
||||
}
|
||||
SyZero(apHash, SXARCHIVE_HASH_SIZE * sizeof(SyArchiveEntry *));
|
||||
pArch->apHash = apHash;
|
||||
pArch->xHash = xHash ? xHash : SyBinHash;
|
||||
pArch->xCmp = xCmp ? xCmp : ArchiveHashCmp;
|
||||
pArch->nSize = SXARCHIVE_HASH_SIZE;
|
||||
pArch->pAllocator = &(*pAllocator);
|
||||
pArch->nMagic = SXARCH_MAGIC;
|
||||
return SXRET_OK;
|
||||
}
|
||||
static sxi32 ArchiveReleaseEntry(SyMemBackend *pAllocator, SyArchiveEntry *pEntry) {
|
||||
SyArchiveEntry *pDup = pEntry->pNextName;
|
||||
SyArchiveEntry *pNextDup;
|
||||
/* Release duplicates first since there are not stored in the hashtable */
|
||||
for(;;) {
|
||||
if(pEntry->nDup == 0) {
|
||||
break;
|
||||
}
|
||||
pNextDup = pDup->pNextName;
|
||||
pDup->nMagic = 0x2661;
|
||||
SyMemBackendFree(pAllocator, (void *)SyStringData(&pDup->sFileName));
|
||||
SyMemBackendPoolFree(pAllocator, pDup);
|
||||
pDup = pNextDup;
|
||||
pEntry->nDup--;
|
||||
}
|
||||
pEntry->nMagic = 0x2661;
|
||||
SyMemBackendFree(pAllocator, (void *)SyStringData(&pEntry->sFileName));
|
||||
SyMemBackendPoolFree(pAllocator, pEntry);
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyArchiveRelease(SyArchive *pArch) {
|
||||
SyArchiveEntry *pEntry, *pNext;
|
||||
pEntry = pArch->pList;
|
||||
for(;;) {
|
||||
if(pArch->nLoaded < 1) {
|
||||
break;
|
||||
}
|
||||
pNext = pEntry->pNext;
|
||||
MACRO_LD_REMOVE(pArch->pList, pEntry);
|
||||
ArchiveReleaseEntry(pArch->pAllocator, pEntry);
|
||||
pEntry = pNext;
|
||||
pArch->nLoaded--;
|
||||
}
|
||||
SyMemBackendFree(pArch->pAllocator, pArch->apHash);
|
||||
pArch->pCursor = 0;
|
||||
pArch->nMagic = 0x2626;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyArchiveResetLoopCursor(SyArchive *pArch) {
|
||||
pArch->pCursor = pArch->pList;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyArchiveGetNextEntry(SyArchive *pArch, SyArchiveEntry **ppEntry) {
|
||||
SyArchiveEntry *pNext;
|
||||
if(pArch->pCursor == 0) {
|
||||
/* Rewind the cursor */
|
||||
pArch->pCursor = pArch->pList;
|
||||
return SXERR_EOF;
|
||||
}
|
||||
*ppEntry = pArch->pCursor;
|
||||
pNext = pArch->pCursor->pNext;
|
||||
/* Advance the cursor to the next entry */
|
||||
pArch->pCursor = pNext;
|
||||
return SXRET_OK;
|
||||
}
|
|
@ -0,0 +1,749 @@
|
|||
/**
|
||||
* @PROJECT PH7 Engine for the AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE engine/lib/memory.c
|
||||
* @DESCRIPTION PH7 Engine memory allocation subsystem
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#if defined(__WINNT__)
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "ph7int.h"
|
||||
|
||||
static void *SyOSHeapAlloc(sxu32 nBytes) {
|
||||
void *pNew;
|
||||
#if defined(__WINNT__)
|
||||
pNew = HeapAlloc(GetProcessHeap(), 0, nBytes);
|
||||
#else
|
||||
pNew = malloc((size_t)nBytes);
|
||||
#endif
|
||||
return pNew;
|
||||
}
|
||||
static void *SyOSHeapRealloc(void *pOld, sxu32 nBytes) {
|
||||
void *pNew;
|
||||
#if defined(__WINNT__)
|
||||
pNew = HeapReAlloc(GetProcessHeap(), 0, pOld, nByte);
|
||||
#else
|
||||
pNew = realloc(pOld, (size_t)nBytes);
|
||||
#endif
|
||||
return pNew;
|
||||
}
|
||||
static void SyOSHeapFree(void *pPtr) {
|
||||
#if defined(__WINNT__)
|
||||
HeapFree(GetProcessHeap(), 0, pPtr);
|
||||
#else
|
||||
free(pPtr);
|
||||
#endif
|
||||
}
|
||||
PH7_PRIVATE void SyZero(void *pSrc, sxu32 nSize) {
|
||||
register unsigned char *zSrc = (unsigned char *)pSrc;
|
||||
unsigned char *zEnd;
|
||||
if(zSrc == 0 || nSize <= 0) {
|
||||
return ;
|
||||
}
|
||||
zEnd = &zSrc[nSize];
|
||||
for(;;) {
|
||||
if(zSrc >= zEnd) {
|
||||
break;
|
||||
}
|
||||
zSrc[0] = 0;
|
||||
zSrc++;
|
||||
}
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyMemcmp(const void *pB1, const void *pB2, sxu32 nSize) {
|
||||
sxi32 rc;
|
||||
if(nSize <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if(pB1 == 0 || pB2 == 0) {
|
||||
return pB1 != 0 ? 1 : (pB2 == 0 ? 0 : -1);
|
||||
}
|
||||
SX_MACRO_FAST_CMP(pB1, pB2, nSize, rc);
|
||||
return rc;
|
||||
}
|
||||
PH7_PRIVATE sxu32 SyMemcpy(const void *pSrc, void *pDest, sxu32 nLen) {
|
||||
if(pSrc == 0 || pDest == 0) {
|
||||
return 0;
|
||||
}
|
||||
if(pSrc == (const void *)pDest) {
|
||||
return nLen;
|
||||
}
|
||||
SX_MACRO_FAST_MEMCPY(pSrc, pDest, nLen);
|
||||
return nLen;
|
||||
}
|
||||
static void *MemOSAlloc(sxu32 nBytes) {
|
||||
sxu32 *pChunk;
|
||||
pChunk = (sxu32 *)SyOSHeapAlloc(nBytes + sizeof(sxu32));
|
||||
if(pChunk == 0) {
|
||||
return 0;
|
||||
}
|
||||
pChunk[0] = nBytes;
|
||||
return (void *)&pChunk[1];
|
||||
}
|
||||
static void *MemOSRealloc(void *pOld, sxu32 nBytes) {
|
||||
sxu32 *pOldChunk;
|
||||
sxu32 *pChunk;
|
||||
pOldChunk = (sxu32 *)(((char *)pOld) - sizeof(sxu32));
|
||||
if(pOldChunk[0] >= nBytes) {
|
||||
return pOld;
|
||||
}
|
||||
pChunk = (sxu32 *)SyOSHeapRealloc(pOldChunk, nBytes + sizeof(sxu32));
|
||||
if(pChunk == 0) {
|
||||
return 0;
|
||||
}
|
||||
pChunk[0] = nBytes;
|
||||
return (void *)&pChunk[1];
|
||||
}
|
||||
static void MemOSFree(void *pBlock) {
|
||||
void *pChunk;
|
||||
pChunk = (void *)(((char *)pBlock) - sizeof(sxu32));
|
||||
SyOSHeapFree(pChunk);
|
||||
}
|
||||
static sxu32 MemOSChunkSize(void *pBlock) {
|
||||
sxu32 *pChunk;
|
||||
pChunk = (sxu32 *)(((char *)pBlock) - sizeof(sxu32));
|
||||
return pChunk[0];
|
||||
}
|
||||
/* Export OS allocation methods */
|
||||
static const SyMemMethods sOSAllocMethods = {
|
||||
MemOSAlloc,
|
||||
MemOSRealloc,
|
||||
MemOSFree,
|
||||
MemOSChunkSize,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
static sxi32 MemBackendCalculate(SyMemBackend *pBackend, sxi32 nBytes) {
|
||||
if(pBackend->pHeap->nLimit && (pBackend->pHeap->nSize + nBytes > pBackend->pHeap->nLimit - 10240)) {
|
||||
if(pBackend->xMemError) {
|
||||
pBackend->xMemError(pBackend->pUserData);
|
||||
}
|
||||
return SXERR_MEM;
|
||||
}
|
||||
pBackend->pHeap->nSize += nBytes;
|
||||
if(pBackend->pHeap->nSize > pBackend->pHeap->nPeak) {
|
||||
pBackend->pHeap->nPeak = pBackend->pHeap->nSize;
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
static void *MemBackendAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
|
||||
SyMemBlock *pBlock;
|
||||
sxi32 nRetry = 0;
|
||||
/* Append an extra block so we can tracks allocated chunks and avoid memory
|
||||
* leaks.
|
||||
*/
|
||||
nBytes += sizeof(SyMemBlock);
|
||||
/* Calculate memory usage */
|
||||
if(MemBackendCalculate(pBackend, nBytes) != SXRET_OK) {
|
||||
return 0;
|
||||
}
|
||||
for(;;) {
|
||||
pBlock = (SyMemBlock *)pBackend->pMethods->xAlloc(nBytes);
|
||||
if(pBlock != 0 || pBackend->xMemError == 0 || nRetry > SXMEM_BACKEND_RETRY
|
||||
|| SXERR_RETRY != pBackend->xMemError(pBackend->pUserData)) {
|
||||
break;
|
||||
}
|
||||
nRetry++;
|
||||
}
|
||||
if(pBlock == 0) {
|
||||
return 0;
|
||||
}
|
||||
pBlock->pNext = pBlock->pPrev = 0;
|
||||
/* Link to the list of already tracked blocks */
|
||||
MACRO_LD_PUSH(pBackend->pBlocks, pBlock);
|
||||
pBlock->nGuard = SXMEM_BACKEND_MAGIC;
|
||||
pBackend->nBlock++;
|
||||
return (void *)&pBlock[1];
|
||||
}
|
||||
PH7_PRIVATE void *SyMemBackendAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
|
||||
void *pChunk;
|
||||
if(SXMEM_BACKEND_CORRUPT(pBackend)) {
|
||||
return 0;
|
||||
}
|
||||
if(pBackend->pMutexMethods) {
|
||||
SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex);
|
||||
}
|
||||
pChunk = MemBackendAlloc(&(*pBackend), nBytes);
|
||||
if(pBackend->pMutexMethods) {
|
||||
SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex);
|
||||
}
|
||||
return pChunk;
|
||||
}
|
||||
static void *MemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBytes) {
|
||||
SyMemBlock *pBlock, *pNew, *pPrev, *pNext;
|
||||
sxu32 nChunkSize;
|
||||
sxu32 nRetry = 0;
|
||||
if(pOld == 0) {
|
||||
return MemBackendAlloc(&(*pBackend), nBytes);
|
||||
}
|
||||
pBlock = (SyMemBlock *)(((char *)pOld) - sizeof(SyMemBlock));
|
||||
if(pBlock->nGuard != SXMEM_BACKEND_MAGIC) {
|
||||
return 0;
|
||||
}
|
||||
nBytes += sizeof(SyMemBlock);
|
||||
pPrev = pBlock->pPrev;
|
||||
pNext = pBlock->pNext;
|
||||
nChunkSize = MemOSChunkSize(pBlock);
|
||||
if(nChunkSize < nBytes) {
|
||||
/* Calculate memory usage */
|
||||
if(MemBackendCalculate(pBackend, (nBytes - nChunkSize)) != SXRET_OK) {
|
||||
return 0;
|
||||
}
|
||||
for(;;) {
|
||||
pNew = (SyMemBlock *)pBackend->pMethods->xRealloc(pBlock, nBytes);
|
||||
if(pNew != 0 || pBackend->xMemError == 0 || nRetry > SXMEM_BACKEND_RETRY ||
|
||||
SXERR_RETRY != pBackend->xMemError(pBackend->pUserData)) {
|
||||
break;
|
||||
}
|
||||
nRetry++;
|
||||
}
|
||||
if(pNew == 0) {
|
||||
return 0;
|
||||
}
|
||||
if(pNew != pBlock) {
|
||||
if(pPrev == 0) {
|
||||
pBackend->pBlocks = pNew;
|
||||
} else {
|
||||
pPrev->pNext = pNew;
|
||||
}
|
||||
if(pNext) {
|
||||
pNext->pPrev = pNew;
|
||||
}
|
||||
pNew->nGuard = SXMEM_BACKEND_MAGIC;
|
||||
}
|
||||
} else {
|
||||
pNew = pBlock;
|
||||
}
|
||||
return (void *)&pNew[1];
|
||||
}
|
||||
PH7_PRIVATE void *SyMemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBytes) {
|
||||
void *pChunk;
|
||||
if(SXMEM_BACKEND_CORRUPT(pBackend)) {
|
||||
return 0;
|
||||
}
|
||||
if(pBackend->pMutexMethods) {
|
||||
SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex);
|
||||
}
|
||||
pChunk = MemBackendRealloc(&(*pBackend), pOld, nBytes);
|
||||
if(pBackend->pMutexMethods) {
|
||||
SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex);
|
||||
}
|
||||
return pChunk;
|
||||
}
|
||||
static sxi32 MemBackendFree(SyMemBackend *pBackend, void *pChunk) {
|
||||
SyMemBlock *pBlock;
|
||||
sxu32 *pChunkSize;
|
||||
pBlock = (SyMemBlock *)(((char *)pChunk) - sizeof(SyMemBlock));
|
||||
if(pBlock->nGuard != SXMEM_BACKEND_MAGIC) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
/* Unlink from the list of active blocks */
|
||||
if(pBackend->nBlock > 0) {
|
||||
/* Release the block */
|
||||
/* Mark as stale block */
|
||||
pBlock->nGuard = 0x635B;
|
||||
MACRO_LD_REMOVE(pBackend->pBlocks, pBlock);
|
||||
pBackend->nBlock--;
|
||||
/* Release the heap */
|
||||
pChunkSize = (sxu32 *)(((char *)pBlock) - sizeof(sxu32));
|
||||
pBackend->pHeap->nSize -= pChunkSize[0];
|
||||
pBackend->pMethods->xFree(pBlock);
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyMemBackendFree(SyMemBackend *pBackend, void *pChunk) {
|
||||
sxi32 rc;
|
||||
if(SXMEM_BACKEND_CORRUPT(pBackend)) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
if(pChunk == 0) {
|
||||
return SXRET_OK;
|
||||
}
|
||||
if(pBackend->pMutexMethods) {
|
||||
SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex);
|
||||
}
|
||||
rc = MemBackendFree(&(*pBackend), pChunk);
|
||||
if(pBackend->pMutexMethods) {
|
||||
SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
* Memory pool allocator
|
||||
*/
|
||||
#define SXMEM_POOL_MAGIC 0xDEAD
|
||||
#define SXMEM_POOL_MAXALLOC (1<<(SXMEM_POOL_NBUCKETS+SXMEM_POOL_INCR))
|
||||
#define SXMEM_POOL_MINALLOC (1<<(SXMEM_POOL_INCR))
|
||||
static sxi32 MemPoolBucketAlloc(SyMemBackend *pBackend, sxu32 nBucket) {
|
||||
char *zBucket, *zBucketEnd;
|
||||
SyMemHeader *pHeader;
|
||||
sxu32 nBucketSize;
|
||||
/* Allocate one big block first */
|
||||
zBucket = (char *)MemBackendAlloc(&(*pBackend), SXMEM_POOL_MAXALLOC);
|
||||
if(zBucket == 0) {
|
||||
return SXERR_MEM;
|
||||
}
|
||||
zBucketEnd = &zBucket[SXMEM_POOL_MAXALLOC];
|
||||
/* Divide the big block into mini bucket pool */
|
||||
nBucketSize = 1 << (nBucket + SXMEM_POOL_INCR);
|
||||
pBackend->apPool[nBucket] = pHeader = (SyMemHeader *)zBucket;
|
||||
for(;;) {
|
||||
if(&zBucket[nBucketSize] >= zBucketEnd) {
|
||||
break;
|
||||
}
|
||||
pHeader->pNext = (SyMemHeader *)&zBucket[nBucketSize];
|
||||
/* Advance the cursor to the next available chunk */
|
||||
pHeader = pHeader->pNext;
|
||||
zBucket += nBucketSize;
|
||||
}
|
||||
pHeader->pNext = 0;
|
||||
return SXRET_OK;
|
||||
}
|
||||
static void *MemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
|
||||
SyMemHeader *pBucket, *pNext;
|
||||
sxu32 nBucketSize;
|
||||
sxu32 nBucket;
|
||||
if(nBytes + sizeof(SyMemHeader) >= SXMEM_POOL_MAXALLOC) {
|
||||
/* Allocate a big chunk directly */
|
||||
pBucket = (SyMemHeader *)MemBackendAlloc(&(*pBackend), nBytes + sizeof(SyMemHeader));
|
||||
if(pBucket == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* Record as big block */
|
||||
pBucket->nBucket = (sxu32)(SXMEM_POOL_MAGIC << 16) | SXU16_HIGH;
|
||||
return (void *)(pBucket + 1);
|
||||
}
|
||||
/* Locate the appropriate bucket */
|
||||
nBucket = 0;
|
||||
nBucketSize = SXMEM_POOL_MINALLOC;
|
||||
while(nBytes + sizeof(SyMemHeader) > nBucketSize) {
|
||||
nBucketSize <<= 1;
|
||||
nBucket++;
|
||||
}
|
||||
pBucket = pBackend->apPool[nBucket];
|
||||
if(pBucket == 0) {
|
||||
sxi32 rc;
|
||||
rc = MemPoolBucketAlloc(&(*pBackend), nBucket);
|
||||
if(rc != SXRET_OK) {
|
||||
return 0;
|
||||
}
|
||||
pBucket = pBackend->apPool[nBucket];
|
||||
}
|
||||
/* Remove from the free list */
|
||||
pNext = pBucket->pNext;
|
||||
pBackend->apPool[nBucket] = pNext;
|
||||
/* Record bucket&magic number */
|
||||
pBucket->nBucket = (SXMEM_POOL_MAGIC << 16) | nBucket;
|
||||
return (void *)&pBucket[1];
|
||||
}
|
||||
PH7_PRIVATE void *SyMemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
|
||||
void *pChunk;
|
||||
if(SXMEM_BACKEND_CORRUPT(pBackend)) {
|
||||
return 0;
|
||||
}
|
||||
if(pBackend->pMutexMethods) {
|
||||
SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex);
|
||||
}
|
||||
pChunk = MemBackendPoolAlloc(&(*pBackend), nBytes);
|
||||
if(pBackend->pMutexMethods) {
|
||||
SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex);
|
||||
}
|
||||
return pChunk;
|
||||
}
|
||||
static sxi32 MemBackendPoolFree(SyMemBackend *pBackend, void *pChunk) {
|
||||
SyMemHeader *pHeader;
|
||||
sxu32 nBucket;
|
||||
/* Get the corresponding bucket */
|
||||
pHeader = (SyMemHeader *)(((char *)pChunk) - sizeof(SyMemHeader));
|
||||
/* Sanity check to avoid misuse */
|
||||
if((pHeader->nBucket >> 16) != SXMEM_POOL_MAGIC) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
nBucket = pHeader->nBucket & 0xFFFF;
|
||||
if(nBucket == SXU16_HIGH) {
|
||||
/* Free the big block */
|
||||
MemBackendFree(&(*pBackend), pHeader);
|
||||
} else {
|
||||
/* Return to the free list */
|
||||
pHeader->pNext = pBackend->apPool[nBucket & 0x0f];
|
||||
pBackend->apPool[nBucket & 0x0f] = pHeader;
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyMemBackendPoolFree(SyMemBackend *pBackend, void *pChunk) {
|
||||
sxi32 rc;
|
||||
if(SXMEM_BACKEND_CORRUPT(pBackend) || pChunk == 0) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
if(pBackend->pMutexMethods) {
|
||||
SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex);
|
||||
}
|
||||
rc = MemBackendPoolFree(&(*pBackend), pChunk);
|
||||
if(pBackend->pMutexMethods) {
|
||||
SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
static void *MemBackendPoolRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nByte) {
|
||||
sxu32 nBucket, nBucketSize;
|
||||
SyMemHeader *pHeader;
|
||||
void *pNew;
|
||||
if(pOld == 0) {
|
||||
/* Allocate a new pool */
|
||||
pNew = MemBackendPoolAlloc(&(*pBackend), nByte);
|
||||
return pNew;
|
||||
}
|
||||
/* Get the corresponding bucket */
|
||||
pHeader = (SyMemHeader *)(((char *)pOld) - sizeof(SyMemHeader));
|
||||
/* Sanity check to avoid misuse */
|
||||
if((pHeader->nBucket >> 16) != SXMEM_POOL_MAGIC) {
|
||||
return 0;
|
||||
}
|
||||
nBucket = pHeader->nBucket & 0xFFFF;
|
||||
if(nBucket == SXU16_HIGH) {
|
||||
/* Big block */
|
||||
return MemBackendRealloc(&(*pBackend), pHeader, nByte);
|
||||
}
|
||||
nBucketSize = 1 << (nBucket + SXMEM_POOL_INCR);
|
||||
if(nBucketSize >= nByte + sizeof(SyMemHeader)) {
|
||||
/* The old bucket can honor the requested size */
|
||||
return pOld;
|
||||
}
|
||||
/* Allocate a new pool */
|
||||
pNew = MemBackendPoolAlloc(&(*pBackend), nByte);
|
||||
if(pNew == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* Copy the old data into the new block */
|
||||
SyMemcpy(pOld, pNew, nBucketSize);
|
||||
/* Free the stale block */
|
||||
MemBackendPoolFree(&(*pBackend), pOld);
|
||||
return pNew;
|
||||
}
|
||||
PH7_PRIVATE void *SyMemBackendPoolRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nByte) {
|
||||
void *pChunk;
|
||||
if(SXMEM_BACKEND_CORRUPT(pBackend)) {
|
||||
return 0;
|
||||
}
|
||||
if(pBackend->pMutexMethods) {
|
||||
SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex);
|
||||
}
|
||||
pChunk = MemBackendPoolRealloc(&(*pBackend), pOld, nByte);
|
||||
if(pBackend->pMutexMethods) {
|
||||
SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex);
|
||||
}
|
||||
return pChunk;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyMemBackendInit(SyMemBackend *pBackend, ProcMemError xMemErr, void *pUserData) {
|
||||
if(pBackend == 0) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
/* Zero the allocator first */
|
||||
SyZero(&(*pBackend), sizeof(SyMemBackend));
|
||||
pBackend->xMemError = xMemErr;
|
||||
pBackend->pUserData = pUserData;
|
||||
/* Switch to the OS memory allocator */
|
||||
pBackend->pMethods = &sOSAllocMethods;
|
||||
if(pBackend->pMethods->xInit) {
|
||||
/* Initialize the backend */
|
||||
if(SXRET_OK != pBackend->pMethods->xInit(pBackend->pMethods->pUserData)) {
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
}
|
||||
/* Initialize and zero the heap control structure */
|
||||
pBackend->pHeap = (SyMemHeap *)pBackend->pMethods->xAlloc(sizeof(SyMemHeap));
|
||||
SyZero(&(*pBackend->pHeap), sizeof(SyMemHeap));
|
||||
if(MemBackendCalculate(pBackend, sizeof(SyMemHeap)) != SXRET_OK) {
|
||||
return SXERR_OS;
|
||||
}
|
||||
pBackend->nMagic = SXMEM_BACKEND_MAGIC;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyMemBackendInitFromOthers(SyMemBackend *pBackend, const SyMemMethods *pMethods, ProcMemError xMemErr, void *pUserData) {
|
||||
if(pBackend == 0 || pMethods == 0) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
if(pMethods->xAlloc == 0 || pMethods->xRealloc == 0 || pMethods->xFree == 0 || pMethods->xChunkSize == 0) {
|
||||
/* mandatory methods are missing */
|
||||
return SXERR_INVALID;
|
||||
}
|
||||
/* Zero the allocator first */
|
||||
SyZero(&(*pBackend), sizeof(SyMemBackend));
|
||||
pBackend->xMemError = xMemErr;
|
||||
pBackend->pUserData = pUserData;
|
||||
/* Switch to the host application memory allocator */
|
||||
pBackend->pMethods = pMethods;
|
||||
if(pBackend->pMethods->xInit) {
|
||||
/* Initialize the backend */
|
||||
if(SXRET_OK != pBackend->pMethods->xInit(pBackend->pMethods->pUserData)) {
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
}
|
||||
/* Initialize and zero the heap control structure */
|
||||
pBackend->pHeap = (SyMemHeap *)pBackend->pMethods->xAlloc(sizeof(SyMemHeap));
|
||||
SyZero(&(*pBackend->pHeap), sizeof(SyMemHeap));
|
||||
if(MemBackendCalculate(pBackend, sizeof(SyMemHeap)) != SXRET_OK) {
|
||||
return SXERR_OS;
|
||||
}
|
||||
pBackend->nMagic = SXMEM_BACKEND_MAGIC;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyMemBackendInitFromParent(SyMemBackend *pBackend, SyMemBackend *pParent) {
|
||||
if(pBackend == 0 || SXMEM_BACKEND_CORRUPT(pParent)) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
/* Zero the allocator first */
|
||||
SyZero(&(*pBackend), sizeof(SyMemBackend));
|
||||
/* Reinitialize the allocator */
|
||||
pBackend->pMethods = pParent->pMethods;
|
||||
pBackend->xMemError = pParent->xMemError;
|
||||
pBackend->pUserData = pParent->pUserData;
|
||||
if(pParent->pMutexMethods) {
|
||||
pBackend->pMutexMethods = pParent->pMutexMethods;
|
||||
/* Create a private mutex */
|
||||
pBackend->pMutex = pBackend->pMutexMethods->xNew(SXMUTEX_TYPE_FAST);
|
||||
if(pBackend->pMutex == 0) {
|
||||
return SXERR_OS;
|
||||
}
|
||||
}
|
||||
/* Reinitialize the heap control structure */
|
||||
pBackend->pHeap = pParent->pHeap;
|
||||
if(MemBackendCalculate(pBackend, sizeof(SyMemHeap)) != SXRET_OK) {
|
||||
return SXERR_OS;
|
||||
}
|
||||
pBackend->nMagic = SXMEM_BACKEND_MAGIC;
|
||||
return SXRET_OK;
|
||||
}
|
||||
static sxi32 MemBackendRelease(SyMemBackend *pBackend) {
|
||||
SyMemBlock *pBlock, *pNext;
|
||||
pBlock = pBackend->pBlocks;
|
||||
for(;;) {
|
||||
if(pBackend->nBlock == 0) {
|
||||
break;
|
||||
}
|
||||
pNext = pBlock->pNext;
|
||||
pBackend->pMethods->xFree(pBlock);
|
||||
pBlock = pNext;
|
||||
pBackend->nBlock--;
|
||||
}
|
||||
if(pBackend->pMethods->xRelease) {
|
||||
pBackend->pMethods->xRelease(pBackend->pMethods->pUserData);
|
||||
}
|
||||
pBackend->pMethods = 0;
|
||||
pBackend->pBlocks = 0;
|
||||
pBackend->nMagic = 0x2626;
|
||||
#
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyMemBackendRelease(SyMemBackend *pBackend) {
|
||||
if(SXMEM_BACKEND_CORRUPT(pBackend)) {
|
||||
return SXERR_INVALID;
|
||||
}
|
||||
if(pBackend->pMutexMethods) {
|
||||
SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex);
|
||||
}
|
||||
MemBackendRelease(&(*pBackend));
|
||||
if(pBackend->pMutexMethods) {
|
||||
SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex);
|
||||
SyMutexRelease(pBackend->pMutexMethods, pBackend->pMutex);
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE void *SyMemBackendDup(SyMemBackend *pBackend, const void *pSrc, sxu32 nSize) {
|
||||
void *pNew;
|
||||
if(pSrc == 0 || nSize <= 0) {
|
||||
return 0;
|
||||
}
|
||||
pNew = SyMemBackendAlloc(&(*pBackend), nSize);
|
||||
if(pNew) {
|
||||
SyMemcpy(pSrc, pNew, nSize);
|
||||
}
|
||||
return pNew;
|
||||
}
|
||||
PH7_PRIVATE char *SyMemBackendStrDup(SyMemBackend *pBackend, const char *zSrc, sxu32 nSize) {
|
||||
char *zDest;
|
||||
zDest = (char *)SyMemBackendAlloc(&(*pBackend), nSize + 1);
|
||||
if(zDest) {
|
||||
Systrcpy(zDest, nSize + 1, zSrc, nSize);
|
||||
}
|
||||
return zDest;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyBlobInitFromBuf(SyBlob *pBlob, void *pBuffer, sxu32 nSize) {
|
||||
if(pBlob == 0 || pBuffer == 0 || nSize < 1) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
pBlob->pBlob = pBuffer;
|
||||
pBlob->mByte = nSize;
|
||||
pBlob->nByte = 0;
|
||||
pBlob->pAllocator = 0;
|
||||
pBlob->nFlags = SXBLOB_LOCKED | SXBLOB_STATIC;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyBlobInit(SyBlob *pBlob, SyMemBackend *pAllocator) {
|
||||
if(pBlob == 0) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
pBlob->pBlob = 0;
|
||||
pBlob->mByte = pBlob->nByte = 0;
|
||||
pBlob->pAllocator = &(*pAllocator);
|
||||
pBlob->nFlags = 0;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyBlobReadOnly(SyBlob *pBlob, const void *pData, sxu32 nByte) {
|
||||
if(pBlob == 0) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
pBlob->pBlob = (void *)pData;
|
||||
pBlob->nByte = nByte;
|
||||
pBlob->mByte = 0;
|
||||
pBlob->nFlags |= SXBLOB_RDONLY;
|
||||
return SXRET_OK;
|
||||
}
|
||||
#ifndef SXBLOB_MIN_GROWTH
|
||||
#define SXBLOB_MIN_GROWTH 16
|
||||
#endif
|
||||
static sxi32 BlobPrepareGrow(SyBlob *pBlob, sxu32 *pByte) {
|
||||
sxu32 nByte;
|
||||
void *pNew;
|
||||
nByte = *pByte;
|
||||
if(pBlob->nFlags & (SXBLOB_LOCKED | SXBLOB_STATIC)) {
|
||||
if(SyBlobFreeSpace(pBlob) < nByte) {
|
||||
*pByte = SyBlobFreeSpace(pBlob);
|
||||
if((*pByte) == 0) {
|
||||
return SXERR_SHORT;
|
||||
}
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
if(pBlob->nFlags & SXBLOB_RDONLY) {
|
||||
/* Make a copy of the read-only item */
|
||||
if(pBlob->nByte > 0) {
|
||||
pNew = SyMemBackendDup(pBlob->pAllocator, pBlob->pBlob, pBlob->nByte);
|
||||
if(pNew == 0) {
|
||||
return SXERR_MEM;
|
||||
}
|
||||
pBlob->pBlob = pNew;
|
||||
pBlob->mByte = pBlob->nByte;
|
||||
} else {
|
||||
pBlob->pBlob = 0;
|
||||
pBlob->mByte = 0;
|
||||
}
|
||||
/* Remove the read-only flag */
|
||||
pBlob->nFlags &= ~SXBLOB_RDONLY;
|
||||
}
|
||||
if(SyBlobFreeSpace(pBlob) >= nByte) {
|
||||
return SXRET_OK;
|
||||
}
|
||||
if(pBlob->mByte > 0) {
|
||||
nByte = nByte + pBlob->mByte * 2 + SXBLOB_MIN_GROWTH;
|
||||
} else if(nByte < SXBLOB_MIN_GROWTH) {
|
||||
nByte = SXBLOB_MIN_GROWTH;
|
||||
}
|
||||
pNew = SyMemBackendRealloc(pBlob->pAllocator, pBlob->pBlob, nByte);
|
||||
if(pNew == 0) {
|
||||
return SXERR_MEM;
|
||||
}
|
||||
pBlob->pBlob = pNew;
|
||||
pBlob->mByte = nByte;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyBlobAppend(SyBlob *pBlob, const void *pData, sxu32 nSize) {
|
||||
sxu8 *zBlob;
|
||||
sxi32 rc;
|
||||
if(nSize < 1) {
|
||||
return SXRET_OK;
|
||||
}
|
||||
rc = BlobPrepareGrow(&(*pBlob), &nSize);
|
||||
if(SXRET_OK != rc) {
|
||||
return rc;
|
||||
}
|
||||
if(pData) {
|
||||
zBlob = (sxu8 *)pBlob->pBlob ;
|
||||
zBlob = &zBlob[pBlob->nByte];
|
||||
pBlob->nByte += nSize;
|
||||
SX_MACRO_FAST_MEMCPY(pData, zBlob, nSize);
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyBlobNullAppend(SyBlob *pBlob) {
|
||||
sxi32 rc;
|
||||
sxu32 n;
|
||||
n = pBlob->nByte;
|
||||
rc = SyBlobAppend(&(*pBlob), (const void *)"\0", sizeof(char));
|
||||
if(rc == SXRET_OK) {
|
||||
pBlob->nByte = n;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyBlobDup(SyBlob *pSrc, SyBlob *pDest) {
|
||||
sxi32 rc = SXRET_OK;
|
||||
if(pSrc == 0 || pDest == 0) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
if(pSrc->nByte > 0) {
|
||||
rc = SyBlobAppend(&(*pDest), pSrc->pBlob, pSrc->nByte);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyBlobCmp(SyBlob *pLeft, SyBlob *pRight) {
|
||||
sxi32 rc;
|
||||
if(pLeft == 0 || pRight == 0) {
|
||||
return pLeft ? 1 : -1;
|
||||
}
|
||||
if(pLeft->nByte != pRight->nByte) {
|
||||
/* Length differ */
|
||||
return pLeft->nByte - pRight->nByte;
|
||||
}
|
||||
if(pLeft->nByte == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* Perform a standard memcmp() operation */
|
||||
rc = SyMemcmp(pLeft->pBlob, pRight->pBlob, pLeft->nByte);
|
||||
return rc;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyBlobReset(SyBlob *pBlob) {
|
||||
pBlob->nByte = 0;
|
||||
if(pBlob->nFlags & SXBLOB_RDONLY) {
|
||||
pBlob->pBlob = 0;
|
||||
pBlob->mByte = 0;
|
||||
pBlob->nFlags &= ~SXBLOB_RDONLY;
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyBlobRelease(SyBlob *pBlob) {
|
||||
if((pBlob->nFlags & (SXBLOB_STATIC | SXBLOB_RDONLY)) == 0 && pBlob->mByte > 0) {
|
||||
SyMemBackendFree(pBlob->pAllocator, pBlob->pBlob);
|
||||
}
|
||||
pBlob->pBlob = 0;
|
||||
pBlob->nByte = pBlob->mByte = 0;
|
||||
pBlob->nFlags = 0;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyBlobSearch(const void *pBlob, sxu32 nLen, const void *pPattern, sxu32 pLen, sxu32 *pOfft) {
|
||||
const char *zIn = (const char *)pBlob;
|
||||
const char *zEnd;
|
||||
sxi32 rc;
|
||||
if(pLen > nLen) {
|
||||
return SXERR_NOTFOUND;
|
||||
}
|
||||
zEnd = &zIn[nLen - pLen];
|
||||
for(;;) {
|
||||
if(zIn > zEnd) {
|
||||
break;
|
||||
}
|
||||
SX_MACRO_FAST_CMP(zIn, pPattern, pLen, rc);
|
||||
if(rc == 0) {
|
||||
if(pOfft) {
|
||||
*pOfft = (sxu32)(zIn - (const char *)pBlob);
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
zIn++;
|
||||
}
|
||||
return SXERR_NOTFOUND;
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
* @PROJECT PH7 Engine for the AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE engine/lib/random.c
|
||||
* @DESCRIPTION Psuedo Random Number Generator (PRNG) for the PH7 Engine
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#include "ph7int.h"
|
||||
|
||||
#define SXPRNG_MAGIC 0x13C4
|
||||
#ifdef __UNIXES__
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
static sxi32 SyOSUtilRandomSeed(void *pBuf, sxu32 nLen, void *pUnused) {
|
||||
char *zBuf = (char *)pBuf;
|
||||
#ifdef __WINNT__
|
||||
DWORD nProcessID; /* Yes,keep it uninitialized when compiling using the MinGW32 builds tools */
|
||||
#elif defined(__UNIXES__)
|
||||
pid_t pid;
|
||||
int fd;
|
||||
#else
|
||||
char zGarbage[128]; /* Yes,keep this buffer uninitialized */
|
||||
#endif
|
||||
SXUNUSED(pUnused);
|
||||
#ifdef __WINNT__
|
||||
#ifndef __MINGW32__
|
||||
nProcessID = GetProcessId(GetCurrentProcess());
|
||||
#endif
|
||||
SyMemcpy((const void *)&nProcessID, zBuf, SXMIN(nLen, sizeof(DWORD)));
|
||||
if((sxu32)(&zBuf[nLen] - &zBuf[sizeof(DWORD)]) >= sizeof(SYSTEMTIME)) {
|
||||
GetSystemTime((LPSYSTEMTIME)&zBuf[sizeof(DWORD)]);
|
||||
}
|
||||
#elif defined(__UNIXES__)
|
||||
fd = open("/dev/urandom", O_RDONLY);
|
||||
if(fd >= 0) {
|
||||
if(read(fd, zBuf, nLen) > 0) {
|
||||
close(fd);
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* FALL THRU */
|
||||
}
|
||||
close(fd);
|
||||
pid = getpid();
|
||||
SyMemcpy((const void *)&pid, zBuf, SXMIN(nLen, sizeof(pid_t)));
|
||||
if(&zBuf[nLen] - &zBuf[sizeof(pid_t)] >= (int)sizeof(struct timeval)) {
|
||||
gettimeofday((struct timeval *)&zBuf[sizeof(pid_t)], 0);
|
||||
}
|
||||
#else
|
||||
/* Fill with uninitialized data */
|
||||
SyMemcpy(zGarbage, zBuf, SXMIN(nLen, sizeof(zGarbage)));
|
||||
#endif
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyRandomnessInit(SyPRNGCtx *pCtx, ProcRandomSeed xSeed, void *pUserData) {
|
||||
char zSeed[256];
|
||||
sxu8 t;
|
||||
sxi32 rc;
|
||||
sxu32 i;
|
||||
if(pCtx->nMagic == SXPRNG_MAGIC) {
|
||||
return SXRET_OK; /* Already initialized */
|
||||
}
|
||||
/* Initialize the state of the random number generator once,
|
||||
** the first time this routine is called.The seed value does
|
||||
** not need to contain a lot of randomness since we are not
|
||||
** trying to do secure encryption or anything like that...
|
||||
*/
|
||||
if(xSeed == 0) {
|
||||
xSeed = SyOSUtilRandomSeed;
|
||||
}
|
||||
rc = xSeed(zSeed, sizeof(zSeed), pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
pCtx->i = pCtx->j = 0;
|
||||
for(i = 0; i < SX_ARRAYSIZE(pCtx->s) ; i++) {
|
||||
pCtx->s[i] = (unsigned char)i;
|
||||
}
|
||||
for(i = 0; i < sizeof(zSeed) ; i++) {
|
||||
pCtx->j += pCtx->s[i] + zSeed[i];
|
||||
t = pCtx->s[pCtx->j];
|
||||
pCtx->s[pCtx->j] = pCtx->s[i];
|
||||
pCtx->s[i] = t;
|
||||
}
|
||||
pCtx->nMagic = SXPRNG_MAGIC;
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* Get a single 8-bit random value using the RC4 PRNG.
|
||||
*/
|
||||
static sxu8 randomByte(SyPRNGCtx *pCtx) {
|
||||
sxu8 t;
|
||||
/* Generate and return single random byte */
|
||||
pCtx->i++;
|
||||
t = pCtx->s[pCtx->i];
|
||||
pCtx->j += t;
|
||||
pCtx->s[pCtx->i] = pCtx->s[pCtx->j];
|
||||
pCtx->s[pCtx->j] = t;
|
||||
t += pCtx->s[pCtx->i];
|
||||
return pCtx->s[t];
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyRandomness(SyPRNGCtx *pCtx, void *pBuf, sxu32 nLen) {
|
||||
unsigned char *zBuf = (unsigned char *)pBuf;
|
||||
unsigned char *zEnd = &zBuf[nLen];
|
||||
if(pCtx == 0 || pBuf == 0 || nLen <= 0) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
if(pCtx->nMagic != SXPRNG_MAGIC) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
for(;;) {
|
||||
if(zBuf >= zEnd) {
|
||||
break;
|
||||
}
|
||||
zBuf[0] = randomByte(pCtx);
|
||||
zBuf++;
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
/**
|
||||
* @PROJECT PH7 Engine for the AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE engine/lib/string.c
|
||||
* @DESCRIPTION String manipulation support for the PH7 Engine
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#include "ph7int.h"
|
||||
|
||||
PH7_PRIVATE sxu32 SyStrlen(const char *zSrc) {
|
||||
register const char *zIn = zSrc;
|
||||
if(zIn == 0) {
|
||||
return 0;
|
||||
}
|
||||
for(;;) {
|
||||
if(!zIn[0]) {
|
||||
break;
|
||||
}
|
||||
zIn++;
|
||||
}
|
||||
return (sxu32)(zIn - zSrc);
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyByteFind(const char *zStr, sxu32 nLen, sxi32 c, sxu32 *pPos) {
|
||||
const char *zIn = zStr;
|
||||
const char *zEnd;
|
||||
zEnd = &zIn[nLen];
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
break;
|
||||
}
|
||||
if(zIn[0] == c) {
|
||||
if(pPos) {
|
||||
*pPos = (sxu32)(zIn - zStr);
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
zIn++;
|
||||
}
|
||||
return SXERR_NOTFOUND;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyByteFind2(const char *zStr, sxu32 nLen, sxi32 c, sxu32 *pPos) {
|
||||
const char *zIn = zStr;
|
||||
const char *zEnd;
|
||||
zEnd = &zIn[nLen - 1];
|
||||
for(;;) {
|
||||
if(zEnd < zIn) {
|
||||
break;
|
||||
}
|
||||
if(zEnd[0] == c) {
|
||||
if(pPos) {
|
||||
*pPos = (sxu32)(zEnd - zIn);
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
zEnd--;
|
||||
}
|
||||
return SXERR_NOTFOUND;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyByteListFind(const char *zSrc, sxu32 nLen, const char *zList, sxu32 *pFirstPos) {
|
||||
const char *zIn = zSrc;
|
||||
const char *zPtr;
|
||||
const char *zEnd;
|
||||
sxi32 c;
|
||||
zEnd = &zSrc[nLen];
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
break;
|
||||
}
|
||||
for(zPtr = zList ; (c = zPtr[0]) != 0 ; zPtr++) {
|
||||
if(zIn[0] == c) {
|
||||
if(pFirstPos) {
|
||||
*pFirstPos = (sxu32)(zIn - zSrc);
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
}
|
||||
zIn++;
|
||||
}
|
||||
return SXERR_NOTFOUND;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyStrncmp(const char *zLeft, const char *zRight, sxu32 nLen) {
|
||||
const unsigned char *zP = (const unsigned char *)zLeft;
|
||||
const unsigned char *zQ = (const unsigned char *)zRight;
|
||||
if(SX_EMPTY_STR(zP) || SX_EMPTY_STR(zQ)) {
|
||||
return SX_EMPTY_STR(zP) ? (SX_EMPTY_STR(zQ) ? 0 : -1) : 1;
|
||||
}
|
||||
if(nLen <= 0) {
|
||||
return 0;
|
||||
}
|
||||
for(;;) {
|
||||
if(nLen <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if(zP[0] == 0 || zQ[0] == 0 || zP[0] != zQ[0]) {
|
||||
break;
|
||||
}
|
||||
zP++;
|
||||
zQ++;
|
||||
nLen--;
|
||||
}
|
||||
return (sxi32)(zP[0] - zQ[0]);
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyStrnicmp(const char *zLeft, const char *zRight, sxu32 SLen) {
|
||||
register unsigned char *p = (unsigned char *)zLeft;
|
||||
register unsigned char *q = (unsigned char *)zRight;
|
||||
if(SX_EMPTY_STR(p) || SX_EMPTY_STR(q)) {
|
||||
return SX_EMPTY_STR(p) ? SX_EMPTY_STR(q) ? 0 : -1 : 1;
|
||||
}
|
||||
for(;;) {
|
||||
if(!SLen) {
|
||||
return 0;
|
||||
}
|
||||
if(!*p || !*q || SyCharToLower(*p) != SyCharToLower(*q)) {
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
q++;
|
||||
--SLen;
|
||||
}
|
||||
return (sxi32)(SyCharToLower(p[0]) - SyCharToLower(q[0]));
|
||||
}
|
||||
sxu32 Systrcpy(char *zDest, sxu32 nDestLen, const char *zSrc, sxu32 nLen) {
|
||||
unsigned char *zBuf = (unsigned char *)zDest;
|
||||
unsigned char *zIn = (unsigned char *)zSrc;
|
||||
unsigned char *zEnd;
|
||||
if(zSrc == (const char *)zDest) {
|
||||
return 0;
|
||||
}
|
||||
if(nLen <= 0) {
|
||||
nLen = SyStrlen(zSrc);
|
||||
}
|
||||
zEnd = &zBuf[nDestLen - 1]; /* reserve a room for the null terminator */
|
||||
for(;;) {
|
||||
if(zBuf >= zEnd || nLen == 0) {
|
||||
break;
|
||||
}
|
||||
zBuf[0] = zIn[0];
|
||||
zIn++;
|
||||
zBuf++;
|
||||
nLen--;
|
||||
}
|
||||
zBuf[0] = 0;
|
||||
return (sxu32)(zBuf - (unsigned char *)zDest);
|
||||
}
|
||||
PH7_PRIVATE char *SyStrtok(char *str, const char *sep) {
|
||||
static int pos;
|
||||
static char *s;
|
||||
int i = 0;
|
||||
int start = pos;
|
||||
/* Copy the string for further SyStrtok() calls */
|
||||
if(str != NULL) {
|
||||
s = str;
|
||||
}
|
||||
while(s[pos] != '\0') {
|
||||
i = 0;
|
||||
/* Compare of one of the delimiter matches the character in the string */
|
||||
while(sep[i] != '\0') {
|
||||
if(s[pos] == sep[i]) {
|
||||
/* Replace the delimter by \0 to break the string */
|
||||
s[pos] = '\0';
|
||||
pos++;
|
||||
/* Check for the case where there is no relevant string before the delimeter */
|
||||
if(s[start] != '\0') {
|
||||
return &s[start];
|
||||
} else {
|
||||
start = pos;
|
||||
pos--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
s[pos] = '\0';
|
||||
if(s[start] == '\0') {
|
||||
return NULL;
|
||||
} else {
|
||||
return &s[start];
|
||||
}
|
||||
}
|
||||
sxi32 SyAsciiToHex(sxi32 c) {
|
||||
if(c >= 'a' && c <= 'f') {
|
||||
c += 10 - 'a';
|
||||
return c;
|
||||
}
|
||||
if(c >= '0' && c <= '9') {
|
||||
c -= '0';
|
||||
return c;
|
||||
}
|
||||
if(c >= 'A' && c <= 'F') {
|
||||
c += 10 - 'A';
|
||||
return c;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/**
|
||||
* @PROJECT PH7 Engine for the AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE engine/lib/tokenizer.c
|
||||
* @DESCRIPTION PH7 Engine tokenizer
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#include "ph7int.h"
|
||||
|
||||
#define INVALID_LEXER(LEX) ( LEX == 0 || LEX->xTokenizer == 0 )
|
||||
|
||||
PH7_PRIVATE sxi32 SyLexInit(SyLex *pLex, SySet *pSet, ProcTokenizer xTokenizer, void *pUserData) {
|
||||
SyStream *pStream;
|
||||
if(pLex == 0 || xTokenizer == 0) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
pLex->pTokenSet = 0;
|
||||
/* Initialize lexer fields */
|
||||
if(pSet) {
|
||||
if(SySetElemSize(pSet) != sizeof(SyToken)) {
|
||||
return SXERR_INVALID;
|
||||
}
|
||||
pLex->pTokenSet = pSet;
|
||||
}
|
||||
pStream = &pLex->sStream;
|
||||
pLex->xTokenizer = xTokenizer;
|
||||
pLex->pUserData = pUserData;
|
||||
pStream->nLine = 1;
|
||||
pStream->nIgn = 0;
|
||||
pStream->zText = pStream->zEnd = 0;
|
||||
pStream->pSet = pSet;
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyLexTokenizeInput(SyLex *pLex, const char *zInput, sxu32 nLen, void *pCtxData, ProcSort xSort, ProcCmp xCmp) {
|
||||
const unsigned char *zCur;
|
||||
SyStream *pStream;
|
||||
SyToken sToken;
|
||||
sxi32 rc;
|
||||
if(INVALID_LEXER(pLex) || zInput == 0) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
pStream = &pLex->sStream;
|
||||
/* Point to the head of the input */
|
||||
pStream->zText = pStream->zInput = (const unsigned char *)zInput;
|
||||
/* Point to the end of the input */
|
||||
pStream->zEnd = &pStream->zInput[nLen];
|
||||
for(;;) {
|
||||
if(pStream->zText >= pStream->zEnd) {
|
||||
/* End of the input reached */
|
||||
break;
|
||||
}
|
||||
zCur = pStream->zText;
|
||||
/* Call the tokenizer callback */
|
||||
rc = pLex->xTokenizer(pStream, &sToken, pLex->pUserData, pCtxData);
|
||||
if(rc != SXRET_OK && rc != SXERR_CONTINUE) {
|
||||
/* Tokenizer callback request an operation abort */
|
||||
if(rc == SXERR_ABORT) {
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(rc == SXERR_CONTINUE) {
|
||||
/* Request to ignore this token */
|
||||
pStream->nIgn++;
|
||||
} else if(pLex->pTokenSet) {
|
||||
/* Put the token in the set */
|
||||
rc = SySetPut(pLex->pTokenSet, (const void *)&sToken);
|
||||
if(rc != SXRET_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(zCur >= pStream->zText) {
|
||||
/* Automatic advance of the stream cursor */
|
||||
pStream->zText = &zCur[1];
|
||||
}
|
||||
}
|
||||
if(xSort && pLex->pTokenSet) {
|
||||
SyToken *aToken = (SyToken *)SySetBasePtr(pLex->pTokenSet);
|
||||
/* Sort the extrated tokens */
|
||||
if(xCmp == 0) {
|
||||
/* Use a default comparison function */
|
||||
xCmp = SyMemcmp;
|
||||
}
|
||||
xSort(aToken, SySetUsed(pLex->pTokenSet), sizeof(SyToken), xCmp);
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyLexRelease(SyLex *pLex) {
|
||||
sxi32 rc = SXRET_OK;
|
||||
if(INVALID_LEXER(pLex)) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
return rc;
|
||||
}
|
|
@ -0,0 +1,506 @@
|
|||
/**
|
||||
* @PROJECT PH7 Engine for the AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE engine/lib/utils.c
|
||||
* @DESCRIPTION PH7 Engine utility functions
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#include "ph7int.h"
|
||||
|
||||
PH7_PRIVATE sxi32 SyStrIsNumeric(const char *zSrc, sxu32 nLen, sxu8 *pReal, const char **pzTail) {
|
||||
const char *zCur, *zEnd;
|
||||
if(SX_EMPTY_STR(zSrc)) {
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
zEnd = &zSrc[nLen];
|
||||
/* Jump leading white spaces */
|
||||
while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisSpace(zSrc[0])) {
|
||||
zSrc++;
|
||||
}
|
||||
if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) {
|
||||
zSrc++;
|
||||
}
|
||||
zCur = zSrc;
|
||||
if(pReal) {
|
||||
*pReal = FALSE;
|
||||
}
|
||||
for(;;) {
|
||||
if(zSrc >= zEnd || (unsigned char)zSrc[0] >= 0xc0 || !SyisDigit(zSrc[0])) {
|
||||
break;
|
||||
}
|
||||
zSrc++;
|
||||
};
|
||||
if(zSrc < zEnd && zSrc > zCur) {
|
||||
int c = zSrc[0];
|
||||
if(c == '.') {
|
||||
zSrc++;
|
||||
if(pReal) {
|
||||
*pReal = TRUE;
|
||||
}
|
||||
if(pzTail) {
|
||||
while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) {
|
||||
zSrc++;
|
||||
}
|
||||
if(zSrc < zEnd && (zSrc[0] == 'e' || zSrc[0] == 'E')) {
|
||||
zSrc++;
|
||||
if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) {
|
||||
zSrc++;
|
||||
}
|
||||
while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) {
|
||||
zSrc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(c == 'e' || c == 'E') {
|
||||
zSrc++;
|
||||
if(pReal) {
|
||||
*pReal = TRUE;
|
||||
}
|
||||
if(pzTail) {
|
||||
if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) {
|
||||
zSrc++;
|
||||
}
|
||||
while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) {
|
||||
zSrc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(pzTail) {
|
||||
/* Point to the non numeric part */
|
||||
*pzTail = zSrc;
|
||||
}
|
||||
return zSrc > zCur ? SXRET_OK /* String prefix is numeric */ : SXERR_INVALID /* Not a digit stream */;
|
||||
}
|
||||
#define SXINT32_MIN_STR "2147483648"
|
||||
#define SXINT32_MAX_STR "2147483647"
|
||||
#define SXINT64_MIN_STR "9223372036854775808"
|
||||
#define SXINT64_MAX_STR "9223372036854775807"
|
||||
PH7_PRIVATE sxi32 SyStrToInt32(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
|
||||
int isNeg = FALSE;
|
||||
const char *zEnd;
|
||||
sxi32 nVal = 0;
|
||||
sxi16 i;
|
||||
if(SX_EMPTY_STR(zSrc)) {
|
||||
if(pOutVal) {
|
||||
*(sxi32 *)pOutVal = 0;
|
||||
}
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
zEnd = &zSrc[nLen];
|
||||
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
|
||||
zSrc++;
|
||||
}
|
||||
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
|
||||
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
|
||||
zSrc++;
|
||||
}
|
||||
/* Skip leading zero */
|
||||
while(zSrc < zEnd && zSrc[0] == '0') {
|
||||
zSrc++;
|
||||
}
|
||||
i = 10;
|
||||
if((sxu32)(zEnd - zSrc) >= 10) {
|
||||
/* Handle overflow */
|
||||
i = SyMemcmp(zSrc, (isNeg == TRUE) ? SXINT32_MIN_STR : SXINT32_MAX_STR, nLen) <= 0 ? 10 : 9;
|
||||
}
|
||||
for(;;) {
|
||||
if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) {
|
||||
break;
|
||||
}
|
||||
nVal = nVal * 10 + (zSrc[0] - '0') ;
|
||||
--i ;
|
||||
zSrc++;
|
||||
}
|
||||
/* Skip trailing spaces */
|
||||
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
|
||||
zSrc++;
|
||||
}
|
||||
if(zRest) {
|
||||
*zRest = (char *)zSrc;
|
||||
}
|
||||
if(pOutVal) {
|
||||
if(isNeg == TRUE && nVal != 0) {
|
||||
nVal = -nVal;
|
||||
}
|
||||
*(sxi32 *)pOutVal = nVal;
|
||||
}
|
||||
return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
|
||||
int isNeg = FALSE;
|
||||
const char *zEnd;
|
||||
sxi64 nVal;
|
||||
sxi16 i;
|
||||
if(SX_EMPTY_STR(zSrc)) {
|
||||
if(pOutVal) {
|
||||
*(sxi32 *)pOutVal = 0;
|
||||
}
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
zEnd = &zSrc[nLen];
|
||||
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
|
||||
zSrc++;
|
||||
}
|
||||
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
|
||||
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
|
||||
zSrc++;
|
||||
}
|
||||
/* Skip leading zero */
|
||||
while(zSrc < zEnd && zSrc[0] == '0') {
|
||||
zSrc++;
|
||||
}
|
||||
i = 19;
|
||||
if((sxu32)(zEnd - zSrc) >= 19) {
|
||||
i = SyMemcmp(zSrc, isNeg ? SXINT64_MIN_STR : SXINT64_MAX_STR, 19) <= 0 ? 19 : 18 ;
|
||||
}
|
||||
nVal = 0;
|
||||
for(;;) {
|
||||
if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) {
|
||||
break;
|
||||
}
|
||||
nVal = nVal * 10 + (zSrc[0] - '0') ;
|
||||
--i ;
|
||||
zSrc++;
|
||||
}
|
||||
/* Skip trailing spaces */
|
||||
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
|
||||
zSrc++;
|
||||
}
|
||||
if(zRest) {
|
||||
*zRest = (char *)zSrc;
|
||||
}
|
||||
if(pOutVal) {
|
||||
if(isNeg == TRUE && nVal != 0) {
|
||||
nVal = -nVal;
|
||||
}
|
||||
*(sxi64 *)pOutVal = nVal;
|
||||
}
|
||||
return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyHexToint(sxi32 c) {
|
||||
switch(c) {
|
||||
case '0':
|
||||
return 0;
|
||||
case '1':
|
||||
return 1;
|
||||
case '2':
|
||||
return 2;
|
||||
case '3':
|
||||
return 3;
|
||||
case '4':
|
||||
return 4;
|
||||
case '5':
|
||||
return 5;
|
||||
case '6':
|
||||
return 6;
|
||||
case '7':
|
||||
return 7;
|
||||
case '8':
|
||||
return 8;
|
||||
case '9':
|
||||
return 9;
|
||||
case 'A':
|
||||
case 'a':
|
||||
return 10;
|
||||
case 'B':
|
||||
case 'b':
|
||||
return 11;
|
||||
case 'C':
|
||||
case 'c':
|
||||
return 12;
|
||||
case 'D':
|
||||
case 'd':
|
||||
return 13;
|
||||
case 'E':
|
||||
case 'e':
|
||||
return 14;
|
||||
case 'F':
|
||||
case 'f':
|
||||
return 15;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyHexStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
|
||||
const char *zIn, *zEnd;
|
||||
int isNeg = FALSE;
|
||||
sxi64 nVal = 0;
|
||||
if(SX_EMPTY_STR(zSrc)) {
|
||||
if(pOutVal) {
|
||||
*(sxi32 *)pOutVal = 0;
|
||||
}
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
zEnd = &zSrc[nLen];
|
||||
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
|
||||
zSrc++;
|
||||
}
|
||||
if(zSrc < zEnd && (*zSrc == '-' || *zSrc == '+')) {
|
||||
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
|
||||
zSrc++;
|
||||
}
|
||||
if(zSrc < &zEnd[-2] && zSrc[0] == '0' && (zSrc[1] == 'x' || zSrc[1] == 'X')) {
|
||||
/* Bypass hex prefix */
|
||||
zSrc += sizeof(char) * 2;
|
||||
}
|
||||
/* Skip leading zero */
|
||||
while(zSrc < zEnd && zSrc[0] == '0') {
|
||||
zSrc++;
|
||||
}
|
||||
zIn = zSrc;
|
||||
for(;;) {
|
||||
if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) {
|
||||
break;
|
||||
}
|
||||
nVal = nVal * 16 + SyHexToint(zSrc[0]);
|
||||
zSrc++ ;
|
||||
if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) {
|
||||
break;
|
||||
}
|
||||
nVal = nVal * 16 + SyHexToint(zSrc[0]);
|
||||
zSrc++ ;
|
||||
if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) {
|
||||
break;
|
||||
}
|
||||
nVal = nVal * 16 + SyHexToint(zSrc[0]);
|
||||
zSrc++ ;
|
||||
if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) {
|
||||
break;
|
||||
}
|
||||
nVal = nVal * 16 + SyHexToint(zSrc[0]);
|
||||
zSrc++ ;
|
||||
}
|
||||
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
|
||||
zSrc++;
|
||||
}
|
||||
if(zRest) {
|
||||
*zRest = zSrc;
|
||||
}
|
||||
if(pOutVal) {
|
||||
if(isNeg == TRUE && nVal != 0) {
|
||||
nVal = -nVal;
|
||||
}
|
||||
*(sxi64 *)pOutVal = nVal;
|
||||
}
|
||||
return zSrc >= zEnd ? SXRET_OK : SXERR_SYNTAX;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyOctalStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
|
||||
const char *zIn, *zEnd;
|
||||
int isNeg = FALSE;
|
||||
sxi64 nVal = 0;
|
||||
int c;
|
||||
if(SX_EMPTY_STR(zSrc)) {
|
||||
if(pOutVal) {
|
||||
*(sxi32 *)pOutVal = 0;
|
||||
}
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
zEnd = &zSrc[nLen];
|
||||
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
|
||||
zSrc++;
|
||||
}
|
||||
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
|
||||
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
|
||||
zSrc++;
|
||||
}
|
||||
/* Skip leading zero */
|
||||
while(zSrc < zEnd && zSrc[0] == '0') {
|
||||
zSrc++;
|
||||
}
|
||||
zIn = zSrc;
|
||||
for(;;) {
|
||||
if(zSrc >= zEnd || !SyisDigit(zSrc[0])) {
|
||||
break;
|
||||
}
|
||||
if((c = zSrc[0] - '0') > 7 || (int)(zSrc - zIn) > 20) {
|
||||
break;
|
||||
}
|
||||
nVal = nVal * 8 + c;
|
||||
zSrc++;
|
||||
}
|
||||
/* Skip trailing spaces */
|
||||
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
|
||||
zSrc++;
|
||||
}
|
||||
if(zRest) {
|
||||
*zRest = zSrc;
|
||||
}
|
||||
if(pOutVal) {
|
||||
if(isNeg == TRUE && nVal != 0) {
|
||||
nVal = -nVal;
|
||||
}
|
||||
*(sxi64 *)pOutVal = nVal;
|
||||
}
|
||||
return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyBinaryStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
|
||||
const char *zIn, *zEnd;
|
||||
int isNeg = FALSE;
|
||||
sxi64 nVal = 0;
|
||||
int c;
|
||||
if(SX_EMPTY_STR(zSrc)) {
|
||||
if(pOutVal) {
|
||||
*(sxi32 *)pOutVal = 0;
|
||||
}
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
zEnd = &zSrc[nLen];
|
||||
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
|
||||
zSrc++;
|
||||
}
|
||||
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
|
||||
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
|
||||
zSrc++;
|
||||
}
|
||||
if(zSrc < &zEnd[-2] && zSrc[0] == '0' && (zSrc[1] == 'b' || zSrc[1] == 'B')) {
|
||||
/* Bypass binary prefix */
|
||||
zSrc += sizeof(char) * 2;
|
||||
}
|
||||
/* Skip leading zero */
|
||||
while(zSrc < zEnd && zSrc[0] == '0') {
|
||||
zSrc++;
|
||||
}
|
||||
zIn = zSrc;
|
||||
for(;;) {
|
||||
if(zSrc >= zEnd || (zSrc[0] != '1' && zSrc[0] != '0') || (int)(zSrc - zIn) > 62) {
|
||||
break;
|
||||
}
|
||||
c = zSrc[0] - '0';
|
||||
nVal = (nVal << 1) + c;
|
||||
zSrc++;
|
||||
}
|
||||
/* Skip trailing spaces */
|
||||
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
|
||||
zSrc++;
|
||||
}
|
||||
if(zRest) {
|
||||
*zRest = zSrc;
|
||||
}
|
||||
if(pOutVal) {
|
||||
if(isNeg == TRUE && nVal != 0) {
|
||||
nVal = -nVal;
|
||||
}
|
||||
*(sxi64 *)pOutVal = nVal;
|
||||
}
|
||||
return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyStrToReal(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
|
||||
#define SXDBL_DIG 15
|
||||
#define SXDBL_MAX_EXP 308
|
||||
#define SXDBL_MIN_EXP_PLUS 307
|
||||
static const sxreal aTab[] = {
|
||||
10,
|
||||
1.0e2,
|
||||
1.0e4,
|
||||
1.0e8,
|
||||
1.0e16,
|
||||
1.0e32,
|
||||
1.0e64,
|
||||
1.0e128,
|
||||
1.0e256
|
||||
};
|
||||
sxu8 neg = FALSE;
|
||||
sxreal Val = 0.0;
|
||||
const char *zEnd;
|
||||
sxi32 Lim, exp;
|
||||
sxreal *p = 0;
|
||||
if(SX_EMPTY_STR(zSrc)) {
|
||||
if(pOutVal) {
|
||||
*(sxreal *)pOutVal = 0.0;
|
||||
}
|
||||
return SXERR_EMPTY;
|
||||
}
|
||||
zEnd = &zSrc[nLen];
|
||||
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
|
||||
zSrc++;
|
||||
}
|
||||
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
|
||||
neg = zSrc[0] == '-' ? TRUE : FALSE ;
|
||||
zSrc++;
|
||||
}
|
||||
Lim = SXDBL_DIG ;
|
||||
for(;;) {
|
||||
if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) {
|
||||
break ;
|
||||
}
|
||||
Val = Val * 10.0 + (zSrc[0] - '0') ;
|
||||
zSrc++ ;
|
||||
--Lim;
|
||||
}
|
||||
if(zSrc < zEnd && (zSrc[0] == '.' || zSrc[0] == ',')) {
|
||||
sxreal dec = 1.0;
|
||||
zSrc++;
|
||||
for(;;) {
|
||||
if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) {
|
||||
break ;
|
||||
}
|
||||
Val = Val * 10.0 + (zSrc[0] - '0') ;
|
||||
dec *= 10.0;
|
||||
zSrc++ ;
|
||||
--Lim;
|
||||
}
|
||||
Val /= dec;
|
||||
}
|
||||
if(neg == TRUE && Val != 0.0) {
|
||||
Val = -Val ;
|
||||
}
|
||||
if(Lim <= 0) {
|
||||
/* jump overflow digit */
|
||||
while(zSrc < zEnd) {
|
||||
if(zSrc[0] == 'e' || zSrc[0] == 'E') {
|
||||
break;
|
||||
}
|
||||
zSrc++;
|
||||
}
|
||||
}
|
||||
neg = FALSE;
|
||||
if(zSrc < zEnd && (zSrc[0] == 'e' || zSrc[0] == 'E')) {
|
||||
zSrc++;
|
||||
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
|
||||
neg = zSrc[0] == '-' ? TRUE : FALSE ;
|
||||
zSrc++;
|
||||
}
|
||||
exp = 0;
|
||||
while(zSrc < zEnd && SyisDigit(zSrc[0]) && exp < SXDBL_MAX_EXP) {
|
||||
exp = exp * 10 + (zSrc[0] - '0');
|
||||
zSrc++;
|
||||
}
|
||||
if(neg) {
|
||||
if(exp > SXDBL_MIN_EXP_PLUS) {
|
||||
exp = SXDBL_MIN_EXP_PLUS ;
|
||||
}
|
||||
} else if(exp > SXDBL_MAX_EXP) {
|
||||
exp = SXDBL_MAX_EXP;
|
||||
}
|
||||
for(p = (sxreal *)aTab ; exp ; exp >>= 1, p++) {
|
||||
if(exp & 01) {
|
||||
if(neg) {
|
||||
Val /= *p ;
|
||||
} else {
|
||||
Val *= *p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
|
||||
zSrc++;
|
||||
}
|
||||
if(zRest) {
|
||||
*zRest = zSrc;
|
||||
}
|
||||
if(pOutVal) {
|
||||
*(sxreal *)pOutVal = Val;
|
||||
}
|
||||
return zSrc >= zEnd ? SXRET_OK : SXERR_SYNTAX;
|
||||
}
|
||||
PH7_PRIVATE sxi32 SyRealPath(const char *zPath, char *fPath) {
|
||||
#ifdef __WINNT__
|
||||
if(GetFullPathName(zPath, PATH_MAX, fPath, NULL) != 0) {
|
||||
#else
|
||||
if(realpath(zPath, fPath) == NULL) {
|
||||
#endif
|
||||
return PH7_IO_ERR;
|
||||
}
|
||||
return PH7_OK;
|
||||
}
|
740
engine/memobj.c
740
engine/memobj.c
File diff suppressed because it is too large
Load Diff
232
engine/oop.c
232
engine/oop.c
|
@ -1,25 +1,44 @@
|
|||
/*
|
||||
* Symisc PH7: An embeddable bytecode compiler and a virtual machine for the PHP(5) programming language.
|
||||
* Copyright (C) 2011-2012, Symisc Systems http://ph7.symisc.net/
|
||||
* Version 2.1.4
|
||||
* For information on licensing,redistribution of this file,and for a DISCLAIMER OF ALL WARRANTIES
|
||||
* please contact Symisc Systems via:
|
||||
* legal@symisc.net
|
||||
* licensing@symisc.net
|
||||
* contact@symisc.net
|
||||
* or visit:
|
||||
* http://ph7.symisc.net/
|
||||
/**
|
||||
* @PROJECT PH7 Engine for the AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE engine/oop.c
|
||||
* @DESCRIPTION Object Oriented (OOP) subsystem for the PH7 Engine
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
/* $SymiscID: oo.c v1.9 FeeBSD 2012-07-17 03:44 devel <chm@symisc.net> $ */
|
||||
#include "ph7int.h"
|
||||
/*
|
||||
* This file implement an Object Oriented (OO) subsystem for the PH7 engine.
|
||||
* Create an empty class inheritance storage.
|
||||
* Return a pointer to a storage (ph7_class_info instance) on success. NULL otherwise.
|
||||
*/
|
||||
PH7_PRIVATE ph7_class_info *PH7_NewClassInfo(ph7_vm *pVm, const SyString *pName) {
|
||||
ph7_class_info *pClassInfo;
|
||||
char *zName;
|
||||
/* Allocate a new instance */
|
||||
pClassInfo = (ph7_class_info *)SyMemBackendPoolAlloc(&pVm->sAllocator, sizeof(ph7_class_info));
|
||||
if(pClassInfo == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* Zero the structure */
|
||||
SyZero(pClassInfo, sizeof(ph7_class_info));
|
||||
/* Duplicate class name */
|
||||
zName = SyMemBackendStrDup(&pVm->sAllocator, pName->zString, pName->nByte);
|
||||
if(zName == 0) {
|
||||
SyMemBackendPoolFree(&pVm->sAllocator, pClassInfo);
|
||||
return 0;
|
||||
}
|
||||
/* Initialize the class information storage */
|
||||
SyStringInitFromBuf(&pClassInfo->sName, zName, pName->nByte);
|
||||
SySetInit(&pClassInfo->sExtends, &pVm->sAllocator, sizeof(SyString));
|
||||
SySetInit(&pClassInfo->sImplements, &pVm->sAllocator, sizeof(SyString));
|
||||
/* All done */
|
||||
return pClassInfo;
|
||||
}
|
||||
/*
|
||||
* Create an empty class.
|
||||
* Return a pointer to a raw class (ph7_class instance) on success. NULL otherwise.
|
||||
*/
|
||||
PH7_PRIVATE ph7_class *PH7_NewRawClass(ph7_vm *pVm, const SyString *pName, sxu32 nLine) {
|
||||
PH7_PRIVATE ph7_class *PH7_NewRawClass(ph7_vm *pVm, const SyString *pName) {
|
||||
ph7_class *pClass;
|
||||
char *zName;
|
||||
/* Allocate a new instance */
|
||||
|
@ -41,7 +60,6 @@ PH7_PRIVATE ph7_class *PH7_NewRawClass(ph7_vm *pVm, const SyString *pName, sxu32
|
|||
SyHashInit(&pClass->hAttr, &pVm->sAllocator, 0, 0);
|
||||
SyHashInit(&pClass->hDerived, &pVm->sAllocator, 0, 0);
|
||||
SySetInit(&pClass->aInterface, &pVm->sAllocator, sizeof(ph7_class *));
|
||||
pClass->nLine = nLine;
|
||||
/* All done */
|
||||
return pClass;
|
||||
}
|
||||
|
@ -49,9 +67,10 @@ PH7_PRIVATE ph7_class *PH7_NewRawClass(ph7_vm *pVm, const SyString *pName, sxu32
|
|||
* Allocate and initialize a new class attribute.
|
||||
* Return a pointer to the class attribute on success. NULL otherwise.
|
||||
*/
|
||||
PH7_PRIVATE ph7_class_attr *PH7_NewClassAttr(ph7_vm *pVm, const SyString *pName, sxu32 nLine, sxi32 iProtection, sxi32 iFlags) {
|
||||
PH7_PRIVATE ph7_class_attr *PH7_NewClassAttr(ph7_vm *pVm, ph7_class *pClass, const SyString *pName, sxu32 nLine, sxi32 iProtection, sxi32 iFlags, sxu32 nType) {
|
||||
ph7_class_attr *pAttr;
|
||||
char *zName;
|
||||
SXUNUSED(pClass);
|
||||
pAttr = (ph7_class_attr *)SyMemBackendPoolAlloc(&pVm->sAllocator, sizeof(ph7_class_attr));
|
||||
if(pAttr == 0) {
|
||||
return 0;
|
||||
|
@ -64,12 +83,13 @@ PH7_PRIVATE ph7_class_attr *PH7_NewClassAttr(ph7_vm *pVm, const SyString *pName,
|
|||
SyMemBackendPoolFree(&pVm->sAllocator, pAttr);
|
||||
return 0;
|
||||
}
|
||||
SyStringInitFromBuf(&pAttr->sName, zName, pName->nByte);
|
||||
/* Initialize fields */
|
||||
SySetInit(&pAttr->aByteCode, &pVm->sAllocator, sizeof(VmInstr));
|
||||
SyStringInitFromBuf(&pAttr->sName, zName, pName->nByte);
|
||||
pAttr->iProtection = iProtection;
|
||||
pAttr->nIdx = SXU32_HIGH;
|
||||
pAttr->iFlags = iFlags;
|
||||
pAttr->nType = nType;
|
||||
pAttr->nLine = nLine;
|
||||
return pAttr;
|
||||
}
|
||||
|
@ -146,14 +166,18 @@ PH7_PRIVATE ph7_class_method *PH7_ClassExtractMethod(ph7_class *pClass, const ch
|
|||
*/
|
||||
PH7_PRIVATE ph7_class_attr *PH7_ClassExtractAttribute(ph7_class *pClass, const char *zName, sxu32 nByte) {
|
||||
SyHashEntry *pEntry;
|
||||
ph7_class_attr *pAttr;
|
||||
/* Perform a hash lookup */
|
||||
pEntry = SyHashGet(&pClass->hAttr, (const void *)zName, nByte);
|
||||
if(pEntry == 0) {
|
||||
/* No such entry */
|
||||
return 0;
|
||||
SyHashResetLoopCursor(&pClass->hAttr);
|
||||
while((pEntry = SyHashGetNextEntry(&pClass->hAttr)) != 0) {
|
||||
/* Point to the desired method */
|
||||
pAttr = (ph7_class_attr *)pEntry->pUserData;
|
||||
if(pAttr->pClass == pClass && SyStrncmp(pAttr->sName.zString, zName, nByte) == 0) {
|
||||
return pAttr;
|
||||
}
|
||||
}
|
||||
/* Point to the desierd method */
|
||||
return (ph7_class_attr *)pEntry->pUserData;
|
||||
/* No such entry */
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Install a class attribute in the corresponding container.
|
||||
|
@ -162,6 +186,7 @@ PH7_PRIVATE ph7_class_attr *PH7_ClassExtractAttribute(ph7_class *pClass, const c
|
|||
PH7_PRIVATE sxi32 PH7_ClassInstallAttr(ph7_class *pClass, ph7_class_attr *pAttr) {
|
||||
SyString *pName = &pAttr->sName;
|
||||
sxi32 rc;
|
||||
pAttr->pClass = pClass;
|
||||
rc = SyHashInsert(&pClass->hAttr, (const void *)pName->zString, pName->nByte, pAttr);
|
||||
return rc;
|
||||
}
|
||||
|
@ -172,6 +197,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstallAttr(ph7_class *pClass, ph7_class_attr *pAttr)
|
|||
PH7_PRIVATE sxi32 PH7_ClassInstallMethod(ph7_class *pClass, ph7_class_method *pMeth) {
|
||||
SyString *pName = &pMeth->sFunc.sName;
|
||||
sxi32 rc;
|
||||
pMeth->sFunc.pClass = pClass;
|
||||
rc = SyHashInsert(&pClass->hMethod, (const void *)pName->zString, pName->nByte, pMeth);
|
||||
return rc;
|
||||
}
|
||||
|
@ -216,76 +242,60 @@ PH7_PRIVATE sxi32 PH7_ClassInstallMethod(ph7_class *pClass, ph7_class_method *pM
|
|||
* Any other return value indicates failure and the upper layer must generate an appropriate
|
||||
* error message.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_ClassInherit(ph7_gen_state *pGen, ph7_class *pSub, ph7_class *pBase) {
|
||||
PH7_PRIVATE sxi32 PH7_ClassInherit(ph7_vm *pVm, ph7_class *pSub, ph7_class *pBase) {
|
||||
ph7_class_method *pMeth;
|
||||
ph7_class_attr *pAttr;
|
||||
SyHashEntry *pEntry;
|
||||
SyString *pName;
|
||||
sxi32 rc;
|
||||
/* Install in the derived hashtable */
|
||||
rc = SyHashInsert(&pBase->hDerived, (const void *)SyStringData(&pSub->sName), SyStringLength(&pSub->sName), pSub);
|
||||
rc = SyHashInsert(&pSub->hDerived, (const void *)SyStringData(&pBase->sName), SyStringLength(&pBase->sName), pBase);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
/* Copy public/protected attributes from the base class */
|
||||
/* Copy all attributes from the base class */
|
||||
SyHashResetLoopCursor(&pBase->hAttr);
|
||||
while((pEntry = SyHashGetNextEntry(&pBase->hAttr)) != 0) {
|
||||
/* Make sure the private attributes are not redeclared in the subclass */
|
||||
/* Check if attributes are not being redeclared in the subclass and emit WARNING */
|
||||
pAttr = (ph7_class_attr *)pEntry->pUserData;
|
||||
pName = &pAttr->sName;
|
||||
if((pEntry = SyHashGet(&pSub->hAttr, (const void *)pName->zString, pName->nByte)) != 0) {
|
||||
if(pAttr->iProtection == PH7_CLASS_PROT_PRIVATE &&
|
||||
((ph7_class_attr *)pEntry->pUserData)->iProtection != PH7_CLASS_PROT_PUBLIC) {
|
||||
/* Cannot redeclare private attribute */
|
||||
PH7_GenCompileError(&(*pGen), E_WARNING, ((ph7_class_attr *)pEntry->pUserData)->nLine,
|
||||
"Private attribute '%z::%z' redeclared inside child class '%z'",
|
||||
&pBase->sName, pName, &pSub->sName);
|
||||
}
|
||||
continue;
|
||||
ph7_class_attr *pSubAttr = (ph7_class_attr *)pEntry->pUserData;
|
||||
PH7_VmThrowError(pVm, PH7_CTX_WARNING, "Attribute '%z::$%z' hides inherited member '%z::$%z'", &pSubAttr->pClass->sName, pName, &pBase->sName, pName);
|
||||
}
|
||||
/* Install the attribute */
|
||||
if(pAttr->iProtection != PH7_CLASS_PROT_PRIVATE) {
|
||||
rc = SyHashInsert(&pSub->hAttr, (const void *)pName->zString, pName->nByte, pAttr);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
rc = SyHashInsert(&pSub->hAttr, (const void *)pName->zString, pName->nByte, pAttr);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
SyHashResetLoopCursor(&pBase->hMethod);
|
||||
while((pEntry = SyHashGetNextEntry(&pBase->hMethod)) != 0) {
|
||||
/* Make sure the private/final methods are not redeclared in the subclass */
|
||||
/* Make sure the final methods are not redeclared in the subclass */
|
||||
pMeth = (ph7_class_method *)pEntry->pUserData;
|
||||
pName = &pMeth->sFunc.sName;
|
||||
if((pEntry = SyHashGet(&pSub->hMethod, (const void *)pName->zString, pName->nByte)) != 0) {
|
||||
if(pMeth->iFlags & PH7_CLASS_ATTR_FINAL) {
|
||||
/* Cannot Overwrite final method */
|
||||
rc = PH7_GenCompileError(&(*pGen), E_ERROR, ((ph7_class_method *)pEntry->pUserData)->nLine,
|
||||
"Cannot Overwrite final method '%z:%z' inside child class '%z'",
|
||||
&pBase->sName, pName, &pSub->sName);
|
||||
if(rc == SXERR_ABORT) {
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Cannot overwrite final method '%z:%z()' inside child class '%z'", &pBase->sName, pName, &pSub->sName);
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
if(pMeth->iFlags & PH7_CLASS_ATTR_ABSTRACT) {
|
||||
/* Abstract method must be defined in the child class */
|
||||
PH7_GenCompileError(&(*pGen), E_WARNING, pMeth->nLine,
|
||||
"Abstract method '%z:%z' must be defined inside child class '%z'",
|
||||
&pBase->sName, pName, &pSub->sName);
|
||||
continue;
|
||||
if(pMeth->iFlags & PH7_CLASS_ATTR_VIRTUAL) {
|
||||
/* Virtual method must be defined in the child class */
|
||||
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Virtual method '%z::%z()' must be defined inside child class '%z'", &pBase->sName, pName, &pSub->sName);
|
||||
}
|
||||
}
|
||||
/* Install the method */
|
||||
if(pMeth->iProtection != PH7_CLASS_PROT_PRIVATE) {
|
||||
rc = SyHashInsert(&pSub->hMethod, (const void *)pName->zString, pName->nByte, pMeth);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
rc = SyHashInsert(&pSub->hMethod, (const void *)pName->zString, pName->nByte, pMeth);
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
/* Mark as subclass */
|
||||
pSub->pBase = pBase;
|
||||
/* Mark first inherited class as direct subclass */
|
||||
if(!pSub->pBase) {
|
||||
pSub->pBase = pBase;
|
||||
}
|
||||
/* All done */
|
||||
return SXRET_OK;
|
||||
}
|
||||
|
@ -309,7 +319,7 @@ PH7_PRIVATE sxi32 PH7_ClassInterfaceInherit(ph7_class *pSub, ph7_class *pBase) {
|
|||
SyString *pName;
|
||||
sxi32 rc;
|
||||
/* Install in the derived hashtable */
|
||||
SyHashInsert(&pBase->hDerived, (const void *)SyStringData(&pSub->sName), SyStringLength(&pSub->sName), pSub);
|
||||
SyHashInsert(&pSub->hDerived, (const void *)SyStringData(&pBase->sName), SyStringLength(&pBase->sName), pBase);
|
||||
SyHashResetLoopCursor(&pBase->hAttr);
|
||||
/* Copy constants */
|
||||
while((pEntry = SyHashGetNextEntry(&pBase->hAttr)) != 0) {
|
||||
|
@ -356,7 +366,8 @@ PH7_PRIVATE sxi32 PH7_ClassInterfaceInherit(ph7_class *pSub, ph7_class *pBase) {
|
|||
* Any other return value indicates failure and the upper layer must generate an appropriate
|
||||
* error message.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_class *pMain, ph7_class *pInterface) {
|
||||
PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_vm *pVm, ph7_class *pMain, ph7_class *pInterface) {
|
||||
ph7_class_method *pMeth;
|
||||
ph7_class_attr *pAttr;
|
||||
SyHashEntry *pEntry;
|
||||
SyString *pName;
|
||||
|
@ -376,12 +387,18 @@ PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_class *pMain, ph7_class *pInterface) {
|
|||
}
|
||||
}
|
||||
}
|
||||
SyHashResetLoopCursor(&pInterface->hMethod);
|
||||
while((pEntry = SyHashGetNextEntry(&pInterface->hMethod)) != 0) {
|
||||
pMeth = (ph7_class_method *)pEntry->pUserData;
|
||||
pName = &pMeth->sFunc.sName;
|
||||
if((pEntry = SyHashGet(&pMain->hMethod, (const void *)pName->zString, pName->nByte)) != 0) {
|
||||
continue;
|
||||
} else {
|
||||
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Method '%z:%z()' must be defined inside class '%z'", &pInterface->sName, pName, &pMain->sName);
|
||||
}
|
||||
}
|
||||
/* Install in the interface container */
|
||||
SySetPut(&pMain->aInterface, (const void *)&pInterface);
|
||||
/* TICKET 1433-49/1: Symisc eXtension
|
||||
* A class may not implemnt all declared interface methods,so there
|
||||
* is no need for a method installer loop here.
|
||||
*/
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
|
@ -635,7 +652,7 @@ PH7_PRIVATE ph7_class_instance *PH7_CloneClassInstance(ph7_class_instance *pSrc)
|
|||
PH7_VmCallClassMethod(pVm, pClone, pMethod, 0, 0, 0);
|
||||
} else {
|
||||
/* Nesting limit reached */
|
||||
PH7_VmThrowError(pVm, 0, PH7_CTX_ERR, "Object clone limit reached,no more call to __clone()");
|
||||
PH7_VmThrowError(pVm, PH7_CTX_ERR, "Object clone limit reached");
|
||||
}
|
||||
/* Reset the cursor */
|
||||
pMethod->iCloneDepth = 0;
|
||||
|
@ -656,7 +673,7 @@ static void PH7_ClassInstanceRelease(ph7_class_instance *pThis) {
|
|||
ph7_vm *pVm;
|
||||
if(pThis->iFlags & CLASS_INSTANCE_DESTROYED) {
|
||||
/*
|
||||
* Already destroyed,return immediately.
|
||||
* Already destroyed, return immediately.
|
||||
* This could happend if someone perform unset($this) in the destructor body.
|
||||
*/
|
||||
return;
|
||||
|
@ -690,10 +707,12 @@ static void PH7_ClassInstanceRelease(ph7_class_instance *pThis) {
|
|||
* If the reference count reaches zero,release the whole instance.
|
||||
*/
|
||||
PH7_PRIVATE void PH7_ClassInstanceUnref(ph7_class_instance *pThis) {
|
||||
pThis->iRef--;
|
||||
if(pThis->iRef < 1) {
|
||||
/* No more reference to this instance */
|
||||
PH7_ClassInstanceRelease(&(*pThis));
|
||||
if(pThis) {
|
||||
pThis->iRef--;
|
||||
if(pThis->iRef < 1) {
|
||||
/* No more reference to this instance */
|
||||
PH7_ClassInstanceRelease(&(*pThis));
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
@ -779,8 +798,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceCmp(ph7_class_instance *pLeft, ph7_class_inst
|
|||
sxi32 rc;
|
||||
if(iNest > 31) {
|
||||
/* Nesting limit reached */
|
||||
PH7_VmThrowError(pLeft->pVm, 0, PH7_CTX_ERR, "Nesting limit reached: Infinite recursion?");
|
||||
return 1;
|
||||
PH7_VmThrowError(pLeft->pVm, PH7_CTX_ERR, "Nesting limit reached, probably infinite recursion");
|
||||
}
|
||||
/* Comparison is performed only if the objects are instance of the same class */
|
||||
if(pLeft->pClass != pRight->pClass) {
|
||||
|
@ -793,7 +811,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceCmp(ph7_class_instance *pLeft, ph7_class_inst
|
|||
* are identical if and only if they refer to the same instance
|
||||
* of the same class.
|
||||
*/
|
||||
return !(pLeft == pRight);
|
||||
return pLeft != pRight;
|
||||
}
|
||||
/*
|
||||
* Attribute comparison.
|
||||
|
@ -863,41 +881,45 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceDump(SyBlob *pOut, ph7_class_instance *pThis,
|
|||
if(!ShowType) {
|
||||
SyBlobAppend(&(*pOut), "Object(", sizeof("Object(") - 1);
|
||||
}
|
||||
/* Append class name */
|
||||
SyBlobFormat(&(*pOut), "%z) {", &pThis->pClass->sName);
|
||||
if(pThis) {
|
||||
/* Append class name */
|
||||
SyBlobFormat(&(*pOut), "%z) {", &pThis->pClass->sName);
|
||||
#ifdef __WINNT__
|
||||
SyBlobAppend(&(*pOut), "\r\n", sizeof("\r\n") - 1);
|
||||
SyBlobAppend(&(*pOut), "\r\n", sizeof("\r\n") - 1);
|
||||
#else
|
||||
SyBlobAppend(&(*pOut), "\n", sizeof(char));
|
||||
SyBlobAppend(&(*pOut), "\n", sizeof(char));
|
||||
#endif
|
||||
/* Dump object attributes */
|
||||
SyHashResetLoopCursor(&pThis->hAttr);
|
||||
while((pEntry = SyHashGetNextEntry(&pThis->hAttr)) != 0) {
|
||||
VmClassAttr *pVmAttr = (VmClassAttr *)pEntry->pUserData;
|
||||
if((pVmAttr->pAttr->iFlags & (PH7_CLASS_ATTR_CONSTANT | PH7_CLASS_ATTR_STATIC)) == 0) {
|
||||
/* Dump non-static/constant attribute only */
|
||||
for(i = 0 ; i < nTab ; i++) {
|
||||
SyBlobAppend(&(*pOut), " ", sizeof(char));
|
||||
}
|
||||
pValue = ExtractClassAttrValue(pThis->pVm, pVmAttr);
|
||||
if(pValue) {
|
||||
SyBlobFormat(&(*pOut), "['%z'] =>", &pVmAttr->pAttr->sName);
|
||||
/* Dump object attributes */
|
||||
SyHashResetLoopCursor(&pThis->hAttr);
|
||||
while((pEntry = SyHashGetNextEntry(&pThis->hAttr)) != 0) {
|
||||
VmClassAttr *pVmAttr = (VmClassAttr *)pEntry->pUserData;
|
||||
if((pVmAttr->pAttr->iFlags & (PH7_CLASS_ATTR_CONSTANT | PH7_CLASS_ATTR_STATIC)) == 0) {
|
||||
/* Dump non-static/constant attribute only */
|
||||
for(i = 0 ; i < nTab ; i++) {
|
||||
SyBlobAppend(&(*pOut), " ", sizeof(char));
|
||||
}
|
||||
pValue = ExtractClassAttrValue(pThis->pVm, pVmAttr);
|
||||
if(pValue) {
|
||||
SyBlobFormat(&(*pOut), "['%z'] =>", &pVmAttr->pAttr->sName);
|
||||
#ifdef __WINNT__
|
||||
SyBlobAppend(&(*pOut), "\r\n", sizeof("\r\n") - 1);
|
||||
SyBlobAppend(&(*pOut), "\r\n", sizeof("\r\n") - 1);
|
||||
#else
|
||||
SyBlobAppend(&(*pOut), "\n", sizeof(char));
|
||||
SyBlobAppend(&(*pOut), "\n", sizeof(char));
|
||||
#endif
|
||||
rc = PH7_MemObjDump(&(*pOut), pValue, ShowType, nTab + 1, nDepth, 0);
|
||||
if(rc == SXERR_LIMIT) {
|
||||
break;
|
||||
rc = PH7_MemObjDump(&(*pOut), pValue, ShowType, nTab + 1, nDepth);
|
||||
if(rc == SXERR_LIMIT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i = 0 ; i < nTab ; i++) {
|
||||
SyBlobAppend(&(*pOut), " ", sizeof(char));
|
||||
}
|
||||
SyBlobAppend(&(*pOut), "}", sizeof(char));
|
||||
} else {
|
||||
SyBlobAppend(&(*pOut), ")", sizeof(char));
|
||||
}
|
||||
for(i = 0 ; i < nTab ; i++) {
|
||||
SyBlobAppend(&(*pOut), " ", sizeof(char));
|
||||
}
|
||||
SyBlobAppend(&(*pOut), "}", sizeof(char));
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
|
@ -936,7 +958,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceDump(SyBlob *pOut, ph7_class_instance *pThis,
|
|||
* The above example will output:
|
||||
* Hello
|
||||
*
|
||||
* Note that PH7 does not support all the magical method and introudces __toFloat(),__toInt()
|
||||
* Note that PH7 does not support all the magical method and introduces __toFloat(),__toInt()
|
||||
* which have the same behaviour as __toString() but for float and integer types
|
||||
* respectively.
|
||||
* Refer to the official documentation for more information.
|
||||
|
@ -957,7 +979,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceCallMagicMethod(
|
|||
/* Make sure the magic method is available */
|
||||
pMeth = PH7_ClassExtractMethod(&(*pClass), zMethod, nByte);
|
||||
if(pMeth == 0) {
|
||||
/* No such method,return immediately */
|
||||
/* No such method, return immediately */
|
||||
return SXERR_NOTFOUND;
|
||||
}
|
||||
nArg = 0;
|
||||
|
@ -1011,7 +1033,7 @@ PH7_PRIVATE ph7_value *PH7_ClassInstanceExtractAttrValue(ph7_class_instance *pTh
|
|||
* int(991)
|
||||
* }
|
||||
* You have noticed that PH7 allow class attributes [i.e: $a,$c,$d in the example above]
|
||||
* have any complex expression (even function calls/Annonymous functions) as their default
|
||||
* have any complex expression (even function calls/anonymous functions) as their default
|
||||
* value unlike the standard PHP engine.
|
||||
* This is a very powerful feature that you have to look at.
|
||||
*/
|
||||
|
@ -1085,7 +1107,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceWalk(
|
|||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* Extract a class atrribute value.
|
||||
* Extract a class attribute value.
|
||||
* Return a pointer to the attribute value on success. Otherwise NULL.
|
||||
* Note:
|
||||
* Access to static and constant attribute is not allowed. That is,the function
|
||||
|
@ -1101,7 +1123,7 @@ PH7_PRIVATE ph7_value *PH7_ClassInstanceFetchAttr(ph7_class_instance *pThis, con
|
|||
/* No such attribute */
|
||||
return 0;
|
||||
}
|
||||
/* Point to the class atrribute */
|
||||
/* Point to the class attribute */
|
||||
pAttr = (VmClassAttr *)pEntry->pUserData;
|
||||
/* Check if we are dealing with a static/constant attribute */
|
||||
if(pAttr->pAttr->iFlags & (PH7_CLASS_ATTR_CONSTANT | PH7_CLASS_ATTR_STATIC)) {
|
||||
|
|
645
engine/parser.c
645
engine/parser.c
File diff suppressed because it is too large
Load Diff
1305
engine/vfs.c
1305
engine/vfs.c
File diff suppressed because it is too large
Load Diff
5928
engine/vm.c
5928
engine/vm.c
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,171 @@
|
|||
#ifndef _COMPILER_H_
|
||||
#define _COMPILER_H_
|
||||
|
||||
#include "ph7int.h"
|
||||
|
||||
/* Forward declaration */
|
||||
typedef struct LangConstruct LangConstruct;
|
||||
typedef struct JumpFixup JumpFixup;
|
||||
typedef struct Label Label;
|
||||
|
||||
/* Block [i.e: set of statements] control flags */
|
||||
#define GEN_BLOCK_LOOP 0x001 /* Loop block [i.e: for,while,...] */
|
||||
#define GEN_BLOCK_PROTECTED 0x002 /* Protected block */
|
||||
#define GEN_BLOCK_COND 0x004 /* Conditional block [i.e: if(condition){} ]*/
|
||||
#define GEN_BLOCK_FUNC 0x008 /* Function body */
|
||||
#define GEN_BLOCK_GLOBAL 0x010 /* Global block (always set)*/
|
||||
#define GEN_BLOCK_NESTED_FUNC 0x020 /* Nested function body */
|
||||
#define GEN_BLOCK_EXPR 0x040 /* Expression */
|
||||
#define GEN_BLOCK_STD 0x080 /* Standard block */
|
||||
#define GEN_BLOCK_EXCEPTION 0x100 /* Exception block [i.e: try{ } }*/
|
||||
#define GEN_BLOCK_SWITCH 0x200 /* Switch statement */
|
||||
#define GEN_BLOCK_CLASS 0x400 /* Class definition */
|
||||
#define GEN_BLOCK_NAMESPACE 0x800 /* Namespace body */
|
||||
|
||||
/*
|
||||
* Each label seen in the input is recorded in an instance
|
||||
* of the following structure.
|
||||
* A label is a target point [i.e: a jump destination] that is specified
|
||||
* by an identifier followed by a colon.
|
||||
*/
|
||||
struct Label {
|
||||
ph7_vm_func *pFunc; /* Compiled function where the label was declared.NULL otherwise */
|
||||
sxu32 nJumpDest; /* Jump destination */
|
||||
SyString sName; /* Label name */
|
||||
sxu32 nLine; /* Line number this label occurs */
|
||||
sxu8 bRef; /* True if the label was referenced */
|
||||
};
|
||||
|
||||
/*
|
||||
* Compilation of some Aer constructs such as if, for, while, the logical or
|
||||
* (||) and logical and (&&) operators in expressions requires the
|
||||
* generation of forward jumps.
|
||||
* Since the destination PC target of these jumps isn't known when the jumps
|
||||
* are emitted, we record each forward jump in an instance of the following
|
||||
* structure. Those jumps are fixed later when the jump destination is resolved.
|
||||
*/
|
||||
struct JumpFixup {
|
||||
sxi32 nJumpType; /* Jump type. Either TRUE jump, FALSE jump or Unconditional jump */
|
||||
sxu32 nInstrIdx; /* Instruction index to fix later when the jump destination is resolved. */
|
||||
SyString sLabel; /* Label name */
|
||||
ph7_vm_func *pFunc; /* Compiled function inside which the goto was emitted. NULL otherwise */
|
||||
sxu32 nLine; /* Track line number */
|
||||
};
|
||||
|
||||
/*
|
||||
* Each language construct is represented by an instance
|
||||
* of the following structure.
|
||||
*/
|
||||
struct LangConstruct {
|
||||
sxu32 nID; /* Language construct ID [i.e: PH7_KEYWORD_WHILE,PH7_KEYWORD_FOR,PH7_KEYWORD_IF...] */
|
||||
ProcLangConstruct xConstruct; /* C function implementing the language construct */
|
||||
};
|
||||
|
||||
/* Compilation flags */
|
||||
#define PH7_COMPILE_STATEMENT 0x001 /* Compile a single statement */
|
||||
|
||||
/* Token stream synchronization macros */
|
||||
#define SWAP_TOKEN_STREAM(GEN,START,END)\
|
||||
pTmp = GEN->pEnd;\
|
||||
pGen->pIn = START;\
|
||||
pGen->pEnd = END
|
||||
|
||||
#define UPDATE_TOKEN_STREAM(GEN)\
|
||||
if( GEN->pIn < pTmp ){\
|
||||
GEN->pIn++;\
|
||||
}\
|
||||
GEN->pEnd = pTmp
|
||||
|
||||
#define SWAP_DELIMITER(GEN,START,END)\
|
||||
pTmpIn = GEN->pIn;\
|
||||
pTmpEnd = GEN->pEnd;\
|
||||
GEN->pIn = START;\
|
||||
GEN->pEnd = END
|
||||
|
||||
#define RE_SWAP_DELIMITER(GEN)\
|
||||
GEN->pIn = pTmpIn;\
|
||||
GEN->pEnd = pTmpEnd
|
||||
|
||||
/* Flags related to expression compilation */
|
||||
#define EXPR_FLAG_LOAD_IDX_STORE 0x001 /* Set the iP2 flag when dealing with the LOAD_IDX instruction */
|
||||
#define EXPR_FLAG_RDONLY_LOAD 0x002 /* Read-only load, refer to the 'PH7_OP_LOAD' VM instruction for more information */
|
||||
#define EXPR_FLAG_COMMA_STATEMENT 0x004 /* Treat comma expression as a single statement (used by class attributes) */
|
||||
|
||||
/* Forward declaration */
|
||||
static sxi32 PH7_CompileExpr(ph7_gen_state *pGen, sxi32 iFlags, sxi32(*xTreeValidator)(ph7_gen_state *, ph7_expr_node *));
|
||||
static GenBlock *PH7_GenStateFetchBlock(GenBlock *pCurrent, sxi32 iBlockType, sxi32 iCount);
|
||||
static void PH7_GenStateInitBlock(ph7_gen_state *pGen, GenBlock *pBlock, sxi32 iType, sxu32 nFirstInstr, void *pUserData);
|
||||
static sxi32 PH7_GenStateEnterBlock(ph7_gen_state *pGen, sxi32 iType, sxu32 nFirstInstr, void *pUserData, GenBlock **ppBlock);
|
||||
static void PH7_GenStateReleaseBlock(GenBlock *pBlock);
|
||||
static void PH7_GenStateFreeBlock(GenBlock *pBlock);
|
||||
static sxi32 PH7_GenStateLeaveBlock(ph7_gen_state *pGen, GenBlock **ppBlock);
|
||||
static sxi32 PH7_GenStateNewJumpFixup(GenBlock *pBlock, sxi32 nJumpType, sxu32 nInstrIdx);
|
||||
static sxu32 PH7_GenStateFixJumps(GenBlock *pBlock, sxi32 nJumpType, sxu32 nJumpDest);
|
||||
static sxi32 PH7_GenStateFindLiteral(ph7_gen_state *pGen, const SyString *pValue, sxu32 *pIdx);
|
||||
static sxi32 PH7_GenStateInstallLiteral(ph7_gen_state *pGen, ph7_value *pObj, sxu32 nIdx);
|
||||
static ph7_value *PH7_GenStateInstallNumLiteral(ph7_gen_state *pGen, sxu32 *pIdx);
|
||||
static sxi32 PH7_CompileNumLiteral(ph7_gen_state *pGen, sxi32 iCompileFlag);
|
||||
PH7_PRIVATE sxi32 PH7_CompileSimpleString(ph7_gen_state *pGen, sxi32 iCompileFlag);
|
||||
static sxi32 PH7_GenStateProcessStringExpression(ph7_gen_state *pGen, sxu32 nLine, const char *zIn, const char *zEnd);
|
||||
static ph7_value *PH7_GenStateNewStrObj(ph7_gen_state *pGen, sxi32 *pCount);
|
||||
static sxi32 PH7_GenStateCompileString(ph7_gen_state *pGen);
|
||||
PH7_PRIVATE sxi32 PH7_CompileString(ph7_gen_state *pGen, sxi32 iCompileFlag);
|
||||
static sxi32 PH7_GenStateCompileArrayEntry(ph7_gen_state *pGen, SyToken *pIn, SyToken *pEnd, sxi32 iFlags, sxi32(*xValidator)(ph7_gen_state *, ph7_expr_node *));
|
||||
PH7_PRIVATE sxi32 PH7_CompileArray(ph7_gen_state *pGen, sxi32 iCompileFlag);
|
||||
static sxi32 PH7_GenStateCompileFunc(ph7_gen_state *pGen, SyString *pName, sxi32 iFlags, int bHandleClosure, ph7_vm_func **ppFunc);
|
||||
static sxi32 GenStateDefineNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot);
|
||||
PH7_PRIVATE sxi32 PH7_CompileDefine(ph7_gen_state *pGen);
|
||||
PH7_PRIVATE sxi32 PH7_CompileVariable(ph7_gen_state *pGen, sxi32 iCompileFlag);
|
||||
static sxi32 PH7_GenStateLoadLiteral(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_GenStateResolveNamespaceLiteral(ph7_gen_state *pGen);
|
||||
PH7_PRIVATE sxi32 PH7_CompileLiteral(ph7_gen_state *pGen, sxi32 iCompileFlag);
|
||||
static int PH7_GenStateIsReservedConstant(SyString *pName);
|
||||
static sxi32 PH7_CompileConstant(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_CompileContinue(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_CompileBreak(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_GenStateNextChunk(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_CompileBlock(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_CompileWhile(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_CompileDoWhile(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_CompileFor(ph7_gen_state *pGen);
|
||||
static sxi32 GenStateForEachNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot);
|
||||
static sxi32 PH7_CompileForeach(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_CompileIf(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_CompileReturn(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_CompileHalt(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_CompileVar(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_CompileNamespace(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_CompileUsing(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_CompileImport(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_CompileInclude(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_GenStateProcessArgValue(ph7_gen_state *pGen, ph7_vm_func_arg *pArg, SyToken *pIn, SyToken *pEnd);
|
||||
static sxi32 PH7_GenStateCollectFuncArgs(ph7_vm_func *pFunc, ph7_gen_state *pGen, SyToken *pEnd);
|
||||
static sxi32 PH7_GenStateCompileFuncBody(ph7_gen_state *pGen, ph7_vm_func *pFunc);
|
||||
static sxi32 PH7_GenStateCompileFunc(ph7_gen_state *pGen, SyString *pName, sxi32 iFlags, int bHandleClosure, ph7_vm_func **ppFunc);
|
||||
static sxi32 PH7_GetProtectionLevel(sxi32 nKeyword);
|
||||
static sxi32 PH7_GenStateCompileClassConstant(ph7_gen_state *pGen, sxi32 iProtection, sxi32 iFlags, ph7_class *pClass);
|
||||
static sxi32 PH7_GenStateCompileClassAttr(ph7_gen_state *pGen, sxi32 iProtection, sxi32 iFlags, sxu32 nType, ph7_class *pClass);
|
||||
static sxi32 PH7_GenStateCompileClassMethod(ph7_gen_state *pGen, sxu32 nType, sxi32 iProtection, sxi32 iFlags, int doBody, ph7_class *pClass);
|
||||
static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags);
|
||||
static sxi32 PH7_CompileClass(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_GenStateThrowNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot);
|
||||
static sxi32 PH7_CompileThrow(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_CompileCatch(ph7_gen_state *pGen, ph7_exception *pException);
|
||||
static sxi32 PH7_CompileTry(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_GenStateCompileSwitchBlock(ph7_gen_state *pGen, sxu32 *pBlockStart);
|
||||
static sxi32 PH7_GenStateCompileCaseExpr(ph7_gen_state *pGen, ph7_case_expr *pExpr);
|
||||
static sxi32 PH7_CompileSwitch(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_GenStateEmitExprCode(ph7_gen_state *pGen, ph7_expr_node *pNode, sxi32 iFlags);
|
||||
static sxi32 PH7_CompileExpr(ph7_gen_state *pGen, sxi32 iFlags, sxi32(*xTreeValidator)(ph7_gen_state *, ph7_expr_node *));
|
||||
PH7_PRIVATE ProcNodeConstruct PH7_GetNodeHandler(sxu32 nNodeType);
|
||||
static ProcLangConstruct PH7_GenStateGetStatementHandler(sxu32 nKeywordID, SyToken *pLookahead);
|
||||
static int PH7_IsLangConstruct(sxu32 nKeywordID);
|
||||
static sxi32 PH7_GenStateCompileChunk(ph7_gen_state *pGen, sxi32 iFlags);
|
||||
static sxi32 PH7_GenStateCompileGlobalScope(ph7_gen_state *pGen);
|
||||
static sxi32 PH7_CompileScript(ph7_gen_state *pGen, SySet *pTokenSet, sxi32 iFlags);
|
||||
PH7_PRIVATE sxi32 PH7_InitCodeGenerator(ph7_vm *pVm, ProcConsumer xErr, void *pErrData);
|
||||
PH7_PRIVATE sxi32 PH7_ResetCodeGenerator(ph7_vm *pVm, ProcConsumer xErr, void *pErrData);
|
||||
PH7_PRIVATE sxi32 PH7_GenCompileError(ph7_gen_state *pGen, sxi32 nErrType, sxu32 nLine, const char *zFormat, ...);
|
||||
|
||||
#endif /* _COMPILER_H_ */
|
247
include/ph7.h
247
include/ph7.h
|
@ -3,7 +3,7 @@
|
|||
#define _PH7_H_
|
||||
/*
|
||||
* Symisc PH7: An embeddable bytecode compiler and a virtual machine for the PHP(5) programming language.
|
||||
* Copyright (C) 2011-2012, Symisc Systems http://ph7.symisc.net/
|
||||
* Copyright (C) 2011-2012, Symisc Systems https://ph7.symisc.net/
|
||||
* Version 2.1.4
|
||||
* For information on licensing,redistribution of this file,and for a DISCLAIMER OF ALL WARRANTIES
|
||||
* please contact Symisc Systems via:
|
||||
|
@ -11,7 +11,7 @@
|
|||
* licensing@symisc.net
|
||||
* contact@symisc.net
|
||||
* or visit:
|
||||
* http://ph7.symisc.net/
|
||||
* https://ph7.symisc.net/
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2011, 2012 Symisc Systems. All rights reserved.
|
||||
|
@ -50,14 +50,11 @@
|
|||
/* $SymiscID: ph7.h v2.1 UNIX|WIN32/64 2012-09-15 09:43 stable <chm@symisc.net> $ */
|
||||
#include <stdarg.h> /* needed for the definition of va_list */
|
||||
#include <stdio.h> /* needed for the definition of snprintf */
|
||||
/*
|
||||
* Compile time engine version, signature, identification in the symisc source tree
|
||||
* and copyright notice.
|
||||
* Each macro have an equivalent C interface associated with it that provide the same
|
||||
* information but are associated with the library instead of the header file.
|
||||
* Refer to [ph7_lib_version()], [ph7_lib_signature()], [ph7_lib_ident()] and
|
||||
* [ph7_lib_copyright()] for more information.
|
||||
*/
|
||||
#include <limits.h> /* needed for MAX_PATH */
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX MAX_PATH
|
||||
#endif
|
||||
/*
|
||||
* The PH7_VERSION C preprocessor macroevaluates to a string literal
|
||||
* that is the ph7 version in the format "X.Y.Z" where X is the major
|
||||
|
@ -65,12 +62,6 @@
|
|||
* number.
|
||||
*/
|
||||
#define PH7_VERSION "2.1.4"
|
||||
/*
|
||||
* The PH7_VERSION_NUMBER C preprocessor macro resolves to an integer
|
||||
* with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same
|
||||
* numbers used in [PH7_VERSION].
|
||||
*/
|
||||
#define PH7_VERSION_NUMBER 2001004
|
||||
/*
|
||||
* The PH7_SIG C preprocessor macro evaluates to a string
|
||||
* literal which is the public signature of the ph7 engine.
|
||||
|
@ -79,23 +70,16 @@
|
|||
* Server: YourWebServer/x.x PH7/x.x.x \r\n
|
||||
*/
|
||||
#define PH7_SIG "PH7/2.1.4"
|
||||
/*
|
||||
* PH7 identification in the Symisc source tree:
|
||||
* Each particular check-in of a particular software released
|
||||
* by symisc systems have an unique identifier associated with it.
|
||||
* This macro hold the one associated with ph7.
|
||||
*/
|
||||
#define PH7_IDENT "ph7:c193f4d8a6b90ee60f9afad11840f1010054fdf9"
|
||||
/*
|
||||
* Copyright notice.
|
||||
* If you have any questions about the licensing situation,please
|
||||
* visit http://ph7.symisc.net/licensing.html
|
||||
* visit https://ph7.symisc.net/licensing.html
|
||||
* or contact Symisc Systems via:
|
||||
* legal@symisc.net
|
||||
* licensing@symisc.net
|
||||
* contact@symisc.net
|
||||
*/
|
||||
#define PH7_COPYRIGHT "Copyright (C) Symisc Systems 2011-2012, http://ph7.symisc.net/"
|
||||
#define PH7_COPYRIGHT "Copyright (C) Symisc Systems 2011-2012, https://ph7.symisc.net/"
|
||||
/* Forward declaration to public objects */
|
||||
typedef struct ph7_io_stream ph7_io_stream;
|
||||
typedef struct ph7_context ph7_context;
|
||||
|
@ -103,96 +87,34 @@ typedef struct ph7_value ph7_value;
|
|||
typedef struct ph7_vfs ph7_vfs;
|
||||
typedef struct ph7_vm ph7_vm;
|
||||
typedef struct ph7 ph7;
|
||||
/*
|
||||
* ------------------------------
|
||||
* Compile time directives
|
||||
* ------------------------------
|
||||
* For most purposes, PH7 can be built just fine using the default compilation options.
|
||||
* However, if required, the compile-time options documented below can be used to omit
|
||||
* PH7 features (resulting in a smaller compiled library size) or to change the default
|
||||
* values of some parameters.
|
||||
* Every effort has been made to ensure that the various combinations of compilation
|
||||
* options work harmoniously and produce a working library.
|
||||
*
|
||||
* PH7_ENABLE_THREADS
|
||||
* This option controls whether or not code is included in PH7 to enable it to operate
|
||||
* safely in a multithreaded environment. The default is not. That is,all mutexing code
|
||||
* is omitted and it is unsafe to use PH7 in a multithreaded program. When compiled
|
||||
* with the PH7_ENABLE_THREADS directive enabled, PH7 can be used in a multithreaded
|
||||
* program and it's safe to share the same virtual machine and engine instance between
|
||||
* two or more threads.
|
||||
* The value of PH7_ENABLE_THREADS can be determined at run-time using the
|
||||
* ph7_lib_is_threadsafe() interface.When PH7 has been compiled with PH7_ENABLE_THREAD
|
||||
* then the threading mode can be altered at run-time using the ph7_lib_config()
|
||||
* interface together with one of these verbs:
|
||||
* PH7_LIB_CONFIG_THREAD_LEVEL_SINGLE
|
||||
* PH7_LIB_CONFIG_THREAD_LEVEL_MULTI
|
||||
* Also note,platforms others than Windows and UNIX systems must install their own
|
||||
* mutex subsystem via ph7_lib_config() with a configuration verb set to
|
||||
* PH7_LIB_CONFIG_USER_MUTEX. Otherwise the library is not threadsafe.
|
||||
* Note that you must link PH7 with the POSIX threads library under UNIX-like systems
|
||||
* (i.e: -lpthread).Otherwise you will get a link time error.
|
||||
* Options To Omit/Enable Features:
|
||||
* The following options can be used to reduce the size of the compiled library
|
||||
* by omitting optional features. This is probably only useful in embedded systems
|
||||
* where space is especially tight, as even with all features included the PH7 library
|
||||
* is relatively small. Don't forget to tell your compiler to optimize for binary
|
||||
* size! (the -Os option if using GCC).
|
||||
* Telling your compiler to optimize for size usually has a much larger impact
|
||||
* on library footprint than employing any of these compile-time options.
|
||||
* PH7_DISABLE_BUILTIN_FUNC
|
||||
* PH7 come with more than 460 built-in functions suitable for most purposes ranging
|
||||
* from string/XML/INI processing to ZIP extracting, Base64 encoding/decoding and so on.
|
||||
* If this directive is enabled, all the built-in functions are omitted from the build.
|
||||
* Note that language construct functions such as is_int(), is_string(), func_get_arg(),
|
||||
* define(), etc. are not omitted from the build and are not affected by this directive.
|
||||
* PH7_ENABLE_MATH_FUNC
|
||||
* If this directive is enabled, built-in math functions such as sqrt(),abs(),
|
||||
* log(), ceil(), etc. are included in the build. Note that you may need to link
|
||||
* PH7 with the math library in same linux/BSD flavor (i.e: -lm).Otherwise you
|
||||
* will get a link time error.
|
||||
* PH7_DISABLE_DISK_IO
|
||||
* If this directive is enabled, built-in Virtual File System functions such as
|
||||
* chdir(), mkdir(), chroot(), unlink(), delete(), etc. are omitted from the build.
|
||||
* PH7_DISABLE_HASH_IO
|
||||
* If this directive is enabled, built-in hash functions such as md5(), sha1(),
|
||||
* md5_file(), crc32(), etc. are omitted from the build.
|
||||
* PH7_OMIT_FLOATING_POINT
|
||||
* This option is used to omit floating-point number support from the PH7 library
|
||||
* if compiling for a processor that lacks floating point support. When specified
|
||||
* the library will substitute 64-bit integer arithmetic for floating-point which
|
||||
* mean that 25.e-3 and 25 are equals and are of type integer.
|
||||
*/
|
||||
/* Symisc public definitions */
|
||||
#if !defined(SYMISC_STANDARD_DEFS)
|
||||
#define SYMISC_STANDARD_DEFS
|
||||
#if defined (_WIN32) || defined (WIN32) || defined(__MINGW32__) || defined (_MSC_VER) || defined (_WIN32_WCE)
|
||||
/* Windows Systems */
|
||||
#if !defined(__WINNT__)
|
||||
#define __WINNT__
|
||||
#endif
|
||||
/* Windows Systems */
|
||||
#if !defined(__WINNT__)
|
||||
#define __WINNT__
|
||||
#endif
|
||||
#else
|
||||
/*
|
||||
* By default we will assume that we are compiling on a UNIX systems.
|
||||
* Otherwise the OS_OTHER directive must be defined.
|
||||
*/
|
||||
#if !defined(OS_OTHER)
|
||||
#if !defined(__UNIXES__)
|
||||
#define __UNIXES__
|
||||
#endif /* __UNIXES__ */
|
||||
#else
|
||||
#endif /* OS_OTHER */
|
||||
/*
|
||||
* By default we will assume that we are compiling on a UNIX systems.
|
||||
* Otherwise the OS_OTHER directive must be defined.
|
||||
*/
|
||||
#if !defined(OS_OTHER)
|
||||
#if !defined(__UNIXES__)
|
||||
#define __UNIXES__
|
||||
#endif /* __UNIXES__ */
|
||||
#else
|
||||
#endif /* OS_OTHER */
|
||||
#endif /* __WINNT__/__UNIXES__ */
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
typedef signed __int64 sxi64; /* 64 bits(8 bytes) signed int64 */
|
||||
typedef unsigned __int64 sxu64; /* 64 bits(8 bytes) unsigned int64 */
|
||||
typedef signed __int64 sxi64; /* 64 bits(8 bytes) signed int64 */
|
||||
typedef unsigned __int64 sxu64; /* 64 bits(8 bytes) unsigned int64 */
|
||||
#else
|
||||
typedef signed long long int sxi64; /* 64 bits(8 bytes) signed int64 */
|
||||
typedef unsigned long long int sxu64; /* 64 bits(8 bytes) unsigned int64 */
|
||||
typedef signed long long int sxi64; /* 64 bits(8 bytes) signed int64 */
|
||||
typedef unsigned long long int sxu64; /* 64 bits(8 bytes) unsigned int64 */
|
||||
#endif /* _MSC_VER */
|
||||
/* Solaris additions */
|
||||
#ifndef MAP_FILE
|
||||
#define MAP_FILE 0
|
||||
#define MAP_FILE 0
|
||||
#endif
|
||||
/* Signature of the consumer routine */
|
||||
typedef int (*ProcConsumer)(const void *, unsigned int, void *);
|
||||
|
@ -265,7 +187,7 @@ struct SyMemMethods {
|
|||
void *(*xAlloc)(unsigned int); /* [Required:] Allocate a memory chunk */
|
||||
void *(*xRealloc)(void *, unsigned int); /* [Required:] Re-allocate a memory chunk */
|
||||
void (*xFree)(void *); /* [Required:] Release a memory chunk */
|
||||
unsigned int (*xChunkSize)(void *); /* [Optional:] Return chunk size */
|
||||
unsigned int (*xChunkSize)(void *); /* [Required:] Return chunk size */
|
||||
int (*xInit)(void *); /* [Optional:] Initialization callback */
|
||||
void (*xRelease)(void *); /* [Optional:] Release callback */
|
||||
void *pUserData; /* [Optional:] First argument to xInit() and xRelease() */
|
||||
|
@ -283,11 +205,11 @@ struct SyMutexMethods {
|
|||
void (*xLeave)(SyMutex *); /* [Required:] Leave a locked mutex */
|
||||
};
|
||||
#if defined (_MSC_VER) || defined (__MINGW32__) || defined (__GNUC__) && defined (__declspec)
|
||||
#define SX_APIIMPORT __declspec(dllimport)
|
||||
#define SX_APIEXPORT __declspec(dllexport)
|
||||
#define SX_APIIMPORT __declspec(dllimport)
|
||||
#define SX_APIEXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define SX_APIIMPORT
|
||||
#define SX_APIEXPORT
|
||||
#define SX_APIIMPORT
|
||||
#define SX_APIEXPORT
|
||||
#endif
|
||||
/* Standard return values from Symisc public interfaces */
|
||||
#define SXRET_OK 0 /* Not an error */
|
||||
|
@ -325,7 +247,6 @@ struct SyMutexMethods {
|
|||
#define SXERR_BIG (-32) /* Too big for processing */
|
||||
#define SXERR_RETRY (-33) /* Retry your call */
|
||||
#define SXERR_IGNORE (-63) /* Ignore */
|
||||
#endif /* SYMISC_PUBLIC_DEFS */
|
||||
/* Standard PH7 return values */
|
||||
#define PH7_OK SXRET_OK /* Successful result */
|
||||
/* beginning-of-error-codes */
|
||||
|
@ -341,13 +262,11 @@ struct SyMutexMethods {
|
|||
* If compiling for a processor that lacks floating point
|
||||
* support, substitute integer for floating-point.
|
||||
*/
|
||||
#ifdef PH7_OMIT_FLOATING_POINT
|
||||
typedef sxi64 ph7_real;
|
||||
#else
|
||||
typedef double ph7_real;
|
||||
#endif
|
||||
typedef sxi64 ph7_int64;
|
||||
#define PH7_APIEXPORT SX_APIEXPORT
|
||||
#define PH7_APIIMPORT SX_APIIMPORT
|
||||
|
||||
/*
|
||||
* Engine Configuration Commands.
|
||||
*
|
||||
|
@ -360,11 +279,12 @@ typedef sxi64 ph7_int64;
|
|||
* return value indicates failure.
|
||||
* For a full discussion on the configuration verbs and their expected
|
||||
* parameters, please refer to this page:
|
||||
* http://ph7.symisc.net/c_api_func.html#ph7_config
|
||||
* https://ph7.symisc.net/c_api_func.html#ph7_config
|
||||
*/
|
||||
#define PH7_CONFIG_ERR_OUTPUT 1 /* TWO ARGUMENTS: int (*xConsumer)(const void *pOut,unsigned int nLen,void *pUserData),void *pUserData */
|
||||
#define PH7_CONFIG_ERR_ABORT 2 /* RESERVED FOR FUTURE USE */
|
||||
#define PH7_CONFIG_ERR_LOG 3 /* TWO ARGUMENTS: const char **pzBuf,int *pLen */
|
||||
#define PH7_CONFIG_MEM_LIMIT 4 /* ONE ARGUMENT: char *nMemLimit */
|
||||
/*
|
||||
* Virtual Machine Configuration Commands.
|
||||
*
|
||||
|
@ -380,28 +300,24 @@ typedef sxi64 ph7_int64;
|
|||
* a HTTP request and PH7_VM_CONFIG_ARGV_ENTRY which populate the $argv array.
|
||||
* For a full discussion on the configuration verbs and their expected parameters, please
|
||||
* refer to this page:
|
||||
* http://ph7.symisc.net/c_api_func.html#ph7_vm_config
|
||||
* https://ph7.symisc.net/c_api_func.html#ph7_vm_config
|
||||
*/
|
||||
#define PH7_VM_CONFIG_OUTPUT 1 /* TWO ARGUMENTS: int (*xConsumer)(const void *pOut,unsigned int nLen,void *pUserData),void *pUserData */
|
||||
#define PH7_VM_CONFIG_IMPORT_PATH 3 /* ONE ARGUMENT: const char *zIncludePath */
|
||||
#define PH7_VM_CONFIG_ERR_REPORT 4 /* NO ARGUMENTS: Report all run-time errors in the VM output */
|
||||
#define PH7_VM_CONFIG_RECURSION_DEPTH 5 /* ONE ARGUMENT: int nMaxDepth */
|
||||
#define PH7_VM_OUTPUT_LENGTH 6 /* ONE ARGUMENT: unsigned int *pLength */
|
||||
#define PH7_VM_CONFIG_CREATE_SUPER 7 /* TWO ARGUMENTS: const char *zName,ph7_value *pValue */
|
||||
#define PH7_VM_CONFIG_CREATE_VAR 8 /* TWO ARGUMENTS: const char *zName,ph7_value *pValue */
|
||||
#define PH7_VM_CONFIG_HTTP_REQUEST 9 /* TWO ARGUMENTS: const char *zRawRequest,int nRequestLength */
|
||||
#define PH7_VM_CONFIG_SERVER_ATTR 10 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
|
||||
#define PH7_VM_CONFIG_ENV_ATTR 11 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
|
||||
#define PH7_VM_CONFIG_SESSION_ATTR 12 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
|
||||
#define PH7_VM_CONFIG_POST_ATTR 13 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
|
||||
#define PH7_VM_CONFIG_GET_ATTR 14 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
|
||||
#define PH7_VM_CONFIG_COOKIE_ATTR 15 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
|
||||
#define PH7_VM_CONFIG_HEADER_ATTR 16 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
|
||||
#define PH7_VM_CONFIG_EXEC_VALUE 17 /* ONE ARGUMENT: ph7_value **ppValue */
|
||||
#define PH7_VM_CONFIG_IO_STREAM 18 /* ONE ARGUMENT: const ph7_io_stream *pStream */
|
||||
#define PH7_VM_CONFIG_ARGV_ENTRY 19 /* ONE ARGUMENT: const char *zValue */
|
||||
#define PH7_VM_CONFIG_EXTRACT_OUTPUT 20 /* TWO ARGUMENTS: const void **ppOut,unsigned int *pOutputLen */
|
||||
#define PH7_VM_CONFIG_ERR_LOG_HANDLER 21 /* ONE ARGUMENT: void (*xErrLog)(const char *,int,const char *,const char *) */
|
||||
#define PH7_VM_CONFIG_CREATE_SUPER 5 /* TWO ARGUMENTS: const char *zName,ph7_value *pValue */
|
||||
#define PH7_VM_CONFIG_CREATE_VAR 6 /* TWO ARGUMENTS: const char *zName,ph7_value *pValue */
|
||||
#define PH7_VM_CONFIG_HTTP_REQUEST 7 /* TWO ARGUMENTS: const char *zRawRequest,int nRequestLength */
|
||||
#define PH7_VM_CONFIG_SERVER_ATTR 8 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
|
||||
#define PH7_VM_CONFIG_ENV_ATTR 9 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
|
||||
#define PH7_VM_CONFIG_SESSION_ATTR 10 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
|
||||
#define PH7_VM_CONFIG_POST_ATTR 11 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
|
||||
#define PH7_VM_CONFIG_GET_ATTR 12 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
|
||||
#define PH7_VM_CONFIG_COOKIE_ATTR 13 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
|
||||
#define PH7_VM_CONFIG_HEADER_ATTR 14 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
|
||||
#define PH7_VM_CONFIG_IO_STREAM 15 /* ONE ARGUMENT: const ph7_io_stream *pStream */
|
||||
#define PH7_VM_CONFIG_ARGV_ENTRY 16 /* ONE ARGUMENT: const char *zValue */
|
||||
#define PH7_VM_CONFIG_EXTRACT_OUTPUT 17 /* TWO ARGUMENTS: const void **ppOut,unsigned int *pOutputLen */
|
||||
/*
|
||||
* Global Library Configuration Commands.
|
||||
*
|
||||
|
@ -426,7 +342,7 @@ typedef sxi64 ph7_int64;
|
|||
* and their expected parameters.
|
||||
* For a full discussion on the configuration verbs and their expected parameters,please
|
||||
* refer to this page:
|
||||
* http://ph7.symisc.net/c_api_func.html#Global_Library_Management_Interfaces
|
||||
* https://ph7.symisc.net/c_api_func.html#Global_Library_Management_Interfaces
|
||||
*/
|
||||
#define PH7_LIB_CONFIG_USER_MALLOC 1 /* ONE ARGUMENT: const SyMemMethods *pMemMethods */
|
||||
#define PH7_LIB_CONFIG_MEM_ERR_CALLBACK 2 /* TWO ARGUMENTS: int (*xMemError)(void *),void *pUserData */
|
||||
|
@ -436,29 +352,26 @@ typedef sxi64 ph7_int64;
|
|||
#define PH7_LIB_CONFIG_VFS 6 /* ONE ARGUMENT: const ph7_vfs *pVfs */
|
||||
/*
|
||||
* Compile-time flags.
|
||||
* The new compile interfaces [ph7_compile_v2()] and [ph7_compile_file()] takes
|
||||
* as their last argument zero or more combination of compile time flags.
|
||||
* These flags are used to control the behavior of the PH7 compiler while
|
||||
*
|
||||
* VmEvalChunk and PH7_CompileAerScript takes iFlags argument
|
||||
* which controls the behavior of the PH7 Engine while
|
||||
* processing the input.
|
||||
* Refer to the official documentation for additional information.
|
||||
*/
|
||||
#define PH7_PHP_ONLY 0x01 /* If this flag is set then the code to compile is assumed
|
||||
* to be plain PHP only. That is, there is no need to delimit
|
||||
* the PHP code using the standard tags such as <?php ?> or <? ?>.
|
||||
* Everything will pass through the PH7 compiler.
|
||||
*/
|
||||
#define PH7_PHP_EXPR 0x02 /* This flag is reserved for future use. */
|
||||
#define PH7_AERSCRIPT_CODE 0x01 /* AerScript Code */
|
||||
#define PH7_AERSCRIPT_CHNK 0x02 /* AerScript Chunk of Code */
|
||||
#define PH7_AERSCRIPT_EXPR 0x04 /* AerScript Expression */
|
||||
#define PH7_AERSCRIPT_FILE 0x08 /* AerScript File Inclusion */
|
||||
/*
|
||||
* Call Context Error Message Severity Level.
|
||||
*
|
||||
* The following constans are the allowed severity level that can
|
||||
* passed as the second argument to the [ph7_context_throw_error()] or
|
||||
* [ph7_context_throw_error_format()] interfaces.
|
||||
* passed as the second argument to the PH7_VmThrowError().
|
||||
* Refer to the official documentation for additional information.
|
||||
*/
|
||||
#define PH7_CTX_ERR 1 /* Call context error such as unexpected number of arguments,invalid types and so on. */
|
||||
#define PH7_CTX_WARNING 2 /* Call context Warning */
|
||||
#define PH7_CTX_NOTICE 3 /* Call context Notice */
|
||||
#define PH7_CTX_ERR 1 /* Call context Error such as unexpected number of arguments,invalid types and so on. */
|
||||
#define PH7_CTX_WARNING 2 /* Call context Warning */
|
||||
#define PH7_CTX_NOTICE 3 /* Call context Notice */
|
||||
#define PH7_CTX_DEPRECATED 4 /* Call context Deprecated notice */
|
||||
/* Current VFS structure version*/
|
||||
#define PH7_VFS_VERSION 2
|
||||
/*
|
||||
|
@ -509,10 +422,13 @@ struct ph7_vfs {
|
|||
ph7_int64(*xFileAtime)(const char *); /* Gets last access time of file */
|
||||
ph7_int64(*xFileMtime)(const char *); /* Gets file modification time */
|
||||
ph7_int64(*xFileCtime)(const char *); /* Gets inode change time of file */
|
||||
ph7_int64(*xFileGroup)(const char *); /* Gets file group */
|
||||
ph7_int64(*xFileInode)(const char *); /* Gets file inode */
|
||||
ph7_int64(*xFileOwner)(const char *); /* Gets file owner */
|
||||
int (*xStat)(const char *, ph7_value *, ph7_value *); /* Gives information about a file */
|
||||
int (*xlStat)(const char *, ph7_value *, ph7_value *); /* Gives information about a file */
|
||||
int (*xIsfile)(const char *); /* Tells whether the filename is a regular file */
|
||||
int (*xIslink)(const char *); /* Tells whether the filename is a symbolic link */
|
||||
int (*xIsFile)(const char *); /* Tells whether the filename is a regular file */
|
||||
int (*xIsLink)(const char *); /* Tells whether the filename is a symbolic link */
|
||||
int (*xReadable)(const char *); /* Tells whether a file exists and is readable */
|
||||
int (*xWritable)(const char *); /* Tells whether the filename is writable */
|
||||
int (*xExecutable)(const char *); /* Tells whether the filename is executable */
|
||||
|
@ -529,14 +445,13 @@ struct ph7_vfs {
|
|||
int (*xUid)(void); /* user ID of the process */
|
||||
int (*xGid)(void); /* group ID of the process */
|
||||
void (*xUsername)(ph7_context *); /* Running username */
|
||||
int (*xExec)(const char *, ph7_context *); /* Execute an external program */
|
||||
};
|
||||
/* Current PH7 IO stream structure version. */
|
||||
#define PH7_IO_STREAM_VERSION 1
|
||||
/*
|
||||
* Possible open mode flags that can be passed to the xOpen() routine
|
||||
* of the underlying IO stream device .
|
||||
* Refer to the PH7 IO Stream C/C++ specification manual (http://ph7.symisc.net/io_stream_spec.html)
|
||||
* Refer to the PH7 IO Stream C/C++ specification manual (https://ph7.symisc.net/io_stream_spec.html)
|
||||
* for additional information.
|
||||
*/
|
||||
#define PH7_IO_OPEN_RDONLY 0x001 /* Read-only open */
|
||||
|
@ -576,7 +491,7 @@ struct ph7_vfs {
|
|||
* Currently the PH7 development team is working on the implementation of the http:// and ftp://
|
||||
* IO stream protocols. These devices will be available in the next major release of the PH7 engine.
|
||||
* Developers wishing to implement their own IO stream devices must understand and follow
|
||||
* The PH7 IO Stream C/C++ specification manual (http://ph7.symisc.net/io_stream_spec.html).
|
||||
* The PH7 IO Stream C/C++ specification manual (https://ph7.symisc.net/io_stream_spec.html).
|
||||
*/
|
||||
struct ph7_io_stream {
|
||||
const char *zName; /* Underlying stream name [i.e: file/http/zip/php,..] */
|
||||
|
@ -604,16 +519,16 @@ struct ph7_io_stream {
|
|||
PH7_APIEXPORT int ph7_init(ph7 **ppEngine);
|
||||
PH7_APIEXPORT int ph7_config(ph7 *pEngine, int nConfigOp, ...);
|
||||
PH7_APIEXPORT int ph7_release(ph7 *pEngine);
|
||||
PH7_APIEXPORT int ph7_vm_init(ph7 *pEngine, ph7_vm **ppOutVm, int bDebug);
|
||||
/* Compile Interfaces */
|
||||
PH7_APIEXPORT int ph7_compile(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOutVm);
|
||||
PH7_APIEXPORT int ph7_compile_v2(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOutVm, int iFlags);
|
||||
PH7_APIEXPORT int ph7_compile_file(ph7 *pEngine, const char *zFilePath, ph7_vm **ppOutVm, int iFlags);
|
||||
PH7_APIEXPORT int ph7_compile_code(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOutVm);
|
||||
PH7_APIEXPORT int ph7_compile_file(ph7 *pEngine, const char *zFilePath, ph7_vm **ppOutVm);
|
||||
/* Virtual Machine Handling Interfaces */
|
||||
PH7_APIEXPORT int ph7_vm_config(ph7_vm *pVm, int iConfigOp, ...);
|
||||
PH7_APIEXPORT int ph7_vm_exec(ph7_vm *pVm, int *pExitStatus);
|
||||
PH7_APIEXPORT int ph7_vm_reset(ph7_vm *pVm);
|
||||
PH7_APIEXPORT int ph7_vm_release(ph7_vm *pVm);
|
||||
PH7_APIEXPORT int ph7_vm_dump_v2(ph7_vm *pVm, int (*xConsumer)(const void *, unsigned int, void *), void *pUserData);
|
||||
PH7_APIEXPORT int ph7_vm_dump(ph7_vm *pVm, int (*xConsumer)(const void *, unsigned int, void *), void *pUserData);
|
||||
/* In-process Extending Interfaces */
|
||||
PH7_APIEXPORT int ph7_create_function(ph7_vm *pVm, const char *zName, int (*xFunc)(ph7_context *, int, ph7_value **), void *pUserData);
|
||||
PH7_APIEXPORT int ph7_delete_function(ph7_vm *pVm, const char *zName);
|
||||
|
@ -640,8 +555,6 @@ PH7_APIEXPORT int ph7_result_resource(ph7_context *pCtx, void *pUserData);
|
|||
/* Call Context Handling Interfaces */
|
||||
PH7_APIEXPORT int ph7_context_output(ph7_context *pCtx, const char *zString, int nLen);
|
||||
PH7_APIEXPORT int ph7_context_output_format(ph7_context *pCtx, const char *zFormat, ...);
|
||||
PH7_APIEXPORT int ph7_context_throw_error(ph7_context *pCtx, int iErr, const char *zErr);
|
||||
PH7_APIEXPORT int ph7_context_throw_error_format(ph7_context *pCtx, int iErr, const char *zFormat, ...);
|
||||
PH7_APIEXPORT unsigned int ph7_context_random_num(ph7_context *pCtx);
|
||||
PH7_APIEXPORT int ph7_context_random_string(ph7_context *pCtx, char *zBuf, int nBuflen);
|
||||
PH7_APIEXPORT void *ph7_context_user_data(ph7_context *pCtx);
|
||||
|
@ -665,13 +578,13 @@ PH7_APIEXPORT void ph7_context_release_value(ph7_context *pCtx, ph7_value *pValu
|
|||
PH7_APIEXPORT int ph7_value_int(ph7_value *pVal, int iValue);
|
||||
PH7_APIEXPORT int ph7_value_int64(ph7_value *pVal, ph7_int64 iValue);
|
||||
PH7_APIEXPORT int ph7_value_bool(ph7_value *pVal, int iBool);
|
||||
PH7_APIEXPORT int ph7_value_null(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_double(ph7_value *pVal, double Value);
|
||||
PH7_APIEXPORT int ph7_value_string(ph7_value *pVal, const char *zString, int nLen);
|
||||
PH7_APIEXPORT int ph7_value_string_format(ph7_value *pVal, const char *zFormat, ...);
|
||||
PH7_APIEXPORT int ph7_value_reset_string_cursor(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_resource(ph7_value *pVal, void *pUserData);
|
||||
PH7_APIEXPORT int ph7_value_release(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_void(ph7_value *pVal);
|
||||
PH7_APIEXPORT ph7_value *ph7_array_fetch(ph7_value *pArray, const char *zKey, int nByte);
|
||||
PH7_APIEXPORT int ph7_array_walk(ph7_value *pArray, int (*xWalk)(ph7_value *, ph7_value *, void *), void *pUserData);
|
||||
PH7_APIEXPORT int ph7_array_add_elem(ph7_value *pArray, ph7_value *pKey, ph7_value *pValue);
|
||||
|
@ -685,14 +598,14 @@ PH7_APIEXPORT int ph7_value_is_int(ph7_value *pVal);
|
|||
PH7_APIEXPORT int ph7_value_is_float(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_bool(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_string(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_null(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_numeric(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_callback(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_callable(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_scalar(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_array(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_numeric(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_object(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_resource(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_empty(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_char(ph7_value *pVal);
|
||||
PH7_APIEXPORT int ph7_value_is_void(ph7_value *pVal);
|
||||
/* Global Library Management Interfaces */
|
||||
PH7_APIEXPORT int ph7_lib_init(void);
|
||||
PH7_APIEXPORT int ph7_lib_config(int nConfigOp, ...);
|
||||
|
|
645
include/ph7int.h
645
include/ph7int.h
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,520 @@
|
|||
/**
|
||||
* @PROJECT AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE modules/ctype/ctype.c
|
||||
* @DESCRIPTION Character type checking module for AerScript Interpreter
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#include "ctype.h"
|
||||
|
||||
/*
|
||||
* bool ctype_alnum(string $text)
|
||||
* Checks if all of the characters in the provided string, text, are alphanumeric.
|
||||
* Parameters
|
||||
* $text
|
||||
* The tested string.
|
||||
* Return
|
||||
* TRUE if every character in text is either a letter or a digit, FALSE otherwise.
|
||||
*/
|
||||
static int PH7_builtin_ctype_alnum(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
const unsigned char *zIn, *zEnd;
|
||||
int nLen;
|
||||
if(nArg < 1) {
|
||||
/* Missing arguments, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract the target string */
|
||||
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
|
||||
zEnd = &zIn[nLen];
|
||||
if(nLen < 1) {
|
||||
/* Empty string, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Perform the requested operation */
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
/* If we reach the end of the string,then the test succeeded. */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
if(!SyisAlphaNum(zIn[0])) {
|
||||
break;
|
||||
}
|
||||
/* Point to the next character */
|
||||
zIn++;
|
||||
}
|
||||
/* The test failed, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* bool ctype_alpha(string $text)
|
||||
* Checks if all of the characters in the provided string, text, are alphabetic.
|
||||
* Parameters
|
||||
* $text
|
||||
* The tested string.
|
||||
* Return
|
||||
* TRUE if every character in text is a letter from the current locale, FALSE otherwise.
|
||||
*/
|
||||
static int PH7_builtin_ctype_alpha(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
const unsigned char *zIn, *zEnd;
|
||||
int nLen;
|
||||
if(nArg < 1) {
|
||||
/* Missing arguments, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract the target string */
|
||||
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
|
||||
zEnd = &zIn[nLen];
|
||||
if(nLen < 1) {
|
||||
/* Empty string, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Perform the requested operation */
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
/* If we reach the end of the string,then the test succeeded. */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
if(!SyisAlpha(zIn[0])) {
|
||||
break;
|
||||
}
|
||||
/* Point to the next character */
|
||||
zIn++;
|
||||
}
|
||||
/* The test failed, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* bool ctype_cntrl(string $text)
|
||||
* Checks if all of the characters in the provided string, text, are control characters.
|
||||
* Parameters
|
||||
* $text
|
||||
* The tested string.
|
||||
* Return
|
||||
* TRUE if every character in text is a control characters,FALSE otherwise.
|
||||
*/
|
||||
static int PH7_builtin_ctype_cntrl(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
const unsigned char *zIn, *zEnd;
|
||||
int nLen;
|
||||
if(nArg < 1) {
|
||||
/* Missing arguments, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract the target string */
|
||||
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
|
||||
zEnd = &zIn[nLen];
|
||||
if(nLen < 1) {
|
||||
/* Empty string, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Perform the requested operation */
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
/* If we reach the end of the string,then the test succeeded. */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
if(zIn[0] >= 0xc0) {
|
||||
/* UTF-8 stream */
|
||||
break;
|
||||
}
|
||||
if(!SyisCtrl(zIn[0])) {
|
||||
break;
|
||||
}
|
||||
/* Point to the next character */
|
||||
zIn++;
|
||||
}
|
||||
/* The test failed, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* bool ctype_digit(string $text)
|
||||
* Checks if all of the characters in the provided string, text, are numerical.
|
||||
* Parameters
|
||||
* $text
|
||||
* The tested string.
|
||||
* Return
|
||||
* TRUE if every character in the string text is a decimal digit, FALSE otherwise.
|
||||
*/
|
||||
static int PH7_builtin_ctype_digit(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
const unsigned char *zIn, *zEnd;
|
||||
int nLen;
|
||||
if(nArg < 1) {
|
||||
/* Missing arguments, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract the target string */
|
||||
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
|
||||
zEnd = &zIn[nLen];
|
||||
if(nLen < 1) {
|
||||
/* Empty string, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Perform the requested operation */
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
/* If we reach the end of the string,then the test succeeded. */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
if(zIn[0] >= 0xc0) {
|
||||
/* UTF-8 stream */
|
||||
break;
|
||||
}
|
||||
if(!SyisDigit(zIn[0])) {
|
||||
break;
|
||||
}
|
||||
/* Point to the next character */
|
||||
zIn++;
|
||||
}
|
||||
/* The test failed, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* bool ctype_xdigit(string $text)
|
||||
* Check for character(s) representing a hexadecimal digit.
|
||||
* Parameters
|
||||
* $text
|
||||
* The tested string.
|
||||
* Return
|
||||
* Returns TRUE if every character in text is a hexadecimal 'digit', that is
|
||||
* a decimal digit or a character from [A-Fa-f] , FALSE otherwise.
|
||||
*/
|
||||
static int PH7_builtin_ctype_xdigit(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
const unsigned char *zIn, *zEnd;
|
||||
int nLen;
|
||||
if(nArg < 1) {
|
||||
/* Missing arguments, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract the target string */
|
||||
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
|
||||
zEnd = &zIn[nLen];
|
||||
if(nLen < 1) {
|
||||
/* Empty string, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Perform the requested operation */
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
/* If we reach the end of the string,then the test succeeded. */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
if(zIn[0] >= 0xc0) {
|
||||
/* UTF-8 stream */
|
||||
break;
|
||||
}
|
||||
if(!SyisHex(zIn[0])) {
|
||||
break;
|
||||
}
|
||||
/* Point to the next character */
|
||||
zIn++;
|
||||
}
|
||||
/* The test failed, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* bool ctype_graph(string $text)
|
||||
* Checks if all of the characters in the provided string, text, creates visible output.
|
||||
* Parameters
|
||||
* $text
|
||||
* The tested string.
|
||||
* Return
|
||||
* Returns TRUE if every character in text is printable and actually creates visible output
|
||||
* (no white space), FALSE otherwise.
|
||||
*/
|
||||
static int PH7_builtin_ctype_graph(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
const unsigned char *zIn, *zEnd;
|
||||
int nLen;
|
||||
if(nArg < 1) {
|
||||
/* Missing arguments, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract the target string */
|
||||
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
|
||||
zEnd = &zIn[nLen];
|
||||
if(nLen < 1) {
|
||||
/* Empty string, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Perform the requested operation */
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
/* If we reach the end of the string,then the test succeeded. */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
if(zIn[0] >= 0xc0) {
|
||||
/* UTF-8 stream */
|
||||
break;
|
||||
}
|
||||
if(!SyisGraph(zIn[0])) {
|
||||
break;
|
||||
}
|
||||
/* Point to the next character */
|
||||
zIn++;
|
||||
}
|
||||
/* The test failed, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* bool ctype_print(string $text)
|
||||
* Checks if all of the characters in the provided string, text, are printable.
|
||||
* Parameters
|
||||
* $text
|
||||
* The tested string.
|
||||
* Return
|
||||
* Returns TRUE if every character in text will actually create output (including blanks).
|
||||
* Returns FALSE if text contains control characters or characters that do not have any output
|
||||
* or control function at all.
|
||||
*/
|
||||
static int PH7_builtin_ctype_print(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
const unsigned char *zIn, *zEnd;
|
||||
int nLen;
|
||||
if(nArg < 1) {
|
||||
/* Missing arguments, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract the target string */
|
||||
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
|
||||
zEnd = &zIn[nLen];
|
||||
if(nLen < 1) {
|
||||
/* Empty string, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Perform the requested operation */
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
/* If we reach the end of the string,then the test succeeded. */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
if(zIn[0] >= 0xc0) {
|
||||
/* UTF-8 stream */
|
||||
break;
|
||||
}
|
||||
if(!SyisPrint(zIn[0])) {
|
||||
break;
|
||||
}
|
||||
/* Point to the next character */
|
||||
zIn++;
|
||||
}
|
||||
/* The test failed, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* bool ctype_punct(string $text)
|
||||
* Checks if all of the characters in the provided string, text, are punctuation character.
|
||||
* Parameters
|
||||
* $text
|
||||
* The tested string.
|
||||
* Return
|
||||
* Returns TRUE if every character in text is printable, but neither letter
|
||||
* digit or blank, FALSE otherwise.
|
||||
*/
|
||||
static int PH7_builtin_ctype_punct(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
const unsigned char *zIn, *zEnd;
|
||||
int nLen;
|
||||
if(nArg < 1) {
|
||||
/* Missing arguments, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract the target string */
|
||||
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
|
||||
zEnd = &zIn[nLen];
|
||||
if(nLen < 1) {
|
||||
/* Empty string, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Perform the requested operation */
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
/* If we reach the end of the string,then the test succeeded. */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
if(zIn[0] >= 0xc0) {
|
||||
/* UTF-8 stream */
|
||||
break;
|
||||
}
|
||||
if(!SyisPunct(zIn[0])) {
|
||||
break;
|
||||
}
|
||||
/* Point to the next character */
|
||||
zIn++;
|
||||
}
|
||||
/* The test failed, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* bool ctype_space(string $text)
|
||||
* Checks if all of the characters in the provided string, text, creates whitespace.
|
||||
* Parameters
|
||||
* $text
|
||||
* The tested string.
|
||||
* Return
|
||||
* Returns TRUE if every character in text creates some sort of white space, FALSE otherwise.
|
||||
* Besides the blank character this also includes tab, vertical tab, line feed, carriage return
|
||||
* and form feed characters.
|
||||
*/
|
||||
static int PH7_builtin_ctype_space(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
const unsigned char *zIn, *zEnd;
|
||||
int nLen;
|
||||
if(nArg < 1) {
|
||||
/* Missing arguments, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract the target string */
|
||||
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
|
||||
zEnd = &zIn[nLen];
|
||||
if(nLen < 1) {
|
||||
/* Empty string, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Perform the requested operation */
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
/* If we reach the end of the string,then the test succeeded. */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
if(zIn[0] >= 0xc0) {
|
||||
/* UTF-8 stream */
|
||||
break;
|
||||
}
|
||||
if(!SyisSpace(zIn[0])) {
|
||||
break;
|
||||
}
|
||||
/* Point to the next character */
|
||||
zIn++;
|
||||
}
|
||||
/* The test failed, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* bool ctype_lower(string $text)
|
||||
* Checks if all of the characters in the provided string, text, are lowercase letters.
|
||||
* Parameters
|
||||
* $text
|
||||
* The tested string.
|
||||
* Return
|
||||
* Returns TRUE if every character in text is a lowercase letter in the current locale.
|
||||
*/
|
||||
static int PH7_builtin_ctype_lower(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
const unsigned char *zIn, *zEnd;
|
||||
int nLen;
|
||||
if(nArg < 1) {
|
||||
/* Missing arguments, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract the target string */
|
||||
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
|
||||
zEnd = &zIn[nLen];
|
||||
if(nLen < 1) {
|
||||
/* Empty string, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Perform the requested operation */
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
/* If we reach the end of the string,then the test succeeded. */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
if(!SyisLower(zIn[0])) {
|
||||
break;
|
||||
}
|
||||
/* Point to the next character */
|
||||
zIn++;
|
||||
}
|
||||
/* The test failed, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* bool ctype_upper(string $text)
|
||||
* Checks if all of the characters in the provided string, text, are uppercase letters.
|
||||
* Parameters
|
||||
* $text
|
||||
* The tested string.
|
||||
* Return
|
||||
* Returns TRUE if every character in text is a uppercase letter in the current locale.
|
||||
*/
|
||||
static int PH7_builtin_ctype_upper(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
const unsigned char *zIn, *zEnd;
|
||||
int nLen;
|
||||
if(nArg < 1) {
|
||||
/* Missing arguments, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract the target string */
|
||||
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
|
||||
zEnd = &zIn[nLen];
|
||||
if(nLen < 1) {
|
||||
/* Empty string, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Perform the requested operation */
|
||||
for(;;) {
|
||||
if(zIn >= zEnd) {
|
||||
/* If we reach the end of the string,then the test succeeded. */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
if(!SyisUpper(zIn[0])) {
|
||||
break;
|
||||
}
|
||||
/* Point to the next character */
|
||||
zIn++;
|
||||
}
|
||||
/* The test failed, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc) {
|
||||
sxi32 rc;
|
||||
sxu32 n;
|
||||
desc->zString = MODULE_DESC;
|
||||
*ver = MODULE_VER;
|
||||
for(n = 0; n < SX_ARRAYSIZE(ctypeFuncList); ++n) {
|
||||
rc = ph7_create_function(&(*pVm), ctypeFuncList[n].zName, ctypeFuncList[n].xFunc, &(*pVm));
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* @PROJECT AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE modules/ctype/ctype.h
|
||||
* @DESCRIPTION Character type checking module for AerScript Interpreter
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#ifndef __CTYPE_H__
|
||||
#define __CTYPE_H__
|
||||
|
||||
#include "ph7.h"
|
||||
#include "ph7int.h"
|
||||
|
||||
#define MODULE_DESC "CType Module"
|
||||
#define MODULE_VER 1.0
|
||||
|
||||
/* Forward reference */
|
||||
static int PH7_builtin_ctype_alnum(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_ctype_alpha(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_ctype_cntrl(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_ctype_digit(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_ctype_xdigit(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_ctype_graph(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_ctype_print(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_ctype_punct(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_ctype_space(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_ctype_lower(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_ctype_upper(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc);
|
||||
|
||||
static const ph7_builtin_func ctypeFuncList[] = {
|
||||
{ "ctype_alnum", PH7_builtin_ctype_alnum },
|
||||
{ "ctype_alpha", PH7_builtin_ctype_alpha },
|
||||
{ "ctype_cntrl", PH7_builtin_ctype_cntrl },
|
||||
{ "ctype_digit", PH7_builtin_ctype_digit },
|
||||
{ "ctype_xdigit", PH7_builtin_ctype_xdigit},
|
||||
{ "ctype_graph", PH7_builtin_ctype_graph },
|
||||
{ "ctype_print", PH7_builtin_ctype_print },
|
||||
{ "ctype_punct", PH7_builtin_ctype_punct },
|
||||
{ "ctype_space", PH7_builtin_ctype_space },
|
||||
{ "ctype_lower", PH7_builtin_ctype_lower },
|
||||
{ "ctype_upper", PH7_builtin_ctype_upper }
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,7 +1,21 @@
|
|||
/**
|
||||
* @PROJECT AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE modules/dummy/dummy.c
|
||||
* @DESCRIPTION Dummy module for AerScript Interpreter
|
||||
* @DEVELOPERS Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#include "dummy.h"
|
||||
|
||||
int psharp_dummy_function(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
static void AER_DUMMY_CONSTANT_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_bool(pVal, 1);
|
||||
}
|
||||
|
||||
int aer_dummy_function(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
SyString dummy;
|
||||
SXUNUSED(nArg);
|
||||
SXUNUSED(apArg);
|
||||
const char *text = "Hello world from dummy module!";
|
||||
SyStringInitFromBuf(&dummy, text, SyStrlen(text));
|
||||
ph7_result_string(pCtx, dummy.zString, dummy.nByte);
|
||||
|
@ -11,9 +25,14 @@ int psharp_dummy_function(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc) {
|
||||
sxi32 rc;
|
||||
sxu32 n;
|
||||
|
||||
desc->zString = MODULE_DESC;
|
||||
*ver = MODULE_VER;
|
||||
for(n = 0; n < SX_ARRAYSIZE(dummyConstList); ++n) {
|
||||
rc = ph7_create_constant(&(*pVm), dummyConstList[n].zName, dummyConstList[n].xExpand, &(*pVm));
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
for(n = 0 ; n < SX_ARRAYSIZE(dummyFuncList) ; ++n) {
|
||||
rc = ph7_create_function(&(*pVm), dummyFuncList[n].zName, dummyFuncList[n].xFunc, &(*pVm));
|
||||
if(rc != SXRET_OK) {
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
/**
|
||||
* @PROJECT AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE modules/dummy/dummy.h
|
||||
* @DESCRIPTION Dummy module for AerScript Interpreter
|
||||
* @DEVELOPERS Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#ifndef __DUMMY_H__
|
||||
#define __DUMMY_H__
|
||||
|
||||
|
@ -10,11 +17,18 @@
|
|||
/* Forward reference & declaration */
|
||||
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc);
|
||||
|
||||
/* Constants provided by DUMMY module */
|
||||
static void AER_DUMMY_CONSTANT_Const(ph7_value *pVal, void *pUserData);
|
||||
|
||||
/* Functions provided by DUMMY module */
|
||||
int psharp_dummy_function(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
int aer_dummy_function(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
|
||||
static const ph7_builtin_constant dummyConstList[] = {
|
||||
{"DUMMY_CONSTANT", AER_DUMMY_CONSTANT_Const},
|
||||
};
|
||||
|
||||
static const ph7_builtin_func dummyFuncList[] = {
|
||||
{"dummy_function", psharp_dummy_function },
|
||||
{"dummy_function", aer_dummy_function },
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
/**
|
||||
* @PROJECT AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE modules/json/json.c
|
||||
* @DESCRIPTION JavaScript Object Notation (JSON) module for AerScript Interpreter
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#include "json.h"
|
||||
|
||||
/*
|
||||
|
@ -151,7 +159,7 @@ static sxi32 VmJsonEncode(
|
|||
ph7_context *pCtx = pData->pCtx;
|
||||
int iFlags = pData->iFlags;
|
||||
int nByte;
|
||||
if(ph7_value_is_null(pIn) || ph7_value_is_resource(pIn)) {
|
||||
if(ph7_value_is_void(pIn) || ph7_value_is_resource(pIn)) {
|
||||
/* null */
|
||||
ph7_result_string(pCtx, "null", (int)sizeof("null") - 1);
|
||||
} else if(ph7_value_is_bool(pIn)) {
|
||||
|
@ -258,7 +266,7 @@ static sxi32 VmJsonEncode(
|
|||
static int VmJsonArrayEncode(ph7_value *pKey, ph7_value *pValue, void *pUserData) {
|
||||
json_private_data *pJson = (json_private_data *)pUserData;
|
||||
if(pJson->nRecCount > 31) {
|
||||
/* Recursion limit reached,return immediately */
|
||||
/* Recursion limit reached, return immediately */
|
||||
return PH7_OK;
|
||||
}
|
||||
if(!pJson->isFirst) {
|
||||
|
@ -288,7 +296,7 @@ static int VmJsonArrayEncode(ph7_value *pKey, ph7_value *pValue, void *pUserData
|
|||
static int VmJsonObjectEncode(const char *zAttr, ph7_value *pValue, void *pUserData) {
|
||||
json_private_data *pJson = (json_private_data *)pUserData;
|
||||
if(pJson->nRecCount > 31) {
|
||||
/* Recursion limit reached,return immediately */
|
||||
/* Recursion limit reached, return immediately */
|
||||
return PH7_OK;
|
||||
}
|
||||
if(!pJson->isFirst) {
|
||||
|
@ -328,7 +336,7 @@ static int VmJsonObjectEncode(const char *zAttr, ph7_value *pValue, void *pUserD
|
|||
static int vm_builtin_json_encode(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
json_private_data sJson;
|
||||
if(nArg < 1) {
|
||||
/* Missing arguments,return FALSE */
|
||||
/* Missing arguments, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -613,14 +621,14 @@ static sxi32 VmJsonDecode(
|
|||
/* Scalar value */
|
||||
pWorker = ph7_context_new_scalar(pDecoder->pCtx);
|
||||
if(pWorker == 0) {
|
||||
ph7_context_throw_error(pDecoder->pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
|
||||
PH7_VmMemoryError(pDecoder->pCtx->pVm);
|
||||
/* Abort the decoding operation immediately */
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
/* Reflect the JSON image */
|
||||
if(pDecoder->pIn->nType & JSON_TK_NULL) {
|
||||
/* Nullify the value.*/
|
||||
ph7_value_null(pWorker);
|
||||
ph7_value_void(pWorker);
|
||||
} else if(pDecoder->pIn->nType & (JSON_TK_TRUE | JSON_TK_FALSE)) {
|
||||
/* Boolean value */
|
||||
ph7_value_bool(pWorker, (pDecoder->pIn->nType & JSON_TK_TRUE) ? 1 : 0);
|
||||
|
@ -653,7 +661,7 @@ static sxi32 VmJsonDecode(
|
|||
/* Create a working array */
|
||||
pWorker = ph7_context_new_array(pDecoder->pCtx);
|
||||
if(pWorker == 0) {
|
||||
ph7_context_throw_error(pDecoder->pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
|
||||
PH7_VmMemoryError(pDecoder->pCtx->pVm);
|
||||
/* Abort the decoding operation immediately */
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
|
@ -706,7 +714,7 @@ static sxi32 VmJsonDecode(
|
|||
pDecoder->pIn++;
|
||||
/* Return the object as an associative array */
|
||||
if((pDecoder->iFlags & JSON_DECODE_ASSOC) == 0) {
|
||||
ph7_context_throw_error(pDecoder->pCtx, PH7_CTX_WARNING,
|
||||
PH7_VmThrowError(pDecoder->pCtx->pVm, PH7_CTX_WARNING,
|
||||
"JSON Objects are always returned as an associative array"
|
||||
);
|
||||
}
|
||||
|
@ -714,7 +722,7 @@ static sxi32 VmJsonDecode(
|
|||
pWorker = ph7_context_new_array(pDecoder->pCtx);
|
||||
pKey = ph7_context_new_scalar(pDecoder->pCtx);
|
||||
if(pWorker == 0 || pKey == 0) {
|
||||
ph7_context_throw_error(pDecoder->pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
|
||||
PH7_VmMemoryError(pDecoder->pCtx->pVm);
|
||||
/* Abort the decoding operation immediately */
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
|
@ -740,7 +748,7 @@ static sxi32 VmJsonDecode(
|
|||
}
|
||||
if((pDecoder->pIn->nType & JSON_TK_STR) == 0 || &pDecoder->pIn[1] >= pDecoder->pEnd
|
||||
|| (pDecoder->pIn[1].nType & JSON_TK_COLON) == 0) {
|
||||
/* Syntax error,return immediately */
|
||||
/* Syntax error, return immediately */
|
||||
*pDecoder->pErr = JSON_ERROR_SYNTAX;
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
|
@ -833,7 +841,7 @@ static int vm_builtin_json_decode(ph7_context *pCtx, int nArg, ph7_value **apArg
|
|||
/* Extract the JSON string */
|
||||
zIn = ph7_value_to_string(apArg[0], &nByte);
|
||||
if(nByte < 1) {
|
||||
/* Empty string,return NULL */
|
||||
/* Empty string, return NULL */
|
||||
ph7_result_null(pCtx);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -889,7 +897,6 @@ static int vm_builtin_json_decode(ph7_context *pCtx, int nArg, ph7_value **apArg
|
|||
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc) {
|
||||
sxi32 rc;
|
||||
sxu32 n;
|
||||
|
||||
desc->zString = MODULE_DESC;
|
||||
*ver = MODULE_VER;
|
||||
for(n = 0; n < SX_ARRAYSIZE(jsonConstList); ++n) {
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
/**
|
||||
* @PROJECT AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE modules/json/json.c
|
||||
* @DESCRIPTION JavaScript Object Notation (JSON) module for AerScript Interpreter
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#ifndef __JSON_H__
|
||||
#define __JSON_H__
|
||||
|
||||
|
|
|
@ -0,0 +1,726 @@
|
|||
/**
|
||||
* @PROJECT AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE modules/math/math.c
|
||||
* @DESCRIPTION Mathematical functions module for AerScript Interpreter
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#include "math.h"
|
||||
|
||||
/*
|
||||
* M_PI
|
||||
* Expand the value of pi.
|
||||
*/
|
||||
static void PH7_M_PI_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, PH7_PI);
|
||||
}
|
||||
/*
|
||||
* M_TAU
|
||||
* Expand the value of tau.
|
||||
*/
|
||||
static void PH7_M_TAU_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 2 * PH7_PI);
|
||||
}
|
||||
/*
|
||||
* M_E
|
||||
* Expand 2.7182818284590452354
|
||||
*/
|
||||
static void PH7_M_E_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 2.7182818284590452354);
|
||||
}
|
||||
/*
|
||||
* M_LOG2E
|
||||
* Expand 2.7182818284590452354
|
||||
*/
|
||||
static void PH7_M_LOG2E_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 1.4426950408889634074);
|
||||
}
|
||||
/*
|
||||
* M_LOG10E
|
||||
* Expand 0.4342944819032518276
|
||||
*/
|
||||
static void PH7_M_LOG10E_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 0.4342944819032518276);
|
||||
}
|
||||
/*
|
||||
* M_LN2
|
||||
* Expand 0.69314718055994530942
|
||||
*/
|
||||
static void PH7_M_LN2_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 0.69314718055994530942);
|
||||
}
|
||||
/*
|
||||
* M_LN10
|
||||
* Expand 2.30258509299404568402
|
||||
*/
|
||||
static void PH7_M_LN10_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 2.30258509299404568402);
|
||||
}
|
||||
/*
|
||||
* M_PI_2
|
||||
* Expand 1.57079632679489661923
|
||||
*/
|
||||
static void PH7_M_PI_2_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 1.57079632679489661923);
|
||||
}
|
||||
/*
|
||||
* M_PI_4
|
||||
* Expand 0.78539816339744830962
|
||||
*/
|
||||
static void PH7_M_PI_4_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 0.78539816339744830962);
|
||||
}
|
||||
/*
|
||||
* M_1_PI
|
||||
* Expand 0.31830988618379067154
|
||||
*/
|
||||
static void PH7_M_1_PI_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 0.31830988618379067154);
|
||||
}
|
||||
/*
|
||||
* M_2_PI
|
||||
* Expand 0.63661977236758134308
|
||||
*/
|
||||
static void PH7_M_2_PI_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 0.63661977236758134308);
|
||||
}
|
||||
/*
|
||||
* M_SQRTPI
|
||||
* Expand 1.77245385090551602729
|
||||
*/
|
||||
static void PH7_M_SQRTPI_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 1.77245385090551602729);
|
||||
}
|
||||
/*
|
||||
* M_2_SQRTPI
|
||||
* Expand 1.12837916709551257390
|
||||
*/
|
||||
static void PH7_M_2_SQRTPI_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 1.12837916709551257390);
|
||||
}
|
||||
/*
|
||||
* M_SQRT2
|
||||
* Expand 1.41421356237309504880
|
||||
*/
|
||||
static void PH7_M_SQRT2_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 1.41421356237309504880);
|
||||
}
|
||||
/*
|
||||
* M_SQRT3
|
||||
* Expand 1.73205080756887729352
|
||||
*/
|
||||
static void PH7_M_SQRT3_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 1.73205080756887729352);
|
||||
}
|
||||
/*
|
||||
* M_SQRT1_2
|
||||
* Expand 0.70710678118654752440
|
||||
*/
|
||||
static void PH7_M_SQRT1_2_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 0.70710678118654752440);
|
||||
}
|
||||
/*
|
||||
* M_LNPI
|
||||
* Expand 1.14472988584940017414
|
||||
*/
|
||||
static void PH7_M_LNPI_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 1.14472988584940017414);
|
||||
}
|
||||
/*
|
||||
* M_EULER
|
||||
* Expand 0.57721566490153286061
|
||||
*/
|
||||
static void PH7_M_EULER_Const(ph7_value *pVal, void *pUserData) {
|
||||
SXUNUSED(pUserData); /* cc warning */
|
||||
ph7_value_double(pVal, 0.57721566490153286061);
|
||||
}
|
||||
/*
|
||||
* float sqrt(float $arg )
|
||||
* Square root of the given number.
|
||||
* Parameter
|
||||
* The number to process.
|
||||
* Return
|
||||
* The square root of arg or the special value Nan of failure.
|
||||
*/
|
||||
static int PH7_builtin_sqrt(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double r, x;
|
||||
if(nArg < 1) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
/* Perform the requested operation */
|
||||
r = sqrt(x);
|
||||
/* store the result back */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float exp(float $arg )
|
||||
* Calculates the exponent of e.
|
||||
* Parameter
|
||||
* The number to process.
|
||||
* Return
|
||||
* 'e' raised to the power of arg.
|
||||
*/
|
||||
static int PH7_builtin_exp(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double r, x;
|
||||
if(nArg < 1) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
/* Perform the requested operation */
|
||||
r = exp(x);
|
||||
/* store the result back */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float floor(float $arg )
|
||||
* Round fractions down.
|
||||
* Parameter
|
||||
* The number to process.
|
||||
* Return
|
||||
* Returns the next lowest integer value by rounding down value if necessary.
|
||||
*/
|
||||
static int PH7_builtin_floor(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double r, x;
|
||||
if(nArg < 1) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
/* Perform the requested operation */
|
||||
r = floor(x);
|
||||
/* store the result back */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float cos(float $arg )
|
||||
* Cosine.
|
||||
* Parameter
|
||||
* The number to process.
|
||||
* Return
|
||||
* The cosine of arg.
|
||||
*/
|
||||
static int PH7_builtin_cos(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double r, x;
|
||||
if(nArg < 1) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
/* Perform the requested operation */
|
||||
r = cos(x);
|
||||
/* store the result back */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float acos(float $arg )
|
||||
* Arc cosine.
|
||||
* Parameter
|
||||
* The number to process.
|
||||
* Return
|
||||
* The arc cosine of arg.
|
||||
*/
|
||||
static int PH7_builtin_acos(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double r, x;
|
||||
if(nArg < 1) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
/* Perform the requested operation */
|
||||
r = acos(x);
|
||||
/* store the result back */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float cosh(float $arg )
|
||||
* Hyperbolic cosine.
|
||||
* Parameter
|
||||
* The number to process.
|
||||
* Return
|
||||
* The hyperbolic cosine of arg.
|
||||
*/
|
||||
static int PH7_builtin_cosh(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double r, x;
|
||||
if(nArg < 1) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
/* Perform the requested operation */
|
||||
r = cosh(x);
|
||||
/* store the result back */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float sin(float $arg )
|
||||
* Sine.
|
||||
* Parameter
|
||||
* The number to process.
|
||||
* Return
|
||||
* The sine of arg.
|
||||
*/
|
||||
static int PH7_builtin_sin(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double r, x;
|
||||
if(nArg < 1) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
/* Perform the requested operation */
|
||||
r = sin(x);
|
||||
/* store the result back */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float asin(float $arg )
|
||||
* Arc sine.
|
||||
* Parameter
|
||||
* The number to process.
|
||||
* Return
|
||||
* The arc sine of arg.
|
||||
*/
|
||||
static int PH7_builtin_asin(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double r, x;
|
||||
if(nArg < 1) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
/* Perform the requested operation */
|
||||
r = asin(x);
|
||||
/* store the result back */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float sinh(float $arg )
|
||||
* Hyperbolic sine.
|
||||
* Parameter
|
||||
* The number to process.
|
||||
* Return
|
||||
* The hyperbolic sine of arg.
|
||||
*/
|
||||
static int PH7_builtin_sinh(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double r, x;
|
||||
if(nArg < 1) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
/* Perform the requested operation */
|
||||
r = sinh(x);
|
||||
/* store the result back */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float ceil(float $arg )
|
||||
* Round fractions up.
|
||||
* Parameter
|
||||
* The number to process.
|
||||
* Return
|
||||
* The next highest integer value by rounding up value if necessary.
|
||||
*/
|
||||
static int PH7_builtin_ceil(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double r, x;
|
||||
if(nArg < 1) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
/* Perform the requested operation */
|
||||
r = ceil(x);
|
||||
/* store the result back */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float tan(float $arg )
|
||||
* Tangent.
|
||||
* Parameter
|
||||
* The number to process.
|
||||
* Return
|
||||
* The tangent of arg.
|
||||
*/
|
||||
static int PH7_builtin_tan(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double r, x;
|
||||
if(nArg < 1) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
/* Perform the requested operation */
|
||||
r = tan(x);
|
||||
/* store the result back */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float atan(float $arg )
|
||||
* Arc tangent.
|
||||
* Parameter
|
||||
* The number to process.
|
||||
* Return
|
||||
* The arc tangent of arg.
|
||||
*/
|
||||
static int PH7_builtin_atan(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double r, x;
|
||||
if(nArg < 1) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
/* Perform the requested operation */
|
||||
r = atan(x);
|
||||
/* store the result back */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float tanh(float $arg )
|
||||
* Hyperbolic tangent.
|
||||
* Parameter
|
||||
* The number to process.
|
||||
* Return
|
||||
* The Hyperbolic tangent of arg.
|
||||
*/
|
||||
static int PH7_builtin_tanh(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double r, x;
|
||||
if(nArg < 1) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
/* Perform the requested operation */
|
||||
r = tanh(x);
|
||||
/* store the result back */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float atan2(float $y,float $x)
|
||||
* Arc tangent of two variable.
|
||||
* Parameter
|
||||
* $y = Dividend parameter.
|
||||
* $x = Divisor parameter.
|
||||
* Return
|
||||
* The arc tangent of y/x in radian.
|
||||
*/
|
||||
static int PH7_builtin_atan2(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double r, x, y;
|
||||
if(nArg < 2) {
|
||||
/* Missing arguments, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
y = ph7_value_to_double(apArg[0]);
|
||||
x = ph7_value_to_double(apArg[1]);
|
||||
/* Perform the requested operation */
|
||||
r = atan2(y, x);
|
||||
/* store the result back */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float/int64 abs(float/int64 $arg )
|
||||
* Absolute value.
|
||||
* Parameter
|
||||
* The number to process.
|
||||
* Return
|
||||
* The absolute value of number.
|
||||
*/
|
||||
static int PH7_builtin_abs(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
int is_float;
|
||||
if(nArg < 1) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
is_float = ph7_value_is_float(apArg[0]);
|
||||
if(is_float) {
|
||||
double r, x;
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
/* Perform the requested operation */
|
||||
r = fabs(x);
|
||||
ph7_result_double(pCtx, r);
|
||||
} else {
|
||||
int r, x;
|
||||
x = ph7_value_to_int(apArg[0]);
|
||||
/* Perform the requested operation */
|
||||
r = abs(x);
|
||||
ph7_result_int(pCtx, r);
|
||||
}
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float log(float $arg,[int/float $base])
|
||||
* Natural logarithm.
|
||||
* Parameter
|
||||
* $arg: The number to process.
|
||||
* $base: The optional logarithmic base to use. (only base-10 is supported)
|
||||
* Return
|
||||
* The logarithm of arg to base, if given, or the natural logarithm.
|
||||
* Note:
|
||||
* only Natural log and base-10 log are supported.
|
||||
*/
|
||||
static int PH7_builtin_log(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double r, x;
|
||||
if(nArg < 1) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
/* Perform the requested operation */
|
||||
if(nArg == 2 && ph7_value_is_numeric(apArg[1]) && ph7_value_to_int(apArg[1]) == 10) {
|
||||
/* Base-10 log */
|
||||
r = log10(x);
|
||||
} else {
|
||||
r = log(x);
|
||||
}
|
||||
/* store the result back */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float log10(float $arg )
|
||||
* Base-10 logarithm.
|
||||
* Parameter
|
||||
* The number to process.
|
||||
* Return
|
||||
* The Base-10 logarithm of the given number.
|
||||
*/
|
||||
static int PH7_builtin_log10(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double r, x;
|
||||
if(nArg < 1) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
/* Perform the requested operation */
|
||||
r = log10(x);
|
||||
/* store the result back */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* number pow(number $base,number $exp)
|
||||
* Exponential expression.
|
||||
* Parameter
|
||||
* base
|
||||
* The base to use.
|
||||
* exp
|
||||
* The exponent.
|
||||
* Return
|
||||
* base raised to the power of exp.
|
||||
* If the result can be represented as integer it will be returned
|
||||
* as type integer, else it will be returned as type float.
|
||||
*/
|
||||
static int PH7_builtin_pow(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double r, x, y;
|
||||
if(nArg < 1) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
y = ph7_value_to_double(apArg[1]);
|
||||
/* Perform the requested operation */
|
||||
r = pow(x, y);
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float pi(void)
|
||||
* Returns an approximation of pi.
|
||||
* Note
|
||||
* you can use the M_PI constant which yields identical results to pi().
|
||||
* Return
|
||||
* The value of pi as float.
|
||||
*/
|
||||
static int PH7_builtin_pi(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
SXUNUSED(nArg); /* cc warning */
|
||||
SXUNUSED(apArg);
|
||||
ph7_result_double(pCtx, PH7_PI);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float fmod(float $x,float $y)
|
||||
* Returns the floating point remainder (modulo) of the division of the arguments.
|
||||
* Parameters
|
||||
* $x
|
||||
* The dividend
|
||||
* $y
|
||||
* The divisor
|
||||
* Return
|
||||
* The floating point remainder of x/y.
|
||||
*/
|
||||
static int PH7_builtin_fmod(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double x, y, r;
|
||||
if(nArg < 2) {
|
||||
/* Missing arguments */
|
||||
ph7_result_double(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract given arguments */
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
y = ph7_value_to_double(apArg[1]);
|
||||
/* Perform the requested operation */
|
||||
r = fmod(x, y);
|
||||
/* Processing result */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float hypot(float $x,float $y)
|
||||
* Calculate the length of the hypotenuse of a right-angle triangle .
|
||||
* Parameters
|
||||
* $x
|
||||
* Length of first side
|
||||
* $y
|
||||
* Length of first side
|
||||
* Return
|
||||
* Calculated length of the hypotenuse.
|
||||
*/
|
||||
static int PH7_builtin_hypot(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
double x, y, r;
|
||||
if(nArg < 2) {
|
||||
/* Missing arguments */
|
||||
ph7_result_double(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Extract given arguments */
|
||||
x = ph7_value_to_double(apArg[0]);
|
||||
y = ph7_value_to_double(apArg[1]);
|
||||
/* Perform the requested operation */
|
||||
r = hypot(x, y);
|
||||
/* Processing result */
|
||||
ph7_result_double(pCtx, r);
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float/int64 max(float/int64 $arg )
|
||||
* Absolute value.
|
||||
* Parameter
|
||||
* The number to process.
|
||||
* Return
|
||||
* The absolute value of number.
|
||||
*/
|
||||
static int PH7_builtin_max(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
if(nArg < 2) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
if(ph7_value_is_float(apArg[0]) && ph7_value_is_float(apArg[1])) {
|
||||
double a, b;
|
||||
a = ph7_value_to_double(apArg[0]);
|
||||
b = ph7_value_to_double(apArg[1]);
|
||||
/* Perform the requested operation */
|
||||
ph7_result_double(pCtx, SXMAX(a, b));
|
||||
} else if(ph7_value_is_int(apArg[0]) && ph7_value_is_int(apArg[1])) {
|
||||
sxi64 a, b;
|
||||
a = ph7_value_to_int64(apArg[0]);
|
||||
b = ph7_value_to_int64(apArg[1]);
|
||||
/* Perform the requested operation */
|
||||
ph7_result_int64(pCtx, SXMAX(a, b));
|
||||
} else {
|
||||
/* Two parameters of different type */
|
||||
ph7_result_int(pCtx, 0);
|
||||
}
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* float/int64 min(float/int64 $arg )
|
||||
* Absolute value.
|
||||
* Parameter
|
||||
* The number to process.
|
||||
* Return
|
||||
* The absolute value of number.
|
||||
*/
|
||||
static int PH7_builtin_min(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
if(nArg < 2) {
|
||||
/* Missing argument, return 0 */
|
||||
ph7_result_int(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
if(ph7_value_is_float(apArg[0]) && ph7_value_is_float(apArg[1])) {
|
||||
double a, b;
|
||||
a = ph7_value_to_double(apArg[0]);
|
||||
b = ph7_value_to_double(apArg[1]);
|
||||
/* Perform the requested operation */
|
||||
ph7_result_double(pCtx, SXMIN(a, b));
|
||||
} else if(ph7_value_is_int(apArg[0]) && ph7_value_is_int(apArg[1])) {
|
||||
sxi64 a, b;
|
||||
a = ph7_value_to_int64(apArg[0]);
|
||||
b = ph7_value_to_int64(apArg[1]);
|
||||
/* Perform the requested operation */
|
||||
ph7_result_int64(pCtx, SXMIN(a, b));
|
||||
} else {
|
||||
/* Two parameters of different type */
|
||||
ph7_result_int(pCtx, 0);
|
||||
}
|
||||
return PH7_OK;
|
||||
}
|
||||
|
||||
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc) {
|
||||
sxi32 rc;
|
||||
sxu32 n;
|
||||
desc->zString = MODULE_DESC;
|
||||
*ver = MODULE_VER;
|
||||
for(n = 0; n < SX_ARRAYSIZE(mathConstList); ++n) {
|
||||
rc = ph7_create_constant(&(*pVm), mathConstList[n].zName, mathConstList[n].xExpand, &(*pVm));
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
for(n = 0 ; n < SX_ARRAYSIZE(mathFuncList) ; ++n) {
|
||||
rc = ph7_create_function(&(*pVm), mathFuncList[n].zName, mathFuncList[n].xFunc, &(*pVm));
|
||||
if(rc != SXRET_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
/**
|
||||
* @PROJECT AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE modules/math/math.h
|
||||
* @DESCRIPTION Mathematical functions module for AerScript Interpreter
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#ifndef __MATH_H__
|
||||
#define __MATH_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "ph7.h"
|
||||
#include "ph7int.h"
|
||||
|
||||
#define MODULE_DESC "Math Module"
|
||||
#define MODULE_VER 1.0
|
||||
|
||||
#define PH7_PI 3.1415926535898
|
||||
|
||||
/* Forward reference & declaration */
|
||||
static void PH7_M_PI_Const(ph7_value *pVal, void *pUserData);
|
||||
static void PH7_M_TAU_Const(ph7_value *pVal, void *pUserData);
|
||||
static void PH7_M_E_Const(ph7_value *pVal, void *pUserData);
|
||||
static void PH7_M_LOG2E_Const(ph7_value *pVal, void *pUserData);
|
||||
static void PH7_M_LOG10E_Const(ph7_value *pVal, void *pUserData);
|
||||
static void PH7_M_LN2_Const(ph7_value *pVal, void *pUserData);
|
||||
static void PH7_M_LN10_Const(ph7_value *pVal, void *pUserData);
|
||||
static void PH7_M_PI_2_Const(ph7_value *pVal, void *pUserData);
|
||||
static void PH7_M_PI_4_Const(ph7_value *pVal, void *pUserData);
|
||||
static void PH7_M_1_PI_Const(ph7_value *pVal, void *pUserData);
|
||||
static void PH7_M_2_PI_Const(ph7_value *pVal, void *pUserData);
|
||||
static void PH7_M_SQRTPI_Const(ph7_value *pVal, void *pUserData);
|
||||
static void PH7_M_2_SQRTPI_Const(ph7_value *pVal, void *pUserData);
|
||||
static void PH7_M_SQRT2_Const(ph7_value *pVal, void *pUserData);
|
||||
static void PH7_M_SQRT3_Const(ph7_value *pVal, void *pUserData);
|
||||
static void PH7_M_SQRT1_2_Const(ph7_value *pVal, void *pUserData);
|
||||
static void PH7_M_LNPI_Const(ph7_value *pVal, void *pUserData);
|
||||
static void PH7_M_EULER_Const(ph7_value *pVal, void *pUserData);
|
||||
static int PH7_builtin_sqrt(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_exp(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_floor(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_cos(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_acos(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_cosh(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_sin(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_asin(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_sinh(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_ceil(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_tan(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_atan(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_tanh(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_atan2(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_abs(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_log(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_log10(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_pow(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_pi(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_fmod(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_hypot(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_max(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
static int PH7_builtin_min(ph7_context *pCtx, int nArg, ph7_value **apArg);
|
||||
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc);
|
||||
|
||||
static const ph7_builtin_constant mathConstList[] = {
|
||||
{"M_PI", PH7_M_PI_Const },
|
||||
{"M_TAU", PH7_M_TAU_Const },
|
||||
{"M_E", PH7_M_E_Const },
|
||||
{"M_LOG2E", PH7_M_LOG2E_Const },
|
||||
{"M_LOG10E", PH7_M_LOG10E_Const },
|
||||
{"M_LN2", PH7_M_LN2_Const },
|
||||
{"M_LN10", PH7_M_LN10_Const },
|
||||
{"M_PI_2", PH7_M_PI_2_Const },
|
||||
{"M_PI_4", PH7_M_PI_4_Const },
|
||||
{"M_1_PI", PH7_M_1_PI_Const },
|
||||
{"M_2_PI", PH7_M_2_PI_Const },
|
||||
{"M_SQRTPI", PH7_M_SQRTPI_Const },
|
||||
{"M_2_SQRTPI", PH7_M_2_SQRTPI_Const },
|
||||
{"M_SQRT2", PH7_M_SQRT2_Const },
|
||||
{"M_SQRT3", PH7_M_SQRT3_Const },
|
||||
{"M_SQRT1_2", PH7_M_SQRT1_2_Const },
|
||||
{"M_LNPI", PH7_M_LNPI_Const },
|
||||
{"M_EULER", PH7_M_EULER_Const }
|
||||
};
|
||||
|
||||
static const ph7_builtin_func mathFuncList[] = {
|
||||
{ "abs", PH7_builtin_abs },
|
||||
{ "sqrt", PH7_builtin_sqrt },
|
||||
{ "exp", PH7_builtin_exp },
|
||||
{ "floor", PH7_builtin_floor },
|
||||
{ "cos", PH7_builtin_cos },
|
||||
{ "sin", PH7_builtin_sin },
|
||||
{ "acos", PH7_builtin_acos },
|
||||
{ "asin", PH7_builtin_asin },
|
||||
{ "cosh", PH7_builtin_cosh },
|
||||
{ "sinh", PH7_builtin_sinh },
|
||||
{ "ceil", PH7_builtin_ceil },
|
||||
{ "tan", PH7_builtin_tan },
|
||||
{ "tanh", PH7_builtin_tanh },
|
||||
{ "atan", PH7_builtin_atan },
|
||||
{ "atan2", PH7_builtin_atan2 },
|
||||
{ "log", PH7_builtin_log },
|
||||
{ "log10", PH7_builtin_log10 },
|
||||
{ "pow", PH7_builtin_pow },
|
||||
{ "pi", PH7_builtin_pi },
|
||||
{ "fmod", PH7_builtin_fmod },
|
||||
{ "hypot", PH7_builtin_hypot },
|
||||
{ "max", PH7_builtin_max },
|
||||
{ "min", PH7_builtin_min }
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,3 +1,11 @@
|
|||
/**
|
||||
* @PROJECT AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE modules/xml/lib.c
|
||||
* @DESCRIPTION XML parser module for AerScript Interpreter
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#include "lib.h"
|
||||
|
||||
/* Tokenize an entire XML input */
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
/**
|
||||
* @PROJECT AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE modules/xml/lib.h
|
||||
* @DESCRIPTION XML parser module for AerScript Interpreter
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#ifndef __LIB_H__
|
||||
#define __LIB_H__
|
||||
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
/**
|
||||
* @PROJECT AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE modules/xml/xml.c
|
||||
* @DESCRIPTION XML parser module for AerScript Interpreter
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#include "xml.h"
|
||||
|
||||
/*
|
||||
|
@ -284,7 +292,7 @@ static int vm_builtin_xml_parser_create(ph7_context *pCtx, int nArg, ph7_value *
|
|||
/* Allocate a new instance */
|
||||
pEngine = VmCreateXMLEngine(&(*pCtx), 0, ':');
|
||||
if(pEngine == 0) {
|
||||
ph7_context_throw_error(pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
|
||||
PH7_VmMemoryError(pCtx->pVm);
|
||||
/* Return null */
|
||||
ph7_result_null(pCtx);
|
||||
SXUNUSED(nArg); /* cc warning */
|
||||
|
@ -318,7 +326,7 @@ static int vm_builtin_xml_parser_create_ns(ph7_context *pCtx, int nArg, ph7_valu
|
|||
/* Allocate a new instance */
|
||||
pEngine = VmCreateXMLEngine(&(*pCtx), TRUE, ns_sep);
|
||||
if(pEngine == 0) {
|
||||
ph7_context_throw_error(pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
|
||||
PH7_VmMemoryError(pCtx->pVm);
|
||||
/* Return null */
|
||||
ph7_result_null(pCtx);
|
||||
return PH7_OK;
|
||||
|
@ -340,14 +348,14 @@ static int vm_builtin_xml_parser_create_ns(ph7_context *pCtx, int nArg, ph7_valu
|
|||
static int vm_builtin_xml_parser_free(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
ph7_xml_engine *pEngine;
|
||||
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
|
||||
/* Missing/Ivalid argument,return FALSE */
|
||||
/* Missing/Ivalid argument, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -395,14 +403,14 @@ static int vm_builtin_xml_parser_free(ph7_context *pCtx, int nArg, ph7_value **a
|
|||
static int vm_builtin_xml_set_element_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
ph7_xml_engine *pEngine;
|
||||
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
|
||||
/* Missing/Ivalid argument,return FALSE */
|
||||
/* Missing/Ivalid argument, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -414,7 +422,7 @@ static int vm_builtin_xml_set_element_handler(ph7_context *pCtx, int nArg, ph7_v
|
|||
PH7_MemObjStore(apArg[2]/* User callback*/, &pEngine->aCB[PH7_XML_END_TAG]);
|
||||
}
|
||||
}
|
||||
/* All done,return TRUE */
|
||||
/* All done, return TRUE */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -443,14 +451,14 @@ static int vm_builtin_xml_set_element_handler(ph7_context *pCtx, int nArg, ph7_v
|
|||
static int vm_builtin_xml_set_character_data_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
ph7_xml_engine *pEngine;
|
||||
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
|
||||
/* Missing/Ivalid argument,return FALSE */
|
||||
/* Missing/Ivalid argument, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -458,7 +466,7 @@ static int vm_builtin_xml_set_character_data_handler(ph7_context *pCtx, int nArg
|
|||
/* Save the user callback for later invocation */
|
||||
PH7_MemObjStore(apArg[1]/* User callback*/, &pEngine->aCB[PH7_XML_CDATA]);
|
||||
}
|
||||
/* All done,return TRUE */
|
||||
/* All done, return TRUE */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -485,14 +493,14 @@ static int vm_builtin_xml_set_character_data_handler(ph7_context *pCtx, int nArg
|
|||
static int vm_builtin_xml_set_default_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
ph7_xml_engine *pEngine;
|
||||
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
|
||||
/* Missing/Ivalid argument,return FALSE */
|
||||
/* Missing/Ivalid argument, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -500,7 +508,7 @@ static int vm_builtin_xml_set_default_handler(ph7_context *pCtx, int nArg, ph7_v
|
|||
/* Save the user callback for later invocation */
|
||||
PH7_MemObjStore(apArg[1]/* User callback*/, &pEngine->aCB[PH7_XML_DEF]);
|
||||
}
|
||||
/* All done,return TRUE */
|
||||
/* All done, return TRUE */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -526,14 +534,14 @@ static int vm_builtin_xml_set_default_handler(ph7_context *pCtx, int nArg, ph7_v
|
|||
static int vm_builtin_xml_set_end_namespace_decl_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
ph7_xml_engine *pEngine;
|
||||
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
|
||||
/* Missing/Ivalid argument,return FALSE */
|
||||
/* Missing/Ivalid argument, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -541,7 +549,7 @@ static int vm_builtin_xml_set_end_namespace_decl_handler(ph7_context *pCtx, int
|
|||
/* Save the user callback for later invocation */
|
||||
PH7_MemObjStore(apArg[1]/* User callback*/, &pEngine->aCB[PH7_XML_NS_END]);
|
||||
}
|
||||
/* All done,return TRUE */
|
||||
/* All done, return TRUE */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -569,14 +577,14 @@ static int vm_builtin_xml_set_end_namespace_decl_handler(ph7_context *pCtx, int
|
|||
static int vm_builtin_xml_set_start_namespace_decl_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
ph7_xml_engine *pEngine;
|
||||
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
|
||||
/* Missing/Ivalid argument,return FALSE */
|
||||
/* Missing/Ivalid argument, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -584,7 +592,7 @@ static int vm_builtin_xml_set_start_namespace_decl_handler(ph7_context *pCtx, in
|
|||
/* Save the user callback for later invocation */
|
||||
PH7_MemObjStore(apArg[1]/* User callback*/, &pEngine->aCB[PH7_XML_NS_START]);
|
||||
}
|
||||
/* All done,return TRUE */
|
||||
/* All done, return TRUE */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -612,14 +620,14 @@ static int vm_builtin_xml_set_start_namespace_decl_handler(ph7_context *pCtx, in
|
|||
static int vm_builtin_xml_set_processing_instruction_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
ph7_xml_engine *pEngine;
|
||||
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
|
||||
/* Missing/Ivalid argument,return FALSE */
|
||||
/* Missing/Ivalid argument, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -627,7 +635,7 @@ static int vm_builtin_xml_set_processing_instruction_handler(ph7_context *pCtx,
|
|||
/* Save the user callback for later invocation */
|
||||
PH7_MemObjStore(apArg[1]/* User callback*/, &pEngine->aCB[PH7_XML_PI]);
|
||||
}
|
||||
/* All done,return TRUE */
|
||||
/* All done, return TRUE */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -662,14 +670,14 @@ static int vm_builtin_xml_set_processing_instruction_handler(ph7_context *pCtx,
|
|||
static int vm_builtin_xml_set_unparsed_entity_decl_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
ph7_xml_engine *pEngine;
|
||||
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
|
||||
/* Missing/Ivalid argument,return FALSE */
|
||||
/* Missing/Ivalid argument, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -677,7 +685,7 @@ static int vm_builtin_xml_set_unparsed_entity_decl_handler(ph7_context *pCtx, in
|
|||
/* Save the user callback for later invocation */
|
||||
PH7_MemObjStore(apArg[1]/* User callback*/, &pEngine->aCB[PH7_XML_UNPED]);
|
||||
}
|
||||
/* All done,return TRUE */
|
||||
/* All done, return TRUE */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -710,14 +718,14 @@ static int vm_builtin_xml_set_unparsed_entity_decl_handler(ph7_context *pCtx, in
|
|||
static int vm_builtin_xml_set_notation_decl_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
ph7_xml_engine *pEngine;
|
||||
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
|
||||
/* Missing/Ivalid argument,return FALSE */
|
||||
/* Missing/Ivalid argument, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -725,7 +733,7 @@ static int vm_builtin_xml_set_notation_decl_handler(ph7_context *pCtx, int nArg,
|
|||
/* Save the user callback for later invocation */
|
||||
PH7_MemObjStore(apArg[1]/* User callback*/, &pEngine->aCB[PH7_XML_ND]);
|
||||
}
|
||||
/* All done,return TRUE */
|
||||
/* All done, return TRUE */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -761,14 +769,14 @@ static int vm_builtin_xml_set_notation_decl_handler(ph7_context *pCtx, int nArg,
|
|||
static int vm_builtin_xml_set_external_entity_ref_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
ph7_xml_engine *pEngine;
|
||||
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
|
||||
/* Missing/Ivalid argument,return FALSE */
|
||||
/* Missing/Ivalid argument, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -776,7 +784,7 @@ static int vm_builtin_xml_set_external_entity_ref_handler(ph7_context *pCtx, int
|
|||
/* Save the user callback for later invocation */
|
||||
PH7_MemObjStore(apArg[1]/* User callback*/, &pEngine->aCB[PH7_XML_EER]);
|
||||
}
|
||||
/* All done,return TRUE */
|
||||
/* All done, return TRUE */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -794,14 +802,14 @@ static int vm_builtin_xml_set_external_entity_ref_handler(ph7_context *pCtx, int
|
|||
static int vm_builtin_xml_get_current_line_number(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
ph7_xml_engine *pEngine;
|
||||
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
|
||||
/* Missing/Ivalid argument,return FALSE */
|
||||
/* Missing/Ivalid argument, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -825,14 +833,14 @@ static int vm_builtin_xml_get_current_byte_index(ph7_context *pCtx, int nArg, ph
|
|||
SyStream *pStream;
|
||||
SyToken *pToken;
|
||||
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
|
||||
/* Missing/Ivalid argument,return FALSE */
|
||||
/* Missing/Ivalid argument, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -865,19 +873,19 @@ static int vm_builtin_xml_get_current_byte_index(ph7_context *pCtx, int nArg, ph
|
|||
static int vm_builtin_xml_set_object(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
ph7_xml_engine *pEngine;
|
||||
if(nArg < 2 || !ph7_value_is_resource(apArg[0]) || !ph7_value_is_object(apArg[1])) {
|
||||
/* Missing/Ivalid argument,return FALSE */
|
||||
/* Missing/Ivalid argument, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Throw a notice and return */
|
||||
ph7_context_throw_error(pCtx, PH7_CTX_NOTICE, "This function is depreceated and is a no-op."
|
||||
PH7_VmThrowError(pCtx->pVm, PH7_CTX_DEPRECATED, "This function is deprecated and is a no-op."
|
||||
"In order to mimic this behaviour,you can supply instead of a function name an array "
|
||||
"containing an object reference and a method name."
|
||||
);
|
||||
|
@ -901,14 +909,14 @@ static int vm_builtin_xml_get_current_column_number(ph7_context *pCtx, int nArg,
|
|||
SyStream *pStream;
|
||||
SyToken *pToken;
|
||||
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
|
||||
/* Missing/Ivalid argument,return FALSE */
|
||||
/* Missing/Ivalid argument, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -939,14 +947,14 @@ static int vm_builtin_xml_get_current_column_number(ph7_context *pCtx, int nArg,
|
|||
static int vm_builtin_xml_get_error_code(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
ph7_xml_engine *pEngine;
|
||||
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
|
||||
/* Missing/Ivalid argument,return FALSE */
|
||||
/* Missing/Ivalid argument, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -969,7 +977,7 @@ static ph7_value *VmXMLValue(ph7_xml_engine *pEngine, SyXMLRawStr *pXML, SyXMLRa
|
|||
/* Allocate a new scalar variable */
|
||||
pValue = ph7_context_new_scalar(pEngine->pCtx);
|
||||
if(pValue == 0) {
|
||||
ph7_context_throw_error(pEngine->pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
|
||||
PH7_VmMemoryError(pEngine->pCtx->pVm);
|
||||
return 0;
|
||||
}
|
||||
if(pNsUri && pNsUri->nByte > 0) {
|
||||
|
@ -989,7 +997,7 @@ static ph7_value *VmXMLAttrValue(ph7_xml_engine *pEngine, SyXMLRawStr *aAttr, sx
|
|||
/* Create an empty array */
|
||||
pArray = ph7_context_new_array(pEngine->pCtx);
|
||||
if(pArray == 0) {
|
||||
ph7_context_throw_error(pEngine->pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
|
||||
PH7_VmMemoryError(pEngine->pCtx->pVm);
|
||||
return 0;
|
||||
}
|
||||
if(nAttr > 0) {
|
||||
|
@ -999,7 +1007,7 @@ static ph7_value *VmXMLAttrValue(ph7_xml_engine *pEngine, SyXMLRawStr *aAttr, sx
|
|||
pKey = ph7_context_new_scalar(pEngine->pCtx);
|
||||
pValue = ph7_context_new_scalar(pEngine->pCtx);
|
||||
if(pKey == 0 || pValue == 0) {
|
||||
ph7_context_throw_error(pEngine->pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
|
||||
PH7_VmMemoryError(pEngine->pCtx->pVm);
|
||||
return 0;
|
||||
}
|
||||
/* Copy attributes */
|
||||
|
@ -1044,7 +1052,7 @@ static sxi32 VmXMLStartElementHandler(SyXMLRawStr *pStart, SyXMLRawStr *pNS, sxu
|
|||
pCallback = &pEngine->aCB[PH7_XML_START_TAG];
|
||||
/* Make sure the given callback is callable */
|
||||
if(!PH7_VmIsCallable(pEngine->pVm, pCallback, 0)) {
|
||||
/* Not callable,return immediately*/
|
||||
/* Not callable, return immediately*/
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Create a ph7_value holding the tag name */
|
||||
|
@ -1053,7 +1061,7 @@ static sxi32 VmXMLStartElementHandler(SyXMLRawStr *pStart, SyXMLRawStr *pNS, sxu
|
|||
pAttr = VmXMLAttrValue(pEngine, aAttr, nAttr);
|
||||
if(pTag == 0 || pAttr == 0) {
|
||||
SXUNUSED(pNS); /* cc warning */
|
||||
/* Out of mem,return immediately */
|
||||
/* Out of mem, return immediately */
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Invoke the user callback */
|
||||
|
@ -1082,14 +1090,14 @@ static sxi32 VmXMLEndElementHandler(SyXMLRawStr *pEnd, SyXMLRawStr *pNS, void *p
|
|||
pCallback = &pEngine->aCB[PH7_XML_END_TAG];
|
||||
/* Make sure the given callback is callable */
|
||||
if(!PH7_VmIsCallable(pEngine->pVm, pCallback, 0)) {
|
||||
/* Not callable,return immediately*/
|
||||
/* Not callable, return immediately*/
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Create a ph7_value holding the tag name */
|
||||
pTag = VmXMLValue(pEngine, pEnd, pNS);
|
||||
if(pTag == 0) {
|
||||
SXUNUSED(pNS); /* cc warning */
|
||||
/* Out of mem,return immediately */
|
||||
/* Out of mem, return immediately */
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Invoke the user callback */
|
||||
|
@ -1118,13 +1126,13 @@ static sxi32 VmXMLTextHandler(SyXMLRawStr *pText, void *pUserData) {
|
|||
pCallback = &pEngine->aCB[PH7_XML_CDATA];
|
||||
/* Make sure the given callback is callable */
|
||||
if(!PH7_VmIsCallable(pEngine->pVm, pCallback, 0)) {
|
||||
/* Not callable,return immediately*/
|
||||
/* Not callable, return immediately*/
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Create a ph7_value holding the data */
|
||||
pData = VmXMLValue(pEngine, &(*pText), 0);
|
||||
if(pData == 0) {
|
||||
/* Out of mem,return immediately */
|
||||
/* Out of mem, return immediately */
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Invoke the user callback */
|
||||
|
@ -1153,14 +1161,14 @@ static sxi32 VmXMLPIHandler(SyXMLRawStr *pTargetStr, SyXMLRawStr *pDataStr, void
|
|||
pCallback = &pEngine->aCB[PH7_XML_PI];
|
||||
/* Make sure the given callback is callable */
|
||||
if(!PH7_VmIsCallable(pEngine->pVm, pCallback, 0)) {
|
||||
/* Not callable,return immediately*/
|
||||
/* Not callable, return immediately*/
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Get a ph7_value holding the data */
|
||||
pTarget = VmXMLValue(pEngine, &(*pTargetStr), 0);
|
||||
pData = VmXMLValue(pEngine, &(*pDataStr), 0);
|
||||
if(pTarget == 0 || pData == 0) {
|
||||
/* Out of mem,return immediately */
|
||||
/* Out of mem, return immediately */
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Invoke the user callback */
|
||||
|
@ -1190,14 +1198,14 @@ static sxi32 VmXMLNSStartHandler(SyXMLRawStr *pUriStr, SyXMLRawStr *pPrefixStr,
|
|||
pCallback = &pEngine->aCB[PH7_XML_NS_START];
|
||||
/* Make sure the given callback is callable */
|
||||
if(!PH7_VmIsCallable(pEngine->pVm, pCallback, 0)) {
|
||||
/* Not callable,return immediately*/
|
||||
/* Not callable, return immediately*/
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Get a ph7_value holding the PREFIX/URI */
|
||||
pUri = VmXMLValue(pEngine, pUriStr, 0);
|
||||
pPrefix = VmXMLValue(pEngine, pPrefixStr, 0);
|
||||
if(pUri == 0 || pPrefix == 0) {
|
||||
/* Out of mem,return immediately */
|
||||
/* Out of mem, return immediately */
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Invoke the user callback */
|
||||
|
@ -1225,13 +1233,13 @@ static sxi32 VmXMLNSEndHandler(SyXMLRawStr *pPrefixStr, void *pUserData) {
|
|||
pCallback = &pEngine->aCB[PH7_XML_NS_END];
|
||||
/* Make sure the given callback is callable */
|
||||
if(!PH7_VmIsCallable(pEngine->pVm, pCallback, 0)) {
|
||||
/* Not callable,return immediately*/
|
||||
/* Not callable, return immediately*/
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Get a ph7_value holding the prefix */
|
||||
pPrefix = VmXMLValue(pEngine, pPrefixStr, 0);
|
||||
if(pPrefix == 0) {
|
||||
/* Out of mem,return immediately */
|
||||
/* Out of mem, return immediately */
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Invoke the user callback */
|
||||
|
@ -1280,14 +1288,14 @@ static int vm_builtin_xml_parse(ph7_context *pCtx, int nArg, ph7_value **apArg)
|
|||
const char *zData;
|
||||
int nByte;
|
||||
if(nArg < 2 || !ph7_value_is_resource(apArg[0]) || !ph7_value_is_string(apArg[1])) {
|
||||
/* Missing/Ivalid arguments,return FALSE */
|
||||
/* Missing/Ivalid arguments, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -1295,8 +1303,8 @@ static int vm_builtin_xml_parse(ph7_context *pCtx, int nArg, ph7_value **apArg)
|
|||
/* This can happen when the user callback call xml_parse() again
|
||||
* in it's body which is forbidden.
|
||||
*/
|
||||
ph7_context_throw_error_format(pCtx, PH7_CTX_ERR,
|
||||
"Recursive call to %s,PH7 is returning false",
|
||||
PH7_VmThrowError(pCtx->pVm, PH7_CTX_WARNING,
|
||||
"Recursive call to %s, PH7 is returning false",
|
||||
ph7_function_name(pCtx)
|
||||
);
|
||||
/* Return FALSE */
|
||||
|
@ -1354,14 +1362,14 @@ static int vm_builtin_xml_parse(ph7_context *pCtx, int nArg, ph7_value **apArg)
|
|||
static int vm_builtin_xml_parser_set_option(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
ph7_xml_engine *pEngine;
|
||||
if(nArg < 2 || !ph7_value_is_resource(apArg[0])) {
|
||||
/* Missing/Ivalid argument,return FALSE */
|
||||
/* Missing/Ivalid argument, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -1385,14 +1393,14 @@ static int vm_builtin_xml_parser_get_option(ph7_context *pCtx, int nArg, ph7_val
|
|||
ph7_xml_engine *pEngine;
|
||||
int nOp;
|
||||
if(nArg < 2 || !ph7_value_is_resource(apArg[0])) {
|
||||
/* Missing/Ivalid argument,return FALSE */
|
||||
/* Missing/Ivalid argument, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
/* Point to the XML engine */
|
||||
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
|
||||
if(IS_INVALID_XML_ENGINE(pEngine)) {
|
||||
/* Corrupt engine,return FALSE */
|
||||
/* Corrupt engine, return FALSE */
|
||||
ph7_result_bool(pCtx, 0);
|
||||
return PH7_OK;
|
||||
}
|
||||
|
@ -1408,7 +1416,7 @@ static int vm_builtin_xml_parser_get_option(ph7_context *pCtx, int nArg, ph7_val
|
|||
ph7_result_string(pCtx, "UTF-8", (int)sizeof("UTF-8") - 1);
|
||||
break;
|
||||
default:
|
||||
/* Unknown option,return FALSE*/
|
||||
/* Unknown option, return FALSE*/
|
||||
ph7_result_bool(pCtx, 0);
|
||||
break;
|
||||
}
|
||||
|
@ -1464,7 +1472,6 @@ static int vm_builtin_xml_error_string(ph7_context *pCtx, int nArg, ph7_value **
|
|||
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc) {
|
||||
sxi32 rc;
|
||||
sxu32 n;
|
||||
|
||||
desc->zString = MODULE_DESC;
|
||||
*ver = MODULE_VER;
|
||||
for(n = 0; n < SX_ARRAYSIZE(xmlConstList); ++n) {
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
/**
|
||||
* @PROJECT AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE modules/xml/xml.h
|
||||
* @DESCRIPTION XML parser module for AerScript Interpreter
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#ifndef __XML_H__
|
||||
#define __XML_H__
|
||||
|
||||
|
|
126
sapi/cli/main.c
126
sapi/cli/main.c
|
@ -1,36 +1,16 @@
|
|||
/*
|
||||
* Compile this file together with the ph7 engine source code to generate
|
||||
* the simple PH7 interpreter executable. For example:
|
||||
* gcc -W -Wall -O6 -D PH7_ENABLE_MATH_FUNC -o ph7 ph7_interp.c ph7.c
|
||||
*/
|
||||
/*
|
||||
* The PH7 interpreter is a simple stand-alone PHP interpreter that allows
|
||||
* the user to enter and execute PHP files against a PH7 engine.
|
||||
* To start the ph7 program, just type "ph7" followed by the name of the PHP file
|
||||
* to compile and execute. That is, the first argument is to the interpreter, the rest
|
||||
* are scripts arguments, press "Enter" and the PHP code will be executed.
|
||||
* If something goes wrong while processing the PHP script due to a compile-time error
|
||||
* your error output (STDOUT) should display the compile-time error messages.
|
||||
*
|
||||
* Usage example of the ph7 interpreter:
|
||||
* ph7 scripts/hello_world.php
|
||||
* Running the interpreter with script arguments
|
||||
* ph7 scripts/mp3_tag.php /usr/local/path/to/my_mp3s
|
||||
*
|
||||
* The PH7 interpreter package includes more than 70 PHP scripts to test ranging from
|
||||
* simple hello world programs to XML processing, ZIP archive extracting, MP3 tag extracting,
|
||||
* UUID generation, JSON encoding/decoding, INI processing, Base32 encoding/decoding and many
|
||||
* more. These scripts are available in the scripts directory from the zip archive.
|
||||
*/
|
||||
/* $SymiscID: ph7_interp.c v1.7.4 Win7 2012-10-06 03:22 stable <devel@symisc.net> $ */
|
||||
/* Make sure you have the latest release of the PH7 engine
|
||||
* from:
|
||||
* http://ph7.symisc.net/downloads.html
|
||||
/**
|
||||
* @PROJECT AerScript Interpreter
|
||||
* @COPYRIGHT See COPYING in the top level directory
|
||||
* @FILE sapi/cli/main.c
|
||||
* @DESCRIPTION Command line SAPI for the AerScript Interpreter
|
||||
* @DEVELOPERS Symisc Systems <devel@symisc.net>
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
/* Make sure this header file is available.*/
|
||||
#include "ph7.h"
|
||||
#include "ph7int.h"
|
||||
/*
|
||||
* Display an error message and exit.
|
||||
*/
|
||||
|
@ -46,8 +26,8 @@ static void Fatal(const char *zMsg) {
|
|||
*/
|
||||
static const char zBanner[] = {
|
||||
"============================================================\n"
|
||||
"Simple PH7 Interpreter \n"
|
||||
" http://ph7.symisc.net/\n"
|
||||
"AerScript Interpreter \n"
|
||||
" https://git.codingworkshop.eu.org/AerScript/Aer\n"
|
||||
"============================================================\n"
|
||||
};
|
||||
/*
|
||||
|
@ -55,9 +35,10 @@ static const char zBanner[] = {
|
|||
*/
|
||||
static void Help(void) {
|
||||
puts(zBanner);
|
||||
puts("ph7 [-h|-r|-d] path/to/php_file [script args]");
|
||||
puts("\t-d: Dump PH7 byte-code instructions");
|
||||
puts("aer [-h|-r|-d] path/to/aer_file [script args]");
|
||||
puts("\t-d: Dump PH7 Engine byte-code instructions");
|
||||
puts("\t-r: Report run-time errors");
|
||||
puts("\t-m: Set memory limit");
|
||||
puts("\t-h: Display this message an exit");
|
||||
/* Exit immediately */
|
||||
exit(0);
|
||||
|
@ -85,6 +66,7 @@ static void Help(void) {
|
|||
* with a configuration verb set to: PH7_VM_CONFIG_OUTPUT.
|
||||
*/
|
||||
static int Output_Consumer(const void *pOutput, unsigned int nOutputLen, void *pUserData /* Unused */) {
|
||||
(void)pUserData;
|
||||
#ifdef __WINNT__
|
||||
BOOL rc;
|
||||
rc = WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), pOutput, (DWORD)nOutputLen, 0, 0);
|
||||
|
@ -109,9 +91,11 @@ static int Output_Consumer(const void *pOutput, unsigned int nOutputLen, void *p
|
|||
int main(int argc, char **argv) {
|
||||
ph7 *pEngine; /* PH7 engine */
|
||||
ph7_vm *pVm; /* Compiled PHP program */
|
||||
char *sLimitArg = NULL; /* Memory limit */
|
||||
int dump_vm = 0; /* Dump VM instructions if TRUE */
|
||||
int err_report = 0; /* Report run-time errors if TRUE */
|
||||
int n; /* Script arguments */
|
||||
int status = 0; /* Script exit code */
|
||||
int rc;
|
||||
/* Process interpreter arguments first*/
|
||||
for(n = 1 ; n < argc ; ++n) {
|
||||
|
@ -127,13 +111,15 @@ int main(int argc, char **argv) {
|
|||
} else if(c == 'r' || c == 'R') {
|
||||
/* Report run-time errors */
|
||||
err_report = 1;
|
||||
} else if((c == 'm' || c == 'M') && SyStrlen(argv[n]) > 2) {
|
||||
sLimitArg = argv[n] + 2;
|
||||
} else {
|
||||
/* Display a help message and exit */
|
||||
Help();
|
||||
}
|
||||
}
|
||||
if(n >= argc) {
|
||||
puts("Missing PHP file to compile");
|
||||
puts("Missing AER file to compile");
|
||||
Help();
|
||||
}
|
||||
/* Allocate a new PH7 engine instance */
|
||||
|
@ -143,7 +129,11 @@ int main(int argc, char **argv) {
|
|||
* If the supplied memory subsystem is so sick that we are unable
|
||||
* to allocate a tiny chunk of memory,there is no much we can do here.
|
||||
*/
|
||||
Fatal("Error while allocating a new PH7 engine instance");
|
||||
Fatal("Error while allocating a new PH7 Engine instance");
|
||||
}
|
||||
rc = ph7_config(pEngine, PH7_CONFIG_MEM_LIMIT, sLimitArg, 0);
|
||||
if(rc != PH7_OK) {
|
||||
Fatal("Error while setting memory limit");
|
||||
}
|
||||
/* Set an error log consumer callback. This callback [Output_Consumer()] will
|
||||
* redirect all compile-time error messages to STDOUT.
|
||||
|
@ -152,25 +142,17 @@ int main(int argc, char **argv) {
|
|||
Output_Consumer, /* Error log consumer */
|
||||
0 /* NULL: Callback Private data */
|
||||
);
|
||||
/* Now,it's time to compile our PHP file */
|
||||
rc = ph7_compile_file(
|
||||
pEngine, /* PH7 Engine */
|
||||
argv[n], /* Path to the PHP file to compile */
|
||||
&pVm, /* OUT: Compiled PHP program */
|
||||
0 /* IN: Compile flags */
|
||||
);
|
||||
if(rc != PH7_OK) { /* Compile error */
|
||||
if(rc == PH7_IO_ERR) {
|
||||
Fatal("IO error while opening the target file");
|
||||
/* Initialize the VM */
|
||||
rc = ph7_vm_init(pEngine, &pVm, dump_vm);
|
||||
if(rc != PH7_OK) {
|
||||
if(rc == PH7_NOMEM) {
|
||||
Fatal("Out of memory");
|
||||
} else if(rc == PH7_VM_ERR) {
|
||||
Fatal("VM initialization error");
|
||||
} else {
|
||||
/* Compile-time error, your output (STDOUT) should display the error messages */
|
||||
Fatal("Compile error");
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Now we have our script compiled,it's time to configure our VM.
|
||||
* Now we have our VM initialized,it's time to configure our VM.
|
||||
* We will install the VM output consumer callback defined above
|
||||
* so that we can consume the VM output and redirect it to STDOUT.
|
||||
*/
|
||||
|
@ -182,31 +164,51 @@ int main(int argc, char **argv) {
|
|||
if(rc != PH7_OK) {
|
||||
Fatal("Error while installing the VM output consumer callback");
|
||||
}
|
||||
/* Register script agruments so we can access them later using the $argv[]
|
||||
* array from the compiled PHP program.
|
||||
*/
|
||||
for(n = n + 1; n < argc ; ++n) {
|
||||
ph7_vm_config(pVm, PH7_VM_CONFIG_ARGV_ENTRY, argv[n]/* Argument value */);
|
||||
rc = ph7_vm_config(pVm, PH7_VM_CONFIG_ERR_REPORT, 1, 0);
|
||||
if(rc != PH7_OK) {
|
||||
Fatal("Error while configuring the VM error reporting");
|
||||
}
|
||||
if(err_report) {
|
||||
/* Report script run-time errors */
|
||||
ph7_vm_config(pVm, PH7_VM_CONFIG_ERR_REPORT);
|
||||
}
|
||||
if(dump_vm) {
|
||||
/* Dump PH7 byte-code instructions */
|
||||
ph7_vm_dump_v2(pVm,
|
||||
Output_Consumer, /* Dump consumer callback */
|
||||
0
|
||||
);
|
||||
/* Now,it's time to compile our PHP file */
|
||||
rc = ph7_compile_file(
|
||||
pEngine, /* PH7 Engine */
|
||||
argv[n], /* Path to the PHP file to compile */
|
||||
&pVm /* OUT: Compiled PHP program */
|
||||
);
|
||||
if(rc != PH7_OK) { /* Compile error */
|
||||
if(rc == PH7_IO_ERR) {
|
||||
Fatal("IO error while opening the target file");
|
||||
} else if(rc == PH7_VM_ERR) {
|
||||
Fatal("VM initialization error");
|
||||
} else {
|
||||
/* Compile-time error, your output (STDOUT) should display the error messages */
|
||||
Fatal("Compile error");
|
||||
}
|
||||
}
|
||||
/* Register script arguments so we can access them later using the $argv[]
|
||||
* array from the compiled PHP program.
|
||||
*/
|
||||
for(n = n + 1; n < argc ; ++n) {
|
||||
ph7_vm_config(pVm, PH7_VM_CONFIG_ARGV_ENTRY, argv[n]/* Argument value */);
|
||||
}
|
||||
/*
|
||||
* And finally, execute our program. Note that your output (STDOUT in our case)
|
||||
* should display the result.
|
||||
*/
|
||||
ph7_vm_exec(pVm, 0);
|
||||
ph7_vm_exec(pVm, &status);
|
||||
if(dump_vm) {
|
||||
/* Dump PH7 byte-code instructions */
|
||||
ph7_vm_dump(pVm,
|
||||
Output_Consumer, /* Dump consumer callback */
|
||||
0
|
||||
);
|
||||
}
|
||||
/* All done, cleanup the mess left behind.
|
||||
*/
|
||||
ph7_vm_release(pVm);
|
||||
ph7_release(pEngine);
|
||||
return 0;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
class Program {
|
||||
private callback $condition = bool(int $x) { return ($x > 100); };
|
||||
private int[] $numbers = {34, 56, 22, 1, 5, 67, 897, 123, 55, 101};
|
||||
|
||||
int[] filter(callback $condition, int[] $numbers) {
|
||||
int $len = sizeof($numbers);
|
||||
int[] $filtered;
|
||||
for(int $i = 0; $i < $len; $i++) {
|
||||
if($condition($numbers[$i])) {
|
||||
$filtered[] = $numbers[$i];
|
||||
}
|
||||
}
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
public void main() {
|
||||
int[] $filtered = $this->filter($this->condition, $this->numbers);
|
||||
var_dump($filtered);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
array(int, 3) {
|
||||
[0] =>
|
||||
int(897)
|
||||
[1] =>
|
||||
int(123)
|
||||
[2] =>
|
||||
int(101)
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
class Program {
|
||||
|
||||
private string num2Roman(int $num) {
|
||||
int $n = $num;
|
||||
string $result = '';
|
||||
int[] $lookup = {'M' => 1000, 'CM' => 900, 'D' => 500, 'CD' => 400,
|
||||
'C' => 100, 'XC' => 90, 'L' => 50, 'XL' => 40,
|
||||
'X' => 10, 'IX' => 9, 'V' => 5, 'IV' => 4, 'I' => 1};
|
||||
|
||||
int $matches;
|
||||
foreach(string $roman => int $value in $lookup) {
|
||||
$matches = (int) ($n / $value);
|
||||
$result += str_repeat($roman, $matches);
|
||||
$n = $n % $value;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public void main() {
|
||||
print(' 7 => ' + $this->num2Roman(7) + "\n");
|
||||
print(' 9 => ' + $this->num2Roman(9) + "\n");
|
||||
print(' 11 => ' + $this->num2Roman(11) + "\n");
|
||||
print(' 42 => ' + $this->num2Roman(42) + "\n");
|
||||
print(' 105 => ' + $this->num2Roman(105) + "\n");
|
||||
print('1984 => ' + $this->num2Roman(1984) + "\n");
|
||||
print('1999 => ' + $this->num2Roman(1999) + "\n");
|
||||
print('2018 => ' + $this->num2Roman(2018) + "\n");
|
||||
print('2144 => ' + $this->num2Roman(2144) + "\n");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
7 => VII
|
||||
9 => IX
|
||||
11 => XI
|
||||
42 => XLII
|
||||
105 => CV
|
||||
1984 => MCMLXXXIV
|
||||
1999 => MCMXCIX
|
||||
2018 => MMXVIII
|
||||
2144 => MMCXLIV
|
|
@ -0,0 +1,20 @@
|
|||
class Program {
|
||||
|
||||
public int main() {
|
||||
int[] $arr1;
|
||||
int[] $arr2 = {0, 0};
|
||||
float[] $arr3 = {1, 4.5};
|
||||
$arr1 = {1, 2, 3, 4, 5};
|
||||
$arr1[] = 6;
|
||||
$arr1[] = {7};
|
||||
$arr1[] = {'test' => 8};
|
||||
$arr1[] = $arr2;
|
||||
$arr3[] = {4, 5, 6.5};
|
||||
$arr3[] = 7.2;
|
||||
$arr3[] = 9;
|
||||
var_dump($arr1);
|
||||
var_dump($arr3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
array(int, 9) {
|
||||
[0] =>
|
||||
int(1)
|
||||
[1] =>
|
||||
int(2)
|
||||
[2] =>
|
||||
int(3)
|
||||
[3] =>
|
||||
int(4)
|
||||
[4] =>
|
||||
int(5)
|
||||
[5] =>
|
||||
int(6)
|
||||
[6] =>
|
||||
array(int, 1) {
|
||||
[0] =>
|
||||
int(7)
|
||||
}
|
||||
[7] =>
|
||||
array(int, 1) {
|
||||
[test] =>
|
||||
int(8)
|
||||
}
|
||||
[8] =>
|
||||
array(int, 2) {
|
||||
[0] =>
|
||||
int(0)
|
||||
[1] =>
|
||||
int(0)
|
||||
}
|
||||
}
|
||||
array(float, 5) {
|
||||
[0] =>
|
||||
float(1)
|
||||
[1] =>
|
||||
float(4.5)
|
||||
[2] =>
|
||||
array(float, 3) {
|
||||
[0] =>
|
||||
float(4)
|
||||
[1] =>
|
||||
float(5)
|
||||
[2] =>
|
||||
float(6.5)
|
||||
}
|
||||
[3] =>
|
||||
float(7.2)
|
||||
[4] =>
|
||||
float(9)
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
class Program {
|
||||
|
||||
void test_assert(mixed $param) {
|
||||
assert("is_bool($param);");
|
||||
}
|
||||
|
||||
public void main() {
|
||||
callback $assert_fail = void(string $file, int $line, string $code) {
|
||||
print("Assertion failed ...\n");
|
||||
};
|
||||
assert_options(ASSERT_ACTIVE, true);
|
||||
assert_options(ASSERT_BAIL, false);
|
||||
assert_options(ASSERT_WARNING, false);
|
||||
assert_options(ASSERT_CALLBACK, $assert_fail);
|
||||
$this->test_assert(true);
|
||||
$this->test_assert(1);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Assertion failed ...
|
|
@ -0,0 +1,79 @@
|
|||
class Base32 {
|
||||
private static char[] $map = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', '2', '3', '4', '5', '6', '7',
|
||||
'='
|
||||
};
|
||||
|
||||
private static int[] $flippedMap = {
|
||||
'A'=>0, 'B'=>1, 'C'=>2, 'D'=>3, 'E'=>4, 'F'=>5, 'G'=>6, 'H'=>7,
|
||||
'I'=>8, 'J'=>9, 'K'=>10, 'L'=>11, 'M'=>12, 'N'=>13, 'O'=>14, 'P'=>15,
|
||||
'Q'=>16, 'R'=>17, 'S'=>18, 'T'=>19, 'U'=>20, 'V'=>21, 'W'=>22, 'X'=>23,
|
||||
'Y'=>24, 'Z'=>25, '2'=>26, '3'=>27, '4'=>28, '5'=>29, '6'=>30, '7'=>31
|
||||
};
|
||||
|
||||
public static string encode(string $input, bool $padding = true) {
|
||||
if(!$input) return '';
|
||||
char[] $aInput = str_split($input);
|
||||
string $binaryString = '';
|
||||
for(int $i = 0; $i < sizeof($aInput); $i++) {
|
||||
$binaryString += str_pad(base_convert(ord($aInput[$i]), 10, 2), 8, '0', STR_PAD_LEFT);
|
||||
}
|
||||
string[] $fiveBitBinaryArray = str_split($binaryString, 5);
|
||||
string $base32 = '';
|
||||
$i = 0;
|
||||
while($i < sizeof($fiveBitBinaryArray)) {
|
||||
$base32 += Base32::$map[base_convert(str_pad($fiveBitBinaryArray[$i], 5,'0'), 2, 10)];
|
||||
$i++;
|
||||
}
|
||||
int $x;
|
||||
if($padding && ($x = strlen($binaryString) % 40) != 0) {
|
||||
if($x == 8) $base32 += str_repeat(Base32::$map[32], 6);
|
||||
else if($x == 16) $base32 += str_repeat(Base32::$map[32], 4);
|
||||
else if($x == 24) $base32 += str_repeat(Base32::$map[32], 3);
|
||||
else if($x == 32) $base32 += Base32::$map[32];
|
||||
}
|
||||
return $base32;
|
||||
}
|
||||
|
||||
public static string decode(string $input) {
|
||||
if(!$input) return '';
|
||||
int $paddingCharCount = substr_count($input, Base32::$map[32]);
|
||||
int[] $allowedValues = {6, 4, 3, 1, 0};
|
||||
if(!in_array($paddingCharCount, $allowedValues)) return '';
|
||||
for(int $i = 0; $i < 4; $i++) {
|
||||
if($paddingCharCount == $allowedValues[$i] && substr($input, -($allowedValues[$i])) != str_repeat(Base32::$map[32], $allowedValues[$i]))
|
||||
return '';
|
||||
}
|
||||
$input = str_replace('=','', $input);
|
||||
char[] $aInput = str_split($input);
|
||||
string $binaryString = '';
|
||||
for($i = 0; $i < sizeof($aInput); $i = $i + 8) {
|
||||
string $x = '';
|
||||
if(!in_array($input[$i], Base32::$map))
|
||||
return '';
|
||||
for(int $j = 0; $j < 8; $j++) {
|
||||
if($i + $j < strlen($input)) {
|
||||
if(array_key_exists($input[$i + $j], Base32::$flippedMap)) {
|
||||
$x += str_pad(base_convert(Base32::$flippedMap[$input[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT);
|
||||
}
|
||||
}
|
||||
}
|
||||
string[] $eightBits = str_split($x, 8);
|
||||
for(int $z = 0; $z < sizeof($eightBits); $z++) {
|
||||
char $y;
|
||||
$binaryString += (($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48) ? $y : '';
|
||||
}
|
||||
}
|
||||
return $binaryString;
|
||||
}
|
||||
}
|
||||
|
||||
class Program {
|
||||
public void main() {
|
||||
var_dump(Base32::encode('Test String'), Base32::encode('DS27DEC985'), Base32::encode('AerScript rocks!'));
|
||||
var_dump(Base32::decode('KRSXG5BAKN2HE2LOM4======'), Base32::decode('IRJTEN2EIVBTSOBV'), Base32::decode('IFSXEU3DOJUXA5BAOJXWG23TEE======'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
string(24 'KRSXG5BAKN2HE2LOM4======')
|
||||
string(16 'IRJTEN2EIVBTSOBV')
|
||||
string(32 'IFSXEU3DOJUXA5BAOJXWG23TEE======')
|
||||
string(11 'Test String')
|
||||
string(10 'DS27DEC985')
|
||||
string(16 'AerScript rocks!')
|
|
@ -0,0 +1,43 @@
|
|||
class Beaufort {
|
||||
private string $cipher;
|
||||
|
||||
public string __construct(string $text, string $key) {
|
||||
string $alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
for(int $i = 0; $i < strlen($text); $i++) {
|
||||
int $j;
|
||||
char $c0 = $text[$i];
|
||||
char $c1 = $key[$i % strlen($key)];
|
||||
int $start = 0;
|
||||
for($j = 0; $j < 26; $j++) {
|
||||
if($alphabet[$j] == strtoupper($c0)) {
|
||||
$start = $j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int $offset = 0;
|
||||
for($j = $start; $j < $start + 26; $j++) {
|
||||
int $letter = $j %26;
|
||||
if($alphabet[$letter] == strtoupper($c1)) {
|
||||
break;
|
||||
}
|
||||
$offset++;
|
||||
}
|
||||
$this->cipher += $alphabet[$offset];
|
||||
}
|
||||
}
|
||||
|
||||
public string getCipher() {
|
||||
return $this->cipher;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Program {
|
||||
|
||||
public void main() {
|
||||
object $beaufort = new Beaufort('thisisasecretmessage', 'youwillneverguessit');
|
||||
var_dump($beaufort->getCipher());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
string(20 'FHMEATLVATNNNIAAAINU')
|
|
@ -0,0 +1,17 @@
|
|||
class Program {
|
||||
|
||||
string fmt_binary(int $x, int $numbits = 8) {
|
||||
string $bin;
|
||||
string $rtnval = '';
|
||||
$bin = decbin($x);
|
||||
$bin = substr(str_repeat(0, $numbits), 0, $numbits - strlen($bin)) + $bin;
|
||||
for($x = 0; $x < $numbits / 4; $x++) {
|
||||
$rtnval += ' ' + substr($bin, $x * 4, 4);
|
||||
}
|
||||
return ltrim($rtnval);
|
||||
}
|
||||
|
||||
public void main() {
|
||||
var_dump($this->fmt_binary(2541));
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
string(9 '0000 1001')
|
|
@ -0,0 +1,107 @@
|
|||
class Brainfuck {
|
||||
private string $code;
|
||||
private int $code_pointer;
|
||||
private int[] $cells;
|
||||
private int $pointer;
|
||||
private string $input;
|
||||
private int $input_pointer;
|
||||
private int[] $buffer;
|
||||
private string $output;
|
||||
|
||||
public void __construct(string $code, string $input = NULL) {
|
||||
$this->code = $code;
|
||||
$this->input = $input;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while ($this->code_pointer < strlen($this->code)) {
|
||||
$this->interpret($this->code[$this->code_pointer]);
|
||||
$this->code_pointer++;
|
||||
}
|
||||
print($this->output);
|
||||
}
|
||||
|
||||
private void interpret(string $command) {
|
||||
if(!array_key_exists($this->pointer, $this->cells)) {
|
||||
$this->cells[$this->pointer] = 0;
|
||||
}
|
||||
switch ($command) {
|
||||
case '>' :
|
||||
$this->pointer++;
|
||||
break;
|
||||
case '<' :
|
||||
$this->pointer--;
|
||||
break;
|
||||
case '+' :
|
||||
$this->cells[$this->pointer]++;
|
||||
if($this->cells[$this->pointer] > 255) {
|
||||
$this->cells[$this->pointer] = 0;
|
||||
}
|
||||
break;
|
||||
case '-' :
|
||||
$this->cells[$this->pointer]--;
|
||||
if($this->cells[$this->pointer] < 0) {
|
||||
$this->cells[$this->pointer] = 255;
|
||||
}
|
||||
break;
|
||||
case '.' :
|
||||
$this->output += chr($this->cells[$this->pointer]);
|
||||
break;
|
||||
case ',' :
|
||||
$this->cells[$this->pointer] = $this->input[$this->input_pointer] ? ord($this->input[$this->input_pointer]) : 0;
|
||||
$this->input_pointer++;
|
||||
break;
|
||||
case '[' :
|
||||
if($this->cells[$this->pointer] == 0) {
|
||||
int $delta = 1;
|
||||
while($delta && $this->code_pointer++ < strlen($this->code)) {
|
||||
switch ($this->code[$this->code_pointer]) {
|
||||
case '[' :
|
||||
$delta++;
|
||||
break;
|
||||
case ']' :
|
||||
$delta--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->buffer[] = $this->code_pointer;
|
||||
}
|
||||
break;
|
||||
case ']' :
|
||||
$this->code_pointer = array_pop($this->buffer) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class Program {
|
||||
|
||||
public void main() {
|
||||
object $bf;
|
||||
string $code;
|
||||
resource $dir;
|
||||
string $file;
|
||||
string[] $files;
|
||||
string $input;
|
||||
$dir = opendir('tests/data/brainfuck');
|
||||
while($file = readdir($dir)) {
|
||||
if($file == '.' || $file == '..') {
|
||||
continue;
|
||||
}
|
||||
$files[] = $file;
|
||||
}
|
||||
sort($files);
|
||||
unset($file);
|
||||
for(int $n = 0; $n < sizeof($files); $n++) {
|
||||
print('Executing "' + $files[$n] + '"' + "\n");
|
||||
$code = file_get_contents('tests/data/brainfuck/' + $files[$n]);
|
||||
$bf = new Brainfuck($code, $input);
|
||||
$bf->run();
|
||||
print("\n");
|
||||
}
|
||||
closedir($dir);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
Executing "array.bf"
|
||||
EC
|
||||
Executing "hello_world.bf"
|
||||
Hello World!
|
||||
|
||||
Executing "sierpinski.bf"
|
||||
*
|
||||
* *
|
||||
* *
|
||||
* * * *
|
||||
* *
|
||||
* * * *
|
||||
* * * *
|
||||
* * * * * * * *
|
||||
* *
|
||||
* * * *
|
||||
* * * *
|
||||
* * * * * * * *
|
||||
* * * *
|
||||
* * * * * * * *
|
||||
* * * * * * * *
|
||||
* * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* * * *
|
||||
* * * *
|
||||
* * * * * * * *
|
||||
* * * *
|
||||
* * * * * * * *
|
||||
* * * * * * * *
|
||||
* * * * * * * * * * * * * * * *
|
||||
* * * *
|
||||
* * * * * * * *
|
||||
* * * * * * * *
|
||||
* * * * * * * * * * * * * * * *
|
||||
* * * * * * * *
|
||||
* * * * * * * * * * * * * * * *
|
||||
* * * * * * * * * * * * * * * *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
class Program {
|
||||
|
||||
public static int[] bubbleSort(int[] $arr) {
|
||||
int $n = sizeof($arr);
|
||||
for(int $i = 1; $i < $n; $i++) {
|
||||
bool $flag = false;
|
||||
for(int $j = $n - 1; $j >= $i; $j--) {
|
||||
if($arr[$j-1] > $arr[$j]) {
|
||||
int $tmp = $arr[$j - 1];
|
||||
$arr[$j - 1] = $arr[$j];
|
||||
$arr[$j] = $tmp;
|
||||
$flag = true;
|
||||
}
|
||||
}
|
||||
if(!$flag) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
|
||||
public void main() {
|
||||
int[] $arr = {7, 9, 1, 2, 5, 6, 10, 14};
|
||||
var_dump(Program::bubbleSort($arr));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
array(int, 8) {
|
||||
[0] =>
|
||||
int(1)
|
||||
[1] =>
|
||||
int(2)
|
||||
[2] =>
|
||||
int(5)
|
||||
[3] =>
|
||||
int(6)
|
||||
[4] =>
|
||||
int(7)
|
||||
[5] =>
|
||||
int(9)
|
||||
[6] =>
|
||||
int(10)
|
||||
[7] =>
|
||||
int(14)
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
class Program {
|
||||
|
||||
public void main(string[] $args) {
|
||||
callback $y = void() {
|
||||
callback $a = 'printf';
|
||||
$a("I'm alive\n");
|
||||
var_dump($a);
|
||||
};
|
||||
$y();
|
||||
var_dump($y);
|
||||
string $a = 'printf';
|
||||
var_dump($a);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
I'm alive
|
||||
callback(6 'printf')
|
||||
callback(11 '{closure_1}')
|
||||
string(6 'printf')
|
|
@ -0,0 +1,23 @@
|
|||
class Program {
|
||||
|
||||
private string center_text(string $word){
|
||||
int $tot_width = 30;
|
||||
char $symbol = '-';
|
||||
int $middle = (int) round($tot_width/2);
|
||||
int $length_word = strlen($word);
|
||||
int $middle_word = (int) round($length_word / 2);
|
||||
int $last_position = $middle + $middle_word;
|
||||
int $number_of_spaces = $middle - $middle_word;
|
||||
string $result = sprintf("%'{$symbol}{$last_position}s", $word);
|
||||
for(int $i = 0; $i < $number_of_spaces; $i++) {
|
||||
$result += "$symbol";
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public void main() {
|
||||
string $str = 'Example text';
|
||||
print($this->center_text($str));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
---------Example text---------
|
|
@ -0,0 +1,19 @@
|
|||
class Test1 {
|
||||
}
|
||||
|
||||
class Test2 extends Test1 {
|
||||
}
|
||||
|
||||
class Program {
|
||||
object $t;
|
||||
|
||||
private void test(Test1 $t = new Test2) {
|
||||
$this->t = $t;
|
||||
var_dump($this->t);
|
||||
}
|
||||
|
||||
public void main() {
|
||||
$this->test();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
object(Test2) {
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
class Button {
|
||||
public callback $OnBeforeClick;
|
||||
public callback $OnAfterClick;
|
||||
public string $Name;
|
||||
|
||||
public void __construct() {
|
||||
$this->Name = 'MyButton';
|
||||
}
|
||||
|
||||
public void Click() {
|
||||
$this->DoBeforeClick();
|
||||
print('Click!');
|
||||
$this->DoAfterClick();
|
||||
}
|
||||
|
||||
private void DoBeforeClick() {
|
||||
if($this->OnBeforeClick) {
|
||||
callback $event = $this->OnBeforeClick;
|
||||
$event($this);
|
||||
}
|
||||
}
|
||||
|
||||
private void DoAfterClick() {
|
||||
if($this->OnAfterClick) {
|
||||
callback $event = $this->OnAfterClick;
|
||||
$event($this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Program {
|
||||
|
||||
public void main() {
|
||||
object $MyWidget = new Button();
|
||||
$MyWidget->OnBeforeClick = void(object $Sender) { print($Sender->Name + ' (Before Click)'); };
|
||||
$MyWidget->OnAfterClick = void(object $Sender) { print($Sender->Name + ' (After Click)'); };
|
||||
$MyWidget->Click();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
MyButton (Before Click)Click!MyButton (After Click)
|
|
@ -0,0 +1,36 @@
|
|||
class Operations {
|
||||
|
||||
public callback ops(int $x, int $y, string $op){
|
||||
switch($op) {
|
||||
case 'ADD':
|
||||
return int() using ($x, $y) {
|
||||
return $x + $y;
|
||||
};
|
||||
break;
|
||||
case 'SUB':
|
||||
return int() using ($x, $y) {
|
||||
return $x - $y;
|
||||
};
|
||||
break;
|
||||
default:
|
||||
return string() {
|
||||
return 'Operation is not supported by class.';
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Program {
|
||||
|
||||
public void main() {
|
||||
callback $fn;
|
||||
object $op = new Operations();
|
||||
$fn = $op->ops(6, 7, 'ADD');
|
||||
print($fn() + "\n");
|
||||
$fn = $op->ops(6, 2, 'SUB');
|
||||
print($fn() + "\n");
|
||||
$fn = $op->ops(6, 7, 'MUL');
|
||||
print($fn() + "\n");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
13
|
||||
4
|
||||
Operation is not supported by class.
|
|
@ -0,0 +1,43 @@
|
|||
class Program {
|
||||
private const MY_CONST = 12 ^ 0x3FD;
|
||||
private callback $callback_test = void(){ print("Welcome everyone!\n");};
|
||||
private static int $value = 4 + 4 * 4;
|
||||
|
||||
void callable(callback $callback = void(){ print("Hello world!\n");}) {
|
||||
$callback();
|
||||
}
|
||||
|
||||
void complexArgs(string $name = 'AerScript' + $this->someStr(), int $age = 10*2+5) {
|
||||
print("Name = $name\n");
|
||||
print("Age = $age\n");
|
||||
}
|
||||
|
||||
string someStr() {
|
||||
return 'ABC';
|
||||
}
|
||||
|
||||
bool someTrue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool someFalse() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int main() {
|
||||
static float $f = 4 + 2.4 * 9.1;
|
||||
var_dump($this->MY_CONST);
|
||||
var_dump($this->callback_test);
|
||||
var_dump($this->value);
|
||||
var_dump($f);
|
||||
$this->complexArgs();
|
||||
$this->complexArgs('Me');
|
||||
$this->callable();
|
||||
$this->callable(void(){ print("Welcome guest!\n");});
|
||||
$this->callable($this->callback_test);
|
||||
$this->someTrue() || print("someTrue() failed\n");
|
||||
$this->someFalse() || print("someFalse() failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
int(1009)
|
||||
callback(11 '{closure_1}')
|
||||
int(20)
|
||||
float(25.84)
|
||||
Name = AerScriptABC
|
||||
Age = 25
|
||||
Name = Me
|
||||
Age = 25
|
||||
Hello world!
|
||||
Welcome guest!
|
||||
Welcome everyone!
|
||||
someFalse() failed
|
|
@ -0,0 +1,16 @@
|
|||
class Program {
|
||||
|
||||
private void test(int $a = (int(int $a, int $b, int $c){return $a+$b+$c;})(14, 10+2, 15), int $b = 0, int $c = 98) {
|
||||
print($a + PHP_EOL);
|
||||
print($b + PHP_EOL);
|
||||
print($c + PHP_EOL);
|
||||
}
|
||||
|
||||
public void main() {
|
||||
$this->test();
|
||||
$this->test(512);
|
||||
$this->test(1024, 32);
|
||||
$this->test(1000, 2000, 4000);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
41
|
||||
0
|
||||
98
|
||||
512
|
||||
0
|
||||
98
|
||||
1024
|
||||
32
|
||||
98
|
||||
1000
|
||||
2000
|
||||
4000
|
|
@ -0,0 +1,21 @@
|
|||
define TEST_CONSTANT 'This is a global constant';
|
||||
|
||||
class Program {
|
||||
const TEST_CONSTANT = 'This is a class constant';
|
||||
|
||||
private void constant_test() {
|
||||
const TEST_CONSTANT = 'This is a local constant';
|
||||
var_dump(TEST_CONSTANT);
|
||||
}
|
||||
|
||||
public void main() {
|
||||
int $var = 69;
|
||||
var_dump(TEST_CONSTANT);
|
||||
$this->constant_test();
|
||||
var_dump(TEST_CONSTANT);
|
||||
var_dump($this->TEST_CONSTANT);
|
||||
const TEST_CONSTANT = 'Local constant overrides a global constant';
|
||||
var_dump(TEST_CONSTANT);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
string(25 'This is a global constant')
|
||||
string(24 'This is a local constant')
|
||||
string(25 'This is a global constant')
|
||||
string(24 'This is a class constant')
|
||||
string(42 'Local constant overrides a global constant')
|
|
@ -0,0 +1,6 @@
|
|||
>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
|
||||
>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
|
||||
>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
|
||||
>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
|
||||
>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
|
||||
<<<<<<<<<<++++[-[>>+<<-]>>]>.<<<<<<<<<++[-[>>+<<-]>>]>.
|
|
@ -0,0 +1 @@
|
|||
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
|
|
@ -0,0 +1 @@
|
|||
++++++++[>+>++++<<-]>++>>+<[-[>>+<<-]+>>]>+[-<<<[->[+[-]+>++>>>-<<]<[<]>>++++++[<<+++++>>-]+<<++.[-]<<]>.>+[>>]>+]
|
|
@ -0,0 +1,8 @@
|
|||
class BaseClass {
|
||||
|
||||
protected void run() {
|
||||
printf('Test launched...');
|
||||
include 'data/includes/include_test.aer';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
printf("OK!\n");
|
|
@ -0,0 +1,3 @@
|
|||
class Test {
|
||||
string $test = 'This is a test';
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
class Program {
|
||||
|
||||
public void main() {
|
||||
$this->b($this->a('First A'), $this->a('Second A'), $this->a('Third A'));
|
||||
}
|
||||
|
||||
string a(string $p) {
|
||||
mixed[] $backtrace = debug_backtrace();
|
||||
if(array_key_exists('args', $backtrace[0])) {
|
||||
var_export($backtrace[0]['args']);
|
||||
} else {
|
||||
print("Cannot aquire arguments\n");
|
||||
}
|
||||
return $p;
|
||||
}
|
||||
|
||||
void b(string $p1, string $p2, string $p3) {
|
||||
print("$p1, $p2, $p3");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
Array(1) {
|
||||
[0] =>
|
||||
First A
|
||||
}
|
||||
Array(1) {
|
||||
[0] =>
|
||||
Second A
|
||||
}
|
||||
Array(1) {
|
||||
[0] =>
|
||||
Third A
|
||||
}
|
||||
First A, Second A, Third A
|
|
@ -0,0 +1,44 @@
|
|||
class Test1 {
|
||||
|
||||
public void __construct() {
|
||||
print("Test1::__construct() called.\n");
|
||||
}
|
||||
|
||||
public void __destruct() {
|
||||
print("Test1::__destruct() called.\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Test2 extends Test1 {
|
||||
|
||||
public void __construct() {
|
||||
print("Test2::__construct() called.\n");
|
||||
$parent->__construct();
|
||||
}
|
||||
|
||||
public void __destruct() {
|
||||
print("Test2::__destruct() called.\n");
|
||||
$parent->__destruct();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Program {
|
||||
object $test;
|
||||
|
||||
public void __construct() {
|
||||
print("Program::__construct() called.\n");
|
||||
$this->test = new Test1();
|
||||
}
|
||||
|
||||
public void __destruct() {
|
||||
print("Program::__destruct() called.\n");
|
||||
}
|
||||
|
||||
public void main() {
|
||||
print("Program::main() called.\n");
|
||||
object $test = new Test2();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
Program::__construct() called.
|
||||
Test1::__construct() called.
|
||||
Program::main() called.
|
||||
Test2::__construct() called.
|
||||
Test1::__construct() called.
|
||||
Program::__destruct() called.
|
||||
Test1::__destruct() called.
|
||||
Test2::__destruct() called.
|
||||
Test1::__destruct() called.
|
|
@ -0,0 +1,29 @@
|
|||
// A simple C program to calculate Euler's Totient Function
|
||||
class Program {
|
||||
|
||||
// Function to return gcd of a and b
|
||||
private int gcd(int $a, int $b) {
|
||||
if($a == 0)
|
||||
return $b;
|
||||
return $this->gcd($b % $a, $a);
|
||||
}
|
||||
|
||||
// A simple method to evaluate Euler Totient Function
|
||||
private int phi(int $n) {
|
||||
int $result = 1;
|
||||
for(int $i = 2; $i < $n; $i++)
|
||||
if($this->gcd($i, $n) == 1)
|
||||
$result++;
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
// Driver program to test above function
|
||||
public int main() {
|
||||
int $n;
|
||||
for($n = 1; $n <= 10; $n++)
|
||||
printf("phi(%d) = %d\n", $n, $this->phi($n));
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
phi(1) = 1
|
||||
phi(2) = 1
|
||||
phi(3) = 2
|
||||
phi(4) = 2
|
||||
phi(5) = 4
|
||||
phi(6) = 2
|
||||
phi(7) = 6
|
||||
phi(8) = 4
|
||||
phi(9) = 6
|
||||
phi(10) = 4
|
|
@ -0,0 +1,43 @@
|
|||
class ExceptionHandler {
|
||||
|
||||
public static void printException(Exception $e) {
|
||||
print('Uncaught ' + get_class($e) + ', code: ' + $e->getCode() + "\nMessage: " + htmlentities($e->getMessage()) + "\n");
|
||||
}
|
||||
|
||||
public static void handleException(Exception $e) {
|
||||
ExceptionHandler::printException($e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class NewException extends Exception {
|
||||
}
|
||||
|
||||
class Program {
|
||||
|
||||
public void main() {
|
||||
callback $handler = void(Exception $e) {
|
||||
ExceptionHandler::handleException($e);
|
||||
};
|
||||
set_exception_handler($handler);
|
||||
try {
|
||||
print("Called try block 0\n");
|
||||
} finally {
|
||||
print("Called finally block 0\n");
|
||||
}
|
||||
try {
|
||||
throw new NewException("Catch me once", 1);
|
||||
} catch(Exception $e) {
|
||||
ExceptionHandler::handleException($e);
|
||||
} finally {
|
||||
print("Called finally block 1\n");
|
||||
}
|
||||
try {
|
||||
throw new NewException("Catch me twice", 2);
|
||||
} finally {
|
||||
print("Called finally block 2\n");
|
||||
}
|
||||
throw new Exception("Catch me thrice", 3);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
Called try block 0
|
||||
Called finally block 0
|
||||
Uncaught NewException, code: 1
|
||||
Message: Catch me once
|
||||
Called finally block 1
|
||||
Called finally block 2
|
||||
Uncaught NewException, code: 2
|
||||
Message: Catch me twice
|
||||
Uncaught Exception, code: 3
|
||||
Message: Catch me thrice
|
|
@ -0,0 +1,24 @@
|
|||
class Dog {
|
||||
public string $name;
|
||||
public string $color;
|
||||
|
||||
public void __construct(string $name, string $color) {
|
||||
$this->name = $name;
|
||||
$this->color = $color;
|
||||
}
|
||||
|
||||
public callback greet(string $greeting) {
|
||||
return void() using ($greeting) {
|
||||
print("$greeting, I am a {$this->color} dog named {$this->name}\n");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class Program {
|
||||
|
||||
public void main() {
|
||||
object $dog = new Dog('Alex', 'red');
|
||||
callback $c = $dog->greet('Hello');
|
||||
$c();
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Hello, I am a red dog named Alex
|
|
@ -0,0 +1,15 @@
|
|||
class Program {
|
||||
|
||||
private int factorial(int $num) {
|
||||
if($num == 0 || $num == 1)
|
||||
return 1;
|
||||
else
|
||||
return $num * $this->factorial($num - 1);
|
||||
}
|
||||
|
||||
public void main() {
|
||||
int $num = 7;
|
||||
print('Factorial of ', $num, ' is ', $this->factorial($num), '.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Factorial of 7 is 5040.
|
|
@ -0,0 +1,29 @@
|
|||
class Circle {
|
||||
public void draw() {
|
||||
print("Circle\n");
|
||||
}
|
||||
}
|
||||
|
||||
class Square {
|
||||
public void draw() {
|
||||
print("Square\n");
|
||||
}
|
||||
}
|
||||
|
||||
class Program {
|
||||
|
||||
object ShapeFactoryMethod(string $shape) {
|
||||
switch ($shape) {
|
||||
case "Circle":
|
||||
return new Circle();
|
||||
case "Square":
|
||||
return new Square();
|
||||
}
|
||||
}
|
||||
|
||||
public void main() {
|
||||
$this->ShapeFactoryMethod("Circle")->draw();
|
||||
$this->ShapeFactoryMethod("Square")->draw();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
Circle
|
||||
Square
|
|
@ -0,0 +1,19 @@
|
|||
class Program {
|
||||
|
||||
private int fib(int $n) {
|
||||
int $last = 0;
|
||||
int $cur = 1;
|
||||
--$n;
|
||||
while($n > 0) {
|
||||
--$n;
|
||||
int $tmp = $cur;
|
||||
$cur = $last + $cur;
|
||||
$last = $tmp;
|
||||
}
|
||||
return $cur;
|
||||
}
|
||||
|
||||
public int main() {
|
||||
var_dump($this->fib(43));
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue