chore(developer): refactor kmcmplib interfaces

Relates to #8493.

* Removes kmcmplib calls from kmcmpdll (now that we have kmc)
* Removes old kmcmp_CompileKeyboardFile and
  kmcmp_CompileKeyboardFileToBuffer functions in preference for a much
  cleaner kmcmp_CompileKeyboard function
* Removes json validation helper from kmcmplib (we'll use js-native
  json schema validation instead)

This change means that we no longer need to keep compfile.h consistent
between kmcmplib and kmcmpdll. This will simplify upcoming refactoring
of kmcmplib.

kmcmplib no longer writes files, but it does still read them. The next
refactor will move file load responsibility into the caller.
This commit is contained in:
Marc Durdin 2023-05-30 08:14:23 +07:00
parent a92917f947
commit d763cf315a
15 changed files with 158 additions and 356 deletions

View file

@ -409,7 +409,6 @@ typedef COMP_GROUP *PCOMP_GROUP;
typedef struct _COMPILER_OPTIONS {
DWORD dwSize;
BOOL ShouldAddCompilerVersion;
BOOL UseKmcmpLib;
} COMPILER_OPTIONS;
typedef COMPILER_OPTIONS *PCOMPILER_OPTIONS;

View file

@ -176,7 +176,6 @@ type
TCompilerOptions = record
dwSize: DWORD;
ShouldAddCompilerVersion: BOOL;
UseKmcmpLib: BOOL;
end;
COMPILER_OPTIONS = TCompilerOptions;

View file

