Merge pull request #2419 from keymanapp/feat/developer/2101-kmdecomp

feat(developer): add kmdecomp
This commit is contained in:
Marc Durdin 2019-12-07 05:39:07 +01:00 committed by GitHub
commit 175bb404b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 142 additions and 58 deletions

View file

@ -3,7 +3,7 @@
#
TARGETS=kmcmpdll kmcomp kmanalyze kmconvert tike samples setup inst
TARGETS=kmcmpdll kmcomp kmanalyze kmconvert tike samples setup inst kmdecomp
MANIFESTS=kmcomp tike setup
CLEANS=clean-developer
@ -19,6 +19,10 @@ kmcmpdll:
cd $(ROOT)\src\developer\kmcmpdll
$(MAKE) $(TARGET)
kmdecomp:
cd $(ROOT)\src\developer\kmdecomp
$(MAKE) $(TARGET)
kmcomp: kmcmpdll
cd $(ROOT)\src\developer\kmcomp
$(MAKE) $(TARGET)

View file

@ -2,6 +2,7 @@
## 13.0 alpha
* Start version 13.0
* Feature: Add unsupported kmdecomp decompiler utility (#2419)
## 2019-11-18 12.0.55 stable
* Bug Fix: Some keyboards were incorrectly marked as mobile-capable (#2334)

View file

@ -166,6 +166,14 @@
<RegistryValue Root="HKCR" Key="KeymanDeveloper.File.OnScreenKeyboard\Shell\edit\Command" Type="string" Value='"[#tike.exe]" "%1"' />
</Component>
<Component>
<File Name="kmdecomp.exe" KeyPath="yes" />
</Component>
<Component>
<File Name="kmdecomp.md" KeyPath="yes" Source="..\..\developer\kmdecomp\kmdecomp.md" />
</Component>
<Component>
<File Name="kmcomp.exe" KeyPath="yes" />
</Component>

View file

@ -0,0 +1,28 @@
#
# kmdecomp Makefile
#
!include ..\..\Defines.mak
build: version.res dirs
$(MSBUILD) kmdecomp.sln $(MSBUILD_BUILD) /p:Platform=Win32
$(COPY) $(WIN32_TARGET_PATH)\kmdecomp.exe $(PROGRAM)\developer
$(COPY) $(WIN32_TARGET_PATH)\kmdecomp.pdb $(DEBUGPATH)\developer
clean: def-clean
$(MSBUILD) kmdecomp.sln $(MSBUILD_CLEAN)
signcode:
$(SIGNCODE) /d "Keyman Developer Decompiler" $(PROGRAM)\developer\kmdecomp.exe
backup:
$(WZZIP) $(BUILD)\developer\kmdecomp.zip $(BACKUPDEFAULTS) $(PROGRAM)\developer\kmdecomp.exe
test-manifest:
@rem This target needed as dependency for KMDECOMP
install:
$(COPY) $(PROGRAM)\developer\kmdecomp.exe "$(INSTALLPATH_KEYMANDEVELOPER)\kmdecomp.exe"
!include ..\..\Target.mak

View file

@ -57,9 +57,9 @@ int main(int argc, char *argv[])
if(!LoadKeyboard(argv[1], &kbd, &lpBitmap, &cbBitmap)) return 2;
_splitpath(argv[1], drive, dir, filename, NULL);
_makepath(buf, drive, dir, filename, ".kmn");
_makepath(buf2, drive, dir, filename, ".bmp");
_splitpath_s(argv[1], drive, _MAX_DRIVE, dir, _MAX_DIR, filename, _MAX_FNAME, NULL, 0);
_makepath_s(buf, _MAX_PATH, drive, dir, filename, ".kmn");
_makepath_s(buf2, _MAX_PATH, drive, dir, filename, ".bmp");
int n = SaveKeyboardSource(kbd, lpBitmap, cbBitmap, buf, buf2);

View file

@ -0,0 +1,9 @@
# kmdecomp Keyman Decompiler
This unsupported utility decompiles a Keyman .kmx keyboard.
It will produce a .kmn source file and optionally a .ico or
.bmp image. The source file may not contain symbols and will
include optimisations that were made by the compiler such as
expanding `any()` rules in key components into multiple rules.
Usage: kmdecomp <infile.kmx>

View file

@ -41,11 +41,8 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
@ -54,6 +51,13 @@
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Midl>
<TypeLibraryName>.\Debug/kmdecomp.tlb</TypeLibraryName>
@ -64,13 +68,8 @@
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\global\inc;..\..\resellers;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeaderOutputFile>.\Debug/kmdecomp.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
<ObjectFileName>.\Debug/</ObjectFileName>
<ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
@ -80,10 +79,8 @@
<Culture>0x0c09</Culture>
</ResourceCompile>
<Link>
<OutputFile>.\Debug/kmdecomp.exe</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>.\Debug/kmdecomp.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<TreatWarningAsError>true</TreatWarningAsError>
@ -107,10 +104,6 @@
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeaderOutputFile>.\Release/kmdecomp.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Release/</AssemblerListingLocation>
<ObjectFileName>.\Release/</ObjectFileName>
<ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TreatWarningAsError>true</TreatWarningAsError>
@ -120,9 +113,7 @@
<Culture>0x0c09</Culture>
</ResourceCompile>
<Link>
<OutputFile>.\Release/kmdecomp.exe</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<ProgramDatabaseFile>.\Release/kmdecomp.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<TreatWarningAsError>true</TreatWarningAsError>
@ -152,6 +143,9 @@
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="version.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View file

@ -25,4 +25,9 @@
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="version.rc">
<Filter>Source Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View file

@ -43,9 +43,9 @@ void SaveBitmapFile(LPBYTE lpBitmap, DWORD cbBitmap, char *bmpfile);
LPKEYBOARD g_kbd;
PWCHAR wcscat2(PWCHAR c1, const PWCHAR c2)
PWCHAR wcscat2(PWCHAR c1, size_t sz, const PWCHAR c2)
{
wcscat(c1, c2);
wcscat_s(c1, sz, c2);
return wcschr(c1, 0);
}
@ -134,23 +134,23 @@ PWCHAR flagstr(int flag)
{
static WCHAR buf[256];
*buf = 0;
if(flag & LCTRLFLAG) wcscat2(buf, L"LCTRL ");
if(flag & RCTRLFLAG) wcscat2(buf, L"RCTRL ");
if(flag & LALTFLAG) wcscat2(buf, L"LALT ");
if(flag & RALTFLAG) wcscat2(buf, L"RALT ");
if(flag & K_SHIFTFLAG) wcscat2(buf, L"SHIFT ");
if(flag & K_CTRLFLAG) wcscat2(buf, L"CTRL ");
if(flag & K_ALTFLAG) wcscat2(buf, L"ALT ");
if(flag & CAPITALFLAG) wcscat2(buf, L"CAPS ");
if(flag & NOTCAPITALFLAG) wcscat2(buf, L"NCAPS ");
if(flag & NUMLOCKFLAG) wcscat2(buf, L"NUM ");
if(flag & NOTNUMLOCKFLAG) wcscat2(buf, L"NNUM ");
if(flag & SCROLLFLAG) wcscat2(buf, L"SCROLL ");
if(flag & NOTSCROLLFLAG) wcscat2(buf, L"NSCROLL ");
if(flag & LCTRLFLAG) wcscat2(buf, _countof(buf), L"LCTRL ");
if(flag & RCTRLFLAG) wcscat2(buf, _countof(buf), L"RCTRL ");
if(flag & LALTFLAG) wcscat2(buf, _countof(buf), L"LALT ");
if(flag & RALTFLAG) wcscat2(buf, _countof(buf), L"RALT ");
if(flag & K_SHIFTFLAG) wcscat2(buf, _countof(buf), L"SHIFT ");
if(flag & K_CTRLFLAG) wcscat2(buf, _countof(buf), L"CTRL ");
if(flag & K_ALTFLAG) wcscat2(buf, _countof(buf), L"ALT ");
if(flag & CAPITALFLAG) wcscat2(buf, _countof(buf), L"CAPS ");
if(flag & NOTCAPITALFLAG) wcscat2(buf, _countof(buf), L"NCAPS ");
if(flag & NUMLOCKFLAG) wcscat2(buf, _countof(buf), L"NUM ");
if(flag & NOTNUMLOCKFLAG) wcscat2(buf, _countof(buf), L"NNUM ");
if(flag & SCROLLFLAG) wcscat2(buf, _countof(buf), L"SCROLL ");
if(flag & NOTSCROLLFLAG) wcscat2(buf, _countof(buf), L"NSCROLL ");
return buf;
}
PWCHAR GetVKeyName(LPKEY key) // I3438
PCWCHAR GetVKeyName(LPKEY key) // I3438
{
static WCHAR buf[100];
if(key->Key <= VK__MAX)
@ -187,9 +187,10 @@ PWCHAR ifvalue(WCHAR ch)
return L"=";
}
#define BUFSIZE 512
PWCHAR ExtString(PWCHAR str)
{
static WCHAR buf[2][512], bufpointer = 0; // allows for multiple strings in one printf
static WCHAR buf[2][BUFSIZE], bufpointer = 0; // allows for multiple strings in one printf
// dodgy hack?
PWCHAR p;
@ -203,7 +204,7 @@ PWCHAR ExtString(PWCHAR str)
if(*str == UC_SENTINEL)
{
str++;
if(inquotes) p = wcscat2(p, L"\" ");
if(inquotes) p = wcscat2(p, BUFSIZE, L"\" ");
inquotes = 0;
switch(*str)
{
@ -219,10 +220,10 @@ PWCHAR ExtString(PWCHAR str)
p = wcschr(p, 0);
break;
case CODE_CONTEXT:
p = wcscat2(p, L"context ");
p = wcscat2(p, BUFSIZE, L"context ");
break;
case CODE_NUL:
p = wcscat2(p, L"nul ");
p = wcscat2(p, BUFSIZE, L"nul ");
break;
case CODE_USE:
str++;
@ -230,10 +231,10 @@ PWCHAR ExtString(PWCHAR str)
p = wcschr(p, 0);
break;
case CODE_RETURN:
p = wcscat2(p, L"return ");
p = wcscat2(p, BUFSIZE, L"return ");
break;
case CODE_BEEP:
p = wcscat2(p, L"beep ");
p = wcscat2(p, BUFSIZE, L"beep ");
break;
case CODE_DEADKEY:
str++;
@ -257,13 +258,13 @@ PWCHAR ExtString(PWCHAR str)
p = wcschr(p, 0);
break;
case CODE_SWITCH:
p = wcscat2(p, L"switch<deprecated> ");
p = wcscat2(p, BUFSIZE, L"switch<deprecated> ");
break;
case CODE_KEY:
p = wcscat2(p, L"key<deprecated> ");
p = wcscat2(p, BUFSIZE, L"key<deprecated> ");
break;
case CODE_CLEARCONTEXT:
p = wcscat2(p, L"clearcontext ");
p = wcscat2(p, BUFSIZE, L"clearcontext ");
break;
case CODE_CALL:
str++;
@ -321,7 +322,7 @@ PWCHAR ExtString(PWCHAR str)
break;
default:
p = wcscat2(p, L"unknown() ");
p = wcscat2(p, BUFSIZE, L"unknown() ");
break;
}
}
@ -329,13 +330,13 @@ PWCHAR ExtString(PWCHAR str)
{
if(*str == L'"')
{
if(inquotes) p = wcscat2(p, L"\" ");
if(inquotes) p = wcscat2(p, BUFSIZE, L"\" ");
inquotes = 0;
p = wcscat2(p, L"'\"' ");
p = wcscat2(p, BUFSIZE, L"'\"' ");
}
else if(*str < 32)
{
if(inquotes) p = wcscat2(p, L"\" ");
if(inquotes) p = wcscat2(p, BUFSIZE, L"\" ");
inquotes = 0;
wsprintfW(p, L"x%x ", *str);
p = wcschr(p, 0);
@ -345,7 +346,7 @@ PWCHAR ExtString(PWCHAR str)
if(!inquotes)
{
inquotes = 1;
p = wcscat2(p, L"\"");
p = wcscat2(p, BUFSIZE, L"\"");
}
*p++ = *str;
*p = 0;
@ -353,7 +354,7 @@ PWCHAR ExtString(PWCHAR str)
}
}
if(inquotes) p = wcscat2(p, L"\" ");
if(inquotes) p = wcscat2(p, BUFSIZE, L"\" ");
return buf[bufpointer];
}
@ -376,10 +377,12 @@ int SaveKeyboardSource(LPKEYBOARD kbd, LPBYTE lpBitmap, DWORD cbBitmap, char *fi
g_kbd = kbd;
fp = fopen(filename, "wb");
fwrite(UTF16Sig, 2, 1, fp);
if (fopen_s(&fp, filename, "wb") != 0) {
Err("Unable to create output file.");
return 3;
}
if(!fp) { Err("Unable to create output file."); return 3; }
fwrite(UTF16Sig, 2, 1, fp);
wsprintfW(buf, L"c Keyboard created by KMDECOMP\n"); wr(fp, buf);
wsprintfW(buf, L"c\n"); wr(fp, buf);
@ -450,7 +453,9 @@ int SaveKeyboardSource(LPKEYBOARD kbd, LPBYTE lpBitmap, DWORD cbBitmap, char *fi
void SaveBitmapFile(LPBYTE lpBitmap, DWORD cbBitmap, char *bmpfile)
{
FILE * fp = fopen(bmpfile, "wb");
fwrite(lpBitmap, cbBitmap, 1, fp);
fclose(fp);
FILE *fp;
if (fopen_s(&fp, bmpfile, "wb") == 0) {
fwrite(lpBitmap, cbBitmap, 1, fp);
fclose(fp);
}
}

View file

@ -0,0 +1,30 @@
1 VERSIONINFO
FILEVERSION $VERSIONNUM
PRODUCTVERSION $VERSIONNUM
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "0C0904E4"
BEGIN
VALUE "CompanyName", "SIL International\0"
VALUE "FileDescription", "Keyman decompiler\0"
VALUE "FileVersion", "$VERSION\0"
VALUE "InternalName", "KMDECOMP\0"
VALUE "LegalCopyright", "<22> SIL International\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "KMDECOMP.EXE\0"
VALUE "ProductName", "Keyman Developer\0"
VALUE "ProductVersion", "$VERSION\0"
VALUE "Comments", "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0xc09, 1252
END
END