Compare commits

...

888 Commits

Author SHA1 Message Date
Rafal Kupiec 5e6ed0f668
New pipeline for new CI/CD.
continuous-integration/drone/push Build is failing Details
2020-06-20 00:43:25 +02:00
Rafal Kupiec c940224d21
Tower of Hanoi test.
The build was successful. Details
2019-12-22 22:58:36 +01:00
Rafal Kupiec 3eb82e632b
Add new test - sudoku solver.
The build was successful. Details
2019-12-22 22:44:15 +01:00
Rafal Kupiec 709b5971c6
Return can break loop execution as well. If it does, it needs to ensure VM_FRAME_ACTIVE is on top.
The build was successful. Details
2019-12-22 22:40:11 +01:00
Rafal Kupiec c730082fa0
Do not issue OP_LF_STOP on 'break' inside 'switch' statement.
The build was successful. Details
2019-12-21 22:48:44 +01:00
Rafal Kupiec 0bf2f6d94f
Correct error message.
The build was successful. Details
2019-12-21 16:22:16 +01:00
Rafal Kupiec b527840f10
Correct arguments length. Get rid of some additional non-printable characters from the end of string.
The build was successful. Details
2019-12-21 15:33:55 +01:00
Rafal Kupiec ab36234ff3
Add beaufort cipher test.
The build was successful. Details
2019-12-17 14:41:27 +01:00
Rafal Kupiec 9d762a2350
Move debug-related code into separate file.
The build was successful. Details
2019-12-15 13:32:45 +01:00
Rafal Kupiec 0b5e94bacc
Add missing operator description.
The build was successful. Details
2019-12-15 00:00:54 +01:00
Rafal Kupiec e623111f41
Correct comment.
The build was successful. Details
2019-12-14 23:37:55 +01:00
Rafal Kupiec fd0685f16e
Code formatting.
The build was successful. Details
2019-12-14 23:31:47 +01:00
Rafal Kupiec ad5784f81f
Reimplement import() builtin function as a global-scope statement. This fixes #58.
The build was successful. Details
2019-12-14 23:30:38 +01:00
Rafal Kupiec 0e757111a3
Add 'include' & 'require' statements test.
The build was successful. Details
2019-12-10 19:21:27 +01:00
Rafal Kupiec 469e5ba059
Do not need debug symbols in CI/CD.
The build was successful. Details
2019-12-10 16:23:39 +01:00
Rafal Kupiec 9290db2504
Another changes in file inclusion mechanism (#58):
The build was successful. Details
* Remove builtin functions: 'include' & 'require'
* Implement 'include' and 'require' statements compiler
* Implement OP_INCLUDE operator
* Allow 'require' statement to be used in global scope as well as in method body and 'include' only in method body
2019-12-10 16:09:26 +01:00
Rafal Kupiec 09e7400349
Add forward declaration for VmExecIncludedFile().
The build was successful. Details
2019-12-09 19:36:40 +01:00
Rafal Kupiec cb91a4bbf4
Rework including mechanism (#58) related changes:
The build was successful. Details
* VmExecIncludedFile() does not need a call context
 * Builtin include() function does not need to return false, it throws an error
2019-12-09 19:30:28 +01:00
Rafal Kupiec f3156bcbd5
Throw E_ERROR when impossible to include specified file.
The build was successful. Details
2019-11-27 20:15:43 +01:00
Rafal Kupiec cb71daec12
Code inclusion rework that include several changes (#58):
The build was successful. Details
* include() builtin function allows now to include a chunk of code, eg. a body of some loop
 * include() allows to load and execute file several times
 * require() still allows to include file just once and included file must have a valid OOP syntax
 * both functions will throw E_ERROR when impossible to include specified file
2019-11-27 20:07:50 +01:00
Rafal Kupiec 63fd76c9c8
Rework PH7_GenStateGetGlobalScopeHandler() function.
The build was successful. Details
2019-11-19 08:10:59 +01:00
Rafal Kupiec e1e6a19f30
Update code formatting.
The build was successful. Details
2019-11-18 18:57:10 +01:00
Rafal Kupiec d3479a6e80
Correct formatting.
The build was successful. Details
2019-11-18 08:11:13 +01:00
Rafal Kupiec a24e44fbf3
Completely remove this broken threading implementation. Fixes #55.
The build was successful. Details
2019-10-28 21:35:16 +01:00
Rafal Kupiec f3972a9ca2
Rename LFB/LFE operators.
The build was successful. Details
2019-10-25 23:09:30 +02:00
Rafal Kupiec f323e3cb57
Make a use from PH7_MemObjIsHashmap().
The build was successful. Details
2019-09-10 14:12:07 +02:00
Rafal Kupiec 426ec932ec
Implement MemObjIsHashmap().
The build was successful. Details
2019-09-10 10:55:54 +02:00
Rafal Kupiec 3aa31a9dfa
Make a use from MemObjIsNumeric().
The build was successful. Details
2019-09-10 10:10:52 +02:00
Rafal Kupiec f0aba06f4f
Allow increment/decrement operations only on numeric operands.
The build was successful. Details
2019-09-10 08:03:35 +02:00
Rafal Kupiec 18b96064e4
Do not allow to call non-existen array/string index.
The build was successful. Details
PHP returns a NULL for each call to non-existen array element, while AerScript design disallows usage of indexes outside the bounds. This fixes one of most serious PHP problems.
2019-09-09 16:55:48 +02:00
Rafal Kupiec 91887c0185
Do not try to access non-existen string index.
The build was successful. Details
2019-09-07 20:07:46 +02:00
Rafal Kupiec 3b9d91f186
Revert 3dcc908788.
The build was successful. Details
2019-08-29 14:23:33 +02:00
Rafal Kupiec 0fb44bb1ae
GitHub Funding.
The build was successful. Details
2019-08-23 13:48:56 +02:00
Piotr Likoski d2335c86b2
Base32::decode() cannot return boolean values.
The build was successful. Details
2019-07-12 17:05:27 +02:00
Piotr Likoski 843c2d67d9
I am pretty sure we want to use the number of elements in array in this place, not the actual size of array.
The build was successful. Details
The size of a structure is greater than the sum of its parts because of what is called packing. A particular processor has a preferred data size that it works with. Most modern processors' preferred size if 32-bits (4 bytes).
2019-07-12 14:36:56 +02:00
Piotr Likoski 33b0f20573
Check the snprintf() return value.
The build was successful. Details
2019-07-12 14:10:09 +02:00
David Carlier d96dcdf1e0 Little build warning removal
The build was successful. Details
2019-07-11 07:17:34 +00:00
Rafal Kupiec a09c6b3fad
Fix for index outside the bounds.
The build was successful. Details
2019-07-01 21:08:07 +02:00
Rafal Kupiec 4d150c2fe3
No way this is working!
The build was successful. Details
2019-07-01 21:03:45 +02:00
Rafal Kupiec c94de60c29
Properly implement tests.
The build was successful. Details
2019-07-01 20:07:06 +02:00
Rafal Kupiec 376b9510a9
Fix typos, formatting.
The build was successful. Details
2019-06-30 14:13:35 +02:00
Rafal Kupiec ad49b81b33
Add support for HTTP/2.0 protocol version.
The build was successful. Details
2019-06-30 09:51:15 +02:00
Rafal Kupiec 4afcbc0815
Extend singleton test.
The build was successful. Details
2019-06-29 16:04:15 +02:00
Rafal Kupiec 171456beb4
Release all elements in object allocation table.
The build was successful. Details
2019-06-29 15:54:05 +02:00
Rafal Kupiec 204060fa9d
Implement TAU.
The build was successful. Details
2019-06-29 14:21:29 +02:00
Rafal Kupiec 616b2eeae3
Cleanup the headers a bit.
The build was successful. Details
2019-06-29 11:50:01 +02:00
Rafal Kupiec 563c10bd20
Do not omit floating point.
The build was successful. Details
2019-06-29 11:41:37 +02:00
Rafal Kupiec 2e695a9d35
Link dynamically with libC.
The build was successful. Details
2019-06-29 11:15:03 +02:00
Rafal Kupiec 2ef2b6265c
Never disable IO library.
The build was successful. Details
2019-06-29 11:10:50 +02:00
Rafal Kupiec a6d89da16b
Do not support old libC.
The build was successful. Details
2019-06-28 19:43:23 +02:00
Rafal Kupiec 48d5088265
Enable the magic number protection.
The build was successful. Details
2019-06-27 22:57:08 +02:00
Rafal Kupiec 3dcc908788
Enable threading.
The build was successful. Details
2019-06-27 20:52:37 +02:00
Rafal Kupiec 4881ddf6de
Pass compatible pointer type.
The build was successful. Details
2019-06-27 20:44:50 +02:00
Rafal Kupiec 312fb97db6
Another FS-related bugfix to make compiler happy.
The build was successful. Details
2019-06-25 20:25:56 +02:00
Rafal Kupiec 0a2f1133d5
Do not use pointer for file path.
The build was successful. Details
2019-06-25 20:10:27 +02:00
Rafal Kupiec 647454b98d
Another signedness correction.
The build was successful. Details
2019-06-22 20:45:22 +02:00
Rafal Kupiec 72782b147a
Do not convert between data pointers and function pointers.
The build was successful. Details
2019-06-22 12:35:33 +02:00
Rafal Kupiec edb62ed692
Correct signedness.
The build was successful. Details
2019-06-22 12:34:49 +02:00
Rafal Kupiec 8b2086402e
Fix all compiler warnings in AerScript compiler.
The build was successful. Details
2019-06-22 11:59:43 +02:00
Rafal Kupiec 8ee2dece06
Test NULL-coalescing operator.
The build was successful. Details
2019-06-21 23:53:01 +02:00
Rafal Kupiec dcf37af75e
Implement a NULL-coalescing '??' operator.
The build was successful. Details
2019-06-21 00:34:41 +02:00
Rafal Kupiec 6d964d6113
Add missing declaration for PH7_MemObjIsNull() function.
The build was successful. Details
2019-06-21 00:30:35 +02:00
Rafal Kupiec 3045bd2d88
Update lexer. Add missing operators.
The build was successful. Details
2019-06-20 14:30:49 +02:00
Rafal Kupiec 19d0628afc
Do not try to duplicate an array when source equals to destination.
The build was successful. Details
2019-06-20 13:36:30 +02:00
Rafal Kupiec 59811ac742
Completely rely on the compiler.
The build was successful. Details
2019-06-20 12:10:02 +02:00
Rafal Kupiec e40dc34026
Pass proper line number from compiler to the virtual machine.
The build was successful. Details
2019-06-20 12:07:47 +02:00
Rafal Kupiec c76ae15a7b
Disable undefined behavior sanitizer.
The build was successful. Details
2019-06-20 00:19:52 +02:00
Rafal Kupiec a1f1d50d25
Allow to use compiler's sanitizer. This fixes #53.
The build was successful. Details
2019-06-19 17:38:36 +02:00
Rafal Kupiec ca51e2a5da
Add comments.
The build was successful. Details
2019-06-19 10:14:01 +02:00
Rafal Kupiec bd24aa0605
Correct more compiler warnings.
The build was successful. Details
2019-06-19 09:31:40 +02:00
Rafal Kupiec 690213e0c7
Do not use a pointer for temporary value.
The build was successful. Details
2019-06-18 13:25:40 +02:00
Rafal Kupiec 0be38392bd
Correct variable types, to make compiler silent.
The build was successful. Details
2019-06-17 14:28:03 +02:00
Rafal Kupiec bffd44a7b4
Get rid of some annoying compiler warnings.
The build was successful. Details
2019-06-17 09:51:37 +02:00
Rafal Kupiec 173bac16ad
Add missing definitions.
The build was successful. Details
2019-06-16 19:54:42 +02:00
Rafal Kupiec b3eb2d0139
Include missing header.
The build was successful. Details
2019-06-16 08:41:42 +02:00
Rafal Kupiec 050a637e88
Add missing declarations.
The build was successful. Details
2019-06-16 08:31:43 +02:00
Rafal Kupiec 8d0c128d22
Fix comparison of integer expressions of different signedness.
The build was successful. Details
2019-06-16 00:37:20 +02:00
Rafal Kupiec c7b6e76d0d
Get rid of unused variables/labels/etc.
The build was successful. Details
2019-06-16 00:33:03 +02:00
Rafal Kupiec 1a91fedb1f
Proper SXUNUSED() macro implementation.
The build was successful. Details
2019-06-16 00:10:27 +02:00
Rafal Kupiec fffce10ba8
Test for implicitly typed declarations.
The build was successful. Details
2019-06-15 23:44:10 +02:00
Rafal Kupiec ace4d56d7f
The '-Og' is a better choice than '-O0' for producing debuggable code because some compiler passes that collect debug information are disabled at '-O0'.
The build was successful. Details
2019-06-15 18:12:27 +02:00
Rafal Kupiec 8985044054
Remove some unused variables.
The build was successful. Details
2019-06-15 17:43:24 +02:00
Rafal Kupiec 77150e9d26
Enable some code diagnostics.
The build was successful. Details
2019-06-15 17:20:51 +02:00
Rafal Kupiec aff19a98da
Fibonacci sequence in AerScript implementation.
The build was successful. Details
2019-06-14 22:52:02 +02:00
Rafal Kupiec 010bdd7331
Properly destroy temporary memory object. Fix memory leak.
The build was successful. Details
2019-06-14 17:16:41 +02:00
Rafal Kupiec 0bef248298
Implement PH7_VmDestroyMemObj() to forcibly destroy a memory object.
The build was successful. Details
2019-06-14 17:11:34 +02:00
Rafal Kupiec d09a33da55
Do not duplicate variable name in this case.
The build was successful. Details
This should save a lot of memory on many method calls.
2019-06-14 10:17:50 +02:00
Rafal Kupiec 673796d878
Add missing function description.
The build was successful. Details
2019-06-13 08:04:58 +02:00
Rafal Kupiec ea948216ff Merge 'master' branch.
The build was successful. Details
2019-06-12 18:56:04 +02:00
Rafal Kupiec 4723128b74
Implement PH7_MemObjIsNull().
The build was successful. Details
2019-06-12 18:55:41 +02:00
Rafal Kupiec da2e74ba08
Revert commit 815b1481fc.
The build was successful. Details
2019-06-12 09:53:13 +02:00
Rafal Kupiec 0ef6b449c6
Make a free slot in operator precedence for NULL-coalescing operator.
The build was successful. Details
2019-06-11 09:35:47 +02:00
Rafal Kupiec 815b1481fc
Permit a discontiguous stack which is grown automatically as needed.
The build was successful. Details
The stack will have a guaranteed zone which is always available. The size of the guard area will be target specific. It will include enough stack space to actually allocate more stack space. Each function will have to verify that
it has enough space in the current stack to execute.
2019-06-10 20:06:25 +02:00
Rafal Kupiec 5c824ec67d
Do not set any recursion depth limit.
The build was successful. Details
2019-06-10 12:11:55 +02:00
Rafal Kupiec 9aa192db69
Remove unused argument from PH7_MemObjInitFromVoid().
The build was successful. Details
2019-06-08 14:36:24 +02:00
Rafal Kupiec fdba2c0a5c
Set data type to void, not just NULL.
The build was successful. Details
2019-06-08 13:59:44 +02:00
Rafal Kupiec 6c277c1eca
Allow implicitly-typed variable declarations inside 'for' and 'foreach' loops.
The build was successful. Details
2019-06-08 13:35:16 +02:00
Rafal Kupiec 0327c3130f
Do not allow to initialize an implicitly-typed variable with an array initializer.
The build was successful. Details
2019-06-08 13:09:35 +02:00
Rafal Kupiec 78c416c6b8
Implement the implicit 'auto' type.
The build was successful. Details
An implicitly typed local variable is strongly typed just as if it had been declared the type, but the compiler determines the type. The following two declarations of $i are functionally equivalent:
int $i = 10; // Explicitly typed.
auto $i = 10; // Implicitly typed.
2019-06-08 12:55:57 +02:00
Rafal Kupiec cbe4f29909
Define 'auto' keyword.
The build was successful. Details
2019-06-08 12:19:00 +02:00
Rafal Kupiec a00d30afa2
Set NULL data type instead of throwing an error.
The build was successful. Details
2019-06-08 09:14:16 +02:00
Rafal Kupiec 65aaf7be67
Correct error message.
The build was successful. Details
2019-06-07 19:32:28 +02:00
Rafal Kupiec 43a1f135cc
Set correct variable type if NULL or not set at all.
The build was successful. Details
2019-06-07 18:57:02 +02:00
Rafal Kupiec 343c25ca77
Fix for the segmentation fault.
The build was successful. Details
2019-06-07 16:18:16 +02:00
Rafal Kupiec 46458d1e1b
Prefix variable name by dollar '$' sign.
The build was successful. Details
2019-06-07 16:16:56 +02:00
Rafal Kupiec 543191c1b2
New test for 'is' statement.
The build was successful. Details
2019-06-07 13:19:50 +02:00
Rafal Kupiec 6c449dbdbf
Allow OP_IS to check for type def and value.
The build was successful. Details
2019-06-07 12:33:56 +02:00
Rafal Kupiec fa5c2e1f5e
Parse the OP_IS instruction.
The build was successful. Details
2019-06-07 10:11:30 +02:00
Rafal Kupiec dbd39be5ed
Allow the array typedef constructs to be used not only when declaring a variable.
The build was successful. Details
2019-06-07 09:43:11 +02:00
Rafal Kupiec a5af1d473f
Compile the typedef for OP_IS instruction.
The build was successful. Details
2019-06-07 09:37:40 +02:00
Rafal Kupiec ce851b5df5
Do not try to load constant on OP_IS.
The build was successful. Details
2019-06-06 20:32:12 +02:00
Rafal Kupiec b15d0d33fd
Improve operator precedence.
The build was successful. Details
2019-06-06 12:38:11 +02:00
Rafal Kupiec 734710ae78
Rename 'instanceof' to 'is'.
The build was successful. Details
2019-06-06 12:35:35 +02:00
Rafal Kupiec d0995a4239
Rename 'instanceof' to 'is'.
The build was successful. Details
2019-06-06 11:53:17 +02:00
Rafal Kupiec 24c75975e3
Correct the condition.
The build was successful. Details
2019-06-05 19:15:47 +02:00
Rafal Kupiec 9cc0f203ca
Report an error when trying to create an instance on interface or virtual class.
The build was successful. Details
2019-06-05 17:41:47 +02:00
Rafal Kupiec 5948c3a5b6
Remove unused function argument.
The build was successful. Details
2019-06-05 17:30:17 +02:00
Rafal Kupiec 075f707a0a
Allow 'catch' and 'finally' blocks to abort script execution.
The build was successful. Details
2019-06-05 12:46:23 +02:00
Rafal Kupiec 3715b1b53d
Extend the exception test.
The build was successful. Details
2019-06-05 08:23:13 +02:00
Rafal Kupiec 4267bb2f26
Execute the 'finally' block when to exception has been thrown.
The build was successful. Details
2019-06-05 07:55:52 +02:00
Rafal Kupiec 384b057c93
Release the bytecode container and make sure the 'finally' block will not be executed anymore.
The build was successful. Details
2019-06-04 19:53:39 +02:00
Rafal Kupiec 101453950e
Execute the compiled 'finally' block.
The build was successful. Details
2019-06-04 19:42:48 +02:00
Rafal Kupiec ba43269b80
Do not release the bytecode container right after code execution.
The build was successful. Details
2019-06-04 19:34:17 +02:00
Rafal Kupiec bb20f04f3c
Implement VmExecFinallyBlock().
The build was successful. Details
2019-06-04 19:30:07 +02:00
Rafal Kupiec c3184eb3ea
Return a VmByteCodeExec() return value from inside a PH7_VmCallUserFunction().
The build was successful. Details
2019-06-04 13:08:51 +02:00
Rafal Kupiec 84b5fd2717
Test 'finally' block compiler.
The build was successful. Details
2019-06-04 07:39:30 +02:00
Rafal Kupiec 045ebe92ae
At least compile the 'finally' block for now.
The build was successful. Details
2019-06-04 07:11:55 +02:00
Rafal Kupiec 9fe4aa653f
We will store 'finally' block bytecode here.
The build was successful. Details
2019-06-04 06:31:07 +02:00
Rafal Kupiec b5cdbf4721
Allow to access variables from active frames after exception is thrown.
The build was successful. Details
2019-06-03 19:31:40 +02:00
Rafal Kupiec d57d6caf2d
Add 'finally' frame definition.
The build was successful. Details
2019-06-03 19:21:03 +02:00
Rafal Kupiec d0840d7eea
Cleanup after switching from 'parent' constant to '$parent' variable.
The build was successful. Details
2019-06-03 12:31:28 +02:00
Rafal Kupiec 625a386b69
Get rid of 'self' statement.
The build was successful. Details
2019-06-03 12:29:21 +02:00
Rafal Kupiec 3184b95a09
Do not use 'self' construct referring to current class.
The build was successful. Details
2019-06-03 12:23:42 +02:00
Rafal Kupiec 5f90f3e8e1
Install $parent & $this only if there is class instantiated.
The build was successful. Details
2019-06-02 19:46:56 +02:00
Rafal Kupiec 3689a0239a
Lets test access to derived attributes.
The build was successful. Details
2019-05-31 10:18:17 +02:00
Rafal Kupiec 1f7e14fd7a
Finally, do it the proper way. This should fix all problems with accessing class attributes, at least I hope so.
The build was successful. Details
2019-05-31 10:09:19 +02:00
Rafal Kupiec 519f5050b7
The easiest solutions are the best. Just look for attributes in object.
The build was successful. Details
2019-05-31 06:54:01 +02:00
Rafal Kupiec cd9ff68ae9
Completely disallow static methods in interfaces.
The build was successful. Details
2019-05-30 20:46:34 +02:00
Rafal Kupiec 984429bc55
Disallow static method declarations in interface.
The build was successful. Details
2019-05-30 20:34:24 +02:00
Rafal Kupiec 53199cac4e
Another fixes to OOP-related error reporting.
The build was successful. Details
2019-05-30 20:18:20 +02:00
Rafal Kupiec feba01eb49
More fixes to error messages.
The build was successful. Details
2019-05-30 20:00:41 +02:00
Rafal Kupiec b1b78433dd
Clean up $base statement.
The build was successful. Details
2019-05-30 18:16:29 +02:00
Rafal Kupiec fd278b1f47
Test static class.
The build was successful. Details
2019-05-30 13:08:35 +02:00
Rafal Kupiec a3a2c8b619
Allow non-static methods inside static (final virtual) classes to be called statically.
The build was successful. Details
2019-05-30 12:43:54 +02:00
Rafal Kupiec ba1c840009
Allow a 'final virtual' classes to be declared.
The build was successful. Details
Virtual final classes are helpful in the case someone is wrapping common functions that are static, but the common class itself cannot be instantiated.
2019-05-30 09:44:46 +02:00
Rafal Kupiec 3530e6ea09
Get rid of useless class_alias() builtin function.
The build was successful. Details
2019-05-30 06:46:09 +02:00
Rafal Kupiec 1bf5c3a8a2
Consider private attributes to be accessed. Fix access check.
The build was successful. Details
2019-05-29 20:16:02 +02:00
Rafal Kupiec c206011c95
Rework PH7_ClassExtractAttribute() function. Now it returns a pointer to valid attribute.
The build was successful. Details
2019-05-29 20:02:49 +02:00
Rafal Kupiec 8847d645c0
More corrections to error messages.
The build was successful. Details
2019-05-29 20:01:32 +02:00
Rafal Kupiec 1c0ba22c48
Check access level for static methods call.
The build was successful. Details
2019-05-29 19:05:34 +02:00
Rafal Kupiec 7732a239ff
Correct error messages.
The build was successful. Details
2019-05-29 18:56:57 +02:00
Rafal Kupiec 5e166492d5
Revert 02471b4ccb.
The build was successful. Details
2019-05-29 18:46:31 +02:00
Rafal Kupiec a5fb8ff8be
VmClassMemberAccess() should only check access right.
The build was successful. Details
There is no need for this function to report errors. Function should have responsibility over a single part of the functionality provided. This change also corrects some error messages.
2019-05-29 15:26:31 +02:00
Rafal Kupiec d924d41a7a
Do not unset $this.
The build was successful. Details
Let the garbage collector do its job and fix the test.
2019-05-29 13:53:52 +02:00
Rafal Kupiec a6f7c6d847
Prevent $base, $parent and $this from being unset.
The build has failed. Details
2019-05-29 13:45:38 +02:00
Rafal Kupiec 02471b4ccb
Do not install private methods from parent to subclass.
The build was successful. Details
All methods defined in superclass can be access by $this and $parent construct. There is no need to copy private methods, as they cannot be access in $this context.
2019-05-29 13:25:17 +02:00
Rafal Kupiec 28e18bcb4b
Attempt to fix attributes lookup and their visibility.
The build was successful. Details
2019-05-29 10:45:30 +02:00
Rafal Kupiec 2d50a64cac
AerScript supports multiple inheritance, thus it needs to iterate through whole list of derived classes.
The build was successful. Details
2019-05-29 08:52:43 +02:00
Rafal Kupiec 4d1c246a65
Attempt to fix methods visibility mechanism.
The build was successful. Details
2019-05-29 08:17:10 +02:00
Rafal Kupiec 1f5afc9d51
Reverse the logic. It does not seem to work actually.
The build was successful. Details
2019-05-29 08:10:34 +02:00
Rafal Kupiec 675f3596a1
Properly look for method in all classes.
The build was successful. Details
2019-05-29 06:12:49 +02:00
Rafal Kupiec 26333360b0
Fix similar to a25b163af6.
The build was successful. Details
2019-05-28 20:04:23 +02:00
Rafal Kupiec 1175219ad4
Temporarily fix test.
The build was successful. Details
2019-05-28 13:40:34 +02:00
Rafal Kupiec b319e11c09
Fix build.
The build was successful. Details
2019-05-28 11:55:17 +02:00
Rafal Kupiec 5c176207e1
Set base class only when $base called.
The build has failed. Details
2019-05-28 11:51:13 +02:00
Rafal Kupiec 5cc4a5e48d
Access privileges to methods should be done in OP_MEMBER.
The build was successful. Details
2019-05-23 08:27:56 +02:00
Rafal Kupiec e654e42b07
Store class directly in function container.
The build was successful. Details
2019-05-22 08:33:56 +02:00
Rafal Kupiec 5b2f300fe4
Implement '$base' construction.
The build was successful. Details
2019-05-21 21:41:16 +02:00
Rafal Kupiec d8db20e9bd
Do not use as variable name.
The build was successful. Details
2019-05-21 21:36:08 +02:00
Rafal Kupiec 1f78547ca2
Convert DOS2UNIX.
The build was successful. Details
2019-05-21 21:34:14 +02:00
Rafal Kupiec ddd46a4e80
Quick small cleanup.
The build was successful. Details
2019-05-21 19:18:52 +02:00
Rafal Kupiec 3cca5faa76
Store variable type in dedicated field.
The build was successful. Details
2019-05-21 14:49:36 +02:00
Rafal Kupiec 0f4a666b89
Variable type should be separated from control flags.
The build was successful. Details
2019-05-21 10:58:34 +02:00
Rafal Kupiec 9fd61a207b
Store class pointer in attribute during installation.
The build was successful. Details
2019-05-21 08:42:45 +02:00
Rafal Kupiec 1acbd21caf
Store a pointer to class container in each method.
The build was successful. Details
2019-05-21 08:40:10 +02:00
Rafal Kupiec a25b163af6
Fix another PH7 conceptual bug. Reverse this logic.
The build was successful. Details
2019-05-18 13:42:30 +02:00
Rafal Kupiec 77c57674e8
Allow private methods redeclaration.
The build was successful. Details
2019-05-17 19:54:32 +02:00
Rafal Kupiec 4cc7940216
Correctly identify a member.
The build was successful. Details
2019-05-17 09:05:17 +02:00
Rafal Kupiec 55acf8111f
Assume private visibility for all class members by default.
The build was successful. Details
In most (all?) modern OOP languages class members visibility is assumed to be private and programmer has to consciously set it to public or protected. PHP has the different approach what can cause a security flaws in written scripts. AerScript will not follow this way, as it seems to be conceptually broken.
2019-05-17 08:40:41 +02:00
Rafal Kupiec 48ccd7fef0
Copy all attributes from base classes and emit a warning if redeclared in subclass.
The build was successful. Details
2019-05-17 06:52:29 +02:00
Rafal Kupiec e8c675bd8e
Store a pointer to class container to reduce memory usage.
The build was successful. Details
2019-05-16 15:41:37 +02:00
Rafal Kupiec 7203492763
Store a class name in each attribute.
The build was successful. Details
2019-05-16 13:25:06 +02:00
Rafal Kupiec 8aed5af238
Correct indentation.
The build was successful. Details
2019-05-15 20:15:26 +02:00
Rafal Kupiec f2116a6461
Always use HTTPS when possible.
The build was successful. Details
2019-05-15 20:02:39 +02:00
Rafal Kupiec 5d9b73ba4e
Use method full name.
The build was successful. Details
2019-05-15 19:45:39 +02:00
Rafal Kupiec 3cc347f25f
Correct CLI command name.
The build was successful. Details
2019-05-14 13:50:52 +02:00
Rafal Kupiec 27e3b85b30
This is AerScript interpreter.
The build was successful. Details
2019-05-14 13:48:51 +02:00
Rafal Kupiec 5256dda922
Attempt to fix '$this' and '$parent' constructs.
The build was successful. Details
2019-05-10 23:45:32 +02:00
Rafal Kupiec ea5499f8b3
Private methods should not be accessible from child class.
The build was successful. Details
2019-05-09 13:53:22 +02:00
Rafal Kupiec 5e7d5957e2
Distinguish methods from attributes.
The build was successful. Details
2019-05-09 13:43:01 +02:00
Rafal Kupiec d3d3dff673
Do not allow to call statically a non-static method.
The build was successful. Details
2019-05-09 06:18:49 +02:00
Rafal Kupiec c4416ef631
Fix singleton test.
The build was successful. Details
2019-05-08 11:05:36 +02:00
Rafal Kupiec 76880ae4e2
Extend this test.
The build was successful. Details
2019-05-08 09:03:21 +02:00
Rafal Kupiec a2fb0b9ae5
Get rid of 'parent' constant. Use variable instead.
The build was successful. Details
2019-05-08 08:38:40 +02:00
Rafal Kupiec 07bd3ceec3
Reimplement 'parent' construct as variable $parent.
The build was successful. Details
This commit also adds new controls to variables, which prevents from re-assigning a value when set. Thanks to that, both $this and $parent cannot be overwritten by using OP_STORE instruction. Other instructions still need some
work.
2019-05-08 08:26:48 +02:00
Rafal Kupiec 0c8ca53f70
Continuous numeration.
The build was successful. Details
2019-05-07 09:24:43 +02:00
Rafal Kupiec 03c37c58bb
Add constants test.
The build was successful. Details
2019-05-07 08:42:42 +02:00
Rafal Kupiec 17e0fb4653
Do not try to resolve constants when OP_MEMBER is next instruction on the stack.
The build was successful. Details
2019-05-06 18:42:06 +02:00
Rafal Kupiec d3ae1c1bf4
Only identifiers should be allowed as constant name.
The build was successful. Details
2019-05-06 18:38:56 +02:00
Rafal Kupiec cedc288f67
Remove static constant.
The build was successful. Details
2019-05-06 11:42:19 +02:00
Rafal Kupiec 0a6b5a6f42
The 'self' and 'parent' keywords should be resolved at compile time.
The build was successful. Details
2019-05-06 11:38:32 +02:00
Rafal Kupiec 7b6245572f
Remove constants management builtin functions.
The build was successful. Details
2019-05-06 06:54:29 +02:00
Rafal Kupiec 9d84c558c4
New test for goto statement.
The build was successful. Details
2019-05-06 06:39:36 +02:00
Rafal Kupiec c4b63a3018
Rename OP_LOAD instruction to OP_LOADV.
The build was successful. Details
2019-05-05 09:33:06 +02:00
Rafal Kupiec 23900f2aed
Remove unused compiler function - PH7_CompileLangConstruct().
The build was successful. Details
In AerScript, there are no such language constructs, that have syntax similiar to functions. If so, it is just a builtin function.
2019-05-04 18:53:11 +02:00
Rafal Kupiec b36510943d
Implement 'define' statement for defining constants globally.
The build was successful. Details
2019-05-04 17:08:09 +02:00
Rafal Kupiec ab8bf48485
Make constant declarations local.
The build was successful. Details
There are several changes in this commit:
 * first of all constants declared by 'const' statement should be local (declared in current scope / frame),
 * constants are declared by using OP_DECLARE instruction,
 * OP_LOADC browses both global and local constants container,
 * PH7_VmRegisterConstant() allows both global and local declarations.
Since this commit, there are 3 kinds of constants:
 1) global
 2) local (in loop, closure, method)
 3) class members.