@ -114,14 +114,17 @@ export class KmnCompiler {
private runCompiler(infile: string, outfile: string, options: CompilerOptions): CompilerResult {
let result: CompilerResult = {};
let wasm_interface = new this.Module.CompilerInterface();
let wasm_options = new this.Module.CompilerOptions();
let wasm_result = null;
try {
wasm_interface.saveDebug = options.saveDebug;
wasm_interface.compilerWarningsAsErrors = options.compilerWarningsAsErrors;
wasm_interface.warnDeprecatedCode = options.warnDeprecatedCode;
wasm_options.saveDebug = options.saveDebug;
wasm_options.compilerWarningsAsErrors = options.compilerWarningsAsErrors;
wasm_options.warnDeprecatedCode = options.warnDeprecatedCode;
wasm_options.shouldAddCompilerVersion = options.shouldAddCompilerVersion;
wasm_options.target = 0; //CKF_KEYMAN; TODO, support KMW
wasm_interface.messageCallback = this.callbackName;
wasm_interface.loadFileCallback = this.callbackName; // TODO: this is wrong, needs to be a new callback; not yet used though
wasm_result = this.Module.kmcmp_compile(infile, wasm_interface);
wasm_result = this.Module.kmcmp_compile(infile, wasm_options, wasm_interface);
if(!wasm_result.result) {
return null;
}
@ -147,6 +150,7 @@ export class KmnCompiler {
wasm_result.delete();
}
wasm_interface.delete();
wasm_options.delete();
}
}

View file

@ -86,20 +86,20 @@ describe('Compiler class', function() {
const kmxFixture = fixtureDir + '/binary/caps_lock_layer_3620.kmx';
const kvkFixture = fixtureDir + '/binary/caps_lock_layer_3620.kvk';
const kmxfile = __dirname + '/caps_lock_layer_3620.kmx';
const kvkfile = __dirname + '/caps_lock_layer_3620.kvk';
const resultingKmxfile = __dirname + '/caps_lock_layer_3620.kmx';
const resultingKvkfile = __dirname + '/caps_lock_layer_3620.kvk';
assert(compiler.run(infile, kmxfile, {saveDebug: true, shouldAddCompilerVersion: false}));
assert(compiler.run(infile, resultingKmxfile, {saveDebug: true, shouldAddCompilerVersion: false}));
assert(fs.existsSync(kmxfile));
assert(fs.existsSync(kvkfile));
assert(fs.existsSync(resultingKmxfile));
assert(fs.existsSync(resultingKvkfile));
const kmxData = fs.readFileSync(kmxfile);
const kmxData = fs.readFileSync(resultingKmxfile);
const kmxFixtureData = fs.readFileSync(kmxFixture);
assert.equal(kmxData.byteLength, kmxFixtureData.byteLength);
assert.deepEqual(kmxData, kmxFixtureData);
const kvkData = fs.readFileSync(kvkfile);
const kvkData = fs.readFileSync(resultingKvkfile);
const kvkFixtureData = fs.readFileSync(kvkFixture);
assert.equal(kvkData.byteLength, kvkFixtureData.byteLength);
assert.deepEqual(kvkData, kvkFixtureData);

View file

@ -90,8 +90,6 @@
#include "UnreachableRules.h"
#include "CheckForDuplicates.h"
#include "../kmcmplib/include/kmcmplibapi.h"
int xatoi(PWSTR *p);
int atoiW(PWSTR p);
void safe_wcsncpy(PWSTR out, PWSTR in, int cbMax);
@ -291,33 +289,15 @@ BOOL AddCompileMessage(DWORD msg)
return FALSE;
}
bool flag_use_new_kmcomp = true; // flag to switch to new kmcompx
extern "C" BOOL __declspec(dllexport) SetCompilerOptions(PCOMPILER_OPTIONS options) {
if(!options || options->dwSize < sizeof(COMPILER_OPTIONS)) {
return FALSE;
}
flag_use_new_kmcomp = options->UseKmcmpLib;
//printf("\n---> started in SetCompilerOptions() of kmcmpdll\n");
if ( flag_use_new_kmcomp )
{
KMCMP_COMPILER_OPTIONS kmcmp_options = {0};
kmcmp_options.dwSize = sizeof(KMCMP_COMPILER_OPTIONS);
kmcmp_options.ShouldAddCompilerVersion = options->ShouldAddCompilerVersion;
return kmcmp_SetCompilerOptions(&kmcmp_options);
}
//printf("---> stayed in SetCompilerOptions() of kmcmpdll\n");
FShouldAddCompilerVersion = options->ShouldAddCompilerVersion;
return TRUE;
}
int kmcmpMsgproc(int line, uint32_t dwMsgCode, char* szText, void* context) {
return static_cast<CompilerMessageProc>(context)(line, dwMsgCode, szText);
}
extern "C" BOOL __declspec(dllexport) CompileKeyboardFile(PSTR pszInfile, PSTR pszOutfile, BOOL ASaveDebug, BOOL ACompilerWarningsAsErrors, BOOL AWarnDeprecatedCode, CompilerMessageProc pMsgProc) // I4865 // I4866
{
HANDLE hInfile = INVALID_HANDLE_VALUE, hOutfile = INVALID_HANDLE_VALUE;
@ -325,15 +305,6 @@ extern "C" BOOL __declspec(dllexport) CompileKeyboardFile(PSTR pszInfile, PSTR p
DWORD len;
char str[260];
//printf("\n---> started in CompileKeyboardFile() of kmcmpdll\n");
if ( flag_use_new_kmcomp )
{
return kmcmp_CompileKeyboardFile(pszInfile, pszOutfile, ASaveDebug, ACompilerWarningsAsErrors,AWarnDeprecatedCode, kmcmpMsgproc, (void*) pMsgProc);
}
//printf("---> stayed in CompileKeyboardFile() of kmcmpdll\n");
FSaveDebug = ASaveDebug;
FCompilerWarningsAsErrors = ACompilerWarningsAsErrors; // I4865
FWarnDeprecatedCode = AWarnDeprecatedCode; // I4866
@ -418,15 +389,6 @@ extern "C" BOOL __declspec(dllexport) CompileKeyboardFileToBuffer(PSTR pszInfile
DWORD len;
char str[260];
//printf("\n---> started in CompileKeyboardFileToBuffer() of kmcmpdll\n");
if ( flag_use_new_kmcomp )
{
return kmcmp_CompileKeyboardFileToBuffer( pszInfile, (void*) pfkBuffer, ACompilerWarningsAsErrors, AWarnDeprecatedCode, kmcmpMsgproc, (void*) pMsgProc, Target);
}
//printf("---> stayed in CompileKeyboardFileToBuffer() of kmcmpdll\n");
FSaveDebug = TRUE; // I3681
FCompilerWarningsAsErrors = ACompilerWarningsAsErrors; // I4865
FWarnDeprecatedCode = AWarnDeprecatedCode; // I4866

View file

@ -1,14 +1,11 @@
#include <json-schema.hpp>
#include <fstream>
#include "../kmcmplib/include/kmcmplibapi.h"
#include <windows.h>
typedef bool (*kmcmp_ValidateJsonMessageProc)(int64_t offset, const char* szText, void* context);
extern bool flag_use_new_kmcomp;
using nlohmann::json;
using nlohmann::json_uri;
using nlohmann::json_schema_draft4::json_validator;
@ -35,13 +32,6 @@ bool kmcmpMessageProc(int64_t offset, const char* szText, void* context) {
extern "C" BOOL __declspec(dllexport) ValidateJsonFile(PWSTR pwszSchemaFile, PWSTR pwszJsonFile, ValidateJsonMessageProc MessageProc) {
if ( flag_use_new_kmcomp )
{
std::fstream f(pwszSchemaFile);
std::fstream fd(pwszJsonFile);
return kmcmp_ValidateJsonFile(f, fd, kmcmpMessageProc, (void*)MessageProc);
}
std::fstream f(pwszSchemaFile);
if (!f.good()) {
MessageProc(-1, "Schema file could not be loaded.");

View file

@ -89,25 +89,25 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(KEYMAN_ROOT)\developer\src\common\include;$(KEYMAN_ROOT)\developer\src\ext\json;$(KEYMAN_ROOT)\developer\src\ext\json-schema-validator</IncludePath>
<OutDir>$(ProjectDir)bin\$(Platform)\$(Configuration)\</OutDir>
<LibraryPath>$(KEYMAN_ROOT)\developer\src\kmcmplib\build\x86\$(Configuration)\src;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(KEYMAN_ROOT)\developer\src\common\include;$(KEYMAN_ROOT)\developer\src\ext\json;$(KEYMAN_ROOT)\developer\src\ext\json-schema-validator</IncludePath>
<IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\</IntDir>
<TargetName>$(ProjectName).x64</TargetName>
<OutDir>$(ProjectDir)bin\$(Platform)\$(Configuration)\</OutDir>
<LibraryPath>$(KEYMAN_ROOT)\developer\src\kmcmplib\build\x64\$(Configuration)\src;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(KEYMAN_ROOT)\developer\src\common\include;$(KEYMAN_ROOT)\developer\src\ext\json;$(KEYMAN_ROOT)\developer\src\ext\json-schema-validator</IncludePath>
<LibraryPath>$(KEYMAN_ROOT)\developer\src\kmcmplib\build\x86\$(Configuration)\src;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(KEYMAN_ROOT)\developer\src\common\include;$(KEYMAN_ROOT)\developer\src\ext\json;$(KEYMAN_ROOT)\developer\src\ext\json-schema-validator</IncludePath>
<IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\</IntDir>
<TargetName>$(ProjectName).x64</TargetName>
<OutDir>$(ProjectDir)bin\$(Platform)\$(Configuration)\</OutDir>
<LibraryPath>$(KEYMAN_ROOT)\developer\src\kmcmplib\build\x64\$(Configuration)\src;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Midl>
@ -142,7 +142,7 @@
<AdditionalIncludeDirectories>$(KEYMAN_ROOT)\windows\src\global\inc</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<AdditionalDependencies>libkmcmplib.a;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SuppressStartupBanner>true</SuppressStartupBanner>
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>
@ -190,7 +190,7 @@
<AdditionalIncludeDirectories>$(KEYMAN_ROOT)\windows\src\global\inc</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<AdditionalDependencies>libkmcmplib.a;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SuppressStartupBanner>true</SuppressStartupBanner>
<GenerateMapFile>true</GenerateMapFile>
<SubSystem>Windows</SubSystem>
@ -233,7 +233,7 @@
<AdditionalIncludeDirectories>$(KEYMAN_ROOT)\windows\src\global\inc</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<AdditionalDependencies>libkmcmplib.a;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SuppressStartupBanner>true</SuppressStartupBanner>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>
@ -277,7 +277,7 @@
<AdditionalIncludeDirectories>$(KEYMAN_ROOT)\windows\src\global\inc</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<AdditionalDependencies>libkmcmplib.a;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SuppressStartupBanner>true</SuppressStartupBanner>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateMapFile>true</GenerateMapFile>

View file

@ -16,49 +16,48 @@
#define EXTERN EMSCRIPTEN_KEEPALIVE
#endif
typedef struct _KMCMP_COMPILER_OPTIONS {
uint32_t dwSize;
bool ShouldAddCompilerVersion;
} KMCMP_COMPILER_OPTIONS;
EXTERN bool kmcmp_SetCompilerOptions(
KMCMP_COMPILER_OPTIONS* options
);
typedef int (*kmcmp_CompilerMessageProc)(int line, uint32_t dwMsgCode, char* szText, void* context);
EXTERN bool kmcmp_CompileKeyboardFile(
char* pszInfile,
char* pszOutfile,
bool ASaveDebug,
bool ACompilerWarningsAsErrors,
bool AWarnDeprecatedCode,
kmcmp_CompilerMessageProc pMsgproc,
void* AmsgprocContext
);
/* Compile target */
#define CKF_KEYMAN 0
#define CKF_KEYMANWEB 1
EXTERN bool kmcmp_CompileKeyboardFileToBuffer(
char* pszInfile,
void* pfkBuffer,
bool ACompilerWarningsAsErrors,
bool AWarnDeprecatedCode,
kmcmp_CompilerMessageProc pMsgproc,
void* AmsgprocContext,
int Target
);
struct KMCMP_COMPILER_OPTIONS {
bool saveDebug;
bool compilerWarningsAsErrors;
bool warnDeprecatedCode;
bool shouldAddCompilerVersion;
int target; // CKF_KEYMAN, CKF_KEYMANWEB
};
typedef bool (*kmcmp_ValidateJsonMessageProc)(int64_t offset, const char* szText, void* context);
struct KMCMP_COMPILER_RESULT {
void* kmx;
size_t kmxSize;
std::string kvksFilename;
};
EXTERN bool kmcmp_ValidateJsonFile(
std::fstream& f,
std::fstream& fd,
kmcmp_ValidateJsonMessageProc MessageProc,
void* context
// TODO: parameters in UTF-8
typedef int (*kmcmp_CompilerMessageProc)(int line, uint32_t dwMsgCode, char* szText, void* context);
// parameters in UTF-8
// TODO typical usage:
// if(!kmcmp_LoadFileProc("filename.ico", "/tmp/filename.kmn", nullptr, &size)) {
// return error;
// }
// buf = new unsigned char[size];
// if(!kmcmp_LoadFileProc("filename.ico", "/tmp/filename.kmn", buf, &size)) {
// delete[] buf;
// return error;
// }
typedef bool (*kmcmp_LoadFileProc)(char* loadFilename, char* baseFilename, void* buffer, int* bufferSize);
// Parameters in UTF-8
EXTERN bool kmcmp_CompileKeyboard(
const char* pszInfile,
const KMCMP_COMPILER_OPTIONS& options,
kmcmp_CompilerMessageProc messageProc,
kmcmp_LoadFileProc loadFileProc,
const void* procContext,
KMCMP_COMPILER_RESULT& result
);
/**

View file

@ -20,7 +20,5 @@ configure_file(
inc = include_directories(
'.',
'../../common/include',
'../../../../common/include',
'../../ext/json',
'../../ext/json-schema-validator'
'../../../../common/include'
)

View file

@ -12,19 +12,6 @@
#include "../../../../common/windows/cpp/include/keymanversion.h"
bool CompileKeyboardHandle(FILE* fp_in, PFILE_KEYBOARD fk);
bool CompileKeyboard(const char* pszInfile,
void* pfkBuffer, bool ASaveDebug, bool ACompilerWarningsAsErrors,
bool AWarnDeprecatedCode, kmcmp_CompilerMessageProc pMsgproc, const void* AmsgprocContext,
int Target);
EXTERN bool kmcmp_SetCompilerOptions(KMCMP_COMPILER_OPTIONS* options) {
//printf("°°-> changed to SetCompilerOptions() of kmcmplib \n");
if(!options || options->dwSize < sizeof(KMCMP_COMPILER_OPTIONS)) {
return FALSE;
}
kmcmp::FShouldAddCompilerVersion = options->ShouldAddCompilerVersion;
return TRUE;
}
#ifdef __EMSCRIPTEN__
@ -46,17 +33,12 @@ int wasm_CompilerMessageProc(int line, uint32_t dwMsgCode, char* szText, void* c
return wasm_msgproc(line, dwMsgCode, szText, msgProc);
}
struct COMPILER_INTERFACE {
bool saveDebug;
bool compilerWarningsAsErrors;
bool warnDeprecatedCode;
bool shouldAddCompilerVersion;
int target; // CKF_KEYMAN, CKF_KEYMANWEB
struct WASM_COMPILER_INTERFACE {
std::string messageCallback; // int line, uint32_t dwMsgCode, char* szText
std::string loadFileCallback; // char* infile, char* filenameRelativeToInfile --> buffer
std::string loadFileCallback; // TODO: char* filename, char* baseFilename --> buffer
};
struct COMPILER_RESULT {
struct WASM_COMPILER_RESULT {
bool result;
// Following are pointer offsets in heap + buffer size
int kmx;
@ -67,104 +49,101 @@ struct COMPILER_RESULT {
// TODO: additional data to be passed back
};
COMPILER_RESULT kmcmp_compile(std::string pszInfile, const COMPILER_INTERFACE intf) {
COMPILER_RESULT r = {false};
WASM_COMPILER_RESULT kmcmp_wasm_compile(std::string pszInfile, const KMCMP_COMPILER_OPTIONS options, const WASM_COMPILER_INTERFACE intf) {
WASM_COMPILER_RESULT r = {false};
KMCMP_COMPILER_RESULT kr;
FILE_KEYBOARD fk;
r.kmx = 0;
r.kmxSize = 0;
r.kvksFilename = "";
// TODO: this should be included in CompileKeyboard?
kmcmp::FShouldAddCompilerVersion = intf.shouldAddCompilerVersion;
r.result = CompileKeyboard(
r.result = kmcmp_CompileKeyboard(
pszInfile.c_str(),
&fk,
intf.saveDebug,
intf.compilerWarningsAsErrors,
intf.warnDeprecatedCode,
options,
wasm_CompilerMessageProc,
nullptr, //wasm_LoadFileProc,
intf.messageCallback.c_str(),
intf.target);
kr
);
if(!r.result) {
return r;
if(r.result) {
// TODO: additional data as required by kmc_kmw
r.kmx = (int) kr.kmx;
r.kmxSize = (int) kr.kmxSize;
r.kvksFilename = kr.kvksFilename;
}
KMX_DWORD msg;
KMX_BYTE* data = nullptr;
size_t dataSize = 0;
msg = WriteCompiledKeyboard(&fk, &data, dataSize);
//TODO: FreeKeyboardPointers(fk);
if(msg != CERR_None) {
AddCompileError(msg);
r.result = FALSE;
return r;
}
r.kmx = (int) data;
r.kmxSize = (int) dataSize;
r.kvksFilename = string_from_u16string(fk.extra->kvksFilename); // convert to UTF8
return r;
}
EMSCRIPTEN_BINDINGS(compiler_interface) {
emscripten::class_<COMPILER_INTERFACE>("CompilerInterface")
emscripten::class_<KMCMP_COMPILER_OPTIONS>("CompilerOptions")
.constructor<>()
.property("saveDebug", &COMPILER_INTERFACE::saveDebug)
.property("compilerWarningsAsErrors", &COMPILER_INTERFACE::compilerWarningsAsErrors)
.property("warnDeprecatedCode", &COMPILER_INTERFACE::warnDeprecatedCode)
.property("shouldAddCompilerVersion", &COMPILER_INTERFACE::shouldAddCompilerVersion)
.property("target", &COMPILER_INTERFACE::target)
.property("messageCallback", &COMPILER_INTERFACE::messageCallback)
.property("loadFileCallback", &COMPILER_INTERFACE::loadFileCallback)
.property("saveDebug", &KMCMP_COMPILER_OPTIONS::saveDebug)
.property("compilerWarningsAsErrors", &KMCMP_COMPILER_OPTIONS::compilerWarningsAsErrors)
.property("warnDeprecatedCode", &KMCMP_COMPILER_OPTIONS::warnDeprecatedCode)
.property("shouldAddCompilerVersion", &KMCMP_COMPILER_OPTIONS::shouldAddCompilerVersion)
.property("target", &KMCMP_COMPILER_OPTIONS::target)
;
emscripten::class_<COMPILER_RESULT>("CompilerResult")
emscripten::class_<WASM_COMPILER_INTERFACE>("CompilerInterface")
.constructor<>()
.property("result", &COMPILER_RESULT::result)
.property("kmx", &COMPILER_RESULT::kmx)
.property("kmxSize", &COMPILER_RESULT::kmxSize)
.property("kvksFilename", &COMPILER_RESULT::kvksFilename)
.property("messageCallback", &WASM_COMPILER_INTERFACE::messageCallback)
.property("loadFileCallback", &WASM_COMPILER_INTERFACE::loadFileCallback)
;
emscripten::function("kmcmp_compile", &kmcmp_compile);
emscripten::class_<WASM_COMPILER_RESULT>("CompilerResult")
.constructor<>()
.property("result", &WASM_COMPILER_RESULT::result)
.property("kmx", &WASM_COMPILER_RESULT::kmx)
.property("kmxSize", &WASM_COMPILER_RESULT::kmxSize)
.property("kvksFilename", &WASM_COMPILER_RESULT::kvksFilename)
;
emscripten::function("kmcmp_compile", &kmcmp_wasm_compile);
emscripten::function("kmcmp_parseUnicodeSet", &kmcmp_parseUnicodeSet);
}
#endif
bool CompileKeyboard(const char* pszInfile,
void* pfkBuffer, bool ASaveDebug, bool ACompilerWarningsAsErrors,
bool AWarnDeprecatedCode, kmcmp_CompilerMessageProc pMsgproc, const void* AmsgprocContext,
int Target) {
EXTERN bool kmcmp_CompileKeyboard(
const char* pszInfile,
const KMCMP_COMPILER_OPTIONS& options,
kmcmp_CompilerMessageProc messageProc,
kmcmp_LoadFileProc loadFileProc,
const void* procContext,
KMCMP_COMPILER_RESULT& result
) {
FILE* fp_in = NULL;
KMX_CHAR str[260];
FILE_KEYBOARD fk;
kmcmp::FSaveDebug = ASaveDebug; // I3681
kmcmp::FCompilerWarningsAsErrors = ACompilerWarningsAsErrors; // I4865
AWarnDeprecatedCode_GLOBAL_LIB = AWarnDeprecatedCode;
kmcmp::FSaveDebug = options.saveDebug; // I3681
kmcmp::FCompilerWarningsAsErrors = options.compilerWarningsAsErrors; // I4865
AWarnDeprecatedCode_GLOBAL_LIB = options.warnDeprecatedCode;
kmcmp::FShouldAddCompilerVersion = options.shouldAddCompilerVersion;
kmcmp::CompileTarget = options.target;
kmcmp::CompileTarget = Target;
if (!pMsgproc || !pszInfile || !pfkBuffer) {
if (!messageProc || !pszInfile) { // TODO: add loadFileProc
AddCompileError(CERR_BadCallParams);
return FALSE;
}
PKMX_STR p;
if ((p = strrchr_slash((char*)pszInfile)) != nullptr)
{
if ((p = strrchr_slash((char*)pszInfile)) != nullptr) {
strncpy(kmcmp::CompileDir, pszInfile, (int)(p - pszInfile + 1)); // I3481
kmcmp::CompileDir[(int)(p - pszInfile + 1)] = 0;
}
else
else {
kmcmp::CompileDir[0] = 0;
}
msgproc = pMsgproc;
msgprocContext = (void*)AmsgprocContext;
msgproc = messageProc;
//TODO: loadfileproc = loadFileProc;
msgprocContext = (void*)procContext;
kmcmp::currentLine = 0;
kmcmp::nErrors = 0;
@ -196,71 +175,32 @@ bool CompileKeyboard(const char* pszInfile,
}
kmcmp::CodeConstants = new kmcmp::NamedCodeConstants;
bool result = CompileKeyboardHandle(fp_in, static_cast<PFILE_KEYBOARD>(pfkBuffer));
bool success = CompileKeyboardHandle(fp_in, &fk);
delete kmcmp::CodeConstants;
fclose(fp_in);
if (kmcmp::nErrors > 0) {
return FALSE;
}
return result;
}
EXTERN bool kmcmp_CompileKeyboardFileToBuffer(char* pszInfile, void* pfkBuffer, bool ACompilerWarningsAsErrors, bool AWarnDeprecatedCode,
kmcmp_CompilerMessageProc pMsgproc, void* AmsgprocContext, int Target) // I4865 // I4866
{
if (!pMsgproc || !pszInfile || !pfkBuffer) {
AddCompileError(CERR_BadCallParams);
return FALSE;
}
return CompileKeyboard(pszInfile, pfkBuffer, TRUE, ACompilerWarningsAsErrors, AWarnDeprecatedCode,
pMsgproc, AmsgprocContext, Target);
}
EXTERN bool kmcmp_CompileKeyboardFile(char* pszInfile,
char* pszOutfile, bool ASaveDebug, bool ACompilerWarningsAsErrors,
bool AWarnDeprecatedCode, kmcmp_CompilerMessageProc pMsgproc, void* AmsgprocContext) // I4865 // I4866
{
if (!pMsgproc || !pszInfile || !pszOutfile) {
AddCompileError(CERR_BadCallParams);
return FALSE;
}
FILE_KEYBOARD fk;
if(!CompileKeyboard(pszInfile, &fk, ASaveDebug, ACompilerWarningsAsErrors, AWarnDeprecatedCode,
pMsgproc, AmsgprocContext, CKF_KEYMAN)) {
// any errors will have been reported directly by CompileKeyboard
return FALSE;
}
FILE* fp_out = Open_File(pszOutfile, "wb");
if (fp_out == NULL) {
AddCompileError(CERR_CannotCreateOutfile);
if (kmcmp::nErrors > 0 || !success) {
return FALSE;
}
// fill in result data
KMX_DWORD msg;
KMX_BYTE* data = nullptr;
size_t dataSize = 0;
if ((msg = WriteCompiledKeyboard(&fk, &data, dataSize)) != CERR_None) {
msg = WriteCompiledKeyboard(&fk, &data, dataSize);
//TODO: FreeKeyboardPointers(fk);
if(msg != CERR_None) {
AddCompileError(msg);
} else {
if(fwrite(data, 1, dataSize, fp_out) != dataSize) {
AddCompileError(CERR_UnableToWriteFully);
}
delete[] data;
}
fclose(fp_out);
if (kmcmp::nErrors > 0) {
remove(pszOutfile);
return FALSE;
}
result.kmx = data;
result.kmxSize = dataSize;
result.kvksFilename = string_from_u16string(fk.extra->kvksFilename); // convert to UTF8
return TRUE;
}

View file

@ -1,68 +0,0 @@
#include <json-schema.hpp>
#include <fstream>
#include <kmcmplibapi.h>
#include "kmcompx.h"
using nlohmann::json;
using nlohmann::json_uri;
using nlohmann::json_schema_draft4::json_validator;
static void loader(const json_uri &uri, json &schema)
{
std::fstream lf("." + uri.path());
if (!lf.good())
throw std::invalid_argument("could not open " + uri.url() + " tried with " + uri.path());
lf >> schema;
}
EXTERN bool kmcmp_ValidateJsonFile(std::fstream& f, std::fstream& fd, kmcmp_ValidateJsonMessageProc MessageProc, void* context) {
if (!f.good()) {
MessageProc(-1, "Schema file could not be loaded.", context);
return FALSE;
}
// 1) Read the schema for the document you want to validate
json schema;
try {
f >> schema;
}
catch (std::exception &e) {
MessageProc(f.tellp(), e.what(), context);
return FALSE;
}
// 2) create the validator and
json_validator validator(loader, [](const std::string &, const std::string &) {});
try {
// insert this schema as the root to the validator
// this resolves remote-schemas, sub-schemas and references via the given loader-function
validator.set_root_schema(schema);
}
catch (std::exception &e) {
MessageProc(-2, e.what(), context);
return FALSE;
}
// 3) do the actual validation of the document
json document;
if (!fd.good()) {
MessageProc(-3, "Json file could not be loaded.", context);
return FALSE;
}
try {
fd >> document;
validator.validate(document);
}
catch (std::exception &e) {
MessageProc(fd.tellp(), e.what(), context);
return FALSE;
}
return TRUE;
}

View file

@ -43,7 +43,6 @@ lib = library('kmcmplib',
'DeprecationChecks.cpp',
'Edition.cpp',
'filesystem.cpp',
'json-validation.cpp',
'NamedCodeConstants.cpp',
'versioning.cpp',
'virtualcharkeys.cpp',
@ -62,9 +61,6 @@ lib = library('kmcmplib',
'../../../../common/windows/cpp/src/vkeys.cpp',
'xstring.cpp',
'../../ext/json-schema-validator/json-schema-draft4.json.cpp',
'../../ext/json-schema-validator/json-uri.cpp',
'../../ext/json-schema-validator/json-validator.cpp',
version_res,
cpp_args: defns + warns + flags,
link_args: links,

View file

@ -20,8 +20,7 @@
#include <test_assert.h>
void setup();
void test_kmcmp_CompileKeyboardFile();
void test_kmcmp_CompileKeyboardFileToBuffer();
void test_kmcmp_CompileKeyboard();
std::vector<int> error_vec;
@ -40,10 +39,7 @@ int msgproc(int line, uint32_t dwMsgCode, char* szText, void* context) {
int main(int argc, char *argv[]) {
setup();
test_kmcmp_CompileKeyboardFile();
setup();
test_kmcmp_CompileKeyboardFileToBuffer();
test_kmcmp_CompileKeyboard();
return 0;
}
@ -52,7 +48,7 @@ void setup() {
error_vec.clear();
}
void test_kmcmp_CompileKeyboardFile() {
void test_kmcmp_CompileKeyboard() {
char kmn_file[L_tmpnam], kmx_file[L_tmpnam];
tmpnam(kmn_file);
tmpnam(kmx_file);
@ -62,26 +58,14 @@ void test_kmcmp_CompileKeyboardFile() {
fclose(fp);
// It should fail when a zero-byte file is passed in
assert(!kmcmp_CompileKeyboardFile(kmn_file, kmx_file, true, false, true, msgproc, nullptr));
assert(error_vec.size() == 1);
assert(error_vec[0] == CERR_CannotReadInfile);
unlink(kmn_file);
}
void test_kmcmp_CompileKeyboardFileToBuffer() {
char kmn_file[L_tmpnam], kmx_file[L_tmpnam];
tmpnam(kmn_file);
tmpnam(kmx_file);
// Create an empty file
FILE *fp = fopen(kmn_file, "w");
fclose(fp);
FILE_KEYBOARD fk;
// It should fail when a zero-byte file is passed in
assert(!kmcmp_CompileKeyboardFileToBuffer(kmn_file, &fk, true, false, msgproc, nullptr, CKF_KEYMAN));
KMCMP_COMPILER_RESULT result;
KMCMP_COMPILER_OPTIONS options;
options.saveDebug = true;
options.compilerWarningsAsErrors = false;
options.warnDeprecatedCode = true;
options.shouldAddCompilerVersion = false;
options.target = CKF_KEYMAN;
assert(!kmcmp_CompileKeyboard(kmn_file, options, msgproc, nullptr, nullptr, result));
assert(error_vec.size() == 1);
assert(error_vec[0] == CERR_CannotReadInfile);

View file

@ -71,14 +71,15 @@ int main(int argc, char *argv[])
char first5[6] = "CERR_";
char* pfirst5 = first5;
KMCMP_COMPILER_OPTIONS kcopts;
kcopts.dwSize = sizeof(KMCMP_COMPILER_OPTIONS);
kcopts.ShouldAddCompilerVersion = false; // So we can compare against existing compiled keyboards that also don't have compiler version
if(!kmcmp_SetCompilerOptions(&kcopts)) {
return __LINE__;
}
KMCMP_COMPILER_RESULT result;
KMCMP_COMPILER_OPTIONS options;
options.saveDebug = true;
options.compilerWarningsAsErrors = false;
options.warnDeprecatedCode = true;
options.shouldAddCompilerVersion = false;
options.target = CKF_KEYMAN;
if(kmcmp_CompileKeyboardFile(kmn_file, kmx_file, true, false, true, msgproc, nullptr)) {
if(kmcmp_CompileKeyboard(kmn_file, options, msgproc, nullptr, nullptr, result)) {
char* testname = strrchr( (char*) kmn_file, '/') + 1;
if(strncmp(testname, pfirst5, 5) == 0){
return __LINE__; // exit code: CERR_ in Name + no Error found
@ -87,26 +88,24 @@ int main(int argc, char *argv[])
// On non-win32 platforms, we cannot get kmcmpdll.dll to build keyboards
// legacy-mode, so we'll compare to a hopefully existing file that we've
// been passed
FILE* fp1 = Open_File(kmx_file, "rb");
FILE* fp1 = Open_File(kmx_file, "wb");
if(!fp1) return __LINE__;
// Write out for reference
fwrite(result.kmx, 1, result.kmxSize, fp1);
FILE* fp2 = Open_File(reference_kmx, "rb");
if(!fp2) return __LINE__; // exit code: fail if no reference kmx file in build-folder
fseek(fp1, 0, SEEK_END);
auto sz1 = ftell(fp1);
fseek(fp1, 0, SEEK_SET);
fseek(fp2, 0, SEEK_END);
auto sz2 = ftell(fp2);
fseek(fp2, 0, SEEK_SET);
if (sz1 != sz2) return __LINE__; // exit code: size of kmx-file in build differs from size of kmx-file in source folder
if (result.kmxSize != sz2) return __LINE__; // exit code: size of kmx-file in build differs from size of kmx-file in source folder
char* buf1 = new char[sz1];
char* buf2 = new char[sz1];
fread(buf1, 1, sz1, fp1);
fread(buf2, 1, sz1, fp2);
return memcmp(buf1, buf2, sz1) ? __LINE__ : 0; // exit code: when contents of kmx-file in build differs from contents of kmx-file in source folder
char* buf2 = new char[result.kmxSize];
fread(buf2, 1, result.kmxSize, fp2);
return memcmp(result.kmx, buf2, result.kmxSize) ? __LINE__ : 0; // exit code: when contents of kmx-file in build differs from contents of kmx-file in source folder
// success: when contents of kmx-file in build and source folder are the same
}
else { /*if Errors found: check number (e.g. CERR_4061_balochi_phonetic.kmn should produce Error 4061)*/

View file

@ -115,7 +115,7 @@ begin
TProject.CompilerMessageFile := Self;
options.dwSize := sizeof(COMPILER_OPTIONS);
options.ShouldAddCompilerVersion := addVersion;
options.UseKmcmpLib := not useLegacyCompiler;
// TODO: useLegacyCompiler means we switch to kmcmpdll vs kmc
if not SetCompilerOptions(@options, ProjectCompilerMessage) then
begin
Log(plsFatal, 'Unable to set compiler options', CERR_FATAL, 0);