From d1d6dc5d9922f67ef41b6f7285f25b9e9398c9cc Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 23 May 2023 15:26:28 +0700 Subject: [PATCH 1/3] refactor(developer): compiler interface part 1 for wasm This starts the refactor of the .kmn compiler interfaces for WASM, moving more file writes into typescript and out of the compiler. Adds a cleaner binding and structures for passing compile metadata back to typescript for additional build steps (e.g. kvk, js builds). Will rebase the Typescript-based KMW compiler onto this so it can start to benefit from the refactoring. * Fixes a minor issue with loading a .kvks file with an empty flags set. * Adds a writeFileSync method to the compiler callback interfaces. * Adds an e2e compiler test to verify that .kmx and .kvk are both correctly compiled. --- .../binary/caps_lock_layer_3620.kmx | Bin 0 -> 4330 bytes .../binary/caps_lock_layer_3620.kvk | Bin 0 -> 101 bytes common/web/types/src/kvk/kvks-file-reader.ts | 7 ++ .../web/types/src/util/compiler-interfaces.ts | 1 + .../src/kmc-kmn/src/compiler/compiler.ts | 98 +++++++++++++--- developer/src/kmc-kmn/test/test-compiler.ts | 50 +++++--- developer/src/kmcmplib/include/kmcmplibapi.h | 2 + developer/src/kmcmplib/src/Compiler.cpp | 5 +- .../src/kmcmplib/src/CompilerInterfaces.cpp | 110 ++++++++++++++++-- developer/src/kmcmplib/src/compfile.h | 11 +- developer/src/kmcmplib/src/kmcmplib.h | 2 +- developer/src/kmcmplib/src/meson.build | 2 +- 12 files changed, 244 insertions(+), 44 deletions(-) create mode 100644 common/test/keyboards/caps_lock_layer_3620/binary/caps_lock_layer_3620.kmx create mode 100644 common/test/keyboards/caps_lock_layer_3620/binary/caps_lock_layer_3620.kvk diff --git a/common/test/keyboards/caps_lock_layer_3620/binary/caps_lock_layer_3620.kmx b/common/test/keyboards/caps_lock_layer_3620/binary/caps_lock_layer_3620.kmx new file mode 100644 index 0000000000000000000000000000000000000000..563a139c19f7c6168fb49117503263b82ac5b616 GIT binary patch literal 4330 zcmeH~e~6A*6vr=Ft7+HXb~h_&o2+KFt;twfY1^I|V}8D7#>_ioX4+VcA2U0~m>J_o zk|arzBuSDaSxJ&4Ns=Tgt&$;KB zx3)FkA$+ff*y6d(Qz)$8#U4T=W7w17Cr+;3XI(;0xaI`7tPm zj|0Quc|IG!M0g*cU7!elfX_W(Ec_9lC&4%HM!879F)#xE5Pu5a0KO&v`XlZOmt}d@ zTL6R?@mUC_z@4jgOWZoQ!Yy@E_cCH+AURI#=rEaJ_TCgCef2cMYzM@2hr|uFB=fmZUq?;%swecuH}U z|Le}Ox^>}u^1)GwKhMe>tB7k_;JSy_Buv+|Ag!sG)eZt#OABjga?N~Gj=%q(cm8kR z_@Q=_-2nGr&3cx*$wMm;JrM4g<6dq2b2$=;tOUz8B~}K&|n;LjP%U;(LRB3v$Ny4n6#{ z4>|FTK#u}*jIRJa+T_IN(O-f(;~Rq>XL8~jk1hoD#y0_7WOCx0g#I2h7+*1Zs>z9O z8hQqpYkV`&KbxHRGITj;G`lM~-- z^c$e_Kzx6p-sgzf%xjsjV33) zJh~Osn?7hq&o?>o{fh1Y4aT<=-DPs(>qhqiod1JHROzK!V3CMUiv z=xspff%vwgcbc5|cA@tGod@FEi{5W?;yZvo1auyV?=bqP$%*e6`UKE~u zv5RAmYLq^V-57gKqx4hks@O9cr7vQ4#AmNjo^O20@fm8A=McR9LEToHJTJ%Pu# zGVmCC1CMc4;4$_E9%FytG0N{q-hLsjHgPcU7}o?I { source = r as KVKSourceFile }); source = this.boxArrays(source); + this.cleanupFlags(source); this.cleanupUnderscore('visualkeyboard', source.visualkeyboard); return source; } + private cleanupFlags(source: any) { + if(source.visualkeyboard?.header?.flags === '') { + source.visualkeyboard.header.flags = {}; + } + } + /** * The only element that allows spaces is . Remove * all other empty whitespace-only values. diff --git a/common/web/types/src/util/compiler-interfaces.ts b/common/web/types/src/util/compiler-interfaces.ts index c7058b1578..849e945321 100644 --- a/common/web/types/src/util/compiler-interfaces.ts +++ b/common/web/types/src/util/compiler-interfaces.ts @@ -109,6 +109,7 @@ export interface CompilerFileSystemCallbacks { readFileSync(path: string, options?: { encoding?: null; flag?: string; } | null): Uint8Array; readFileSync(path: string, options: { encoding: string; flag?: string; } | string): string; readFileSync(path: string, options?: { encoding?: string | null; flag?: string; } | string | null): string | Uint8Array; + writeFileSync(path: string, data: Uint8Array): void; existsSync(name: string): boolean; } diff --git a/developer/src/kmc-kmn/src/compiler/compiler.ts b/developer/src/kmc-kmn/src/compiler/compiler.ts index 2f83e83aee..352d597104 100644 --- a/developer/src/kmc-kmn/src/compiler/compiler.ts +++ b/developer/src/kmc-kmn/src/compiler/compiler.ts @@ -22,10 +22,21 @@ TODO: implement additional interfaces: */ // TODO: rename wasm-host? -import { CompilerCallbacks, CompilerEvent } from '@keymanapp/common-types'; +import { CompilerCallbacks, CompilerEvent, KvkFileWriter, KvksFileReader } from '@keymanapp/common-types'; import loadWasmHost from '../import/kmcmplib/wasm-host.js'; import { CompilerMessages, mapErrorFromKmcmplib } from './messages.js'; +export interface CompilerResultFile { + filename: string; + data: Uint8Array; +}; + +export interface CompilerResult { + kmx?: CompilerResultFile; + kvk?: CompilerResultFile; + js?: CompilerResultFile; +}; + export interface CompilerOptions { shouldAddCompilerVersion?: boolean; saveDebug?: boolean; @@ -136,7 +147,19 @@ export class KmnCompiler { // TODO: use callbacks for file access -- so kmc-kmn is entirely fs agnostic let result = this.runCompiler(infile, outfile, options); delete (globalThis as any)[this.callbackName]; - return result; + //TODO: write the file out! + if(result) { + if(result.kmx) { + this.callbacks.fs.writeFileSync(result.kmx.filename, result.kmx.data); + } + if(result.kvk) { + this.callbacks.fs.writeFileSync(result.kvk.filename, result.kvk.data); + } + if(result.js) { + this.callbacks.fs.writeFileSync(result.js.filename, result.js.data); + } + } + return !!result; } private compilerMessageCallback = (line: number, code: number, msg: string): number => { @@ -144,24 +167,73 @@ export class KmnCompiler { return 1; } - private runCompiler(infile: string, outfile: string, options: CompilerOptions): boolean { + private runCompiler(infile: string, outfile: string, options: CompilerOptions): CompilerResult { try { - if (!this.wasm.setCompilerOptions(options.shouldAddCompilerVersion ? 1 : 0)) { - this.callbacks.reportMessage(CompilerMessages.Fatal_UnableToSetCompilerOptions()); + let result: CompilerResult = {}; + let wasm_interface = new this.wasm.Module.CompilerInterface(); + let wasm_result = null; + try { + wasm_interface.saveDebug = options.saveDebug; + wasm_interface.compilerWarningsAsErrors = options.compilerWarningsAsErrors; + wasm_interface.warnDeprecatedCode = options.warnDeprecatedCode; + wasm_interface.messageCallback = this.callbackName; + wasm_interface.loadFileCallback = this.callbackName; + wasm_result = this.wasm.Module.kmcmp_compile(infile, wasm_interface); + if(!wasm_result.result) { + return null; + } + + if(wasm_result.kvksFilename) { + result.kvk = this.runKvkCompiler(wasm_result.kvksFilename, infile, outfile); + if(!result.kvk) { + return null; + } + } + + result.kmx = { + filename: outfile, + data: new Uint8Array(this.wasm.Module.HEAP8.buffer, wasm_result.kmx, wasm_result.kmxSize) + }; + + return result; + } finally { + if(wasm_result) { + wasm_result.delete(); + } + wasm_interface.delete(); } - return this.wasm.compileKeyboardFile( - infile, - outfile, - options.saveDebug ? 1 : 0, - options.compilerWarningsAsErrors ? 1 : 0, - options.warnDeprecatedCode ? 1 : 0, - this.callbackName); } catch(e) { this.callbacks.reportMessage(CompilerMessages.Fatal_UnexpectedException({e:e})); - return false; + return null; } } + private runKvkCompiler(kvksFilename: string, kmnFilename: string, kmxFilename: string) { + // The compiler detected a .kvks file, which needs to be captured + let reader = new KvksFileReader(); + kvksFilename = this.callbacks.resolveFilename(kmnFilename, kvksFilename); + let kvks = reader.read(this.callbacks.loadFile(kvksFilename)); + try { + reader.validate(kvks, this.callbacks.loadSchema('kvks')); + } catch(e) { + console.log(e); + // TODO: this.callbacks.reportMessage(CompilerMessages.Error_InvalidKvksFile({e})); + return null; + } + let errors: any = []; //TODO: KVKSParseError[]; + let vk = reader.transform(kvks, errors); + if(!vk || errors.length) { + console.dir(errors); + // TODO: this.callbacks.reportMessage(CompilerMessages.Error_InvalidKvksFile({e})); + return null; + } + let writer = new KvkFileWriter(); + return { + filename: this.callbacks.path.join(this.callbacks.path.dirname(kmxFilename), this.callbacks.path.basename(kvksFilename, '.kvks') + '.kvk'), + data: writer.write(vk) + }; + } + /** * * @param pattern UnicodeSet pattern such as `[a-z]` diff --git a/developer/src/kmc-kmn/test/test-compiler.ts b/developer/src/kmc-kmn/test/test-compiler.ts index 2eacd219e6..925656f8f5 100644 --- a/developer/src/kmc-kmn/test/test-compiler.ts +++ b/developer/src/kmc-kmn/test/test-compiler.ts @@ -1,7 +1,5 @@ import 'mocha'; -import sinon from 'sinon'; -import chai, { assert } from 'chai'; -import sinonChai from 'sinon-chai'; +import { assert } from 'chai'; import { KmnCompiler } from '../src/main.js'; import { dirname } from 'path'; import { fileURLToPath } from 'url'; @@ -9,21 +7,10 @@ import fs from 'fs'; import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers'; const __dirname = dirname(fileURLToPath(import.meta.url)).replace(/\\/g, '/'); -const baselineDir = __dirname + '/../../../../../common/test/keyboards/baseline/'; -chai.use(sinonChai); +const keyboardsDir = __dirname + '/../../../../../common/test/keyboards/'; +const baselineDir = keyboardsDir + 'baseline/'; describe('Compiler class', function() { - let consoleLog: any; - - // TODO: do we need this? - beforeEach(function() { - consoleLog = sinon.spy(console, 'log'); - }); - - afterEach(function() { - consoleLog.restore(); - }); - it('should throw on failure', async function() { const compiler = new KmnCompiler(); const callbacks : any = null; // ERROR @@ -87,4 +74,35 @@ describe('Compiler class', function() { } } }); + + it('should compile a keyboard with visual keyboard', async function() { + const compiler = new KmnCompiler(); + const callbacks = new TestCompilerCallbacks(); + assert(await compiler.init(callbacks)); + assert(compiler.verifyInitialized()); + + const fixtureDir = keyboardsDir + 'caps_lock_layer_3620/' + const infile = fixtureDir + 'source/caps_lock_layer_3620.kmn'; + 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'; + + assert(compiler.run(infile, kmxfile, {saveDebug: true, shouldAddCompilerVersion: false})); + + assert(fs.existsSync(kmxfile)); + assert(fs.existsSync(kvkfile)); + + const kmxData = fs.readFileSync(kmxfile); + const kmxFixtureData = fs.readFileSync(kmxFixture); + assert.equal(kmxData.byteLength, kmxFixtureData.byteLength); + assert.deepEqual(kmxData, kmxFixtureData); + + const kvkData = fs.readFileSync(kvkfile); + const kvkFixtureData = fs.readFileSync(kvkFixture); + assert.equal(kvkData.byteLength, kvkFixtureData.byteLength); + assert.deepEqual(kvkData, kvkFixtureData); + }); + }); diff --git a/developer/src/kmcmplib/include/kmcmplibapi.h b/developer/src/kmcmplib/include/kmcmplibapi.h index 97d46c3c36..2fb35979b2 100644 --- a/developer/src/kmcmplib/include/kmcmplibapi.h +++ b/developer/src/kmcmplib/include/kmcmplibapi.h @@ -4,6 +4,8 @@ #ifdef __EMSCRIPTEN__ #include +#include + #else #define EMSCRIPTEN_KEEPALIVE #endif diff --git a/developer/src/kmcmplib/src/Compiler.cpp b/developer/src/kmcmplib/src/Compiler.cpp index 7520bd0450..cb636126fd 100644 --- a/developer/src/kmcmplib/src/Compiler.cpp +++ b/developer/src/kmcmplib/src/Compiler.cpp @@ -784,7 +784,7 @@ KMX_DWORD ProcessStoreLine(PFILE_KEYBOARD fk, PKMX_WCHAR p) return CheckForDuplicateStore(fk, sp); } -KMX_DWORD AddStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, KMX_WCHAR const * str, KMX_DWORD *dwStoreID) +KMX_DWORD AddStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, const KMX_WCHAR * str, KMX_DWORD *dwStoreID) { PFILE_STORE sp; sp = new FILE_STORE[fk->cxStoreArray + 1]; @@ -1023,6 +1023,9 @@ KMX_DWORD ProcessSystemStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, PFILE_STORE case TSS_VISUALKEYBOARD: VERIFY_KEYBOARD_VERSION(fk, VERSION_70, CERR_70FeatureOnly); { + // Store extra metadata for callers as we mutate this store during + // compilation + fk->extra.kvksFilename = sp->dpString; // Strip path from the store, leaving bare filename only p = sp->dpString; diff --git a/developer/src/kmcmplib/src/CompilerInterfaces.cpp b/developer/src/kmcmplib/src/CompilerInterfaces.cpp index 02dda9de10..43655033fc 100644 --- a/developer/src/kmcmplib/src/CompilerInterfaces.cpp +++ b/developer/src/kmcmplib/src/CompilerInterfaces.cpp @@ -14,6 +14,10 @@ #define SetError(err) { if(AddCompileError(err) || (err & CERR_FATAL)) return FALSE; } 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"); @@ -44,6 +48,7 @@ int wasm_CompilerMessageProc(int line, uint32_t dwMsgCode, char* szText, void* c return wasm_msgproc(line, dwMsgCode, szText, msgProc); } +//DEPRECATED EXTERN bool kmcmp_Wasm_SetCompilerOptions(int ShouldAddCompilerVersion) { KMCMP_COMPILER_OPTIONS options; options.dwSize = sizeof(KMCMP_COMPILER_OPTIONS); @@ -51,6 +56,7 @@ EXTERN bool kmcmp_Wasm_SetCompilerOptions(int ShouldAddCompilerVersion) { return kmcmp_SetCompilerOptions(&options); } +//DEPRECATED EXTERN bool kmcmp_Wasm_CompileKeyboardFile(char* pszInfile, char* pszOutfile, int ASaveDebug, int ACompilerWarningsAsErrors, int AWarnDeprecatedCode, char* msgProc @@ -74,11 +80,97 @@ EXTERN int kmcmp_Wasm_ParseUnicodeSet(char* pat, ); } + +struct COMPILER_INTERFACE { + bool saveDebug; + bool compilerWarningsAsErrors; + bool warnDeprecatedCode; + bool shouldAddCompilerVersion; + int target; // CKF_KEYMAN, CKF_KEYMANWEB + std::string messageCallback; // int line, uint32_t dwMsgCode, char* szText + std::string loadFileCallback; // char* infile, char* filenameRelativeToInfile --> buffer +}; + +struct COMPILER_RESULT { + bool result; + // Following are pointer offsets in heap + buffer size + int kmx; + int kmxSize; + // Following are compiler side-channel data, required for + // follow-on transform + std::string kvksFilename; + // TODO: additional data to be passed back +}; + +COMPILER_RESULT kmcmp_compile(std::string pszInfile, const COMPILER_INTERFACE intf) { + COMPILER_RESULT r = {false}; + + FILE_KEYBOARD fk; + + // TODO: this should be included in CompileKeyboard? + kmcmp::FShouldAddCompilerVersion = intf.shouldAddCompilerVersion; + + r.result = CompileKeyboard( + pszInfile.c_str(), + &fk, + intf.saveDebug, + intf.compilerWarningsAsErrors, + intf.warnDeprecatedCode, + wasm_CompilerMessageProc, + intf.messageCallback.c_str(), + intf.target); + + if(!r.result) { + return r; + } + + 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_("CompilerInterface") + .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) + ; + + emscripten::class_("CompilerResult") + .constructor<>() + .property("result", &COMPILER_RESULT::result) + .property("kmx", &COMPILER_RESULT::kmx) + .property("kmxSize", &COMPILER_RESULT::kmxSize) + .property("kvksFilename", &COMPILER_RESULT::kvksFilename) + ; + + emscripten::function("kmcmp_compile", &kmcmp_compile); +} + #endif -bool CompileKeyboard(char* pszInfile, +bool CompileKeyboard(const char* pszInfile, void* pfkBuffer, bool ASaveDebug, bool ACompilerWarningsAsErrors, - bool AWarnDeprecatedCode, kmcmp_CompilerMessageProc pMsgproc, void* AmsgprocContext, + bool AWarnDeprecatedCode, kmcmp_CompilerMessageProc pMsgproc, const void* AmsgprocContext, int Target) { FILE* fp_in = NULL; @@ -95,7 +187,7 @@ bool CompileKeyboard(char* pszInfile, PKMX_STR p; - if ((p = strrchr_slash(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; @@ -104,7 +196,7 @@ bool CompileKeyboard(char* pszInfile, kmcmp::CompileDir[0] = 0; msgproc = pMsgproc; - msgprocContext = AmsgprocContext; + msgprocContext = (void*)AmsgprocContext; kmcmp::currentLine = 0; kmcmp::nErrors = 0; @@ -231,7 +323,7 @@ bool CompileKeyboardHandle(FILE* fp_in, PFILE_KEYBOARD fk) fk->dpDeadKeyArray = NULL; fk->cxVKDictionary = 0; // I3438 fk->dpVKDictionary = NULL; // I3438 - + fk->extra.kvksFilename = u""; /* fk->szMessage[0] = 0; fk->szLanguageName[0] = 0;*/ fk->dwBitmapSize = 0; @@ -251,12 +343,8 @@ bool CompileKeyboardHandle(FILE* fp_in, PFILE_KEYBOARD fk) } /* Add a system store for the Keyman edition number */ - u16sprintf(str, LINESIZE, L"%d", 0); // I3481 - AddStore(fk, TSS_CUSTOMKEYMANEDITION, str); - - PKMX_WCHAR tbuf = strtowstr((KMX_CHAR*) "Keyman"); - AddStore(fk, TSS_CUSTOMKEYMANEDITIONNAME, tbuf); - delete tbuf; + AddStore(fk, TSS_CUSTOMKEYMANEDITION, u"0"); + AddStore(fk, TSS_CUSTOMKEYMANEDITIONNAME, u"Keyman"); // must preprocess for group and store names -> this isn't really necessary, but never mind! while ((msg = ReadLine(fp_in, str, TRUE)) == CERR_None) diff --git a/developer/src/kmcmplib/src/compfile.h b/developer/src/kmcmplib/src/compfile.h index 48be5f2048..3fb106411f 100644 --- a/developer/src/kmcmplib/src/compfile.h +++ b/developer/src/kmcmplib/src/compfile.h @@ -121,6 +121,13 @@ struct FILE_VKDICTIONARY }; typedef FILE_VKDICTIONARY *PFILE_VKDICTIONARY; +/** + * Extra metadata for API consumers + */ +struct FILE_KEYBOARD_EXTRA { + std::u16string kvksFilename; // original TSS_VISUALKEYBOARD value +}; + struct FILE_KEYBOARD { KMX_DWORD KeyboardID; // as stored in HKEY_LOCAL_MACHINE//system//currentcontrolset//control//keyboard layouts @@ -149,7 +156,9 @@ struct FILE_KEYBOARD { PFILE_DEADKEY dpDeadKeyArray; // temp - dead key array KMX_DWORD cxVKDictionary; PFILE_VKDICTIONARY dpVKDictionary; // temp - virtual key dictionary - }; + + FILE_KEYBOARD_EXTRA extra; +}; typedef FILE_KEYBOARD *PFILE_KEYBOARD; diff --git a/developer/src/kmcmplib/src/kmcmplib.h b/developer/src/kmcmplib/src/kmcmplib.h index b547ecf844..78e945ee0d 100644 --- a/developer/src/kmcmplib/src/kmcmplib.h +++ b/developer/src/kmcmplib/src/kmcmplib.h @@ -42,7 +42,7 @@ PKMX_WCHAR strtowstr(PKMX_STR in); PFILE_STORE FindSystemStore(PFILE_KEYBOARD fk, KMX_DWORD dwSystemID); FILE* UTF16TempFromUTF8(FILE* fp_in , KMX_BOOL hasPreamble); KMX_DWORD WriteCompiledKeyboard(PFILE_KEYBOARD fk, KMX_BYTE**data, size_t& dataSize); -KMX_DWORD AddStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, KMX_WCHAR const * str, KMX_DWORD *dwStoreID= NULL); +KMX_DWORD AddStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, const KMX_WCHAR * str, KMX_DWORD *dwStoreID= NULL); KMX_DWORD ReadLine(FILE* fp_in , PKMX_WCHAR wstr, KMX_BOOL PreProcess); KMX_DWORD ParseLine(PFILE_KEYBOARD fk, PKMX_WCHAR str); KMX_DWORD ProcessGroupLine(PFILE_KEYBOARD fk, PKMX_WCHAR p); diff --git a/developer/src/kmcmplib/src/meson.build b/developer/src/kmcmplib/src/meson.build index fa51ca28a5..292b158ce2 100644 --- a/developer/src/kmcmplib/src/meson.build +++ b/developer/src/kmcmplib/src/meson.build @@ -24,7 +24,7 @@ endif name_suffix = [] if cpp_compiler.get_id() == 'emscripten' - links += ['-lnodefs.js', '-sMODULARIZE', '-sEXPORT_ES6', '-sEXPORTED_RUNTIME_METHODS=[\'cwrap\', \'UTF8ToString\']'] + links += ['-lnodefs.js', '-sMODULARIZE', '-sEXPORT_ES6', '--whole-archive', '--bind', '-sEXPORTED_RUNTIME_METHODS=[\'cwrap\', \'UTF8ToString\']'] # tests are building as ES6 so we need to declare the file extension # note that meson currently struggles with the sanitycheckc_cross.exe # program, because it has a hard coded extension (.exe) which is not From cdf5f7a7c45b51ae32752946e5453f0d92f6a1a0 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 24 May 2023 12:14:41 +0700 Subject: [PATCH 2/3] chore(developer): consolidate 'extra' field for FILE_KEYBOARD FILE_KEYBOARD is a structure used in multiple libraries and languages. It is passed around between kmcmplib, kmcmpdll, and kmcomp, with three separate definitions (kmcmplib/compfile.h, kmcmpdll/compfile.h, and kmcomp/compile.pas). These duplicate definitions must be maintained for now because of type issues between the legacy kmcmpdll and kmcmplib, which means that the definitions must be kept in sync. Because FILE_KEYBOARD_EXTRA has a C++ class in it, it will be initialized in CompileKeyboardHandle rather than in the caller, so FILE_KEYBOARD.extra is now a pointer rather than a struct. When original kmcomp and kmcmpdll are eventually removed, these duplications will disappear and some of the memory management and lifecycle will become easier to manage. --- .../src/common/delphi/compiler/compile.pas | 6 +- .../src/kmc-kmn/src/compiler/compiler.ts | 20 +-- developer/src/kmcmpdll/compfile.h | 116 +++++++------- developer/src/kmcmpdll/kcframe/kcframe.cpp | 2 + developer/src/kmcmplib/meson.build | 3 +- developer/src/kmcmplib/src/Compiler.cpp | 2 +- .../src/kmcmplib/src/CompilerInterfaces.cpp | 5 +- developer/src/kmcmplib/src/compfile.h | 142 +++++++++--------- 8 files changed, 148 insertions(+), 148 deletions(-) diff --git a/developer/src/common/delphi/compiler/compile.pas b/developer/src/common/delphi/compiler/compile.pas index 9b304b39d8..b89ef0eb72 100644 --- a/developer/src/common/delphi/compiler/compile.pas +++ b/developer/src/common/delphi/compiler/compile.pas @@ -126,6 +126,8 @@ type dpDeadKeyArray: PFILE_DEADKEY; // temp - dead key array cxVKDictionary: DWORD; // I3438 dpVKDictionary: PFILE_VKDICTIONARY; // I3438 // temp - virtual key dictionary + + extra: Pointer; end; PFILE_KEYBOARD = ^FILE_KEYBOARD; @@ -152,13 +154,13 @@ const const // kcframe --sizeof returns these values {$IFDEF WIN64} - FILE_KEYBOARD_SIZE = 2984; + FILE_KEYBOARD_SIZE = 2992; FILE_GROUP_SIZE = 200; FILE_STORE_SIZE = 200; FILE_KEY_SIZE = 32; FILE_DEADKEY_SIZE = 160; {$ELSE} - FILE_KEYBOARD_SIZE = 2952; + FILE_KEYBOARD_SIZE = 2956; FILE_GROUP_SIZE = 188; FILE_STORE_SIZE = 192; FILE_KEY_SIZE = 20; diff --git a/developer/src/kmc-kmn/src/compiler/compiler.ts b/developer/src/kmc-kmn/src/compiler/compiler.ts index 352d597104..93ee3c36e8 100644 --- a/developer/src/kmc-kmn/src/compiler/compiler.ts +++ b/developer/src/kmc-kmn/src/compiler/compiler.ts @@ -1,24 +1,8 @@ /* TODO: implement additional interfaces: - extern "C" bool kmcmp_CompileKeyboardFileToBuffer( - char* pszInfile, - void* pfkBuffer, - bool ACompilerWarningsAsErrors, - bool AWarnDeprecatedCode, - kmcmp_CompilerMessageProc pMsgproc, - void* AmsgprocContext, - int Target - ); - - typedef bool (*kmcmp_ValidateJsonMessageProc)(int64_t offset, const char* szText, void* context); - - extern "C" bool kmcmp_ValidateJsonFile( - std::fstream& f, - std::fstream& fd, - kmcmp_ValidateJsonMessageProc MessageProc, - void* context - ); + typedef bool (*kmcmp_ValidateJsonMessageProc)(); + extern "C" bool kmcmp_ValidateJsonFile(); */ // TODO: rename wasm-host? diff --git a/developer/src/kmcmpdll/compfile.h b/developer/src/kmcmpdll/compfile.h index 4fd6e68eb5..2f6e2e654f 100644 --- a/developer/src/kmcmpdll/compfile.h +++ b/developer/src/kmcmpdll/compfile.h @@ -22,6 +22,13 @@ #include "../../../common/windows/cpp/include/legacy_kmx_file.h" + +// This file is deprecated; see kmcmplib/src/compfile.h. However, as long as +// this file continues to live, we need to keep structures in it in exact sync +// with kmcmplib/src/compfile.h, as FILE_KEYBOARD is passed between kmcmplib and +// kmcmpdll. KMX_WCHAR on Windows is identical to wchar_t, so it is safe to map +// accordingly. + #define LINESIZE 8192 #define GLOBAL_BUFSIZE 4096 @@ -70,9 +77,9 @@ enum FileStoreType { FST_STORE, FST_OPTION, FST_RESERVED }; struct FILE_STORE { - DWORD dwSystemID; - WCHAR szName[SZMAX_STORENAME]; // the name of the store - PWSTR dpString; // from start of store structure + DWORD dwSystemID; + WCHAR szName[SZMAX_STORENAME]; // the name of the store + PWSTR dpString; // from start of store structure //FileStoreType fstType; BOOL fIsStore; BOOL fIsReserved; @@ -80,28 +87,27 @@ struct FILE_STORE { BOOL fIsDebug; BOOL fIsCall; int line; // TODO: int vs dword, line vs Line (see FILE_KEY, FILE_GROUP) - }; + }; typedef FILE_STORE *PFILE_STORE; struct FILE_KEY { - WCHAR Key; // WCHAR for consistency; only a byte used however - WORD LineStoreIndex; - DWORD Line; - DWORD ShiftFlags; - PWSTR dpOutput; // from start of key structure - PWSTR dpContext; // from start of key structure - }; - + WCHAR Key; // WCHAR for consistency; only a byte used however + WORD LineStoreIndex; + DWORD Line; + DWORD ShiftFlags; + PWSTR dpOutput; // from start of key structure + PWSTR dpContext; // from start of key structure + }; typedef FILE_KEY *PFILE_KEY; struct FILE_GROUP { - WCHAR szName[SZMAX_GROUPNAME]; - PFILE_KEY dpKeyArray; // address of first item in key array, from start of group structure - PWSTR dpMatch; // from start of group structure - PWSTR dpNoMatch; // from start of group structure - DWORD cxKeyArray; // in array items - BOOL fUsingKeys; // group(xx) [using keys] <-- specified or not + WCHAR szName[SZMAX_GROUPNAME]; + PFILE_KEY dpKeyArray; // address of first item in key array, from start of group structure + PWSTR dpMatch; // from start of group structure + PWSTR dpNoMatch; // from start of group structure + DWORD cxKeyArray; // in array items + BOOL fUsingKeys; // group(xx) [using keys] <-- specified or not BOOL fReadOnly; // group(xx) [readonly] <-- specified or not DWORD Line; }; @@ -110,7 +116,7 @@ typedef FILE_GROUP *PFILE_GROUP; struct FILE_DEADKEY { - WCHAR szName[SZMAX_DEADKEYNAME]; + WCHAR szName[SZMAX_DEADKEYNAME]; }; typedef FILE_DEADKEY *PFILE_DEADKEY; @@ -123,34 +129,36 @@ struct FILE_VKDICTIONARY typedef FILE_VKDICTIONARY *PFILE_VKDICTIONARY; struct FILE_KEYBOARD { - DWORD KeyboardID; // as stored in HKEY_LOCAL_MACHINE//system//currentcontrolset//control//keyboard layouts + DWORD KeyboardID; // as stored in HKEY_LOCAL_MACHINE//system//currentcontrolset//control//keyboard layouts - DWORD version; // keyboard file version with VERSION keyword + DWORD version; // keyboard file version with VERSION keyword - PFILE_STORE dpStoreArray; // address of first item in store array, from start of store structure - PFILE_GROUP dpGroupArray; // address of first item in group array, from start of group structure + PFILE_STORE dpStoreArray; // address of first item in store array, from start of store structure + PFILE_GROUP dpGroupArray; // address of first item in group array, from start of group structure - DWORD cxStoreArray; // in number of items - DWORD cxGroupArray; // in number of items - DWORD StartGroup[2]; // index of starting groups [ANSI=0, Unicode=1] + DWORD cxStoreArray; // in number of items + DWORD cxGroupArray; // in number of items + DWORD StartGroup[2]; // index of starting groups [ANSI=0, Unicode=1] - DWORD dwHotKey; // standard windows hotkey (hiword=shift/ctrl/alt stuff, loword=vkey) + DWORD dwHotKey; // standard windows hotkey (hiword=shift/ctrl/alt stuff, loword=vkey) - WCHAR szName[SZMAX_KEYBOARDNAME]; // Keyboard layout name - WCHAR szLanguageName[SZMAX_LANGUAGENAME]; // Language name - WCHAR szCopyright[SZMAX_COPYRIGHT]; // Copyright information - WCHAR szMessage[SZMAX_MESSAGE]; // General information about the keyboard - PBYTE lpBitmap; - DWORD dwBitmapSize; - DWORD dwFlags; // Flags for the keyboard file + WCHAR szName[SZMAX_KEYBOARDNAME]; // Keyboard layout name + WCHAR szLanguageName[SZMAX_LANGUAGENAME]; // Language name + WCHAR szCopyright[SZMAX_COPYRIGHT]; // Copyright information + WCHAR szMessage[SZMAX_MESSAGE]; // General information about the keyboard + PBYTE lpBitmap; + DWORD dwBitmapSize; + DWORD dwFlags; // Flags for the keyboard file - DWORD currentGroup; // temp - current processing group - DWORD currentStore; // temp - current processing store - DWORD cxDeadKeyArray; - PFILE_DEADKEY dpDeadKeyArray; // temp - dead key array + DWORD currentGroup; // temp - current processing group + DWORD currentStore; // temp - current processing store + DWORD cxDeadKeyArray; + PFILE_DEADKEY dpDeadKeyArray; // temp - dead key array DWORD cxVKDictionary; PFILE_VKDICTIONARY dpVKDictionary; // temp - virtual key dictionary - }; + + void* extra; // used by kmcmplib and its consumers; unused in kmcmpdll +}; typedef FILE_KEYBOARD *PFILE_KEYBOARD; @@ -168,34 +176,34 @@ const DWORD sz_FILE_VKDICTIONARY = sizeof(FILE_VKDICTIONARY); const DWORD sz_FILE_KEYBOARD = sizeof(FILE_KEYBOARD); struct COMPMSG { - char szText[SZMAX_ERRORTEXT]; - DWORD Line; - DWORD dwMsgCode; - }; + char szText[SZMAX_ERRORTEXT]; + DWORD Line; + DWORD dwMsgCode; + }; typedef COMPMSG *PCOMPMSG; struct COMPILEMESSAGES { - int nMessages; - int nErrors; + int nMessages; + int nErrors; - PCOMPMSG cm; + PCOMPMSG cm; - DWORD fatalCode; - char szFatalText[SZMAX_ERRORTEXT]; + DWORD fatalCode; + char szFatalText[SZMAX_ERRORTEXT]; - DWORD currentLine; - }; + DWORD currentLine; + }; typedef COMPILEMESSAGES *PCOMPILEMESSAGES; /* struct TVersion { - //int MinVersion; // 0x0500 usually - //int CompilerVersion[4]; - //int MinCompilerVersion[4]; - int KeyboardVersion; // 0x0500 usually + //int MinVersion; // 0x0500 usually + //int CompilerVersion[4]; + //int MinCompilerVersion[4]; + int KeyboardVersion; // 0x0500 usually }; extern TVersion FVersionInfo; diff --git a/developer/src/kmcmpdll/kcframe/kcframe.cpp b/developer/src/kmcmpdll/kcframe/kcframe.cpp index 4ac80bfe18..22402e5230 100644 --- a/developer/src/kmcmpdll/kcframe/kcframe.cpp +++ b/developer/src/kmcmpdll/kcframe/kcframe.cpp @@ -24,6 +24,8 @@ #include +extern "C" BOOL CompileKeyboardFile(PSTR pszInfile, PSTR pszOutfile, BOOL FSaveDebug, BOOL ACompilerWarningsAsErrors, BOOL AWarnDeprecatedCode, CompilerMessageProc pMsgProc); // I4865 // I4866 + int WINAPI msgproc(int line, DWORD dwMsgCode, LPSTR szText) { printf("line %d error %x %s\n", line, (unsigned int) dwMsgCode, szText); diff --git a/developer/src/kmcmplib/meson.build b/developer/src/kmcmplib/meson.build index ae8fd6ac62..c996981f47 100644 --- a/developer/src/kmcmplib/meson.build +++ b/developer/src/kmcmplib/meson.build @@ -10,7 +10,8 @@ project('kmcmplib', 'cpp', 'c', default_options : ['buildtype=release', 'cpp_std=c++14', 'b_vscrt=static_from_buildtype', - 'default_library=static']) + 'default_library=static', + 'debug=true']) # Import our standard compiler defines; this is copied from # /resources/build/standard.meson.build by build.sh, because diff --git a/developer/src/kmcmplib/src/Compiler.cpp b/developer/src/kmcmplib/src/Compiler.cpp index cb636126fd..b09e36cbc1 100644 --- a/developer/src/kmcmplib/src/Compiler.cpp +++ b/developer/src/kmcmplib/src/Compiler.cpp @@ -1025,7 +1025,7 @@ KMX_DWORD ProcessSystemStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, PFILE_STORE { // Store extra metadata for callers as we mutate this store during // compilation - fk->extra.kvksFilename = sp->dpString; + fk->extra->kvksFilename = sp->dpString; // Strip path from the store, leaving bare filename only p = sp->dpString; diff --git a/developer/src/kmcmplib/src/CompilerInterfaces.cpp b/developer/src/kmcmplib/src/CompilerInterfaces.cpp index 43655033fc..d7b8118b58 100644 --- a/developer/src/kmcmplib/src/CompilerInterfaces.cpp +++ b/developer/src/kmcmplib/src/CompilerInterfaces.cpp @@ -138,7 +138,7 @@ COMPILER_RESULT kmcmp_compile(std::string pszInfile, const COMPILER_INTERFACE in r.kmx = (int) data; r.kmxSize = (int) dataSize; - r.kvksFilename = string_from_u16string(fk.extra.kvksFilename); // convert to UTF8 + r.kvksFilename = string_from_u16string(fk.extra->kvksFilename); // convert to UTF8 return r; } @@ -323,7 +323,8 @@ bool CompileKeyboardHandle(FILE* fp_in, PFILE_KEYBOARD fk) fk->dpDeadKeyArray = NULL; fk->cxVKDictionary = 0; // I3438 fk->dpVKDictionary = NULL; // I3438 - fk->extra.kvksFilename = u""; + fk->extra = new FILE_KEYBOARD_EXTRA; + fk->extra->kvksFilename = u""; /* fk->szMessage[0] = 0; fk->szLanguageName[0] = 0;*/ fk->dwBitmapSize = 0; diff --git a/developer/src/kmcmplib/src/compfile.h b/developer/src/kmcmplib/src/compfile.h index 3fb106411f..4b639a7eb1 100644 --- a/developer/src/kmcmplib/src/compfile.h +++ b/developer/src/kmcmplib/src/compfile.h @@ -22,6 +22,7 @@ #include "kmcompx.h" #include +#include #define LINESIZE 8192 #define GLOBAL_BUFSIZE 4096 @@ -71,53 +72,52 @@ enum FileStoreType { FST_STORE, FST_OPTION, FST_RESERVED }; struct FILE_STORE { - KMX_DWORD dwSystemID; - KMX_WCHAR szName[SZMAX_STORENAME]; // the name of the store - PKMX_WCHAR dpString; // from start of store structure - //FileStoreType fstType; - KMX_BOOL fIsStore; - KMX_BOOL fIsReserved; - KMX_BOOL fIsOption; - KMX_BOOL fIsDebug; - KMX_BOOL fIsCall; - int line; - }; - -typedef FILE_STORE * PFILE_STORE; + KMX_DWORD dwSystemID; + KMX_WCHAR szName[SZMAX_STORENAME]; // the name of the store + PKMX_WCHAR dpString; // from start of store structure + //FileStoreType fstType; + KMX_BOOL fIsStore; + KMX_BOOL fIsReserved; + KMX_BOOL fIsOption; + KMX_BOOL fIsDebug; + KMX_BOOL fIsCall; + int line; + }; +typedef FILE_STORE *PFILE_STORE; struct FILE_KEY { - KMX_WCHAR Key; // WCHAR for consistency; only a byte used however - KMX_WORD LineStoreIndex; - KMX_DWORD Line; - KMX_DWORD ShiftFlags; - PKMX_WCHAR dpOutput; // from start of key structure - PKMX_WCHAR dpContext; // from start of key structure - }; + KMX_WCHAR Key; // WCHAR for consistency; only a byte used however + KMX_WORD LineStoreIndex; + KMX_DWORD Line; + KMX_DWORD ShiftFlags; + PKMX_WCHAR dpOutput; // from start of key structure + PKMX_WCHAR dpContext; // from start of key structure + }; typedef FILE_KEY *PFILE_KEY; - struct FILE_GROUP { - KMX_WCHAR szName[SZMAX_GROUPNAME]; - PFILE_KEY dpKeyArray; // address of first item in key array, from start of group structure - PKMX_WCHAR dpMatch; // from start of group structure - PKMX_WCHAR dpNoMatch; // from start of group structure - KMX_DWORD cxKeyArray; // in array items - KMX_BOOL fUsingKeys; // group(xx) [using keys] <-- specified or not - KMX_BOOL fReadOnly; // group(xx) [readonly] <-- specified or not - KMX_DWORD Line; - }; + KMX_WCHAR szName[SZMAX_GROUPNAME]; + PFILE_KEY dpKeyArray; // address of first item in key array, from start of group structure + PKMX_WCHAR dpMatch; // from start of group structure + PKMX_WCHAR dpNoMatch; // from start of group structure + KMX_DWORD cxKeyArray; // in array items + KMX_BOOL fUsingKeys; // group(xx) [using keys] <-- specified or not + KMX_BOOL fReadOnly; // group(xx) [readonly] <-- specified or not + KMX_DWORD Line; +}; typedef FILE_GROUP *PFILE_GROUP; struct FILE_DEADKEY { - KMX_WCHAR szName[SZMAX_DEADKEYNAME]; + KMX_WCHAR szName[SZMAX_DEADKEYNAME]; }; + typedef FILE_DEADKEY *PFILE_DEADKEY; struct FILE_VKDICTIONARY { - KMX_WCHAR szName[SZMAX_VKDICTIONARYNAME]; + KMX_WCHAR szName[SZMAX_VKDICTIONARYNAME]; }; typedef FILE_VKDICTIONARY *PFILE_VKDICTIONARY; @@ -125,39 +125,41 @@ typedef FILE_VKDICTIONARY *PFILE_VKDICTIONARY; * Extra metadata for API consumers */ struct FILE_KEYBOARD_EXTRA { - std::u16string kvksFilename; // original TSS_VISUALKEYBOARD value + std::u16string kvksFilename; // original TSS_VISUALKEYBOARD value }; +typedef struct FILE_KEYBOARD_EXTRA* PFILE_KEYBOARD_EXTRA; + struct FILE_KEYBOARD { - KMX_DWORD KeyboardID; // as stored in HKEY_LOCAL_MACHINE//system//currentcontrolset//control//keyboard layouts + KMX_DWORD KeyboardID; // as stored in HKEY_LOCAL_MACHINE//system//currentcontrolset//control//keyboard layouts - KMX_DWORD version; // keyboard file version with VERSION keyword + KMX_DWORD version; // keyboard file version with VERSION keyword - PFILE_STORE dpStoreArray; // address of first item in store array, from start of store structure - PFILE_GROUP dpGroupArray; // address of first item in group array, from start of group structure + PFILE_STORE dpStoreArray; // address of first item in store array, from start of store structure + PFILE_GROUP dpGroupArray; // address of first item in group array, from start of group structure - KMX_DWORD cxStoreArray; // in number of items - KMX_DWORD cxGroupArray; // in number of items - KMX_DWORD StartGroup[2]; // index of starting groups [ANSI=0, Unicode=1] + KMX_DWORD cxStoreArray; // in number of items + KMX_DWORD cxGroupArray; // in number of items + KMX_DWORD StartGroup[2]; // index of starting groups [ANSI=0, Unicode=1] - KMX_DWORD dwHotKey; // standard windows hotkey (hiword=shift/ctrl/alt stuff, loword=vkey) + KMX_DWORD dwHotKey; // standard windows hotkey (hiword=shift/ctrl/alt stuff, loword=vkey) - KMX_WCHAR szName[SZMAX_KEYBOARDNAME]; // Keyboard layout name - KMX_WCHAR szLanguageName[SZMAX_LANGUAGENAME]; // Language name - KMX_WCHAR szCopyright[SZMAX_COPYRIGHT]; // Copyright information - KMX_WCHAR szMessage[SZMAX_MESSAGE]; // General information about the keyboard - PKMX_BYTE lpBitmap; - KMX_DWORD dwBitmapSize; - KMX_DWORD dwFlags; // Flags for the keyboard file + KMX_WCHAR szName[SZMAX_KEYBOARDNAME]; // Keyboard layout name + KMX_WCHAR szLanguageName[SZMAX_LANGUAGENAME]; // Language name + KMX_WCHAR szCopyright[SZMAX_COPYRIGHT]; // Copyright information + KMX_WCHAR szMessage[SZMAX_MESSAGE]; // General information about the keyboard + PKMX_BYTE lpBitmap; + KMX_DWORD dwBitmapSize; + KMX_DWORD dwFlags; // Flags for the keyboard file - KMX_DWORD currentGroup; // temp - current processing group - KMX_DWORD currentStore; // temp - current processing store - KMX_DWORD cxDeadKeyArray; - PFILE_DEADKEY dpDeadKeyArray; // temp - dead key array - KMX_DWORD cxVKDictionary; - PFILE_VKDICTIONARY dpVKDictionary; // temp - virtual key dictionary + KMX_DWORD currentGroup; // temp - current processing group + KMX_DWORD currentStore; // temp - current processing store + KMX_DWORD cxDeadKeyArray; + PFILE_DEADKEY dpDeadKeyArray; // temp - dead key array + KMX_DWORD cxVKDictionary; + PFILE_VKDICTIONARY dpVKDictionary; // temp - virtual key dictionary - FILE_KEYBOARD_EXTRA extra; + PFILE_KEYBOARD_EXTRA extra; }; typedef FILE_KEYBOARD *PFILE_KEYBOARD; @@ -176,34 +178,34 @@ const KMX_DWORD sz_FILE_VKDICTIONARY = sizeof(FILE_VKDICTIONARY); const KMX_DWORD sz_FILE_KEYBOARD = sizeof(FILE_KEYBOARD); struct COMPMSG { - KMX_CHAR szText[SZMAX_ERRORTEXT]; - KMX_DWORD Line; - KMX_DWORD dwMsgCode; - }; + KMX_CHAR szText[SZMAX_ERRORTEXT]; + KMX_DWORD Line; + KMX_DWORD dwMsgCode; + }; typedef COMPMSG *PCOMPMSG; struct COMPILEMESSAGES { - int nMessages; - int nErrors; + int nMessages; + int nErrors; - PCOMPMSG cm; + PCOMPMSG cm; - KMX_DWORD fatalCode; - KMX_CHAR szFatalText[SZMAX_ERRORTEXT]; + KMX_DWORD fatalCode; + KMX_CHAR szFatalText[SZMAX_ERRORTEXT]; - KMX_DWORD currentLine; - }; + KMX_DWORD currentLine; + }; typedef COMPILEMESSAGES *PCOMPILEMESSAGES; /* struct TVersion { - //int MinVersion; // 0x0500 usually - //int CompilerVersion[4]; - //int MinCompilerVersion[4]; - int KeyboardVersion; // 0x0500 usually + //int MinVersion; // 0x0500 usually + //int CompilerVersion[4]; + //int MinCompilerVersion[4]; + int KeyboardVersion; // 0x0500 usually }; extern TVersion FVersionInfo; From ef101d746c619d8b0f8c6695132f55a13c98e7b6 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 25 May 2023 08:24:09 +0700 Subject: [PATCH 3/3] chore(developer): address review comments --- .../src/kmc-kmn/src/compiler/compiler.ts | 60 +++++++++---------- developer/src/kmcmpdll/compfile.h | 17 +++--- developer/src/kmcmplib/src/compfile.h | 18 +++--- 3 files changed, 44 insertions(+), 51 deletions(-) diff --git a/developer/src/kmc-kmn/src/compiler/compiler.ts b/developer/src/kmc-kmn/src/compiler/compiler.ts index 93ee3c36e8..c46b894cb3 100644 --- a/developer/src/kmc-kmn/src/compiler/compiler.ts +++ b/developer/src/kmc-kmn/src/compiler/compiler.ts @@ -152,50 +152,48 @@ export class KmnCompiler { } private runCompiler(infile: string, outfile: string, options: CompilerOptions): CompilerResult { + let result: CompilerResult = {}; + let wasm_interface = new this.wasm.Module.CompilerInterface(); + let wasm_result = null; try { - let result: CompilerResult = {}; - let wasm_interface = new this.wasm.Module.CompilerInterface(); - let wasm_result = null; - try { - wasm_interface.saveDebug = options.saveDebug; - wasm_interface.compilerWarningsAsErrors = options.compilerWarningsAsErrors; - wasm_interface.warnDeprecatedCode = options.warnDeprecatedCode; - wasm_interface.messageCallback = this.callbackName; - wasm_interface.loadFileCallback = this.callbackName; - wasm_result = this.wasm.Module.kmcmp_compile(infile, wasm_interface); - if(!wasm_result.result) { + wasm_interface.saveDebug = options.saveDebug; + wasm_interface.compilerWarningsAsErrors = options.compilerWarningsAsErrors; + wasm_interface.warnDeprecatedCode = options.warnDeprecatedCode; + 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.wasm.Module.kmcmp_compile(infile, wasm_interface); + if(!wasm_result.result) { + return null; + } + + if(wasm_result.kvksFilename) { + result.kvk = this.runKvkCompiler(wasm_result.kvksFilename, infile, outfile); + if(!result.kvk) { return null; } - - if(wasm_result.kvksFilename) { - result.kvk = this.runKvkCompiler(wasm_result.kvksFilename, infile, outfile); - if(!result.kvk) { - return null; - } - } - - result.kmx = { - filename: outfile, - data: new Uint8Array(this.wasm.Module.HEAP8.buffer, wasm_result.kmx, wasm_result.kmxSize) - }; - - return result; - } finally { - if(wasm_result) { - wasm_result.delete(); - } - wasm_interface.delete(); } + + result.kmx = { + filename: outfile, + data: new Uint8Array(this.wasm.Module.HEAP8.buffer, wasm_result.kmx, wasm_result.kmxSize) + }; + + return result; } catch(e) { this.callbacks.reportMessage(CompilerMessages.Fatal_UnexpectedException({e:e})); return null; + } finally { + if(wasm_result) { + wasm_result.delete(); + } + wasm_interface.delete(); } } private runKvkCompiler(kvksFilename: string, kmnFilename: string, kmxFilename: string) { // The compiler detected a .kvks file, which needs to be captured let reader = new KvksFileReader(); - kvksFilename = this.callbacks.resolveFilename(kmnFilename, kvksFilename); + kvksFilename = this.callbacks.resolveFilename(kmnFilename, kvksFilename); let kvks = reader.read(this.callbacks.loadFile(kvksFilename)); try { reader.validate(kvks, this.callbacks.loadSchema('kvks')); diff --git a/developer/src/kmcmpdll/compfile.h b/developer/src/kmcmpdll/compfile.h index 2f6e2e654f..9e65c36600 100644 --- a/developer/src/kmcmpdll/compfile.h +++ b/developer/src/kmcmpdll/compfile.h @@ -87,7 +87,7 @@ struct FILE_STORE { BOOL fIsDebug; BOOL fIsCall; int line; // TODO: int vs dword, line vs Line (see FILE_KEY, FILE_GROUP) - }; +}; typedef FILE_STORE *PFILE_STORE; @@ -98,7 +98,7 @@ struct FILE_KEY { DWORD ShiftFlags; PWSTR dpOutput; // from start of key structure PWSTR dpContext; // from start of key structure - }; +}; typedef FILE_KEY *PFILE_KEY; struct FILE_GROUP { @@ -114,22 +114,19 @@ struct FILE_GROUP { typedef FILE_GROUP *PFILE_GROUP; -struct FILE_DEADKEY -{ +struct FILE_DEADKEY { WCHAR szName[SZMAX_DEADKEYNAME]; }; typedef FILE_DEADKEY *PFILE_DEADKEY; -struct FILE_VKDICTIONARY -{ +struct FILE_VKDICTIONARY { WCHAR szName[SZMAX_VKDICTIONARYNAME]; }; - typedef FILE_VKDICTIONARY *PFILE_VKDICTIONARY; struct FILE_KEYBOARD { - DWORD KeyboardID; // as stored in HKEY_LOCAL_MACHINE//system//currentcontrolset//control//keyboard layouts + DWORD KeyboardID; // deprecated, unused DWORD version; // keyboard file version with VERSION keyword @@ -179,7 +176,7 @@ struct COMPMSG { char szText[SZMAX_ERRORTEXT]; DWORD Line; DWORD dwMsgCode; - }; +}; typedef COMPMSG *PCOMPMSG; @@ -193,7 +190,7 @@ struct COMPILEMESSAGES { char szFatalText[SZMAX_ERRORTEXT]; DWORD currentLine; - }; +}; typedef COMPILEMESSAGES *PCOMPILEMESSAGES; diff --git a/developer/src/kmcmplib/src/compfile.h b/developer/src/kmcmplib/src/compfile.h index 4b639a7eb1..595d1fecec 100644 --- a/developer/src/kmcmplib/src/compfile.h +++ b/developer/src/kmcmplib/src/compfile.h @@ -82,7 +82,7 @@ struct FILE_STORE { KMX_BOOL fIsDebug; KMX_BOOL fIsCall; int line; - }; +}; typedef FILE_STORE *PFILE_STORE; @@ -93,7 +93,7 @@ struct FILE_KEY { KMX_DWORD ShiftFlags; PKMX_WCHAR dpOutput; // from start of key structure PKMX_WCHAR dpContext; // from start of key structure - }; +}; typedef FILE_KEY *PFILE_KEY; struct FILE_GROUP { @@ -108,15 +108,13 @@ struct FILE_GROUP { }; typedef FILE_GROUP *PFILE_GROUP; -struct FILE_DEADKEY -{ +struct FILE_DEADKEY { KMX_WCHAR szName[SZMAX_DEADKEYNAME]; }; typedef FILE_DEADKEY *PFILE_DEADKEY; -struct FILE_VKDICTIONARY -{ +struct FILE_VKDICTIONARY { KMX_WCHAR szName[SZMAX_VKDICTIONARYNAME]; }; typedef FILE_VKDICTIONARY *PFILE_VKDICTIONARY; @@ -131,7 +129,7 @@ struct FILE_KEYBOARD_EXTRA { typedef struct FILE_KEYBOARD_EXTRA* PFILE_KEYBOARD_EXTRA; struct FILE_KEYBOARD { - KMX_DWORD KeyboardID; // as stored in HKEY_LOCAL_MACHINE//system//currentcontrolset//control//keyboard layouts + KMX_DWORD KeyboardID; // deprecated, unused KMX_DWORD version; // keyboard file version with VERSION keyword @@ -159,7 +157,7 @@ struct FILE_KEYBOARD { KMX_DWORD cxVKDictionary; PFILE_VKDICTIONARY dpVKDictionary; // temp - virtual key dictionary - PFILE_KEYBOARD_EXTRA extra; + PFILE_KEYBOARD_EXTRA extra; }; typedef FILE_KEYBOARD *PFILE_KEYBOARD; @@ -181,7 +179,7 @@ struct COMPMSG { KMX_CHAR szText[SZMAX_ERRORTEXT]; KMX_DWORD Line; KMX_DWORD dwMsgCode; - }; +}; typedef COMPMSG *PCOMPMSG; @@ -195,7 +193,7 @@ struct COMPILEMESSAGES { KMX_CHAR szFatalText[SZMAX_ERRORTEXT]; KMX_DWORD currentLine; - }; +}; typedef COMPILEMESSAGES *PCOMPILEMESSAGES;