├── src ├── jit │ ├── jitcomp.h │ ├── disasm.h │ ├── jit.h │ ├── stack.h │ ├── Makefile │ ├── data.h │ ├── flow.h │ ├── genclang.h │ ├── typed.h │ ├── block.h │ ├── jitcomp.cpp │ ├── code.h │ ├── instruction.h │ └── flow.cpp ├── kfun │ ├── rgx │ │ ├── libiberty │ │ │ ├── config │ │ │ └── xregex.h │ │ ├── README.md │ │ ├── doc │ │ │ └── kfun │ │ │ │ └── regexp │ │ ├── doc-0.3 │ │ │ └── regexps │ │ └── Makefile.diff │ ├── tls │ │ ├── doc │ │ │ ├── tls_close │ │ │ ├── tls_send │ │ │ ├── tls_server │ │ │ ├── tls_client │ │ │ └── tls_receive │ │ └── README.md │ ├── zlib │ │ ├── doc │ │ │ ├── gunzip │ │ │ ├── inflate │ │ │ ├── gzip │ │ │ └── deflate │ │ ├── README.md │ │ ├── 1.2.11 │ │ │ ├── LICENSE │ │ │ ├── inftrees.h │ │ │ ├── inflate.h │ │ │ └── zutil.h │ │ ├── 1.2.12 │ │ │ ├── LICENSE │ │ │ ├── inftrees.h │ │ │ ├── inflate.h │ │ │ └── zutil.h │ │ └── 1.2.8 │ │ │ ├── LICENSE │ │ │ ├── inftrees.h │ │ │ ├── inflate.h │ │ │ └── zutil.h │ └── lower_case.c ├── dllmain.cpp ├── Makefile ├── lpc_ext.h ├── lpc_ext.c └── dbase │ └── dbase.c ├── project ├── jit │ ├── jit.vcxproj.filters │ └── jit.vcxproj ├── lower_case │ ├── lower_case.vcxproj.filters │ └── lower_case.vcxproj ├── lpc-ext │ ├── lpc-ext.vcxproj.filters │ └── lpc-ext.vcxproj ├── regexp │ ├── regexp.vcxproj.filters │ └── regexp.vcxproj └── jitcomp │ ├── jitcomp.vcxproj.filters │ └── jitcomp.vcxproj ├── LICENSE ├── doc ├── JIT.md └── extensions.md ├── jitcomp.sln ├── README.md └── lpc-ext.sln /src/jit/jitcomp.h: -------------------------------------------------------------------------------- 1 | extern void fatal (const char*, ...); 2 | -------------------------------------------------------------------------------- /src/kfun/rgx/libiberty/config: -------------------------------------------------------------------------------- 1 | -DHAVE_ALLOCA_H=1 2 | -DHAVE_LIMITS_H=1 3 | -DHAVE_STRING_H=1 4 | -DHAVE_UINTPTR_T=1 5 | -DSTDC_HEADERS=1 6 | -------------------------------------------------------------------------------- /src/dllmain.cpp: -------------------------------------------------------------------------------- 1 | # include 2 | 3 | BOOL APIENTRY DllMain(HMODULE module, DWORD why, LPVOID ptr) 4 | { 5 | return TRUE; 6 | } 7 | -------------------------------------------------------------------------------- /src/kfun/tls/doc/tls_close: -------------------------------------------------------------------------------- 1 | NAME 2 | tls_close - close a TLS session 3 | 4 | SYNOPSIS 5 | string tls_close() 6 | 7 | 8 | DESCRIPTION 9 | Close the TLS session that is associated with the current object. This 10 | will deallocate the internal TLS context. The returned string, if not 11 | nil, will tell the other side to shut down the TLS session. 12 | 13 | SEE ALSO 14 | kfun/tls_client, kfun/tls_receive, kfun/tls_send, kfun/tls_server 15 | -------------------------------------------------------------------------------- /src/kfun/tls/doc/tls_send: -------------------------------------------------------------------------------- 1 | NAME 2 | tls_send - send a string in a TLS session 3 | 4 | SYNOPSIS 5 | string *tls_send(string str) 6 | 7 | 8 | DESCRIPTION 9 | Process a message to be sent in a TLS session. The returned value is 10 | an array of 2 strings: 11 | 12 | 0: output which could not be processed at this time 13 | 1: encrypted output to send to the other side 14 | 15 | ERRORS 16 | Any errors that may occur are unrecoverable, requiring the TLS session 17 | to be closed. 18 | 19 | SEE ALSO 20 | kfun/tls_client, kfun/tls_close, kfun/tls_receive, kfun/tls_server 21 | -------------------------------------------------------------------------------- /src/kfun/tls/doc/tls_server: -------------------------------------------------------------------------------- 1 | NAME 2 | tls_server - start a server TLS session 3 | 4 | SYNOPSIS 5 | void tls_server(string certificate, string key) 6 | 7 | 8 | DESCRIPTION 9 | Start a server TLS session. The arguments certificate and key are 10 | the paths of files, in PEM format, with the certificate chain and 11 | private key to use. These path are relative to the configured 12 | directory of the TLS module. 13 | The current object will be associated with the TLS session, and should 14 | not be destructed before tls_close() is called, or memory will leak. 15 | 16 | SEE ALSO 17 | kfun/tls_client, kfun/tls_close, kfun/tls_receive, kfun/tls_send 18 | -------------------------------------------------------------------------------- /src/kfun/tls/README.md: -------------------------------------------------------------------------------- 1 | These kfuns manage a TLS session. The current object is associated with the 2 | OpenSSL context, which must be freed using `tls_close()` before the object is 3 | destructed. The configuration argument for the module specifies the 4 | directory which contains the certificate chain and key files, both in PEM 5 | format. 6 | 7 | Several constraints apply. Since the TLS state is kept inside OpenSSL 8 | datastructures, these functions cannot be used from atomic code, and will 9 | not work properly in Hydra where the entire task in which they are used 10 | could be rolled back. Furthermore, the TLS state will not persist during 11 | a hotboot; `tls_close()` must be called before the hotboot occurs. 12 | -------------------------------------------------------------------------------- /src/kfun/tls/doc/tls_client: -------------------------------------------------------------------------------- 1 | NAME 2 | tls_client - start a client TLS session 3 | 4 | SYNOPSIS 5 | string tls_client(varargs string certificate, string key) 6 | 7 | 8 | DESCRIPTION 9 | Start a client TLS session. The optional arguments certificate and key 10 | are the paths of files, in PEM format, with the certificate chain and 11 | private key to use. These path are relative to the configured 12 | directory of the TLS module. The return value is the initial string 13 | to send to the server. 14 | The current object will be associated with the TLS session, and should 15 | not be destructed before tls_close() is called, or memory will leak. 16 | 17 | SEE ALSO 18 | kfun/tls_close, kfun/tls_receive, kfun/tls_send, kfun/tls_server 19 | -------------------------------------------------------------------------------- /src/kfun/zlib/doc/gunzip: -------------------------------------------------------------------------------- 1 | NAME 2 | gunzip - decompress a string 3 | 4 | SYNOPSIS 5 | string *gunzip(varargs string str, int flag) 6 | 7 | 8 | DESCRIPTION 9 | Decompress a string compressed with gzip compression. This function can 10 | only be called from a persistent object, and preserves state between 11 | calls. It can be called repeatedly to keep adding compressed strings 12 | to the internal state, and returns an array of decompressed strings. 13 | The optional flag specifies whether the internal buffer should be 14 | flushed. 15 | To finish decompression, flush the internal buffer and discard the 16 | internal decompression state, call gunzip() without arguments. 17 | 18 | SEE ALSO 19 | kfun/deflate, kfun/gzip, kfun/inflate 20 | -------------------------------------------------------------------------------- /src/kfun/zlib/doc/inflate: -------------------------------------------------------------------------------- 1 | NAME 2 | inflate - decompress a string 3 | 4 | SYNOPSIS 5 | string *inflate(varargs string str, int flag) 6 | 7 | 8 | DESCRIPTION 9 | Decompress a string compressed with deflate compression. This function 10 | can only be called from a persistent object, and preserves state between 11 | calls. It can be called repeatedly to keep adding compressed strings 12 | to the internal state, and returns an array of decompressed strings. 13 | The optional flag specifies whether the internal buffer should be 14 | flushed. 15 | To finish decompression, flush the internal buffer and discard the 16 | internal decompression state, call inflate() without arguments. 17 | 18 | SEE ALSO 19 | kfun/deflate, kfun/gunzip, kfun/gzip 20 | -------------------------------------------------------------------------------- /src/jit/disasm.h: -------------------------------------------------------------------------------- 1 | class DisCode : public FlowCode { 2 | public: 3 | DisCode(CodeFunction *function); 4 | virtual ~DisCode(); 5 | 6 | virtual void emit(class GenContext *context); 7 | 8 | static Code *create(CodeFunction *function); 9 | 10 | private: 11 | void emitType(GenContext *context, LPCType *type); 12 | }; 13 | 14 | class DisBlock : public FlowBlock { 15 | public: 16 | DisBlock(Code *first, Code *last, CodeSize size); 17 | virtual ~DisBlock(); 18 | 19 | virtual void emit(class GenContext *context, CodeFunction *function); 20 | 21 | static Block *create(Code *first, Code *last, CodeSize size); 22 | }; 23 | 24 | class DisFunction { 25 | public: 26 | static void emit(FILE *stream, CodeFunction *function); 27 | }; 28 | -------------------------------------------------------------------------------- /src/kfun/zlib/doc/gzip: -------------------------------------------------------------------------------- 1 | NAME 2 | gzip - compress a string 3 | 4 | SYNOPSIS 5 | string *gzip(varargs string str, int mode) 6 | 7 | 8 | DESCRIPTION 9 | Compress a string using gzip compression. This function can only be 10 | called from a persistent object, and preserves state between calls. 11 | It can be called repeatedly to keep adding strings to the compressed 12 | state, and returns an array of compressed strings. 13 | The optional mode argument is interpreted as the compression level in 14 | the first call (0 to 9, default is 6) and as a flag that specifies 15 | whether the internal buffer should be flushed in followup calls. 16 | To finish compression, flush the internal buffer and discard the 17 | internal compression state, call gzip() without arguments. 18 | 19 | SEE ALSO 20 | kfun/deflate, kfun/gunzip, kfun/inflate 21 | -------------------------------------------------------------------------------- /src/kfun/rgx/README.md: -------------------------------------------------------------------------------- 1 | This package adds the following regular expression matching kfun to DGD, using 2 | the DGD extension interface: 3 | ``` 4 | regexp(pattern, str, case_insensitive, reverse) 5 | ``` 6 | For a description of the regular expression language accepted by this kfun, 7 | please read `doc-0.3/regexps`. 8 | 9 | To install, move `regexp.c` and `libiberty` into `dgd/src`, apply 10 | `Makefile.diff` to `dgd/src/Makefile`, and fully recompile DGD. 11 | 12 | This package is based on Robert Leslie's regular expression matching 13 | package `rgx-0.3`. The files in the directory `libiberty` were copied from 14 | `gdb-6.8`, and are released under the GNU LGPL. The file `doc-0.3/regexps` is 15 | from rgx 0.3 (slightly modified by me), and was released under GPLv2. All 16 | other files are new with this release, and are released under GPLv3. 17 | -------------------------------------------------------------------------------- /src/kfun/zlib/doc/deflate: -------------------------------------------------------------------------------- 1 | NAME 2 | deflate - compress a string 3 | 4 | SYNOPSIS 5 | string *deflate(varargs string str, int mode) 6 | 7 | 8 | DESCRIPTION 9 | Compress a string using deflate compression. This function can only be 10 | called from a persistent object, and preserves state between calls. 11 | It can be called repeatedly to keep adding strings to the compressed 12 | state, and returns an array of compressed strings. 13 | The optional mode argument is interpreted as the compression level in 14 | the first call (0 to 9, default is 6) and as a flag that specifies 15 | whether the internal buffer should be flushed in followup calls. 16 | To finish compression, flush the internal buffer and discard the 17 | internal compression state, call deflate() without arguments. 18 | 19 | SEE ALSO 20 | kfun/gunzip, kfun/gzip, kfun/inflate 21 | -------------------------------------------------------------------------------- /src/kfun/tls/doc/tls_receive: -------------------------------------------------------------------------------- 1 | NAME 2 | tls_receive - receive a string in a TLS session 3 | 4 | SYNOPSIS 5 | string *tls_receive(string str) 6 | 7 | 8 | DESCRIPTION 9 | Process an encrypted message received in a TLS session. The return 10 | value is an array of 4 strings: 11 | 12 | 0: input which could not be processed at this time 13 | 1: decrypted input 14 | 2: output to send to the other side immediately without further 15 | processing (protocol negotiation) 16 | 3: a status value that can be "connecting", nil, or an error 17 | message (with the latter also indicating that the session was 18 | shut down, and should be closed) 19 | 20 | ERRORS 21 | Any errors that may occur are unrecoverable, requiring the TLS session 22 | to be closed. 23 | 24 | SEE ALSO 25 | kfun/tls_client, kfun/tls_close, kfun/tls_send, kfun/tls_server 26 | -------------------------------------------------------------------------------- /src/kfun/rgx/doc/kfun/regexp: -------------------------------------------------------------------------------- 1 | NAME 2 | regexp - match a regular expression 3 | 4 | SYNOPSIS 5 | int *regexp(string pattern, string str, 6 | varargs int case_insensive, int reverse) 7 | 8 | DESCRIPTION 9 | The argument str is matched against the regular expression pattern. 10 | If the argument case_insensitive is nonzero, the match is 11 | case-insensitive. If the argument reverse is nonzero, matching is 12 | performed from right-to-left; otherwise, matching is performed 13 | left-to-right. 14 | If the argument str could not be matched with the regular expression, 15 | nil is returned. Otherwise, an array is returned containing the 16 | offset in str of the first character of the match, followed by the 17 | offset in str of the last character of the match. For any matched 18 | subexpressions, further pairs of offsets are appended to the array. 19 | 20 | SEE ALSO 21 | kfun/parse_string 22 | -------------------------------------------------------------------------------- /src/kfun/rgx/libiberty/xregex.h: -------------------------------------------------------------------------------- 1 | /* This file redefines all regex external names before including 2 | a renamed copy of glibc's regex.h. */ 3 | 4 | #ifndef _XREGEX_H 5 | #define _XREGEX_H 1 6 | 7 | # define regfree xregfree 8 | # define regexec xregexec 9 | # define regcomp xregcomp 10 | # define regerror xregerror 11 | # define re_set_registers xre_set_registers 12 | # define re_match_2 xre_match_2 13 | # define re_match xre_match 14 | # define re_search xre_search 15 | # define re_compile_pattern xre_compile_pattern 16 | # define re_set_syntax xre_set_syntax 17 | # define re_search_2 xre_search_2 18 | # define re_compile_fastmap xre_compile_fastmap 19 | # define re_syntax_options xre_syntax_options 20 | # define re_max_failures xre_max_failures 21 | 22 | # define _REGEX_RE_COMP 23 | # define re_comp xre_comp 24 | # define re_exec xre_exec 25 | 26 | #include "xregex2.h" 27 | 28 | #endif /* xregex.h */ 29 | -------------------------------------------------------------------------------- /src/kfun/zlib/README.md: -------------------------------------------------------------------------------- 1 | The compression functionality offered by zlib allocates internal buffers. 2 | Zlib supports user-supplied allocation functions, allowing the kfun module 3 | to store these buffers in LPC strings. However, zlib does not support 4 | relocation of buffers, which is needed by the kfun module. 5 | 6 | Therefore, the kfun module does its own reallocation, adjusting pointers when 7 | needed. This means that the kfun module has to know about zlib internal 8 | datastructures, which can change between zlib versions. Currently, the 9 | kfun module supports zlib versions 1.2.8, 1.2.11 to 1.2.13, and 1.3. 10 | 11 | Thanks to buffer reallocation, the compression kfuns can be used in atomic 12 | functions (an error will roll back the compression state too) and across 13 | hotboots. Note that it is not possible to preserve compression state while 14 | hotbooting to a different CPU architecture or to a different zlib version. 15 | -------------------------------------------------------------------------------- /project/jit/jit.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Header Files 16 | 17 | 18 | 19 | 20 | Source Files 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/jit/jit.h: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | uint8_t major; /* 2 */ 3 | uint8_t minor; /* 4 */ 4 | uint16_t flags; /* flags */ 5 | size_t intSize; /* size of Int */ 6 | size_t inheritSize; /* size of inherit offset */ 7 | int nBuiltins; /* # builtin prototypes */ 8 | int nKfuns; /* # kfun prototypes */ 9 | size_t protoSize; /* size of all prototypes together */ 10 | } JitInfo; 11 | 12 | typedef struct { 13 | uint8_t flags; /* flags (affects checksum) */ 14 | uint8_t intInheritSize; /* integer & inherit size */ 15 | uint16_t nInherits; /* # inherited objects */ 16 | int nFunctions; /* # functions */ 17 | size_t progSize; /* program size */ 18 | size_t fTypeSize; /* function type size */ 19 | size_t vTypeSize; /* variable type size */ 20 | } JitCompile; 21 | 22 | /* flags */ 23 | # define JIT_TYPECHECKING 0x0f /* typechecking mode */ 24 | # define JIT_NOREF 0x10 /* no reference counting */ 25 | -------------------------------------------------------------------------------- /project/lower_case/lower_case.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Header Files 16 | 17 | 18 | 19 | 20 | Source Files 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/jit/stack.h: -------------------------------------------------------------------------------- 1 | typedef uint32_t StackSize; 2 | 3 | enum StackPointer { 4 | STACK_EMPTY = 0, 5 | STACK_INVALID = 0xffff 6 | }; 7 | 8 | template class Stack { 9 | public: 10 | Stack(StackSize size) { 11 | elements = new Elem[size]; 12 | nElems = STACK_EMPTY; 13 | } 14 | 15 | virtual ~Stack() { 16 | delete[] elements; 17 | } 18 | 19 | StackSize push(StackSize pointer, const T &item) { 20 | elements[++nElems].item = item; 21 | elements[nElems].next = pointer; 22 | return nElems; 23 | } 24 | 25 | StackSize pop(StackSize pointer) { 26 | return elements[pointer].next; 27 | } 28 | 29 | void set(StackSize pointer, const T &item) { 30 | elements[pointer].item = item; 31 | } 32 | 33 | T &get(StackSize pointer) { 34 | return elements[pointer].item; 35 | } 36 | 37 | private: 38 | struct Elem { 39 | T item; 40 | StackSize next; 41 | }; 42 | 43 | Elem *elements; 44 | StackSize nElems; 45 | }; 46 | -------------------------------------------------------------------------------- /project/lpc-ext/lpc-ext.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Header Files 16 | 17 | 18 | 19 | 20 | Source Files 21 | 22 | 23 | Source Files 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/kfun/zlib/1.2.11/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright notice from zlib 1.2.11: 2 | 3 | (C) 1995-2017 Jean-loup Gailly and Mark Adler 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | 21 | Jean-loup Gailly Mark Adler 22 | jloup@gzip.org madler@alumni.caltech.edu 23 | -------------------------------------------------------------------------------- /src/kfun/zlib/1.2.12/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright notice from zlib 1.2.12: 2 | 3 | (C) 1995-2022 Jean-loup Gailly and Mark Adler 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | 21 | Jean-loup Gailly Mark Adler 22 | jloup@gzip.org madler@alumni.caltech.edu 23 | -------------------------------------------------------------------------------- /src/kfun/zlib/1.2.8/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright notice from zlib 1.2.8: 2 | 3 | Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | 21 | Jean-loup Gailly Mark Adler 22 | jloup@gzip.org madler@alumni.caltech.edu 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /doc/JIT.md: -------------------------------------------------------------------------------- 1 | The JIT compiler consists of two parts, the jit module and the `jitcomp` 2 | program. The jit module is loaded by Hydra or DGD: 3 | ``` 4 | modules = ([ "/home/user/lpc-ext/jit.1.5" : "/home/user/lpc-ext/src/jit" ]); 5 | ``` 6 | The directory `/home/user/lpc-ext/jit` specifies where the `jitcomp` program 7 | can be found, and where the JIT compiler cache will be created. 8 | 9 | The jit module saves LPC bytecode programs in the cache. The compiler then 10 | decompiles the bytecode into basic blocks, performs flow analysis, 11 | determines the types of variables and expressions, and emits LLVM IR as a `.ll` 12 | file in the cache. Clang is executed to compile the `.ll` file into a shared 13 | object, and if the compilation succeeds the jit module will load the shared 14 | object and make the code available to the LPC runtime. 15 | 16 | Running the `jitcomp` program independently ensures that any memory leaks and 17 | crashes will not affect the main program. Storing the JIT-compiled objects in 18 | a cache makes them available for re-use. 19 | 20 | Decompiling to LLVM IR, and using clang to compile that to a shared object, 21 | simplifies JIT compilation considerably. Decompiling to LLVM bitcode, and 22 | compiling that using the LLVM libraries, is left as an exercise to the reader. 23 | -------------------------------------------------------------------------------- /src/jit/Makefile: -------------------------------------------------------------------------------- 1 | #DISASM=1 2 | GENCLANG=1 3 | 4 | DEFINES= 5 | DEBUG= 6 | ifdef DISASM 7 | CODEGEN=-DDISASM 8 | endif 9 | ifdef GENCLANG 10 | CODEGEN=-DGENCLANG 11 | endif 12 | CXX=c++ 13 | CXXFLAGS=$(DEFINES) $(DEBUG) $(CODEGEN) -I.. 14 | 15 | OBJ= code.o block.o typed.o flow.o jitcomp.o 16 | ifdef DISASM 17 | OBJ+=disasm.o 18 | endif 19 | ifdef GENCLANG 20 | OBJ+=genclang.o 21 | endif 22 | 23 | all: jitcomp 24 | 25 | jitcomp: $(OBJ) 26 | $(CXX) $(DEBUG) -o jitcomp $(OBJ) 27 | 28 | jit.o: jit.c jit.h ../lpc_ext.h 29 | $(CC) -c $(CFLAGS) $(CODEGEN) -I.. jit.c 30 | 31 | clean: 32 | rm -rf jit.o $(OBJ) gentt.h jitcomp cache 33 | 34 | gentt.h: 35 | clang -v 2>&1 | \ 36 | sed -n 's/Target: \(.*\)/# define TARGET_TRIPLE "\1"/p' > gentt.h 37 | 38 | $(OBJ): ../lpc_ext.h data.h jitcomp.h 39 | code.o: instruction.h code.h 40 | block.o: code.h stack.h block.h 41 | typed.o: instruction.h code.h stack.h block.h typed.h 42 | flow.o: code.h stack.h block.h typed.h flow.h 43 | disasm.o: code.h stack.h block.h typed.h flow.h disasm.h 44 | genclang.o: instruction.h code.h stack.h block.h typed.h flow.h gentt.h \ 45 | genclang.h 46 | jitcomp.o: code.h stack.h block.h typed.h flow.h jit.h 47 | ifdef DISASM 48 | jitcomp.o: disasm.h 49 | endif 50 | ifdef GENCLANG 51 | jitcomp.o: genclang.h 52 | endif 53 | -------------------------------------------------------------------------------- /src/kfun/lower_case.c: -------------------------------------------------------------------------------- 1 | /* 2 | * lower_case() kfun extension 3 | * This code is released into the public domain. 4 | */ 5 | 6 | # include "lpc_ext.h" 7 | 8 | static void lower_case(LPC_frame f, int nargs, LPC_value retval) 9 | { 10 | LPC_value val; 11 | LPC_string str; 12 | LPC_dataspace data; 13 | char *p; 14 | unsigned int i; 15 | 16 | /* tick cost */ 17 | lpc_runtime_check(f, 6); 18 | 19 | /* fetch the argument string */ 20 | val = lpc_frame_arg(f, nargs, 0); 21 | str = lpc_string_getval(val); 22 | 23 | /* make a copy */ 24 | data = lpc_frame_dataspace(f); 25 | str = lpc_string_new(data, lpc_string_text(str), lpc_string_length(str)); 26 | 27 | /* turn to lowercase */ 28 | p = lpc_string_text(str); 29 | for (i = lpc_string_length(str); i != 0; --i) { 30 | if (*p >= 'A' && *p <= 'Z') { 31 | *p += 'a' - 'A'; 32 | } 33 | p++; 34 | } 35 | 36 | /* put result in return value */ 37 | lpc_string_putval(retval, str); 38 | } 39 | 40 | static char lower_case_proto[] = { LPC_TYPE_STRING, LPC_TYPE_STRING, 0 }; 41 | static LPC_ext_kfun kf[1] = { 42 | "lower_case", 43 | lower_case_proto, 44 | &lower_case 45 | }; 46 | 47 | int lpc_ext_init(int major, int minor, const char *config) 48 | { 49 | lpc_ext_kfun(kf, 1); 50 | return 1; 51 | } 52 | -------------------------------------------------------------------------------- /project/regexp/regexp.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Header Files 16 | 17 | 18 | Header Files 19 | 20 | 21 | Header Files 22 | 23 | 24 | Header Files 25 | 26 | 27 | 28 | 29 | Source Files 30 | 31 | 32 | Source Files 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/kfun/rgx/doc-0.3/regexps: -------------------------------------------------------------------------------- 1 | 2 | Regular expressions are composed of the following operators: 3 | 4 | . Match any single character 5 | XY Match X immediately followed by Y 6 | X* Match zero-or-more of X 7 | X+ Match one-or-more of X 8 | X? Match zero-or-one of X 9 | X\|Y Match either X or Y 10 | [charset] Match any single character in `charset' 11 | [^charset] Match any single character not in `charset' 12 | \(X\) Match X, but also remember the match as a subexpression 13 | \digit Match the numbered previous subexpression 14 | ^X Match X anchored at the beginning of a line 15 | X$ Match X anchored at the end of a line 16 | \b Match the empty string at the beginning or end of a word 17 | \B Match the empty string only within the middle of a word 18 | \< Match the beginning of a word 19 | \> Match the end of a word 20 | \w Match any word-constituent character 21 | \W Match any character that is not word-constituent 22 | 23 | Any other character in a regular expression is matched literally with itself. 24 | To match any of the special operator characters .*+?\[^$ literally, precede 25 | the character with `\'. 26 | 27 | A `charset' is formed by listing all desired characters with brackets. To 28 | include a literal `^' in a charset, do not list it in the first position. To 29 | include a literal `]', list it immediately after the opening `[' or `[^'. All 30 | characters are non-special (and should not be escaped) within a charset, 31 | except `-', which denotes a character range. To include a literal `-', list it 32 | either first or last. 33 | -------------------------------------------------------------------------------- /src/jit/data.h: -------------------------------------------------------------------------------- 1 | # define LPC_TYPE_CLASS 7 2 | # define LPC_TYPE_MASK 0x0f 3 | # define LPC_TYPE_REF(t) ((t) >> 4) 4 | 5 | typedef int64_t LPCInt; 6 | 7 | struct LPCFloat { 8 | uint32_t high; /* 1 sign, 15 exponent, ... */ 9 | uint64_t low; /* ... 80 mantissa */ 10 | }; 11 | 12 | typedef uint16_t LPCInherit; 13 | 14 | struct LPCStringConst { 15 | LPCInherit inherit; /* program */ 16 | uint16_t index; /* index in string constant table */ 17 | }; 18 | 19 | typedef uint8_t Type; 20 | 21 | struct LPCType { 22 | Type type; /* compile-time type */ 23 | LPCInherit inherit; /* optional class string program */ 24 | uint16_t index; /* optional class string index */ 25 | }; 26 | 27 | typedef uint8_t LPCParam; 28 | typedef uint8_t LPCLocal; 29 | 30 | struct LPCGlobal { 31 | LPCInherit inherit; /* program */ 32 | uint8_t index; /* index in variable table */ 33 | Type type; /* type of variable */ 34 | }; 35 | 36 | typedef uint16_t LPCKFun; 37 | 38 | struct LPCKFunCall { 39 | LPCKFun func; /* index in kfun table */ 40 | LPCParam nargs; /* # arguments */ 41 | LPCParam lval; /* # non-lvalue parameters or 0 */ 42 | Type type; /* return type */ 43 | }; 44 | 45 | struct LPCDFunCall { 46 | LPCInherit inherit; /* program */ 47 | uint8_t func; /* index in function table */ 48 | LPCParam nargs; /* # arguments */ 49 | Type type; /* return type */ 50 | }; 51 | 52 | struct LPCVFunCall { 53 | uint16_t call; /* index in call table */ 54 | LPCParam nargs; /* # arguments */ 55 | }; 56 | -------------------------------------------------------------------------------- /jitcomp.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jitcomp", "project\jitcomp\jitcomp.vcxproj", "{F66B4AF3-C067-4CC0-95AC-879AF05318DB}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x86 = Debug|x86 11 | Debug|x64 = Debug|x64 12 | Release|x86 = Release|x86 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {F66B4AF3-C067-4CC0-95AC-879AF05318DB}.Debug|x86.ActiveCfg = Debug|Win32 17 | {F66B4AF3-C067-4CC0-95AC-879AF05318DB}.Debug|x86.Build.0 = Debug|Win32 18 | {F66B4AF3-C067-4CC0-95AC-879AF05318DB}.Debug|x64.ActiveCfg = Debug|x64 19 | {F66B4AF3-C067-4CC0-95AC-879AF05318DB}.Debug|x64.Build.0 = Debug|x64 20 | {F66B4AF3-C067-4CC0-95AC-879AF05318DB}.Release|x86.ActiveCfg = Release|Win32 21 | {F66B4AF3-C067-4CC0-95AC-879AF05318DB}.Release|x86.Build.0 = Release|Win32 22 | {F66B4AF3-C067-4CC0-95AC-879AF05318DB}.Release|x64.ActiveCfg = Release|x64 23 | {F66B4AF3-C067-4CC0-95AC-879AF05318DB}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {B06B4E31-7CE6-4343-BFA5-A1506729C999} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /src/kfun/rgx/Makefile.diff: -------------------------------------------------------------------------------- 1 | Index: Makefile 2 | =================================================================== 3 | --- Makefile (revision 65) 4 | +++ Makefile (working copy) 5 | @@ -16,7 +16,7 @@ 6 | # along with this program. If not, see . 7 | # 8 | HOST= DARWIN 9 | -DEFINES=-D$(HOST) #-DNETWORK_EXTENSIONS #-DDUMP_FUNCS 10 | +DEFINES=-D$(HOST) -DLPC_EXTENSION #-DNETWORK_EXTENSIONS #-DDUMP_FUNCS 11 | DEBUG= -O -g 12 | CCFLAGS=$(DEFINES) $(DEBUG) 13 | CFLAGS= -I. -Icomp -Ilex -Ied -Iparser -Ikfun $(CCFLAGS) 14 | @@ -29,12 +29,13 @@ 15 | YACC= yacc 16 | BIN= ../bin 17 | 18 | +REGOBJ= regex.o regexp.o 19 | SRC= alloc.c error.c hash.c swap.c str.c array.c object.c sdata.c data.c \ 20 | path.c editor.c comm.c call_out.c interpret.c config.c dgd.c 21 | OBJ= alloc.o error.o hash.o swap.o str.o array.o object.o sdata.o data.o \ 22 | - path.o editor.o comm.o call_out.o interpret.o config.o dgd.o 23 | + path.o editor.o comm.o call_out.o interpret.o config.o dgd.o $(REGOBJ) 24 | COMPOBJ=alloc.o error.o hash.o path.o str.o array.o object.o sdata.o data.o \ 25 | - interpret.o config.o 26 | + interpret.o config.o $(REGOBJ) 27 | 28 | a.out: $(OBJ) always 29 | cd comp; $(DMAKE) 'CC=$(CC)' 'CCFLAGS=$(CCFLAGS)' 'YACC=$(YACC)' dgd 30 | @@ -124,3 +125,8 @@ 31 | call_out.o config.o dgd.o: call_out.h 32 | error.o comm.o config.o dgd.o: comm.h 33 | comm.o config.o: version.h 34 | + 35 | +regex.o: libiberty/regex.c 36 | + $(CC) -c $(CFLAGS) -Ilibiberty `cat libiberty/config` libiberty/regex.c -o $@ 37 | +regexp.o: regexp.c dgd_ext.h 38 | + $(CC) -c $(CFLAGS) -Ilibiberty regexp.c 39 | -------------------------------------------------------------------------------- /src/jit/flow.h: -------------------------------------------------------------------------------- 1 | class FlowContext : public TypedContext { 2 | public: 3 | FlowContext(CodeFunction *func, StackSize size); 4 | virtual ~FlowContext(); 5 | 6 | int paramRef(LPCParam param); 7 | int localRef(LPCLocal local); 8 | 9 | static const int INITIAL = 0x20000; 10 | static const int NEEDED = 0x20001; 11 | 12 | int *inParams, *outParams; /* parameter references */ 13 | int *inLocals, *outLocals; /* local references */ 14 | }; 15 | 16 | class FlowCode : public TypedCode { 17 | public: 18 | FlowCode(CodeFunction *function); 19 | virtual ~FlowCode(); 20 | 21 | virtual void evaluateFlow(FlowContext *context); 22 | 23 | int inputRef() { 24 | return in; 25 | } 26 | int outputRef() { 27 | return out; 28 | } 29 | 30 | private: 31 | int in; /* variable input reference */ 32 | int out; /* variable output reference */ 33 | }; 34 | 35 | class FlowBlock : public TypedBlock { 36 | public: 37 | FlowBlock(Code *fist, Code *last, CodeSize size); 38 | virtual ~FlowBlock(); 39 | 40 | virtual int paramIn(LPCParam param); 41 | virtual int paramOut(LPCParam param); 42 | virtual bool paramMerged(LPCParam param); 43 | virtual int localIn(LPCLocal local); 44 | virtual int localOut(LPCLocal local); 45 | virtual bool localMerged(LPCLocal local); 46 | virtual Type mergedParamType(LPCParam param, Type type); 47 | virtual Type mergedLocalType(LPCLocal local); 48 | virtual void prepareFlow(FlowContext *context); 49 | virtual void evaluateFlow(FlowContext *context, Block **list); 50 | virtual void evaluateInputs(FlowContext *context, Block **list); 51 | virtual void evaluateOutputs(FlowContext *context, Block **list); 52 | void evaluate(FlowContext *context); 53 | 54 | private: 55 | int *inParams; /* parameter input references */ 56 | int *inLocals; /* local input references */ 57 | int *outParams; /* parameter output references */ 58 | int *outLocals; /* local output references */ 59 | }; 60 | -------------------------------------------------------------------------------- /src/jit/genclang.h: -------------------------------------------------------------------------------- 1 | class ClangCode : public FlowCode { 2 | public: 3 | ClangCode(CodeFunction *function); 4 | virtual ~ClangCode(); 5 | 6 | virtual void emit(class GenContext *context); 7 | void emitRangeTable(class GenContext *context); 8 | void emitStringTable(class GenContext *context); 9 | 10 | static void intArg(class GenContext *context, StackSize sp); 11 | static void floatArg(class GenContext *context, StackSize sp); 12 | static char *tmpRef(StackSize sp); 13 | static char *paramRef(LPCParam param, int ref); 14 | static char *localRef(LPCLocal local, int ref); 15 | static Code *create(CodeFunction *function); 16 | 17 | ClangCode *list; /* next in switch list */ 18 | 19 | private: 20 | char *paramRef(class GenContext *context, LPCParam param); 21 | char *localRef(class GenContext *context, LPCLocal local); 22 | char *localPre(class GenContext *context, LPCLocal local); 23 | void pushResult(class GenContext *context); 24 | void popResult(class GenContext *context); 25 | void popStores(class GenContext *context, StackSize sp); 26 | void switchInt(class GenContext *context); 27 | void genTable(class GenContext *context, const char *type); 28 | }; 29 | 30 | class ClangBlock : public FlowBlock { 31 | public: 32 | ClangBlock(Code *fist, Code *last, CodeSize size); 33 | virtual ~ClangBlock(); 34 | 35 | virtual void emit(class GenContext *context, CodeFunction *function); 36 | 37 | static Block *create(Code *first, Code *last, CodeSize size); 38 | }; 39 | 40 | class ClangObject { 41 | public: 42 | ClangObject(CodeObject *object, CodeByte *prog, int nFunctions); 43 | virtual ~ClangObject(); 44 | 45 | bool emit(char *base, int flags); 46 | 47 | private: 48 | void header(FILE *stream); 49 | void table(FILE *stream, int nFunctions); 50 | 51 | CodeObject *object; /* object being compiled */ 52 | CodeByte *prog; /* LPC bytecode */ 53 | int nFunctions; /* # functions in object */ 54 | }; 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The overaching license for the LPC extensions is the Unlicense. Some modules 2 | or portions thereof in the `src/kfun` directory have their own open source 3 | license; please consult the relevant code for the details. 4 | 5 | - doc 6 | documentation 7 | - src 8 | API glue to compile with your module 9 | - src/dbase 10 | example database module 11 | - src/jit 12 | JIT compiler module 13 | - src/kfun 14 | kfun modules 15 | 16 | To build modules for most kfuns, just type `make` (or whatever your GNU make 17 | command is) in the src directory. On Windows, use Visual Studio 2010 with 18 | the solution file `lpc-ext.sln`, or use `make EXT=dll` with Cygwin. 19 | 20 | Use `make zlib` to build the zlib module, for version 1.2.13. For other 21 | versions, use: 22 | 23 | - 1.2.8 24 | `make zlib ZLIB=1.2.8 ZLIBDIR=1.2.8` 25 | - 1.2.11 26 | `make zlib ZLIB=1.2.11 ZLIBDIR=1.2.11` 27 | - 1.2.12 28 | `make zlib ZLIB=1.2.12` 29 | - 1.3 30 | `make zlib ZLIB=1.3` 31 | - 1.3.1 32 | `make zlib ZLIB=1.3.1` 33 | 34 | Use `make jit` to build the JIT compiler module. This requires clang to 35 | be installed (any version from 3.7 onward will work). The jit module 36 | will start the actual JIT compiler as a separate program. It must be 37 | configured with the directory that contains the JIT compiler, and where 38 | the JIT cache will be created: 39 | ``` 40 | modules = ([ 41 | "/home/server/lpc-ext/jit.1.5" : /* JIT module */ 42 | "/home/server/lpc-ext/src/jit" /* where jitcomp resides */ 43 | ]); 44 | ``` 45 | On Windows, there are different solution files for the components of the JIT 46 | compiler. `lpc-ext.sln` is used to build the JIT extension, `jitcomp.sln` is 47 | used to build the actual jit compiler which runs as a separate program, and 48 | which depends on clang. Clang can be installed as a component of Visual Studio 49 | Community 2022. Note that jitcomp.sln is a VS2019 solution, whereas 50 | `lpc-ext.sln` can be built with any Visual Studio version from 2010 onward. 51 | 52 | Use `make crypto` to build the cryptographic functions module. This requires 53 | OpenSSL 1.1.1 or later. 54 | 55 | Use `make tls` to build the TLS module (for DGD only). This also requires 56 | OpenSSL 1.1.1 or later. 57 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for extension modules 3 | # 4 | EXT=1.5 5 | DEFINES= # -DLARGENUM 6 | DEBUG=-ggdb 7 | CCFLAGS=$(DEFINES) $(DEBUG) 8 | CC=cc 9 | 10 | CFLAGS= -fPIC -DPIC $(CCFLAGS) 11 | LD=$(CC) 12 | LDFLAGS=-shared $(DEBUG) 13 | 14 | OBJ= lpc_ext.o 15 | LIBLIB= kfun/rgx/libiberty 16 | ZLIB= 1.2.13 # 1.2.8, 1.2.11, 1.2.12, 1.2.13, 1.3, 1.3.1 17 | ZLIBDIR=1.2.12 # 1.2.8, 1.2.11, 1.2.12+ 18 | 19 | all: ../lower_case.$(EXT) ../regexp.$(EXT) ../dbase.$(EXT) 20 | 21 | jit: ../jit.$(EXT) 22 | 23 | zlib: ../zlib.$(EXT) 24 | 25 | crypto: ../crypto.$(EXT) 26 | 27 | tls: ../tls.$(EXT) 28 | 29 | lpc_ext.o: lpc_ext.c lpc_ext.h 30 | $(CC) -o $@ -c $(CFLAGS) -I. lpc_ext.c 31 | 32 | kfun/lower_case.o: kfun/lower_case.c lpc_ext.h 33 | $(CC) -o $@ -c $(CFLAGS) -I. kfun/lower_case.c 34 | 35 | ../lower_case.$(EXT): kfun/lower_case.o $(OBJ) 36 | $(LD) -o $@ $(LDFLAGS) $+ 37 | 38 | kfun/rgx/regexp.o: kfun/rgx/regexp.c lpc_ext.h 39 | $(CC) -o $@ -c $(CFLAGS) -I. -I$(LIBLIB) kfun/rgx/regexp.c 40 | 41 | kfun/rgx/regex.o: kfun/rgx/libiberty/regex.c 42 | $(CC) -o $@ -c $(CFLAGS) -I$(LIBLIB) `cat $(LIBLIB)/config` $+ 43 | 44 | ../regexp.$(EXT): kfun/rgx/regexp.o kfun/rgx/regex.o $(OBJ) 45 | $(LD) -o $@ $(LDFLAGS) $+ 46 | 47 | dbase/dbase.o: dbase/dbase.c lpc_ext.h 48 | $(CC) -o $@ -c $(CFLAGS) -I. dbase/dbase.c 49 | 50 | ../dbase.$(EXT): dbase/dbase.o $(OBJ) 51 | $(LD) -o $@ $(LDFLAGS) $+ 52 | 53 | jit/jitcomp:: 54 | $(MAKE) -C jit 'DEFINES=$(DEFINES)' 'DEBUG=$(DEBUG)' 55 | 56 | jit/jit.o:: 57 | $(MAKE) -C jit 'CFLAGS=$(CFLAGS)' jit.o 58 | 59 | ../jit.$(EXT): jit/jit.o $(OBJ) jit/jitcomp 60 | $(LD) -o $@ $(LDFLAGS) jit/jit.o $(OBJ) 61 | 62 | kfun/zlib/zlib.o: kfun/zlib/zlib.c lpc_ext.h 63 | $(CC) -o $@ -c $(CFLAGS) -I. -Ikfun/zlib/$(ZLIBDIR) -DVERSION=$(ZLIB) \ 64 | kfun/zlib/zlib.c 65 | 66 | ../zlib.$(EXT): kfun/zlib/zlib.o $(OBJ) 67 | $(LD) -o $@ $(LDFLAGS) $+ -lz 68 | 69 | kfun/crypto.o: kfun/crypto.c lpc_ext.h 70 | $(CC) -o $@ -c $(CFLAGS) -I. kfun/crypto.c 71 | 72 | ../crypto.$(EXT): kfun/crypto.o $(OBJ) 73 | $(LD) -o $@ $(LDFLAGS) $+ -lcrypto 74 | 75 | kfun/tls/tls.o: kfun/tls/tls.c lpc_ext.h 76 | $(CC) -o $@ -c $(CFLAGS) -I. kfun/tls/tls.c 77 | 78 | ../tls.$(EXT): kfun/tls/tls.o $(OBJ) 79 | $(LD) -o $@ $(LDFLAGS) $+ -lssl 80 | 81 | clean: 82 | rm -f ../lower_case.$(EXT) ../regexp.$(EXT) ../zlib.$(EXT) \ 83 | ../jit.$(EXT) ../dbase.$(EXT) ../crypto.$(EXT) ../tls.$(EXT) \ 84 | *.o kfun/*.o kfun/*/*.o dbase/*.o 85 | $(MAKE) -C jit clean 86 | -------------------------------------------------------------------------------- /project/jitcomp/jitcomp.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | Source Files 19 | 20 | 21 | Source Files 22 | 23 | 24 | Source Files 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | 34 | 35 | Header Files 36 | 37 | 38 | Header Files 39 | 40 | 41 | Header Files 42 | 43 | 44 | Header Files 45 | 46 | 47 | Header Files 48 | 49 | 50 | Header Files 51 | 52 | 53 | Header Files 54 | 55 | 56 | Header Files 57 | 58 | 59 | Header Files 60 | 61 | 62 | Header Files 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/kfun/zlib/1.2.11/inftrees.h: -------------------------------------------------------------------------------- 1 | /* inftrees.h -- header to use inftrees.c 2 | * Copyright (C) 1995-2005, 2010 Mark Adler 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the compression library and is 8 | subject to change. Applications should only use zlib.h. 9 | */ 10 | 11 | /* Structure for decoding tables. Each entry provides either the 12 | information needed to do the operation requested by the code that 13 | indexed that table entry, or it provides a pointer to another 14 | table that indexes more bits of the code. op indicates whether 15 | the entry is a pointer to another table, a literal, a length or 16 | distance, an end-of-block, or an invalid code. For a table 17 | pointer, the low four bits of op is the number of index bits of 18 | that table. For a length or distance, the low four bits of op 19 | is the number of extra bits to get after the code. bits is 20 | the number of bits in this code or part of the code to drop off 21 | of the bit buffer. val is the actual byte to output in the case 22 | of a literal, the base length or distance, or the offset from 23 | the current table to the next table. Each entry is four bytes. */ 24 | typedef struct { 25 | unsigned char op; /* operation, extra bits, table bits */ 26 | unsigned char bits; /* bits in this part of the code */ 27 | unsigned short val; /* offset in table or code value */ 28 | } code; 29 | 30 | /* op values as set by inflate_table(): 31 | 00000000 - literal 32 | 0000tttt - table link, tttt != 0 is the number of table index bits 33 | 0001eeee - length or distance, eeee is the number of extra bits 34 | 01100000 - end of block 35 | 01000000 - invalid code 36 | */ 37 | 38 | /* Maximum size of the dynamic table. The maximum number of code structures is 39 | 1444, which is the sum of 852 for literal/length codes and 592 for distance 40 | codes. These values were found by exhaustive searches using the program 41 | examples/enough.c found in the zlib distribtution. The arguments to that 42 | program are the number of symbols, the initial root table size, and the 43 | maximum bit length of a code. "enough 286 9 15" for literal/length codes 44 | returns returns 852, and "enough 30 6 15" for distance codes returns 592. 45 | The initial root table size (9 or 6) is found in the fifth argument of the 46 | inflate_table() calls in inflate.c and infback.c. If the root table size is 47 | changed, then these maximum sizes would be need to be recalculated and 48 | updated. */ 49 | #define ENOUGH_LENS 852 50 | #define ENOUGH_DISTS 592 51 | #define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) 52 | 53 | /* Type of code to build for inflate_table() */ 54 | typedef enum { 55 | CODES, 56 | LENS, 57 | DISTS 58 | } codetype; 59 | 60 | int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, 61 | unsigned codes, code FAR * FAR *table, 62 | unsigned FAR *bits, unsigned short FAR *work)); 63 | -------------------------------------------------------------------------------- /src/kfun/zlib/1.2.12/inftrees.h: -------------------------------------------------------------------------------- 1 | /* inftrees.h -- header to use inftrees.c 2 | * Copyright (C) 1995-2005, 2010 Mark Adler 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the compression library and is 8 | subject to change. Applications should only use zlib.h. 9 | */ 10 | 11 | /* Structure for decoding tables. Each entry provides either the 12 | information needed to do the operation requested by the code that 13 | indexed that table entry, or it provides a pointer to another 14 | table that indexes more bits of the code. op indicates whether 15 | the entry is a pointer to another table, a literal, a length or 16 | distance, an end-of-block, or an invalid code. For a table 17 | pointer, the low four bits of op is the number of index bits of 18 | that table. For a length or distance, the low four bits of op 19 | is the number of extra bits to get after the code. bits is 20 | the number of bits in this code or part of the code to drop off 21 | of the bit buffer. val is the actual byte to output in the case 22 | of a literal, the base length or distance, or the offset from 23 | the current table to the next table. Each entry is four bytes. */ 24 | typedef struct { 25 | unsigned char op; /* operation, extra bits, table bits */ 26 | unsigned char bits; /* bits in this part of the code */ 27 | unsigned short val; /* offset in table or code value */ 28 | } code; 29 | 30 | /* op values as set by inflate_table(): 31 | 00000000 - literal 32 | 0000tttt - table link, tttt != 0 is the number of table index bits 33 | 0001eeee - length or distance, eeee is the number of extra bits 34 | 01100000 - end of block 35 | 01000000 - invalid code 36 | */ 37 | 38 | /* Maximum size of the dynamic table. The maximum number of code structures is 39 | 1444, which is the sum of 852 for literal/length codes and 592 for distance 40 | codes. These values were found by exhaustive searches using the program 41 | examples/enough.c found in the zlib distribtution. The arguments to that 42 | program are the number of symbols, the initial root table size, and the 43 | maximum bit length of a code. "enough 286 9 15" for literal/length codes 44 | returns returns 852, and "enough 30 6 15" for distance codes returns 592. 45 | The initial root table size (9 or 6) is found in the fifth argument of the 46 | inflate_table() calls in inflate.c and infback.c. If the root table size is 47 | changed, then these maximum sizes would be need to be recalculated and 48 | updated. */ 49 | #define ENOUGH_LENS 852 50 | #define ENOUGH_DISTS 592 51 | #define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) 52 | 53 | /* Type of code to build for inflate_table() */ 54 | typedef enum { 55 | CODES, 56 | LENS, 57 | DISTS 58 | } codetype; 59 | 60 | int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, 61 | unsigned codes, code FAR * FAR *table, 62 | unsigned FAR *bits, unsigned short FAR *work)); 63 | -------------------------------------------------------------------------------- /src/kfun/zlib/1.2.8/inftrees.h: -------------------------------------------------------------------------------- 1 | /* inftrees.h -- header to use inftrees.c 2 | * Copyright (C) 1995-2005, 2010 Mark Adler 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the compression library and is 8 | subject to change. Applications should only use zlib.h. 9 | */ 10 | 11 | /* Structure for decoding tables. Each entry provides either the 12 | information needed to do the operation requested by the code that 13 | indexed that table entry, or it provides a pointer to another 14 | table that indexes more bits of the code. op indicates whether 15 | the entry is a pointer to another table, a literal, a length or 16 | distance, an end-of-block, or an invalid code. For a table 17 | pointer, the low four bits of op is the number of index bits of 18 | that table. For a length or distance, the low four bits of op 19 | is the number of extra bits to get after the code. bits is 20 | the number of bits in this code or part of the code to drop off 21 | of the bit buffer. val is the actual byte to output in the case 22 | of a literal, the base length or distance, or the offset from 23 | the current table to the next table. Each entry is four bytes. */ 24 | typedef struct { 25 | unsigned char op; /* operation, extra bits, table bits */ 26 | unsigned char bits; /* bits in this part of the code */ 27 | unsigned short val; /* offset in table or code value */ 28 | } code; 29 | 30 | /* op values as set by inflate_table(): 31 | 00000000 - literal 32 | 0000tttt - table link, tttt != 0 is the number of table index bits 33 | 0001eeee - length or distance, eeee is the number of extra bits 34 | 01100000 - end of block 35 | 01000000 - invalid code 36 | */ 37 | 38 | /* Maximum size of the dynamic table. The maximum number of code structures is 39 | 1444, which is the sum of 852 for literal/length codes and 592 for distance 40 | codes. These values were found by exhaustive searches using the program 41 | examples/enough.c found in the zlib distribtution. The arguments to that 42 | program are the number of symbols, the initial root table size, and the 43 | maximum bit length of a code. "enough 286 9 15" for literal/length codes 44 | returns returns 852, and "enough 30 6 15" for distance codes returns 592. 45 | The initial root table size (9 or 6) is found in the fifth argument of the 46 | inflate_table() calls in inflate.c and infback.c. If the root table size is 47 | changed, then these maximum sizes would be need to be recalculated and 48 | updated. */ 49 | #define ENOUGH_LENS 852 50 | #define ENOUGH_DISTS 592 51 | #define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) 52 | 53 | /* Type of code to build for inflate_table() */ 54 | typedef enum { 55 | CODES, 56 | LENS, 57 | DISTS 58 | } codetype; 59 | 60 | int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, 61 | unsigned codes, code FAR * FAR *table, 62 | unsigned FAR *bits, unsigned short FAR *work)); 63 | -------------------------------------------------------------------------------- /src/jit/typed.h: -------------------------------------------------------------------------------- 1 | class TVC { 2 | public: 3 | TVC() { } 4 | TVC(Type type, LPCInt val) : 5 | type(type), val(val), code(NULL), ref(STACK_EMPTY) { } 6 | 7 | Type type; /* type */ 8 | LPCInt val; /* value, only relevant for integer on the stack */ 9 | Code *code; /* instruction that consumes this TVC */ 10 | StackSize ref; /* replacement reference */ 11 | }; 12 | 13 | class TypedContext : public BlockContext { 14 | public: 15 | TypedContext(CodeFunction *func, StackSize size); 16 | virtual ~TypedContext(); 17 | 18 | void prologue(Type *mergeParams, Type *mergeLocals, StackSize mergeSp, 19 | Block *b); 20 | void push(TVC val); 21 | void push(Type type, LPCInt val = 0) { 22 | push(TVC(type, val)); 23 | } 24 | TVC pop(Code *code); 25 | TVC indexed(); 26 | void storeParam(LPCParam param, Type type); 27 | void storeLocal(LPCParam local, Type type); 28 | void endStores(); 29 | void spread() { 30 | spreadArgs = true; 31 | } 32 | Type kfun(LPCKFunCall *kf, Code *code); 33 | void args(int nargs, Code *code); 34 | void startCatch(); 35 | void modCaught(); 36 | void endCatch(); 37 | StackSize merge(StackSize codeSp); 38 | bool changed(Type *params, Type *locals); 39 | TVC get(StackSize stackPointer); 40 | Code *consumer(StackSize stackPointer, Type *type); 41 | StackSize nextSp(StackSize stackPointer, int depth = 1); 42 | 43 | Type *params; /* function parameter types */ 44 | Type *locals; /* function local variable types */ 45 | LPCParam nParams; /* # parameters */ 46 | LPCLocal nLocals; /* # local variables */ 47 | StackSize sp; /* stack pointer */ 48 | Type castType; /* CASTX argument */ 49 | Block *block; /* current block */ 50 | Block *caught; /* catch context */ 51 | Block **list; /* visitation list */ 52 | 53 | private: 54 | StackSize copyStack(StackSize copy, StackSize from, StackSize to); 55 | 56 | static Type mergeType(Type type1, Type type2); 57 | 58 | Stack *stack; /* type/val/code stack */ 59 | TVC altStack[3]; /* alternative stack */ 60 | StackSize altSp; /* alternative stack pointer */ 61 | bool spreadArgs; /* SPREAD before call? */ 62 | bool merging; /* merging stack values? */ 63 | }; 64 | 65 | class TypedCode : public Code { 66 | public: 67 | TypedCode(CodeFunction *function); 68 | virtual ~TypedCode(); 69 | 70 | virtual void evaluateTypes(TypedContext *context); 71 | StackSize stackPointer() { return sp; } 72 | 73 | static Type simplifiedType(Type type); 74 | static Type offStack(TypedContext *context, StackSize stackPointer); 75 | 76 | Type varType; /* STORES param/local type */ 77 | 78 | private: 79 | StackSize sp; /* stack pointer */ 80 | }; 81 | 82 | class TypedBlock : public Block { 83 | public: 84 | TypedBlock(Code *first, Code *last, CodeSize size); 85 | virtual ~TypedBlock(); 86 | 87 | virtual Type paramType(LPCParam param); 88 | virtual Type localType(LPCLocal local); 89 | virtual void setContext(TypedContext *context, Block *b); 90 | virtual void evaluateTypes(TypedContext *context, Block **list); 91 | void evaluate(TypedContext *context); 92 | 93 | private: 94 | Type *params; /* parameter types at end of block */ 95 | Type *locals; /* local variable types at end of block */ 96 | }; 97 | -------------------------------------------------------------------------------- /src/jit/block.h: -------------------------------------------------------------------------------- 1 | class BlockContext { 2 | public: 3 | BlockContext(); 4 | virtual ~BlockContext(); 5 | 6 | bool stores(int count, Code *popCode, bool flag); 7 | bool lval() { 8 | return lvalue; 9 | } 10 | bool storeN(); 11 | Code *storePop() { 12 | return storeCode; 13 | } 14 | 15 | private: 16 | int storeCount; /* number of STOREX instructions left */ 17 | Code *storeCode; /* pop at end of STORES? */ 18 | bool lvalue; /* lvalue stores? */ 19 | }; 20 | 21 | class Block { 22 | public: 23 | Block(Code *first, Code *last, CodeSize size); 24 | virtual ~Block(); 25 | 26 | void startVisits(Block **list); 27 | void startAllVisits(Block **list); 28 | void toVisit(Block **list); 29 | 30 | void initMod(LPCParam size); 31 | void setRelay(); 32 | bool relay(); 33 | bool relayToDefault(Block *to); 34 | CodeSize fragment(); 35 | void clear(); 36 | virtual void setContext(class TypedContext *context, Block *b); 37 | virtual Type paramType(LPCParam param); 38 | virtual int paramIn(LPCParam param); 39 | virtual int paramOut(LPCParam param); 40 | virtual bool paramMerged(LPCParam param); 41 | virtual Type localType(LPCLocal local); 42 | virtual int localIn(LPCLocal local); 43 | virtual int localOut(LPCLocal local); 44 | virtual bool localMerged(LPCLocal local); 45 | virtual Type mergedParamType(LPCParam param, Type type); 46 | virtual Type mergedLocalType(LPCLocal local); 47 | virtual void prepareFlow(class FlowContext *context); 48 | virtual void evaluateTypes(class TypedContext *context, Block **list); 49 | virtual void evaluateFlow(class FlowContext *context, Block **list); 50 | virtual void evaluateInputs(class FlowContext *context, Block **list); 51 | virtual void evaluateOutputs(class FlowContext *context, Block **list); 52 | virtual void emit(class GenContext *context, CodeFunction *function); 53 | 54 | static Block *function(CodeFunction *function); 55 | static Block *nextVisit(Block **List); 56 | 57 | static Block *produce(Code *first, Code *last, CodeSize size); 58 | static void producer(Block *(*factory)(Code*, Code*, CodeSize)); 59 | 60 | Code *first, *last; /* first and last code in block */ 61 | Block *next; /* next block */ 62 | Block *caught; /* catch context at start of block */ 63 | Block **from; /* entrance blocks */ 64 | bool *fromVisit; /* entrance flags */ 65 | Block **to; /* following blocks */ 66 | CodeSize nFrom; /* # entrance blocks */ 67 | CodeSize nTo; /* # following blocks */ 68 | CodeSize size; /* size of block */ 69 | StackSize sp; /* stack pointer */ 70 | StackSize endSp; /* final stack pointer */ 71 | bool *mod; /* modification flags */ 72 | 73 | private: 74 | enum Context { 75 | CATCH, 76 | RLIMITS 77 | }; 78 | 79 | Block *find(CodeSize addr); 80 | Block *split(CodeSize addr); 81 | void toVisitOnce(Block **list, StackSize stackPointer, Block *catchContext); 82 | Block *pass1(); 83 | Block *pass2(Block *tree, StackSize size); 84 | void pass3(Block *b); 85 | void pass4(); 86 | 87 | Block *left, *right; /* left and right child in tree */ 88 | Block *visit; /* next in visit list */ 89 | uint16_t flags; /* flag bits */ 90 | 91 | static Block *(*factory)(Code*, Code*, CodeSize); 92 | }; 93 | 94 | # define BLOCK_DEFAULT 0x0001 95 | # define BLOCK_RELAY 0x0002 96 | -------------------------------------------------------------------------------- /lpc-ext.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "regexp", "project\regexp\regexp.vcxproj", "{670ABFEA-96E8-4D68-BA2A-9445A48358D7}" 5 | ProjectSection(ProjectDependencies) = postProject 6 | {BF10E509-A9A8-4FA6-94E9-EE1C53DDDE74} = {BF10E509-A9A8-4FA6-94E9-EE1C53DDDE74} 7 | EndProjectSection 8 | EndProject 9 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lower_case", "project\lower_case\lower_case.vcxproj", "{7FDD6043-348D-451B-9E95-14FDD0A829EE}" 10 | ProjectSection(ProjectDependencies) = postProject 11 | {BF10E509-A9A8-4FA6-94E9-EE1C53DDDE74} = {BF10E509-A9A8-4FA6-94E9-EE1C53DDDE74} 12 | EndProjectSection 13 | EndProject 14 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jit", "project\jit\jit.vcxproj", "{3F740FAA-4EC8-4C77-8A0B-C0B47466684C}" 15 | ProjectSection(ProjectDependencies) = postProject 16 | {BF10E509-A9A8-4FA6-94E9-EE1C53DDDE74} = {BF10E509-A9A8-4FA6-94E9-EE1C53DDDE74} 17 | EndProjectSection 18 | EndProject 19 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lpc-ext", "project\lpc-ext\lpc-ext.vcxproj", "{BF10E509-A9A8-4FA6-94E9-EE1C53DDDE74}" 20 | EndProject 21 | Global 22 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 23 | Debug|Win32 = Debug|Win32 24 | Debug|x64 = Debug|x64 25 | Release|Win32 = Release|Win32 26 | Release|x64 = Release|x64 27 | EndGlobalSection 28 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 29 | {670ABFEA-96E8-4D68-BA2A-9445A48358D7}.Debug|Win32.ActiveCfg = Debug|Win32 30 | {670ABFEA-96E8-4D68-BA2A-9445A48358D7}.Debug|Win32.Build.0 = Debug|Win32 31 | {670ABFEA-96E8-4D68-BA2A-9445A48358D7}.Debug|x64.ActiveCfg = Debug|x64 32 | {670ABFEA-96E8-4D68-BA2A-9445A48358D7}.Debug|x64.Build.0 = Debug|x64 33 | {670ABFEA-96E8-4D68-BA2A-9445A48358D7}.Release|Win32.ActiveCfg = Release|Win32 34 | {670ABFEA-96E8-4D68-BA2A-9445A48358D7}.Release|Win32.Build.0 = Release|Win32 35 | {670ABFEA-96E8-4D68-BA2A-9445A48358D7}.Release|x64.ActiveCfg = Release|x64 36 | {670ABFEA-96E8-4D68-BA2A-9445A48358D7}.Release|x64.Build.0 = Release|x64 37 | {7FDD6043-348D-451B-9E95-14FDD0A829EE}.Debug|Win32.ActiveCfg = Debug|Win32 38 | {7FDD6043-348D-451B-9E95-14FDD0A829EE}.Debug|Win32.Build.0 = Debug|Win32 39 | {7FDD6043-348D-451B-9E95-14FDD0A829EE}.Debug|x64.ActiveCfg = Debug|x64 40 | {7FDD6043-348D-451B-9E95-14FDD0A829EE}.Debug|x64.Build.0 = Debug|x64 41 | {7FDD6043-348D-451B-9E95-14FDD0A829EE}.Release|Win32.ActiveCfg = Release|Win32 42 | {7FDD6043-348D-451B-9E95-14FDD0A829EE}.Release|Win32.Build.0 = Release|Win32 43 | {7FDD6043-348D-451B-9E95-14FDD0A829EE}.Release|x64.ActiveCfg = Release|x64 44 | {7FDD6043-348D-451B-9E95-14FDD0A829EE}.Release|x64.Build.0 = Release|x64 45 | {3F740FAA-4EC8-4C77-8A0B-C0B47466684C}.Debug|Win32.ActiveCfg = Debug|Win32 46 | {3F740FAA-4EC8-4C77-8A0B-C0B47466684C}.Debug|Win32.Build.0 = Debug|Win32 47 | {3F740FAA-4EC8-4C77-8A0B-C0B47466684C}.Debug|x64.ActiveCfg = Debug|x64 48 | {3F740FAA-4EC8-4C77-8A0B-C0B47466684C}.Debug|x64.Build.0 = Debug|x64 49 | {3F740FAA-4EC8-4C77-8A0B-C0B47466684C}.Release|Win32.ActiveCfg = Release|Win32 50 | {3F740FAA-4EC8-4C77-8A0B-C0B47466684C}.Release|Win32.Build.0 = Release|Win32 51 | {3F740FAA-4EC8-4C77-8A0B-C0B47466684C}.Release|x64.ActiveCfg = Release|x64 52 | {3F740FAA-4EC8-4C77-8A0B-C0B47466684C}.Release|x64.Build.0 = Release|x64 53 | {BF10E509-A9A8-4FA6-94E9-EE1C53DDDE74}.Debug|Win32.ActiveCfg = Debug|Win32 54 | {BF10E509-A9A8-4FA6-94E9-EE1C53DDDE74}.Debug|Win32.Build.0 = Debug|Win32 55 | {BF10E509-A9A8-4FA6-94E9-EE1C53DDDE74}.Debug|x64.ActiveCfg = Debug|x64 56 | {BF10E509-A9A8-4FA6-94E9-EE1C53DDDE74}.Debug|x64.Build.0 = Debug|x64 57 | {BF10E509-A9A8-4FA6-94E9-EE1C53DDDE74}.Release|Win32.ActiveCfg = Release|Win32 58 | {BF10E509-A9A8-4FA6-94E9-EE1C53DDDE74}.Release|Win32.Build.0 = Release|Win32 59 | {BF10E509-A9A8-4FA6-94E9-EE1C53DDDE74}.Release|x64.ActiveCfg = Release|x64 60 | {BF10E509-A9A8-4FA6-94E9-EE1C53DDDE74}.Release|x64.Build.0 = Release|x64 61 | EndGlobalSection 62 | GlobalSection(SolutionProperties) = preSolution 63 | HideSolutionNode = FALSE 64 | EndGlobalSection 65 | EndGlobal 66 | -------------------------------------------------------------------------------- /src/jit/jitcomp.cpp: -------------------------------------------------------------------------------- 1 | # ifndef WIN32 2 | # include 3 | # else 4 | # include 5 | # include 6 | # include 7 | # endif 8 | # include 9 | # include 10 | # include 11 | # include 12 | # include 13 | # include 14 | # include 15 | # include 16 | extern "C" { 17 | # include "lpc_ext.h" 18 | # include "jit.h" 19 | } 20 | # include "data.h" 21 | # include "code.h" 22 | # include "stack.h" 23 | # include "block.h" 24 | # include "typed.h" 25 | # include "flow.h" 26 | # ifdef DISASM 27 | # include "disasm.h" 28 | # endif 29 | # ifdef GENCLANG 30 | # include "genclang.h" 31 | # endif 32 | # include "jitcomp.h" 33 | 34 | # ifndef WIN32 35 | # define O_BINARY 0 36 | # else 37 | # define open _open 38 | # define close _close 39 | # define read _read 40 | # define write _write 41 | # define mkdir(path, mode) _mkdir(path) 42 | # define chdir _chdir 43 | # define dup _dup 44 | # define dup2 _dup2 45 | # endif 46 | 47 | /* 48 | * fatal error 49 | */ 50 | void fatal(const char *format, ...) 51 | { 52 | va_list argp; 53 | char buf[1024]; 54 | 55 | va_start(argp, format); 56 | vsprintf(buf, format, argp); 57 | va_end(argp); 58 | fprintf(stderr, "Fatal error: %s\n", buf); 59 | 60 | abort(); 61 | } 62 | 63 | /* 64 | * JIT compile a single object using a particular code generator 65 | */ 66 | static bool jitComp(CodeObject *object, CodeByte *prog, int nFunctions, 67 | char *base, int flags) 68 | { 69 | # ifdef DISASM 70 | Code::producer(&DisCode::create); 71 | Block::producer(&DisBlock::create); 72 | 73 | for (int i = 0; i < nFunctions; i++) { 74 | CodeFunction func(object, prog); 75 | DisFunction::emit(stderr, &func); 76 | prog = func.endProg(); 77 | fprintf(stderr, "\n"); 78 | } 79 | return false; 80 | # endif 81 | 82 | # ifdef GENCLANG 83 | Code::producer(&ClangCode::create); 84 | Block::producer(&ClangBlock::create); 85 | 86 | ClangObject clang(object, prog, nFunctions); 87 | return clang.emit(base, flags); 88 | # endif 89 | } 90 | 91 | /* 92 | * hash to filename 93 | */ 94 | static void filename(char *buffer, uint8_t *hash) 95 | { 96 | static const char hex[] = "0123456789abcdef"; 97 | int i; 98 | 99 | sprintf(buffer, "cache/%c%c/", hex[hash[0] >> 4], hex[hash[0] & 0xf]); 100 | buffer += 9; 101 | for (i = 0; i < 16; i++) { 102 | *buffer++ = hex[hash[i]>> 4]; 103 | *buffer++ = hex[hash[i] & 0xf]; 104 | } 105 | *buffer = '\0'; 106 | } 107 | 108 | /* 109 | * main function 110 | */ 111 | int main(int argc, char *argv[]) 112 | { 113 | JitInfo info; 114 | uint8_t cmdhash[17]; 115 | char reply; 116 | int out; 117 | CodeByte protos[65536]; 118 | CodeContext *cc; 119 | 120 | if (argc != 2 || chdir(argv[1]) < 0) { 121 | return 1; 122 | } 123 | mkdir("cache", 0750); 124 | 125 | # ifdef WIN32 126 | _setmode(0, O_BINARY); 127 | # endif 128 | 129 | /* read init params from 0 */ 130 | if (read(0, &info, sizeof(JitInfo)) != sizeof(JitInfo)) { 131 | return 2; 132 | } 133 | if (read(0, protos, info.protoSize) != info.protoSize) { 134 | return 2; 135 | } 136 | 137 | /* force output to stderr */ 138 | out = dup(1); 139 | dup2(2, 1); 140 | 141 | # ifdef WIN32 142 | _setmode(out, O_BINARY); 143 | # endif 144 | 145 | if (!CodeContext::validVM(info.major, info.minor)) { 146 | reply = false; 147 | (void) write(out, &reply, 1); 148 | return 3; 149 | } 150 | 151 | cc = new CodeContext(info.intSize, info.inheritSize, protos, info.nBuiltins, 152 | info.nKfuns, info.flags & JIT_TYPECHECKING); 153 | reply = true; 154 | (void) write(out, &reply, 1); 155 | 156 | cmdhash[0] = '\0'; 157 | while (read(0, cmdhash + 1, 16) == 16) { 158 | char path[42]; 159 | JitCompile comp; 160 | int fd; 161 | CodeByte *prog, *ftypes, *vtypes; 162 | 163 | filename(path, cmdhash + 1); 164 | fd = open(path, O_RDONLY | O_BINARY); 165 | if (fd >= 0) { 166 | (void) read(fd, &comp, sizeof(JitCompile)); 167 | prog = new CodeByte[comp.progSize]; 168 | ftypes = new CodeByte[comp.fTypeSize]; 169 | vtypes = new CodeByte[comp.vTypeSize]; 170 | (void) read(fd, prog, comp.progSize); 171 | (void) read(fd, ftypes, comp.fTypeSize); 172 | (void) read(fd, vtypes, comp.vTypeSize); 173 | close(fd); 174 | 175 | CodeObject object(cc, comp.nInherits, ftypes, vtypes); 176 | if (jitComp(&object, prog, comp.nFunctions, path, info.flags)) { 177 | (void) write(out, cmdhash, 17); 178 | } 179 | 180 | delete[] vtypes; 181 | delete[] ftypes; 182 | delete[] prog; 183 | } 184 | } 185 | 186 | return 0; 187 | } 188 | -------------------------------------------------------------------------------- /src/jit/code.h: -------------------------------------------------------------------------------- 1 | typedef uint8_t CodeByte; /* code byte */ 2 | typedef uint16_t CodeSize; /* function code size */ 3 | typedef uint16_t CodeLine; /* line number */ 4 | 5 | class CodeContext { 6 | public: 7 | class Kfun { 8 | public: 9 | LPCType *proto; /* return and argument types */ 10 | LPCParam nargs, vargs; /* # arguments & optional arguments */ 11 | bool lval; /* has lvalue arguments? */ 12 | }; 13 | 14 | CodeContext(size_t intSize, size_t inhSize, CodeByte *protos, int nBuiltins, 15 | int nKfuns, int typechecking); 16 | virtual ~CodeContext(); 17 | 18 | CodeByte *type(CodeByte *pc, LPCType *vType); 19 | 20 | static bool validVM(int major, int minor); 21 | 22 | size_t intSize; /* integer size */ 23 | size_t inhSize; /* inherit size */ 24 | Kfun *kfuns; /* kfun prototypes */ 25 | LPCKFun nkfun; /* # kfuns */ 26 | int typechecking; /* typechecking mode */ 27 | }; 28 | 29 | class CodeObject { 30 | public: 31 | CodeObject(CodeContext *context, LPCInherit nInherits, CodeByte *funcTypes, 32 | CodeByte *varTypes); 33 | virtual ~CodeObject(); 34 | 35 | Type varType(LPCGlobal *var); 36 | Type funcType(LPCDFunCall *func); 37 | 38 | CodeContext *context; /* context */ 39 | LPCInherit nInherits; /* # inherits */ 40 | 41 | private: 42 | CodeByte **funcTypes; /* function types */ 43 | CodeByte **varTypes; /* variable types */ 44 | }; 45 | 46 | class CodeFunction { 47 | public: 48 | enum Class { 49 | CLASS_PRIVATE = 0x01, 50 | CLASS_STATIC = 0x02, 51 | CLASS_NOMASK = 0x04, 52 | CLASS_ELLIPSIS = 0x08, 53 | CLASS_VARARGS = 0x08, 54 | CLASS_ATOMIC = 0x10, 55 | CLASS_TYPECHECKED = 0x20, 56 | CLASS_UNDEFINED = 0x80 57 | }; 58 | 59 | CodeFunction(CodeObject *object, CodeByte *prog); 60 | virtual ~CodeFunction(); 61 | 62 | CodeByte *getPC(CodeSize *addr); 63 | void setPC(CodeByte *pc); 64 | CodeLine getLine(CodeByte instr); 65 | CodeByte *endProg(); 66 | 67 | CodeObject *object; /* code object */ 68 | LPCType *proto; /* function prototype */ 69 | uint8_t fclass; /* function class */ 70 | LPCParam nargs, vargs; /* # arguments & optional arguments */ 71 | LPCLocal locals; /* # locals */ 72 | uint16_t stack; /* stack depth */ 73 | 74 | private: 75 | CodeByte *program, *lines; /* program & line numbers */ 76 | CodeSize pc, lc; /* program counter and line counter */ 77 | CodeLine line; /* current line */ 78 | }; 79 | 80 | 81 | class Code { 82 | public: 83 | struct CaseInt { 84 | LPCInt num; /* integer case label */ 85 | CodeSize addr; /* case address */ 86 | }; 87 | struct CaseRange { 88 | LPCInt from; /* range from case label */ 89 | LPCInt to; /* range to case label */ 90 | CodeSize addr; /* case address */ 91 | }; 92 | struct CaseString { 93 | LPCStringConst str; /* string constant case label */ 94 | CodeSize addr; /* case address */ 95 | }; 96 | 97 | Code(CodeFunction *function); 98 | virtual ~Code(); 99 | 100 | virtual void evaluateTypes(class TypedContext *context); 101 | virtual void evaluateFlow(class FlowContext *context); 102 | virtual void emit(class GenContext *context) = 0; 103 | 104 | static Code *produce(CodeFunction *function); 105 | static void producer(Code *(*factory)(CodeFunction*)); 106 | 107 | Code *next; /* following instruction */ 108 | CodeSize addr; /* address of this instruction */ 109 | CodeLine line; /* line number of this instruction */ 110 | bool pop; /* pop stack? */ 111 | enum { 112 | INT, 113 | FLOAT, 114 | STRING, 115 | PARAM, 116 | LOCAL, 117 | GLOBAL, 118 | INDEX, 119 | INDEX2, 120 | SPREAD, 121 | SPREAD_LVAL, 122 | AGGREGATE, 123 | MAP_AGGREGATE, 124 | CAST, 125 | INSTANCEOF, 126 | CHECK_RANGE, 127 | CHECK_RANGE_FROM, 128 | CHECK_RANGE_TO, 129 | STORES, 130 | STORES_LVAL, 131 | STORE_PARAM, 132 | STORE_LOCAL, 133 | STORE_GLOBAL, 134 | STORE_INDEX, 135 | STORE_PARAM_INDEX, 136 | STORE_LOCAL_INDEX, 137 | STORE_GLOBAL_INDEX, 138 | STORE_INDEX_INDEX, 139 | STORES_SPREAD, 140 | STORES_CAST, 141 | STORES_PARAM, 142 | STORES_LOCAL, 143 | STORES_GLOBAL, 144 | STORES_INDEX, 145 | STORES_PARAM_INDEX, 146 | STORES_LOCAL_INDEX, 147 | STORES_GLOBAL_INDEX, 148 | STORES_INDEX_INDEX, 149 | JUMP, 150 | JUMP_ZERO, 151 | JUMP_NONZERO, 152 | SWITCH_INT, 153 | SWITCH_RANGE, 154 | SWITCH_STRING, 155 | KFUNC, 156 | KFUNC_LVAL, 157 | KFUNC_SPREAD, 158 | KFUNC_SPREAD_LVAL, 159 | DFUNC, 160 | DFUNC_SPREAD, 161 | FUNC, 162 | FUNC_SPREAD, 163 | CATCH, 164 | CAUGHT, 165 | END_CATCH, 166 | RLIMITS, 167 | RLIMITS_CHECK, 168 | END_RLIMITS, 169 | RETURN 170 | } instruction; 171 | CodeSize size; /* size */ 172 | union { 173 | LPCInt num; /* integer */ 174 | LPCFloat flt; /* float */ 175 | LPCStringConst str; /* string constant */ 176 | LPCParam param; /* function parameter */ 177 | LPCLocal local; /* local variable */ 178 | LPCGlobal var; /* global variable */ 179 | LPCType type; /* type */ 180 | int8_t spread; /* spread */ 181 | CodeSize target; /* target address */ 182 | CaseInt *caseInt; /* int case labels */ 183 | CaseRange *caseRange; /* range case labels */ 184 | CaseString *caseString; /* string case labels */ 185 | LPCKFunCall kfun; /* kernel function call */ 186 | LPCDFunCall dfun; /* direct function call */ 187 | LPCVFunCall fun; /* virtual function call */ 188 | }; 189 | 190 | private: 191 | CodeByte *switchInt(CodeByte *pc); 192 | CodeByte *switchRange(CodeByte *pc); 193 | CodeByte *switchStr(CodeByte *pc, CodeContext *context); 194 | 195 | static Code *(*factory)(CodeFunction*); 196 | }; 197 | -------------------------------------------------------------------------------- /src/jit/instruction.h: -------------------------------------------------------------------------------- 1 | /* 2 | * VM Version 2.4 3 | * 10 August 2022 4 | */ 5 | 6 | # define I_INSTR_MASK 0x3f 7 | 8 | # define I_INT1 0x00 9 | # define I_INT2 0x20 10 | # define I_INT4 0x01 11 | # define I_INT8 0x21 12 | # define I_FLOAT6 0x03 13 | # define I_FLOAT12 0x23 14 | # define I_STRING 0x04 15 | # define I_NEAR_STRING 0x24 16 | # define I_FAR_STRING 0x05 17 | # define I_LOCAL 0x25 18 | # define I_GLOBAL 0x06 19 | # define I_FAR_GLOBAL 0x26 20 | # define I_INDEX 0x07 21 | # define I_INDEX2 0x08 22 | # define I_SPREAD 0x28 23 | # define I_AGGREGATE 0x09 24 | # define I_CAST 0x0a 25 | # define I_INSTANCEOF 0x0b 26 | # define I_STORES 0x0c 27 | # define I_STORE_GLOBAL_INDEX 0x0d 28 | # define I_CALL_EFUNC 0x0e 29 | # define I_CALL_CEFUNC 0x0f 30 | # define I_CALL_CKFUNC 0x10 31 | # define I_STORE_LOCAL 0x11 32 | # define I_STORE_GLOBAL 0x12 33 | # define I_STORE_FAR_GLOBAL 0x13 34 | # define I_STORE_INDEX 0x14 35 | # define I_STORE_LOCAL_INDEX 0x15 36 | # define I_STORE_FAR_GLOBAL_INDEX 0x16 37 | # define I_STORE_INDEX_INDEX 0x17 38 | # define I_JUMP_ZERO 0x18 39 | # define I_JUMP_NONZERO 0x38 40 | # define I_JUMP 0x19 41 | # define I_SWITCH 0x39 42 | # define I_CALL_KFUNC 0x1a 43 | # define I_CALL_AFUNC 0x1b 44 | # define I_CALL_DFUNC 0x1c 45 | # define I_CALL_FUNC 0x1d 46 | # define I_CATCH 0x1e 47 | # define I_RLIMITS 0x1f 48 | # define I_RETURN 0x3f 49 | 50 | # define I_POP_BIT 0x20 51 | # define I_LINE_MASK 0xc0 52 | # define I_LINE_SHIFT 6 53 | 54 | # define I_SWITCH_INT 0 55 | # define I_SWITCH_RANGE 1 56 | # define I_SWITCH_STRING 2 57 | 58 | # define VERSION_VM_MAJOR 2 59 | # define VERSION_VM_MINOR 4 60 | 61 | # define FETCH1U(pc) (*(pc)++) 62 | # define FETCH1S(pc) ((int64_t) (int8_t) *(pc)++) 63 | # define GET2(pc) (((uint16_t) (pc)[-2] << 8) + (pc)[-1]) 64 | # define FETCH2U(pc) ((pc) += 2, GET2(pc)) 65 | # define FETCH2S(pc) ((pc) += 2, ((int64_t) (int8_t) (pc)[-2] << 8) + \ 66 | (pc)[-1]) 67 | # define GET3(pc) (((uint32_t) (pc)[-3] << 16) + GET2(pc)) 68 | # define FETCH3U(pc) ((pc) += 3, GET3(pc)) 69 | # define FETCH3S(pc) ((pc) += 3, ((int64_t) (int8_t) (pc)[-3] << 16) + \ 70 | GET2(pc)) 71 | # define GET4(pc) (((uint32_t) (pc)[-4] << 24) + GET3(pc)) 72 | # define FETCH4U(pc) ((pc) += 4, GET4(pc)) 73 | # define FETCH4S(pc) ((pc) += 4, ((int64_t) (int8_t) (pc)[-4] << 24) + \ 74 | GET3(pc)) 75 | # define GET5(pc) (((uint64_t) (pc)[-5] << 32) + GET4(pc)) 76 | # define FETCH5U(pc) ((pc) += 5, GET5(pc)) 77 | # define FETCH5S(pc) ((pc) += 5, ((int64_t) (int8_t) (pc)[-5] << 32) + \ 78 | GET4(pc)) 79 | # define GET6(pc) (((uint64_t) (pc)[-6] << 40) + GET5(pc)) 80 | # define FETCH6U(pc) ((pc) += 6,GET6(pc)) 81 | # define FETCH6S(pc) ((pc) += 6, ((int64_t) (int8_t) (pc)[-6] << 40) + \ 82 | GET5(pc)) 83 | # define GET7(pc) (((uint64_t) (pc)[-7] << 48) + GET6(pc)) 84 | # define FETCH7U(pc) ((pc) += 7, GET7(pc)) 85 | # define FETCH7S(pc) ((pc) += 7, ((int64_t) (int8_t) (pc)[-7] << 48) + \ 86 | GET6(pc)) 87 | # define GET8(pc) (((uint64_t) (pc)[-8] << 56) + GET7(pc)) 88 | # define FETCH8U(pc) ((pc) += 8, GET8(pc)) 89 | # define FETCH8S(pc) ((pc) += 8, (int64_t) GET8(pc)) 90 | 91 | # define PROTO_CLASS(p) ((p)[0]) 92 | # define PROTO_NARGS(p) ((p)[1]) 93 | # define PROTO_VARGS(p) ((p)[2]) 94 | # define PROTO_FTYPE(p) ((p)[5]) 95 | 96 | # define KF_ADD 0 97 | # define KF_ADD_INT 1 98 | # define KF_ADD1 2 99 | # define KF_ADD1_INT 3 100 | # define KF_AND 4 101 | # define KF_AND_INT 5 102 | # define KF_DIV 6 103 | # define KF_DIV_INT 7 104 | # define KF_EQ 8 105 | # define KF_EQ_INT 9 106 | # define KF_GE 10 107 | # define KF_GE_INT 11 108 | # define KF_GT 12 109 | # define KF_GT_INT 13 110 | # define KF_LE 14 111 | # define KF_LE_INT 15 112 | # define KF_LSHIFT 16 113 | # define KF_LSHIFT_INT 17 114 | # define KF_LT 18 115 | # define KF_LT_INT 19 116 | # define KF_MOD 20 117 | # define KF_MOD_INT 21 118 | # define KF_MULT 22 119 | # define KF_MULT_INT 23 120 | # define KF_NE 24 121 | # define KF_NE_INT 25 122 | # define KF_NEG 26 123 | # define KF_NEG_INT 27 124 | # define KF_NOT 28 125 | # define KF_NOT_INT 29 126 | # define KF_OR 30 127 | # define KF_OR_INT 31 128 | # define KF_RANGEFT 32 129 | # define KF_RANGEF 33 130 | # define KF_RANGET 34 131 | # define KF_RANGE 35 132 | # define KF_RSHIFT 36 133 | # define KF_RSHIFT_INT 37 134 | # define KF_SUB 38 135 | # define KF_SUB_INT 39 136 | # define KF_SUB1 40 137 | # define KF_SUB1_INT 41 138 | # define KF_TOFLOAT 42 139 | # define KF_TOINT 43 140 | # define KF_TST 44 141 | # define KF_TST_INT 45 142 | # define KF_UMIN 46 143 | # define KF_UMIN_INT 47 144 | # define KF_XOR 48 145 | # define KF_XOR_INT 49 146 | # define KF_TOSTRING 50 147 | # define KF_CKRANGEFT 51 148 | # define KF_CKRANGEF 52 149 | # define KF_CKRANGET 53 150 | # define KF_CALL_OTHER 54 151 | # define KF_STATUS_IDX 55 152 | # define KF_STATUSO_IDX 56 153 | # define KF_CALLTR_IDX 57 154 | # define KF_NIL 58 155 | # define KF_STATUS 59 156 | # define KF_CALL_TRACE 60 157 | # define KF_ADD_FLT 61 158 | # define KF_ADD_FLT_STR 62 159 | # define KF_ADD_INT_STR 63 160 | # define KF_ADD_STR 64 161 | # define KF_ADD_STR_FLT 65 162 | # define KF_ADD_STR_INT 66 163 | # define KF_ADD1_FLT 67 164 | # define KF_DIV_FLT 68 165 | # define KF_EQ_FLT 69 166 | # define KF_EQ_STR 70 167 | # define KF_GE_FLT 71 168 | # define KF_GE_STR 72 169 | # define KF_GT_FLT 73 170 | # define KF_GT_STR 74 171 | # define KF_LE_FLT 75 172 | # define KF_LE_STR 76 173 | # define KF_LT_FLT 77 174 | # define KF_LT_STR 78 175 | # define KF_MULT_FLT 79 176 | # define KF_NE_FLT 80 177 | # define KF_NE_STR 81 178 | # define KF_NOT_FLT 82 179 | # define KF_NOT_STR 83 180 | # define KF_SUB_FLT 84 181 | # define KF_SUB1_FLT 85 182 | # define KF_TST_FLT 86 183 | # define KF_TST_STR 87 184 | # define KF_UMIN_FLT 88 185 | # define KF_SUM 89 186 | # define KF_FABS 90 187 | # define KF_FLOOR 91 188 | # define KF_CEIL 92 189 | # define KF_FMOD 93 190 | # define KF_FREXP 94 191 | # define KF_LDEXP 95 192 | # define KF_MODF 96 193 | # define KF_EXP 97 194 | # define KF_LOG 98 195 | # define KF_LOG10 99 196 | # define KF_POW 100 197 | # define KF_SQRT 101 198 | # define KF_COS 102 199 | # define KF_SIN 103 200 | # define KF_TAN 104 201 | # define KF_ACOS 105 202 | # define KF_ASIN 106 203 | # define KF_ATAN 107 204 | # define KF_ATAN2 108 205 | # define KF_COSH 109 206 | # define KF_SINH 110 207 | # define KF_TANH 111 208 | # define KF_CALLTR_IDX_IDX 112 209 | # define KF_STRLEN 113 210 | # define KF_RANGEFT_STR 114 211 | # define KF_RANGEF_STR 115 212 | # define KF_RANGET_STR 116 213 | 214 | # define KF_BUILTINS 128 215 | 216 | # define SUM_SIMPLE -2 217 | # define SUM_AGGREGATE -6 218 | -------------------------------------------------------------------------------- /src/lpc_ext.h: -------------------------------------------------------------------------------- 1 | # ifndef LPC_EXT_H 2 | # define LPC_EXT_H 3 | 4 | # include 5 | # include 6 | 7 | 8 | # define LPC_EXT_VERSION_MAJOR 1 9 | # define LPC_EXT_VERSION_MINOR 5 10 | 11 | # define LPC_TYPE_NIL 0 12 | # define LPC_TYPE_INT 1 13 | # define LPC_TYPE_FLOAT 2 14 | # define LPC_TYPE_STRING 3 15 | # define LPC_TYPE_OBJECT 4 16 | # define LPC_TYPE_ARRAY 5 17 | # define LPC_TYPE_MAPPING 6 18 | # define LPC_TYPE_LWOBJ 7 19 | # define LPC_TYPE_MIXED 8 20 | # define LPC_TYPE_VOID 9 21 | # define LPC_TYPE_LVALUE 10 22 | # define LPC_TYPE_VARARGS 16 23 | # define LPC_TYPE_ELLIPSIS 16 24 | # define LPC_TYPE_ARRAY_OF(t) ((t) + 16) 25 | 26 | # ifdef LARGENUM 27 | typedef int64_t LPC_int; 28 | # else 29 | typedef int32_t LPC_int; 30 | # endif 31 | # ifndef NOFLOAT 32 | typedef long double LPC_float; 33 | # endif 34 | typedef struct _string_ *LPC_string; 35 | typedef struct _object_ *LPC_object; 36 | typedef struct _array_ *LPC_array; 37 | typedef struct _array_ *LPC_mapping; 38 | typedef struct _array_ *LPC_lwobj; 39 | typedef struct _value_ *LPC_value; 40 | typedef struct _frame_ *LPC_frame; 41 | typedef struct _dataspace_ *LPC_dataspace; 42 | typedef void (*LPC_kfun)(LPC_frame, int, LPC_value); 43 | typedef struct { 44 | char *name; /* kfun name */ 45 | char *proto; /* kfun prototype */ 46 | LPC_kfun func; /* kfun address */ 47 | } LPC_ext_kfun; 48 | typedef struct _lpc_database_ LPC_db; 49 | typedef struct _lpc_db_object_ LPC_db_object; 50 | typedef uint64_t LPC_db_index; 51 | typedef uint16_t LPC_db_handle; 52 | typedef struct { 53 | void *data; /* address */ 54 | uint64_t offset; /* offset of request */ 55 | uint64_t size; /* size of request */ 56 | } LPC_db_request; 57 | typedef struct { 58 | int (*valid) (const char*); 59 | LPC_db *(*open) (const char*, int*); 60 | void (*close) (LPC_db*); 61 | LPC_db_object *(*new_obj) (LPC_db*, LPC_db_index); 62 | LPC_db_object *(*load_obj) (LPC_db*, LPC_db_index, LPC_db_handle); 63 | int (*del_obj) (LPC_db_object*); 64 | int (*refresh_obj) (LPC_db_object*); 65 | int (*resize_obj) (LPC_db_object*, uint64_t, LPC_db_handle*); 66 | int (*read_obj) (LPC_db_object*, LPC_db_request*, int); 67 | int (*write_obj) (LPC_db_object*, LPC_db_request*, int); 68 | int (*remove_obj) (LPC_db_object*); 69 | int (*save) (LPC_db*, LPC_db_request*); 70 | int (*restore) (LPC_db*, LPC_db_request*); 71 | int (*save_snapshot) (LPC_db*, LPC_db_request*); 72 | int (*restore_snapshot) (LPC_db*, LPC_db_request*); 73 | } LPC_ext_dbase; 74 | typedef void (*LPC_function) (void**, LPC_frame); 75 | typedef int (*LPC_jit_init)(int, int, size_t, size_t, int, 76 | int, int, uint8_t*, size_t, 77 | void**); 78 | typedef void (*LPC_jit_finish)(void); 79 | typedef void (*LPC_jit_compile)(uint64_t, uint64_t, int, 80 | uint8_t*, size_t, int, 81 | uint8_t*, size_t, uint8_t*, 82 | size_t); 83 | typedef int (*LPC_jit_execute)(uint64_t, uint64_t, int, int, 84 | void*); 85 | typedef void (*LPC_jit_release)(uint64_t, uint64_t); 86 | typedef int (*LPC_jit_functions)(uint64_t, uint64_t, int, 87 | LPC_function**); 88 | 89 | 90 | extern int lpc_ext_init(int, int, const char*); 91 | extern int lpc_ext_spawn(const char*); 92 | extern int lpc_ext_read(void*, int); 93 | extern int lpc_ext_write(const void*, int); 94 | extern int lpc_ext_writeback(const void*, int); 95 | 96 | # ifndef LPCEXT 97 | # define LPCEXT extern 98 | # endif 99 | 100 | LPCEXT void (*lpc_ext_kfun)(const LPC_ext_kfun*, int); 101 | LPCEXT void (*lpc_ext_dbase)(const LPC_ext_dbase*); 102 | LPCEXT int (*lpc_ext_jit)(LPC_jit_init, LPC_jit_finish, 103 | LPC_jit_compile, LPC_jit_execute, 104 | LPC_jit_release, 105 | LPC_jit_functions); 106 | 107 | LPCEXT LPC_object (*lpc_frame_object)(LPC_frame); 108 | LPCEXT LPC_dataspace (*lpc_frame_dataspace)(LPC_frame); 109 | LPCEXT LPC_value (*lpc_frame_arg)(LPC_frame, int, int); 110 | LPCEXT int (*lpc_frame_atomic)(LPC_frame); 111 | 112 | LPCEXT LPC_value (*lpc_data_get_val)(LPC_dataspace); 113 | LPCEXT void (*lpc_data_set_val)(LPC_dataspace, LPC_value); 114 | 115 | LPCEXT int (*lpc_value_type)(LPC_value); 116 | LPCEXT LPC_value (*lpc_value_nil)(void); 117 | LPCEXT LPC_value (*lpc_value_temp)(LPC_dataspace); 118 | LPCEXT LPC_value (*lpc_value_temp2)(LPC_dataspace); 119 | 120 | LPCEXT LPC_int (*lpc_int_getval)(LPC_value); 121 | LPCEXT void (*lpc_int_putval)(LPC_value, LPC_int); 122 | 123 | # ifndef NOFLOAT 124 | LPCEXT LPC_float (*lpc_float_getval)(LPC_value); 125 | LPCEXT void (*lpc_float_putval)(LPC_value, LPC_float); 126 | # endif 127 | 128 | LPCEXT LPC_string (*lpc_string_getval)(LPC_value); 129 | LPCEXT void (*lpc_string_putval)(LPC_value, LPC_string); 130 | LPCEXT LPC_string (*lpc_string_new)(LPC_dataspace, const char*, 131 | int); 132 | LPCEXT char * (*lpc_string_text)(LPC_string); 133 | LPCEXT int (*lpc_string_length)(LPC_string); 134 | 135 | LPCEXT void (*lpc_object_putval)(LPC_value, LPC_object); 136 | LPCEXT const char * (*lpc_object_name)(LPC_frame, LPC_object, 137 | char*); 138 | LPCEXT int (*lpc_object_isspecial)(LPC_frame, LPC_object); 139 | LPCEXT int (*lpc_object_ismarked)(LPC_frame, LPC_object); 140 | LPCEXT void (*lpc_object_mark)(LPC_frame, LPC_object); 141 | LPCEXT void (*lpc_object_unmark)(LPC_frame, LPC_object); 142 | 143 | LPCEXT LPC_array (*lpc_array_getval)(LPC_value); 144 | LPCEXT void (*lpc_array_putval)(LPC_value, LPC_array); 145 | LPCEXT LPC_array (*lpc_array_new)(LPC_dataspace, int); 146 | LPCEXT LPC_value (*lpc_array_index)(LPC_array, int); 147 | LPCEXT void (*lpc_array_assign)(LPC_dataspace, LPC_array, 148 | int, LPC_value); 149 | LPCEXT int (*lpc_array_size)(LPC_array); 150 | 151 | LPCEXT LPC_mapping (*lpc_mapping_getval)(LPC_value); 152 | LPCEXT void (*lpc_mapping_putval)(LPC_value, LPC_mapping); 153 | LPCEXT LPC_mapping (*lpc_mapping_new)(LPC_dataspace); 154 | LPCEXT LPC_value (*lpc_mapping_index)(LPC_mapping, LPC_value); 155 | LPCEXT void (*lpc_mapping_assign)(LPC_dataspace, 156 | LPC_mapping, LPC_value, 157 | LPC_value); 158 | LPCEXT LPC_value (*lpc_mapping_enum)(LPC_mapping, unsigned int); 159 | LPCEXT int (*lpc_mapping_size)(LPC_mapping); 160 | 161 | LPCEXT void (*lpc_runtime_error)(LPC_frame, const char*); 162 | LPCEXT void (*lpc_md5_start)(uint32_t*); 163 | LPCEXT void (*lpc_md5_block)(uint32_t*, 164 | const unsigned char*); 165 | LPCEXT void (*lpc_md5_end)(unsigned char*, uint32_t*, 166 | unsigned char*, uint16_t, 167 | uint32_t); 168 | LPCEXT void (*lpc_runtime_ticks)(LPC_frame, int); 169 | LPCEXT void (*lpc_runtime_check)(LPC_frame, int); 170 | # endif /* LPC_EXT_H */ 171 | -------------------------------------------------------------------------------- /src/kfun/zlib/1.2.8/inflate.h: -------------------------------------------------------------------------------- 1 | /* inflate.h -- internal inflate state definition 2 | * Copyright (C) 1995-2009 Mark Adler 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the compression library and is 8 | subject to change. Applications should only use zlib.h. 9 | */ 10 | 11 | /* define NO_GZIP when compiling if you want to disable gzip header and 12 | trailer decoding by inflate(). NO_GZIP would be used to avoid linking in 13 | the crc code when it is not needed. For shared libraries, gzip decoding 14 | should be left enabled. */ 15 | #ifndef NO_GZIP 16 | # define GUNZIP 17 | #endif 18 | 19 | /* Possible inflate modes between inflate() calls */ 20 | typedef enum { 21 | HEAD, /* i: waiting for magic header */ 22 | FLAGS, /* i: waiting for method and flags (gzip) */ 23 | TIME, /* i: waiting for modification time (gzip) */ 24 | OS, /* i: waiting for extra flags and operating system (gzip) */ 25 | EXLEN, /* i: waiting for extra length (gzip) */ 26 | EXTRA, /* i: waiting for extra bytes (gzip) */ 27 | NAME, /* i: waiting for end of file name (gzip) */ 28 | COMMENT, /* i: waiting for end of comment (gzip) */ 29 | HCRC, /* i: waiting for header crc (gzip) */ 30 | DICTID, /* i: waiting for dictionary check value */ 31 | DICT, /* waiting for inflateSetDictionary() call */ 32 | TYPE, /* i: waiting for type bits, including last-flag bit */ 33 | TYPEDO, /* i: same, but skip check to exit inflate on new block */ 34 | STORED, /* i: waiting for stored size (length and complement) */ 35 | COPY_, /* i/o: same as COPY below, but only first time in */ 36 | COPY, /* i/o: waiting for input or output to copy stored block */ 37 | TABLE, /* i: waiting for dynamic block table lengths */ 38 | LENLENS, /* i: waiting for code length code lengths */ 39 | CODELENS, /* i: waiting for length/lit and distance code lengths */ 40 | LEN_, /* i: same as LEN below, but only first time in */ 41 | LEN, /* i: waiting for length/lit/eob code */ 42 | LENEXT, /* i: waiting for length extra bits */ 43 | DIST, /* i: waiting for distance code */ 44 | DISTEXT, /* i: waiting for distance extra bits */ 45 | MATCH, /* o: waiting for output space to copy string */ 46 | LIT, /* o: waiting for output space to write literal */ 47 | CHECK, /* i: waiting for 32-bit check value */ 48 | LENGTH, /* i: waiting for 32-bit length (gzip) */ 49 | DONE, /* finished check, done -- remain here until reset */ 50 | BAD, /* got a data error -- remain here until reset */ 51 | MEM, /* got an inflate() memory error -- remain here until reset */ 52 | SYNC /* looking for synchronization bytes to restart inflate() */ 53 | } inflate_mode; 54 | 55 | /* 56 | State transitions between above modes - 57 | 58 | (most modes can go to BAD or MEM on error -- not shown for clarity) 59 | 60 | Process header: 61 | HEAD -> (gzip) or (zlib) or (raw) 62 | (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> 63 | HCRC -> TYPE 64 | (zlib) -> DICTID or TYPE 65 | DICTID -> DICT -> TYPE 66 | (raw) -> TYPEDO 67 | Read deflate blocks: 68 | TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK 69 | STORED -> COPY_ -> COPY -> TYPE 70 | TABLE -> LENLENS -> CODELENS -> LEN_ 71 | LEN_ -> LEN 72 | Read deflate codes in fixed or dynamic block: 73 | LEN -> LENEXT or LIT or TYPE 74 | LENEXT -> DIST -> DISTEXT -> MATCH -> LEN 75 | LIT -> LEN 76 | Process trailer: 77 | CHECK -> LENGTH -> DONE 78 | */ 79 | 80 | /* state maintained between inflate() calls. Approximately 10K bytes. */ 81 | struct inflate_state { 82 | inflate_mode mode; /* current inflate mode */ 83 | int last; /* true if processing last block */ 84 | int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ 85 | int havedict; /* true if dictionary provided */ 86 | int flags; /* gzip header method and flags (0 if zlib) */ 87 | unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ 88 | unsigned long check; /* protected copy of check value */ 89 | unsigned long total; /* protected copy of output count */ 90 | gz_headerp head; /* where to save gzip header information */ 91 | /* sliding window */ 92 | unsigned wbits; /* log base 2 of requested window size */ 93 | unsigned wsize; /* window size or zero if not using window */ 94 | unsigned whave; /* valid bytes in the window */ 95 | unsigned wnext; /* window write index */ 96 | unsigned char FAR *window; /* allocated sliding window, if needed */ 97 | /* bit accumulator */ 98 | unsigned long hold; /* input bit accumulator */ 99 | unsigned bits; /* number of bits in "in" */ 100 | /* for string and stored block copying */ 101 | unsigned length; /* literal or length of data to copy */ 102 | unsigned offset; /* distance back to copy string from */ 103 | /* for table and code decoding */ 104 | unsigned extra; /* extra bits needed */ 105 | /* fixed and dynamic code tables */ 106 | code const FAR *lencode; /* starting table for length/literal codes */ 107 | code const FAR *distcode; /* starting table for distance codes */ 108 | unsigned lenbits; /* index bits for lencode */ 109 | unsigned distbits; /* index bits for distcode */ 110 | /* dynamic table building */ 111 | unsigned ncode; /* number of code length code lengths */ 112 | unsigned nlen; /* number of length code lengths */ 113 | unsigned ndist; /* number of distance code lengths */ 114 | unsigned have; /* number of code lengths in lens[] */ 115 | code FAR *next; /* next available space in codes[] */ 116 | unsigned short lens[320]; /* temporary storage for code lengths */ 117 | unsigned short work[288]; /* work area for code table building */ 118 | code codes[ENOUGH]; /* space for code tables */ 119 | int sane; /* if false, allow invalid distance too far */ 120 | int back; /* bits back of last unprocessed length/lit */ 121 | unsigned was; /* initial length of match */ 122 | }; 123 | -------------------------------------------------------------------------------- /project/lpc-ext/lpc-ext.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {BF10E509-A9A8-4FA6-94E9-EE1C53DDDE74} 23 | Win32Proj 24 | lpcext 25 | 26 | 27 | 28 | StaticLibrary 29 | true 30 | NotSet 31 | 32 | 33 | StaticLibrary 34 | true 35 | NotSet 36 | 37 | 38 | StaticLibrary 39 | false 40 | true 41 | NotSet 42 | 43 | 44 | StaticLibrary 45 | false 46 | true 47 | NotSet 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | Level3 71 | Disabled 72 | WIN32;_USRDLL;_DEBUG;%(PreprocessorDefinitions) 73 | 74 | 75 | Windows 76 | true 77 | 78 | 79 | 80 | 81 | 82 | 83 | Level3 84 | Disabled 85 | WIN32;_USRDLL;_DEBUG;%(PreprocessorDefinitions) 86 | 87 | 88 | Windows 89 | true 90 | 91 | 92 | 93 | 94 | Level3 95 | 96 | 97 | MaxSpeed 98 | true 99 | true 100 | WIN32;_USRDLL;NDEBUG;%(PreprocessorDefinitions) 101 | 102 | 103 | Windows 104 | true 105 | true 106 | true 107 | 108 | 109 | 110 | 111 | Level3 112 | 113 | 114 | MaxSpeed 115 | true 116 | true 117 | WIN32;_USRDLL;NDEBUG;%(PreprocessorDefinitions) 118 | 119 | 120 | Windows 121 | true 122 | true 123 | true 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /src/kfun/zlib/1.2.11/inflate.h: -------------------------------------------------------------------------------- 1 | /* inflate.h -- internal inflate state definition 2 | * Copyright (C) 1995-2016 Mark Adler 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the compression library and is 8 | subject to change. Applications should only use zlib.h. 9 | */ 10 | 11 | /* define NO_GZIP when compiling if you want to disable gzip header and 12 | trailer decoding by inflate(). NO_GZIP would be used to avoid linking in 13 | the crc code when it is not needed. For shared libraries, gzip decoding 14 | should be left enabled. */ 15 | #ifndef NO_GZIP 16 | # define GUNZIP 17 | #endif 18 | 19 | /* Possible inflate modes between inflate() calls */ 20 | typedef enum { 21 | HEAD = 16180, /* i: waiting for magic header */ 22 | FLAGS, /* i: waiting for method and flags (gzip) */ 23 | TIME, /* i: waiting for modification time (gzip) */ 24 | OS, /* i: waiting for extra flags and operating system (gzip) */ 25 | EXLEN, /* i: waiting for extra length (gzip) */ 26 | EXTRA, /* i: waiting for extra bytes (gzip) */ 27 | NAME, /* i: waiting for end of file name (gzip) */ 28 | COMMENT, /* i: waiting for end of comment (gzip) */ 29 | HCRC, /* i: waiting for header crc (gzip) */ 30 | DICTID, /* i: waiting for dictionary check value */ 31 | DICT, /* waiting for inflateSetDictionary() call */ 32 | TYPE, /* i: waiting for type bits, including last-flag bit */ 33 | TYPEDO, /* i: same, but skip check to exit inflate on new block */ 34 | STORED, /* i: waiting for stored size (length and complement) */ 35 | COPY_, /* i/o: same as COPY below, but only first time in */ 36 | COPY, /* i/o: waiting for input or output to copy stored block */ 37 | TABLE, /* i: waiting for dynamic block table lengths */ 38 | LENLENS, /* i: waiting for code length code lengths */ 39 | CODELENS, /* i: waiting for length/lit and distance code lengths */ 40 | LEN_, /* i: same as LEN below, but only first time in */ 41 | LEN, /* i: waiting for length/lit/eob code */ 42 | LENEXT, /* i: waiting for length extra bits */ 43 | DIST, /* i: waiting for distance code */ 44 | DISTEXT, /* i: waiting for distance extra bits */ 45 | MATCH, /* o: waiting for output space to copy string */ 46 | LIT, /* o: waiting for output space to write literal */ 47 | CHECK, /* i: waiting for 32-bit check value */ 48 | LENGTH, /* i: waiting for 32-bit length (gzip) */ 49 | DONE, /* finished check, done -- remain here until reset */ 50 | BAD, /* got a data error -- remain here until reset */ 51 | MEM, /* got an inflate() memory error -- remain here until reset */ 52 | SYNC /* looking for synchronization bytes to restart inflate() */ 53 | } inflate_mode; 54 | 55 | /* 56 | State transitions between above modes - 57 | 58 | (most modes can go to BAD or MEM on error -- not shown for clarity) 59 | 60 | Process header: 61 | HEAD -> (gzip) or (zlib) or (raw) 62 | (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> 63 | HCRC -> TYPE 64 | (zlib) -> DICTID or TYPE 65 | DICTID -> DICT -> TYPE 66 | (raw) -> TYPEDO 67 | Read deflate blocks: 68 | TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK 69 | STORED -> COPY_ -> COPY -> TYPE 70 | TABLE -> LENLENS -> CODELENS -> LEN_ 71 | LEN_ -> LEN 72 | Read deflate codes in fixed or dynamic block: 73 | LEN -> LENEXT or LIT or TYPE 74 | LENEXT -> DIST -> DISTEXT -> MATCH -> LEN 75 | LIT -> LEN 76 | Process trailer: 77 | CHECK -> LENGTH -> DONE 78 | */ 79 | 80 | /* State maintained between inflate() calls -- approximately 7K bytes, not 81 | including the allocated sliding window, which is up to 32K bytes. */ 82 | struct inflate_state { 83 | z_streamp strm; /* pointer back to this zlib stream */ 84 | inflate_mode mode; /* current inflate mode */ 85 | int last; /* true if processing last block */ 86 | int wrap; /* bit 0 true for zlib, bit 1 true for gzip, 87 | bit 2 true to validate check value */ 88 | int havedict; /* true if dictionary provided */ 89 | int flags; /* gzip header method and flags (0 if zlib) */ 90 | unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ 91 | unsigned long check; /* protected copy of check value */ 92 | unsigned long total; /* protected copy of output count */ 93 | gz_headerp head; /* where to save gzip header information */ 94 | /* sliding window */ 95 | unsigned wbits; /* log base 2 of requested window size */ 96 | unsigned wsize; /* window size or zero if not using window */ 97 | unsigned whave; /* valid bytes in the window */ 98 | unsigned wnext; /* window write index */ 99 | unsigned char FAR *window; /* allocated sliding window, if needed */ 100 | /* bit accumulator */ 101 | unsigned long hold; /* input bit accumulator */ 102 | unsigned bits; /* number of bits in "in" */ 103 | /* for string and stored block copying */ 104 | unsigned length; /* literal or length of data to copy */ 105 | unsigned offset; /* distance back to copy string from */ 106 | /* for table and code decoding */ 107 | unsigned extra; /* extra bits needed */ 108 | /* fixed and dynamic code tables */ 109 | code const FAR *lencode; /* starting table for length/literal codes */ 110 | code const FAR *distcode; /* starting table for distance codes */ 111 | unsigned lenbits; /* index bits for lencode */ 112 | unsigned distbits; /* index bits for distcode */ 113 | /* dynamic table building */ 114 | unsigned ncode; /* number of code length code lengths */ 115 | unsigned nlen; /* number of length code lengths */ 116 | unsigned ndist; /* number of distance code lengths */ 117 | unsigned have; /* number of code lengths in lens[] */ 118 | code FAR *next; /* next available space in codes[] */ 119 | unsigned short lens[320]; /* temporary storage for code lengths */ 120 | unsigned short work[288]; /* work area for code table building */ 121 | code codes[ENOUGH]; /* space for code tables */ 122 | int sane; /* if false, allow invalid distance too far */ 123 | int back; /* bits back of last unprocessed length/lit */ 124 | unsigned was; /* initial length of match */ 125 | }; 126 | -------------------------------------------------------------------------------- /src/kfun/zlib/1.2.12/inflate.h: -------------------------------------------------------------------------------- 1 | /* inflate.h -- internal inflate state definition 2 | * Copyright (C) 1995-2019 Mark Adler 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the compression library and is 8 | subject to change. Applications should only use zlib.h. 9 | */ 10 | 11 | /* define NO_GZIP when compiling if you want to disable gzip header and 12 | trailer decoding by inflate(). NO_GZIP would be used to avoid linking in 13 | the crc code when it is not needed. For shared libraries, gzip decoding 14 | should be left enabled. */ 15 | #ifndef NO_GZIP 16 | # define GUNZIP 17 | #endif 18 | 19 | /* Possible inflate modes between inflate() calls */ 20 | typedef enum { 21 | HEAD = 16180, /* i: waiting for magic header */ 22 | FLAGS, /* i: waiting for method and flags (gzip) */ 23 | TIME, /* i: waiting for modification time (gzip) */ 24 | OS, /* i: waiting for extra flags and operating system (gzip) */ 25 | EXLEN, /* i: waiting for extra length (gzip) */ 26 | EXTRA, /* i: waiting for extra bytes (gzip) */ 27 | NAME, /* i: waiting for end of file name (gzip) */ 28 | COMMENT, /* i: waiting for end of comment (gzip) */ 29 | HCRC, /* i: waiting for header crc (gzip) */ 30 | DICTID, /* i: waiting for dictionary check value */ 31 | DICT, /* waiting for inflateSetDictionary() call */ 32 | TYPE, /* i: waiting for type bits, including last-flag bit */ 33 | TYPEDO, /* i: same, but skip check to exit inflate on new block */ 34 | STORED, /* i: waiting for stored size (length and complement) */ 35 | COPY_, /* i/o: same as COPY below, but only first time in */ 36 | COPY, /* i/o: waiting for input or output to copy stored block */ 37 | TABLE, /* i: waiting for dynamic block table lengths */ 38 | LENLENS, /* i: waiting for code length code lengths */ 39 | CODELENS, /* i: waiting for length/lit and distance code lengths */ 40 | LEN_, /* i: same as LEN below, but only first time in */ 41 | LEN, /* i: waiting for length/lit/eob code */ 42 | LENEXT, /* i: waiting for length extra bits */ 43 | DIST, /* i: waiting for distance code */ 44 | DISTEXT, /* i: waiting for distance extra bits */ 45 | MATCH, /* o: waiting for output space to copy string */ 46 | LIT, /* o: waiting for output space to write literal */ 47 | CHECK, /* i: waiting for 32-bit check value */ 48 | LENGTH, /* i: waiting for 32-bit length (gzip) */ 49 | DONE, /* finished check, done -- remain here until reset */ 50 | BAD, /* got a data error -- remain here until reset */ 51 | MEM, /* got an inflate() memory error -- remain here until reset */ 52 | SYNC /* looking for synchronization bytes to restart inflate() */ 53 | } inflate_mode; 54 | 55 | /* 56 | State transitions between above modes - 57 | 58 | (most modes can go to BAD or MEM on error -- not shown for clarity) 59 | 60 | Process header: 61 | HEAD -> (gzip) or (zlib) or (raw) 62 | (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> 63 | HCRC -> TYPE 64 | (zlib) -> DICTID or TYPE 65 | DICTID -> DICT -> TYPE 66 | (raw) -> TYPEDO 67 | Read deflate blocks: 68 | TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK 69 | STORED -> COPY_ -> COPY -> TYPE 70 | TABLE -> LENLENS -> CODELENS -> LEN_ 71 | LEN_ -> LEN 72 | Read deflate codes in fixed or dynamic block: 73 | LEN -> LENEXT or LIT or TYPE 74 | LENEXT -> DIST -> DISTEXT -> MATCH -> LEN 75 | LIT -> LEN 76 | Process trailer: 77 | CHECK -> LENGTH -> DONE 78 | */ 79 | 80 | /* State maintained between inflate() calls -- approximately 7K bytes, not 81 | including the allocated sliding window, which is up to 32K bytes. */ 82 | struct inflate_state { 83 | z_streamp strm; /* pointer back to this zlib stream */ 84 | inflate_mode mode; /* current inflate mode */ 85 | int last; /* true if processing last block */ 86 | int wrap; /* bit 0 true for zlib, bit 1 true for gzip, 87 | bit 2 true to validate check value */ 88 | int havedict; /* true if dictionary provided */ 89 | int flags; /* gzip header method and flags, 0 if zlib, or 90 | -1 if raw or no header yet */ 91 | unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ 92 | unsigned long check; /* protected copy of check value */ 93 | unsigned long total; /* protected copy of output count */ 94 | gz_headerp head; /* where to save gzip header information */ 95 | /* sliding window */ 96 | unsigned wbits; /* log base 2 of requested window size */ 97 | unsigned wsize; /* window size or zero if not using window */ 98 | unsigned whave; /* valid bytes in the window */ 99 | unsigned wnext; /* window write index */ 100 | unsigned char FAR *window; /* allocated sliding window, if needed */ 101 | /* bit accumulator */ 102 | unsigned long hold; /* input bit accumulator */ 103 | unsigned bits; /* number of bits in "in" */ 104 | /* for string and stored block copying */ 105 | unsigned length; /* literal or length of data to copy */ 106 | unsigned offset; /* distance back to copy string from */ 107 | /* for table and code decoding */ 108 | unsigned extra; /* extra bits needed */ 109 | /* fixed and dynamic code tables */ 110 | code const FAR *lencode; /* starting table for length/literal codes */ 111 | code const FAR *distcode; /* starting table for distance codes */ 112 | unsigned lenbits; /* index bits for lencode */ 113 | unsigned distbits; /* index bits for distcode */ 114 | /* dynamic table building */ 115 | unsigned ncode; /* number of code length code lengths */ 116 | unsigned nlen; /* number of length code lengths */ 117 | unsigned ndist; /* number of distance code lengths */ 118 | unsigned have; /* number of code lengths in lens[] */ 119 | code FAR *next; /* next available space in codes[] */ 120 | unsigned short lens[320]; /* temporary storage for code lengths */ 121 | unsigned short work[288]; /* work area for code table building */ 122 | code codes[ENOUGH]; /* space for code tables */ 123 | int sane; /* if false, allow invalid distance too far */ 124 | int back; /* bits back of last unprocessed length/lit */ 125 | unsigned was; /* initial length of match */ 126 | }; 127 | -------------------------------------------------------------------------------- /src/kfun/zlib/1.2.8/zutil.h: -------------------------------------------------------------------------------- 1 | /* zutil.h -- internal interface and configuration of the compression library 2 | * Copyright (C) 1995-2013 Jean-loup Gailly. 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the compression library and is 8 | subject to change. Applications should only use zlib.h. 9 | */ 10 | 11 | /* @(#) $Id$ */ 12 | 13 | #ifndef ZUTIL_H 14 | #define ZUTIL_H 15 | 16 | #ifdef HAVE_HIDDEN 17 | # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) 18 | #else 19 | # define ZLIB_INTERNAL 20 | #endif 21 | 22 | #include "zlib.h" 23 | 24 | #if defined(STDC) && !defined(Z_SOLO) 25 | # if !(defined(_WIN32_WCE) && defined(_MSC_VER)) 26 | # include 27 | # endif 28 | # include 29 | # include 30 | #endif 31 | 32 | #ifdef Z_SOLO 33 | typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ 34 | #endif 35 | 36 | #ifndef local 37 | # define local static 38 | #endif 39 | /* compile with -Dlocal if your debugger can't find static symbols */ 40 | 41 | typedef unsigned char uch; 42 | typedef uch FAR uchf; 43 | typedef unsigned short ush; 44 | typedef ush FAR ushf; 45 | typedef unsigned long ulg; 46 | 47 | extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ 48 | /* (size given to avoid silly warnings with Visual C++) */ 49 | 50 | #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] 51 | 52 | #define ERR_RETURN(strm,err) \ 53 | return (strm->msg = ERR_MSG(err), (err)) 54 | /* To be used only when the state is known to be valid */ 55 | 56 | /* common constants */ 57 | 58 | #ifndef DEF_WBITS 59 | # define DEF_WBITS MAX_WBITS 60 | #endif 61 | /* default windowBits for decompression. MAX_WBITS is for compression only */ 62 | 63 | #if MAX_MEM_LEVEL >= 8 64 | # define DEF_MEM_LEVEL 8 65 | #else 66 | # define DEF_MEM_LEVEL MAX_MEM_LEVEL 67 | #endif 68 | /* default memLevel */ 69 | 70 | #define STORED_BLOCK 0 71 | #define STATIC_TREES 1 72 | #define DYN_TREES 2 73 | /* The three kinds of block type */ 74 | 75 | #define MIN_MATCH 3 76 | #define MAX_MATCH 258 77 | /* The minimum and maximum match lengths */ 78 | 79 | #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ 80 | 81 | /* target dependencies */ 82 | 83 | #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) 84 | # define OS_CODE 0x00 85 | # ifndef Z_SOLO 86 | # if defined(__TURBOC__) || defined(__BORLANDC__) 87 | # if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) 88 | /* Allow compilation with ANSI keywords only enabled */ 89 | void _Cdecl farfree( void *block ); 90 | void *_Cdecl farmalloc( unsigned long nbytes ); 91 | # else 92 | # include 93 | # endif 94 | # else /* MSC or DJGPP */ 95 | # include 96 | # endif 97 | # endif 98 | #endif 99 | 100 | #ifdef AMIGA 101 | # define OS_CODE 0x01 102 | #endif 103 | 104 | #if defined(VAXC) || defined(VMS) 105 | # define OS_CODE 0x02 106 | # define F_OPEN(name, mode) \ 107 | fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") 108 | #endif 109 | 110 | #if defined(ATARI) || defined(atarist) 111 | # define OS_CODE 0x05 112 | #endif 113 | 114 | #ifdef OS2 115 | # define OS_CODE 0x06 116 | # if defined(M_I86) && !defined(Z_SOLO) 117 | # include 118 | # endif 119 | #endif 120 | 121 | #if defined(MACOS) || defined(TARGET_OS_MAC) 122 | # define OS_CODE 0x07 123 | # ifndef Z_SOLO 124 | # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os 125 | # include /* for fdopen */ 126 | # else 127 | # ifndef fdopen 128 | # define fdopen(fd,mode) NULL /* No fdopen() */ 129 | # endif 130 | # endif 131 | # endif 132 | #endif 133 | 134 | #ifdef TOPS20 135 | # define OS_CODE 0x0a 136 | #endif 137 | 138 | #ifdef WIN32 139 | # ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ 140 | # define OS_CODE 0x0b 141 | # endif 142 | #endif 143 | 144 | #ifdef __50SERIES /* Prime/PRIMOS */ 145 | # define OS_CODE 0x0f 146 | #endif 147 | 148 | #if defined(_BEOS_) || defined(RISCOS) 149 | # define fdopen(fd,mode) NULL /* No fdopen() */ 150 | #endif 151 | 152 | #if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX 153 | # if defined(_WIN32_WCE) 154 | # define fdopen(fd,mode) NULL /* No fdopen() */ 155 | # ifndef _PTRDIFF_T_DEFINED 156 | typedef int ptrdiff_t; 157 | # define _PTRDIFF_T_DEFINED 158 | # endif 159 | # else 160 | # define fdopen(fd,type) _fdopen(fd,type) 161 | # endif 162 | #endif 163 | 164 | #if defined(__BORLANDC__) && !defined(MSDOS) 165 | #pragma warn -8004 166 | #pragma warn -8008 167 | #pragma warn -8066 168 | #endif 169 | 170 | /* provide prototypes for these when building zlib without LFS */ 171 | #if !defined(_WIN32) && \ 172 | (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) 173 | ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); 174 | ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); 175 | #endif 176 | 177 | /* common defaults */ 178 | 179 | #ifndef OS_CODE 180 | # define OS_CODE 0x03 /* assume Unix */ 181 | #endif 182 | 183 | #ifndef F_OPEN 184 | # define F_OPEN(name, mode) fopen((name), (mode)) 185 | #endif 186 | 187 | /* functions */ 188 | 189 | #if defined(pyr) || defined(Z_SOLO) 190 | # define NO_MEMCPY 191 | #endif 192 | #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) 193 | /* Use our own functions for small and medium model with MSC <= 5.0. 194 | * You may have to use the same strategy for Borland C (untested). 195 | * The __SC__ check is for Symantec. 196 | */ 197 | # define NO_MEMCPY 198 | #endif 199 | #if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) 200 | # define HAVE_MEMCPY 201 | #endif 202 | #ifdef HAVE_MEMCPY 203 | # ifdef SMALL_MEDIUM /* MSDOS small or medium model */ 204 | # define zmemcpy _fmemcpy 205 | # define zmemcmp _fmemcmp 206 | # define zmemzero(dest, len) _fmemset(dest, 0, len) 207 | # else 208 | # define zmemcpy memcpy 209 | # define zmemcmp memcmp 210 | # define zmemzero(dest, len) memset(dest, 0, len) 211 | # endif 212 | #else 213 | void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); 214 | int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); 215 | void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); 216 | #endif 217 | 218 | /* Diagnostic functions */ 219 | #ifdef DEBUG 220 | # include 221 | extern int ZLIB_INTERNAL z_verbose; 222 | extern void ZLIB_INTERNAL z_error OF((char *m)); 223 | # define Assert(cond,msg) {if(!(cond)) z_error(msg);} 224 | # define Trace(x) {if (z_verbose>=0) fprintf x ;} 225 | # define Tracev(x) {if (z_verbose>0) fprintf x ;} 226 | # define Tracevv(x) {if (z_verbose>1) fprintf x ;} 227 | # define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} 228 | # define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} 229 | #else 230 | # define Assert(cond,msg) 231 | # define Trace(x) 232 | # define Tracev(x) 233 | # define Tracevv(x) 234 | # define Tracec(c,x) 235 | # define Tracecv(c,x) 236 | #endif 237 | 238 | #ifndef Z_SOLO 239 | voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, 240 | unsigned size)); 241 | void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); 242 | #endif 243 | 244 | #define ZALLOC(strm, items, size) \ 245 | (*((strm)->zalloc))((strm)->opaque, (items), (size)) 246 | #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) 247 | #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} 248 | 249 | /* Reverse the bytes in a 32-bit value */ 250 | #define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ 251 | (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) 252 | 253 | #endif /* ZUTIL_H */ 254 | -------------------------------------------------------------------------------- /src/kfun/zlib/1.2.11/zutil.h: -------------------------------------------------------------------------------- 1 | /* zutil.h -- internal interface and configuration of the compression library 2 | * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the compression library and is 8 | subject to change. Applications should only use zlib.h. 9 | */ 10 | 11 | /* @(#) $Id$ */ 12 | 13 | #ifndef ZUTIL_H 14 | #define ZUTIL_H 15 | 16 | #ifdef HAVE_HIDDEN 17 | # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) 18 | #else 19 | # define ZLIB_INTERNAL 20 | #endif 21 | 22 | #include "zlib.h" 23 | 24 | #if defined(STDC) && !defined(Z_SOLO) 25 | # if !(defined(_WIN32_WCE) && defined(_MSC_VER)) 26 | # include 27 | # endif 28 | # include 29 | # include 30 | #endif 31 | 32 | #ifdef Z_SOLO 33 | typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ 34 | #endif 35 | 36 | #ifndef local 37 | # define local static 38 | #endif 39 | /* since "static" is used to mean two completely different things in C, we 40 | define "local" for the non-static meaning of "static", for readability 41 | (compile with -Dlocal if your debugger can't find static symbols) */ 42 | 43 | typedef unsigned char uch; 44 | typedef uch FAR uchf; 45 | typedef unsigned short ush; 46 | typedef ush FAR ushf; 47 | typedef unsigned long ulg; 48 | 49 | extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ 50 | /* (size given to avoid silly warnings with Visual C++) */ 51 | 52 | #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] 53 | 54 | #define ERR_RETURN(strm,err) \ 55 | return (strm->msg = ERR_MSG(err), (err)) 56 | /* To be used only when the state is known to be valid */ 57 | 58 | /* common constants */ 59 | 60 | #ifndef DEF_WBITS 61 | # define DEF_WBITS MAX_WBITS 62 | #endif 63 | /* default windowBits for decompression. MAX_WBITS is for compression only */ 64 | 65 | #if MAX_MEM_LEVEL >= 8 66 | # define DEF_MEM_LEVEL 8 67 | #else 68 | # define DEF_MEM_LEVEL MAX_MEM_LEVEL 69 | #endif 70 | /* default memLevel */ 71 | 72 | #define STORED_BLOCK 0 73 | #define STATIC_TREES 1 74 | #define DYN_TREES 2 75 | /* The three kinds of block type */ 76 | 77 | #define MIN_MATCH 3 78 | #define MAX_MATCH 258 79 | /* The minimum and maximum match lengths */ 80 | 81 | #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ 82 | 83 | /* target dependencies */ 84 | 85 | #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) 86 | # define OS_CODE 0x00 87 | # ifndef Z_SOLO 88 | # if defined(__TURBOC__) || defined(__BORLANDC__) 89 | # if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) 90 | /* Allow compilation with ANSI keywords only enabled */ 91 | void _Cdecl farfree( void *block ); 92 | void *_Cdecl farmalloc( unsigned long nbytes ); 93 | # else 94 | # include 95 | # endif 96 | # else /* MSC or DJGPP */ 97 | # include 98 | # endif 99 | # endif 100 | #endif 101 | 102 | #ifdef AMIGA 103 | # define OS_CODE 1 104 | #endif 105 | 106 | #if defined(VAXC) || defined(VMS) 107 | # define OS_CODE 2 108 | # define F_OPEN(name, mode) \ 109 | fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") 110 | #endif 111 | 112 | #ifdef __370__ 113 | # if __TARGET_LIB__ < 0x20000000 114 | # define OS_CODE 4 115 | # elif __TARGET_LIB__ < 0x40000000 116 | # define OS_CODE 11 117 | # else 118 | # define OS_CODE 8 119 | # endif 120 | #endif 121 | 122 | #if defined(ATARI) || defined(atarist) 123 | # define OS_CODE 5 124 | #endif 125 | 126 | #ifdef OS2 127 | # define OS_CODE 6 128 | # if defined(M_I86) && !defined(Z_SOLO) 129 | # include 130 | # endif 131 | #endif 132 | 133 | #if defined(MACOS) || defined(TARGET_OS_MAC) 134 | # define OS_CODE 7 135 | # ifndef Z_SOLO 136 | # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os 137 | # include /* for fdopen */ 138 | # else 139 | # ifndef fdopen 140 | # define fdopen(fd,mode) NULL /* No fdopen() */ 141 | # endif 142 | # endif 143 | # endif 144 | #endif 145 | 146 | #ifdef __acorn 147 | # define OS_CODE 13 148 | #endif 149 | 150 | #if defined(WIN32) && !defined(__CYGWIN__) 151 | # define OS_CODE 10 152 | #endif 153 | 154 | #ifdef _BEOS_ 155 | # define OS_CODE 16 156 | #endif 157 | 158 | #ifdef __TOS_OS400__ 159 | # define OS_CODE 18 160 | #endif 161 | 162 | #ifdef __APPLE__ 163 | # define OS_CODE 19 164 | #endif 165 | 166 | #if defined(_BEOS_) || defined(RISCOS) 167 | # define fdopen(fd,mode) NULL /* No fdopen() */ 168 | #endif 169 | 170 | #if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX 171 | # if defined(_WIN32_WCE) 172 | # define fdopen(fd,mode) NULL /* No fdopen() */ 173 | # ifndef _PTRDIFF_T_DEFINED 174 | typedef int ptrdiff_t; 175 | # define _PTRDIFF_T_DEFINED 176 | # endif 177 | # else 178 | # define fdopen(fd,type) _fdopen(fd,type) 179 | # endif 180 | #endif 181 | 182 | #if defined(__BORLANDC__) && !defined(MSDOS) 183 | #pragma warn -8004 184 | #pragma warn -8008 185 | #pragma warn -8066 186 | #endif 187 | 188 | /* provide prototypes for these when building zlib without LFS */ 189 | #if !defined(_WIN32) && \ 190 | (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) 191 | ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); 192 | ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); 193 | #endif 194 | 195 | /* common defaults */ 196 | 197 | #ifndef OS_CODE 198 | # define OS_CODE 3 /* assume Unix */ 199 | #endif 200 | 201 | #ifndef F_OPEN 202 | # define F_OPEN(name, mode) fopen((name), (mode)) 203 | #endif 204 | 205 | /* functions */ 206 | 207 | #if defined(pyr) || defined(Z_SOLO) 208 | # define NO_MEMCPY 209 | #endif 210 | #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) 211 | /* Use our own functions for small and medium model with MSC <= 5.0. 212 | * You may have to use the same strategy for Borland C (untested). 213 | * The __SC__ check is for Symantec. 214 | */ 215 | # define NO_MEMCPY 216 | #endif 217 | #if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) 218 | # define HAVE_MEMCPY 219 | #endif 220 | #ifdef HAVE_MEMCPY 221 | # ifdef SMALL_MEDIUM /* MSDOS small or medium model */ 222 | # define zmemcpy _fmemcpy 223 | # define zmemcmp _fmemcmp 224 | # define zmemzero(dest, len) _fmemset(dest, 0, len) 225 | # else 226 | # define zmemcpy memcpy 227 | # define zmemcmp memcmp 228 | # define zmemzero(dest, len) memset(dest, 0, len) 229 | # endif 230 | #else 231 | void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); 232 | int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); 233 | void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); 234 | #endif 235 | 236 | /* Diagnostic functions */ 237 | #ifdef ZLIB_DEBUG 238 | # include 239 | extern int ZLIB_INTERNAL z_verbose; 240 | extern void ZLIB_INTERNAL z_error OF((char *m)); 241 | # define Assert(cond,msg) {if(!(cond)) z_error(msg);} 242 | # define Trace(x) {if (z_verbose>=0) fprintf x ;} 243 | # define Tracev(x) {if (z_verbose>0) fprintf x ;} 244 | # define Tracevv(x) {if (z_verbose>1) fprintf x ;} 245 | # define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} 246 | # define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} 247 | #else 248 | # define Assert(cond,msg) 249 | # define Trace(x) 250 | # define Tracev(x) 251 | # define Tracevv(x) 252 | # define Tracec(c,x) 253 | # define Tracecv(c,x) 254 | #endif 255 | 256 | #ifndef Z_SOLO 257 | voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, 258 | unsigned size)); 259 | void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); 260 | #endif 261 | 262 | #define ZALLOC(strm, items, size) \ 263 | (*((strm)->zalloc))((strm)->opaque, (items), (size)) 264 | #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) 265 | #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} 266 | 267 | /* Reverse the bytes in a 32-bit value */ 268 | #define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ 269 | (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) 270 | 271 | #endif /* ZUTIL_H */ 272 | -------------------------------------------------------------------------------- /project/jit/jit.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {3F740FAA-4EC8-4C77-8A0B-C0B47466684C} 23 | Win32Proj 24 | jit 25 | 26 | 27 | 28 | DynamicLibrary 29 | true 30 | NotSet 31 | 32 | 33 | DynamicLibrary 34 | true 35 | NotSet 36 | 37 | 38 | DynamicLibrary 39 | false 40 | true 41 | NotSet 42 | 43 | 44 | DynamicLibrary 45 | false 46 | true 47 | NotSet 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | true 67 | 68 | 69 | true 70 | 71 | 72 | false 73 | 74 | 75 | false 76 | 77 | 78 | 79 | 80 | 81 | Level3 82 | Disabled 83 | WIN32;_DEBUG;_WINDOWS;_USRDLL;JIT_EXPORTS;%(PreprocessorDefinitions) 84 | ..\..\src 85 | 86 | 87 | Windows 88 | true 89 | ..\..\Debug\lpc-ext.lib;%(AdditionalDependencies) 90 | 91 | 92 | 93 | 94 | 95 | 96 | Level3 97 | Disabled 98 | WIN32;_DEBUG;_WINDOWS;_USRDLL;JIT_EXPORTS;%(PreprocessorDefinitions) 99 | ..\..\src 100 | 101 | 102 | Windows 103 | true 104 | ..\..\x64\Debug\lpc-ext.lib;%(AdditionalDependencies) 105 | 106 | 107 | 108 | 109 | Level3 110 | 111 | 112 | MaxSpeed 113 | true 114 | true 115 | WIN32;NDEBUG;_WINDOWS;_USRDLL;JIT_EXPORTS;%(PreprocessorDefinitions) 116 | ..\..\src 117 | 118 | 119 | Windows 120 | true 121 | true 122 | true 123 | ..\..\Release\lpc-ext.lib;%(AdditionalDependencies) 124 | 125 | 126 | 127 | 128 | Level3 129 | 130 | 131 | MaxSpeed 132 | true 133 | true 134 | WIN32;NDEBUG;_WINDOWS;_USRDLL;JIT_EXPORTS;%(PreprocessorDefinitions) 135 | ..\..\src 136 | 137 | 138 | Windows 139 | true 140 | true 141 | true 142 | ..\..\x64\Release\lpc-ext.lib;%(AdditionalDependencies) 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /project/lower_case/lower_case.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {7FDD6043-348D-451B-9E95-14FDD0A829EE} 23 | Win32Proj 24 | lower_case 25 | 26 | 27 | 28 | DynamicLibrary 29 | true 30 | NotSet 31 | 32 | 33 | DynamicLibrary 34 | true 35 | NotSet 36 | 37 | 38 | DynamicLibrary 39 | false 40 | true 41 | NotSet 42 | 43 | 44 | DynamicLibrary 45 | false 46 | true 47 | NotSet 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | true 67 | 68 | 69 | true 70 | 71 | 72 | false 73 | 74 | 75 | false 76 | 77 | 78 | 79 | 80 | 81 | Level3 82 | Disabled 83 | WIN32;_DEBUG;_WINDOWS;_USRDLL;LOWER_CASE_EXPORTS;%(PreprocessorDefinitions) 84 | ..\..\src 85 | 86 | 87 | Windows 88 | true 89 | ..\..\Debug\lpc-ext.lib;%(AdditionalDependencies) 90 | 91 | 92 | 93 | 94 | 95 | 96 | Level3 97 | Disabled 98 | WIN32;_DEBUG;_WINDOWS;_USRDLL;LOWER_CASE_EXPORTS;%(PreprocessorDefinitions) 99 | ..\..\src 100 | 101 | 102 | Windows 103 | true 104 | ..\..\x64\Debug\lpc-ext.lib;%(AdditionalDependencies) 105 | 106 | 107 | 108 | 109 | Level3 110 | 111 | 112 | MaxSpeed 113 | true 114 | true 115 | WIN32;NDEBUG;_WINDOWS;_USRDLL;LOWER_CASE_EXPORTS;%(PreprocessorDefinitions) 116 | ..\..\src 117 | 118 | 119 | Windows 120 | true 121 | true 122 | true 123 | ..\..\Release\lpc-ext.lib;%(AdditionalDependencies) 124 | 125 | 126 | 127 | 128 | Level3 129 | 130 | 131 | MaxSpeed 132 | true 133 | true 134 | WIN32;NDEBUG;_WINDOWS;_USRDLL;LOWER_CASE_EXPORTS;%(PreprocessorDefinitions) 135 | ..\..\src 136 | 137 | 138 | Windows 139 | true 140 | true 141 | true 142 | ..\..\x64\Release\lpc-ext.lib;%(AdditionalDependencies) 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /src/kfun/zlib/1.2.12/zutil.h: -------------------------------------------------------------------------------- 1 | /* zutil.h -- internal interface and configuration of the compression library 2 | * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler 3 | * For conditions of distribution and use, see copyright notice in zlib.h 4 | */ 5 | 6 | /* WARNING: this file should *not* be used by applications. It is 7 | part of the implementation of the compression library and is 8 | subject to change. Applications should only use zlib.h. 9 | */ 10 | 11 | /* @(#) $Id$ */ 12 | 13 | #ifndef ZUTIL_H 14 | #define ZUTIL_H 15 | 16 | #ifdef HAVE_HIDDEN 17 | # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) 18 | #else 19 | # define ZLIB_INTERNAL 20 | #endif 21 | 22 | #include "zlib.h" 23 | 24 | #if defined(STDC) && !defined(Z_SOLO) 25 | # if !(defined(_WIN32_WCE) && defined(_MSC_VER)) 26 | # include 27 | # endif 28 | # include 29 | # include 30 | #endif 31 | 32 | #ifndef local 33 | # define local static 34 | #endif 35 | /* since "static" is used to mean two completely different things in C, we 36 | define "local" for the non-static meaning of "static", for readability 37 | (compile with -Dlocal if your debugger can't find static symbols) */ 38 | 39 | typedef unsigned char uch; 40 | typedef uch FAR uchf; 41 | typedef unsigned short ush; 42 | typedef ush FAR ushf; 43 | typedef unsigned long ulg; 44 | 45 | #if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC) 46 | # include 47 | # if (ULONG_MAX == 0xffffffffffffffff) 48 | # define Z_U8 unsigned long 49 | # elif (ULLONG_MAX == 0xffffffffffffffff) 50 | # define Z_U8 unsigned long long 51 | # elif (UINT_MAX == 0xffffffffffffffff) 52 | # define Z_U8 unsigned 53 | # endif 54 | #endif 55 | 56 | extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ 57 | /* (size given to avoid silly warnings with Visual C++) */ 58 | 59 | #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] 60 | 61 | #define ERR_RETURN(strm,err) \ 62 | return (strm->msg = ERR_MSG(err), (err)) 63 | /* To be used only when the state is known to be valid */ 64 | 65 | /* common constants */ 66 | 67 | #ifndef DEF_WBITS 68 | # define DEF_WBITS MAX_WBITS 69 | #endif 70 | /* default windowBits for decompression. MAX_WBITS is for compression only */ 71 | 72 | #if MAX_MEM_LEVEL >= 8 73 | # define DEF_MEM_LEVEL 8 74 | #else 75 | # define DEF_MEM_LEVEL MAX_MEM_LEVEL 76 | #endif 77 | /* default memLevel */ 78 | 79 | #define STORED_BLOCK 0 80 | #define STATIC_TREES 1 81 | #define DYN_TREES 2 82 | /* The three kinds of block type */ 83 | 84 | #define MIN_MATCH 3 85 | #define MAX_MATCH 258 86 | /* The minimum and maximum match lengths */ 87 | 88 | #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ 89 | 90 | /* target dependencies */ 91 | 92 | #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) 93 | # define OS_CODE 0x00 94 | # ifndef Z_SOLO 95 | # if defined(__TURBOC__) || defined(__BORLANDC__) 96 | # if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) 97 | /* Allow compilation with ANSI keywords only enabled */ 98 | void _Cdecl farfree( void *block ); 99 | void *_Cdecl farmalloc( unsigned long nbytes ); 100 | # else 101 | # include 102 | # endif 103 | # else /* MSC or DJGPP */ 104 | # include 105 | # endif 106 | # endif 107 | #endif 108 | 109 | #ifdef AMIGA 110 | # define OS_CODE 1 111 | #endif 112 | 113 | #if defined(VAXC) || defined(VMS) 114 | # define OS_CODE 2 115 | # define F_OPEN(name, mode) \ 116 | fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") 117 | #endif 118 | 119 | #ifdef __370__ 120 | # if __TARGET_LIB__ < 0x20000000 121 | # define OS_CODE 4 122 | # elif __TARGET_LIB__ < 0x40000000 123 | # define OS_CODE 11 124 | # else 125 | # define OS_CODE 8 126 | # endif 127 | #endif 128 | 129 | #if defined(ATARI) || defined(atarist) 130 | # define OS_CODE 5 131 | #endif 132 | 133 | #ifdef OS2 134 | # define OS_CODE 6 135 | # if defined(M_I86) && !defined(Z_SOLO) 136 | # include 137 | # endif 138 | #endif 139 | 140 | #if defined(MACOS) || defined(TARGET_OS_MAC) 141 | # define OS_CODE 7 142 | # ifndef Z_SOLO 143 | # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os 144 | # include /* for fdopen */ 145 | # else 146 | # ifndef fdopen 147 | # define fdopen(fd,mode) NULL /* No fdopen() */ 148 | # endif 149 | # endif 150 | # endif 151 | #endif 152 | 153 | #ifdef __acorn 154 | # define OS_CODE 13 155 | #endif 156 | 157 | #if defined(WIN32) && !defined(__CYGWIN__) 158 | # define OS_CODE 10 159 | #endif 160 | 161 | #ifdef _BEOS_ 162 | # define OS_CODE 16 163 | #endif 164 | 165 | #ifdef __TOS_OS400__ 166 | # define OS_CODE 18 167 | #endif 168 | 169 | #ifdef __APPLE__ 170 | # define OS_CODE 19 171 | #endif 172 | 173 | #if defined(_BEOS_) || defined(RISCOS) 174 | # define fdopen(fd,mode) NULL /* No fdopen() */ 175 | #endif 176 | 177 | #if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX 178 | # if defined(_WIN32_WCE) 179 | # define fdopen(fd,mode) NULL /* No fdopen() */ 180 | # else 181 | # define fdopen(fd,type) _fdopen(fd,type) 182 | # endif 183 | #endif 184 | 185 | #if defined(__BORLANDC__) && !defined(MSDOS) 186 | #pragma warn -8004 187 | #pragma warn -8008 188 | #pragma warn -8066 189 | #endif 190 | 191 | /* provide prototypes for these when building zlib without LFS */ 192 | #if !defined(_WIN32) && \ 193 | (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) 194 | ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); 195 | ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); 196 | #endif 197 | 198 | /* common defaults */ 199 | 200 | #ifndef OS_CODE 201 | # define OS_CODE 3 /* assume Unix */ 202 | #endif 203 | 204 | #ifndef F_OPEN 205 | # define F_OPEN(name, mode) fopen((name), (mode)) 206 | #endif 207 | 208 | /* functions */ 209 | 210 | #if defined(pyr) || defined(Z_SOLO) 211 | # define NO_MEMCPY 212 | #endif 213 | #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) 214 | /* Use our own functions for small and medium model with MSC <= 5.0. 215 | * You may have to use the same strategy for Borland C (untested). 216 | * The __SC__ check is for Symantec. 217 | */ 218 | # define NO_MEMCPY 219 | #endif 220 | #if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) 221 | # define HAVE_MEMCPY 222 | #endif 223 | #ifdef HAVE_MEMCPY 224 | # ifdef SMALL_MEDIUM /* MSDOS small or medium model */ 225 | # define zmemcpy _fmemcpy 226 | # define zmemcmp _fmemcmp 227 | # define zmemzero(dest, len) _fmemset(dest, 0, len) 228 | # else 229 | # define zmemcpy memcpy 230 | # define zmemcmp memcmp 231 | # define zmemzero(dest, len) memset(dest, 0, len) 232 | # endif 233 | #else 234 | void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); 235 | int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); 236 | void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); 237 | #endif 238 | 239 | /* Diagnostic functions */ 240 | #ifdef ZLIB_DEBUG 241 | # include 242 | extern int ZLIB_INTERNAL z_verbose; 243 | extern void ZLIB_INTERNAL z_error OF((char *m)); 244 | # define Assert(cond,msg) {if(!(cond)) z_error(msg);} 245 | # define Trace(x) {if (z_verbose>=0) fprintf x ;} 246 | # define Tracev(x) {if (z_verbose>0) fprintf x ;} 247 | # define Tracevv(x) {if (z_verbose>1) fprintf x ;} 248 | # define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} 249 | # define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} 250 | #else 251 | # define Assert(cond,msg) 252 | # define Trace(x) 253 | # define Tracev(x) 254 | # define Tracevv(x) 255 | # define Tracec(c,x) 256 | # define Tracecv(c,x) 257 | #endif 258 | 259 | #ifndef Z_SOLO 260 | voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, 261 | unsigned size)); 262 | void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); 263 | #endif 264 | 265 | #define ZALLOC(strm, items, size) \ 266 | (*((strm)->zalloc))((strm)->opaque, (items), (size)) 267 | #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) 268 | #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} 269 | 270 | /* Reverse the bytes in a 32-bit value */ 271 | #define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ 272 | (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) 273 | 274 | #endif /* ZUTIL_H */ 275 | -------------------------------------------------------------------------------- /project/regexp/regexp.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {670ABFEA-96E8-4D68-BA2A-9445A48358D7} 23 | Win32Proj 24 | regexp 25 | 26 | 27 | 28 | DynamicLibrary 29 | true 30 | NotSet 31 | 32 | 33 | DynamicLibrary 34 | true 35 | NotSet 36 | 37 | 38 | DynamicLibrary 39 | false 40 | true 41 | NotSet 42 | 43 | 44 | DynamicLibrary 45 | false 46 | true 47 | NotSet 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | true 67 | 68 | 69 | true 70 | 71 | 72 | false 73 | 74 | 75 | false 76 | 77 | 78 | 79 | 80 | 81 | Level3 82 | Disabled 83 | WIN32;REGEX_MALLOC;HAVE_LIMITS_H=1;HAVE_STRING_H=1;HAVE_UINTPTR_T=1;STDC_HEADERS=1;_DEBUG;_WINDOWS;_USRDLL;REGEXP_EXPORTS;%(PreprocessorDefinitions) 84 | ..\..\src;..\..\src\kfun\rgx\libiberty 85 | 86 | 87 | Windows 88 | true 89 | ..\..\Debug\lpc-ext.lib;%(AdditionalDependencies) 90 | 91 | 92 | 93 | 94 | 95 | 96 | Level3 97 | Disabled 98 | WIN32;REGEX_MALLOC;HAVE_LIMITS_H=1;HAVE_STRING_H=1;HAVE_UINTPTR_T=1;STDC_HEADERS=1;_DEBUG;_WINDOWS;_USRDLL;REGEXP_EXPORTS;%(PreprocessorDefinitions) 99 | ..\..\src;..\..\src\kfun\rgx\libiberty 100 | 101 | 102 | Windows 103 | true 104 | ..\..\x64\Debug\lpc-ext.lib;%(AdditionalDependencies) 105 | 106 | 107 | 108 | 109 | Level3 110 | 111 | 112 | MaxSpeed 113 | true 114 | true 115 | WIN32;REGEX_MALLOC;HAVE_LIMITS_H=1;HAVE_STRING_H=1;HAVE_UINTPTR_T=1;STDC_HEADERS=1;NDEBUG;_WINDOWS;_USRDLL;REGEXP_EXPORTS;%(PreprocessorDefinitions) 116 | ..\..\src;..\..\src\kfun\rgx\libiberty 117 | 118 | 119 | Windows 120 | true 121 | true 122 | true 123 | ..\..\Release\lpc-ext.lib;%(AdditionalDependencies) 124 | 125 | 126 | 127 | 128 | Level3 129 | 130 | 131 | MaxSpeed 132 | true 133 | true 134 | WIN32;REGEX_MALLOC;HAVE_LIMITS_H=1;HAVE_STRING_H=1;HAVE_UINTPTR_T=1;STDC_HEADERS=1;NDEBUG;_WINDOWS;_USRDLL;REGEXP_EXPORTS;%(PreprocessorDefinitions) 135 | ..\..\src;..\..\src\kfun\rgx\libiberty 136 | 137 | 138 | Windows 139 | true 140 | true 141 | true 142 | ..\..\x64\Release\lpc-ext.lib;%(AdditionalDependencies) 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /project/jitcomp/jitcomp.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 16.0 43 | {F66B4AF3-C067-4CC0-95AC-879AF05318DB} 44 | Win32Proj 45 | jitcomp 46 | 10.0 47 | 48 | 49 | 50 | Application 51 | true 52 | v142 53 | Unicode 54 | 55 | 56 | Application 57 | false 58 | v142 59 | true 60 | Unicode 61 | 62 | 63 | Application 64 | true 65 | v142 66 | Unicode 67 | 68 | 69 | Application 70 | false 71 | v142 72 | true 73 | Unicode 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | true 95 | ..\..\src;$(IncludePath) 96 | 97 | 98 | true 99 | ..\..\src;$(IncludePath) 100 | 101 | 102 | false 103 | ..\..\src;$(IncludePath) 104 | 105 | 106 | false 107 | ..\..\src;$(IncludePath) 108 | 109 | 110 | 111 | 112 | 113 | Level3 114 | true 115 | WIN32;GENCLANG;_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 116 | true 117 | 118 | 119 | Console 120 | true 121 | 122 | 123 | 124 | 125 | 126 | 127 | Level3 128 | true 129 | WIN32;GENCLANG;_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 130 | true 131 | 132 | 133 | Console 134 | true 135 | 136 | 137 | 138 | 139 | 140 | 141 | Level3 142 | true 143 | true 144 | true 145 | WIN32;GENCLANG;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 146 | true 147 | 148 | 149 | Console 150 | true 151 | true 152 | true 153 | 154 | 155 | 156 | 157 | 158 | 159 | Level3 160 | true 161 | true 162 | true 163 | WIN32;GENCLANG;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 164 | true 165 | 166 | 167 | Console 168 | true 169 | true 170 | true 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /src/lpc_ext.c: -------------------------------------------------------------------------------- 1 | # ifdef WIN32 2 | # include 3 | # define DLLEXPORT __declspec(dllexport) 4 | # else 5 | # define DLLEXPORT /* nothing */ 6 | # endif 7 | 8 | # define LPCEXT /* declare */ 9 | # include "lpc_ext.h" 10 | # include 11 | # ifndef WIN32 12 | # include 13 | # include 14 | # include 15 | # include 16 | # else 17 | # include 18 | # endif 19 | 20 | 21 | /* 22 | * NAME: ext->cb() 23 | * DESCRIPTION: set up callbacks 24 | */ 25 | static int ext_cb(void *ftab[], int size, int n, ...) 26 | { 27 | va_list args; 28 | void **func; 29 | 30 | if (size < n) { 31 | return 0; 32 | } 33 | 34 | va_start(args, n); 35 | while (n > 0) { 36 | func = va_arg(args, void**); 37 | *func = *ftab++; 38 | --n; 39 | } 40 | va_end(args); 41 | 42 | return 1; 43 | } 44 | 45 | static void (*ext_spawn)(void (*)(int*, int), void (*)(int)); 46 | static void (*ext_fdclose)(int*, int); 47 | static void (*ext_cleanup)(void); 48 | 49 | # ifndef WIN32 50 | # define INVALID_HANDLE_VALUE -1 51 | static int in, out, back, pid; 52 | # else 53 | static HANDLE in, out, back; 54 | 55 | /* 56 | * NAME: read() 57 | * DESCRIPTION: Windows compatibility wrapper 58 | */ 59 | static int read(HANDLE h, void *buffer, int len) 60 | { 61 | int size; 62 | 63 | if (!ReadFile(h, buffer, len, &size, NULL)) { 64 | return -1; 65 | } 66 | return size; 67 | } 68 | 69 | /* 70 | * NAME: write() 71 | * DESCRIPTION: Windows compatibility wrapper 72 | */ 73 | static int write(HANDLE h, const void *buffer, int len) 74 | { 75 | int size; 76 | 77 | if (!WriteFile(h, buffer, len, &size, NULL)) { 78 | return -1; 79 | } 80 | return size; 81 | } 82 | 83 | /* 84 | * NAME: close() 85 | * DESCRIPTION: Windows compatibility wrapper 86 | */ 87 | static void close(HANDLE h) 88 | { 89 | CloseHandle(h); 90 | } 91 | # endif 92 | 93 | /* 94 | * NAME: ext->init() 95 | * DESCRIPTION: initialize extension handling 96 | */ 97 | DLLEXPORT int ext_init(int major, int minor, void **ftabs[], int sizes[], 98 | const char *config) 99 | { 100 | in = out = back = INVALID_HANDLE_VALUE; 101 | 102 | return (major == LPC_EXT_VERSION_MAJOR && minor >= LPC_EXT_VERSION_MINOR && 103 | ext_cb(ftabs[0], sizes[0], 6, 104 | &lpc_ext_kfun, 105 | &lpc_ext_dbase, 106 | &ext_spawn, 107 | &ext_fdclose, 108 | &lpc_ext_jit, 109 | &ext_cleanup) && 110 | ext_cb(ftabs[1], sizes[1], 4, 111 | &lpc_frame_object, 112 | &lpc_frame_dataspace, 113 | &lpc_frame_arg, 114 | &lpc_frame_atomic) && 115 | ext_cb(ftabs[2], sizes[2], 2, 116 | &lpc_data_get_val, 117 | &lpc_data_set_val) && 118 | ext_cb(ftabs[3], sizes[3], 4, 119 | &lpc_value_type, 120 | &lpc_value_nil, 121 | &lpc_value_temp, 122 | &lpc_value_temp2) && 123 | ext_cb(ftabs[4], sizes[4], 2, 124 | &lpc_int_getval, 125 | &lpc_int_putval) && 126 | # ifndef NOFLOAT 127 | ext_cb(ftabs[5], sizes[5], 2, 128 | &lpc_float_getval, 129 | &lpc_float_putval) && 130 | # endif 131 | ext_cb(ftabs[6], sizes[6], 5, 132 | &lpc_string_getval, 133 | &lpc_string_putval, 134 | &lpc_string_new, 135 | &lpc_string_text, 136 | &lpc_string_length) && 137 | ext_cb(ftabs[7], sizes[7], 6, 138 | &lpc_object_putval, 139 | &lpc_object_name, 140 | &lpc_object_isspecial, 141 | &lpc_object_ismarked, 142 | &lpc_object_mark, 143 | &lpc_object_unmark) && 144 | ext_cb(ftabs[8], sizes[8], 6, 145 | &lpc_array_getval, 146 | &lpc_array_putval, 147 | &lpc_array_new, 148 | &lpc_array_index, 149 | &lpc_array_assign, 150 | &lpc_array_size) && 151 | ext_cb(ftabs[9], sizes[9], 7, 152 | &lpc_mapping_getval, 153 | &lpc_mapping_putval, 154 | &lpc_mapping_new, 155 | &lpc_mapping_index, 156 | &lpc_mapping_assign, 157 | &lpc_mapping_enum, 158 | &lpc_mapping_size) && 159 | ext_cb(ftabs[10], sizes[10], 6, 160 | &lpc_runtime_error, 161 | &lpc_md5_start, 162 | &lpc_md5_block, 163 | &lpc_md5_end, 164 | &lpc_runtime_ticks, 165 | &lpc_runtime_check) && 166 | lpc_ext_init(major, minor, config)); 167 | } 168 | 169 | 170 | # define FD_CHUNK 500 /* # file descriptors to close in one batch */ 171 | 172 | /* 173 | * NAME: ext->fdlist() 174 | * DESCRIPTION: pass file descriptors to child process 175 | */ 176 | static void ext_fdlist(int *fdlist, int size) 177 | { 178 | int num; 179 | 180 | while (size != 0) { 181 | num = (size > FD_CHUNK) ? FD_CHUNK : size; 182 | (void) write(out, &num, sizeof(num)); 183 | (void) write(out, fdlist, num * sizeof(int)); 184 | fdlist += num; 185 | size -= num; 186 | } 187 | 188 | num = 0; 189 | (void) write(out, &num, sizeof(num)); 190 | } 191 | 192 | /* 193 | * NAME: ext->finish() 194 | * DESCRIPTION: clean up before exiting 195 | */ 196 | static void ext_finish(int wait) 197 | { 198 | close(in); 199 | close(out); 200 | close(back); 201 | # ifndef WIN32 202 | if (wait) { 203 | waitpid(pid, &out, 0); 204 | } 205 | # endif 206 | } 207 | 208 | /* 209 | * NAME: lpc_ext->spawn() 210 | * DESCRIPTION: Spawn a child process and execute the given program. This 211 | * is intended to be used by modules that offload some of their 212 | * functionality in an external program, rather than as a way 213 | * for LPC code to execute and communicate with such a program. 214 | * The JIT compiler module uses this to run the LPC VM decompiler 215 | * in isolation. 216 | */ 217 | int lpc_ext_spawn(const char *program) 218 | { 219 | # ifndef WIN32 220 | int input[2], output[2]; 221 | 222 | if (pipe(input) != 0) { 223 | return 0; 224 | } 225 | if (pipe(output) != 0) { 226 | close(input[0]); 227 | close(input[1]); 228 | return 0; 229 | } 230 | pid = fork(); 231 | if (pid > 0) { 232 | in = input[0]; 233 | out = output[1]; 234 | back = input[1]; 235 | fcntl(in, F_SETFD, FD_CLOEXEC); 236 | fcntl(out, F_SETFD, FD_CLOEXEC); 237 | fcntl(back, F_SETFD, FD_CLOEXEC); 238 | close(output[0]); 239 | 240 | (*ext_spawn)(&ext_fdlist, &ext_finish); 241 | return 1; 242 | } else if (pid == 0) { 243 | int fds[FD_CHUNK], num; 244 | 245 | dup2(output[0], 0); 246 | dup2(input[1], 1); 247 | close(input[0]); 248 | close(input[1]); 249 | close(output[0]); 250 | close(output[1]); 251 | 252 | (*ext_cleanup)(); 253 | 254 | /* 255 | * receive file descriptors to close, until there are none left 256 | */ 257 | for (;;) { 258 | if (read(0, &num, sizeof(num)) != sizeof(num)) { 259 | break; 260 | } 261 | if (num == 0) { 262 | /* execute the program */ 263 | execl("/bin/sh", "sh", "-c", program, (char *) NULL); 264 | break; 265 | } 266 | if (read(0, fds, num * sizeof(int)) != num * sizeof(int)) { 267 | break; 268 | } 269 | (*ext_fdclose)(fds, num); 270 | } 271 | 272 | /* exec failed */ 273 | _exit(0); 274 | } else { 275 | close(input[0]); 276 | close(input[1]); 277 | close(output[0]); 278 | close(output[1]); 279 | } 280 | 281 | return 0; /* failure of some sort */ 282 | # else 283 | SECURITY_ATTRIBUTES sattr; 284 | HANDLE output; 285 | STARTUPINFO sinfo; 286 | PROCESS_INFORMATION pinfo; 287 | 288 | /* create pipes */ 289 | sattr.nLength = sizeof(SECURITY_ATTRIBUTES); 290 | sattr.bInheritHandle = TRUE; 291 | sattr.lpSecurityDescriptor = NULL; 292 | if (!CreatePipe(&in, &back, &sattr, 0)) { 293 | return 0; 294 | } 295 | if (!SetHandleInformation(in, HANDLE_FLAG_INHERIT, 0) || 296 | !CreatePipe(&output, &out, &sattr, 0)) { 297 | CloseHandle(in); 298 | CloseHandle(back); 299 | return 0; 300 | } 301 | if (!SetHandleInformation(out, HANDLE_FLAG_INHERIT, 0)) { 302 | CloseHandle(in); 303 | CloseHandle(back); 304 | CloseHandle(output); 305 | CloseHandle(out); 306 | return 0; 307 | } 308 | 309 | /* spawn process */ 310 | ZeroMemory(&sinfo, sizeof(STARTUPINFO)); 311 | sinfo.cb = sizeof(STARTUPINFO); 312 | sinfo.hStdInput = output; 313 | sinfo.hStdOutput = back; 314 | sinfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); 315 | sinfo.dwFlags |= STARTF_USESTDHANDLES; 316 | ZeroMemory(&pinfo, sizeof(PROCESS_INFORMATION)); 317 | if (!CreateProcess(NULL, (LPTSTR) program, NULL, NULL, TRUE, 0, NULL, NULL, 318 | &sinfo, &pinfo)) { 319 | CloseHandle(in); 320 | CloseHandle(back); 321 | CloseHandle(output); 322 | CloseHandle(out); 323 | return 0; 324 | } 325 | 326 | CloseHandle(pinfo.hProcess); 327 | CloseHandle(pinfo.hThread); 328 | CloseHandle(output); 329 | return 1; 330 | # endif 331 | } 332 | 333 | /* 334 | * NAME: lpc_ext->read() 335 | * DESCRIPTION: Read input from the child process. Not intended for use by 336 | * LPC kfuns. 337 | */ 338 | int lpc_ext_read(void *buffer, int len) 339 | { 340 | return read(in, buffer, len); 341 | } 342 | 343 | /* 344 | * NAME: lpc_ext->write() 345 | * DESCRIPTION: Write output to the child process. Not intended for use by 346 | * LPC kfuns. 347 | */ 348 | int lpc_ext_write(const void *buffer, int len) 349 | { 350 | return write(out, buffer, len); 351 | } 352 | 353 | /* 354 | * NAME: lpc_ext->writeback() 355 | * DESCRIPTION: Write back to oneself. Not intended for use by LPC kfuns. 356 | */ 357 | int lpc_ext_writeback(const void *buffer, int len) 358 | { 359 | return write(back, buffer, len); 360 | } 361 | -------------------------------------------------------------------------------- /doc/extensions.md: -------------------------------------------------------------------------------- 1 | # LPC extension interface 2 | 3 | ## 1. Introduction 4 | 5 | DGD presents an interface for extending the driver with new kfuns and special 6 | object types. Extension modules can be specified in the config file using 7 | the modules parameter: 8 | ``` 9 | modules = ([ "/path/to/extension/module" : "module configuration" ]); 10 | ``` 11 | The extension module will be loaded into DGD at runtime, and the function 12 | `int lpc_ext_init(int major, int minor, char *config)` will be called to 13 | initialize it; this function must return a non-zero value to indicate that 14 | initialization was successful. 15 | 16 | 17 | ## 2. Kernel functions 18 | 19 | Kernel functions may be added during the initialization phase by calling the 20 | following function: 21 | ``` 22 | void lpc_ext_kfun(LPC_ext_kfun *kf, int n); 23 | ``` 24 | where `kf` is an array of `LPC_ext_kfun` structs, and `n` the number of 25 | elements in that array. `lpc_ext_kfun()` must not redeclare any existing kfuns. 26 | 27 | The `LPC_ext_kfun` struct has the following fields: 28 | ``` 29 | char *name; /* kfun name */ 30 | char *proto; /* kfun prototype */ 31 | func; /* kfun function pointer */ 32 | ``` 33 | Here `func` is a pointer to a C function with the following prototype: 34 | ``` 35 | void func(LPC_frame f, int nargs, LPC_value retval); 36 | ``` 37 | Calls to the kfun with name `name` will be routed to that C function. The 38 | argument `f` contains the function context, `nargs` is the number of 39 | arguments on the stack, and `retval` is a pointer to the return value. The 40 | function should not attempt to push or pop arguments; instead, arguments should 41 | be accessed using the relevant `lpc_frame_*()` functions listed below, and the 42 | return value, if any, should be stored in the `retval` value using one of the 43 | `lpc_*_putval()` functions. The default return value is `nil`. 44 | 45 | Functions with lvalue parameters should put the values to be assigned in an 46 | array, which is stored in the scratch value returned by `lpc_value_temp()`. 47 | 48 | Kfuns can call `lpc_runtime_error()` to indicate that an error occurred. Errors 49 | will interrupt the flow of execution, so `lpc_runtime_error()` is best called 50 | before any LPC values are constructed or changed, including the return value of 51 | the kfun. 52 | 53 | Note that at present, the extension interface does not define a way to call an 54 | LPC function from a kfun. 55 | ``` 56 | LPC_object lpc_frame_object(LPC_frame f); /* current object */ 57 | LPC_dataspace lpc_frame_dataspace(LPC_frame f); /* current dataspace */ 58 | LPC_value lpc_frame_arg(LPC_frame f, int nargs, int n); /* argument n */ 59 | int lpc_frame_atomic(LPC_frame f); /* atomic? */ 60 | 61 | void lpc_runtime_error(LPC_frame f, char *error); 62 | ``` 63 | The `proto` field of the `LPC_ext_kfun` struct is a prototype for the function, 64 | represented as a 0-terminated array of chars. For example, the LPC prototypes 65 | ``` 66 | string lower_case(string str); 67 | string concat(string str...); 68 | int foo(int *a, varargs object **b); 69 | void bar(void); 70 | void gnu(); 71 | int sscanf(string str, string format, mixed...); /* lvalue arguments */ 72 | ``` 73 | would be represented as 74 | ``` 75 | char lower_case_proto[] = { LPC_TYPE_STRING, LPC_TYPE_STRING, 0 }; 76 | char concat_proto[] = { LPC_TYPE_STRING, LPC_TYPE_STRING, 77 | LPC_TYPE_ELLIPSIS, 0 }; 78 | char foo_proto[] = { LPC_TYPE_INT, LPC_TYPE_ARRAY_OF(LPC_TYPE_INT), 79 | LPC_TYPE_VARARGS, 80 | LPC_TYPE_ARRAY_OF(LPC_TYPE_ARRAY_OF(LPC_TYPE_OBJECT)), 81 | 0 }; 82 | char bar_proto[] = { LPC_TYPE_VOID, LPC_TYPE_VOID, 0 }; 83 | char gnu_proto[] = { LPC_TYPE_VOID, 0 }; 84 | char sscanf_proto[] = { LPC_TYPE_INT, LPC_TYPE_STRING, LPC_TYPE_STRING, 85 | LPC_TYPE_LVALUE, LPC_TYPE_ELLIPSIS, 0 }; 86 | ``` 87 | Note that the prototypes of `bar()` and `gnu()` are effectively identical, just 88 | as they would be for LPC functions; also note that `varargs` must be specified 89 | among the arguments of the prototype rather than in front of the return type. 90 | 91 | The building blocks for prototypes are: 92 | ``` 93 | LPC_TYPE_VOID 94 | LPC_TYPE_INT 95 | LPC_TYPE_FLOAT 96 | LPC_TYPE_STRING 97 | LPC_TYPE_OBJECT 98 | LPC_TYPE_ARRAY_OF(lpc_type) 99 | LPC_TYPE_MAPPING 100 | LPC_TYPE_MIXED 101 | LPC_TYPE_LVALUE 102 | LPC_TYPE_VARARGS 103 | LPC_TYPE_ELLIPSIS 104 | ``` 105 | 106 | ## 3. Special objects 107 | 108 | DGD defines various types of special objects: user objects, editor objects 109 | and parser objects. Extensions may define their own additional special 110 | object type. Special objects have an additional LPC value. 111 | 112 | Objects should only be marked as special if they are not special already. 113 | If an object is to be unmarked, and a special LPC value has been set, it 114 | should be reset to `lpc_value_nil()` first. 115 | ``` 116 | int lpc_object_isspecial(LPC_frame, LPC_object obj);/* special object */ 117 | int lpc_object_ismarked(LPC_frame, LPC_object obj); /* user-def special */ 118 | void lpc_object_mark(LPC_frame, LPC_object obj); /* mark as special */ 119 | void lpc_object_unmark(LPC_frame, LPC_object obj); /* unmark as special */ 120 | ``` 121 | To retrieve or set the LPC value associated with a special object, the 122 | following functions can be used. 123 | ``` 124 | LPC_value lpc_data_get_val(LPC_dataspace data); 125 | void lpc_data_set_val(LPC_dataspace data, LPC_value val); 126 | ``` 127 | 128 | ## 4. Operations on LPC values 129 | 130 | The type of an LPC value can be determined with 131 | ``` 132 | int lpc_value_type(LPC_value val); 133 | ``` 134 | The return values can be: 135 | ``` 136 | LPC_TYPE_NIL 137 | LPC_TYPE_INT => LPC_int 138 | LPC_TYPE_FLOAT => LPC_float 139 | LPC_TYPE_STRING => LPC_string 140 | LPC_TYPE_OBJECT => LPC_object 141 | LPC_TYPE_ARRAY => LPC_array 142 | LPC_TYPE_MAPPING => LPC_mapping 143 | LPC_TYPE_LWOBJ => LPC_lwobj 144 | ``` 145 | `LPC_int` and `LPC_float` can be used directly, and are represented by an 146 | integral and a floating point type, respectively. The other types must be 147 | handled by the proper functions. Light-weight objects cannot be manipulated by 148 | an extension kfun, at all. 149 | ``` 150 | int lpc_value_type(LPC_value val); 151 | LPC_value lpc_value_nil(); /* the nil value */ 152 | LPC_value lpc_value_temp(LPC_datspace data); /* temporary value 1 */ 153 | LPC_value lpc_value_temp2(LPC_datspace data); /* temporary value 2 */ 154 | ``` 155 | To save data, it must first be stored in a value. Since `LPC_value` is 156 | actually a pointer, there is no way to construct a new value. 157 | `lpc_value_temp()` can be used as temporary storage (it always returns the 158 | same pointer), which can then be copied to some other value. 159 | ``` 160 | LPC_int lpc_int_getval(LPC_value val); 161 | void lpc_int_putval(LPC_value val, LPC_int num); 162 | 163 | LPC_float lpc_float_getval(LPC_value val); 164 | void lpc_float_putval(LPC_value val, LPC_float flt); 165 | 166 | LPC_string lpc_string_getval(LPC_value val); 167 | void lpc_string_putval(LPC_value val, LPC_string str); 168 | LPC_string lpc_string_new(LPC_dataspace data, const char *text, int len); 169 | char *lpc_string_text(LPC_string str); 170 | int lpc_string_length(LPC_string str); 171 | ``` 172 | The current object may be stored as an array or mapping element. 173 | ``` 174 | void lpc_object_putval(LPC_value val, LPC_object obj); 175 | char *lpc_object_name(LPC_frame f, LPC_object obj, char *buffer); 176 | ``` 177 | Don't modify array elements directly, but use `lpc_array_assign()` to change 178 | their value. 179 | ``` 180 | LPC_array lpc_array_getval(LPC_value val); 181 | void lpc_array_putval(LPC_value val, LPC_array arr); 182 | LPC_array lpc_array_new(LPC_dataspace data, int size); 183 | LPC_value lpc_array_index(LPC_array arr, int i); 184 | void lpc_array_assign(LPC_dataspace data, LPC_array arr, int index, 185 | LPC_value val); 186 | int lpc_array_size(LPC_array arr); 187 | ``` 188 | Don't modify mapping elements directly, but use `lpc_mapping_assign()` to 189 | change their value. `lpc_mapping_enum()` can be used to enumerate the 190 | indices of a mapping. 191 | ``` 192 | LPC_mapping lpc_mapping_getval(LPC_value val); 193 | void lpc_mapping_putval(LPC_value val, LPC_mapping map); 194 | LPC_mapping lpc_mapping_new(LPC_dataspace data); 195 | LPC_value lpc_mapping_index(LPC_mapping map, LPC_value index); 196 | void lpc_mapping_assign(LPC_dataspace data, LPC_mapping map, 197 | LPC_value index, LPC_value val); 198 | LPC_value lpc_mapping_enum(LPC_mapping map, unsigned int i); 199 | int lpc_mapping_size(LPC_mapping map); 200 | ``` 201 | 202 | ## 5. Spawning a process 203 | 204 | A program may be executed from an extension module. This can only be done 205 | once per module, and must be done from `lpc_ext_init()`. The process can be 206 | communicated with using pipes connected to standard input and output. 207 | ``` 208 | void lpc_ext_spawn(const char *cmdline); 209 | int lpc_ext_read(void *buffer, int len); 210 | int lpc_ext_write(const void *buffer, int len); 211 | ``` 212 | Data can also be put directly into the input pipe, to be read back with 213 | `lpc_ext_read()`, as if it came from the external process. 214 | ``` 215 | int lpc_ext_writeback(const void *buffer, int len); 216 | ``` 217 | 218 | This is intended for modules that offload some of their functionality into 219 | an external program. It cannot be used to execute an arbitrary program and 220 | communicate with it from LPC code. 221 | 222 | ## 6. Example 223 | 224 | The following code implements a `lower_case()` kfun. 225 | ``` 226 | # include "lpc_ext.h" 227 | 228 | static void lower_case(LPC_frame f, int nargs, LPC_value retval) 229 | { 230 | LPC_value val; 231 | LPC_string str; 232 | LPC_dataspace data; 233 | char *p; 234 | unsigned int i; 235 | 236 | /* fetch the argument string */ 237 | val = lpc_frame_arg(f, nargs, 0); 238 | str = lpc_string_getval(val); 239 | 240 | /* make a copy */ 241 | data = lpc_frame_dataspace(f); 242 | str = lpc_string_new(data, lpc_string_text(str), lpc_string_length(str)); 243 | 244 | /* turn to lowercase */ 245 | p = lpc_string_text(str); 246 | for (i = lpc_string_length(str); i != 0; --i) { 247 | if (*p >= 'A' && *p <= 'Z') { 248 | *p += 'a' - 'A'; 249 | } 250 | p++; 251 | } 252 | 253 | /* put result in return value */ 254 | lpc_string_putval(retval, str); 255 | } 256 | 257 | static char lower_case_proto[] = { LPC_TYPE_STRING, LPC_TYPE_STRING, 0 }; 258 | static LPC_ext_kfun kf[1] = { 259 | "lower_case", 260 | lower_case_proto, 261 | &lower_case 262 | }; 263 | 264 | int lpc_ext_init(int major, int minor, char *config) 265 | { 266 | lpc_ext_kfun(kf, 1); 267 | return 1; 268 | } 269 | ``` 270 | -------------------------------------------------------------------------------- /src/jit/flow.cpp: -------------------------------------------------------------------------------- 1 | # include 2 | # include 3 | # include 4 | # include 5 | extern "C" { 6 | # include "lpc_ext.h" 7 | } 8 | # include "data.h" 9 | # include "code.h" 10 | # include "stack.h" 11 | # include "block.h" 12 | # include "typed.h" 13 | # include "flow.h" 14 | # include "jitcomp.h" 15 | 16 | 17 | FlowContext::FlowContext(CodeFunction *func, StackSize size) : 18 | TypedContext(func, size) 19 | { 20 | inParams = outParams = inLocals = outLocals = NULL; 21 | } 22 | 23 | FlowContext::~FlowContext() 24 | { 25 | } 26 | 27 | /* 28 | * get a reference to a parameter 29 | */ 30 | int FlowContext::paramRef(LPCParam param) 31 | { 32 | if (outParams[param] != 0) { 33 | return outParams[param]; 34 | } else { 35 | inParams[param] = NEEDED; 36 | return 0; 37 | } 38 | } 39 | 40 | /* 41 | * get a reference to a local variable 42 | */ 43 | int FlowContext::localRef(LPCLocal local) 44 | { 45 | if (outLocals[local] != 0) { 46 | return outLocals[local]; 47 | } else { 48 | inLocals[local] = NEEDED; 49 | return 0; 50 | } 51 | } 52 | 53 | 54 | FlowCode::FlowCode(CodeFunction *function) : 55 | TypedCode(function) 56 | { 57 | in = out = 0; 58 | } 59 | 60 | FlowCode::~FlowCode() 61 | { 62 | } 63 | 64 | /* 65 | * determine inputs and outputs 66 | */ 67 | void FlowCode::evaluateFlow(FlowContext *context) 68 | { 69 | LPCParam n; 70 | 71 | switch (instruction) { 72 | case PARAM: 73 | out = context->paramRef(param); 74 | break; 75 | 76 | case LOCAL: 77 | out = context->localRef(local); 78 | break; 79 | 80 | case STORES_PARAM: 81 | case STORES_PARAM_INDEX: 82 | in = context->paramRef(param); 83 | /* fall through */ 84 | case STORE_PARAM: 85 | case STORE_PARAM_INDEX: 86 | context->outParams[param] = out = addr + 1; 87 | break; 88 | 89 | case STORES_LOCAL: 90 | case STORES_LOCAL_INDEX: 91 | in = context->localRef(local); 92 | /* fall through */ 93 | case STORE_LOCAL: 94 | case STORE_LOCAL_INDEX: 95 | context->outLocals[local] = out = addr + 1; 96 | break; 97 | 98 | case CAUGHT: 99 | out = addr + 1; 100 | for (n = 0; n < context->nParams; n++) { 101 | if (context->block->mod[n]) { 102 | context->outParams[n] = out; 103 | } 104 | } 105 | for (n = 0; n < context->nLocals; n++) { 106 | if (context->block->mod[context->nParams + n]) { 107 | context->outLocals[n] = out; 108 | } 109 | } 110 | break; 111 | 112 | default: 113 | break; 114 | } 115 | } 116 | 117 | 118 | FlowBlock::FlowBlock(Code *first, Code *last, CodeSize size) : 119 | TypedBlock(first, last, size) 120 | { 121 | inParams = inLocals = outParams = outLocals = NULL; 122 | } 123 | 124 | FlowBlock::~FlowBlock() 125 | { 126 | delete[] inParams; 127 | delete[] inLocals; 128 | delete[] outParams; 129 | delete[] outLocals; 130 | } 131 | 132 | /* 133 | * return input param reference 134 | */ 135 | int FlowBlock::paramIn(LPCParam param) 136 | { 137 | return inParams[param]; 138 | } 139 | 140 | /* 141 | * return output param reference 142 | */ 143 | int FlowBlock::paramOut(LPCParam param) 144 | { 145 | return (outParams[param] != 0) ? outParams[param] : inParams[param]; 146 | } 147 | 148 | /* 149 | * was a parameter merged? 150 | */ 151 | bool FlowBlock::paramMerged(LPCParam param) 152 | { 153 | return (paramIn(param) == -(first->addr + 1)); 154 | } 155 | 156 | /* 157 | * return input local var reference 158 | */ 159 | int FlowBlock::localIn(LPCLocal local) 160 | { 161 | return inLocals[local]; 162 | } 163 | 164 | /* 165 | * return output local var reference 166 | */ 167 | int FlowBlock::localOut(LPCLocal local) 168 | { 169 | return (outLocals[local] != 0) ? outLocals[local] : inLocals[local]; 170 | } 171 | 172 | /* 173 | * was a local var merged? 174 | */ 175 | bool FlowBlock::localMerged(LPCLocal local) 176 | { 177 | return (localIn(local) == -(first->addr + 1)); 178 | } 179 | 180 | /* 181 | * parameter merged type 182 | */ 183 | Type FlowBlock::mergedParamType(LPCParam param, Type type) 184 | { 185 | CodeSize i; 186 | 187 | if (!paramMerged(param)) { 188 | return LPC_TYPE_VOID; 189 | } 190 | 191 | i = 0; 192 | if (type == LPC_TYPE_VOID) { 193 | for (; i < nFrom; i++) { 194 | if (from[i]->paramOut(param) != 0) { 195 | type = from[i]->paramType(param); 196 | break; 197 | } 198 | } 199 | } 200 | for (; i < nFrom; i++) { 201 | if (from[i]->paramOut(param) != 0 && from[i]->paramType(param) != type) 202 | { 203 | type = LPC_TYPE_MIXED; 204 | break; 205 | } 206 | } 207 | return type; 208 | } 209 | 210 | /* 211 | * local variable merged type 212 | */ 213 | Type FlowBlock::mergedLocalType(LPCLocal local) 214 | { 215 | Type type; 216 | CodeSize i; 217 | 218 | if (!localMerged(local)) { 219 | return LPC_TYPE_VOID; 220 | } 221 | 222 | type = LPC_TYPE_MIXED; 223 | for (i = 0; i < nFrom; i++) { 224 | if (from[i]->localOut(local) != 0) { 225 | type = from[i]->localType(local); 226 | break; 227 | } 228 | } 229 | for (; i < nFrom; i++) { 230 | if (from[i]->localOut(local) != 0 && from[i]->localType(local) != type) 231 | { 232 | type = LPC_TYPE_MIXED; 233 | break; 234 | } 235 | } 236 | return type; 237 | } 238 | 239 | /* 240 | * give Context access to the inputs and outputs of this block 241 | */ 242 | void FlowBlock::prepareFlow(FlowContext *context) 243 | { 244 | context->inParams = inParams; 245 | context->inLocals = inLocals; 246 | context->outParams = outParams; 247 | context->outLocals = outLocals; 248 | } 249 | 250 | /* 251 | * determine inputs and outputs for this block 252 | */ 253 | void FlowBlock::evaluateFlow(FlowContext *context, Block **list) 254 | { 255 | Code *code; 256 | LPCParam n; 257 | 258 | /* 259 | * initialize params & locals 260 | */ 261 | if (context->nParams != 0) { 262 | memset(inParams = new int[context->nParams], '\0', 263 | context->nParams * sizeof(int)); 264 | memset(outParams = new int[context->nParams], '\0', 265 | context->nParams * sizeof(int)); 266 | } 267 | if (context->nLocals != 0) { 268 | memset(inLocals = new int[context->nLocals], '\0', 269 | context->nLocals * sizeof(int)); 270 | memset(outLocals = new int[context->nLocals], '\0', 271 | context->nLocals * sizeof(int)); 272 | } 273 | 274 | prepareFlow(context); 275 | context->block = this; 276 | 277 | for (code = first; ; code = code->next) { 278 | code->evaluateFlow(context); 279 | if (code == last) { 280 | break; 281 | } 282 | } 283 | 284 | for (n = 0; n < context->nParams; n++) { 285 | if (inParams[n] != 0) { 286 | toVisit(list); 287 | break; 288 | } 289 | } 290 | for (n = 0; n < context->nLocals; n++) { 291 | if (inLocals[n] != 0) { 292 | toVisit(list); 293 | break; 294 | } 295 | } 296 | } 297 | 298 | /* 299 | * flow back inputs 300 | */ 301 | void FlowBlock::evaluateInputs(FlowContext *context, Block **list) 302 | { 303 | LPCParam n; 304 | 305 | for (n = 0; n < context->nParams; n++) { 306 | if (context->inParams[n] != 0) { 307 | if (inParams[n] == 0 && outParams[n] == 0) { 308 | inParams[n] = FlowContext::NEEDED; 309 | toVisit(list); 310 | } 311 | } 312 | } 313 | for (n = 0; n < context->nLocals; n++) { 314 | if (context->inLocals[n] != 0) { 315 | if (inLocals[n] == 0 && outLocals[n] == 0) { 316 | inLocals[n] = FlowContext::NEEDED; 317 | toVisit(list); 318 | } 319 | } 320 | } 321 | } 322 | 323 | /* 324 | * flow forward outputs 325 | */ 326 | void FlowBlock::evaluateOutputs(FlowContext *context, Block **list) 327 | { 328 | LPCParam n; 329 | 330 | for (n = 0; n < context->nParams; n++) { 331 | if (inParams[n] != 0 && inParams[n] != -(first->addr + 1)) { 332 | if (context->outParams[n] != 0) { 333 | if (context->outParams[n] != inParams[n]) { 334 | if (inParams[n] == FlowContext::NEEDED || 335 | nFrom + (first->addr == 0) <= 1) { 336 | inParams[n] = context->outParams[n]; 337 | } else { 338 | inParams[n] = -(first->addr + 1); 339 | } 340 | toVisit(list); 341 | } 342 | } else if (context->inParams[n] != 0 && 343 | context->inParams[n] != FlowContext::NEEDED && 344 | context->inParams[n] != inParams[n]) { 345 | if (inParams[n] == FlowContext::NEEDED || 346 | nFrom + (first->addr == 0) <= 1) { 347 | inParams[n] = context->inParams[n]; 348 | } else { 349 | inParams[n] = -(first->addr + 1); 350 | } 351 | toVisit(list); 352 | } 353 | } 354 | } 355 | 356 | for (n = 0; n < context->nLocals; n++) { 357 | if (inLocals[n] != 0 && inLocals[n] != -(first->addr + 1)) { 358 | if (context->outLocals[n] != 0) { 359 | if (context->outLocals[n] != inLocals[n]) { 360 | if (inLocals[n] == FlowContext::NEEDED || 361 | nFrom + (first->addr == 0) <= 1) { 362 | inLocals[n] = context->outLocals[n]; 363 | } else { 364 | inLocals[n] = -(first->addr + 1); 365 | } 366 | toVisit(list); 367 | } 368 | } else if (context->inLocals[n] != 0 && 369 | context->inLocals[n] != FlowContext::NEEDED && 370 | context->inLocals[n] != inLocals[n]) { 371 | if (inLocals[n] == FlowContext::NEEDED || 372 | nFrom + (first->addr == 0) <= 1) { 373 | inLocals[n] = context->inLocals[n]; 374 | } else { 375 | inLocals[n] = -(first->addr + 1); 376 | } 377 | toVisit(list); 378 | } 379 | } 380 | } 381 | } 382 | 383 | /* 384 | * evaluate all blocks 385 | */ 386 | void FlowBlock::evaluate(FlowContext *context) 387 | { 388 | Block *list, *b; 389 | CodeSize i; 390 | LPCParam n; 391 | 392 | TypedBlock::evaluate(context); 393 | 394 | /* 395 | * determine inputs and outputs for each block 396 | */ 397 | startAllVisits(&list); 398 | for (b = this; b != NULL; b = b->next) { 399 | b->evaluateFlow(context, &list); 400 | } 401 | 402 | /* 403 | * flow back inputs 404 | */ 405 | while ((b=nextVisit(&list)) != NULL) { 406 | b->prepareFlow(context); 407 | for (i = 0; i < b->nFrom; i++) { 408 | b->from[i]->evaluateInputs(context, &list); 409 | } 410 | } 411 | 412 | /* 413 | * inputs for the first block are initial values 414 | */ 415 | for (n = 0; n < context->nParams; n++) { 416 | if (inParams[n] != 0) { 417 | inParams[n] = FlowContext::INITIAL; 418 | } 419 | } 420 | for (n = 0; n < context->nLocals; n++) { 421 | if (inLocals[n] != 0) { 422 | inLocals[n] = FlowContext::INITIAL; 423 | } 424 | } 425 | 426 | /* 427 | * flow forward outputs 428 | */ 429 | startAllVisits(&list); 430 | for (b = this; b != NULL; b = b->next) { 431 | b->prepareFlow(context); 432 | for (i = 0; i < b->nTo; i++) { 433 | b->to[i]->evaluateOutputs(context, &list); 434 | } 435 | } 436 | while ((b=nextVisit(&list)) != NULL) { 437 | b->prepareFlow(context); 438 | for (i = 0; i < b->nTo; i++) { 439 | b->to[i]->evaluateOutputs(context, &list); 440 | } 441 | } 442 | } 443 | -------------------------------------------------------------------------------- /src/dbase/dbase.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This code is released into the public domain. 3 | * 4 | * Minimal example implementation of database module: replace snapshots with 5 | * database. This is incomplete; not all errors are checked for, locking is 6 | * not implemented, pwrite/pread/aio/io_uring could be used, file descriptors 7 | * are kept open for all database objects, internal database snapshots are 8 | * not cleaned up and the database can grow very large, etc. 9 | * 10 | * Functions may simultaneously be called from different threads, but each 11 | * database object will only be accessed by one thread at a time. Snapshot 12 | * functions are always called sequentially. 13 | * 14 | * The database module support code in Hydra is not as well-tested as the 15 | * swap/snapshot code. Note that Hydra can restore snapshots into a database 16 | * but not the other way around; once you switch to using the database 17 | * interface, you are committed! 18 | * 19 | * Hydra's snapshot code is not an implementation of the database interface, 20 | * and there is a difference in what data is saved. That difference is likely 21 | * to increase in the future. 22 | * 23 | * For use in production, this code should be completely rewritten, perhaps to 24 | * forward calls to an external database. 25 | */ 26 | 27 | # include 28 | # include 29 | # include 30 | # include 31 | # include 32 | # include 33 | # include 34 | # include "lpc_ext.h" 35 | 36 | 37 | # define TRUE 1 38 | # define FALSE 0 39 | 40 | struct _lpc_database_ { 41 | char path[1024]; /* path to database directory */ 42 | int generation; /* start at 1, up to 65534, wraparound */ 43 | }; 44 | struct _lpc_db_object_ { 45 | uint64_t index; /* unique object index */ 46 | int generation; /* database generation */ 47 | int fd; /* database object file descriptor */ 48 | LPC_db *db; /* database this object is in */ 49 | }; 50 | 51 | /* 52 | * determine, based on the file name, whether something is a database 53 | */ 54 | static int db_valid(const char *file) 55 | { 56 | ssize_t len; 57 | 58 | len = strlen(file); 59 | return (len >= 8 && strcmp(file + len - 7, ".testdb") == 0); 60 | } 61 | 62 | /* 63 | * open a database 64 | */ 65 | static LPC_db *db_open(const char *file, int *created) 66 | { 67 | char buffer[2048]; 68 | struct stat statbuf; 69 | LPC_db *db; 70 | 71 | if (!db_valid(file)) { 72 | return NULL; 73 | } 74 | strncpy(buffer, file, sizeof(buffer) - 20); 75 | memset(&statbuf, '\0', sizeof(statbuf)); 76 | if (stat(buffer, &statbuf) != 0 && created != NULL) { 77 | /* 78 | * create new database 79 | */ 80 | if (mkdir(buffer, 0700) != 0) { 81 | return NULL; 82 | } 83 | 84 | db = malloc(sizeof(LPC_db)); 85 | strcpy(db->path, buffer); 86 | db->generation = 1; 87 | 88 | /* first generation */ 89 | strcat(buffer, "/1"); 90 | if (mkdir(buffer, 0700) != 0) { 91 | free(db); 92 | return NULL; 93 | } 94 | 95 | *created = TRUE; 96 | } else { 97 | int fd; 98 | 99 | /* 100 | * open existing databse 101 | */ 102 | if ((statbuf.st_mode & S_IFMT) != S_IFDIR) { 103 | return NULL; 104 | } 105 | db = malloc(sizeof(LPC_db)); 106 | strcpy(db->path, buffer); 107 | 108 | strcat(buffer, "/snapshot"); 109 | fd = open(buffer, O_RDONLY); 110 | if (fd < 0) { 111 | free(db); 112 | return NULL; 113 | } 114 | if (read(fd, buffer, sizeof(buffer)) < 0) { 115 | close(fd); 116 | free(db); 117 | return NULL; 118 | } 119 | close(fd); 120 | 121 | /* start new generation */ 122 | db->generation = atoi(buffer) + 1; 123 | if (db->generation == 65535) { 124 | db->generation = 1; 125 | } 126 | 127 | if (created != NULL) { 128 | *created = FALSE; 129 | } 130 | } 131 | 132 | return db; 133 | } 134 | 135 | /* 136 | * close a database 137 | */ 138 | static void db_close(LPC_db *db) 139 | { 140 | /* expect that all dbase objects will be deleted first */ 141 | free(db); 142 | } 143 | 144 | /* 145 | * create a new object in a database 146 | */ 147 | static LPC_db_object *db_new_obj(LPC_db *db, LPC_db_index index) 148 | { 149 | char buffer[2048]; 150 | int fd; 151 | LPC_db_object *obj; 152 | 153 | sprintf(buffer, "%s/%d/%lld", db->path, db->generation, (long long) index); 154 | fd = open(buffer, O_CREAT | O_TRUNC | O_RDWR, 0600); 155 | if (fd < 0) { 156 | return NULL; 157 | } 158 | 159 | obj = malloc(sizeof(LPC_db_object)); 160 | obj->index = index; 161 | obj->generation = db->generation; 162 | obj->fd = fd; 163 | obj->db = db; 164 | return obj; 165 | } 166 | 167 | /* 168 | * load an object from a database 169 | */ 170 | static LPC_db_object *db_load_obj(LPC_db *db, LPC_db_index index, 171 | LPC_db_handle handle) 172 | { 173 | char buffer[2048]; 174 | int fd; 175 | LPC_db_object *obj; 176 | 177 | /* assume that the handle passed by the caller is the object generation */ 178 | sprintf(buffer, "%s/%d/%lld", db->path, (int) handle, (long long) index); 179 | fd = open(buffer, O_RDWR); 180 | if (fd < 0) { 181 | return NULL; 182 | } 183 | 184 | obj = malloc(sizeof(LPC_db_object)); 185 | obj->index = index; 186 | obj->generation = (int) handle; 187 | obj->fd = fd; 188 | obj->db = db; 189 | return obj; 190 | } 191 | 192 | /* 193 | * delete an object reference 194 | */ 195 | static int db_del_obj(LPC_db_object *obj) 196 | { 197 | if (obj->fd >= 0) { 198 | close(obj->fd); 199 | } 200 | free(obj); 201 | 202 | return TRUE; 203 | } 204 | 205 | /* 206 | * if the object is not of the current generation, it should be refreshed 207 | * (recreated in the current generation) when modified 208 | */ 209 | static int db_refresh_obj(LPC_db_object *obj) 210 | { 211 | return (obj->generation != obj->db->generation); 212 | } 213 | 214 | /* 215 | * Resize an object in a database (first time, resize from 0). Objects that 216 | * change in size are always resized before they are written to. 217 | */ 218 | static int db_resize_obj(LPC_db_object *obj, uint64_t size, 219 | LPC_db_handle *handle) 220 | { 221 | if (ftruncate(obj->fd, (size_t) size) == 0) { 222 | /* pass the object generation to the caller */ 223 | *handle = obj->generation; 224 | return TRUE; 225 | } else { 226 | return FALSE; 227 | } 228 | } 229 | 230 | /* 231 | * read from an object in a database 232 | */ 233 | static int db_read_obj(LPC_db_object *obj, LPC_db_request *request, 234 | int nrequest) 235 | { 236 | int i; 237 | 238 | for (i = 0; i < nrequest; i++) { 239 | if (lseek(obj->fd, (off_t) request[i].offset, SEEK_SET) < 0 || 240 | read(obj->fd, request[i].data, request[i].size) != request[i].size) 241 | { 242 | return FALSE; 243 | } 244 | } 245 | 246 | return TRUE; 247 | } 248 | 249 | /* 250 | * write to an object in a database 251 | */ 252 | static int db_write_obj(LPC_db_object *obj, LPC_db_request *request, 253 | int nrequest) 254 | { 255 | int i; 256 | 257 | for (i = 0; i < nrequest; i++) { 258 | if (lseek(obj->fd, (off_t) request[i].offset, SEEK_SET) < 0 || 259 | write(obj->fd, request[i].data, request[i].size) != request[i].size) 260 | { 261 | return FALSE; 262 | } 263 | } 264 | 265 | return TRUE; 266 | } 267 | 268 | /* 269 | * remove an object from the database 270 | */ 271 | static int db_remove_obj(LPC_db_object *obj) 272 | { 273 | char buffer[2048]; 274 | 275 | if (obj->fd < 0) { 276 | return FALSE; /* already removed */ 277 | } 278 | 279 | close(obj->fd); 280 | obj->fd = -1; 281 | sprintf(buffer, "%s/%d/%lld", obj->db->path, obj->generation, 282 | (long long) obj->index); 283 | return (unlink(buffer) == 0); 284 | } 285 | 286 | /* 287 | * save snapshot info in a database 288 | */ 289 | static int db_save(LPC_db *db, LPC_db_request *request) 290 | { 291 | char buffer[2048]; 292 | int fd; 293 | 294 | /* save snapshot tables for current generation */ 295 | sprintf(buffer, "%s/snapshot-%d", db->path, db->generation); 296 | fd = open(buffer, O_WRONLY | O_CREAT, 0600); 297 | if (fd < 0) { 298 | return FALSE; 299 | } 300 | 301 | if (lseek(fd, (off_t) (request->offset + 1024), SEEK_SET) < 0 || 302 | write(fd, request->data, request->size) != request->size) { 303 | close(fd); 304 | return FALSE; 305 | } 306 | close(fd); 307 | 308 | return TRUE; 309 | } 310 | 311 | /* 312 | * restore snapshot info from a database 313 | */ 314 | static int db_restore(LPC_db *db, LPC_db_request *request) 315 | { 316 | char buffer[2048]; 317 | int snapshot; 318 | int fd; 319 | 320 | /* restore snapshot tables from previous generation */ 321 | snapshot = db->generation - 1; 322 | if (snapshot == 0) { 323 | snapshot = 65534; 324 | } 325 | sprintf(buffer, "%s/snapshot-%d", db->path, snapshot); 326 | fd = open(buffer, O_RDONLY); 327 | if (fd < 0) { 328 | return FALSE; 329 | } 330 | 331 | if (lseek(fd, (off_t) (request->offset + 1024), SEEK_SET) < 0 || 332 | read(fd, request->data, request->size) != request->size) { 333 | close(fd); 334 | return FALSE; 335 | } 336 | close(fd); 337 | 338 | return TRUE; 339 | } 340 | 341 | /* 342 | * finish snapshot in a database 343 | */ 344 | static int db_save_snapshot(LPC_db *db, LPC_db_request *request) 345 | { 346 | char buffer[2048]; 347 | int fd; 348 | 349 | /* save snapshot header for current generation */ 350 | sprintf(buffer, "%s/snapshot-%d", db->path, db->generation); 351 | fd = open(buffer, O_WRONLY); 352 | if (fd < 0) { 353 | return FALSE; 354 | } 355 | if (write(fd, request->data, request->size) != request->size) { 356 | close(fd); 357 | return FALSE; 358 | } 359 | close(fd); 360 | 361 | /* save snapshot generation number */ 362 | sprintf(buffer, "%s/snapshot", db->path); 363 | fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, 0600); 364 | if (fd < 0) { 365 | return FALSE; 366 | } 367 | sprintf(buffer, "%d", db->generation); 368 | if (write(fd, buffer, strlen(buffer)) != strlen(buffer)) { 369 | close(fd); 370 | return FALSE; 371 | } 372 | close(fd); 373 | 374 | /* increase generation */ 375 | db->generation++; 376 | if (db->generation == 65535) { 377 | db->generation = 1; 378 | } 379 | sprintf(buffer, "%s/%d", db->path, db->generation); 380 | mkdir(buffer, 0700); /* allowed to fail (generation wraparound) */ 381 | 382 | return TRUE; 383 | } 384 | 385 | /* 386 | * restore snapshot from a database 387 | */ 388 | static int db_restore_snapshot(LPC_db *db, LPC_db_request *request) 389 | { 390 | char buffer[2048]; 391 | int snapshot; 392 | int fd; 393 | 394 | /* restore previous generation */ 395 | snapshot = db->generation - 1; 396 | if (snapshot == 0) { 397 | snapshot = 65534; 398 | } 399 | sprintf(buffer, "%s/snapshot-%d", db->path, snapshot); 400 | fd = open(buffer, O_RDONLY); 401 | if (fd < 0) { 402 | return FALSE; 403 | } 404 | if (read(fd, request->data, request->size) != request->size) { 405 | close(fd); 406 | return FALSE; 407 | } 408 | close(fd); 409 | 410 | return TRUE; 411 | } 412 | 413 | static const LPC_ext_dbase db_ext = { 414 | &db_valid, 415 | &db_open, 416 | &db_close, 417 | &db_new_obj, 418 | &db_load_obj, 419 | &db_del_obj, 420 | &db_refresh_obj, 421 | &db_resize_obj, 422 | &db_read_obj, 423 | &db_write_obj, 424 | &db_remove_obj, 425 | &db_save, 426 | &db_restore, 427 | &db_save_snapshot, 428 | &db_restore_snapshot 429 | }; 430 | 431 | /* 432 | * initialize database interface 433 | */ 434 | int lpc_ext_init(int major, int minor, const char *config) 435 | { 436 | (*lpc_ext_dbase)(&db_ext); 437 | 438 | return TRUE; 439 | } 440 | --------------------------------------------------------------------------------