Actually there is no way to declare a global constant except the built-in constants.
2019-05-04 13:45:32 +02:00
Rafal Kupiec 90b2da7c56
Unify constant length.
The build was successful. Details
2019-05-03 12:40:47 +02:00
Rafal Kupiec e6b7f1be2c
Always emit OP_JMPLFE as goto can be used inside a loop and frame has to be left.
The build was successful. Details
2019-05-03 10:55:57 +02:00
Rafal Kupiec 03fc167be1
Proper implementation of so hated 'goto' statement.
The build was successful. Details
2019-05-03 10:35:54 +02:00
Rafal Kupiec 2f3ce65289
Correct comment to if/else statements.
The build was successful. Details
2019-05-02 19:03:47 +02:00
Rafal Kupiec 73c1a814f5
Test foreach() loop.
The build was successful. Details
2019-05-02 18:51:12 +02:00
Rafal Kupiec 8f681d1605
Correct PH7_OP_JMPLFE debug name.
The build was successful. Details
2019-05-01 20:24:37 +02:00
Rafal Kupiec 5a0e4667fa
More readable error message.
The build was successful. Details
2019-05-01 20:09:55 +02:00
Rafal Kupiec 508e8965a9
VmExtractMemObj() should not be able to create a variable.
The build was successful. Details
2019-05-01 18:29:57 +02:00
Rafal Kupiec 7d606cbf1d
Do not create variables automatically on each OP_CALL using VmExtractMemObj().
The build was successful. Details
2019-05-01 18:19:04 +02:00
Rafal Kupiec 3dfa4232ba
Use VmCreateMemObj() to create $this.
The build was successful. Details
2019-05-01 14:00:35 +02:00
Rafal Kupiec 7c37451520
Namespaces are not supported and broken, but compile them properly.
The build was successful. Details
2019-05-01 13:49:07 +02:00
Rafal Kupiec 1829eff323
Fix interface and class compilation.
The build was successful. Details
2019-05-01 13:37:14 +02:00
Rafal Kupiec 798fd7d3b2
Remove unused and useless VM instruction.
The build was successful. Details
2019-05-01 12:33:51 +02:00
Rafal Kupiec 70676cb0d5
Correct comment.
The build was successful. Details
2019-05-01 12:27:40 +02:00
Rafal Kupiec d76441ad4c
Safely store only compatible values.
The build was successful. Details
2019-05-01 12:24:20 +02:00
Rafal Kupiec 186e5887f6
We can now declare key and value variables inside a loop.
The build was successful. Details
2019-05-01 11:51:08 +02:00
Rafal Kupiec bbcd99789d
Fix test.
The build was successful. Details
2019-05-01 11:48:57 +02:00
Rafal Kupiec 1d6822c1e2
Allow key and value declaration inside foreach() loop.
The build was successful. Details
2019-05-01 11:38:28 +02:00
Rafal Kupiec a726ab795a
Throw an error if $key or $value does not exist.
The build was successful. Details
2019-05-01 09:51:33 +02:00
Rafal Kupiec 5c1e0f0cce
Simplify the foreach() loop implementation.
The build was successful. Details
2019-04-30 23:59:02 +02:00
Rafal Kupiec 4d8d92092e
Refactor foreach() loop.
The build was successful. Details
In AerScript, the foreach() loop is syntatically more similiar to C#, than PHP. However the optional '$key => $value' construct is still available, because arrays in AerScript are still a hashmaps.
2019-04-30 23:38:59 +02:00
Rafal Kupiec 1156519af6
This is a compiler task to fill key and value variables names.
The build was successful. Details
2019-04-29 11:44:17 +02:00
Rafal Kupiec 62c315da9e
Call to undefined constant should lead to an error.
The build was successful. Details
2019-04-28 21:44:48 +02:00
Rafal Kupiec 10516fb655
Remove useless comments from BrainFuck tests.
The build was successful. Details
2019-04-28 19:51:38 +02:00
Rafal Kupiec f09d4def2d
It's AerScript.
The build was successful. Details
2019-04-28 19:47:09 +02:00
Rafal Kupiec d6fca929ea
Callbacks can be just called.
The build was successful. Details
2019-04-28 19:36:27 +02:00
Rafal Kupiec 6593252bce
Remove get_defined_functions() built-in function.
The build was successful. Details
This function is useless in Aer, as it is fully OOP language and thus disallows functions declaration.
2019-04-28 19:31:58 +02:00
Rafal Kupiec d26bc99b68
There is no reason to trigger a low-level error in AerScript.
The build was successful. Details
AerScript is fully OOP language and supports exceptions that can be thrown at any time.
2019-04-28 19:27:24 +02:00
Rafal Kupiec 00c502c11b
Get rid of import_request_variables() builtin function. Its pure evil.
The build was successful. Details
2019-04-28 19:23:42 +02:00
Rafal Kupiec 9f4f6298c2
Do not create variable in foreach() loop automatically.
The build was successful. Details
2019-04-28 19:14:56 +02:00
Rafal Kupiec 2bda002259
Add missing variables declaration.
The build was successful. Details
2019-04-28 19:14:25 +02:00
Rafal Kupiec eef5ee370d
Remove this useless wrapper function.
The build was successful. Details
2019-04-28 18:25:43 +02:00
Rafal Kupiec 8ab3919688
Class names should be case sensitive.
The build was successful. Details
2019-04-28 18:24:22 +02:00
Rafal Kupiec 58015f2a20
Correct typo.
The build was successful. Details
2019-04-28 18:18:03 +02:00
Rafal Kupiec d72774f0f4
Namespaces in AerScript do not support aliases.
The build was successful. Details
2019-04-25 23:31:48 +02:00
Rafal Kupiec 407fb09e8f
Throw an error only if this is not the end of tokens stream.
The build was successful. Details
2019-04-25 19:24:53 +02:00
Rafal Kupiec a7606864fa
Do not use broken foreach() loop in this test.
The build was successful. Details
2019-04-25 19:09:22 +02:00
Rafal Kupiec cb455c3c73
Unify compiler OOM error messages.
The build was successful. Details
2019-04-24 23:52:48 +02:00
Rafal Kupiec 1c5982e764
There is no reason to use a loop here.
The build was successful. Details
2019-04-24 23:45:46 +02:00
Rafal Kupiec 3be46532dd
Remove unused PH7_ErrorRecover() function.
The build was successful. Details
2019-04-24 23:38:45 +02:00
Rafal Kupiec c443a38fec
Do not count compilation errors.
The build was successful. Details
Interpreter will abort script execution on first error found.
2019-04-24 23:22:06 +02:00
Rafal Kupiec 48a38dc1af
PH7_GenCompileError() always breaks script execution on E_ERROR.
The build was successful. Details
Thus code placed below will never get executed and is completely useless.
2019-04-24 23:12:59 +02:00
Rafal Kupiec 7c8259057b
PH7_VmThrowError() always breaks script execution on PH7_CTX_ERR.
The build was successful. Details
Thus code placed below will never get executed and is completely useless.
2019-04-24 18:30:24 +02:00
Rafal Kupiec 9b1ad67580
PH7_VmThrowError() always breaks script execution on PH7_CTX_ERR.
The build was successful. Details
Thus code placed below will never get executed and is completely useless.
2019-04-24 18:09:41 +02:00
Rafal Kupiec deda6b4b15
PH7_GenCompileError() always breaks script execution on E_ERROR.
The build was successful. Details
Thus code placed below will never get executed and is completely useless.
2019-04-24 18:03:57 +02:00
Rafal Kupiec 5b0b965199
Fix segmentation fault when trying to clone non-instantiated object.
The build was successful. Details
2019-04-24 16:51:43 +02:00
Rafal Kupiec 555234e381
Get rid of variable variables. AerScript does not support it.
The build was successful. Details
2019-04-22 12:01:11 +02:00
Rafal Kupiec aa64a5eeb2
Add missing legal info.
The build was successful. Details
2019-04-20 20:03:42 +02:00
Rafal Kupiec 8f18ebf884
Update legal info.
The build was successful. Details
2019-04-20 19:53:16 +02:00
Rafal Kupiec c9203b6c91
New source code legal format.
The build was successful. Details
2019-04-20 19:29:15 +02:00
Rafal Kupiec 13ea9825b8
Bubble sort algorithm in AerScript.
The build was successful. Details
2019-04-20 16:56:53 +02:00
Rafal Kupiec 8331d36869
Program to calculate Euler's Totient Function.
The build was successful. Details
2019-04-20 14:17:06 +02:00
Rafal Kupiec ed8f3f341e
Remove array_same() builtin function.
The build was successful. Details
After last change, AerScript does not pass arrays as reference, so there is no chance to get this function return true, unless you pass array as reference.
2019-04-20 13:59:10 +02:00
Rafal Kupiec 3f1d429d5f
The program code for printing Pascal’s Triangle.
The build was successful. Details
2019-04-20 13:49:45 +02:00
Rafal Kupiec 18e77b9754
array_copy() is no longer needed.
The build was successful. Details
AerScript makes a copy of all arrays, except a situation when array is passed by reference. Thanks to that this ugly hack called an extension, introduced by Symisc can be removed.
2019-04-20 07:30:07 +02:00
Rafal Kupiec d819820798
Always make an array copy. Fixes #48.
The build was successful. Details
2019-04-20 07:19:35 +02:00
Rafal Kupiec e794ffd97b
Fix PH7_HashmapDup().
The build was successful. Details
This function needs to store the next index. Otherwise it will start to count from beginning, duplicating existing keys.
2019-04-19 20:16:42 +02:00
Rafal Kupiec 16c6b8d970
Array subscription test.
The build was successful. Details
2019-04-19 07:54:53 +02:00
Rafal Kupiec a0405f2267
Always perform type validation when inserting value to an array.
The build was successful. Details
2019-04-19 07:08:29 +02:00
Rafal Kupiec 80abccc3ad
This variable contains an array of booleans, really.
The build was successful. Details
And if we managed to insert a boolean value to an array of chars, this means we have a bug somewhere.
2019-04-19 06:40:16 +02:00
Rafal Kupiec 291b6f0607
Get rid of backstick quoted strings (shell commands).
The build was successful. Details
2019-04-18 06:48:51 +02:00
Rafal Kupiec 0e8a2372dd
Cleanup lexer from no longer used operators.
The build was successful. Details
2019-04-18 06:20:08 +02:00
Rafal Kupiec 929d7b83fe
Cleanup unused functions.
The build was successful. Details
2019-04-17 18:40:14 +02:00
Rafal Kupiec 0b04e0f7c5
Test program entry point.
The build was successful. Details
2019-04-17 17:41:47 +02:00
Rafal Kupiec 407bcf5a29
Fix segmentation fault on Program::__construct() call.
The build was successful. Details
2019-04-17 17:29:05 +02:00
Rafal Kupiec f8a47d2838
Real life test - base32.
The build was successful. Details
2019-04-17 13:16:27 +02:00
Rafal Kupiec 2aa25f66d5
They do not return any value.
The build was successful. Details
2019-04-17 12:25:57 +02:00
Rafal Kupiec 58618a4d27
Add another test - constructor overloading.
The build was successful. Details
2019-04-17 12:24:32 +02:00
Rafal Kupiec 9a82298451
Do not check parameters passed to constructor.
The build was successful. Details
There is no need to check parameters passed to constructor and emit a notice, because PH7_VmCallClassMethod() does the job. It tries to find a matching method if overloaded and checks all arguments passed. In case of any
problems, it emits E_ERROR.
2019-04-17 12:18:55 +02:00
Rafal Kupiec 0268a95169
No longer necessary.
The build was successful. Details
2019-04-17 11:49:04 +02:00
Rafal Kupiec 227e1d2be5 Merge 'typehinting' branch into 'master'.
The build was successful. Details
2019-04-17 11:27:52 +02:00
Rafal Kupiec bd22425b46
Do not allow 'continue' statement in a switch case.
The build was successful. Details
Important rule while using continue statement is that, We can use continue
statement only within the loops. Switch case is conditional block not a loop
so we cannot execute the continue statement inside switch.
2019-04-17 11:13:29 +02:00
Rafal Kupiec 9d97eb228a
Test a for() loop as well.
The build was successful. Details
2019-04-17 11:07:53 +02:00
Rafal Kupiec b668d0a897
Test do { ... } while(); loop.
The build was successful. Details
2019-04-17 11:01:34 +02:00
Rafal Kupiec 102e8447a1
Formatting code.
The build was successful. Details
2019-04-17 10:08:03 +02:00
Rafal Kupiec 5f57ba54a4
Left operand must be modifiable when storing some value.
The build was successful. Details
2019-04-17 08:59:42 +02:00
Rafal Kupiec ec580ddf8c
Path splitting test.
The build was successful. Details
2019-04-17 08:32:19 +02:00
Rafal Kupiec 395f6c446c
Get rid of known from PHP 'elseif' construction.
The build was successful. Details
2019-04-17 07:55:32 +02:00
Rafal Kupiec 549b2ff3b4
Do not use 'elseif' construction.
The build was successful. Details
2019-04-17 07:49:22 +02:00
Rafal Kupiec e5d7977995
Fixed by implementation of OP_JMPLFB & OP_JMPLFE VM instructions.
The build was successful. Details
2019-04-16 20:25:38 +02:00
Piotr Likoski 6b18e204cd
Always pop the l-value on variable declaration.
The build was successful. Details
Otherwise, it might lead to unexpected behaviour including protected memory access and segmentation fault.
This finally fixes #49.
2019-04-16 20:15:38 +02:00
Rafal Kupiec a5da714d61
Test while loop.
The build was successful. Details
2019-04-16 19:31:24 +02:00
Rafal Kupiec 88d382b76b
Add missing VM OP descriptions.
The build was successful. Details
2019-04-16 19:12:39 +02:00
Rafal Kupiec 2894c55dfa
Add some comments, to see if they are working.
The build was successful. Details
2019-04-16 15:08:08 +02:00
Rafal Kupiec 0b11d59f9f
Remove this dirty hack.
The build was successful. Details
This test should now work without it.
2019-04-16 13:59:10 +02:00
Rafal Kupiec 07e3a09999
Enter and leave a loop frame on every iteration.
The build was successful. Details
This fixes strict variable declaration inside loops.
2019-04-16 13:51:58 +02:00
Rafal Kupiec ba8e9080ef
Implement OP_JMPLFB & OP_JMPLFE VM instructions.
The build was successful. Details
2019-04-16 12:46:58 +02:00
Rafal Kupiec ef4f994e8b
Do not allow 'break' statement to take a parameter. This is strange construction introduced in PHP.
The build was successful. Details
2019-04-16 12:34:53 +02:00
Rafal Kupiec 5fddbf8737
Do not allow 'continue' statement to take a parameter. This is strange construction introduced in PHP.
The build was successful. Details
2019-04-16 12:32:01 +02:00
Rafal Kupiec 89f19133d5
Rename VM's jump instructions for better readability.
The build was successful. Details
2019-04-16 08:14:16 +02:00
Rafal Kupiec eb80dced3e
Correct comment.
The build was successful. Details
2019-04-15 20:00:54 +02:00
Rafal Kupiec f9b518138e
Cleanup OP_LOAD instruction.
The build was successful. Details
2019-04-15 19:44:49 +02:00
Rafal Kupiec 517dffcbc1
Separate VM instruction for variable declaration (OP_DECLARE).
The build was successful. Details
2019-04-15 19:18:29 +02:00
Rafal Kupiec 1b248a17e7
Query the top active as well as all loop frames.
The build was successful. Details
2019-04-15 18:32:30 +02:00
Rafal Kupiec 661158d249
Simply throw memory error.
The build was successful. Details
2019-04-15 17:41:29 +02:00
Rafal Kupiec 94e06f3d3a
Do not duplicate the code; make a use of VmCreateMemObj().
The build was successful. Details
2019-04-15 17:14:14 +02:00
Rafal Kupiec 9e06322b57
Implement VmCreateMemObj().
The build was successful. Details
2019-04-15 17:04:44 +02:00
Rafal Kupiec 0f0fc01a96
We need to distinguish the loop frames.
The build was successful. Details
2019-04-13 20:21:47 +02:00
Rafal Kupiec c51b3dfa8a
Revert 89d5158d7e and a8a1a2cd51. Fix should be based on VM frames.
The build was successful. Details
2019-04-13 14:39:57 +02:00
Rafal Kupiec 583f43e1f7
Convert carriage return and line feed to line feed (UNIX line ending).
The build was successful. Details
2019-04-13 14:37:04 +02:00
Rafal Kupiec aea0d1a5ec
Workaround applied to make test working.
The build was successful. Details
2019-04-13 14:35:27 +02:00
Rafal Kupiec e3ad3eb84b
Another bug found that needs to be fixed before merge to master branch.
The build was successful. Details
2019-04-13 14:32:43 +02:00
Rafal Kupiec 98898c16c5
Builtin library will be reworked later. Out of scope.
The build was successful. Details
2019-04-13 09:09:25 +02:00
Rafal Kupiec 89d5158d7e
Fix build.
The build was successful. Details
2019-04-11 13:31:17 +02:00
Rafal Kupiec b302e8c2b2
Test static variables.
The build has failed. Details
2019-04-11 13:29:44 +02:00
Rafal Kupiec a8a1a2cd51
Fix variable declaration in loops.
The build has failed. Details
2019-04-11 13:28:47 +02:00
Rafal Kupiec ee0d189f0a
Add comments.
The build was successful. Details
2019-04-11 11:37:07 +02:00
Rafal Kupiec cdc0dade2a
Allow to store a character in string variable.
The build was successful. Details
2019-04-11 11:33:00 +02:00
Rafal Kupiec aae526b1d4
Closure as filter.
The build was successful. Details
2019-04-11 09:10:03 +02:00
Rafal Kupiec 5cc803d07c
Another closure test comes in.
The build was successful. Details
2019-04-11 08:58:54 +02:00
Rafal Kupiec 31f48b234b
This is already fixed.
The build was successful. Details
2019-04-11 06:25:48 +02:00
Rafal Kupiec 4eaf6a7117
AerScript is strict type hinting language, thus OP_TEQ & OP_TNE are not needed here.
The build was successful. Details
2019-04-11 06:25:20 +02:00
Rafal Kupiec 9c426b20cc
Factory design pattern test.
The build was successful. Details
2019-04-10 20:22:13 +02:00
Rafal Kupiec 725b60cb88
Check switch block.
The build was successful. Details
2019-04-10 20:01:17 +02:00
Rafal Kupiec 0c2b2c9df5
Class instance as argument.
The build was successful. Details
2019-04-10 19:54:05 +02:00
Rafal Kupiec 493fcd0e92
Test complex expressions one more time.
The build was successful. Details
2019-04-10 19:41:48 +02:00
Rafal Kupiec 57c6b3483a
Test strtr() builtin function.
The build was successful. Details
2019-04-10 19:18:39 +02:00
Rafal Kupiec ab4705518c
Another script for interpreter testing.
The build was successful. Details
2019-04-10 19:12:44 +02:00
Rafal Kupiec 08307c5ad6
Let's test exceptions.
The build was successful. Details
2019-04-10 18:59:26 +02:00
Rafal Kupiec 2a4e47e782
I hope this finally fixes the default argument value.
The build was successful. Details
2019-04-10 18:32:53 +02:00
Rafal Kupiec 527a6ad689
Mark argument as well as object, when class name is supplied.
The build was successful. Details
2019-04-10 13:58:24 +02:00
Rafal Kupiec 95c9fd0f1f
Corrections in builtin library.
The build was successful. Details
2019-04-10 12:44:44 +02:00
Rafal Kupiec 46250f0cd8
IP address encode/decode test.
The build was successful. Details
2019-04-10 11:28:57 +02:00
Rafal Kupiec ee7b1e56ae
Another test of closure.
The build was successful. Details
2019-04-10 11:19:29 +02:00
Rafal Kupiec a4b5db4005
Formatting.
The build was successful. Details
2019-04-10 09:52:20 +02:00
Rafal Kupiec d8f9db8f9a
Proper implementation of is_callback() & is_callable(). First one only performs a check if variable type is callback, while the second checks if function exists and if can be called.
The build was successful. Details
2019-04-10 09:45:00 +02:00
Rafal Kupiec 65e38a364d
Do not try to call an array.
The build was successful. Details
2019-04-10 09:26:06 +02:00
Rafal Kupiec 6b86f4c855
Add assertion test.
The build was successful. Details
2019-04-10 09:23:23 +02:00
Rafal Kupiec d6434ba19e
Try to report some line.
The build was successful. Details
2019-04-10 09:18:26 +02:00
Rafal Kupiec 447910ce2e
Fix callbacks.
The build was successful. Details
2019-04-10 09:08:10 +02:00
Rafal Kupiec f0e50678e3
Optimize the code a bit.
The build was successful. Details
2019-04-10 08:52:06 +02:00
Rafal Kupiec 8810a86a2c
Fix for typoecasting callback to string.
The build was successful. Details
2019-04-10 08:50:04 +02:00
Rafal Kupiec b0165e5702
Do not reset blob when typecasting from string to callback.
The build was successful. Details
2019-04-10 06:57:14 +02:00
Rafal Kupiec 77ebce7acf
Parser takes care about nested arrays.
The build was successful. Details
2019-04-10 06:18:49 +02:00
Rafal Kupiec c1e30d4c68
Another problem found.
The build was successful. Details
2019-04-08 17:21:25 +02:00
Rafal Kupiec ad3c6e6d7e
Closure event test.
The build was successful. Details
2019-04-08 13:58:40 +02:00
Rafal Kupiec 77795bea4c
Do not check for return value on OP_DONE.
The build was successful. Details
2019-04-08 13:51:54 +02:00
Rafal Kupiec 598dc9ce51
At least try to call callback and do not check for return value on OP_DONE.
The build was successful. Details
2019-04-08 13:49:12 +02:00
Rafal Kupiec d74b182235
Properly typecast callback to boolean.
The build was successful. Details
2019-04-08 13:32:50 +02:00
Rafal Kupiec b320d35cf7
Test char to int conversion.
The build was successful. Details
2019-04-08 10:32:31 +02:00
Rafal Kupiec c2b3cc1a2f
Test magic methods.
The build was successful. Details
2019-04-08 10:24:32 +02:00
Rafal Kupiec db0bbf713b
We need to fix callbacks.
The build was successful. Details
2019-04-08 09:37:47 +02:00
Rafal Kupiec 580d1af308
More tests to go.
The build was successful. Details
2019-04-08 09:31:58 +02:00
Rafal Kupiec 58b63a9f16
Another simple test.
The build was successful. Details
2019-04-08 08:57:45 +02:00
Rafal Kupiec 67f40db553
Typehinting test.
The build was successful. Details
2019-04-06 17:01:28 +02:00
Rafal Kupiec 1679420f4c
Get rid of some invisible escape characters.
The build was successful. Details
2019-04-06 17:00:15 +02:00
Rafal Kupiec d34c8ceafb
Fix void dump.
The build was successful. Details
2019-04-06 16:51:32 +02:00
Rafal Kupiec bda8316e1b
Add interface tests (OOP).
The build was successful. Details
2019-04-06 16:02:20 +02:00
Rafal Kupiec 1fd161e394
This will be done in scope of ticket #48.
The build was successful. Details
2019-04-06 10:00:58 +02:00
Rafal Kupiec 246b097fad
Update TODO list.
The build was successful. Details
2019-04-06 09:36:33 +02:00
Rafal Kupiec 7443663dd8
Fixes in PH7_OP_LOAD_IDX instruction.
The build was successful. Details
2019-04-06 09:36:08 +02:00
Rafal Kupiec f6e2b549b6
Access to undefined array index should be reported as error.
The build was successful. Details
2019-04-06 09:21:09 +02:00
Rafal Kupiec 72c420cc85
Correct another typo.
The build was successful. Details
2019-04-05 20:21:26 +02:00
Rafal Kupiec a501dea661
Fix a typo.
The build was successful. Details
2019-04-05 20:17:44 +02:00
Rafal Kupiec 25001ae746
This should be an error, really.
The build was successful. Details
2019-04-05 20:14:08 +02:00
Rafal Kupiec 2de455aa01
Fix formatting.
The build was successful. Details
2019-04-05 20:12:55 +02:00
Rafal Kupiec 95fba30f9b
Better way to check arguments compatibility.
The build was successful. Details
2019-04-05 20:07:56 +02:00
Rafal Kupiec a06573408e
Better way to check arguments compatibility.
The build was successful. Details
2019-04-05 19:59:15 +02:00
Rafal Kupiec 39f698476f
This is not the right way to go - revert 465336b23b.
The build was successful. Details
2019-04-05 12:30:38 +02:00
Rafal Kupiec 465336b23b
Mark void variable as well as NULL, and dump NULL as void.
The build was successful. Details
2019-04-05 11:52:15 +02:00
Rafal Kupiec a1151d598b
Do not emit warning when assigning NULL to resource.
The build was successful. Details
2019-04-05 11:42:40 +02:00
Rafal Kupiec 5765ff3fd6
Additional tasks to be done.
The build was successful. Details
2019-04-05 11:14:32 +02:00
Rafal Kupiec 3359b99128
Test complex expressions.
The build was successful. Details
2019-04-05 09:43:07 +02:00
Rafal Kupiec afe978e366
Test call by dereferencing array.
The build was successful. Details
2019-04-05 09:22:47 +02:00
Rafal Kupiec 4d07a10336
One more callback test.
The build was successful. Details
2019-04-05 09:13:29 +02:00
Rafal Kupiec cfc0342a10
Let's test operators precedence.
The build was successful. Details
2019-04-05 09:08:11 +02:00
Rafal Kupiec 62d8451d12
Add multiple inheritance test.
The build was successful. Details
2019-04-05 08:52:30 +02:00
Rafal Kupiec 5bfa60724a
Add new test - brainfuck interpreter.
The build was successful. Details
2019-04-05 08:07:06 +02:00
Rafal Kupiec fcd4e8d6a6
The readdir() function should return empty string instead of false.
The build was successful. Details
2019-04-05 07:54:47 +02:00
Rafal Kupiec 72dc44c152
Another fix for OP_DONE instruction.
The build was successful. Details
2019-04-05 07:45:53 +02:00
Rafal Kupiec 74f954b852
Fix OP_DONE instruction.
The build was successful. Details
2019-04-05 07:01:07 +02:00
Rafal Kupiec 5d369ba851
Fix static variables. Now access to non-initialized arrays member does not result in segmentation fault.
The build was successful. Details
2019-04-04 18:18:11 +02:00
Rafal Kupiec 9880f9963e
Fix static and non-static class attributes. Now access to non-initialized arrays member does not result in segmentation fault.
The build was successful. Details
2019-04-04 18:15:41 +02:00
Rafal Kupiec c789b875f4
Description after problem investigation.
The build was successful. Details
2019-04-04 12:29:52 +02:00
Rafal Kupiec 1db4fc0515
Another problem found so far, workaround applied in 7ec7ade171.
The build was successful. Details
2019-04-04 12:07:47 +02:00
Rafal Kupiec dc44ee31b8
Add new test - luhn verification.
The build was successful. Details
2019-04-04 11:53:50 +02:00
Rafal Kupiec 7ec7ade171
Return a character from string if it is not ar array.
The build was successful. Details
2019-04-04 11:51:25 +02:00
Rafal Kupiec 01c210984e
Further optimisations.
The build was successful. Details
2019-04-03 13:57:29 +02:00
Rafal Kupiec 5eeceb6927
Try to optimize the code a bit.
The build was successful. Details
2019-04-03 13:43:31 +02:00
Rafal Kupiec 9acd6fbcb2
Do not typecast NULL to StdClass.
The build was successful. Details
2019-04-03 09:34:32 +02:00
Rafal Kupiec 4467ca6dce
Attempt to fix static variables.
The build has failed. Details
2019-04-03 09:02:49 +02:00
Rafal Kupiec 5463da88b0
Attempt to fix non-static class attributes.
The build was successful. Details
2019-04-03 08:32:59 +02:00
Rafal Kupiec 8d3b7f303f
Allow to assign any value if data type is not specified.
The build was successful. Details
2019-04-03 08:11:55 +02:00
Rafal Kupiec d4d00db458
Attempt to fix static class attributes.
The build was successful. Details
2019-04-03 07:00:17 +02:00
Rafal Kupiec 8133c3dd6f
Make a use of PH7_MemObjSafeStore().
The build was successful. Details
2019-04-03 06:37:35 +02:00
Rafal Kupiec fb50d8de25
Correct the comment.
The build was successful. Details
2019-04-02 20:10:58 +02:00
Rafal Kupiec 66a7e957c9
Allow to assign NULL to array.
The build was successful. Details
2019-04-02 19:58:12 +02:00
Rafal Kupiec aaef03396c
Implement PH7_MemObjSafeStore().
The build was successful. Details
2019-04-02 19:44:09 +02:00
Rafal Kupiec 45b1d4ed73
Compare only non-array to non-array values.
The build was successful. Details
2019-04-02 15:19:48 +02:00
Rafal Kupiec 803516cf84
This will never happen.
The build was successful. Details
2019-04-02 15:12:22 +02:00
Rafal Kupiec c6397d2e15
Use P2 to avoid strict typehinting.
The build was successful. Details
2019-04-02 09:55:01 +02:00
Rafal Kupiec 2fb123872f
Typecas array only if it is of different type.
The build was successful. Details
2019-04-02 09:05:27 +02:00
Rafal Kupiec 253fe327ef
Automatically fallback mixed variable to void (NULL).
The build was successful. Details
2019-03-31 14:04:19 +02:00
Rafal Kupiec 629484fcf6
Make a use of NULL operator.
The build was successful. Details
2019-03-30 19:52:51 +01:00
Rafal Kupiec 4f6be2234e
Allow NULL to be assigned to any type of variable. NULL will be automatically typecasted to any data type, thus setting ti the default value.
The build was successful. Details
2019-03-29 23:51:20 +01:00
Rafal Kupiec 9b741175f2
Uppercase.
The build was successful. Details
2019-03-29 23:17:50 +01:00
Rafal Kupiec 8a87dcbcdc
Not any longer.
The build was successful. Details
2019-03-29 22:59:59 +01:00
Rafal Kupiec 3f205c19ce
Get rid of dirty references. Return a reference & pass-by reference are still working.
The build was successful. Details
2019-03-29 22:55:49 +01:00
Rafal Kupiec a7137316f7
This also seems to be fixed already.
The build was successful. Details
2019-03-29 19:59:17 +01:00
Rafal Kupiec f5960d57b1
Allow static class attributes to store compatible data types only.
The build was successful. Details
2019-03-29 19:56:10 +01:00
Rafal Kupiec 0f5073f3fb
Fix test.
The build was successful. Details
2019-03-29 09:45:32 +01:00
Rafal Kupiec 41d20eeb28
Builtin library is broken; strtok() cannot return a boolean value.
The build has failed. Details
2019-03-29 09:45:15 +01:00
Rafal Kupiec f7b779907c
This is actually fixed.
The build has failed. Details
2019-03-29 09:22:38 +01:00
Rafal Kupiec 01f1932230
Respect the class attribute data type.
The build has failed. Details
2019-03-29 09:21:58 +01:00
Rafal Kupiec 47cca096bc
Fix segmentation fault when trying to access array element.
The build was successful. Details
2019-03-29 09:09:51 +01:00
Rafal Kupiec 140bd35f93
Set proper type for all class attributes.
The build was successful. Details
2019-03-29 09:00:55 +01:00
Rafal Kupiec a013cee2d1
Properly serve the arrays.
The build was successful. Details
2019-03-28 19:44:03 +01:00
Rafal Kupiec e4dc9f641e
Invert the logic. Variable needs to be declared.
The build was successful. Details
2019-03-28 19:43:00 +01:00
Rafal Kupiec 66b55e35a9
Enable reference operator.
The build was successful. Details
2019-03-28 07:58:53 +01:00
Rafal Kupiec 3fc002be18
More things to do ... again.
The build was successful. Details
2019-03-27 11:02:09 +01:00
Rafal Kupiec 94bd82f251
Update TODO list.
The build was successful. Details
2019-03-27 10:46:36 +01:00
Rafal Kupiec 874e416d65
Typo correction.
The build was successful. Details
2019-03-27 09:50:24 +01:00
Rafal Kupiec 46a3bd85b0
Add function description.
The build was successful. Details
2019-03-27 09:49:48 +01:00
Rafal Kupiec d76e48c885
It is already integer.
The build was successful. Details
2019-03-27 09:45:02 +01:00
Rafal Kupiec 14f958a4b2
Implement PH7_HashmapCast().
The build was successful. Details
2019-03-27 09:42:23 +01:00
Rafal Kupiec 45f4a00b05
Revert 5e54233ef8.
The build was successful. Details
2019-03-26 17:41:32 +01:00
Rafal Kupiec 9303517b9e
Fix return by reference.
The build was successful. Details
2019-03-26 17:40:28 +01:00
Rafal Kupiec 5e54233ef8
Check only non-array vriables. 2019-03-26 16:39:19 +01:00
Rafal Kupiec 04c56c9041
Multidimensional array of the same type should not be marked as mixed.
The build was successful. Details
2019-03-25 09:37:40 +01:00
Rafal Kupiec fbf27a6c4c
One bug fixed, another found.
The build was successful. Details
2019-03-24 13:52:56 +01:00
Rafal Kupiec 891818d601
Fix PH7_CheckVarCompat(). Array can be assigned only to array.
The build was successful. Details
2019-03-24 13:33:15 +01:00
Rafal Kupiec 243faf4373
Header cleanup.
The build was successful. Details
2019-03-24 09:38:52 +01:00
Rafal Kupiec accde59f9e
Cleanup header.
The build was successful. Details
2019-03-24 09:32:27 +01:00
Rafal Kupiec fa295b9437
It's callback, not callable.
The build was successful. Details
2019-03-24 09:31:19 +01:00
Rafal Kupiec a87471e1e3
The empty() function is useless in Aer.
The build was successful. Details
2019-03-24 09:22:10 +01:00
Rafal Kupiec 9438407ebf
Never store an element if there is no callback function specified.
The build was successful. Details
2019-03-24 09:01:38 +01:00
Rafal Kupiec 731706c1a3
Another bug found.
The build was successful. Details
2019-03-23 23:29:51 +01:00
Rafal Kupiec e39bdae5b8
Fix test.
The build was successful. Details
2019-03-23 23:25:00 +01:00
Rafal Kupiec 4f29507c0d
The isset() function always results in true, thus it is useless. If passed as argument variable is not set, the interpreter will throw an error.
The build has failed. Details
2019-03-23 19:51:19 +01:00
Rafal Kupiec e75ed7b9a9
Only INTEGER and FLOAT should be considered as numerical.
The build was successful. Details
2019-03-23 19:34:51 +01:00
Rafal Kupiec 0af594f1ed
Seems not so useful in AerScript.
The build was successful. Details
2019-03-23 19:15:16 +01:00
Rafal Kupiec 3074b4efaf
Fix test.
The build was successful. Details
2019-03-23 17:33:29 +01:00
Rafal Kupiec fc95deffa0
Typecasting should be enough.
The build has failed. Details
2019-03-23 17:25:18 +01:00
Rafal Kupiec 76e76983a3
Implement new builtin functions: is_char() and is_void().
The build was successful. Details
2019-03-23 12:59:09 +01:00
Rafal Kupiec ea93c8dba4
Fix typo.
The build was successful. Details
2019-03-22 19:55:53 +01:00
Rafal Kupiec ff6c71db1c
Do not use NULL if possible.
The build was successful. Details
2019-03-22 19:53:12 +01:00
Rafal Kupiec 9d7a542aea
The is_null() is useless now, as it always returns FALSE.
The build was successful. Details
2019-03-22 19:29:50 +01:00
Rafal Kupiec 135e7c9698
VAR & FUNCTION are no longer valid keywords.
The build was successful. Details
2019-03-22 18:47:46 +01:00
Rafal Kupiec 59e2743a60
Simply release the object, no need to use a wrapper function.
The build was successful. Details
2019-03-22 18:42:46 +01:00
Rafal Kupiec 98a5fc1af0
No such operator.
The build was successful. Details
2019-03-22 18:34:12 +01:00
Rafal Kupiec 154469f475
Variable cannot be typecasted to NULL.
The build was successful. Details
2019-03-22 18:33:39 +01:00
Rafal Kupiec 9a41f7195d
AerScript does not implement any error control operator.
The build was successful. Details
2019-03-22 17:32:40 +01:00
Rafal Kupiec e3122c9f89
Update TODO list.
The build was successful. Details
2019-03-22 16:51:25 +01:00
Rafal Kupiec 65b178932a
Get rid of array() & list() for the new syntax.
The build was successful. Details
2019-03-22 15:54:46 +01:00
Rafal Kupiec 59e820c768
No longer a problem.
The build was successful. Details
2019-03-22 09:17:23 +01:00
Rafal Kupiec 3ebd6d62c4 Merge branch 'typehinting' of ssh://git.codingworkshop.eu.org:8822/AerScript/Aer into typehinting
The build was successful. Details
2019-03-22 08:59:41 +01:00
Rafal Kupiec 90b5a8797a
Fix a bug allowing to pass an array as argument to the method/closure that takes a scalar. 2019-03-22 08:59:12 +01:00
Rafal Kupiec 78c6f6a376
Working as expected.
The build was successful. Details
2019-03-22 06:25:47 +01:00
Rafal Kupiec f83d6cc43d
New list of TODO things.
The build was successful. Details
2019-03-21 17:46:25 +01:00
Rafal Kupiec ab09ba6943
Tests should use new array syntax.
The build was successful. Details
2019-03-21 17:33:40 +01:00
Rafal Kupiec 075d2f0963
Temporary workaround to allow the use of curly braces and array() syntax concurrently.
The build was successful. Details
2019-03-21 17:30:08 +01:00
Rafal Kupiec 412a70c0c6
Allow the array to be defined inside curly braces, instead of using array() keyword.
The build was successful. Details
2019-03-21 17:27:19 +01:00
Rafal Kupiec a0d72d067c
Neither C++ does.
The build was successful. Details
2019-03-21 09:17:08 +01:00
Rafal Kupiec 0115b30d01
Extension to PHP, standard in AerScript.
The build was successful. Details
2019-03-21 06:19:27 +01:00
Rafal Kupiec 1460200919
This is true about PH7, but not about the AerScript.
The build was successful. Details
2019-03-20 19:39:30 +01:00
Rafal Kupiec 24013f4a52
Correct project name.
The build was successful. Details
2019-03-20 19:25:46 +01:00
Rafal Kupiec 166b1a2c41
This is not a bug.
The build was successful. Details
2019-03-20 12:58:16 +01:00
Rafal Kupiec 4eba80b2ba
Update TODO list.
The build was successful. Details
2019-03-20 09:32:38 +01:00
Rafal Kupiec 7b1ed59f41
Basic check if all methods declared in interface are also defined in class.
The build was successful. Details
2019-03-20 09:24:30 +01:00
Rafal Kupiec 3d23d43040
Enable garbage collector for Program class. This also partially fixes #47, as from now Program::__destruct() will be called automatically.
The build was successful. Details
2019-03-19 12:52:36 +01:00
Rafal Kupiec b60c1de4cf
Abort on SXERR_ABORT, #47.
The build was successful. Details
2019-03-19 10:42:53 +01:00
Rafal Kupiec 23601fe9c5
Partially fix #47, static variables are still affected.
The build was successful. Details
2019-03-19 10:38:07 +01:00
Rafal Kupiec d6751484d0
Another bug found so far.
The build was successful. Details
2019-03-18 12:26:21 +01:00
Rafal Kupiec d4967da9e4
Some bugs found already.
The build was successful. Details
2019-03-18 12:08:35 +01:00
Rafal Kupiec c6d95c16d3
Fix typo.
The build was successful. Details
2019-03-18 08:59:28 +01:00
Rafal Kupiec fc3a66315b
These are already done.
The build was successful. Details
2019-03-17 20:25:22 +01:00
Rafal Kupiec 6ca08c9c4a
Fix typo and builtin library.
The build was successful. Details
2019-03-17 19:57:31 +01:00
Rafal Kupiec 55b652c740
Verify that Program::main() returns a value of int or void.
The build has failed. Details
2019-03-17 19:56:07 +01:00
Rafal Kupiec fe898ec7e7
Update builtin library to follow new syntax.
The build has failed. Details
2019-03-17 19:52:28 +01:00
Rafal Kupiec ff73690111
Update tests to follow new syntax.
The build has failed. Details
2019-03-17 19:48:52 +01:00
Rafal Kupiec c26f8cd777
Strict data types for classes and interfaces:
The build has failed. Details
1) New syntax for method declaration, now requiring a strict data type to be passed (i.e. void main()),
2) New syntax for attributes declaration, als orequiring a strict data type before variable name (i.e. string $str).
2019-03-17 19:43:03 +01:00
Rafal Kupiec 128f4bba01
This is already done, even methods do not support strict data type hinting.
The build was successful. Details
2019-03-17 19:41:32 +01:00
Rafal Kupiec 9934489ed9
Fix build.
The build was successful. Details
2019-03-17 18:56:17 +01:00
Rafal Kupiec f3d10dd4bc
Try to exit with code returned by Program::main() only when it is integer value.
The build has failed. Details
2019-03-17 18:49:22 +01:00
Rafal Kupiec de2b355862
Return 0, when display error message.
The build was successful. Details
2019-03-17 18:47:17 +01:00
Rafal Kupiec 615e75fb8a
Store methods return type.
The build was successful. Details
2019-03-16 14:57:04 +01:00
Rafal Kupiec 7897f28ebb
Fix parameters order.
The build was successful. Details
2019-03-13 20:10:32 +01:00
Rafal Kupiec e498bc7646
It is enought to declare 'object'.
The build was successful. Details
2019-03-13 19:59:48 +01:00
Rafal Kupiec a2749000d6
Do not store these information twice; save the memory.
The build was successful. Details
2019-03-13 09:58:00 +01:00
Rafal Kupiec f71e60f641
Add fields to store information about method's return data type.
The build was successful. Details
2019-03-13 09:43:27 +01:00
Rafal Kupiec cc4a9aa063 Merge branch 'typehinting' of ssh://git.codingworkshop.eu.org:8822/AerScript/Aer into typehinting
The build was successful. Details
2019-03-13 09:36:26 +01:00
Rafal Kupiec c8985032ef
Verify that return value match the data type of declared method/closure. 2019-03-13 09:36:10 +01:00
Rafal Kupiec 3e4064f55a
Another feature to not forget about.
The build was successful. Details
2019-03-11 12:02:24 +01:00
Rafal Kupiec ac16d5ce57
Still many things to do here.
The build was successful. Details
2019-03-11 08:24:13 +01:00
Rafal Kupiec df3d00d02c
Revert f1d4d80f65.
The build was successful. Details
2019-03-11 08:16:51 +01:00
Rafal Kupiec 051bca470e
Save the closure return data type for further use.
The build was successful. Details
2019-03-10 21:02:06 +01:00
Rafal Kupiec f1d4d80f65
Cleanup keywords.
The build was successful. Details
2019-03-09 22:39:26 +01:00
Rafal Kupiec 8aacf7c70e
Do not use PH7_KEYWORD_FUNCTION for closure declaration.
The build was successful. Details
2019-03-09 19:43:56 +01:00
Rafal Kupiec 0524092539
Add missing space in error message
The build was successful. Details
2019-03-09 16:49:46 +01:00
Rafal Kupiec d6c5f01905
PH7_VmMemoryError() always breaks script execution.
The build was successful. Details
2019-03-09 14:00:11 +01:00
Rafal Kupiec e86894f724
PH7_VmMemoryError() always breaks script execution.
The build was successful. Details
2019-03-09 13:59:04 +01:00
Rafal Kupiec bd4151f426
Just fixed.
The build was successful. Details
2019-03-09 13:40:24 +01:00
Rafal Kupiec a5ee2d75eb
PH7_VmMemoryError() always breaks script execution.
The build was successful. Details
2019-03-09 13:37:15 +01:00
Rafal Kupiec b7e3ad9f46
PH7_VmMemoryError() always breaks script execution.
The build was successful. Details
2019-03-09 13:28:04 +01:00
Rafal Kupiec 7eba38a633
Fix segmentation fault when trying to store a value under next index into an array.
The build was successful. Details
2019-03-09 13:25:13 +01:00
Rafal Kupiec 4af3220018
Throw a warning when trying to typecast to resource.
The build was successful. Details
2019-02-13 13:22:30 +01:00
Rafal Kupiec a7b4c6e880
Do not typecast to resource type at all. This might lead to attempt of access to the invalid memory area and segmentation fault.
The build was successful. Details
2019-02-08 14:28:04 +01:00
Rafal Kupiec fa0b487cc0
Implement typecasting to resource data type.
The build was successful. Details
2019-02-08 14:06:39 +01:00
Rafal Kupiec efbe191989
Update todo list.
The build was successful. Details
2019-02-08 13:57:15 +01:00
Rafal Kupiec 5d3acf74d0
Another test - tokenizer.
The build was successful. Details
2019-02-07 18:43:58 +01:00
Rafal Kupiec 6927c5c038
Factorial test.
The build was successful. Details
2019-02-07 18:29:53 +01:00
Rafal Kupiec 6a74bf9e8b
Test if method overloading is working properly.
The build was successful. Details
2019-02-07 18:23:37 +01:00
Rafal Kupiec ed8dab7870
Add more tests.
The build was successful. Details
2019-02-05 19:48:38 +01:00
Rafal Kupiec ff9e38a480
This is really an array.
The build was successful. Details
2019-02-05 19:26:06 +01:00
Rafal Kupiec bbdc740388
Finally, do not allow a string variables to act as callback.
The build was successful. Details
2018-12-20 19:37:03 +01:00
Rafal Kupiec 4db8ec02cd
Make tests.
The build was successful. Details
2018-12-20 18:31:59 +01:00
Rafal Kupiec f97e2a8294
Implement typecasting to callback data type.
The build was successful. Details
2018-12-20 18:30:21 +01:00
Rafal Kupiec 2949c8dcfb
Fix typo.
The build was successful. Details
2018-12-20 18:20:18 +01:00
Rafal Kupiec 784c705af6
Add callback cast operator.
The build was successful. Details
2018-12-13 10:07:44 +01:00
Rafal Kupiec 1c3211e00d
Add missing PH7_OP_CVT_CALL definition.
The build was successful. Details
2018-12-13 09:35:48 +01:00
Rafal Kupiec 0278f0a630
Add callback cast operator.
The build has failed. Details
2018-12-13 09:31:32 +01:00
Rafal Kupiec d87ce3ad1d
1. Set a proper data type when compiling closure.
The build was successful. Details
2. Temporarily allow to call a closure/function if its name is stored in a variable of callback or string type. Ultimately, only callback will be allowed.
2018-12-01 12:53:58 +01:00
Rafal Kupiec 2572b9321d
This is already fixed.
The build was successful. Details
2018-11-29 13:10:00 +01:00
Rafal Kupiec 3f9e3b0664
Check for compatible data types on OP_CALL & OP_STORE.
The build was successful. Details
2018-11-28 21:58:41 +01:00
Rafal Kupiec 9ab896c2e2
Implement PH7_CheckVarCompat().
The build was successful. Details
2018-11-28 20:37:07 +01:00
Rafal Kupiec f3f1723104
Return valid function for conversion to char.
The build was successful. Details
2018-11-28 20:11:47 +01:00
Rafal Kupiec 0d3cb90d5f
Always convert integer value to char as it is done in C/C++.
The build was successful. Details
2018-11-28 20:10:14 +01:00
Rafal Kupiec a5ef118263
More bugs to fix in this branch.
The build was successful. Details
2018-11-28 14:09:21 +01:00
Rafal Kupiec d3e0ffe4bf
Update TODO list.
The build was successful. Details
2018-11-28 14:01:55 +01:00
Rafal Kupiec 3cc8cfe6a2
Remove duplicated code.
The build was successful. Details
2018-11-28 13:58:33 +01:00
Rafal Kupiec 1cebd3af37
Allow char to be typecasted to value of any other type.
The build was successful. Details
2018-11-26 20:41:15 +01:00
Rafal Kupiec 5dde778382
Release object to free some memory.
The build was successful. Details
2018-11-26 20:39:08 +01:00
Rafal Kupiec d65a529d21
Initial support for char data type.
The build was successful. Details
2018-11-26 20:37:51 +01:00
Rafal Kupiec 8782b9c25b
Update tests to use more strict data types instead of mixed.
The build was successful. Details
2018-11-26 14:41:41 +01:00
Rafal Kupiec 174ecb2a38
Initial support for void type.
The build was successful. Details
2018-11-23 09:19:37 +01:00
Rafal Kupiec 87db6d6dfd
Allow a method/closure to take compatible mixed variable as argument.
The build was successful. Details
2018-11-18 22:06:40 +01:00
Rafal Kupiec 5878a171e6
Update TODO list
The build was successful. Details
2018-11-13 20:26:22 +01:00
Rafal Kupiec e727453ccf
Fix var_dump() for mixed arrays.
The build was successful. Details
2018-11-13 20:24:55 +01:00
Rafal Kupiec 7a34716298
Add TODO list.
The build was successful. Details
2018-11-07 19:53:15 +01:00
Rafal Kupiec 8724cebf71
Do not actually support references in the same scope.
The build was successful. Details
2018-10-28 19:45:31 +01:00
Rafal Kupiec ec47190874
Array dump format.
The build was successful. Details
2018-10-27 19:56:13 +02:00
Rafal Kupiec e5fb7d625e
Allow only a colon as variable separator.
The build was successful. Details
2018-10-27 19:49:24 +02:00
Rafal Kupiec 6f13c347d8
Set the proper type of array.
The build was successful. Details
2018-10-26 19:45:10 +02:00
Rafal Kupiec 03cf969c31
Check for a type of array.
The build was successful. Details
2018-10-11 15:15:48 +02:00
Rafal Kupiec b66515516e
First check if array or object.
The build was successful. Details
2018-10-01 22:46:35 +02:00
Rafal Kupiec 6293b8f5bf
Do not try to dump empty array.
The build was successful. Details
2018-10-01 22:43:23 +02:00
Rafal Kupiec c00080e190
Correct comment.
The build was successful. Details
2018-09-24 19:20:23 +02:00
Rafal Kupiec b5eb268ce1
Do not allow to set a value of different type to the variable.
The build was successful. Details
2018-09-24 19:17:46 +02:00
Rafal Kupiec 5f2f9d9c08
Set proper data type for static variables;
The build was successful. Details
2018-09-24 19:16:44 +02:00
Rafal Kupiec 6e7bc74949
Put comment in right place.
The build was successful. Details
2018-09-24 13:39:50 +02:00
Rafal Kupiec f26095658d
Treat empty object as false.
The build was successful. Details
2018-09-24 13:38:33 +02:00
Rafal Kupiec 2db1954779
Another bunch of fixes for object type.
The build was successful. Details
2018-09-24 13:34:22 +02:00
Rafal Kupiec 550107235c
Do not try to dump a non-instantiated object.
The build was successful. Details
2018-09-24 12:22:58 +02:00
Rafal Kupiec 369cadfcda
Tryeing to call a non-instantiated object should result in an error.
The build was successful. Details
2018-09-24 12:10:19 +02:00
Rafal Kupiec f72d6c3922
Load data from array/object only if there is anything stored.
The build was successful. Details
2018-09-24 11:47:30 +02:00
Rafal Kupiec 59fda6d797
Unref hashmap and object only if there is any data stored.
The build was successful. Details
2018-09-24 11:29:51 +02:00
Rafal Kupiec ba0c250911
Fix test.
The build was successful. Details
2018-09-23 19:07:03 +02:00
Rafal Kupiec 08296110fb
Temporarily fix tests.
The build was successful. Details
2018-09-23 17:51:47 +02:00
Rafal Kupiec dd774be005
Fix for() loop, do not use iP1 for OP_LOAD.
The build has failed. Details
2018-09-23 17:51:09 +02:00
Rafal Kupiec ae0fde152c
Create a variable only on OP_LOAD.
The build has failed. Details
2018-09-23 17:40:26 +02:00
Rafal Kupiec 28a5fa59ad
Duplicate variable name. Fix variable declaration.
The build was successful. Details
2018-09-22 17:54:59 +02:00
Rafal Kupiec 514e07c7f3
Fix static variables not containing any value.
The build was successful. Details
2018-09-21 22:18:11 +02:00
Rafal Kupiec f927667d85
Strictly check for data type of static variable declaration.
The build has failed. Details
2018-09-21 22:06:36 +02:00
Rafal Kupiec 79e4bac7eb
Remove no longer used PH7_CompileStatic().
The build was successful. Details
2018-09-21 00:22:29 +02:00
Rafal Kupiec bd4d146d0a
Initial version of variable definition.
The build was successful. Details
2018-09-21 00:21:15 +02:00
Rafal Kupiec 241c7d8168
First step to declare a variable with specified data type.
The build was successful. Details
2018-09-20 17:06:23 +02:00
Rafal Kupiec e6e59d299e
Fix method parameters.
The build was successful. Details
2018-09-19 19:27:50 +02:00
Rafal Kupiec 9884f8288b
Do not allow typecasting to unset a variable.
The build was successful. Details
2018-09-18 22:11:57 +02:00
Rafal Kupiec 5a6af65cfa
Object of wrong type passed as argument should be generate error.
The build was successful. Details
2018-09-17 22:06:53 +02:00
Rafal Kupiec 82998ffd0f
Silently typecast integer value to float.
The build was successful. Details
This is a necessary step, to allow passing integer numbers. Otherwise, every float variable would need a floating point value. In other words, "float $x = 5" is allowed construct. Without this simple change, only accepted
construction was "float $x = 5.0".
2018-09-16 20:02:34 +02:00
Rafal Kupiec 58103ea5fe
Mark method/closure call frame as active.
The build was successful. Details
It is impossible to dump the frame during its initialization, as it does not contain all necessary information. Such frame should be skipped. After initialization is done, the frame has to be marked as active just before
evaluating a function body.
2018-09-16 19:52:24 +02:00
Rafal Kupiec 3a16eced8a
Push error if argument type does not match.
The build was successful. Details
2018-09-15 14:13:46 +02:00
Rafal Kupiec 5504579566
Passing an object of different type as expected should result in error.
The build was successful. Details
2018-09-14 22:27:38 +02:00
Rafal Kupiec faca9b7fb2
Another fix in debug trace.
The build was successful. Details
2018-09-14 22:22:37 +02:00
Rafal Kupiec 94ae7d187b
No data type for argument specified leads to E_ERROR.
The build was successful. Details
2018-09-14 21:33:31 +02:00
Rafal Kupiec ca00cadba7
Use strict type hinting in all tests.
The build was successful. Details
2018-09-14 21:32:08 +02:00
Rafal Kupiec 8b48786f29
Add missing data types.
The build was successful. Details
2018-09-14 08:47:16 +02:00
Rafal Kupiec ecebbb6094
Use type hinting in standard library.
The build has failed. Details
2018-09-14 08:36:00 +02:00
Rafal Kupiec 74b1c196f9
Treat invalid type name as error.
The build was successful. Details
2018-09-13 18:56:01 +02:00
Rafal Kupiec d4992ff4ba
At least try to report correct line number.
The build was successful. Details
2018-09-12 19:24:48 +02:00
Rafal Kupiec 1e5538fc67
Remove useless fields in pVm.
The build was successful. Details
2018-09-11 17:52:28 +02:00
Rafal Kupiec 58b7ceeae9
Get rid of $GLOBALS completely.
The build was successful. Details
2018-09-11 17:49:20 +02:00
Rafal Kupiec 0804407582
Correct typo.
The build was successful. Details
2018-09-11 13:58:03 +02:00
Rafal Kupiec e383536dc4
Do not store script arguments in $GLOBALS.
The build was successful. Details
2018-09-11 06:47:48 +02:00
Rafal Kupiec 9ebc3dc61a
Extract a list of parameters and pass them to Program::main();
The build was successful. Details
2018-09-10 23:12:08 +02:00
Rafal Kupiec 82e5dc1565
Add SyStrtok() declaration.
The build was successful. Details
2018-09-10 23:02:25 +02:00
Rafal Kupiec 10d3bfe5e1
Correct comments.
The build was successful. Details
2018-09-10 20:17:42 +02:00
Rafal Kupiec 7e754db07f
Implement SyStrtok();
The build was successful. Details
2018-09-10 20:16:46 +02:00
Rafal Kupiec eb79ed500e
Store float values in an union.
The build was successful. Details
Single variable cannot have many values of different types. This also saves some memory, because union allocates memory just for one of its members.
2018-09-07 12:04:51 +02:00
Rafal Kupiec af1d59dab4
Don't try to get an integer representation of float.
The build was successful. Details
2018-09-07 06:49:50 +02:00
Rafal Kupiec ac8b8b0fdb
Don't try to get an integer representation of float.
The build was successful. Details
2018-09-07 06:43:07 +02:00
Rafal Kupiec 9ee0f1954c
Do not omit the floating point.
The build was successful. Details
Every modern hardware, including embedded devices, should support floating point numbers.
2018-09-07 06:38:32 +02:00
Rafal Kupiec 0a9cfce672
Group and add missing keywords.
The build was successful. Details
2018-09-06 19:47:06 +02:00
Rafal Kupiec 43a36f070c
Correct comments.
The build was successful. Details
2018-09-06 18:00:34 +02:00
Rafal Kupiec cb8ddaab5f
This is obsolete.
The build was successful. Details
2018-09-05 21:54:52 +02:00
Rafal Kupiec 3887aa69a6
Never disable hash functions.
The build was successful. Details
2018-09-05 21:46:25 +02:00
Rafal Kupiec c3a4c8de77
Never disable builtin functions.
The build was successful. Details
2018-09-05 20:47:07 +02:00
Rafal Kupiec 00e1c842d5
Never disable builtin functions.
The build was successful. Details
2018-09-05 20:43:39 +02:00
Rafal Kupiec ea4daa9335
Take last instruction being executed, not necessarily OP_CALL.
The build was successful. Details
2018-09-05 19:45:38 +02:00
Rafal Kupiec 6387026e15
Do not limit the output buffering callbacks.
The build was successful. Details
2018-09-05 18:46:42 +02:00
Rafal Kupiec 11ba0ce738
No need to store output length in VM.
The build was successful. Details
2018-09-05 18:33:53 +02:00
Rafal Kupiec 404f5a2688
No need to store unique ID in VM.
The build was successful. Details
2018-09-05 18:24:34 +02:00
Rafal Kupiec ae79cb57de
No need to store information about line number in ph7_class struct.
The build was successful. Details
2018-09-05 17:42:10 +02:00
Rafal Kupiec 894dbe47d6
Allow compiler to specify line number, on which instruction has been generated.
The build was successful. Details
This also fixes line number on OP_CLASS_INIT and OP_INTERFACE_INIT.
2018-09-05 17:31:06 +02:00
Rafal Kupiec 543176a2f4
Switch VM state to PH7_VM_INCL when including new file.
The build was successful. Details
2018-09-05 13:28:20 +02:00
Rafal Kupiec d58249cb3f
Use debug trace only if VM is really executing some code.
The build was successful. Details
2018-09-05 13:16:57 +02:00
Rafal Kupiec 765d2cf3eb
Another VM state.
The build was successful. Details
2018-09-05 13:13:36 +02:00
Rafal Kupiec 8ca6deca4e
Allow to set memory limit from SAPI.
The build was successful. Details
2018-09-04 11:52:55 +02:00
Rafal Kupiec c00c91599f
Enable unused API functions.
The build was successful. Details
2018-09-04 09:33:28 +02:00
Rafal Kupiec 19eaaab081
Remove unused code.
The build was successful. Details
2018-09-04 09:19:15 +02:00
Rafal Kupiec 1643d2ee94
Remove unused code.
The build was successful. Details
2018-09-04 09:18:13 +02:00
Rafal Kupiec 03e452ea7b
Shutdown library properly on error.
The build was successful. Details
2018-09-04 09:13:28 +02:00
Rafal Kupiec 1daf17bcd4
Correct typo.
The build was successful. Details
2018-09-04 09:07:58 +02:00
Rafal Kupiec d793d3ed70
Rename PH7_VmGenericError() to PH7_VmThrowError()
The build was successful. Details
2018-09-04 08:54:48 +02:00
Rafal Kupiec 758ace0d1a
Shutdown library properly on error.
The build was successful. Details
2018-09-04 08:49:38 +02:00
Rafal Kupiec dc0a55c8c0
Cleanup old error handler.
The build was successful. Details
2018-09-04 08:38:41 +02:00
Rafal Kupiec ac73632cb1
Use new error handler.
The build was successful. Details
2018-09-04 08:26:58 +02:00
Rafal Kupiec bd44dba33c
Use new error handler in modules.
The build was successful. Details
2018-09-03 20:19:12 +02:00
Rafal Kupiec d85a517eb0
Rework trigger_error() builtin function.
The build was successful. Details
2018-09-03 19:27:38 +02:00
Rafal Kupiec 0a28e492a7
error_reporting() is useless for Aer.
The build was successful. Details
Whole configuration should be done in config file.
2018-09-03 19:11:44 +02:00
Rafal Kupiec fd4206a227
Remove error_log() builtin function and corresponding PH7_VM_CONFIG_ERR_LOG_HANDLER.
The build was successful. Details
It was not fully implemented and such feature should be implemented in separate module or on developers own.
2018-09-03 19:03:05 +02:00
Rafal Kupiec 109f4e981a
Aer does not support custom error handlers.
The build was successful. Details
Errors are used only internally to emit notifications about compilation/execution problems. They should not be catched and handled by custom handlers, but properly configured (to be displayed or logged). Instead developers should
use exceptions that can be catched with try-catch block.
2018-09-03 16:43:08 +02:00
Rafal Kupiec dd35b5b8b4
Uncaught exception message.
The build was successful. Details
2018-09-03 16:29:50 +02:00
Rafal Kupiec d3d3dcc767
Partially switch to new error reporting.
The build was successful. Details
2018-09-03 16:16:32 +02:00
Rafal Kupiec 5895141ae1
Add missing declarations.
The build was successful. Details
2018-09-03 10:59:20 +02:00
Rafal Kupiec 0298299169
Extend SEQ field.
The build was successful. Details
2018-09-03 09:36:22 +02:00
Rafal Kupiec 9c4eb59b49
Variable list of arguments for PH7_VmGenericError();
The build was successful. Details
2018-09-03 09:30:23 +02:00
Rafal Kupiec f176414bce
Release VM and exit automatically, do not rely on VM.
The build was successful. Details
2018-09-03 08:40:18 +02:00
Rafal Kupiec eea9eee6e5
Implement PH7_VmGenericError();
The build was successful. Details
2018-09-03 08:19:14 +02:00
Rafal Kupiec a2acf64272
VmExtractDebugTrace() provides information about a kind of call.
The build was successful. Details
Both VmExtractDebugTrace() and VmDebugTrace structure should provide information whether it was object call or a static method call.
2018-09-02 20:15:17 +02:00
Rafal Kupiec d135748bcd
Always iterate through all frames.
The build was successful. Details
2018-09-02 18:53:23 +02:00
Rafal Kupiec ea7955b6ee
Remove useless VmExtractPeekDebugTrace();
The build was successful. Details
2018-09-02 18:50:00 +02:00
Rafal Kupiec f89af70ab2
Fix VmExtractDebugTrace();
The build was successful. Details
If there is no information about class in the frame (when closure was called), pClassName should point always to NULL.
2018-09-02 18:46:30 +02:00
Rafal Kupiec 3e1d91e909
Add more comments.
The build was successful. Details
2018-09-02 18:45:01 +02:00
Rafal Kupiec da198fcb44
Implement PH7_VmMemoryError();
The build was successful. Details
2018-09-02 12:27:32 +02:00
Rafal Kupiec 90ab131ce8
Do not append spaces. Instructions names are properly displayed without them.
The build was successful. Details
2018-09-01 20:28:16 +02:00
Rafal Kupiec 8bfaa83b04
Correct typo.
The build was successful. Details
2018-09-01 20:19:10 +02:00
Rafal Kupiec 4dae0bcc9e
Always record last instruction.
The build was successful. Details
2018-09-01 19:56:36 +02:00
Rafal Kupiec 383fe01943
Reserve 10KB for error reporting.
The build was successful. Details
2018-09-01 17:54:45 +02:00
Rafal Kupiec 8fcb3c608a
Remove duplicate of SySetUsed() macro.
The build was successful. Details
2018-08-31 23:45:46 +02:00
Rafal Kupiec d9db6bbc26
There is no need for global working buffer in VM.
The build was successful. Details
2018-08-31 23:34:35 +02:00
Rafal Kupiec 67ce98d924
Look for executed OP_CALL.
The build was successful. Details
Each function contains a list of all instructions inside, thus we should consider only OP_CALL that has already been executed. As the list is browsed from bottom to top, no more checks are necessary. The first match is what we
are looking for.
2018-08-31 08:30:59 +02:00
Rafal Kupiec 838842fa02
Add execution marker to each instruction.
The build was successful. Details
2018-08-31 08:25:48 +02:00
Rafal Kupiec 3e2a5b3be2
Correct field length.
The build was successful. Details
2018-08-30 19:23:06 +02:00
Rafal Kupiec 90a02d8fdd
Add operator ID to the debugging information.
The build was successful. Details
2018-08-30 16:52:09 +02:00
Rafal Kupiec 461ee00034
Allow to use PH7_CTX_DEPRECATED.
The build was successful. Details
2018-08-30 13:47:01 +02:00
Rafal Kupiec fbc725c935
We are tokenizing Aer.
The build was successful. Details
2018-08-30 12:33:38 +02:00
Rafal Kupiec 8215c4e984
Correct comment.
The build was successful. Details
2018-08-30 12:15:48 +02:00
Rafal Kupiec 041c65d63e
Implement SySetGetUsed();
The build was successful. Details
2018-08-30 12:00:02 +02:00
Rafal Kupiec b6161b0e4b
Fix VM ByteCode debugging.
The build was successful. Details
Only executed bytecode should be registered for debugging. In this way we do not register all emitted bytecode and save some memory. What is more, this change registers the bytecode in correct executing order including jumps.
Previously all bytecode generated by compiler has been saved what made the bytecode to be saved in compile, not execute order.
2018-08-30 09:46:40 +02:00
Rafal Kupiec 98d3de2105
Record all instructions in debugging set.
The build was successful. Details
2018-08-29 08:04:19 +02:00
Rafal Kupiec 8f92782fe2
Fix segmentation fault.
The build was successful. Details
2018-08-28 19:07:07 +02:00
Rafal Kupiec d97c0a6634
Fix VmExtractPeekDebugTrace();
The build was successful. Details
2018-08-28 11:17:32 +02:00
Rafal Kupiec 603672b8e2
PH7 disallows function calls from global scope.
The build was successful. Details
2018-08-28 11:16:34 +02:00
Rafal Kupiec 37c960e313
Fix uninitialized value leading to segmentation fault.
The build was successful. Details
2018-08-27 20:23:08 +02:00
Rafal Kupiec 6a14e88973
Remove unused definition.
The build has failed. Details
2018-08-27 20:22:23 +02:00
Rafal Kupiec 349bbed774
Allow to enable or disable debugging.
The build has failed. Details
2018-08-27 19:53:24 +02:00
Rafal Kupiec c8e2dccbeb
Assign Program::main() return value as program exit code.
The build has failed. Details
2018-08-27 19:32:17 +02:00
Rafal Kupiec 7a740c0570
Correct typo.
The build was successful. Details
2018-08-27 18:23:12 +02:00
Rafal Kupiec 6d27069590
Add new file for every chunk.
The build was successful. Details
Every chunk should has its own file associated, even if it is [MEMORY]. Otherwise, some false information can be provided by interpreter to developer.
2018-08-27 18:04:45 +02:00
Rafal Kupiec c9a1971ace
Rewrite debug_backtrace() builtin function.
The build was successful. Details
It makes a use of new VmExtractDebugTrace() function. This probably fixes #45.
2018-08-27 15:47:34 +02:00
Rafal Kupiec ce621cc49c
Implement VmExtractPeekDebugTrace();
The build was successful. Details
2018-08-27 12:42:02 +02:00
Rafal Kupiec d0b0a416d0
Allow to dump last frame only.
The build was successful. Details
2018-08-27 12:36:21 +02:00
Rafal Kupiec 8f7b28d46c
Formatting for VM dump.
The build was successful. Details
2018-08-27 12:16:41 +02:00
Rafal Kupiec fb671ec2d7
Implement VmExtractDebugTrace().
The build was successful. Details
2018-08-27 11:32:21 +02:00
Rafal Kupiec 18222dce8c
Implement VmDebugTrace structure.
The build was successful. Details
2018-08-27 11:22:02 +02:00
Rafal Kupiec 1403b144d9
Sequence numbers should start from 1.
The build was successful. Details
2018-08-27 09:30:51 +02:00
Rafal Kupiec 782a4df1cf
Formatting, add information about file and line.
The build was successful. Details
2018-08-27 09:17:18 +02:00
Rafal Kupiec b1f71167d9
Unify memory indicator.
The build was successful. Details
2018-08-27 08:22:05 +02:00
Rafal Kupiec 3f7bac2d85
Associate a filename with VM instructions.
The build was successful. Details
2018-08-27 06:45:53 +02:00
Rafal Kupiec f552c54992
Better formatting.
The build was successful. Details
2018-08-26 22:10:47 +02:00
Rafal Kupiec e6ad76b031
Dump VM after execution.
The build was successful. Details
VM instructions dump should be processed after script execution to follow included files.
2018-08-26 20:29:19 +02:00
Rafal Kupiec a7bbd55d48
Temporarily enable debugging by default.
The build was successful. Details
2018-08-26 20:09:30 +02:00
Rafal Kupiec 178f3820f6
Enable debugging.
The build was successful. Details
This commit introduces ne debug feature. The PH7 Engine limits the VM dump to the global scope. Since Aer Script is fully object-oriented language the dump option contains only information about last call of OP_DONE. This change,
forces the VM to store all instructions set in a global container when debugging is enabled, thus providing information the dump of whole script parse.
2018-08-26 19:59:17 +02:00
Rafal Kupiec ab5ee94f99
API function rename.
The build was successful. Details
2018-08-26 19:18:33 +02:00
Rafal Kupiec 98ee931a04
Correct instruction length.
The build was successful. Details
2018-08-26 18:33:57 +02:00
Rafal Kupiec 877d19a815
API function rename.
The build was successful. Details
2018-08-26 18:30:21 +02:00
Rafal Kupiec c8c6208cca
Return script exit code.
The build was successful. Details
2018-08-26 08:37:35 +02:00
Rafal Kupiec 94b213674a
Change the script located in memory indicator.
The build was successful. Details
For easier reading with line numbers.
2018-08-23 18:27:14 +02:00
Rafal Kupiec 4197737ddc
Move structure definitions to header.
The build was successful. Details
2018-08-23 17:08:10 +02:00
Rafal Kupiec 82c18dc109
Do not pop out the processed files.
The build was successful. Details
List of procesed files is still needed, as we point to them.
2018-08-23 07:06:33 +02:00
Rafal Kupiec 20c1611902
Implement PH7_VmExtractActiveClass().
The build was successful. Details
This function extracts an active class with specified depth, #45.
2018-08-22 15:33:16 +02:00
Rafal Kupiec 0ff32e6673
Remove duplicated constants.
The build was successful. Details
2018-08-22 11:24:34 +02:00
Rafal Kupiec dbe373d537
Resolve __CLASS__ at compile time.
The build was successful. Details
Ticket: #45: __CLASS__ constant must be resolved at compile time, not run time. Otherwise it returns incorrect data.
2018-08-22 09:59:10 +02:00
Rafal Kupiec 3e18a5b8e8
Optimize the code, #45.
The build was successful. Details
2018-08-22 08:51:45 +02:00
Rafal Kupiec a0f7949b24
Resolve __DIR__ at compile time.
The build was successful. Details
Ticket: #45: __DIR__ constant must be resolved at compile time, not run time. Otherwise it returns incorrect data.
2018-08-22 06:23:43 +02:00
Rafal Kupiec 02242bb93d
Resolve __FILE__ at compile time.
The build was successful. Details
Ticket: #45: __FILE__ constant must be resolved at compile time, not run time. Otherwise it returns incorrect data.
2018-08-21 20:18:39 +02:00
Rafal Kupiec 19a504fe11
Enter the class block during compilation, #45.
The build was successful. Details
2018-08-21 19:45:50 +02:00
Rafal Kupiec 33523e4e8a
Block definitions for class and namespace.
The build was successful. Details
2018-08-21 19:35:00 +02:00
Rafal Kupiec 2d99881240
Get rid of manual optimisation technique.
The build was successful. Details
This optimisation technique results in non insignificant speed boost on some old x86 architectures. Novadays, we should rely on compiler optimisation.
2018-08-21 06:27:07 +02:00
Rafal Kupiec 81325b5059
Correct typo.
The build was successful. Details
2018-08-18 21:05:46 +02:00
Rafal Kupiec 2160747479
Make get_included_files() returning full path.
The build was successful. Details
2018-08-18 21:02:23 +02:00
Rafal Kupiec cbb4a0aa5c
get_included_files() should return a list of included, files.
The build was successful. Details
2018-08-18 20:42:54 +02:00
Rafal Kupiec 00dc23ee4a Get rid of manual optimisation technique resulting in non insignificant speed boost on some old x86 architectures, #38;
The build was successful. Details
2018-08-18 19:44:02 +02:00
Rafal Kupiec 4b3279ef01
Correct function description.
The build was successful. Details
2018-08-18 19:32:33 +02:00
Rafal Kupiec 4dbd3ea412
New memory subsystem.
The build was successful. Details
This is a new memory subsystem implementing heap calculations as well as new builtin functions:
 * get_memory_usage()
 * get_memory_peak_usage()
 * get_memory_limit()
