add a cool lua repl

This commit is contained in:
jacqueline
2023-12-13 16:10:08 +11:00
parent 5a2f0b08e0
commit 64b106c13e
87 changed files with 8150 additions and 5 deletions
+13
View File
@@ -0,0 +1,13 @@
*.o
*.so
*.dylib
*.rock
*.dll
*.def
*.exp
*.lib
*.obj
history.txt
VSProj/Release/*.*
VSProj/Debug/*.*
+4
View File
@@ -0,0 +1,4 @@
idf_component_register(
SRCS "linenoise.c" "encodings/utf8.c"
INCLUDE_DIRS "."
REQUIRES "console" "esp-idf-lua")
+18
View File
@@ -0,0 +1,18 @@
Copyright (c) 2011-2015 Rob Hoelz <rob@hoelz.ro>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+24
View File
@@ -0,0 +1,24 @@
0.9 2018 Apr 04
- Add syntactic sugar for addcompletion (thanks, Natanael Copa!)
- Add bindings for new linenoise functions: setmultiline, sethintscallback, printkeycodes (GH #16, GH #17)
- Propagate errors in completion callback (GH #14)
- Remove ability to use custom linenoise library (explanation in fa53845)
- Unicode 9.0 support (thanks, Alec Larson!)
- UTF8 support (thanks, Alec Larson!)
- ANSI support (GH #15 - thanks, Alec Larson!)
0.8 2015 Apr 29
- Fix memory leak (thanks, Dirk Feytons!)
0.7 2015 Feb 24
- Bump linenoise version
0.4 2012 Dec 18
- Offer more options when building.
- Update bundled version of linenoise.
0.3 2012 Sep 19
- Update rockspec and upload to luarocks.
0.2 ???
- Initial release.
+15
View File
@@ -0,0 +1,15 @@
OS=$(shell uname)
OBJECTS=linenoise.o encodings/utf8.o linenoiselib.o
ifeq ($(OS),Darwin)
linenoise.dylib: $(OBJECTS)
gcc -o $@ -bundle -undefined dynamic_lookup $^ $(OPT_LIB)
else
CFLAGS=-fPIC -I/usr/include/lua5.1
linenoise.so: $(OBJECTS)
gcc -o $@ -shared $^ $(OPT_LIB)
endif
clean:
rm -f *.o encodings/*.o *.so *.dylib
+134
View File
@@ -0,0 +1,134 @@
# lua-linenoise - Lua binding for the linenoise command line library
Linenoise (https://github.com/antirez/linenoise) is a delightfully simple command
line library. This Lua module is simply a binding for it.
The main Linenoise upstream has stagnated a bit, so this binding tracks https://github.com/yhirose/linenoise/tree/utf8-support, which
includes things like UTF-8 support and ANSI terminal escape sequence detection.
This repository also contains a Windows-compatible version of linenoise taken from MSOpenTech's [Windows port](https://github.com/MSOpenTech/redis) of redis.
# Compilation
If you use LuaRocks, you can run `luarocks make` on the latest rockspec.
You can also build with make. When building this module using make, you may use the original linenoise source included in
the repository, or you may set the Makefile variable `LIBLINENOISE` to override
it:
```sh
make LIBLINENOISE=-llinenoise
# OR:
make LIBLINENOISE=/path/to/liblinenoise.a
```
You may need to change the value of the LN_EXPORT macro in lua-linenoise.c to the appropriate keyword to ensure the luaopen_linenoise function is exported properly (I don't know much about C or Unix-like systems, so I may have gotten it wrong).
If you have Visual Studio 2012 (even the free Express version), you can compile this module with the Windows-compatible linenoise source using the included solution file (you'll need to edit the include paths and import library dependencies to match your configuration).
If you prefer to compile using other tools, just link lua-linenoise.c with line-noise-windows/linenoise.c and line-noise-windows/win32fixes.c to create the Windows-compatible DLL.
# Usage
This library is a fairly thin wrapper over linenoise itself, so the function calls
are named similarly. I may develop a "porcelain" layer in the future.
## L.linenoise(prompt)
Prompts for a line of input, using *prompt* as the prompt string. Returns nil if
no more input is available; Returns nil and an error string if an error occurred.
## L.historyadd(line)
Adds *line* to the history list.
## L.historysetmaxlen(length)
Sets the history list size to *length*.
## L.historysave(filename)
Saves the history list to *filename*.
## L.historyload(filename)
Loads the history list from *filename*.
## L.clearscreen()
Clears the screen.
## L.setcompletion(callback)
Sets the completion callback. This callback is called with two arguments:
* A completions object. Use object:add or L.addcompletion to add a completion to this object.
* The current line of input.
## L.addcompletion(completions, string)
Adds *string* to the list of completions.
All functions return nil on error; functions that don't have an obvious return value
return true on success.
## L.setmultiline(multiline)
Enables multi-line mode if *multiline* is true, disables otherwise.
## L.sethints(callback)
Sets a hints callback to provide hint information on the right hand side of the
prompt. *calback* should be a function that takes a single parameter (a
string, the line entered so far) and returns zero, one, or two values. Zero
values means no hint. The first value may be *nil* for no hint, or a string
value for a hint. If the first value is a string, the second value may be a table
with the *color* and *bold* keys - *color* is an ANSI terminal color code (such as
those provided by the [lua-term](https://luarocks.org/modules/hoelzro/lua-term) colors
module), whereas *bold* is a boolean indicating whether or not the hint should be printed
as bold.
## L.printkeycodes()
Prints linenoise key codes. Primarly used for debugging.
## L.enableutf8()
Enables UTF-8 handling.
# Example
```lua
local L = require 'linenoise'
local colors = require('term').colors -- optional
-- L.clearscreen()
print '----- Testing lua-linenoise! ------'
local prompt, history = '? ', 'history.txt'
L.historyload(history) -- load existing history
L.setcompletion(function(completion,str)
if str == 'h' then
completion:add('help')
completion:add('halt')
end
end)
L.sethints(function(str)
if str == 'h' then
return ' bold hints in red', { color = colors.red, bold = true }
end
end)
L.enableutf8()
local line, err = L.linenoise(prompt)
while line do
if #line > 0 then
print(line:upper())
L.historyadd(line)
L.historysave(history) -- save every new line
end
line, err = L.linenoise(prompt)
end
if err then
print('An error occurred: ' .. err)
end
```
Binary file not shown.
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lua-linenoise", "lua-linenoise.vcxproj", "{CC66E7EE-467D-4397-B311-99B5F2A06829}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CC66E7EE-467D-4397-B311-99B5F2A06829}.Debug|Win32.ActiveCfg = Debug|Win32
{CC66E7EE-467D-4397-B311-99B5F2A06829}.Debug|Win32.Build.0 = Debug|Win32
{CC66E7EE-467D-4397-B311-99B5F2A06829}.Release|Win32.ActiveCfg = Release|Win32
{CC66E7EE-467D-4397-B311-99B5F2A06829}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
Binary file not shown.
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{CC66E7EE-467D-4397-B311-99B5F2A06829}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<TargetName>linenoise</TargetName>
<TargetExt>.dll</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>true</LinkIncremental>
<TargetName>linenoise</TargetName>
<TargetExt>.dll</TargetExt>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>C:\Lua\LuaJIT_2.0\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>ws2_32.lib;C:\Lua\LuaJIT_2.0\lib\lua51.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>C:\Lua\LuaJIT\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>ws2_32.lib;C:\Lua\LuaJIT\lib\lua51.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\fmacros.h" />
<ClInclude Include="..\linenoise.h" />
<ClInclude Include="..\win32fixes.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\linenoiselib.c" />
<ClCompile Include="..\win32fixes.c" />
<ClCompile Include="..\linenoise.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\fmacros.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\linenoise.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\win32fixes.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\linenoiselib.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\win32fixes.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\linenoise.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
+505
View File
@@ -0,0 +1,505 @@
/* encoding/utf8.c -- VERSION 1.0
*
* Guerrilla line editing library against the idea that a line editing lib
* needs to be 20,000 lines of C code.
*
* You can find the latest source code at:
*
* http://github.com/antirez/linenoise
*
* Does a number of crazy assumptions that happen to be true in 99.9999% of
* the 2010 UNIX computers around.
*
* ------------------------------------------------------------------------
*
* Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com>
* Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <unistd.h>
#include <stdio.h>
#define UNUSED(x) (void)(x)
/* ============================ UTF8 utilities ============================== */
static unsigned long wideCharTable[][2] = {
{ 0x1100, 0x115F },
{ 0x231A, 0x231B },
{ 0x2329, 0x232A },
{ 0x23E9, 0x23EC },
{ 0x23F0, 0x23F0 },
{ 0x23F3, 0x23F3 },
{ 0x25FD, 0x25FE },
{ 0x2614, 0x2615 },
{ 0x2648, 0x2653 },
{ 0x267F, 0x267F },
{ 0x2693, 0x2693 },
{ 0x26A1, 0x26A1 },
{ 0x26AA, 0x26AB },
{ 0x26BD, 0x26BE },
{ 0x26C4, 0x26C5 },
{ 0x26CE, 0x26CE },
{ 0x26D4, 0x26D4 },
{ 0x26EA, 0x26EA },
{ 0x26F2, 0x26F3 },
{ 0x26F5, 0x26F5 },
{ 0x26FA, 0x26FA },
{ 0x26FD, 0x26FD },
{ 0x2705, 0x2705 },
{ 0x270A, 0x270B },
{ 0x2728, 0x2728 },
{ 0x274C, 0x274C },
{ 0x274E, 0x274E },
{ 0x2753, 0x2755 },
{ 0x2757, 0x2757 },
{ 0x2795, 0x2797 },
{ 0x27B0, 0x27B0 },
{ 0x27BF, 0x27BF },
{ 0x2B1B, 0x2B1C },
{ 0x2B50, 0x2B50 },
{ 0x2B55, 0x2B55 },
{ 0x2E80, 0x2E99 },
{ 0x2E9B, 0x2EF3 },
{ 0x2F00, 0x2FD5 },
{ 0x2FF0, 0x2FFB },
{ 0x3001, 0x303E },
{ 0x3041, 0x3096 },
{ 0x3099, 0x30FF },
{ 0x3105, 0x312D },
{ 0x3131, 0x318E },
{ 0x3190, 0x31BA },
{ 0x31C0, 0x31E3 },
{ 0x31F0, 0x321E },
{ 0x3220, 0x3247 },
{ 0x3250, 0x32FE },
{ 0x3300, 0x4DBF },
{ 0x4E00, 0xA48C },
{ 0xA490, 0xA4C6 },
{ 0xA960, 0xA97C },
{ 0xAC00, 0xD7A3 },
{ 0xF900, 0xFAFF },
{ 0xFE10, 0xFE19 },
{ 0xFE30, 0xFE52 },
{ 0xFE54, 0xFE66 },
{ 0xFE68, 0xFE6B },
{ 0x16FE0, 0x16FE0 },
{ 0x17000, 0x187EC },
{ 0x18800, 0x18AF2 },
{ 0x1B000, 0x1B001 },
{ 0x1F004, 0x1F004 },
{ 0x1F0CF, 0x1F0CF },
{ 0x1F18E, 0x1F18E },
{ 0x1F191, 0x1F19A },
{ 0x1F200, 0x1F202 },
{ 0x1F210, 0x1F23B },
{ 0x1F240, 0x1F248 },
{ 0x1F250, 0x1F251 },
{ 0x1F300, 0x1F320 },
{ 0x1F32D, 0x1F335 },
{ 0x1F337, 0x1F37C },
{ 0x1F37E, 0x1F393 },
{ 0x1F3A0, 0x1F3CA },
{ 0x1F3CF, 0x1F3D3 },
{ 0x1F3E0, 0x1F3F0 },
{ 0x1F3F4, 0x1F3F4 },
{ 0x1F3F8, 0x1F43E },
{ 0x1F440, 0x1F440 },
{ 0x1F442, 0x1F4FC },
{ 0x1F4FF, 0x1F53D },
{ 0x1F54B, 0x1F54E },
{ 0x1F550, 0x1F567 },
{ 0x1F57A, 0x1F57A },
{ 0x1F595, 0x1F596 },
{ 0x1F5A4, 0x1F5A4 },
{ 0x1F5FB, 0x1F64F },
{ 0x1F680, 0x1F6C5 },
{ 0x1F6CC, 0x1F6CC },
{ 0x1F6D0, 0x1F6D2 },
{ 0x1F6EB, 0x1F6EC },
{ 0x1F6F4, 0x1F6F6 },
{ 0x1F910, 0x1F91E },
{ 0x1F920, 0x1F927 },
{ 0x1F930, 0x1F930 },
{ 0x1F933, 0x1F93E },
{ 0x1F940, 0x1F94B },
{ 0x1F950, 0x1F95E },
{ 0x1F980, 0x1F991 },
{ 0x1F9C0, 0x1F9C0 },
{ 0x20000, 0x2FFFD },
{ 0x30000, 0x3FFFD },
};
static size_t wideCharTableSize = sizeof(wideCharTable) / sizeof(wideCharTable[0]);
static unsigned long combiningCharTable[] = {
0x0300,0x0301,0x0302,0x0303,0x0304,0x0305,0x0306,0x0307,
0x0308,0x0309,0x030A,0x030B,0x030C,0x030D,0x030E,0x030F,
0x0310,0x0311,0x0312,0x0313,0x0314,0x0315,0x0316,0x0317,
0x0318,0x0319,0x031A,0x031B,0x031C,0x031D,0x031E,0x031F,
0x0320,0x0321,0x0322,0x0323,0x0324,0x0325,0x0326,0x0327,
0x0328,0x0329,0x032A,0x032B,0x032C,0x032D,0x032E,0x032F,
0x0330,0x0331,0x0332,0x0333,0x0334,0x0335,0x0336,0x0337,
0x0338,0x0339,0x033A,0x033B,0x033C,0x033D,0x033E,0x033F,
0x0340,0x0341,0x0342,0x0343,0x0344,0x0345,0x0346,0x0347,
0x0348,0x0349,0x034A,0x034B,0x034C,0x034D,0x034E,0x034F,
0x0350,0x0351,0x0352,0x0353,0x0354,0x0355,0x0356,0x0357,
0x0358,0x0359,0x035A,0x035B,0x035C,0x035D,0x035E,0x035F,
0x0360,0x0361,0x0362,0x0363,0x0364,0x0365,0x0366,0x0367,
0x0368,0x0369,0x036A,0x036B,0x036C,0x036D,0x036E,0x036F,
0x0483,0x0484,0x0485,0x0486,0x0487,0x0591,0x0592,0x0593,
0x0594,0x0595,0x0596,0x0597,0x0598,0x0599,0x059A,0x059B,
0x059C,0x059D,0x059E,0x059F,0x05A0,0x05A1,0x05A2,0x05A3,
0x05A4,0x05A5,0x05A6,0x05A7,0x05A8,0x05A9,0x05AA,0x05AB,
0x05AC,0x05AD,0x05AE,0x05AF,0x05B0,0x05B1,0x05B2,0x05B3,
0x05B4,0x05B5,0x05B6,0x05B7,0x05B8,0x05B9,0x05BA,0x05BB,
0x05BC,0x05BD,0x05BF,0x05C1,0x05C2,0x05C4,0x05C5,0x05C7,
0x0610,0x0611,0x0612,0x0613,0x0614,0x0615,0x0616,0x0617,
0x0618,0x0619,0x061A,0x064B,0x064C,0x064D,0x064E,0x064F,
0x0650,0x0651,0x0652,0x0653,0x0654,0x0655,0x0656,0x0657,
0x0658,0x0659,0x065A,0x065B,0x065C,0x065D,0x065E,0x065F,
0x0670,0x06D6,0x06D7,0x06D8,0x06D9,0x06DA,0x06DB,0x06DC,
0x06DF,0x06E0,0x06E1,0x06E2,0x06E3,0x06E4,0x06E7,0x06E8,
0x06EA,0x06EB,0x06EC,0x06ED,0x0711,0x0730,0x0731,0x0732,
0x0733,0x0734,0x0735,0x0736,0x0737,0x0738,0x0739,0x073A,
0x073B,0x073C,0x073D,0x073E,0x073F,0x0740,0x0741,0x0742,
0x0743,0x0744,0x0745,0x0746,0x0747,0x0748,0x0749,0x074A,
0x07A6,0x07A7,0x07A8,0x07A9,0x07AA,0x07AB,0x07AC,0x07AD,
0x07AE,0x07AF,0x07B0,0x07EB,0x07EC,0x07ED,0x07EE,0x07EF,
0x07F0,0x07F1,0x07F2,0x07F3,0x0816,0x0817,0x0818,0x0819,
0x081B,0x081C,0x081D,0x081E,0x081F,0x0820,0x0821,0x0822,
0x0823,0x0825,0x0826,0x0827,0x0829,0x082A,0x082B,0x082C,
0x082D,0x0859,0x085A,0x085B,0x08D4,0x08D5,0x08D6,0x08D7,
0x08D8,0x08D9,0x08DA,0x08DB,0x08DC,0x08DD,0x08DE,0x08DF,
0x08E0,0x08E1,0x08E3,0x08E4,0x08E5,0x08E6,0x08E7,0x08E8,
0x08E9,0x08EA,0x08EB,0x08EC,0x08ED,0x08EE,0x08EF,0x08F0,
0x08F1,0x08F2,0x08F3,0x08F4,0x08F5,0x08F6,0x08F7,0x08F8,
0x08F9,0x08FA,0x08FB,0x08FC,0x08FD,0x08FE,0x08FF,0x0900,
0x0901,0x0902,0x093A,0x093C,0x0941,0x0942,0x0943,0x0944,
0x0945,0x0946,0x0947,0x0948,0x094D,0x0951,0x0952,0x0953,
0x0954,0x0955,0x0956,0x0957,0x0962,0x0963,0x0981,0x09BC,
0x09C1,0x09C2,0x09C3,0x09C4,0x09CD,0x09E2,0x09E3,0x0A01,
0x0A02,0x0A3C,0x0A41,0x0A42,0x0A47,0x0A48,0x0A4B,0x0A4C,
0x0A4D,0x0A51,0x0A70,0x0A71,0x0A75,0x0A81,0x0A82,0x0ABC,
0x0AC1,0x0AC2,0x0AC3,0x0AC4,0x0AC5,0x0AC7,0x0AC8,0x0ACD,
0x0AE2,0x0AE3,0x0B01,0x0B3C,0x0B3F,0x0B41,0x0B42,0x0B43,
0x0B44,0x0B4D,0x0B56,0x0B62,0x0B63,0x0B82,0x0BC0,0x0BCD,
0x0C00,0x0C3E,0x0C3F,0x0C40,0x0C46,0x0C47,0x0C48,0x0C4A,
0x0C4B,0x0C4C,0x0C4D,0x0C55,0x0C56,0x0C62,0x0C63,0x0C81,
0x0CBC,0x0CBF,0x0CC6,0x0CCC,0x0CCD,0x0CE2,0x0CE3,0x0D01,
0x0D41,0x0D42,0x0D43,0x0D44,0x0D4D,0x0D62,0x0D63,0x0DCA,
0x0DD2,0x0DD3,0x0DD4,0x0DD6,0x0E31,0x0E34,0x0E35,0x0E36,
0x0E37,0x0E38,0x0E39,0x0E3A,0x0E47,0x0E48,0x0E49,0x0E4A,
0x0E4B,0x0E4C,0x0E4D,0x0E4E,0x0EB1,0x0EB4,0x0EB5,0x0EB6,
0x0EB7,0x0EB8,0x0EB9,0x0EBB,0x0EBC,0x0EC8,0x0EC9,0x0ECA,
0x0ECB,0x0ECC,0x0ECD,0x0F18,0x0F19,0x0F35,0x0F37,0x0F39,
0x0F71,0x0F72,0x0F73,0x0F74,0x0F75,0x0F76,0x0F77,0x0F78,
0x0F79,0x0F7A,0x0F7B,0x0F7C,0x0F7D,0x0F7E,0x0F80,0x0F81,
0x0F82,0x0F83,0x0F84,0x0F86,0x0F87,0x0F8D,0x0F8E,0x0F8F,
0x0F90,0x0F91,0x0F92,0x0F93,0x0F94,0x0F95,0x0F96,0x0F97,
0x0F99,0x0F9A,0x0F9B,0x0F9C,0x0F9D,0x0F9E,0x0F9F,0x0FA0,
0x0FA1,0x0FA2,0x0FA3,0x0FA4,0x0FA5,0x0FA6,0x0FA7,0x0FA8,
0x0FA9,0x0FAA,0x0FAB,0x0FAC,0x0FAD,0x0FAE,0x0FAF,0x0FB0,
0x0FB1,0x0FB2,0x0FB3,0x0FB4,0x0FB5,0x0FB6,0x0FB7,0x0FB8,
0x0FB9,0x0FBA,0x0FBB,0x0FBC,0x0FC6,0x102D,0x102E,0x102F,
0x1030,0x1032,0x1033,0x1034,0x1035,0x1036,0x1037,0x1039,
0x103A,0x103D,0x103E,0x1058,0x1059,0x105E,0x105F,0x1060,
0x1071,0x1072,0x1073,0x1074,0x1082,0x1085,0x1086,0x108D,
0x109D,0x135D,0x135E,0x135F,0x1712,0x1713,0x1714,0x1732,
0x1733,0x1734,0x1752,0x1753,0x1772,0x1773,0x17B4,0x17B5,
0x17B7,0x17B8,0x17B9,0x17BA,0x17BB,0x17BC,0x17BD,0x17C6,
0x17C9,0x17CA,0x17CB,0x17CC,0x17CD,0x17CE,0x17CF,0x17D0,
0x17D1,0x17D2,0x17D3,0x17DD,0x180B,0x180C,0x180D,0x1885,
0x1886,0x18A9,0x1920,0x1921,0x1922,0x1927,0x1928,0x1932,
0x1939,0x193A,0x193B,0x1A17,0x1A18,0x1A1B,0x1A56,0x1A58,
0x1A59,0x1A5A,0x1A5B,0x1A5C,0x1A5D,0x1A5E,0x1A60,0x1A62,
0x1A65,0x1A66,0x1A67,0x1A68,0x1A69,0x1A6A,0x1A6B,0x1A6C,
0x1A73,0x1A74,0x1A75,0x1A76,0x1A77,0x1A78,0x1A79,0x1A7A,
0x1A7B,0x1A7C,0x1A7F,0x1AB0,0x1AB1,0x1AB2,0x1AB3,0x1AB4,
0x1AB5,0x1AB6,0x1AB7,0x1AB8,0x1AB9,0x1ABA,0x1ABB,0x1ABC,
0x1ABD,0x1B00,0x1B01,0x1B02,0x1B03,0x1B34,0x1B36,0x1B37,
0x1B38,0x1B39,0x1B3A,0x1B3C,0x1B42,0x1B6B,0x1B6C,0x1B6D,
0x1B6E,0x1B6F,0x1B70,0x1B71,0x1B72,0x1B73,0x1B80,0x1B81,
0x1BA2,0x1BA3,0x1BA4,0x1BA5,0x1BA8,0x1BA9,0x1BAB,0x1BAC,
0x1BAD,0x1BE6,0x1BE8,0x1BE9,0x1BED,0x1BEF,0x1BF0,0x1BF1,
0x1C2C,0x1C2D,0x1C2E,0x1C2F,0x1C30,0x1C31,0x1C32,0x1C33,
0x1C36,0x1C37,0x1CD0,0x1CD1,0x1CD2,0x1CD4,0x1CD5,0x1CD6,
0x1CD7,0x1CD8,0x1CD9,0x1CDA,0x1CDB,0x1CDC,0x1CDD,0x1CDE,
0x1CDF,0x1CE0,0x1CE2,0x1CE3,0x1CE4,0x1CE5,0x1CE6,0x1CE7,
0x1CE8,0x1CED,0x1CF4,0x1CF8,0x1CF9,0x1DC0,0x1DC1,0x1DC2,
0x1DC3,0x1DC4,0x1DC5,0x1DC6,0x1DC7,0x1DC8,0x1DC9,0x1DCA,
0x1DCB,0x1DCC,0x1DCD,0x1DCE,0x1DCF,0x1DD0,0x1DD1,0x1DD2,
0x1DD3,0x1DD4,0x1DD5,0x1DD6,0x1DD7,0x1DD8,0x1DD9,0x1DDA,
0x1DDB,0x1DDC,0x1DDD,0x1DDE,0x1DDF,0x1DE0,0x1DE1,0x1DE2,
0x1DE3,0x1DE4,0x1DE5,0x1DE6,0x1DE7,0x1DE8,0x1DE9,0x1DEA,
0x1DEB,0x1DEC,0x1DED,0x1DEE,0x1DEF,0x1DF0,0x1DF1,0x1DF2,
0x1DF3,0x1DF4,0x1DF5,0x1DFB,0x1DFC,0x1DFD,0x1DFE,0x1DFF,
0x20D0,0x20D1,0x20D2,0x20D3,0x20D4,0x20D5,0x20D6,0x20D7,
0x20D8,0x20D9,0x20DA,0x20DB,0x20DC,0x20E1,0x20E5,0x20E6,
0x20E7,0x20E8,0x20E9,0x20EA,0x20EB,0x20EC,0x20ED,0x20EE,
0x20EF,0x20F0,0x2CEF,0x2CF0,0x2CF1,0x2D7F,0x2DE0,0x2DE1,
0x2DE2,0x2DE3,0x2DE4,0x2DE5,0x2DE6,0x2DE7,0x2DE8,0x2DE9,
0x2DEA,0x2DEB,0x2DEC,0x2DED,0x2DEE,0x2DEF,0x2DF0,0x2DF1,
0x2DF2,0x2DF3,0x2DF4,0x2DF5,0x2DF6,0x2DF7,0x2DF8,0x2DF9,
0x2DFA,0x2DFB,0x2DFC,0x2DFD,0x2DFE,0x2DFF,0x302A,0x302B,
0x302C,0x302D,0x3099,0x309A,0xA66F,0xA674,0xA675,0xA676,
0xA677,0xA678,0xA679,0xA67A,0xA67B,0xA67C,0xA67D,0xA69E,
0xA69F,0xA6F0,0xA6F1,0xA802,0xA806,0xA80B,0xA825,0xA826,
0xA8C4,0xA8C5,0xA8E0,0xA8E1,0xA8E2,0xA8E3,0xA8E4,0xA8E5,
0xA8E6,0xA8E7,0xA8E8,0xA8E9,0xA8EA,0xA8EB,0xA8EC,0xA8ED,
0xA8EE,0xA8EF,0xA8F0,0xA8F1,0xA926,0xA927,0xA928,0xA929,
0xA92A,0xA92B,0xA92C,0xA92D,0xA947,0xA948,0xA949,0xA94A,
0xA94B,0xA94C,0xA94D,0xA94E,0xA94F,0xA950,0xA951,0xA980,
0xA981,0xA982,0xA9B3,0xA9B6,0xA9B7,0xA9B8,0xA9B9,0xA9BC,
0xA9E5,0xAA29,0xAA2A,0xAA2B,0xAA2C,0xAA2D,0xAA2E,0xAA31,
0xAA32,0xAA35,0xAA36,0xAA43,0xAA4C,0xAA7C,0xAAB0,0xAAB2,
0xAAB3,0xAAB4,0xAAB7,0xAAB8,0xAABE,0xAABF,0xAAC1,0xAAEC,
0xAAED,0xAAF6,0xABE5,0xABE8,0xABED,0xFB1E,0xFE00,0xFE01,
0xFE02,0xFE03,0xFE04,0xFE05,0xFE06,0xFE07,0xFE08,0xFE09,
0xFE0A,0xFE0B,0xFE0C,0xFE0D,0xFE0E,0xFE0F,0xFE20,0xFE21,
0xFE22,0xFE23,0xFE24,0xFE25,0xFE26,0xFE27,0xFE28,0xFE29,
0xFE2A,0xFE2B,0xFE2C,0xFE2D,0xFE2E,0xFE2F,
0x101FD,0x102E0,0x10376,0x10377,0x10378,0x10379,0x1037A,0x10A01,
0x10A02,0x10A03,0x10A05,0x10A06,0x10A0C,0x10A0D,0x10A0E,0x10A0F,
0x10A38,0x10A39,0x10A3A,0x10A3F,0x10AE5,0x10AE6,0x11001,0x11038,
0x11039,0x1103A,0x1103B,0x1103C,0x1103D,0x1103E,0x1103F,0x11040,
0x11041,0x11042,0x11043,0x11044,0x11045,0x11046,0x1107F,0x11080,
0x11081,0x110B3,0x110B4,0x110B5,0x110B6,0x110B9,0x110BA,0x11100,
0x11101,0x11102,0x11127,0x11128,0x11129,0x1112A,0x1112B,0x1112D,
0x1112E,0x1112F,0x11130,0x11131,0x11132,0x11133,0x11134,0x11173,
0x11180,0x11181,0x111B6,0x111B7,0x111B8,0x111B9,0x111BA,0x111BB,
0x111BC,0x111BD,0x111BE,0x111CA,0x111CB,0x111CC,0x1122F,0x11230,
0x11231,0x11234,0x11236,0x11237,0x1123E,0x112DF,0x112E3,0x112E4,
0x112E5,0x112E6,0x112E7,0x112E8,0x112E9,0x112EA,0x11300,0x11301,
0x1133C,0x11340,0x11366,0x11367,0x11368,0x11369,0x1136A,0x1136B,
0x1136C,0x11370,0x11371,0x11372,0x11373,0x11374,0x11438,0x11439,
0x1143A,0x1143B,0x1143C,0x1143D,0x1143E,0x1143F,0x11442,0x11443,
0x11444,0x11446,0x114B3,0x114B4,0x114B5,0x114B6,0x114B7,0x114B8,
0x114BA,0x114BF,0x114C0,0x114C2,0x114C3,0x115B2,0x115B3,0x115B4,
0x115B5,0x115BC,0x115BD,0x115BF,0x115C0,0x115DC,0x115DD,0x11633,
0x11634,0x11635,0x11636,0x11637,0x11638,0x11639,0x1163A,0x1163D,
0x1163F,0x11640,0x116AB,0x116AD,0x116B0,0x116B1,0x116B2,0x116B3,
0x116B4,0x116B5,0x116B7,0x1171D,0x1171E,0x1171F,0x11722,0x11723,
0x11724,0x11725,0x11727,0x11728,0x11729,0x1172A,0x1172B,0x11C30,
0x11C31,0x11C32,0x11C33,0x11C34,0x11C35,0x11C36,0x11C38,0x11C39,
0x11C3A,0x11C3B,0x11C3C,0x11C3D,0x11C3F,0x11C92,0x11C93,0x11C94,
0x11C95,0x11C96,0x11C97,0x11C98,0x11C99,0x11C9A,0x11C9B,0x11C9C,
0x11C9D,0x11C9E,0x11C9F,0x11CA0,0x11CA1,0x11CA2,0x11CA3,0x11CA4,
0x11CA5,0x11CA6,0x11CA7,0x11CAA,0x11CAB,0x11CAC,0x11CAD,0x11CAE,
0x11CAF,0x11CB0,0x11CB2,0x11CB3,0x11CB5,0x11CB6,0x16AF0,0x16AF1,
0x16AF2,0x16AF3,0x16AF4,0x16B30,0x16B31,0x16B32,0x16B33,0x16B34,
0x16B35,0x16B36,0x16F8F,0x16F90,0x16F91,0x16F92,0x1BC9D,0x1BC9E,
0x1D167,0x1D168,0x1D169,0x1D17B,0x1D17C,0x1D17D,0x1D17E,0x1D17F,
0x1D180,0x1D181,0x1D182,0x1D185,0x1D186,0x1D187,0x1D188,0x1D189,
0x1D18A,0x1D18B,0x1D1AA,0x1D1AB,0x1D1AC,0x1D1AD,0x1D242,0x1D243,
0x1D244,0x1DA00,0x1DA01,0x1DA02,0x1DA03,0x1DA04,0x1DA05,0x1DA06,
0x1DA07,0x1DA08,0x1DA09,0x1DA0A,0x1DA0B,0x1DA0C,0x1DA0D,0x1DA0E,
0x1DA0F,0x1DA10,0x1DA11,0x1DA12,0x1DA13,0x1DA14,0x1DA15,0x1DA16,
0x1DA17,0x1DA18,0x1DA19,0x1DA1A,0x1DA1B,0x1DA1C,0x1DA1D,0x1DA1E,
0x1DA1F,0x1DA20,0x1DA21,0x1DA22,0x1DA23,0x1DA24,0x1DA25,0x1DA26,
0x1DA27,0x1DA28,0x1DA29,0x1DA2A,0x1DA2B,0x1DA2C,0x1DA2D,0x1DA2E,
0x1DA2F,0x1DA30,0x1DA31,0x1DA32,0x1DA33,0x1DA34,0x1DA35,0x1DA36,
0x1DA3B,0x1DA3C,0x1DA3D,0x1DA3E,0x1DA3F,0x1DA40,0x1DA41,0x1DA42,
0x1DA43,0x1DA44,0x1DA45,0x1DA46,0x1DA47,0x1DA48,0x1DA49,0x1DA4A,
0x1DA4B,0x1DA4C,0x1DA4D,0x1DA4E,0x1DA4F,0x1DA50,0x1DA51,0x1DA52,
0x1DA53,0x1DA54,0x1DA55,0x1DA56,0x1DA57,0x1DA58,0x1DA59,0x1DA5A,
0x1DA5B,0x1DA5C,0x1DA5D,0x1DA5E,0x1DA5F,0x1DA60,0x1DA61,0x1DA62,
0x1DA63,0x1DA64,0x1DA65,0x1DA66,0x1DA67,0x1DA68,0x1DA69,0x1DA6A,
0x1DA6B,0x1DA6C,0x1DA75,0x1DA84,0x1DA9B,0x1DA9C,0x1DA9D,0x1DA9E,
0x1DA9F,0x1DAA1,0x1DAA2,0x1DAA3,0x1DAA4,0x1DAA5,0x1DAA6,0x1DAA7,
0x1DAA8,0x1DAA9,0x1DAAA,0x1DAAB,0x1DAAC,0x1DAAD,0x1DAAE,0x1DAAF,
0x1E000,0x1E001,0x1E002,0x1E003,0x1E004,0x1E005,0x1E006,0x1E008,
0x1E009,0x1E00A,0x1E00B,0x1E00C,0x1E00D,0x1E00E,0x1E00F,0x1E010,
0x1E011,0x1E012,0x1E013,0x1E014,0x1E015,0x1E016,0x1E017,0x1E018,
0x1E01B,0x1E01C,0x1E01D,0x1E01E,0x1E01F,0x1E020,0x1E021,0x1E023,
0x1E024,0x1E026,0x1E027,0x1E028,0x1E029,0x1E02A,0x1E8D0,0x1E8D1,
0x1E8D2,0x1E8D3,0x1E8D4,0x1E8D5,0x1E8D6,0x1E944,0x1E945,0x1E946,
0x1E947,0x1E948,0x1E949,0x1E94A,0xE0100,0xE0101,0xE0102,0xE0103,
0xE0104,0xE0105,0xE0106,0xE0107,0xE0108,0xE0109,0xE010A,0xE010B,
0xE010C,0xE010D,0xE010E,0xE010F,0xE0110,0xE0111,0xE0112,0xE0113,
0xE0114,0xE0115,0xE0116,0xE0117,0xE0118,0xE0119,0xE011A,0xE011B,
0xE011C,0xE011D,0xE011E,0xE011F,0xE0120,0xE0121,0xE0122,0xE0123,
0xE0124,0xE0125,0xE0126,0xE0127,0xE0128,0xE0129,0xE012A,0xE012B,
0xE012C,0xE012D,0xE012E,0xE012F,0xE0130,0xE0131,0xE0132,0xE0133,
0xE0134,0xE0135,0xE0136,0xE0137,0xE0138,0xE0139,0xE013A,0xE013B,
0xE013C,0xE013D,0xE013E,0xE013F,0xE0140,0xE0141,0xE0142,0xE0143,
0xE0144,0xE0145,0xE0146,0xE0147,0xE0148,0xE0149,0xE014A,0xE014B,
0xE014C,0xE014D,0xE014E,0xE014F,0xE0150,0xE0151,0xE0152,0xE0153,
0xE0154,0xE0155,0xE0156,0xE0157,0xE0158,0xE0159,0xE015A,0xE015B,
0xE015C,0xE015D,0xE015E,0xE015F,0xE0160,0xE0161,0xE0162,0xE0163,
0xE0164,0xE0165,0xE0166,0xE0167,0xE0168,0xE0169,0xE016A,0xE016B,
0xE016C,0xE016D,0xE016E,0xE016F,0xE0170,0xE0171,0xE0172,0xE0173,
0xE0174,0xE0175,0xE0176,0xE0177,0xE0178,0xE0179,0xE017A,0xE017B,
0xE017C,0xE017D,0xE017E,0xE017F,0xE0180,0xE0181,0xE0182,0xE0183,
0xE0184,0xE0185,0xE0186,0xE0187,0xE0188,0xE0189,0xE018A,0xE018B,
0xE018C,0xE018D,0xE018E,0xE018F,0xE0190,0xE0191,0xE0192,0xE0193,
0xE0194,0xE0195,0xE0196,0xE0197,0xE0198,0xE0199,0xE019A,0xE019B,
0xE019C,0xE019D,0xE019E,0xE019F,0xE01A0,0xE01A1,0xE01A2,0xE01A3,
0xE01A4,0xE01A5,0xE01A6,0xE01A7,0xE01A8,0xE01A9,0xE01AA,0xE01AB,
0xE01AC,0xE01AD,0xE01AE,0xE01AF,0xE01B0,0xE01B1,0xE01B2,0xE01B3,
0xE01B4,0xE01B5,0xE01B6,0xE01B7,0xE01B8,0xE01B9,0xE01BA,0xE01BB,
0xE01BC,0xE01BD,0xE01BE,0xE01BF,0xE01C0,0xE01C1,0xE01C2,0xE01C3,
0xE01C4,0xE01C5,0xE01C6,0xE01C7,0xE01C8,0xE01C9,0xE01CA,0xE01CB,
0xE01CC,0xE01CD,0xE01CE,0xE01CF,0xE01D0,0xE01D1,0xE01D2,0xE01D3,
0xE01D4,0xE01D5,0xE01D6,0xE01D7,0xE01D8,0xE01D9,0xE01DA,0xE01DB,
0xE01DC,0xE01DD,0xE01DE,0xE01DF,0xE01E0,0xE01E1,0xE01E2,0xE01E3,
0xE01E4,0xE01E5,0xE01E6,0xE01E7,0xE01E8,0xE01E9,0xE01EA,0xE01EB,
0xE01EC,0xE01ED,0xE01EE,0xE01EF,
};
static unsigned long combiningCharTableSize = sizeof(combiningCharTable) / sizeof(combiningCharTable[0]);
/* Check if the code is a wide character
*/
static int isWideChar(unsigned long cp) {
size_t i;
for (i = 0; i < wideCharTableSize; i++)
if (wideCharTable[i][0] <= cp && cp <= wideCharTable[i][1]) return 1;
return 0;
}
/* Check if the code is a combining character
*/
static int isCombiningChar(unsigned long cp) {
size_t i;
for (i = 0; i < combiningCharTableSize; i++)
if (combiningCharTable[i] == cp) return 1;
return 0;
}
/* Get length of previous UTF8 character
*/
static size_t prevUtf8CharLen(const char* buf, int pos) {
int end = pos--;
while (pos >= 0 && ((unsigned char)buf[pos] & 0xC0) == 0x80)
pos--;
return end - pos;
}
/* Convert UTF8 to Unicode code point
*/
static size_t utf8BytesToCodePoint(const char* buf, size_t len, int* cp) {
if (len) {
unsigned char byte = buf[0];
if ((byte & 0x80) == 0) {
*cp = byte;
return 1;
} else if ((byte & 0xE0) == 0xC0) {
if (len >= 2) {
*cp = (((unsigned long)(buf[0] & 0x1F)) << 6) |
((unsigned long)(buf[1] & 0x3F));
return 2;
}
} else if ((byte & 0xF0) == 0xE0) {
if (len >= 3) {
*cp = (((unsigned long)(buf[0] & 0x0F)) << 12) |
(((unsigned long)(buf[1] & 0x3F)) << 6) |
((unsigned long)(buf[2] & 0x3F));
return 3;
}
} else if ((byte & 0xF8) == 0xF0) {
if (len >= 4) {
*cp = (((unsigned long)(buf[0] & 0x07)) << 18) |
(((unsigned long)(buf[1] & 0x3F)) << 12) |
(((unsigned long)(buf[2] & 0x3F)) << 6) |
((unsigned long)(buf[3] & 0x3F));
return 4;
}
}
}
return 0;
}
/* Get length of next grapheme
*/
size_t linenoiseUtf8NextCharLen(const char* buf, size_t buf_len, size_t pos, size_t *col_len) {
size_t beg = pos;
int cp;
size_t len = utf8BytesToCodePoint(buf + pos, buf_len - pos, &cp);
if (isCombiningChar(cp)) {
/* NOTREACHED */
return 0;
}
if (col_len != NULL) *col_len = isWideChar(cp) ? 2 : 1;
pos += len;
while (pos < buf_len) {
int cp;
len = utf8BytesToCodePoint(buf + pos, buf_len - pos, &cp);
if (!isCombiningChar(cp)) return pos - beg;
pos += len;
}
return pos - beg;
}
/* Get length of previous grapheme
*/
size_t linenoiseUtf8PrevCharLen(const char* buf, size_t buf_len, size_t pos, size_t *col_len) {
UNUSED(buf_len);
size_t end = pos;
while (pos > 0) {
size_t len = prevUtf8CharLen(buf, pos);
pos -= len;
int cp;
utf8BytesToCodePoint(buf + pos, len, &cp);
if (!isCombiningChar(cp)) {
if (col_len != NULL) *col_len = isWideChar(cp) ? 2 : 1;
return end - pos;
}
}
/* NOTREACHED */
return 0;
}
/* Read a Unicode from file.
*/
size_t linenoiseUtf8ReadCode(int fd, char* buf, size_t buf_len, int* cp) {
if (buf_len < 1) return -1;
size_t nread = read(fd,&buf[0],1);
if (nread <= 0) return nread;
unsigned char byte = buf[0];
if ((byte & 0x80) == 0) {
;
} else if ((byte & 0xE0) == 0xC0) {
if (buf_len < 2) return -1;
nread = read(fd,&buf[1],1);
if (nread <= 0) return nread;
} else if ((byte & 0xF0) == 0xE0) {
if (buf_len < 3) return -1;
nread = read(fd,&buf[1],2);
if (nread <= 0) return nread;
} else if ((byte & 0xF8) == 0xF0) {
if (buf_len < 3) return -1;
nread = read(fd,&buf[1],3);
if (nread <= 0) return nread;
} else {
return -1;
}
return utf8BytesToCodePoint(buf, buf_len, cp);
}
+55
View File
@@ -0,0 +1,55 @@
/* encodings/utf8.h -- VERSION 1.0
*
* Guerrilla line editing library against the idea that a line editing lib
* needs to be 20,000 lines of C code.
*
* See linenoise.c for more information.
*
* ------------------------------------------------------------------------
*
* Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com>
* Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LINENOISE_ENCODINGS_UTF8_H
#define __LINENOISE_ENCODINGS_UTF8_H
#ifdef __cplusplus
extern "C" {
#endif
size_t linenoiseUtf8PrevCharLen(const char* buf, size_t buf_len, size_t pos, size_t *col_len);
size_t linenoiseUtf8NextCharLen(const char* buf, size_t buf_len, size_t pos, size_t *col_len);
size_t linenoiseUtf8ReadCode(int fd, char* buf, size_t buf_len, int* cp);
#ifdef __cplusplus
}
#endif
#endif /* __LINENOISE_ENCODINGS_UTF8_H */
+32
View File
@@ -0,0 +1,32 @@
local L = require 'linenoise'
-- L.clearscreen()
print '----- Testing lua-linenoise! ------'
local prompt, history = '? ', 'history.txt'
L.historyload(history) -- load existing history
L.setcompletion(function(c,s)
if s == 'h' then
c:add('help') -- same as L.addcompletion(c,'help)
L.addcompletion(c,'halt') -- same as c:add('halt')
end
end)
L.sethints(function(s)
if s == 'h' then
return ' test hint'
end
end)
L.enableutf8()
local line, err = L.linenoise(prompt)
while line do
if #line > 0 then
print(line:upper())
L.historyadd(line)
L.historysave(history) -- save every new line
end
line, err = L.linenoise(prompt)
end
if err then
print('An error occurred: ' .. err)
end
+19
View File
@@ -0,0 +1,19 @@
#ifndef _REDIS_FMACRO_H
#define _REDIS_FMACRO_H
#define _BSD_SOURCE
#if defined(__linux__) || defined(__OpenBSD__)
#define _XOPEN_SOURCE 700
#else
#define _XOPEN_SOURCE
#endif
#define _LARGEFILE_SOURCE
#define _FILE_OFFSET_BITS 64
#ifdef _WIN32
#define off off_t
#endif
#endif
@@ -0,0 +1,33 @@
package = 'linenoise'
version = '0.9-1'
source = {
url = 'https://github.com/hoelzro/lua-linenoise/archive/0.9.tar.gz',
dir = 'lua-linenoise-0.9',
}
description = {
summary = 'A binding for the linenoise command line library',
homepage = 'https://github.com/hoelzro/lua-linenoise',
license = 'MIT/X11',
}
dependencies = {
'lua >= 5.1'
}
build = {
type = 'builtin',
modules = {
linenoise = {
sources = { 'linenoise.c', 'linenoiselib.c', 'encodings/utf8.c' },
},
},
platforms = {
win32 = {
modules = {
linenoise = {
sources = { 'linenoise.c', 'linenoiselib.c', 'encodings/utf8.c', 'win32fixes.c' },
libraries = { 'ws2_32' },
},
},
},
},
}
+376
View File
@@ -0,0 +1,376 @@
/* vim:sts=4 sw=4 expandtab
*/
/*
* Copyright (c) 2011-2015 Rob Hoelz <rob@hoelz.ro>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <lua.h>
#include <lauxlib.h>
#include <stdlib.h>
#include <string.h>
#include "linenoise.h"
#include "encodings/utf8.h"
#define LN_COMPLETION_TYPE "linenoiseCompletions*"
#ifdef _WIN32
#define LN_EXPORT __declspec(dllexport)
#else
#define LN_EXPORT extern
#endif
#ifndef LUA_OK
#define LUA_OK 0
#endif
static int completion_func_ref = LUA_NOREF;
static int hints_func_ref = LUA_NOREF;
static lua_State *completion_state;
static int callback_error_ref;
static int handle_ln_error(lua_State *L)
{
lua_pushnil(L);
return 1;
}
static int handle_ln_ok(lua_State *L)
{
lua_pushboolean(L, 1);
return 1;
}
static int completion_callback_wrapper(const char *line, linenoiseCompletions *completions)
{
lua_State *L = completion_state;
int status;
lua_rawgeti(L, LUA_REGISTRYINDEX, completion_func_ref);
*((linenoiseCompletions **) lua_newuserdata(L, sizeof(linenoiseCompletions *))) = completions;
luaL_getmetatable(L, LN_COMPLETION_TYPE);
lua_setmetatable(L, -2);
lua_pushstring(L, line);
status = lua_pcall(L, 2, 0, 0);
if(status == LUA_OK) {
return 0;
} else {
lua_rawseti(L, LUA_REGISTRYINDEX, callback_error_ref);
return 1;
}
}
static char *
hints_callback_wrapper(const char *line, int *color, int *bold, int *err)
{
lua_State *L = completion_state;
char *result = NULL;
int status;
lua_rawgeti(L, LUA_REGISTRYINDEX, hints_func_ref);
lua_pushstring(L, line);
status = lua_pcall(L, 1, 2, 0);
if(status != LUA_OK) {
lua_rawseti(L, LUA_REGISTRYINDEX, callback_error_ref);
*err = 1;
return NULL;
}
if(!lua_isnoneornil(L, -2)) {
if(lua_isstring(L, -2)) {
const char *hint;
lua_Alloc alloc_f;
void *ud;
hint = lua_tostring(L, -2);
alloc_f = lua_getallocf(L, &ud);
result = alloc_f(&ud, NULL, LUA_TSTRING, strlen(hint) + 1);
if(result) {
strcpy(result, hint);
}
} else {
lua_pushfstring(L, "Invalid first value of type '%s' from hints callback - string or nil required", lua_typename(L, lua_type(L, -2)));
lua_rawseti(L, LUA_REGISTRYINDEX, callback_error_ref);
*err = 1;
lua_pop(L, 2);
return NULL;
}
if(!lua_isnoneornil(L, -1)) {
if(lua_istable(L, -1)) {
lua_getfield(L, -1, "color");
if(lua_isnumber(L, -1)) {
*color = lua_tointeger(L, -1);
} else if(!lua_isnoneornil(L, -1)) {
lua_pushfstring(L, "Invalid color value of type '%s' from hints callback - number or nil required", lua_typename(L, lua_type(L, -1)));
lua_rawseti(L, LUA_REGISTRYINDEX, callback_error_ref);
*err = 1;
lua_pop(L, 3);
// return the result to allow linenoise to free it
return result;
}
lua_pop(L, 1);
lua_getfield(L, -1, "bold");
*bold = lua_toboolean(L, -1);
lua_pop(L, 1);
} else {
lua_pushfstring(L, "Invalid second value of type '%s' from hints callback - table or nil required", lua_typename(L, lua_type(L, -1)));
lua_rawseti(L, LUA_REGISTRYINDEX, callback_error_ref);
*err = 1;
lua_pop(L, 2);
// return the result to allow linenoise to free it
return result;
}
}
}
lua_pop(L, 2);
return result;
}
static void
free_hints_callback(void *p)
{
lua_State *L = completion_state;
lua_Alloc alloc_f;
void *ud;
alloc_f = lua_getallocf(L, &ud);
alloc_f(ud, p, 0, 0);
}
static int l_linenoise(lua_State *L)
{
const char *prompt = luaL_checkstring(L, 1);
char *line;
completion_state = L;
lua_pushliteral(L, "");
lua_rawseti(L, LUA_REGISTRYINDEX, callback_error_ref);
line = linenoise(prompt);
completion_state = NULL;
lua_rawgeti(L, LUA_REGISTRYINDEX, callback_error_ref);
if(strlen(lua_tostring(L, -1)) != 0) {
lua_pushnil(L);
lua_insert(L, -2);
if(line) {
linenoiseFree(line);
}
return 2;
}
if(! line) {
return handle_ln_error(L);
}
lua_pushstring(L, line);
linenoiseFree(line);
return 1;
}
static int lines_next(lua_State *L)
{
lua_pushcfunction(L, l_linenoise);
lua_pushvalue(L, lua_upvalueindex(1));
lua_call(L, 1, 1);
return 1;
}
static int l_lines(lua_State *L)
{
luaL_checkstring(L, 1);
lua_pushcclosure(L, lines_next, 1);
return 1;
}
static int l_historyadd(lua_State *L)
{
const char *line = luaL_checkstring(L, 1);
if(! linenoiseHistoryAdd(line)) {
return handle_ln_error(L);
}
return handle_ln_ok(L);
}
static int l_historysetmaxlen(lua_State *L)
{
int len = luaL_checkinteger(L, 1);
if(! linenoiseHistorySetMaxLen(len)) {
return handle_ln_error(L);
}
return handle_ln_ok(L);
}
static int l_historysave(lua_State *L)
{
const char *filename = luaL_checkstring(L, 1);
if(linenoiseHistorySave((char *) filename) < 0) {
return handle_ln_error(L);
}
return handle_ln_ok(L);
}
static int l_historyload(lua_State *L)
{
const char *filename = luaL_checkstring(L, 1);
if(linenoiseHistoryLoad((char *) filename) < 0) {
return handle_ln_error(L);
}
return handle_ln_ok(L);
}
static int l_clearscreen(lua_State *L)
{
linenoiseClearScreen();
return handle_ln_ok(L);
}
static int l_setcompletion(lua_State *L)
{
if(lua_isnoneornil(L, 1)) {
luaL_unref(L, LUA_REGISTRYINDEX, completion_func_ref);
completion_func_ref = LUA_NOREF;
linenoiseSetCompletionCallback(NULL);
} else {
luaL_checktype(L, 1, LUA_TFUNCTION);
lua_pushvalue(L, 1);
if(completion_func_ref == LUA_NOREF) {
completion_func_ref = luaL_ref(L, LUA_REGISTRYINDEX);
} else {
lua_rawseti(L, LUA_REGISTRYINDEX, completion_func_ref);
}
linenoiseSetCompletionCallback(completion_callback_wrapper);
}
return handle_ln_ok(L);
}
static int l_addcompletion(lua_State *L)
{
linenoiseCompletions *completions = *((linenoiseCompletions **) luaL_checkudata(L, 1, LN_COMPLETION_TYPE));
const char *entry = luaL_checkstring(L, 2);
linenoiseAddCompletion(completions, (char *) entry);
return handle_ln_ok(L);
}
static int
l_setmultiline(lua_State *L)
{
int is_multi_line = lua_toboolean(L, 1);
linenoiseSetMultiLine(is_multi_line);
return handle_ln_ok(L);
}
static int
l_sethints(lua_State *L)
{
if(lua_isnoneornil(L, 1)) {
luaL_unref(L, LUA_REGISTRYINDEX, hints_func_ref);
hints_func_ref = LUA_NOREF;
linenoiseSetHintsCallback(NULL);
linenoiseSetFreeHintsCallback(NULL);
} else {
luaL_checktype(L, 1, LUA_TFUNCTION);
lua_pushvalue(L, 1);
if(hints_func_ref == LUA_NOREF) {
hints_func_ref = luaL_ref(L, LUA_REGISTRYINDEX);
} else {
lua_rawseti(L, LUA_REGISTRYINDEX, hints_func_ref);
}
linenoiseSetHintsCallback(hints_callback_wrapper);
linenoiseSetFreeHintsCallback(free_hints_callback);
}
return handle_ln_ok(L);
}
luaL_Reg linenoise_funcs[] = {
{ "linenoise", l_linenoise },
{ "historyadd", l_historyadd },
{ "historysetmaxlen", l_historysetmaxlen },
{ "historysave", l_historysave },
{ "historyload", l_historyload },
{ "clearscreen", l_clearscreen },
{ "setcompletion", l_setcompletion},
{ "addcompletion", l_addcompletion },
{ "setmultiline", l_setmultiline },
{ "sethints", l_sethints },
/* Aliases for more consistent function names */
{ "addhistory", l_historyadd },
{ "sethistorymaxlen", l_historysetmaxlen },
{ "savehistory", l_historysave },
{ "loadhistory", l_historyload },
{ "line", l_linenoise },
{ "lines", l_lines },
{ NULL, NULL }
};
luaL_Reg linenoise_methods[] = {
{ "add", l_addcompletion },
{ NULL, NULL }
};
LN_EXPORT int luaopen_linenoise(lua_State *L)
{
lua_pushliteral(L, "");
callback_error_ref = luaL_ref(L, LUA_REGISTRYINDEX);
lua_newtable(L);
luaL_newmetatable(L, LN_COMPLETION_TYPE);
lua_pushboolean(L, 0);
lua_setfield(L, -2, "__metatable");
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
#if LUA_VERSION_NUM > 501
luaL_setfuncs(L, linenoise_methods, 0);
lua_pop(L, 1);
luaL_setfuncs(L,linenoise_funcs,0);
#else
luaL_register(L, NULL, linenoise_methods);
lua_pop(L, 1);
luaL_register(L, NULL, linenoise_funcs);
#endif
return 1;
}
+82
View File
@@ -0,0 +1,82 @@
/* linenoise.h -- VERSION 1.0
*
* Guerrilla line editing library against the idea that a line editing lib
* needs to be 20,000 lines of C code.
*
* See linenoise.c for more information.
*
* ------------------------------------------------------------------------
*
* Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com>
* Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LINENOISE_H
#define __LINENOISE_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct linenoiseCompletions {
size_t len;
char **cvec;
} linenoiseCompletions;
typedef int(linenoiseCompletionCallback)(const char *, linenoiseCompletions *);
typedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold, int *err);
typedef void(linenoiseFreeHintsCallback)(void *);
void linenoiseSetCompletionCallback(linenoiseCompletionCallback *);
void linenoiseSetHintsCallback(linenoiseHintsCallback *);
void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *);
void linenoiseAddCompletion(linenoiseCompletions *, const char *);
char *linenoise(const char *prompt);
void linenoiseFree(void *ptr);
int linenoiseHistoryAdd(const char *line);
int linenoiseHistorySetMaxLen(int len);
int linenoiseHistorySave(const char *filename);
int linenoiseHistoryLoad(const char *filename);
void linenoiseClearScreen(void);
void linenoiseSetMultiLine(int ml);
void linenoisePrintKeyCodes(void);
typedef size_t (linenoisePrevCharLen)(const char *buf, size_t buf_len, size_t pos, size_t *col_len);
typedef size_t (linenoiseNextCharLen)(const char *buf, size_t buf_len, size_t pos, size_t *col_len);
typedef size_t (linenoiseReadCode)(int fd, char *buf, size_t buf_len, int* c);
void linenoiseSetEncodingFunctions(
linenoisePrevCharLen *prevCharLenFunc,
linenoiseNextCharLen *nextCharLenFunc,
linenoiseReadCode *readCodeFunc);
#ifdef __cplusplus
}
#endif
#endif /* __LINENOISE_H */
File diff suppressed because it is too large Load Diff
+47
View File
@@ -0,0 +1,47 @@
# Linenoise
A minimal, zero-config, BSD licensed, readline replacement.
News: linenoise now includes minimal completion support, thanks to Pieter Noordhuis (@pnoordhuis).
News: linenoise is now part of [Android](http://android.git.kernel.org/?p=platform/system/core.git;a=tree;f=liblinenoise;h=56450eaed7f783760e5e6a5993ef75cde2e29dea;hb=HEAD Android)!
## Can a line editing library be 20k lines of code?
Line editing with some support for history is a really important feature for command line utilities. Instead of retyping almost the same stuff again and again it's just much better to hit the up arrow and edit on syntax errors, or in order to try a slightly different command. But apparently code dealing with terminals is some sort of Black Magic: readline is 30k lines of code, libedit 20k. Is it reasonable to link small utilities to huge libraries just to get a minimal support for line editing?
So what usually happens is either:
* Large programs with configure scripts disabling line editing if readline is not present in the system, or not supporting it at all since readline is GPL licensed and libedit (the BSD clone) is not as known and available as readline is (Readl world example of this problem: Tclsh).
* Smaller programs not using a configure script not supporting line editing at all (A problem we had with Redis-cli for instance).
The result is a pollution of binaries without line editing support.
So I spent more or less two hours doing a reality check resulting in this little library: is it *really* needed for a line editing library to be 20k lines of code? Apparently not, it is possibe to get a very small, zero configuration, trivial to embed library, that solves the problem. Smaller programs will just include this, supporing line editing out of the box. Larger programs may use this little library or just checking with configure if readline/libedit is available and resorting to linenoise if not.
## Terminals, in 2010.
Apparently almost every terminal you can happen to use today has some kind of support for VT100 alike escape sequences. So I tried to write a lib using just very basic VT100 features. The resulting library appears to work everywhere I tried to use it.
Since it's so young I guess there are a few bugs, or the lib may not compile or work with some operating system, but it's a matter of a few weeks and eventually we'll get it right, and there will be no excuses for not shipping command line tools without built-in line editing support.
The library is currently less than 400 lines of code. In order to use it in your project just look at the *example.c* file in the source distribution, it is trivial. Linenoise is BSD code, so you can use both in free software and commercial software.
## Tested with...
* Linux text only console ($TERM = linux)
* Linux KDE terminal application ($TERM = xterm)
* Linux xterm ($TERM = xterm)
* Mac OS X iTerm ($TERM = xterm)
* Mac OS X default Terminal.app ($TERM = xterm)
* OpenBSD 4.5 through an OSX Terminal.app ($TERM = screen)
* IBM AIX 6.1
* FreeBSD xterm ($TERM = xterm)
Please test it everywhere you can and report back!
## Let's push this forward!
Please fork it and add something interesting and send me a pull request. What's especially interesting are fixes, new key bindings, completion.
Send feedbacks to antirez at gmail
+539
View File
@@ -0,0 +1,539 @@
/*
* Modified by Henry Rawas (henryr@schakra.com)
* - make it compatible with Visual Studio builds
* - added wstrtod to handle INF, NAN
* - added gettimeofday routine
* - modified rename to retry after failure
*/
#if defined(_WIN32) && !defined(__MINGW32__) /* MinGW doesn't like this file */
#include <process.h>
#include <stdlib.h>
#include <errno.h>
#ifndef FD_SETSIZE
#define FD_SETSIZE 16000
#endif
#include <winsock2.h>
#include <windows.h>
#include <signal.h>
#include <time.h>
#include <locale.h>
#include <math.h>
#include "win32fixes.h"
/* Redefined here to avoid redis.h so it can be used in other projects */
#define REDIS_NOTUSED(V) ((void) V)
#define REDIS_THREAD_STACK_SIZE (1024*1024*4)
/* Winsock requires library initialization on startup */
int w32initWinSock(void) {
WSADATA t_wsa;
WORD wVers;
int iError;
wVers = MAKEWORD(2, 2);
iError = WSAStartup(wVers, &t_wsa);
if(iError != NO_ERROR || LOBYTE(t_wsa.wVersion) != 2 || HIBYTE(t_wsa.wVersion) != 2 ) {
return 0; /* not done; check WSAGetLastError() for error number */
};
return 1;
}
/* Behaves as posix, works without ifdefs, makes compiler happy */
int sigaction(int sig, struct sigaction *in, struct sigaction *out) {
REDIS_NOTUSED(out);
/* When the SA_SIGINFO flag is set in sa_flags then sa_sigaction
* is used. Otherwise, sa_handler is used */
if (in->sa_flags & SA_SIGINFO)
signal(sig, in->sa_sigaction);
else
signal(sig, in->sa_handler);
return 0;
}
/* Terminates process, implemented only for SIGKILL */
int kill(pid_t pid, int sig) {
if (sig == SIGKILL) {
HANDLE h = OpenProcess(PROCESS_TERMINATE, 0, pid);
if (!TerminateProcess(h, 127)) {
errno = EINVAL; /* GetLastError() */
CloseHandle(h);
return -1;
};
CloseHandle(h);
return 0;
} else {
errno = EINVAL;
return -1;
};
}
/* Forced write to disk */
int fsync (int fd) {
HANDLE h = (HANDLE) _get_osfhandle(fd);
DWORD err;
if (h == INVALID_HANDLE_VALUE) {
errno = EBADF;
return -1;
}
if (!FlushFileBuffers(h)) {
/* Windows error -> Unix */
err = GetLastError();
switch (err) {
case ERROR_INVALID_HANDLE:
errno = EINVAL;
break;
default:
errno = EIO;
}
return -1;
}
return 0;
}
/* Missing wait3() implementation */
pid_t wait3(int *stat_loc, int options, void *rusage) {
REDIS_NOTUSED(stat_loc);
REDIS_NOTUSED(options);
REDIS_NOTUSED(rusage);
return (pid_t) waitpid((intptr_t) -1, 0, WAIT_FLAGS);
}
/* Replace MS C rtl rand which is 15bit with 32 bit */
int replace_random() {
unsigned int x=0;
if (RtlGenRandom == NULL) {
// load proc if not loaded
HMODULE lib = LoadLibraryA("advapi32.dll");
RtlGenRandom = (RtlGenRandomFunc)GetProcAddress(lib, "SystemFunction036");
if (RtlGenRandom == NULL) return 1;
}
RtlGenRandom(&x, sizeof(UINT_MAX));
return (int)(x >> 1);
}
/* BSD sockets compatibile replacement */
int replace_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen) {
return (setsockopt)((SOCKET)socket, level, optname, (const char *)optval, optlen);
}
/* set size with 64bit support */
int replace_ftruncate(int fd, off64_t length) {
HANDLE h = (HANDLE) _get_osfhandle (fd);
LARGE_INTEGER l, o;
if (h == INVALID_HANDLE_VALUE) {
errno = EBADF;
return -1;
}
l.QuadPart = length;
if (!SetFilePointerEx(h, l, &o, FILE_BEGIN)) return -1;
if (!SetEndOfFile(h)) return -1;
return 0;
}
/* Rename which works on Windows when file exists */
int replace_rename(const char *src, const char *dst) {
/* anti-virus may lock file - error code 5. Retry until it works or get a different error */
int retries = 50;
while (1) {
if (MoveFileEx(src, dst, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH)) {
return 0;
} else {
errno = GetLastError();
if (errno != 5) break;
retries--;
if (retries == 0) {
retries = 50;
Sleep(10);
}
}
}
/* On error we will return generic error code without GetLastError() */
return -1;
}
/* Proxy structure to pass func and arg to thread */
typedef struct thread_params
{
void *(*func)(void *);
void * arg;
} thread_params;
/* Proxy function by windows thread requirements */
static unsigned __stdcall win32_proxy_threadproc(void *arg) {
thread_params *p = (thread_params *) arg;
p->func(p->arg);
/* Dealocate params */
free(p);
_endthreadex(0);
return 0;
}
int pthread_create(pthread_t *thread, const void *unused,
void *(*start_routine)(void*), void *arg) {
HANDLE h;
thread_params *params = (thread_params *)malloc(sizeof(thread_params));
REDIS_NOTUSED(unused);
params->func = start_routine;
params->arg = arg;
h =(HANDLE) _beginthreadex(NULL, /* Security not used */
REDIS_THREAD_STACK_SIZE, /* Set custom stack size */
win32_proxy_threadproc, /* calls win32 stdcall proxy */
params, /* real threadproc is passed as paremeter */
STACK_SIZE_PARAM_IS_A_RESERVATION, /* reserve stack */
thread /* returned thread id */
);
if (!h)
return errno;
CloseHandle(h);
return 0;
}
/* Noop in windows */
int pthread_detach (pthread_t thread) {
REDIS_NOTUSED(thread);
return 0; /* noop */
}
pthread_t pthread_self(void) {
return GetCurrentThreadId();
}
int win32_pthread_join(pthread_t *thread, void **value_ptr) {
int result;
HANDLE h = OpenThread(SYNCHRONIZE, FALSE, *thread);
REDIS_NOTUSED(value_ptr);
switch (WaitForSingleObject(h, INFINITE)) {
case WAIT_OBJECT_0:
result = 0;
case WAIT_ABANDONED:
result = EINVAL;
default:
result = GetLastError();
}
CloseHandle(h);
return result;
}
int pthread_cond_init(pthread_cond_t *cond, const void *unused) {
REDIS_NOTUSED(unused);
cond->waiters = 0;
cond->was_broadcast = 0;
InitializeCriticalSection(&cond->waiters_lock);
cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
if (!cond->sema) {
errno = GetLastError();
return -1;
}
cond->continue_broadcast = CreateEvent(NULL, /* security */
FALSE, /* auto-reset */
FALSE, /* not signaled */
NULL); /* name */
if (!cond->continue_broadcast) {
errno = GetLastError();
return -1;
}
return 0;
}
int pthread_cond_destroy(pthread_cond_t *cond) {
CloseHandle(cond->sema);
CloseHandle(cond->continue_broadcast);
DeleteCriticalSection(&cond->waiters_lock);
return 0;
}
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) {
int last_waiter;
EnterCriticalSection(&cond->waiters_lock);
cond->waiters++;
LeaveCriticalSection(&cond->waiters_lock);
/*
* Unlock external mutex and wait for signal.
* NOTE: we've held mutex locked long enough to increment
* waiters count above, so there's no problem with
* leaving mutex unlocked before we wait on semaphore.
*/
LeaveCriticalSection(mutex);
/* let's wait - ignore return value */
WaitForSingleObject(cond->sema, INFINITE);
/*
* Decrease waiters count. If we are the last waiter, then we must
* notify the broadcasting thread that it can continue.
* But if we continued due to cond_signal, we do not have to do that
* because the signaling thread knows that only one waiter continued.
*/
EnterCriticalSection(&cond->waiters_lock);
cond->waiters--;
last_waiter = cond->was_broadcast && cond->waiters == 0;
LeaveCriticalSection(&cond->waiters_lock);
if (last_waiter) {
/*
* cond_broadcast was issued while mutex was held. This means
* that all other waiters have continued, but are contending
* for the mutex at the end of this function because the
* broadcasting thread did not leave cond_broadcast, yet.
* (This is so that it can be sure that each waiter has
* consumed exactly one slice of the semaphor.)
* The last waiter must tell the broadcasting thread that it
* can go on.
*/
SetEvent(cond->continue_broadcast);
/*
* Now we go on to contend with all other waiters for
* the mutex. Auf in den Kampf!
*/
}
/* lock external mutex again */
EnterCriticalSection(mutex);
return 0;
}
/*
* IMPORTANT: This implementation requires that pthread_cond_signal
* is called while the mutex is held that is used in the corresponding
* pthread_cond_wait calls!
*/
int pthread_cond_signal(pthread_cond_t *cond) {
int have_waiters;
EnterCriticalSection(&cond->waiters_lock);
have_waiters = cond->waiters > 0;
LeaveCriticalSection(&cond->waiters_lock);
/*
* Signal only when there are waiters
*/
if (have_waiters)
return ReleaseSemaphore(cond->sema, 1, NULL) ?
0 : GetLastError();
else
return 0;
}
/* Redis forks to perform background writing */
/* fork() on unix will split process in two */
/* marking memory pages as Copy-On-Write so */
/* child process will have data snapshot. */
/* Windows has no support for fork(). */
int fork(void) {
return -1;
}
/* Redis CPU GetProcessTimes -> rusage */
int getrusage(int who, struct rusage * r) {
FILETIME starttime, exittime, kerneltime, usertime;
ULARGE_INTEGER li;
if (r == NULL) {
errno = EFAULT;
return -1;
}
memset(r, 0, sizeof(struct rusage));
if (who == RUSAGE_SELF) {
if (!GetProcessTimes(GetCurrentProcess(),
&starttime,
&exittime,
&kerneltime,
&usertime))
{
errno = EFAULT;
return -1;
}
}
if (who == RUSAGE_CHILDREN) {
/* Childless on windows */
starttime.dwLowDateTime = 0;
starttime.dwHighDateTime = 0;
exittime.dwLowDateTime = 0;
exittime.dwHighDateTime = 0;
kerneltime.dwLowDateTime = 0;
kerneltime.dwHighDateTime = 0;
usertime.dwLowDateTime = 0;
usertime.dwHighDateTime = 0;
}
memcpy(&li, &kerneltime, sizeof(FILETIME));
li.QuadPart /= 10L;
r->ru_stime.tv_sec = (long)(li.QuadPart / 1000000L);
r->ru_stime.tv_usec = (long)(li.QuadPart % 1000000L);
memcpy(&li, &usertime, sizeof(FILETIME));
li.QuadPart /= 10L;
r->ru_utime.tv_sec = (long)(li.QuadPart / 1000000L);
r->ru_utime.tv_usec = (long)(li.QuadPart % 1000000L);
return 0;
}
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
struct timezone
{
int tz_minuteswest; /* minutes W of Greenwich */
int tz_dsttime; /* type of dst correction */
};
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
FILETIME ft;
unsigned __int64 tmpres = 0;
static int tzflag;
if (NULL != tv)
{
GetSystemTimeAsFileTime(&ft);
tmpres |= ft.dwHighDateTime;
tmpres <<= 32;
tmpres |= ft.dwLowDateTime;
/*converting file time to unix epoch*/
tmpres -= DELTA_EPOCH_IN_MICROSECS;
tmpres /= 10; /*convert into microseconds*/
tv->tv_sec = (long)(tmpres / 1000000UL);
tv->tv_usec = (long)(tmpres % 1000000UL);
}
if (NULL != tz)
{
if (!tzflag)
{
_tzset();
tzflag++;
}
tz->tz_minuteswest = _timezone / 60;
tz->tz_dsttime = _daylight;
}
return 0;
}
static _locale_t clocale = NULL;
double wstrtod(const char *nptr, char **eptr) {
double d;
char *leptr;
if (clocale == NULL)
clocale = _create_locale(LC_ALL, "C");
d = _strtod_l(nptr, &leptr, clocale);
/* if 0, check if input was inf */
if (d == 0 && nptr == leptr) {
int neg = 0;
while (isspace(*nptr))
nptr++;
if (*nptr == '+')
nptr++;
else if (*nptr == '-') {
nptr++;
neg = 1;
}
if (strnicmp("INF", nptr, 3) == 0) {
if (eptr != NULL) {
if (strnicmp("INFINITE", nptr, 8) == 0)
*eptr = (char*)(nptr + 8);
else
*eptr = (char*)(nptr + 3);
}
if (neg == 1)
return -HUGE_VAL;
else
return HUGE_VAL;
} else if (strnicmp("NAN", nptr, 3) == 0) {
if (eptr != NULL)
*eptr = (char*)(nptr + 3);
/* create a NaN : 0 * infinity*/
d = HUGE_VAL;
return d * 0;
}
}
if (eptr != NULL)
*eptr = leptr;
return d;
}
int strerror_r(int err, char* buf, size_t buflen) {
int size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
err,
0,
buf,
(DWORD)buflen,
NULL);
if (size == 0) {
char* strerr = strerror(err);
if (strlen(strerr) >= buflen) {
errno = ERANGE;
return -1;
}
strcpy(buf, strerr);
}
if (size > 2 && buf[size - 2] == '\r') {
/* remove extra CRLF */
buf[size - 2] = '\0';
}
return 0;
}
char wsa_strerror_buf[128];
char *wsa_strerror(int err) {
int size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
err,
0,
wsa_strerror_buf,
128,
NULL);
if (size == 0) return strerror(err);
if (size > 2 && wsa_strerror_buf[size - 2] == '\r') {
/* remove extra CRLF */
wsa_strerror_buf[size - 2] = '\0';
}
return wsa_strerror_buf;
}
#endif
+318
View File
@@ -0,0 +1,318 @@
/*
* Modified by Henry Rawas (henryr@schakra.com)
* - make it compatible with Visual Studio builds
* - added wstrtod to handle INF, NAN
* - added support for using IOCP with sockets
*/
#ifndef WIN32FIXES_H
#define WIN32FIXES_H
#ifdef WIN32
#ifndef _WIN32
#define _WIN32
#endif
#endif
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define NOGDI
#define __USE_W32_SOCKETS
#include "fmacros.h"
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <signal.h>
#include <sys/types.h>
#ifndef FD_SETSIZE
#define FD_SETSIZE 16000
#endif
#include <winsock2.h> /* setsocketopt */
#include <ws2tcpip.h>
#include <windows.h>
#include <float.h>
#include <fcntl.h> /* _O_BINARY */
#include <limits.h> /* INT_MAX */
#include <process.h>
#include <sys/types.h>
#define fseeko fseeko64
#define ftello ftello64
#define inline __inline
#undef ftruncate
#define ftruncate replace_ftruncate
#ifndef off64_t
#define off64_t off_t
#endif
int replace_ftruncate(int fd, off64_t length);
#define snprintf _snprintf
#define ftello64 _ftelli64
#define fseeko64 _fseeki64
#define strcasecmp _stricmp
#define strtoll _strtoi64
#define isnan _isnan
#define isfinite _finite
#define isinf(x) (!_finite(x))
#define lseek64 lseek
/* following defined to choose little endian byte order */
#define __i386__ 1
#if !defined(va_copy)
#define va_copy(d,s) d = (s)
#endif
#define sleep(x) Sleep((x)*1000)
#ifndef __RTL_GENRANDOM
#define __RTL_GENRANDOM 1
typedef BOOLEAN (_stdcall* RtlGenRandomFunc)(void * RandomBuffer, ULONG RandomBufferLength);
#endif
RtlGenRandomFunc RtlGenRandom;
#define random() (long)replace_random()
#define rand() replace_random()
int replace_random();
#if !defined(ssize_t)
typedef int ssize_t;
#endif
#if !defined(mode_t)
#define mode_t long
#endif
#if !defined(u_int32_t)
/* sha1 */
typedef unsigned __int32 u_int32_t;
#endif
/* Redis calls usleep(1) to give thread some time
* Sleep(0) should do the same on windows
* In other cases, usleep is called with milisec resolution,
* which can be directly translated to winapi Sleep() */
#undef usleep
#define usleep(x) (x == 1) ? Sleep(0) : Sleep((int)((x)/1000))
#define pipe(fds) _pipe(fds, 8192, _O_BINARY|_O_NOINHERIT)
/* Processes */
#define waitpid(pid,statusp,options) _cwait (statusp, pid, WAIT_CHILD)
#define WAIT_T int
#define WTERMSIG(x) ((x) & 0xff) /* or: SIGABRT ?? */
#define WCOREDUMP(x) 0
#define WEXITSTATUS(x) (((x) >> 8) & 0xff) /* or: (x) ?? */
#define WIFSIGNALED(x) (WTERMSIG (x) != 0) /* or: ((x) == 3) ?? */
#define WIFEXITED(x) (WTERMSIG (x) == 0) /* or: ((x) != 3) ?? */
#define WIFSTOPPED(x) 0
#define WNOHANG 1
/* file mapping */
#define PROT_READ 1
#define PROT_WRITE 2
#define MAP_FAILED (void *) -1
#define MAP_SHARED 1
#define MAP_PRIVATE 2
/* rusage */
#define RUSAGE_SELF 0
#define RUSAGE_CHILDREN (-1)
#ifndef _RUSAGE_T_
#define _RUSAGE_T_
struct rusage {
struct timeval ru_utime; /* user time used */
struct timeval ru_stime; /* system time used */
};
#endif
int getrusage(int who, struct rusage * rusage);
/* Signals */
#define SIGNULL 0 /* Null Check access to pid*/
#define SIGHUP 1 /* Hangup Terminate; can be trapped*/
#define SIGINT 2 /* Interrupt Terminate; can be trapped */
#define SIGQUIT 3 /* Quit Terminate with core dump; can be trapped */
#define SIGTRAP 5
#define SIGBUS 7
#define SIGKILL 9 /* Kill Forced termination; cannot be trapped */
#define SIGPIPE 13
#define SIGALRM 14
#define SIGTERM 15 /* Terminate Terminate; can be trapped */
#define SIGSTOP 17
#define SIGTSTP 18
#define SIGCONT 19
#define SIGCHLD 20
#define SIGTTIN 21
#define SIGTTOU 22
#define SIGABRT 22
/* #define SIGSTOP 24 /*Pause the process; cannot be trapped*/
/* #define SIGTSTP 25 /*Terminal stop Pause the process; can be trapped*/
/* #define SIGCONT 26 */
#define SIGWINCH 28
#define SIGUSR1 30
#define SIGUSR2 31
#define ucontext_t void*
#define SA_NOCLDSTOP 0x00000001u
#define SA_NOCLDWAIT 0x00000002u
#define SA_SIGINFO 0x00000004u
#define SA_ONSTACK 0x08000000u
#define SA_RESTART 0x10000000u
#define SA_NODEFER 0x40000000u
#define SA_RESETHAND 0x80000000u
#define SA_NOMASK SA_NODEFER
#define SA_ONESHOT SA_RESETHAND
#define SA_RESTORER 0x04000000
#define sigemptyset(pset) (*(pset) = 0)
#define sigfillset(pset) (*(pset) = (unsigned int)-1)
#define sigaddset(pset, num) (*(pset) |= (1L<<(num)))
#define sigdelset(pset, num) (*(pset) &= ~(1L<<(num)))
#define sigismember(pset, num) (*(pset) & (1L<<(num)))
#ifndef SIG_SETMASK
#define SIG_SETMASK (0)
#define SIG_BLOCK (1)
#define SIG_UNBLOCK (2)
#endif /*SIG_SETMASK*/
typedef void (*__p_sig_fn_t)(int);
typedef int pid_t;
#ifndef _SIGSET_T_
#define _SIGSET_T_
#ifdef _WIN64
typedef unsigned long long _sigset_t;
#else
typedef unsigned long _sigset_t;
#endif
# define sigset_t _sigset_t
#endif /* _SIGSET_T_ */
struct sigaction {
int sa_flags;
sigset_t sa_mask;
__p_sig_fn_t sa_handler;
__p_sig_fn_t sa_sigaction;
};
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
/* Sockets */
#ifndef ECONNRESET
#define ECONNRESET WSAECONNRESET
#endif
#ifndef EINPROGRESS
#define EINPROGRESS WSAEINPROGRESS
#endif
#ifndef ETIMEDOUT
#define ETIMEDOUT WSAETIMEDOUT
#endif
#define setsockopt(a,b,c,d,e) replace_setsockopt(a,b,c,d,e)
int replace_setsockopt(int socket, int level, int optname,
const void *optval, socklen_t optlen);
#define rename(a,b) replace_rename(a,b)
int replace_rename(const char *src, const char *dest);
//threads avoiding pthread.h
#define pthread_mutex_t CRITICAL_SECTION
#define pthread_attr_t ssize_t
#define pthread_mutex_init(a,b) (InitializeCriticalSectionAndSpinCount((a), 0x80000400),0)
#define pthread_mutex_destroy(a) DeleteCriticalSection((a))
#define pthread_mutex_lock EnterCriticalSection
#define pthread_mutex_unlock LeaveCriticalSection
#define pthread_equal(t1, t2) ((t1) == (t2))
#define pthread_attr_init(x) (*(x) = 0)
#define pthread_attr_getstacksize(x, y) (*(y) = *(x))
#define pthread_attr_setstacksize(x, y) (*(x) = y)
#define pthread_t u_int
int pthread_create(pthread_t *thread, const void *unused,
void *(*start_routine)(void*), void *arg);
pthread_t pthread_self(void);
typedef struct {
CRITICAL_SECTION waiters_lock;
LONG waiters;
int was_broadcast;
HANDLE sema;
HANDLE continue_broadcast;
} pthread_cond_t;
int pthread_cond_init(pthread_cond_t *cond, const void *unused);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_detach (pthread_t thread);
/* Misc Unix -> Win32 */
int kill(pid_t pid, int sig);
int fsync (int fd);
pid_t wait3(int *stat_loc, int options, void *rusage);
int w32initWinSock(void);
/* int inet_aton(const char *cp_arg, struct in_addr *addr) */
/* redis-check-dump */
void *mmap(void *start, size_t length, int prot, int flags, int fd, off offset);
int munmap(void *start, size_t length);
int fork(void);
int gettimeofday(struct timeval *tv, struct timezone *tz);
/* strtod does not handle Inf and Nan
We need to do the check before calling strtod */
#undef strtod
#define strtod(nptr, eptr) wstrtod((nptr), (eptr))
double wstrtod(const char *nptr, char **eptr);
/* structs and functions for using IOCP with windows sockets */
/* need callback on write complete. aeWinSendReq is used to pass parameters */
typedef struct aeWinSendReq {
void *client;
void *data;
char *buf;
int len;
} aeWinSendReq;
int aeWinSocketAttach(int fd);
int aeWinSocketDetach(int fd, int shutd);
int aeWinReceiveDone(int fd);
int aeWinSocketSend(int fd, char *buf, int len, int flags,
void *eventLoop, void *client, void *data, void *proc);
int aeWinListen(SOCKET sock, int backlog);
int aeWinAccept(int fd, struct sockaddr *sa, socklen_t *len);
int strerror_r(int err, char* buf, size_t buflen);
char *wsa_strerror(int err);
#endif /* WIN32 */
#endif /* WIN32FIXES_H */