It also allows to set an upper memory limit, ensuring that processed script will not be able to allocate more memory from OS.
New subsystem is based on work done in 'memory_limit' branch. Big thanks to devnexen!
This finally fixes #25.
2018-08-18 19:24:38 +02:00
Rafal Kupiec 08c47b7528
Correct dictionary issues.
The build was successful. Details
2018-08-17 09:25:29 +02:00
Rafal Kupiec ab1266ef5d
Rename VFS
The build was successful. Details
2018-08-16 22:05:30 +02:00
Rafal Kupiec c83d6e13fc
Removing xExec.
The build was successful. Details
First of all, VFS is not a right place for this, finally it was not implemented anyway.
2018-08-16 21:37:34 +02:00
Rafal Kupiec 03a5b7e397 Merge branch 'compiler_rework' into master
The build was successful. Details
2018-08-16 21:28:49 +02:00
Rafal Kupiec a8a88b4746
Compile closures.
The build was successful. Details
2018-08-16 18:40:23 +02:00
Rafal Kupiec f28c671e69
Compile closures.
The build was successful. Details
2018-08-16 18:31:12 +02:00
Rafal Kupiec 074edd11d3
Add Windows 10 information
The build was successful. Details
2018-08-16 18:19:33 +02:00
Rafal Kupiec a8961eb36f
Fix build
The build was successful. Details
2018-08-16 17:48:17 +02:00
Rafal Kupiec 2c28b63d90
Properly interpret language constructs, fixes #28.
The build has failed. Details
2018-08-16 17:42:30 +02:00
Rafal Kupiec 9100bf0696
Treat 'import' as a special keyword.
The build was successful. Details
2018-08-16 16:32:28 +02:00
Rafal Kupiec b5fe36c14b
There is no need for include_once() and require_once()
The build was successful. Details
Aer is object-oriented language and the code it includes is executed in the global scope. Global scope can contain only classes and namespaces and they cannot be re-declared. Thus every file can be included just once. We can
leave this to programmer, or take care about it on interpreter side. With this commit, include() and require() builtin functions allows to load file just once. Thanks to that, there is no need for include_once() and
require_once(). Done in scope of #30.
2018-08-16 16:12:29 +02:00
Rafal Kupiec 510410096b
Aer is OOP language. There is nothing like function.
The build was successful. Details
2018-08-16 13:57:35 +02:00
Rafal Kupiec 4961922b1d
Unify error with other related to namespace.
The build was successful. Details
2018-08-16 13:36:19 +02:00
Rafal Kupiec 793b6127d5
Temporarily fix namespace support.
The build was successful. Details
The namespace feature is not supported in this version, they are treated same way as global scope.
2018-08-16 12:39:05 +02:00
Rafal Kupiec 787f3b5d5f
Synchronize the namespace also with first semicolon.
The build was successful. Details
2018-08-16 12:01:36 +02:00
Rafal Kupiec be27532fdf
Unify error level for namespace support.
The build was successful. Details
2018-08-16 11:26:47 +02:00
Rafal Kupiec e208e778e0
Compile global scope independently, fixes #40.
The build was successful. Details
2018-08-16 11:15:03 +02:00
Rafal Kupiec 039fde099f
Compile Aer code or chunk of code.
The build was successful. Details
2018-08-16 09:34:18 +02:00
Rafal Kupiec f9946e9842
Reimplement filegroup() and fileowner() as builtin function, #42.
The build was successful. Details
2018-08-15 21:58:21 +02:00
Rafal Kupiec f33f8d66b4
Correct warning messages.
The build was successful. Details
2018-08-15 21:43:17 +02:00
Rafal Kupiec 16ea44372f
Dictionary correction.
The build was successful. Details
2018-08-15 21:35:44 +02:00
Rafal Kupiec ac1dee48c9
Reimplement fileinode() as builtin function, #42.
The build was successful. Details
2018-08-15 21:28:59 +02:00
Rafal Kupiec b642858044
Add missing definition
The build was successful. Details
2018-08-15 20:20:56 +02:00
Rafal Kupiec b94a23d580
Get rid of PH7 ident
The build was successful. Details
2018-08-15 20:03:39 +02:00
Rafal Kupiec 7c7a837efb
Correct another bunch of typos.
The build was successful. Details
2018-08-15 19:06:00 +02:00
Rafal Kupiec 71d46e3052
Compiler rework does not allow functions in global scope.
The build was successful. Details
These functions will be rewritten in C as a builtin functions in scope of #42.
2018-08-15 18:56:10 +02:00
Rafal Kupiec da0b7eb629
Some useless function
The build was successful. Details
2018-08-15 17:34:40 +02:00
Rafal Kupiec af139b3f0a
Reimplement C-like min() and max() functions.
The build was successful. Details
These functions should have C-like implementation and take exactly 2 arguments: integer or float.
Finally, C-implementation will be faster than using PH7 builtin library that needs to be compiled and interpreted.
2018-08-15 17:26:26 +02:00
Rafal Kupiec 89d7aca73a
Correct typo
The build was successful. Details
2018-08-15 16:38:33 +02:00
Rafal Kupiec 8ab67084a0
It is as easy to instantiate the class as to remove this useless functions.
The build was successful. Details
2018-08-15 16:31:28 +02:00
Rafal Kupiec 6f491b398a
Always show compilation errors
The build was successful. Details
2018-08-15 16:01:09 +02:00
Rafal Kupiec 8e87989719
A;ways show compilation errors from evaluated code
The build was successful. Details
2018-08-15 15:41:53 +02:00
Rafal Kupiec 052649e677
Trust builtin library.
The build was successful. Details
The builtin library should compile successfully. Otherwise, we want to know about it.
2018-08-15 14:12:44 +02:00
Rafal Kupiec 0e64c7cc6e
Fix builtin library
The build was successful. Details
2018-08-15 14:08:59 +02:00
Rafal Kupiec 64b9ac4406
Forward declaration already in compiler.h
The build was successful. Details
2018-08-15 11:18:40 +02:00
Rafal Kupiec be454ff7be
Rename PH7_COMPILE_SINGLE_STMT to PH7_COMPILE_STATEMENT
The build was successful. Details
2018-08-14 23:48:15 +02:00
Rafal Kupiec 26b1675021
API function rename
The build was successful. Details
2018-08-14 17:43:43 +02:00
Rafal Kupiec ece036b214
Rework the entry point
The build was successful. Details
* some functions were not used and have been removed
 * some parameters seemed to be useless and have been removed
 * code cleanup
2018-08-14 13:45:27 +02:00
Rafal Kupiec 1cb3e394cf
Implement pseudo boolean type.
The build was successful. Details
2018-08-14 10:42:52 +02:00
Rafal Kupiec 7e3c79d3c5
Functions naming cleanup
The build was successful. Details
2018-08-13 20:16:37 +02:00
Rafal Kupiec 02fde9c30f
It is not PHP compiler
The build was successful. Details
2018-08-13 19:53:08 +02:00
Rafal Kupiec d7f9d8e157
Add missing 'finally' keyword.
The build was successful. Details
2018-08-12 22:04:47 +02:00
Rafal Kupiec aa6e00db27
Forward declaration for all functions.
The build was successful. Details
2018-08-12 21:58:27 +02:00
Rafal Kupiec 59c15caf4e
Use something more human readable
The build was successful. Details
2018-08-12 21:16:05 +02:00
Rafal Kupiec 6b7591a137
Move common part to compiler.h
The build was successful. Details
2018-08-12 21:11:13 +02:00
Rafal Kupiec 289af8f9ae
Unify compiler's function naming convenction
The build was successful. Details
2018-08-12 20:58:01 +02:00
Rafal Kupiec 5ef5cf3e46
Make errors more readable.
The build was successful. Details
2018-08-12 19:36:17 +02:00
Rafal Kupiec 429c28d0cc
Rework error lovels for AerScript.
The build was successful. Details
2018-08-12 19:35:43 +02:00
Rafal Kupiec 029dd9bfb4
Several changes made:
The build was successful. Details
* Do not overload entry point
 * Automatically call Program::__construct()
 * Automatically call Program::main();
 * Fix all tests
2018-08-12 12:52:35 +02:00
Rafal Kupiec 8cbfca2bc9
Do not overload entry point
The build was successful. Details
2018-08-12 12:27:15 +02:00
Rafal Kupiec c39e627aef
Remove the backtick quoted string.
The build was successful. Details
2018-08-12 11:08:09 +02:00
Rafal Kupiec cef0f40820
Compile namespace
The build was successful. Details
2018-08-12 11:06:01 +02:00
Rafal Kupiec c298a41eb7
More verbose error messages
The build was successful. Details
2018-08-12 10:30:44 +02:00
Rafal Kupiec e866575cb5
More verbose errors
The build was successful. Details
2018-08-12 10:18:42 +02:00
Rafal Kupiec c759b1f106
Improove error reporting for method declarations
The build was successful. Details
2018-08-12 09:23:21 +02:00
Rafal Kupiec b61fc9d3e6
Rename function to save it from typo
The build was successful. Details
2018-08-11 23:21:40 +02:00
Rafal Kupiec 576edc6c20
Several changes to virtual class/method. Fixes #41
The build was successful. Details
* do not automatically mark class as virtual when at least one virtual method found
 * force non-virtual method to contain body
 * force non-virtual class to implement all methods
2018-08-11 22:50:05 +02:00
Rafal Kupiec 3f46f01805
Rename anonymous functions
The build was successful. Details
2018-08-11 21:40:05 +02:00
Rafal Kupiec 0d8391eaaa
Correct typos
The build was successful. Details
2018-08-11 21:22:04 +02:00
Rafal Kupiec 5d9ccf9c65
More tests
The build was successful. Details
2018-08-10 08:51:38 +02:00
Rafal Kupiec 3252f54615 Temporarily look for modules in binary/ subdirectory. This will allow us to test modules.
The build was successful. Details
Final version should take the full path from configuration.
2018-08-10 08:47:42 +02:00
Rafal Kupiec 0561c5f901
Redundant slash
The build was successful. Details
2018-08-10 08:44:58 +02:00
Rafal Kupiec bfbe97255c
This is not needed to build modules
The build was successful. Details
2018-08-10 08:44:09 +02:00
Rafal Kupiec fc4b17434e
Remove duplicated builtin functions
The build was successful. Details
2018-08-09 21:34:13 +02:00
Rafal Kupiec 8936f6529f
Remove duplicate
The build was successful. Details
2018-08-09 21:32:00 +02:00
Rafal Kupiec 94b29fa238
Remove duplicates
The build was successful. Details
2018-08-09 21:27:24 +02:00
Rafal Kupiec 8f7fc71027
Consider a method with compiled default value associated as a candidate to call. Fixes #37.
The build was successful. Details
2018-08-08 09:00:24 +02:00
Rafal Kupiec e15166d940
Temporary fix for master branch
The build was successful. Details
2018-08-08 06:52:15 +02:00
Rafal Kupiec bca4d1a2fa
Always select an appropriate function to call
The build has failed. Details
It does not matter, if we call function, anonymouss function or method. It is important to select appropriate function to call everytime. Otherwise, if function or method is not overloaded it will call it regardless the number
and type of parameters it takes.
type
2018-08-07 19:48:12 +02:00
Rafal Kupiec 34dd052f74
quick typo fix
The build was successful. Details
2018-08-07 19:45:34 +02:00
Rafal Kupiec 370465fe79
We should use %z to match (SyString *) length and to not display trash.
The build was successful. Details
2018-08-07 19:02:28 +02:00
Rafal Kupiec c419b8605d
Add more tests
The build was successful. Details
2018-08-07 17:16:28 +02:00
David Carlier 7711bdb6bc Merge branch 'master' of https://git.codingworkshop.eu.org/AerScript/Aer
The build was successful. Details
2018-08-07 13:55:27 +00:00
David Carlier a0fb911d7a Fix #36, unrolling through the frames needed to also reset to the initial frame after 2018-08-07 13:55:13 +00:00
Rafal Kupiec 80f376af62
Test debug_backtrace() function
The build has failed. Details
2018-08-07 15:47:14 +02:00
Rafal Kupiec cdc58f2795
Cleanup after 2c37807370 - get rid of global keyword, #29.
The build was successful. Details
2018-08-07 12:27:21 +02:00
Rafal Kupiec a4e6962a67
Free dot operator for further usage
The build was successful. Details
2018-08-07 08:13:44 +02:00
Rafal Kupiec 6f0d1ab3ff
Tests should use new string concatenation operator
The build was successful. Details
2018-08-07 07:53:26 +02:00
Rafal Kupiec e4ab5974fa
Let the compiler use OP_ADD instead of OP_CAT
The build was successful. Details
2018-08-07 07:47:25 +02:00
Rafal Kupiec 9a56751879
Allow addition operator (+) to concatenate strings.
The build was successful. Details
2018-08-07 06:54:44 +02:00
Rafal Kupiec 3a994221ce
Add another chapter to the readme
The build was successful. Details
2018-08-06 19:28:03 +02:00
Rafal Kupiec 4bbdc20174
This commit contains several changes:
The build was successful. Details
* print() is now treated as standard function
 * get rid of echo() function
 * fix test suite
and it fixes #26.
2018-08-06 17:18:27 +02:00
Piotr Likoski bcde1f446d
It does not matter if it is empty string or not, we want to process it. Empty string should not ever been even considered as a NULL. Fixing #35.
The build was successful. Details
2018-08-06 16:13:49 +02:00
Piotr Likoski a8259e7dbc
Empty double-quoted string can be served as single-quoted string. Preparing for further changes in scope of #35.
The build was successful. Details
2018-08-06 16:03:22 +02:00
Rafal Kupiec dd239530d8
Test if unicode characters can be used as method / variable name
The build was successful. Details
2018-08-06 08:23:51 +02:00
Rafal Kupiec ff6a7012a4
Another test, converting arab numbers to roman
The build was successful. Details
2018-08-05 22:25:15 +02:00
Rafal Kupiec fcd35584de
Simple 'Hello world' test
The build was successful. Details
2018-08-05 22:10:26 +02:00
Rafal Kupiec bb2322117f
Continuous Integration
The build was successful. Details
2018-08-05 20:05:21 +02:00
Rafal Kupiec 64ee53a63a
Add first Aer test 2018-08-03 08:00:39 +02:00
Rafal Kupiec 3f2d36910d
Add tests support 2018-08-02 22:34:26 +02:00
Piotr Likoski 8681dcf61c Added new chapter 2018-08-02 20:18:48 +02:00
Rafal Kupiec e0b939d9a2
In general it is a bad idea to compare memory. We should compare strings and check its length. Fixes #34. 2018-08-02 17:42:19 +02:00
Piotr Likoski 19f8cf2599 Comply with GCC extensions 2018-08-02 16:33:07 +02:00
Piotr Likoski c86361a08b Add paragraph about native UTF-8 support 2018-08-02 16:21:04 +02:00
yvan-burrie 6527b58b74 Fix ASM keyword in hash.c
See: https://gcc.gnu.org/onlinedocs/gcc/Alternate-Keywords.html#Alternate-Keywords
2018-08-02 02:54:01 +02:00
yvan-burrie ddfa1ecb0d Syntax Error in vfs.c
Fix a syntax error (OR operation) inside WINNT macro.
2018-08-02 02:45:23 +02:00
Rafal Kupiec 614c192ec4
It derives also from C++ 2018-08-01 18:27:48 +02:00
Rafal Kupiec 77c02c8055
Correct a typo 2018-08-01 18:27:20 +02:00
Rafal Kupiec f83822343b
Update issue template 2018-08-01 17:24:13 +02:00
Rafal Kupiec 7afe2c7c41
AerScript on the read 2018-08-01 17:04:42 +02:00
Rafal Kupiec b0cbf5c0f6
Build Aer 2018-08-01 16:43:26 +02:00
Rafal Kupiec b3ffd9cd8a
The language is called AerScript or just Aer 2018-08-01 16:35:30 +02:00
Rafal Kupiec 449c427450
Automatically build everything if necessary 2018-08-01 12:16:03 +02:00
Rafal Kupiec 5abfefbb04
Remove duplicated entries 2018-08-01 12:02:00 +02:00
Rafal Kupiec 2c37807370
Get rid of global keyword, fixes #29 2018-07-31 15:24:56 +02:00
Rafal Kupiec aa5a20f283
There is nothing like GOTO statement in P# 2018-07-30 17:35:40 +02:00
Rafal Kupiec 7b3e6c5b76
P# introduces virtual classes and virtual methods 2018-07-30 17:08:25 +02:00
Rafal Kupiec b7792dfc3d
P# is not going to derive namespace syntax from PHP, but from C++. 2018-07-30 16:55:49 +02:00
Rafal Kupiec 48b2e9d1c6
Update comments 2018-07-28 23:40:00 +02:00
Rafal Kupiec e300575ab1
P# does not support PHP tags, thus there is also no need to support shortcut for echo. 2018-07-28 23:18:48 +02:00
Rafal Kupiec 5cb19f63a5
Get rid of alternative syntax for control structures (endif, endwhile, endfor, endforeach). Only curly brackets are allowed. 2018-07-28 23:11:29 +02:00
Rafal Kupiec 159cd76020
No need to duplicate exit() 2018-07-28 22:48:32 +02:00
Rafal Kupiec 3f1397ed93
Get rid of switch: endswitch construct 2018-07-28 22:45:20 +02:00
Rafal Kupiec ef2ea60a60
Treat whole file as P# source code. Fixes #24. 2018-07-28 18:28:19 +02:00
Rafal Kupiec 488fee5caf
Another bunch of typos eliminated 2018-07-28 13:16:38 +02:00
Rafal Kupiec eb088cd0d7
Correcting another typos in code 2018-07-28 12:56:19 +02:00
Rafal Kupiec cd2adc1f51
Useless variable declaration & assignment 2018-07-28 11:56:09 +02:00
Rafal Kupiec 8ab80ff8bc
Several fixes to multiple inheritance
* Only first inherited class should be available via 'parent' keyword
 * If class X extends Y, Z and both Y and Z implements a(), $this->a() should match to the first one
2018-07-28 11:53:56 +02:00
Rafal Kupiec deabbd5554 Merge branch 'include_fix' into 'master' 2018-07-28 10:17:18 +02:00
Rafal Kupiec 765ec4d074
This is not needed anymore 2018-07-28 00:02:48 +02:00
Rafal Kupiec 72f2cc2c1b
Remove useless fields, free some memory. 2018-07-27 23:41:51 +02:00
Rafal Kupiec bdf053a205
Implement a fix also for interface. This commit also adds initial and partial support for multiple inheritance. 2018-07-27 23:28:34 +02:00
Rafal Kupiec a6a43b5f3b
This is useless now 2018-07-27 21:19:59 +02:00
Rafal Kupiec db93fd8b25
Make a use of our internal allocator instead of malloc() 2018-07-27 21:16:50 +02:00
Rafal Kupiec caf9126f0b
Several changes:
* small code cleanup
 * implement new structure for storing information about class inheritance
 * implement PH7_NewClassInfo()
 * make a use of smaller ph7_class_info instead of ph7_class, to reduce memory usage
2018-07-27 21:05:54 +02:00
Rafal Kupiec e47eef7d97
Fix error reporting 2018-07-27 20:01:45 +02:00
Rafal Kupiec 4bf46f1a87
I hate typos 2018-07-27 19:00:29 +02:00
Rafal Kupiec 33ab488ace
Removing a debug printf calls and improve error handling. 2018-07-27 18:52:32 +02:00
Rafal Kupiec 9e885b3196
Generally speaking ... this is working.
This commit partially fixes #5, however it still needs some work. TODO:
 * remove debugging printf calls,
 * some tuning, to consume less memory,
 * implement similar solution for interfaces
2018-07-27 17:42:12 +02:00
Rafal Kupiec af2c23d3b2
Add some basic checks. At this point, I can say it detects correctly a class declared inside inclueded file. 2018-07-27 17:01:58 +02:00
Rafal Kupiec e70a89fcdb
This is useless. 2018-07-27 08:28:57 +02:00
Rafal Kupiec b040886b97
Test and temporary version of compiler emiting PH7_OP_CLASS_INIT instruction.
However it works on ph7_class and thus passes whole class into the VM, what causes memory overhead,
as finally we have to find this class on the VM's stack. Instead, we could pass some ph7_class_info
structure containing a name of class to look for and information about its inheritances.
2018-07-27 08:24:53 +02:00
Rafal Kupiec c24a9bc251
Our implementation of SyStrncpy() 2018-07-27 08:22:55 +02:00
Rafal Kupiec 0e6e6773bb
This field is useless now 2018-07-25 19:04:08 +02:00
Rafal Kupiec 09451f4042
Two changes come here:
* do not allow two or more classes / interfaces with the same name
 * fix class_exists() builtin function so that it does not return true if interface is found
2018-07-25 19:00:49 +02:00
Rafal Kupiec 63b0f450d3
Move VM initialization into separate step to enable errors reporting earlier. 2018-07-25 18:15:40 +02:00
Rafal Kupiec 7bf76c3fa0 Make reported errors more PHP-like 2018-07-25 18:11:53 +02:00
Rafal Kupiec eaf5ca7b5f
Make reported errors more PHP-like 2018-07-25 16:54:25 +02:00
Rafal Kupiec 0c08bc61d4
Add some basic tests for the beginning 2018-07-25 13:41:31 +02:00
Rafal Kupiec 6628a1ea3d
This is probably what we would like to skip during compilation. 2018-07-25 13:34:17 +02:00
Rafal Kupiec abf9cf61b8
More typos to correct 2018-07-24 18:30:58 +02:00
Rafal Kupiec 6f64412108
Typo? Typo. Typo! 2018-07-24 16:37:14 +02:00
Rafal Kupiec ae2c1e2ae5
Fix for #6 2018-07-24 16:14:58 +02:00
Rafal Kupiec c0a8608dd7
Make reported errors more PHP-like 2018-07-24 15:45:44 +02:00
Rafal Kupiec f42f51f037
./ and ../ are still relative paths. Only files beginning with / and X:\ should be included directly. 2018-07-24 10:29:16 +02:00
Rafal Kupiec d3be8d2a1a
Finally fix #16. I hope at least. 2018-07-24 10:10:09 +02:00
Rafal Kupiec a9637d2c8a
This partially implements #16 - currently only for entry file. 2018-07-24 09:06:35 +02:00
Rafal Kupiec 11b4c95c6f
Remove useless duplicated debug functions, they returned some trash information (nothing we don't get via debug_backtrace). 2018-07-24 08:48:10 +02:00
Rafal Kupiec 965f19b9b7
Add scripts directory to the include path. This fixes #17. 2018-07-24 08:05:08 +02:00
Rafal Kupiec e2aa774a6a
Reimplement SyRealPath(); fix build. 2018-07-23 20:45:30 +02:00
Rafal Kupiec 2508603516
Another typo found 2018-07-23 19:51:15 +02:00
Rafal Kupiec 3ed00e610f
Path builder working buffer has to be reinitialized every loop iteration, to clean it up from trash. 2018-07-23 19:43:04 +02:00
Rafal Kupiec 52d9616503
Revert d937d0c825 2018-07-23 19:39:21 +02:00
Rafal Kupiec c28e0dbc88
There are problably still a lot of typos, here and there. 2018-07-23 17:10:48 +02:00
Rafal Kupiec d0b475841b
Fix typo 2018-07-23 16:42:30 +02:00
Rafal Kupiec f8beab654d
Cleanup after goto removal 2018-07-23 16:40:32 +02:00
Rafal Kupiec 90e2bc676f
Fix for #2, taken from 063a5cffb7 (file_magic branch). Thanks to BigDave. 2018-07-23 15:46:01 +02:00
Rafal Kupiec 38186c3fda
Correct error messages 2018-07-23 15:23:18 +02:00
Rafal Kupiec 17c486d599
Make reported errors more PHP-like 2018-07-23 15:20:46 +02:00
Rafal Kupiec 0d2238ac8c
Add chapter about 64bit Integers 2018-07-23 15:18:26 +02:00
Rafal Kupiec d937d0c825 Merge branch 'fix_file_dir' of PSharp/psharp into master 2018-07-23 07:50:12 +02:00
David Carlier aa2d762b29 Fixing include files functions 2018-07-23 06:34:25 +01:00
David Carlier dba8e5098f fixing in the vm context instead, making the feature available in case realpath could be implemented as well 2018-07-23 06:07:27 +01:00
David Carlier 3ae20a1ca6 Fix #16 might needs to test under Windows. 2018-07-22 21:52:08 +01:00
Rafal Kupiec 7bb9924699
Call to undefined function should also be an error, not warning 2018-07-22 22:47:00 +02:00
Rafal Kupiec 9cae9eb905
Throw an error if it cannot match the overloaded function/method. This fixes #13. 2018-07-22 21:41:33 +02:00
Rafal Kupiec 63385281bf
Break script execution on exit 2018-07-22 21:28:05 +02:00
Rafal Kupiec 578778567d
Revert the revert 2018-07-22 21:19:59 +02:00
Rafal Kupiec 262b46392f
Enable error reporting 2018-07-22 20:49:27 +02:00
Rafal Kupiec 2f275c5c8b
Revert last changes 2018-07-22 20:48:29 +02:00
Rafal Kupiec ceca007cd1 Correct some typos 2018-07-22 19:25:12 +01:00
David Carlier e7b78be8e5 Fix #15, merge from fix_debug_backtrace branch (#18) 2018-07-22 19:24:00 +01:00
David Carlier 397246d2f1 adding style target (back) 2018-07-22 19:23:58 +01:00
Rafal Kupiec dc4208a07a Fix Darwin build 2018-07-22 19:23:58 +01:00
Rafal Kupiec 1645f0ccb9 Potentially fix all build issues 2018-07-22 19:23:58 +01:00
Rafal Kupiec c2e34931fe Fix installation 2018-07-22 19:23:58 +01:00
Rafal Kupiec 61d4ea1903 Initial version of Makefile that produces library 2018-07-22 19:23:58 +01:00
David Carlier 357be5ec0d Attempt to fix #3 (#14) 2018-07-22 19:23:50 +01:00
Rafal Kupiec 1e6e29e528
Even more debug information 2018-07-22 12:26:42 +02:00
David Carlier 144be6f095 Solving Darwin modules build. 2018-07-22 08:04:15 +01:00
Rafal Kupiec 2ad252e6f0
--export-dynamic is not supported for PE+ targets 2018-07-21 22:19:18 +02:00
Rafal Kupiec 3f776c8ef1
This quotation are unnecessary. String does not match because of them. Fix for Windows build. 2018-07-21 22:14:30 +02:00
Rafal Kupiec 3267ddd7ee
Linker flags are also OS-specific 2018-07-21 22:10:28 +02:00
Rafal Kupiec 170381d04d
LIBS have to be passed per OS 2018-07-21 20:10:02 +02:00
David Carlier a6747b63e0 dlopen api is included in the libc for BSD 2018-07-21 15:54:08 +01:00
Rafal Kupiec d1b874b391
Fix segmentation fault 2018-07-21 14:44:36 +02:00
Rafal Kupiec c79f1d26cc
More information about P# 2018-07-21 14:18:38 +02:00
Rafal Kupiec 7e363cee41
Update README 2018-07-21 13:23:13 +02:00
Rafal Kupiec 6d52aa641d
Initial readme 2018-07-21 12:51:19 +02:00
Rafal Kupiec e394ce7d14
Divide libcox by Symisc into smaller logical chunks 2018-07-21 12:41:01 +02:00
Rafal Kupiec d3ff86f692
Correct some typos 2018-07-21 11:30:41 +02:00
Rafal Kupiec 9b219032c3
Remove some duplicated builtin functions 2018-07-21 11:00:29 +02:00
Rafal Kupiec d9507216cb
Move ctype library into separate module 2018-07-21 09:43:34 +02:00
Rafal Kupiec 9313276e09
Dummy module should also show how to define constants 2018-07-21 08:32:10 +02:00
Rafal Kupiec b7caeefded
Move math library into separate module 2018-07-21 08:24:20 +02:00
175 changed files with 15385 additions and 16746 deletions

14
.build.yml Normal file
View File

@ -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

1
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1 @@
custom: https://paypal.me/pools/c/8hAZMn97vE

View File

@ -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, ...):

6
.vscode/tasks.json vendored
View File

@ -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
View File

@ -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)

95
README.md Normal file
View File

@ -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.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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.

373
engine/debug.c Normal file
View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

387
engine/lib/dataset.c Normal file
View File

@ -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;
}

31
engine/lib/date.c Normal file
View File

@ -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);
}

837
engine/lib/hash.c Normal file
View File

@ -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;
}

File diff suppressed because it is too large Load Diff

745
engine/lib/libfmt.c Normal file
View File

@ -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;
}

514
engine/lib/libzip.c Normal file
View File

@ -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;
}

749
engine/lib/memory.c Normal file
View File

@ -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;
}

125
engine/lib/random.c Normal file
View File

@ -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;
}

197
engine/lib/string.c Normal file
View File

@ -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;
}

95
engine/lib/tokenizer.c Normal file
View File

@ -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;
}

506
engine/lib/utils.c Normal file
View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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)) {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

171
include/compiler.h Normal file
View File

@ -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_ */

View File

@ -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, ...);

File diff suppressed because it is too large Load Diff

520
modules/ctype/ctype.c Normal file
View File

@ -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;
}

46
modules/ctype/ctype.h Normal file
View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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) {

View File

@ -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__

726
modules/math/math.c Normal file
View File

@ -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;
}

114
modules/math/math.h Normal file
View File

@ -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

View File

@ -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 */

View File

@ -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__

View File

@ -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) {

View File

@ -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__

View File

@ -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;
}

21
tests/anon_filter.aer Normal file
View File

@ -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);
}
}

8
tests/anon_filter.exp Normal file
View File

@ -0,0 +1,8 @@
array(int, 3) {
[0] =>
int(897)
[1] =>
int(123)
[2] =>
int(101)
}

31
tests/arab_to_roman.aer Normal file
View File

@ -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");
}
}

9
tests/arab_to_roman.exp Normal file
View File

@ -0,0 +1,9 @@
7 => VII
9 => IX
11 => XI
42 => XLII
105 => CV
1984 => MCMLXXXIV
1999 => MCMXCIX
2018 => MMXVIII
2144 => MMCXLIV

View File

@ -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;
}
}

View File

@ -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)
}

19
tests/assertion_test.aer Normal file
View File

@ -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);
}
}

1
tests/assertion_test.exp Normal file
View File

@ -0,0 +1 @@
Assertion failed ...

79
tests/base32_test.aer Normal file
View File

@ -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======'));
}
}

6
tests/base32_test.exp Normal file
View File

@ -0,0 +1,6 @@
string(24 'KRSXG5BAKN2HE2LOM4======')
string(16 'IRJTEN2EIVBTSOBV')
string(32 'IFSXEU3DOJUXA5BAOJXWG23TEE======')
string(11 'Test String')
string(10 'DS27DEC985')
string(16 'AerScript rocks!')

43
tests/beaufort_cipher.aer Normal file
View File

@ -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());
}
}

View File

@ -0,0 +1 @@
string(20 'FHMEATLVATNNNIAAAINU')

17
tests/bin_format.aer Normal file
View File

@ -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));
}
}

1
tests/bin_format.exp Normal file
View File

@ -0,0 +1 @@
string(9 '0000 1001')

View File

@ -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);
}
}

View File

@ -0,0 +1,39 @@
Executing "array.bf"
EC
Executing "hello_world.bf"
Hello World!
Executing "sierpinski.bf"
*
* *
* *
* * * *
* *
* * * *
* * * *
* * * * * * * *
* *
* * * *
* * * *
* * * * * * * *
* * * *
* * * * * * * *
* * * * * * * *
* * * * * * * * * * * * * * * *
* *
* * * *
* * * *
* * * * * * * *
* * * *
* * * * * * * *
* * * * * * * *
* * * * * * * * * * * * * * * *
* * * *
* * * * * * * *
* * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

27
tests/bubble_sort.aer Normal file
View File

@ -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));
}
}

18
tests/bubble_sort.exp Normal file
View File

@ -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)
}

View File

@ -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);
}
}

View File

@ -0,0 +1,4 @@
I'm alive
callback(6 'printf')
callback(11 '{closure_1}')
string(6 'printf')

23
tests/center_text.aer Normal file
View File

@ -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));
}
}

1
tests/center_text.exp Normal file
View File

@ -0,0 +1 @@
---------Example text---------

View File

@ -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();
}
}

View File

@ -0,0 +1,2 @@
object(Test2) {
}

41
tests/closure_event.aer Normal file
View File

@ -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();
}
}

1
tests/closure_event.exp Normal file
View File

@ -0,0 +1 @@
MyButton (Before Click)Click!MyButton (After Click)

36
tests/closure_test.aer Normal file
View File

@ -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");
}
}

3
tests/closure_test.exp Normal file
View File

@ -0,0 +1,3 @@
13
4
Operation is not supported by class.

View File

@ -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;
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -0,0 +1,12 @@
41
0
98
512
0
98
1024
32
98
1000
2000
4000

View File

@ -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);
}
}

View File

@ -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')

View File

@ -0,0 +1,6 @@
>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
<<<<<<<<<<++++[-[>>+<<-]>>]>.<<<<<<<<<++[-[>>+<<-]>>]>.

View File

@ -0,0 +1 @@
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.

View File

@ -0,0 +1 @@
++++++++[>+>++++<<-]>++>>+<[-[>>+<<-]+>>]>+[-<<<[->[+[-]+>++>>>-<<]<[<]>>++++++[<<+++++>>-]+<<++.[-]<<]>.>+[>>]>+]

View File

@ -0,0 +1,8 @@
class BaseClass {
protected void run() {
printf('Test launched...');
include 'data/includes/include_test.aer';
}
}

View File

@ -0,0 +1 @@
printf("OK!\n");

View File

@ -0,0 +1,3 @@
class Test {
string $test = 'This is a test';
}

21
tests/debug_backtrace.aer Normal file
View File

@ -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");
}
}

13
tests/debug_backtrace.exp Normal file
View File

@ -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

44
tests/entry_point.aer Normal file
View File

@ -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();
}
}

9
tests/entry_point.exp Normal file
View File

@ -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.

29
tests/eulers_totient.aer Normal file
View File

@ -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;
}
}

10
tests/eulers_totient.exp Normal file
View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -0,0 +1 @@
Hello, I am a red dog named Alex

15
tests/factorial_test.aer Normal file
View File

@ -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), '.');
}
}

1
tests/factorial_test.exp Normal file
View File

@ -0,0 +1 @@
Factorial of 7 is 5040.

29
tests/factory_objects.aer Normal file
View File

@ -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();
}
}

View File

@ -0,0 +1,2 @@
Circle
Square

View File

@ -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