mirror of
https://github.com/keymanapp/keyman.git
synced 2026-10-12 08:57:30 +00:00
Merge remote-tracking branch 'origin/master' into fv-all/keyboards-json
This commit is contained in:
commit
5fca4c7d85
71 changed files with 1917 additions and 1575 deletions
14
HISTORY.md
14
HISTORY.md
|
|
@ -1,5 +1,19 @@
|
|||
# Keyman Version History
|
||||
|
||||
## 18.0.81 alpha 2024-08-03
|
||||
|
||||
* chore(developer): Revert "chore(developer): remove redundant references from tsconfig.json" (#12076)
|
||||
* chore(common): use nvm in builds to select a node version automatically (#12069)
|
||||
* refactor(developer): move functions and variables into CompilerErrors.cpp (#12030)
|
||||
* refactor(developer): improve the callbacks for kmcmplib (#12031)
|
||||
* refactor(developer): align kmcmplib error codes and names with kmc-kmn (#12044)
|
||||
* refactor(developer): move error reporting to error site in kmcmplib (part 1) (#12045)
|
||||
* refactor(developer): move error reporting inside `GetCompileTargetsFromTargetsStore` and `ProcessGroupFinish` (#12048)
|
||||
* refactor(developer): move kmcmplib message construction to kmc-kmn (#12059)
|
||||
* refactor(developer): rename compiler error reporting functions in kmcmplib (#12060)
|
||||
* chore(developer): support filename field in kmcmplib compiler messages (#12061)
|
||||
* refactor(developer): replace `VERIFY_KEYBOARD_VERSION()` calls with `VerifyKeyboardVersion()` (#12063)
|
||||
|
||||
## 18.0.80 alpha 2024-07-31
|
||||
|
||||
* chore(developer): remove redundant references from tsconfig.json (#12037)
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
18.0.81
|
||||
18.0.82
|
||||
|
|
@ -29,7 +29,6 @@ const
|
|||
SZMAX_GROUPNAME = 80;
|
||||
SZMAX_DEADKEYNAME = 80;
|
||||
SZMAX_VKDICTIONARYNAME = 80; // I3438
|
||||
SZMAX_ERRORTEXT = 512;
|
||||
|
||||
SZMAX_LANGUAGENAME = 80;
|
||||
SZMAX_KEYBOARDNAME = 80;
|
||||
|
|
|
|||
|
|
@ -23,21 +23,38 @@
|
|||
#ifndef _kmn_compiler_errors_h
|
||||
#define _kmn_compiler_errors_h
|
||||
|
||||
// Compiler Error Masks
|
||||
// Compiler Error Masks -- matches compiler-interfaces.ts
|
||||
|
||||
#define CERR_SEVERITY_MASK 0x0000F000
|
||||
#define CERR_MESSAGE_MASK 0x00000FFF
|
||||
#define CERR_MASK 0x0000FFFF
|
||||
namespace CompilerErrorSeverity {
|
||||
// We use a namespace to stop the enum names leaking out into global namespace scope
|
||||
enum {
|
||||
Info = 0x000000, // Informational, not necessarily a problem
|
||||
Hint = 0x100000, // Something the user might want to be aware of
|
||||
Warn = 0x200000, // Warning: Not great, but we can keep going.
|
||||
Error = 0x300000, // Severe error where we can't continue
|
||||
Fatal = 0x400000, // OOM or should-not-happen internal problem
|
||||
};
|
||||
};
|
||||
|
||||
// Severity codes
|
||||
//
|
||||
// Note: these may not be combined, and are not a bitmask, for historical
|
||||
// reasons they are separate bits
|
||||
#define CERR_FATAL 0x00008000
|
||||
#define CERR_ERROR 0x00004000
|
||||
#define CERR_WARNING 0x00002000
|
||||
#define CERR_HINT 0x00001000
|
||||
#define CERR_INFO 0x00000000
|
||||
#define MESSAGE_SEVERITY_MASK 0x00F00000 // includes reserved bits, 16 possible severity levels
|
||||
#define MESSAGE_ERROR_MASK 0x000FFFFF // error | namespace
|
||||
#define MESSAGE_NAMESPACE_MASK 0x000FF000 // 256 possible namespaces
|
||||
#define MESSAGE_BASEERROR_MASK 0x00000FFF // error code, 2,048 possible error codes per namespace
|
||||
#define MESSAGE_RESERVED_MASK 0xFF000000 // do not use these error values at this time
|
||||
|
||||
#define MESSAGE_NAMESPACE_KmnCompiler 0x2000
|
||||
|
||||
// Severity codes + namespace for shorthand use
|
||||
#define SevFatal (MESSAGE_NAMESPACE_KmnCompiler | CompilerErrorSeverity::Fatal)
|
||||
#define SevError (MESSAGE_NAMESPACE_KmnCompiler | CompilerErrorSeverity::Error)
|
||||
#define SevWarn (MESSAGE_NAMESPACE_KmnCompiler | CompilerErrorSeverity::Warn)
|
||||
#define SevHint (MESSAGE_NAMESPACE_KmnCompiler | CompilerErrorSeverity::Hint)
|
||||
#define SevInfo (MESSAGE_NAMESPACE_KmnCompiler | CompilerErrorSeverity::Info)
|
||||
|
||||
// These two values are not true error codes; they are used as
|
||||
// return values in kmcmplib and are never passed to kmc-kmn
|
||||
#define STATUS_Success 0x00000000 // NOTE: Not a message code
|
||||
#define STATUS_EndOfFile 0x00000001 // NOTE: Not a message code
|
||||
|
||||
// Message codes
|
||||
//
|
||||
|
|
@ -46,215 +63,216 @@
|
|||
// sure to update that file also. Note that this correlation is currently
|
||||
// maintained manually. All values must be below 0x1000 (exclusive of severity
|
||||
// code).
|
||||
#define CERR_None 0x00000000
|
||||
#define CERR_EndOfFile 0x00000001
|
||||
|
||||
#define CERR_BadCallParams 0x00008002 // TODO: rename to CFATAL_
|
||||
#define CERR_CannotAllocateMemory 0x00008004 // TODO: rename to CFATAL_
|
||||
#define CERR_InfileNotExist 0x00004005 // #10678: reduced from fatal to error in 17.0
|
||||
// #define CERR_CannotCreateOutfile 0x00004006 // #10678: reduced from fatal to error in 17.0, but unused
|
||||
#define CERR_UnableToWriteFully 0x00008007 // TODO: rename to CFATAL_
|
||||
#define CERR_CannotReadInfile 0x00004008 // #10678: reduced from fatal to error in 17.0
|
||||
#define CERR_SomewhereIGotItWrong 0x00008009 // TODO: rename to CFATAL_
|
||||
namespace KmnCompilerMessages {
|
||||
enum {
|
||||
FATAL_BadCallParams = SevFatal | 0x002,
|
||||
FATAL_CannotAllocateMemory = SevFatal | 0x004,
|
||||
ERROR_InfileNotExist = SevError | 0x005, // #10678: reduced from fatal to error in 17.0
|
||||
// ERROR_CannotCreateOutfile = SevError | 0x006, // #10678: reduced from fatal to error in 17.0, but unused
|
||||
// FATAL_UnableToWriteFully = SevFatal | 0x007, // unused
|
||||
ERROR_CannotReadInfile = SevError | 0x008, // #10678: reduced from fatal to error in 17.0
|
||||
FATAL_SomewhereIGotItWrong = SevFatal | 0x009,
|
||||
|
||||
#define CERR_InvalidToken 0x0000400A
|
||||
#define CERR_InvalidBegin 0x0000400B
|
||||
#define CERR_InvalidName 0x0000400C
|
||||
#define CERR_InvalidVersion 0x0000400D
|
||||
#define CERR_InvalidLanguageLine 0x0000400E
|
||||
#define CERR_LayoutButNoLanguage 0x0000400F
|
||||
#define CERR_InvalidLayoutLine 0x00004010
|
||||
#define CERR_NoVersionLine 0x00004011
|
||||
#define CERR_InvalidGroupLine 0x00004012
|
||||
#define CERR_InvalidStoreLine 0x00004013
|
||||
#define CERR_InvalidCodeInKeyPartOfRule 0x00004014
|
||||
#define CERR_InvalidDeadkey 0x00004015
|
||||
#define CERR_InvalidValue 0x00004016
|
||||
#define CERR_ZeroLengthString 0x00004017
|
||||
#define CERR_TooManyIndexToKeyRefs 0x00004018
|
||||
#define CERR_UnterminatedString 0x00004019
|
||||
#define CERR_StringInVirtualKeySection 0x0000401A
|
||||
#define CERR_AnyInVirtualKeySection 0x0000401B
|
||||
#define CERR_InvalidAny 0x0000401C
|
||||
#define CERR_StoreDoesNotExist 0x0000401D
|
||||
#define CERR_BeepInVirtualKeySection 0x0000401E
|
||||
#define CERR_IndexInVirtualKeySection 0x0000401F
|
||||
#define CERR_InvalidIndex 0x00004020
|
||||
#define CERR_OutsInVirtualKeySection 0x00004021
|
||||
#define CERR_InvalidOuts 0x00004022
|
||||
#define CERR_ContextInVirtualKeySection 0x00004024
|
||||
#define CERR_InvalidUse 0x00004025
|
||||
#define CERR_GroupDoesNotExist 0x00004026
|
||||
#define CERR_VirtualKeyNotAllowedHere 0x00004027
|
||||
#define CERR_InvalidSwitch 0x00004028
|
||||
#define CERR_NoTokensFound 0x00004029
|
||||
#define CERR_InvalidLineContinuation 0x0000402A
|
||||
#define CERR_LineTooLong 0x0000402B
|
||||
#define CERR_InvalidCopyright 0x0000402C
|
||||
#define CERR_CodeInvalidInThisSection 0x0000402D
|
||||
#define CERR_InvalidMessage 0x0000402E
|
||||
#define CERR_InvalidLanguageName 0x0000402F
|
||||
#define CERR_InvalidBitmapLine 0x00004030
|
||||
#define CERR_CannotReadBitmapFile 0x00004031
|
||||
#define CERR_IndexDoesNotPointToAny 0x00004032
|
||||
#define CERR_ReservedCharacter 0x00004033
|
||||
#define CERR_InvalidCharacter 0x00004034
|
||||
#define CERR_InvalidCall 0x00004035
|
||||
#define CERR_CallInVirtualKeySection 0x00004036
|
||||
#define CERR_CodeInvalidInKeyStore 0x00004037
|
||||
#define CERR_CannotLoadIncludeFile 0x00004038
|
||||
ERROR_InvalidToken = SevError | 0x00A,
|
||||
ERROR_InvalidBegin = SevError | 0x00B,
|
||||
ERROR_InvalidName = SevError | 0x00C,
|
||||
ERROR_InvalidVersion = SevError | 0x00D,
|
||||
ERROR_InvalidLanguageLine = SevError | 0x00E,
|
||||
ERROR_LayoutButNoLanguage = SevError | 0x00F,
|
||||
ERROR_InvalidLayoutLine = SevError | 0x010,
|
||||
ERROR_NoVersionLine = SevError | 0x011,
|
||||
ERROR_InvalidGroupLine = SevError | 0x012,
|
||||
ERROR_InvalidStoreLine = SevError | 0x013,
|
||||
ERROR_InvalidCodeInKeyPartOfRule = SevError | 0x014,
|
||||
ERROR_InvalidDeadkey = SevError | 0x015,
|
||||
ERROR_InvalidValue = SevError | 0x016,
|
||||
ERROR_ZeroLengthString = SevError | 0x017,
|
||||
ERROR_TooManyIndexToKeyRefs = SevError | 0x018,
|
||||
ERROR_UnterminatedString = SevError | 0x019,
|
||||
ERROR_StringInVirtualKeySection = SevError | 0x01A,
|
||||
ERROR_AnyInVirtualKeySection = SevError | 0x01B,
|
||||
ERROR_InvalidAny = SevError | 0x01C,
|
||||
ERROR_StoreDoesNotExist = SevError | 0x01D,
|
||||
ERROR_BeepInVirtualKeySection = SevError | 0x01E,
|
||||
ERROR_IndexInVirtualKeySection = SevError | 0x01F,
|
||||
ERROR_InvalidIndex = SevError | 0x020,
|
||||
ERROR_OutsInVirtualKeySection = SevError | 0x021,
|
||||
ERROR_InvalidOuts = SevError | 0x022,
|
||||
ERROR_ContextInVirtualKeySection = SevError | 0x024,
|
||||
ERROR_InvalidUse = SevError | 0x025,
|
||||
ERROR_GroupDoesNotExist = SevError | 0x026,
|
||||
ERROR_VirtualKeyNotAllowedHere = SevError | 0x027,
|
||||
ERROR_InvalidSwitch = SevError | 0x028,
|
||||
ERROR_NoTokensFound = SevError | 0x029,
|
||||
ERROR_InvalidLineContinuation = SevError | 0x02A,
|
||||
ERROR_LineTooLong = SevError | 0x02B,
|
||||
ERROR_InvalidCopyright = SevError | 0x02C,
|
||||
ERROR_CodeInvalidInThisSection = SevError | 0x02D,
|
||||
ERROR_InvalidMessage = SevError | 0x02E,
|
||||
ERROR_InvalidLanguageName = SevError | 0x02F,
|
||||
ERROR_InvalidBitmapLine = SevError | 0x030,
|
||||
ERROR_CannotReadBitmapFile = SevError | 0x031,
|
||||
ERROR_IndexDoesNotPointToAny = SevError | 0x032,
|
||||
ERROR_ReservedCharacter = SevError | 0x033,
|
||||
ERROR_InvalidCharacter = SevError | 0x034,
|
||||
ERROR_InvalidCall = SevError | 0x035,
|
||||
ERROR_CallInVirtualKeySection = SevError | 0x036,
|
||||
ERROR_CodeInvalidInKeyStore = SevError | 0x037,
|
||||
ERROR_CannotLoadIncludeFile = SevError | 0x038,
|
||||
|
||||
#define CERR_60FeatureOnly_EthnologueCode 0x00004039
|
||||
#define CERR_60FeatureOnly_MnemonicLayout 0x0000403A
|
||||
#define CERR_60FeatureOnly_OldCharPosMatching 0x0000403B
|
||||
#define CERR_60FeatureOnly_NamedCodes 0x0000403C
|
||||
#define CERR_60FeatureOnly_Contextn 0x0000403D
|
||||
#define CERR_501FeatureOnly_Call 0x0000403E
|
||||
ERROR_60FeatureOnly_EthnologueCode = SevError | 0x039,
|
||||
ERROR_60FeatureOnly_MnemonicLayout = SevError | 0x03A,
|
||||
ERROR_60FeatureOnly_OldCharPosMatching = SevError | 0x03B,
|
||||
ERROR_60FeatureOnly_NamedCodes = SevError | 0x03C,
|
||||
ERROR_60FeatureOnly_Contextn = SevError | 0x03D,
|
||||
ERROR_501FeatureOnly_Call = SevError | 0x03E,
|
||||
|
||||
#define CERR_InvalidNamedCode 0x0000403F
|
||||
#define CERR_InvalidSystemStore 0x00004040
|
||||
ERROR_InvalidNamedCode = SevError | 0x03F,
|
||||
ERROR_InvalidSystemStore = SevError | 0x040,
|
||||
|
||||
#define CERR_60FeatureOnly_VirtualCharKey 0x00004044
|
||||
ERROR_60FeatureOnly_VirtualCharKey = SevError | 0x044,
|
||||
|
||||
#define CERR_VersionAlreadyIncluded 0x00004045
|
||||
ERROR_VersionAlreadyIncluded = SevError | 0x045,
|
||||
|
||||
#define CERR_70FeatureOnly 0x00004046
|
||||
ERROR_70FeatureOnly = SevError | 0x046,
|
||||
|
||||
#define CERR_80FeatureOnly 0x00004047
|
||||
#define CERR_InvalidInVirtualKeySection 0x00004048
|
||||
#define CERR_InvalidIf 0x00004049
|
||||
#define CERR_InvalidReset 0x0000404A
|
||||
#define CERR_InvalidSet 0x0000404B
|
||||
#define CERR_InvalidSave 0x0000404C
|
||||
ERROR_80FeatureOnly = SevError | 0x047,
|
||||
ERROR_InvalidInVirtualKeySection = SevError | 0x048,
|
||||
ERROR_InvalidIf = SevError | 0x049,
|
||||
ERROR_InvalidReset = SevError | 0x04A,
|
||||
ERROR_InvalidSet = SevError | 0x04B,
|
||||
ERROR_InvalidSave = SevError | 0x04C,
|
||||
|
||||
#define CERR_InvalidEthnologueCode 0x0000404D
|
||||
ERROR_InvalidEthnologueCode = SevError | 0x04D,
|
||||
|
||||
#define CERR_CannotCreateTempfile 0x0000804E // TODO: rename to CFATAL_
|
||||
FATAL_CannotCreateTempfile = SevFatal | 0x04E,
|
||||
|
||||
#define CERR_90FeatureOnly_IfSystemStores 0x0000404F
|
||||
#define CERR_IfSystemStore_NotFound 0x00004050
|
||||
#define CERR_90FeatureOnly_SetSystemStores 0x00004051
|
||||
#define CERR_SetSystemStore_NotFound 0x00004052
|
||||
#define CERR_90FeatureOnlyVirtualKeyDictionary 0x00004053
|
||||
ERROR_90FeatureOnly_IfSystemStores = SevError | 0x04F,
|
||||
ERROR_IfSystemStore_NotFound = SevError | 0x050,
|
||||
ERROR_90FeatureOnly_SetSystemStores = SevError | 0x051,
|
||||
ERROR_SetSystemStore_NotFound = SevError | 0x052,
|
||||
ERROR_90FeatureOnlyVirtualKeyDictionary = SevError | 0x053,
|
||||
|
||||
#define CERR_NotSupportedInKeymanWebContext 0x00004054
|
||||
#define CERR_NotSupportedInKeymanWebOutput 0x00004055
|
||||
#define CERR_NotSupportedInKeymanWebStore 0x00004056
|
||||
#define CERR_VirtualCharacterKeysNotSupportedInKeymanWeb 0x00004057
|
||||
#define CERR_VirtualKeysNotValidForMnemonicLayouts 0x00004058
|
||||
#define CERR_InvalidTouchLayoutFile 0x00004059
|
||||
#define CERR_TouchLayoutInvalidIdentifier 0x0000405A
|
||||
#define CERR_InvalidKeyCode 0x0000405B
|
||||
#define CERR_90FeatureOnlyLayoutFile 0x0000405C
|
||||
#define CERR_90FeatureOnlyKeyboardVersion 0x0000405D
|
||||
#define CERR_KeyboardVersionFormatInvalid 0x0000405E
|
||||
#define CERR_ContextExHasInvalidOffset 0x0000405F
|
||||
#define CERR_90FeatureOnlyEmbedCSS 0x00004060
|
||||
#define CERR_90FeatureOnlyTargets 0x00004061
|
||||
#define CERR_ContextAndIndexInvalidInMatchNomatch 0x00004062
|
||||
#define CERR_140FeatureOnlyContextAndNotAnyWeb 0x00004063
|
||||
ERROR_NotSupportedInKeymanWebContext = SevError | 0x054,
|
||||
ERROR_NotSupportedInKeymanWebOutput = SevError | 0x055,
|
||||
ERROR_NotSupportedInKeymanWebStore = SevError | 0x056,
|
||||
ERROR_VirtualCharacterKeysNotSupportedInKeymanWeb = SevError | 0x057,
|
||||
ERROR_VirtualKeysNotValidForMnemonicLayouts = SevError | 0x058,
|
||||
ERROR_InvalidTouchLayoutFile = SevError | 0x059,
|
||||
ERROR_TouchLayoutInvalidIdentifier = SevError | 0x05A,
|
||||
ERROR_InvalidKeyCode = SevError | 0x05B,
|
||||
ERROR_90FeatureOnlyLayoutFile = SevError | 0x05C,
|
||||
ERROR_90FeatureOnlyKeyboardVersion = SevError | 0x05D,
|
||||
ERROR_KeyboardVersionFormatInvalid = SevError | 0x05E,
|
||||
ERROR_ContextExHasInvalidOffset = SevError | 0x05F,
|
||||
ERROR_90FeatureOnlyEmbedCSS = SevError | 0x060,
|
||||
ERROR_90FeatureOnlyTargets = SevError | 0x061,
|
||||
ERROR_ContextAndIndexInvalidInMatchNomatch = SevError | 0x062,
|
||||
ERROR_140FeatureOnlyContextAndNotAnyWeb = SevError | 0x063,
|
||||
|
||||
#define CERR_ExpansionMustFollowCharacterOrVKey 0x00004064
|
||||
#define CERR_VKeyExpansionMustBeFollowedByVKey 0x00004065
|
||||
#define CERR_CharacterExpansionMustBeFollowedByCharacter 0x00004066
|
||||
#define CERR_VKeyExpansionMustUseConsistentShift 0x00004067
|
||||
#define CERR_ExpansionMustBePositive 0x00004068
|
||||
ERROR_ExpansionMustFollowCharacterOrVKey = SevError | 0x064,
|
||||
ERROR_VKeyExpansionMustBeFollowedByVKey = SevError | 0x065,
|
||||
ERROR_CharacterExpansionMustBeFollowedByCharacter = SevError | 0x066,
|
||||
ERROR_VKeyExpansionMustUseConsistentShift = SevError | 0x067,
|
||||
ERROR_ExpansionMustBePositive = SevError | 0x068,
|
||||
|
||||
#define CERR_CasedKeysMustContainOnlyVirtualKeys 0x00004069
|
||||
#define CERR_CasedKeysMustNotIncludeShiftStates 0x0000406A
|
||||
#define CERR_CasedKeysNotSupportedWithMnemonicLayout 0x0000406B
|
||||
ERROR_CasedKeysMustContainOnlyVirtualKeys = SevError | 0x069,
|
||||
ERROR_CasedKeysMustNotIncludeShiftStates = SevError | 0x06A,
|
||||
ERROR_CasedKeysNotSupportedWithMnemonicLayout = SevError | 0x06B,
|
||||
|
||||
#define CERR_CannotUseReadWriteGroupFromReadonlyGroup 0x0000406C
|
||||
#define CERR_StatementNotPermittedInReadonlyGroup 0x0000406D
|
||||
#define CERR_OutputInReadonlyGroup 0x0000406E
|
||||
#define CERR_NewContextGroupMustBeReadonly 0x0000406F
|
||||
#define CERR_PostKeystrokeGroupMustBeReadonly 0x00004070
|
||||
ERROR_CannotUseReadWriteGroupFromReadonlyGroup = SevError | 0x06C,
|
||||
ERROR_StatementNotPermittedInReadonlyGroup = SevError | 0x06D,
|
||||
ERROR_OutputInReadonlyGroup = SevError | 0x06E,
|
||||
ERROR_NewContextGroupMustBeReadonly = SevError | 0x06F,
|
||||
ERROR_PostKeystrokeGroupMustBeReadonly = SevError | 0x070,
|
||||
|
||||
#define CERR_DuplicateGroup 0x00004071
|
||||
#define CERR_DuplicateStore 0x00004072
|
||||
#define CERR_RepeatedBegin 0x00004073
|
||||
#define CERR_VirtualKeyInContext 0x00004074
|
||||
ERROR_DuplicateGroup = SevError | 0x071,
|
||||
ERROR_DuplicateStore = SevError | 0x072,
|
||||
ERROR_RepeatedBegin = SevError | 0x073,
|
||||
ERROR_VirtualKeyInContext = SevError | 0x074,
|
||||
|
||||
#define CERR_OutsTooLong 0x00004075
|
||||
#define CERR_ExtendedStringTooLong 0x00004076
|
||||
#define CERR_VirtualKeyExpansionTooLong 0x00004077
|
||||
#define CERR_CharacterRangeTooLong 0x00004078
|
||||
#define CERR_NonBMPCharactersNotSupportedInKeySection 0x00004079
|
||||
ERROR_OutsTooLong = SevError | 0x075,
|
||||
ERROR_ExtendedStringTooLong = SevError | 0x076,
|
||||
ERROR_VirtualKeyExpansionTooLong = SevError | 0x077,
|
||||
ERROR_CharacterRangeTooLong = SevError | 0x078,
|
||||
ERROR_NonBMPCharactersNotSupportedInKeySection = SevError | 0x079,
|
||||
|
||||
#define CERR_InvalidTarget 0x0000407A
|
||||
#define CERR_NoTargetsSpecified 0x0000407B
|
||||
ERROR_InvalidTarget = SevError | 0x07A,
|
||||
ERROR_NoTargetsSpecified = SevError | 0x07B,
|
||||
|
||||
#define CWARN_TooManyWarnings 0x00002080
|
||||
#define CWARN_OldVersion 0x00002081
|
||||
#define CWARN_BitmapNotUsed 0x00002082
|
||||
#define CWARN_CustomLanguagesNotSupported 0x00002083
|
||||
#define CWARN_KeyBadLength 0x00002084
|
||||
#define CWARN_IndexStoreShort 0x00002085
|
||||
#define CWARN_UnicodeInANSIGroup 0x00002086
|
||||
#define CWARN_ANSIInUnicodeGroup 0x00002087
|
||||
#define CWARN_UnicodeSurrogateUsed 0x00002088
|
||||
#define CWARN_ReservedCharacter 0x00002089
|
||||
// Note: CWARN_Info has an "info" severity; this changed in 17.0. Earlier versions
|
||||
// had a special case for CWARN_Info in message output.
|
||||
#define CWARN_Info 0x0000008A
|
||||
#define CINFO_Info CWARN_Info
|
||||
#define CWARN_VirtualKeyWithMnemonicLayout 0x0000208B
|
||||
#define CWARN_VirtualCharKeyWithPositionalLayout 0x0000208C
|
||||
#define CWARN_StoreAlreadyUsedAsOptionOrCall 0x0000208D
|
||||
#define CWARN_StoreAlreadyUsedAsStoreOrCall 0x0000208E
|
||||
#define CWARN_StoreAlreadyUsedAsStoreOrOption 0x0000208F
|
||||
WARN_TooManyWarnings = SevWarn | 0x080,
|
||||
WARN_OldVersion = SevWarn | 0x081,
|
||||
WARN_BitmapNotUsed = SevWarn | 0x082,
|
||||
WARN_CustomLanguagesNotSupported = SevWarn | 0x083,
|
||||
WARN_KeyBadLength = SevWarn | 0x084,
|
||||
WARN_IndexStoreShort = SevWarn | 0x085,
|
||||
WARN_UnicodeInANSIGroup = SevWarn | 0x086,
|
||||
WARN_ANSIInUnicodeGroup = SevWarn | 0x087,
|
||||
WARN_UnicodeSurrogateUsed = SevWarn | 0x088,
|
||||
WARN_ReservedCharacter = SevWarn | 0x089,
|
||||
|
||||
#define CWARN_PunctuationInEthnologueCode 0x00002090
|
||||
INFO_MinimumCoreEngineVersion = SevInfo | 0x08A, // renamed from INFO_Info in 18.0-alpha
|
||||
|
||||
#define CWARN_TouchLayoutMissingLayer 0x00002091
|
||||
#define CWARN_TouchLayoutCustomKeyNotDefined 0x00002092
|
||||
#define CWARN_TouchLayoutMissingRequiredKeys 0x00002093
|
||||
#define CWARN_HelpFileMissing 0x00002094
|
||||
#define CWARN_EmbedJsFileMissing 0x00002095
|
||||
#define CWARN_TouchLayoutFileMissing 0x00002096
|
||||
#define CWARN_VisualKeyboardFileMissing 0x00002097
|
||||
#define CWARN_ExtendedShiftFlagsNotSupportedInKeymanWeb 0x00002098 // I4118
|
||||
#define CWARN_TouchLayoutUnidentifiedKey 0x00002099
|
||||
#define CHINT_UnreachableKeyCode 0x0000109A
|
||||
WARN_VirtualKeyWithMnemonicLayout = SevWarn | 0x08B,
|
||||
WARN_VirtualCharKeyWithPositionalLayout = SevWarn | 0x08C,
|
||||
WARN_StoreAlreadyUsedAsOptionOrCall = SevWarn | 0x08D,
|
||||
WARN_StoreAlreadyUsedAsStoreOrCall = SevWarn | 0x08E,
|
||||
WARN_StoreAlreadyUsedAsStoreOrOption = SevWarn | 0x08F,
|
||||
|
||||
#define CWARN_CouldNotCopyJsonFile 0x0000209B
|
||||
#define CWARN_PlatformNotInTargets 0x0000209C
|
||||
WARN_PunctuationInEthnologueCode = SevWarn | 0x090,
|
||||
|
||||
#define CWARN_HeaderStatementIsDeprecated 0x0000209D
|
||||
#define CWARN_UseNotLastStatementInRule 0x0000209E
|
||||
WARN_TouchLayoutMissingLayer = SevWarn | 0x091,
|
||||
WARN_TouchLayoutCustomKeyNotDefined = SevWarn | 0x092,
|
||||
WARN_TouchLayoutMissingRequiredKeys = SevWarn | 0x093,
|
||||
WARN_HelpFileMissing = SevWarn | 0x094,
|
||||
WARN_EmbedJsFileMissing = SevWarn | 0x095,
|
||||
// WARN_TouchLayoutFileMissing = SevWarn | 0x096,
|
||||
// WARN_VisualKeyboardFileMissing = SevWarn | 0x097,
|
||||
WARN_ExtendedShiftFlagsNotSupportedInKeymanWeb = SevWarn | 0x098, // I4118
|
||||
WARN_TouchLayoutUnidentifiedKey = SevWarn | 0x099,
|
||||
HINT_UnreachableKeyCode = SevHint | 0x09A,
|
||||
|
||||
#define CWARN_TouchLayoutFontShouldBeSameForAllPlatforms 0x0000209F
|
||||
#define CWARN_InvalidJSONMetadataFile 0x000020A0
|
||||
#define CWARN_JSONMetadataOSKFontShouldMatchTouchFont 0x000020A1
|
||||
#define CWARN_KVKFileIsInSourceFormat 0x000020A2
|
||||
// WARN_CouldNotCopyJsonFile = SevWarn | 0x09B,
|
||||
WARN_PlatformNotInTargets = SevWarn | 0x09C,
|
||||
|
||||
#define CWARN_DontMixChiralAndNonChiralModifiers 0x000020A3
|
||||
#define CWARN_MixingLeftAndRightModifiers 0x000020A4
|
||||
WARN_HeaderStatementIsDeprecated = SevWarn | 0x09D,
|
||||
WARN_UseNotLastStatementInRule = SevWarn | 0x09E,
|
||||
|
||||
#define CWARN_LanguageHeadersDeprecatedInKeyman10 0x000020A5
|
||||
WARN_TouchLayoutFontShouldBeSameForAllPlatforms = SevWarn | 0x09F,
|
||||
// WARN_InvalidJSONMetadataFile = SevWarn | 0x0A0,
|
||||
// WARN_JSONMetadataOSKFontShouldMatchTouchFont = SevWarn | 0x0A1,
|
||||
WARN_KVKFileIsInSourceFormat = SevWarn | 0x0A2,
|
||||
|
||||
#define CHINT_NonUnicodeFile 0x000010A6
|
||||
WARN_DontMixChiralAndNonChiralModifiers = SevWarn | 0x0A3,
|
||||
WARN_MixingLeftAndRightModifiers = SevWarn | 0x0A4,
|
||||
|
||||
#define CWARN_TooManyErrorsOrWarnings 0x000020A7
|
||||
WARN_LanguageHeadersDeprecatedInKeyman10 = SevWarn | 0x0A5,
|
||||
|
||||
#define CWARN_HotkeyHasInvalidModifier 0x000020A8
|
||||
HINT_NonUnicodeFile = SevHint | 0x0A6,
|
||||
|
||||
#define CWARN_TouchLayoutSpecialLabelOnNormalKey 0x000020A9
|
||||
// WARN_TooManyErrorsOrWarnings = SevWarn | 0x0A7,
|
||||
|
||||
#define CWARN_OptionStoreNameInvalid 0x000020AA
|
||||
WARN_HotkeyHasInvalidModifier = SevWarn | 0x0A8,
|
||||
|
||||
#define CWARN_NulNotFirstStatementInContext 0x000020AB
|
||||
#define CWARN_IfShouldBeAtStartOfContext 0x000020AC
|
||||
WARN_TouchLayoutSpecialLabelOnNormalKey = SevWarn | 0x0A9,
|
||||
|
||||
#define CWARN_KeyShouldIncludeNCaps 0x000020AD
|
||||
WARN_OptionStoreNameInvalid = SevWarn | 0x0AA,
|
||||
|
||||
#define CHINT_UnreachableRule 0x000010AE
|
||||
WARN_NulNotFirstStatementInContext = SevWarn | 0x0AB,
|
||||
WARN_IfShouldBeAtStartOfContext = SevWarn | 0x0AC,
|
||||
|
||||
#define CWARN_VirtualKeyInOutput 0x000020AF
|
||||
WARN_KeyShouldIncludeNCaps = SevWarn | 0x0AD,
|
||||
|
||||
#define CHINT_IndexStoreLong 0x000010B0
|
||||
HINT_UnreachableRule = SevHint | 0x0AE,
|
||||
|
||||
#define CERR_BufferOverflow 0x000080C0 // TODO: Rename to CFATAL_...
|
||||
#define CERR_Break 0x000080C1 // TODO: Rename to CFATAL_...
|
||||
WARN_VirtualKeyInOutput = SevWarn | 0x0AF,
|
||||
|
||||
HINT_IndexStoreLong = SevHint | 0x0B0,
|
||||
|
||||
FATAL_BufferOverflow = SevFatal | 0x0C0
|
||||
// FATAL_Break = SevFatal | 0x0C1, unused
|
||||
};
|
||||
}
|
||||
|
||||
#endif // _kmn_compiler_errors_h
|
||||
|
|
|
|||
|
|
@ -9,4 +9,7 @@
|
|||
"include": [
|
||||
"./*.ts",
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../../../../common/web/types/" },
|
||||
]
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
"helpers/*.ts",
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../" },
|
||||
],
|
||||
{ "path": "../" },
|
||||
{ "path": "../../test-helpers/" },
|
||||
]
|
||||
}
|
||||
|
|
@ -9,4 +9,9 @@
|
|||
"include": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../../common/web/types" },
|
||||
{ "path": "../kmc-kmn" },
|
||||
{ "path": "../common/web/utils/" },
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,5 +15,7 @@
|
|||
],
|
||||
"references": [
|
||||
{ "path": "../" },
|
||||
{ "path": "../../common/web/test-helpers/" },
|
||||
{ "path": "../../kmc-package/" },
|
||||
]
|
||||
}
|
||||
|
|
@ -16,4 +16,9 @@
|
|||
"src/ttfmeta/lib/*.js",
|
||||
"src/imports/langtags.js",
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../../common/web/types" },
|
||||
{ "path": "../kmc-package/" },
|
||||
{ "path": "../common/web/utils/" },
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { UnicodeSetParser, UnicodeSet, VisualKeyboard, KvkFileReader, KeymanComp
|
|||
import { CompilerCallbacks, CompilerEvent, CompilerOptions, KeymanFileTypes, KvkFileWriter, KvksFileReader } from '@keymanapp/common-types';
|
||||
import * as Osk from './osk.js';
|
||||
import loadWasmHost from '../import/kmcmplib/wasm-host.js';
|
||||
import { KmnCompilerMessages, mapErrorFromKmcmplib } from './kmn-compiler-messages.js';
|
||||
import { KmnCompilerMessages } from './kmn-compiler-messages.js';
|
||||
import { WriteCompiledKeyboard } from '../kmw-compiler/kmw-compiler.js';
|
||||
|
||||
//
|
||||
|
|
@ -57,6 +57,15 @@ export interface KmnCompilerResultExtra {
|
|||
groups: CompilerResultExtraGroup[];
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
export interface KmnCompilerResultMessage {
|
||||
errorCode: number;
|
||||
lineNumber: number;
|
||||
columnNumber: number;
|
||||
filename: string;
|
||||
parameters: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
* Internal in-memory build artifacts from a successful compilation
|
||||
|
|
@ -114,16 +123,6 @@ const baseOptions: KmnCompilerOptions = {
|
|||
warnDeprecatedCode: true,
|
||||
};
|
||||
|
||||
/**
|
||||
* Allows multiple instances of the Compiler class, by ensuring that the
|
||||
* 'unique' kmnCompilerCallback global will be correlated with a specific
|
||||
* instance of the Compiler class
|
||||
*/
|
||||
let callbackProcIdentifier = 0;
|
||||
|
||||
const
|
||||
callbackPrefix = 'kmnCompilerCallbacks_';
|
||||
|
||||
interface MallocAndFree {
|
||||
malloc(sz: number) : number;
|
||||
free(p: number) : null;
|
||||
|
|
@ -139,16 +138,10 @@ let
|
|||
* external IO.
|
||||
*/
|
||||
export class KmnCompiler implements KeymanCompiler, UnicodeSetParser {
|
||||
private readonly callbackID: string; // a unique numeric id added to globals with prefixed names
|
||||
private callbacks: CompilerCallbacks;
|
||||
private wasmExports: MallocAndFree;
|
||||
private options: KmnCompilerOptions;
|
||||
|
||||
constructor() {
|
||||
this.callbackID = callbackPrefix + callbackProcIdentifier.toString();
|
||||
callbackProcIdentifier++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the compiler, including loading the WASM host for kmcmplib.
|
||||
* Copies options.
|
||||
|
|
@ -220,46 +213,6 @@ export class KmnCompiler implements KeymanCompiler, UnicodeSetParser {
|
|||
return true;
|
||||
}
|
||||
|
||||
private compilerMessageCallback = (line: number, code: number, msg: string): number => {
|
||||
this.callbacks.reportMessage(mapErrorFromKmcmplib(line, code, msg));
|
||||
return 1;
|
||||
}
|
||||
|
||||
private cachedFile: {filename: string; data: Uint8Array} = {
|
||||
filename: null,
|
||||
data: null
|
||||
};
|
||||
|
||||
private loadFileCallback = (filename: string, baseFilename: string, buffer: number, bufferSize: number): number => {
|
||||
let resolvedFilename = this.callbacks.resolveFilename(baseFilename, filename);
|
||||
let data: Uint8Array;
|
||||
if(this.cachedFile.filename == resolvedFilename) {
|
||||
data = this.cachedFile.data;
|
||||
}
|
||||
else {
|
||||
data = this.callbacks.loadFile(resolvedFilename);
|
||||
if(!data) {
|
||||
return -1;
|
||||
}
|
||||
this.cachedFile.filename = resolvedFilename;
|
||||
this.cachedFile.data = data;
|
||||
}
|
||||
|
||||
if(buffer == 0) {
|
||||
/* We need to return buffer size required */
|
||||
return data.byteLength;
|
||||
}
|
||||
|
||||
if(bufferSize != data.byteLength) {
|
||||
/* c8 ignore next 2 */
|
||||
throw new Error(`loadFileCallback: second call, expected file size ${bufferSize} == ${data.byteLength}`);
|
||||
}
|
||||
|
||||
Module.HEAP8.set(data, buffer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
private copyWasmResult(wasm_result: any): KmnCompilerResult {
|
||||
let result: KmnCompilerResult = {
|
||||
// We cannot Object.assign or {...} on a wasm-defined object, so...
|
||||
|
|
@ -299,6 +252,31 @@ export class KmnCompiler implements KeymanCompiler, UnicodeSetParser {
|
|||
return new Uint8Array(new Uint8Array(Module.HEAP8.buffer, offset, size));
|
||||
}
|
||||
|
||||
private toTitleCase = (s: string) => s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
|
||||
|
||||
private generateKmcmpLibMessage(filename: string, line: number, code: number, parameters: string[]) {
|
||||
const keys = Object.keys(KmnCompilerMessages);
|
||||
const m = KmnCompilerMessages as Record<string,any>;
|
||||
const key = keys.find(key => m[key] === code);
|
||||
if(!key) {
|
||||
return `Unknown message ${code.toString(16)} -- message identifier not found`;
|
||||
}
|
||||
|
||||
const o = /^(INFO|HINT|WARN|ERROR|FATAL)_([A-Za-z0-9_]+)$/.exec(key);
|
||||
if(!o) {
|
||||
return `Unknown message ${code.toString(16)} -- message identifier is not a valid format`;
|
||||
}
|
||||
|
||||
const generator = this.toTitleCase(o[1])+'_'+o[2];
|
||||
if(!generator || typeof m[generator] != 'function') {
|
||||
return `Unknown message ${code.toString(16)} -- generator function not found`;
|
||||
}
|
||||
const result = m[generator]({p:parameters});
|
||||
result.filename = filename;
|
||||
result.line = line;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles a .kmn file to .kmx, .kvk, and/or .js files. Returns an object
|
||||
* containing binary artifacts on success. The files are passed in by name,
|
||||
|
|
@ -322,12 +300,17 @@ export class KmnCompiler implements KeymanCompiler, UnicodeSetParser {
|
|||
|
||||
outfile = outfile ?? infile.replace(/\.kmn$/i, '.kmx');
|
||||
|
||||
(globalThis as any)[this.callbackID] = {
|
||||
message: this.compilerMessageCallback,
|
||||
loadFile: this.loadFileCallback
|
||||
};
|
||||
const compiler = this;
|
||||
const wasm_callbacks = Module.WasmCallbackInterface.implement({
|
||||
message: function(message: KmnCompilerResultMessage) {
|
||||
compiler.callbacks.reportMessage(compiler.generateKmcmpLibMessage(message.filename, message.lineNumber, message.errorCode, message.parameters));
|
||||
},
|
||||
loadFile: function(filename: string, baseFilename: string): number[] {
|
||||
const data: Uint8Array = compiler.callbacks.loadFile(compiler.callbacks.resolveFilename(baseFilename, filename));
|
||||
return data ? Array.from(data) : null;
|
||||
}
|
||||
});
|
||||
|
||||
let wasm_interface = new Module.CompilerInterface();
|
||||
let wasm_options = new Module.CompilerOptions();
|
||||
let wasm_result = null;
|
||||
try {
|
||||
|
|
@ -336,8 +319,8 @@ export class KmnCompiler implements KeymanCompiler, UnicodeSetParser {
|
|||
wasm_options.warnDeprecatedCode = options.warnDeprecatedCode;
|
||||
wasm_options.shouldAddCompilerVersion = options.shouldAddCompilerVersion;
|
||||
wasm_options.target = 0; // CKF_KEYMAN; TODO use COMPILETARGETS_KMX
|
||||
wasm_interface.callbacksKey = this.callbackID; // key of object on globalThis
|
||||
wasm_result = Module.kmcmp_compile(infile, wasm_options, wasm_interface);
|
||||
|
||||
wasm_result = Module.kmcmp_compile(infile, wasm_options, wasm_callbacks);
|
||||
if(!wasm_result.result) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -382,7 +365,7 @@ export class KmnCompiler implements KeymanCompiler, UnicodeSetParser {
|
|||
// should have no impact on the final .js if options.debug is false
|
||||
wasm_options.saveDebug = true;
|
||||
|
||||
wasm_result = Module.kmcmp_compile(infile, wasm_options, wasm_interface);
|
||||
wasm_result = Module.kmcmp_compile(infile, wasm_options, wasm_callbacks);
|
||||
if(!wasm_result.result) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -405,9 +388,8 @@ export class KmnCompiler implements KeymanCompiler, UnicodeSetParser {
|
|||
if(wasm_result) {
|
||||
wasm_result.delete();
|
||||
}
|
||||
wasm_interface.delete();
|
||||
wasm_callbacks.delete();
|
||||
wasm_options.delete();
|
||||
delete (globalThis as any)[this.callbackID];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,30 +18,6 @@ const mw = (code: number, message: string, o?: {filename?: string, line?: number
|
|||
line: o?.line,
|
||||
});
|
||||
|
||||
/**
|
||||
* LogLevel comes from kmn_compiler_errors.h, for legacy compiler error messages
|
||||
*/
|
||||
const enum LogLevel {
|
||||
LEVEL_MASK = 0xF000,
|
||||
CODE_MASK = 0x0FFF,
|
||||
CERR_FATAL = 0x8000,
|
||||
CERR_ERROR = 0x4000,
|
||||
CERR_WARNING = 0x2000,
|
||||
CERR_HINT = 0x1000,
|
||||
CERR_INFO = 0
|
||||
};
|
||||
|
||||
/**
|
||||
* Translate the legacy compiler error messages to Severity codes
|
||||
*/
|
||||
const LogLevelToSeverity: Record<number,number> = {
|
||||
[LogLevel.CERR_FATAL]: SevFatal,
|
||||
[LogLevel.CERR_ERROR]: SevError,
|
||||
[LogLevel.CERR_WARNING]: SevWarn,
|
||||
[LogLevel.CERR_HINT]: SevHint,
|
||||
[LogLevel.CERR_INFO]: SevInfo
|
||||
}
|
||||
|
||||
export const enum KmnCompilerMessageRanges {
|
||||
RANGE_KMN_COMPILER_MIN = 0x001, // from kmn_compiler_errors.h
|
||||
RANGE_KMN_COMPILER_MAX = 0x7FF, // from kmn_compiler_errors.h
|
||||
|
|
@ -51,6 +27,8 @@ export const enum KmnCompilerMessageRanges {
|
|||
RANGE_CompilerMessage_Max = 0xFFF, // Highest available error code for kmc-kmn
|
||||
}
|
||||
|
||||
type KmcmpLibMessageParameters = {p:string[]};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
|
|
@ -211,10 +189,8 @@ export class KmnCompilerMessages {
|
|||
to the file.`
|
||||
);
|
||||
|
||||
// static INFO_None = SevInfo | 0x000;
|
||||
|
||||
static INFO_EndOfFile = SevInfo | 0x001;
|
||||
static Info_EndOfFile = () => m(this.INFO_EndOfFile, `(no error - reserved code)`);
|
||||
// static STATUS_None = 0x000; // This is not a real error
|
||||
// static STATUS_EndOfFile = 0x001; // This is not a real error
|
||||
|
||||
static FATAL_BadCallParams = SevFatal | 0x002;
|
||||
static Fatal_BadCallParams = () => m(this.FATAL_BadCallParams, `CompileKeyboardFile was called with bad parameters`);
|
||||
|
|
@ -228,8 +204,8 @@ export class KmnCompilerMessages {
|
|||
// static ERROR_CannotCreateOutfile = SevError | 0x006; // #10678: reduced from fatal to error in 17.0, but unused
|
||||
// static Error_CannotCreateOutfile = () => m(this.ERROR_CannotCreateOutfile, `Cannot open output file for writing`); unused
|
||||
|
||||
static FATAL_UnableToWriteFully = SevFatal | 0x007;
|
||||
static Fatal_UnableToWriteFully = () => m(this.FATAL_UnableToWriteFully, `Unable to write the file completely`);
|
||||
// static FATAL_UnableToWriteFully = SevFatal | 0x007;
|
||||
// static Fatal_UnableToWriteFully = () => m(this.FATAL_UnableToWriteFully, `Unable to write the file completely`);
|
||||
|
||||
static ERROR_CannotReadInfile = SevError | 0x008; // #10678: reduced from fatal to error in 17.0
|
||||
static Error_CannotReadInfile = () => m(this.ERROR_CannotReadInfile, `Cannot read the input file`);
|
||||
|
|
@ -548,10 +524,16 @@ export class KmnCompilerMessages {
|
|||
static Error_PostKeystrokeGroupMustBeReadonly = () => m(this.ERROR_PostKeystrokeGroupMustBeReadonly, `Group used in begin postKeystroke must be readonly`);
|
||||
|
||||
static ERROR_DuplicateGroup = SevError | 0x071;
|
||||
static Error_DuplicateGroup = () => m(this.ERROR_DuplicateGroup, `A group with this name has already been defined.`);
|
||||
static Error_DuplicateGroup = (o:KmcmpLibMessageParameters) => m(
|
||||
this.ERROR_DuplicateGroup,
|
||||
`A group with the name '${o.p?.[0]}' has already been defined on line ${o.p?.[1]}.`
|
||||
);
|
||||
|
||||
static ERROR_DuplicateStore = SevError | 0x072;
|
||||
static Error_DuplicateStore = () => m(this.ERROR_DuplicateStore, `A store with this name has already been defined.`);
|
||||
static Error_DuplicateStore = (o:KmcmpLibMessageParameters) => m(
|
||||
this.ERROR_DuplicateStore,
|
||||
`A store with the name '${o.p?.[0]}' has already been defined on line ${o.p?.[1]}.`
|
||||
);
|
||||
|
||||
static ERROR_RepeatedBegin = SevError | 0x073;
|
||||
static Error_RepeatedBegin = () => m(this.ERROR_RepeatedBegin, `Begin has already been set`);
|
||||
|
|
@ -575,7 +557,10 @@ export class KmnCompilerMessages {
|
|||
static Error_NonBMPCharactersNotSupportedInKeySection = () => m(this.ERROR_NonBMPCharactersNotSupportedInKeySection, `Characters with codepoints over U+FFFF are not supported in the key part of the rule`);
|
||||
|
||||
static ERROR_InvalidTarget = SevError | 0x07A;
|
||||
static Error_InvalidTarget = () => m(this.ERROR_InvalidTarget, `Unrecognized compile target`);
|
||||
static Error_InvalidTarget = (o:KmcmpLibMessageParameters) => m(
|
||||
this.ERROR_InvalidTarget,
|
||||
`Unrecognized compile target '${o.p?.[0]}'`
|
||||
);
|
||||
|
||||
static ERROR_NoTargetsSpecified = SevError | 0x07B;
|
||||
static Error_NoTargetsSpecified = () => m(this.ERROR_NoTargetsSpecified, `At least one compile target must be specified`);
|
||||
|
|
@ -610,10 +595,11 @@ export class KmnCompilerMessages {
|
|||
static WARN_ReservedCharacter = SevWarn | 0x089;
|
||||
static Warn_ReservedCharacter = () => m(this.WARN_ReservedCharacter, `A Unicode character was found that should not be used`);
|
||||
|
||||
// Note: INFO_Info is called CWARN_Info in kmn_compiler_errors.h, but should have an "info" severity
|
||||
static INFO_Info = SevInfo | 0x08A;
|
||||
static Info_Info = () => m(this.INFO_Info, `Information`);
|
||||
|
||||
static INFO_MinimumCoreEngineVersion = SevInfo | 0x08A;
|
||||
static Info_MinimumCoreEngineVersion = (o:KmcmpLibMessageParameters) => m(
|
||||
this.INFO_MinimumCoreEngineVersion,
|
||||
`The compiler has assigned a minimum engine version of ${o.p?.[0]}.${o.p?.[1]} based on features used in this keyboard`
|
||||
);
|
||||
|
||||
static WARN_VirtualKeyWithMnemonicLayout = SevWarn | 0x08B;
|
||||
static Warn_VirtualKeyWithMnemonicLayout = () => m(this.WARN_VirtualKeyWithMnemonicLayout, `Virtual key used instead of virtual character key with a mnemonic layout`);
|
||||
|
|
@ -730,7 +716,10 @@ export class KmnCompilerMessages {
|
|||
static Warn_KeyShouldIncludeNCaps = () => m(this.WARN_KeyShouldIncludeNCaps, `Other rules which reference this key include CAPS or NCAPS modifiers, so this rule must include NCAPS modifier to avoid inconsistent matches`);
|
||||
|
||||
static HINT_UnreachableRule = SevHint | 0x0AE;
|
||||
static Hint_UnreachableRule = () => m(this.HINT_UnreachableRule, `This rule will never be matched as another rule takes precedence`);
|
||||
static Hint_UnreachableRule = (o:KmcmpLibMessageParameters) => m(
|
||||
this.HINT_UnreachableRule,
|
||||
`This rule will never be matched as the rule on line ${o.p?.[0]} takes precedence`
|
||||
);
|
||||
|
||||
static WARN_VirtualKeyInOutput = SevWarn | 0x0AF;
|
||||
static Warn_VirtualKeyInOutput = () => m(this.WARN_VirtualKeyInOutput, `Virtual keys are not supported in output`);
|
||||
|
|
@ -744,17 +733,6 @@ export class KmnCompilerMessages {
|
|||
static FATAL_BufferOverflow = SevFatal | 0x0C0;
|
||||
static Fatal_BufferOverflow = () => m(this.FATAL_BufferOverflow, `The compiler memory buffer overflowed`);
|
||||
|
||||
static FATAL_Break = SevFatal | 0x0C1;
|
||||
static Fatal_Break = () => m(this.FATAL_Break, `Compiler interrupted by user`);
|
||||
};
|
||||
|
||||
export function mapErrorFromKmcmplib(line: number, code: number, msg: string): CompilerEvent {
|
||||
const severity = LogLevelToSeverity[code & LogLevel.LEVEL_MASK];
|
||||
const baseCode = code & LogLevel.CODE_MASK;
|
||||
const event: CompilerEvent = {
|
||||
line: line,
|
||||
code: severity | CompilerErrorNamespace.KmnCompiler | baseCode,
|
||||
message: msg
|
||||
};
|
||||
return event;
|
||||
// static FATAL_Break = SevFatal | 0x0C1;
|
||||
// static Fatal_Break = () => m(this.FATAL_Break, `Compiler interrupted by user`);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -49,7 +49,9 @@ export class KmwCompilerMessages extends KmnCompilerMessages {
|
|||
static Hint_TouchLayoutUsesUnsupportedGesturesDownlevel = (o:{keyId:string}) => m(this.HINT_TouchLayoutUsesUnsupportedGesturesDownlevel,
|
||||
`The touch layout uses a flick or multi-tap gesture on key ${def(o.keyId)}, which is only available on version 17.0+ of Keyman`);
|
||||
|
||||
static INFO_MinimumEngineVersion = SevInfo | 0x0006;
|
||||
static Info_MinimumEngineVersion = (o:{version:string}) => m(this.INFO_MinimumEngineVersion,
|
||||
`The compiler has assigned a minimum web engine version of ${o.version} based on features used in this keyboard`);
|
||||
static INFO_MinimumWebEngineVersion = SevInfo | 0x0006;
|
||||
static Info_MinimumWebEngineVersion = (o:{version:string}) => m(
|
||||
this.INFO_MinimumWebEngineVersion,
|
||||
`The compiler has assigned a minimum web engine version of ${o.version} based on features used in this keyboard`
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -412,7 +412,7 @@ export function WriteCompiledKeyboard(
|
|||
if((fk.flags & KMX.KMXFile.KF_AUTOMATICVERSION) == KMX.KMXFile.KF_AUTOMATICVERSION) {
|
||||
// Note: the KeymanWeb compiler is responsible for reporting minimum
|
||||
// version for the web targets
|
||||
callbacks.reportMessage(KmwCompilerMessages.Info_MinimumEngineVersion({version:minVer}));
|
||||
callbacks.reportMessage(KmwCompilerMessages.Info_MinimumWebEngineVersion({version:minVer}));
|
||||
}
|
||||
|
||||
return resultPrefix + resultMinVer + result;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
c Description: Verifies that kmcmplib picks up on duplicated groups with Unicode names,
|
||||
c and that the Unicode names are correctly reported in error messages in UTF-8
|
||||
|
||||
store(&NAME) 'cerr_duplicate_group'
|
||||
store(&NAME) 'error_duplicate_group'
|
||||
store(&VERSION) '9.0'
|
||||
|
||||
begin unicode > use(ខ្មែរ)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
c Description: Verifies that kmcmplib picks up on duplicated stores with Unicode names,
|
||||
c and that the Unicode names are correctly reported in error messages in UTF-8
|
||||
|
||||
store(&NAME) 'cerr_duplicate_store'
|
||||
store(&NAME) 'error_duplicate_store'
|
||||
store(&VERSION) '9.0'
|
||||
|
||||
begin unicode > use(ខ្មែរ)
|
||||
|
|
|
|||
|
|
@ -87,10 +87,9 @@ describe('KeymanWeb Compiler', function() {
|
|||
|
||||
let result = await kmnCompiler.run(filenames.source, null);
|
||||
assert.isNotNull(result);
|
||||
assert.isTrue(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumEngineVersion));
|
||||
// The min version message from the .kmn compiler is generic 208A INFO_Info;
|
||||
assert.isTrue(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumWebEngineVersion));
|
||||
// we expect only 1 of the info messages -- for the .kmx target (not 2)
|
||||
assert.equal(callbacks.messages.filter(item => item.code == KmnCompilerMessages.INFO_Info).length, 1);
|
||||
assert.equal(callbacks.messages.filter(item => item.code == KmnCompilerMessages.INFO_MinimumCoreEngineVersion).length, 1);
|
||||
|
||||
const data = new TextDecoder('utf-8').decode(result.artifacts.js.data);
|
||||
assert.match(data, /KMINVER="15.0"/, `Could not find expected 'KMINVER="15.0"'`);
|
||||
|
|
@ -101,9 +100,8 @@ describe('KeymanWeb Compiler', function() {
|
|||
|
||||
let result = await kmnCompiler.run(filenames.source, null);
|
||||
assert.isNull(result);
|
||||
// The min version message from the .kmn compiler is generic 208A INFO_Info
|
||||
assert.isFalse(callbacks.hasMessage(KmnCompilerMessages.INFO_Info));
|
||||
assert.isFalse(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumEngineVersion));
|
||||
assert.isFalse(callbacks.hasMessage(KmnCompilerMessages.INFO_MinimumCoreEngineVersion));
|
||||
assert.isFalse(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumWebEngineVersion));
|
||||
assert.isTrue(callbacks.hasMessage(KmwCompilerMessages.ERROR_TouchLayoutIdentifierRequires15));
|
||||
});
|
||||
|
||||
|
|
@ -113,9 +111,8 @@ describe('KeymanWeb Compiler', function() {
|
|||
|
||||
let result = await kmnCompiler.run(filenames.source, null);
|
||||
assert.isNotNull(result); // only a warning, so output is generated
|
||||
// The min version message from the .kmn compiler is generic 208A INFO_Info
|
||||
assert.isFalse(callbacks.hasMessage(KmnCompilerMessages.INFO_Info));
|
||||
assert.isFalse(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumEngineVersion));
|
||||
assert.isFalse(callbacks.hasMessage(KmnCompilerMessages.INFO_MinimumCoreEngineVersion));
|
||||
assert.isFalse(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumWebEngineVersion));
|
||||
assert.isTrue(callbacks.hasMessage(KmwCompilerMessages.WARN_ExtendedShiftFlagsNotSupportedInKeymanWeb));
|
||||
});
|
||||
|
||||
|
|
@ -125,10 +122,9 @@ describe('KeymanWeb Compiler', function() {
|
|||
let result = await kmnCompiler.run(filenames.source, null);
|
||||
assert.isNotNull(result);
|
||||
|
||||
// The min version message from the .kmn compiler is generic 208A INFO_Info;
|
||||
// we expect only 1 of the info messages -- for the .kmx target (not 2)
|
||||
assert.equal(callbacks.messages.filter(item => item.code == KmnCompilerMessages.INFO_Info).length, 1);
|
||||
assert.isTrue(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumEngineVersion));
|
||||
assert.equal(callbacks.messages.filter(item => item.code == KmnCompilerMessages.INFO_MinimumCoreEngineVersion).length, 1);
|
||||
assert.isTrue(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumWebEngineVersion));
|
||||
assert.isFalse(callbacks.hasMessage(KmwCompilerMessages.WARN_ExtendedShiftFlagsNotSupportedInKeymanWeb));
|
||||
|
||||
const data = new TextDecoder('utf-8').decode(result.artifacts.js.data);
|
||||
|
|
@ -142,10 +138,9 @@ describe('KeymanWeb Compiler', function() {
|
|||
|
||||
let result = await kmnCompiler.run(filenames.source, null);
|
||||
assert.isNotNull(result);
|
||||
assert.isTrue(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumEngineVersion));
|
||||
// The min version message from the .kmn compiler is generic 208A INFO_Info;
|
||||
assert.isTrue(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumWebEngineVersion));
|
||||
// we expect only 1 of the info messages -- for the .kmx target (not 2)
|
||||
assert.equal(callbacks.messages.filter(item => item.code == KmnCompilerMessages.INFO_Info).length, 1);
|
||||
assert.equal(callbacks.messages.filter(item => item.code == KmnCompilerMessages.INFO_MinimumCoreEngineVersion).length, 1);
|
||||
|
||||
const data = new TextDecoder('utf-8').decode(result.artifacts.js.data);
|
||||
assert.match(data, /KMINVER="14.0"/, `Could not find expected 'KMINVER="14.0"'`);
|
||||
|
|
@ -157,9 +152,8 @@ describe('KeymanWeb Compiler', function() {
|
|||
|
||||
let result = await kmnCompiler.run(filenames.source, null);
|
||||
assert.isNull(result);
|
||||
// The min version message from the .kmn compiler is generic 208A INFO_Info
|
||||
assert.isFalse(callbacks.hasMessage(KmnCompilerMessages.INFO_Info));
|
||||
assert.isFalse(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumEngineVersion));
|
||||
assert.isFalse(callbacks.hasMessage(KmnCompilerMessages.INFO_MinimumCoreEngineVersion));
|
||||
assert.isFalse(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumWebEngineVersion));
|
||||
assert.isTrue(callbacks.hasMessage(KmwCompilerMessages.ERROR_140FeatureOnlyContextAndNotAnyWeb));
|
||||
});
|
||||
|
||||
|
|
@ -168,10 +162,9 @@ describe('KeymanWeb Compiler', function() {
|
|||
|
||||
let result = await kmnCompiler.run(filenames.source, null);
|
||||
assert.isNotNull(result);
|
||||
assert.isTrue(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumEngineVersion));
|
||||
// The min version message from the .kmn compiler is generic 208A INFO_Info;
|
||||
assert.isTrue(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumWebEngineVersion));
|
||||
// we expect only 1 of the info messages -- for the .kmx target (not 2)
|
||||
assert.equal(callbacks.messages.filter(item => item.code == KmnCompilerMessages.INFO_Info).length, 1);
|
||||
assert.equal(callbacks.messages.filter(item => item.code == KmnCompilerMessages.INFO_MinimumCoreEngineVersion).length, 1);
|
||||
|
||||
const data = new TextDecoder('utf-8').decode(result.artifacts.js.data);
|
||||
assert.match(data, /KMINVER="14.0"/, `Could not find expected 'KMINVER="14.0"'`);
|
||||
|
|
@ -182,9 +175,8 @@ describe('KeymanWeb Compiler', function() {
|
|||
|
||||
let result = await kmnCompiler.run(filenames.source, null);
|
||||
assert.isNotNull(result);
|
||||
// The min version message from the .kmn compiler is generic 208A INFO_Info
|
||||
assert.isFalse(callbacks.hasMessage(KmnCompilerMessages.INFO_Info));
|
||||
assert.isFalse(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumEngineVersion));
|
||||
assert.isFalse(callbacks.hasMessage(KmnCompilerMessages.INFO_MinimumCoreEngineVersion));
|
||||
assert.isFalse(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumWebEngineVersion));
|
||||
assert.isTrue(callbacks.hasMessage(KmwCompilerMessages.WARN_TouchLayoutSpecialLabelOnNormalKey));
|
||||
});
|
||||
|
||||
|
|
@ -193,10 +185,9 @@ describe('KeymanWeb Compiler', function() {
|
|||
|
||||
let result = await kmnCompiler.run(filenames.source, null);
|
||||
assert.isNotNull(result);
|
||||
assert.isTrue(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumEngineVersion));
|
||||
// The min version message from the .kmn compiler is generic 208A INFO_Info;
|
||||
assert.isTrue(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumWebEngineVersion));
|
||||
// we expect only 1 of the info messages -- for the .kmx target (not 2)
|
||||
assert.equal(callbacks.messages.filter(item => item.code == KmnCompilerMessages.INFO_Info).length, 1);
|
||||
assert.equal(callbacks.messages.filter(item => item.code == KmnCompilerMessages.INFO_MinimumCoreEngineVersion).length, 1);
|
||||
|
||||
const data = new TextDecoder('utf-8').decode(result.artifacts.js.data);
|
||||
assert.match(data, /KMINVER="17.0"/, `Could not find expected 'KMINVER="17.0"'`);
|
||||
|
|
@ -207,9 +198,8 @@ describe('KeymanWeb Compiler', function() {
|
|||
|
||||
let result = await kmnCompiler.run(filenames.source, null);
|
||||
assert.isNotNull(result);
|
||||
// The min version message from the .kmn compiler is generic 208A INFO_Info
|
||||
assert.isFalse(callbacks.hasMessage(KmnCompilerMessages.INFO_Info));
|
||||
assert.isFalse(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumEngineVersion));
|
||||
assert.isFalse(callbacks.hasMessage(KmnCompilerMessages.INFO_MinimumCoreEngineVersion));
|
||||
assert.isFalse(callbacks.hasMessage(KmwCompilerMessages.INFO_MinimumWebEngineVersion));
|
||||
assert.isTrue(callbacks.hasMessage(KmwCompilerMessages.HINT_TouchLayoutUsesUnsupportedGesturesDownlevel));
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import 'mocha';
|
||||
import { assert } from 'chai';
|
||||
import { KmnCompilerMessages } from '../src/compiler/kmn-compiler-messages.js';
|
||||
import { KmnCompilerMessageRanges, KmnCompilerMessages } from '../src/compiler/kmn-compiler-messages.js';
|
||||
import { TestCompilerCallbacks, verifyCompilerMessagesObject } from '@keymanapp/developer-test-helpers';
|
||||
import { makePathToFixture } from './helpers/index.js';
|
||||
import { KmnCompiler } from '../src/main.js';
|
||||
import { CompilerErrorNamespace } from '@keymanapp/common-types';
|
||||
import { CompilerErrorMask, CompilerErrorNamespace } from '@keymanapp/common-types';
|
||||
|
||||
describe('KmnCompilerMessages', function () {
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
|
|
@ -13,6 +13,69 @@ describe('KmnCompilerMessages', function () {
|
|||
return verifyCompilerMessagesObject(KmnCompilerMessages, CompilerErrorNamespace.KmnCompiler);
|
||||
});
|
||||
|
||||
it('should have a 1:1 correspondence with kmn_compiler_errors.h', function() {
|
||||
|
||||
const headerFilename = 'kmn_compiler_errors.h';
|
||||
const tsFilename = 'kmn-compiler-messages.ts';
|
||||
|
||||
// For each message declared in KmnCompilerMessages, look for a
|
||||
// corresponding message in kmn_compiler_errors.h
|
||||
const headerPath = makePathToFixture(`../../../common/include/${headerFilename}`);
|
||||
|
||||
// Matching the following line pattern from kmn_compiler_errors.h:
|
||||
//
|
||||
// FATAL_BadCallParams = SevFatal | 0x002,
|
||||
const messageRegex = /^\s+((FATAL|ERROR|WARN|HINT|INFO)_[a-z0-9_]+)\s+=\s+Sev(Fatal|Error|Warn|Hint|Info)\s+\|\s+0x([0-9a-f]+)/i;
|
||||
|
||||
// Convert matching lines into array of message code data
|
||||
const cppMessages = callbacks.fs.readFileSync(headerPath, 'utf-8')
|
||||
.replace(/\r/g, '')
|
||||
.split('\n')
|
||||
.filter(line => line.match(messageRegex)) // filter first, run regex twice, ;-)
|
||||
.map(line => {
|
||||
const m = line.match(messageRegex);
|
||||
return { name: m[1], nameSeverity: m[2], maskSeverity: m[3], code: parseInt(m[4],16), found: false }
|
||||
});
|
||||
|
||||
const cppMessagesByName: {[index:string]: {name: string, nameSeverity: string, maskSeveity: string, code: number}} = cppMessages
|
||||
.reduce((obj, m) => {obj[m.name] = m; return obj}, {} as any);
|
||||
|
||||
// We validate that the nameSeverity and maskSeverity line up, as a sanity
|
||||
// check. This conceptually belongs in kmcmplib tests, but much easier to
|
||||
// achieve here
|
||||
cppMessages.forEach(m => {
|
||||
assert.strictEqual(m.maskSeverity.toUpperCase(), m.nameSeverity, `${headerFilename} has mismatching severity for ${m.name} and ${m.maskSeverity}`)
|
||||
});
|
||||
|
||||
// Use same pattern as verifyCompilerMessagesObject to get list of messages
|
||||
// from KmnCompilerMessages
|
||||
const keys = Object.keys(KmnCompilerMessages);
|
||||
const m = KmnCompilerMessages as Record<string,any>;
|
||||
|
||||
for(const key of keys) {
|
||||
// Verify each object member matches the pattern we expect
|
||||
if(typeof m[key] == 'number') {
|
||||
|
||||
if((m[key] & CompilerErrorMask.BaseError) < KmnCompilerMessageRanges.RANGE_KMN_COMPILER_MIN ||
|
||||
(m[key] & CompilerErrorMask.BaseError) > KmnCompilerMessageRanges.RANGE_KMN_COMPILER_MAX) {
|
||||
// Message is not from kmcmplib
|
||||
continue;
|
||||
}
|
||||
|
||||
const cppMessage = cppMessagesByName[key];
|
||||
assert.isDefined(cppMessage, `${key} in ${tsFilename} not found in ${headerFilename}`);
|
||||
assert.equal(cppMessage.name, key, `${key} name in ${tsFilename} does not precisely match ${headerFilename}`);
|
||||
assert.equal(cppMessage.code, m[key] & CompilerErrorMask.BaseError, `${key} in ${tsFilename} has a different value than ${headerFilename}`);
|
||||
|
||||
// Remove the entry so we can spot unpaired messages afterwards
|
||||
delete cppMessagesByName[key];
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure there are no remaining messages in kmn_compiler_errors.h
|
||||
assert.isEmpty(Object.keys(cppMessagesByName), `${headerFilename} has entries not found in ${tsFilename}: ${JSON.stringify(cppMessagesByName)}`);
|
||||
});
|
||||
|
||||
//
|
||||
// Message tests
|
||||
//
|
||||
|
|
|
|||
|
|
@ -12,4 +12,9 @@
|
|||
"src/**/*.ts",
|
||||
"src/import/kmcmplib/wasm-host.js"
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../../common/web/types/" },
|
||||
{ "path": "../../../common/web/keyman-version/" },
|
||||
{ "path": "../common/web/utils/" },
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@
|
|||
"./helpers/index.ts"
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../../../common/web/keyman-version" },
|
||||
{ "path": "../../../../common/web/types/" },
|
||||
{ "path": "../../../../common/tools/hextobin/" },
|
||||
{ "path": "../../common/web/test-helpers/" },
|
||||
{ "path": "../" }
|
||||
]
|
||||
}
|
||||
|
|
@ -9,4 +9,10 @@
|
|||
"include": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../../common/web/keyman-version" },
|
||||
{ "path": "../../../common/web/types/" },
|
||||
{ "path": "../kmc-kmn/" },
|
||||
{ "path": "../../../core/include/ldml/"},
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,5 +15,7 @@
|
|||
],
|
||||
"references": [
|
||||
{ "path": "../" },
|
||||
{ "path": "../../common/web/test-helpers/" },
|
||||
{ "path": "../../kmc-package/" },
|
||||
]
|
||||
}
|
||||
|
|
@ -8,4 +8,9 @@
|
|||
"include": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../../common/web/types" },
|
||||
{ "path": "../../../common/models/types" },
|
||||
{ "path": "../common/web/utils" },
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,5 +17,6 @@
|
|||
],
|
||||
"references": [
|
||||
{ "path": "../" },
|
||||
{ "path": "../../common/web/test-helpers/" },
|
||||
]
|
||||
}
|
||||
|
|
@ -10,4 +10,9 @@
|
|||
"include": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../../common/web/keyman-version" },
|
||||
{ "path": "../../../common/models/types" },
|
||||
{ "path": "../../../common/web/types" },
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,5 +14,8 @@
|
|||
],
|
||||
"references": [
|
||||
{ "path": "../" },
|
||||
{ "path": "../../../../common/web/types" },
|
||||
{ "path": "../../../../common/web/keyman-version" },
|
||||
{ "path": "../../common/web/test-helpers/" },
|
||||
]
|
||||
}
|
||||
|
|
@ -9,4 +9,8 @@
|
|||
"include": [
|
||||
"src/**/*.ts",
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../../common/web/keyman-version" },
|
||||
{ "path": "../../../common/web/types" },
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
"./helpers/index.ts",
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../../../common/web/types/" },
|
||||
{ "path": "../../common/web/test-helpers/" },
|
||||
{ "path": "../" }
|
||||
]
|
||||
}
|
||||
|
|
@ -9,4 +9,15 @@
|
|||
"include": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../../common/web/keyman-version" },
|
||||
{ "path": "../../../common/web/types" },
|
||||
{ "path": "../kmc-analyze" },
|
||||
{ "path": "../kmc-keyboard-info" },
|
||||
{ "path": "../kmc-kmn" },
|
||||
{ "path": "../kmc-ldml" },
|
||||
{ "path": "../kmc-model" },
|
||||
{ "path": "../kmc-model-info" },
|
||||
{ "path": "../kmc-package" },
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,14 @@ struct KMCMP_COMPILER_RESULT_EXTRA_GROUP {
|
|||
std::string name;
|
||||
};
|
||||
|
||||
struct KMCMP_COMPILER_RESULT_MESSAGE {
|
||||
unsigned int errorCode;
|
||||
int lineNumber;
|
||||
int columnNumber;
|
||||
std::string filename;
|
||||
std::vector<std::string> parameters;
|
||||
};
|
||||
|
||||
#define COMPILETARGETS_KMX 0x01
|
||||
#define COMPILETARGETS_JS 0x02
|
||||
#define COMPILETARGETS__MASK 0x03
|
||||
|
|
@ -75,19 +83,8 @@ struct KMCMP_COMPILER_RESULT {
|
|||
/**
|
||||
* @param szText UTF-8 string
|
||||
*/
|
||||
typedef int (*kmcmp_CompilerMessageProc)(int line, uint32_t dwMsgCode, const 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)(const char* loadFilename, const char* baseFilename, void* buffer, int* bufferSize, void* context);
|
||||
typedef void (*kmcmp_CompilerMessageProc)(const KMCMP_COMPILER_RESULT_MESSAGE &message, void* context);
|
||||
typedef const std::vector<uint8_t> (*kmcmp_LoadFileProc)(const std::string& loadFilename, const std::string& baseFilename);
|
||||
|
||||
/**
|
||||
* @param pszInfile UTF-8 path to file.kmn
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ KMX_DWORD VerifyCasedKeys(PFILE_STORE sp) {
|
|||
if (kmcmp::FMnemonicLayout) {
|
||||
// The &CasedKeys system store is not supported for
|
||||
// mnemonic layouts in 14.0
|
||||
return CERR_CasedKeysNotSupportedWithMnemonicLayout;
|
||||
return KmnCompilerMessages::ERROR_CasedKeysNotSupportedWithMnemonicLayout;
|
||||
}
|
||||
|
||||
// We will rewrite this store with virtual keys
|
||||
|
|
@ -37,20 +37,20 @@ KMX_DWORD VerifyCasedKeys(PFILE_STORE sp) {
|
|||
KMX_UINT key = 0, shift = 0;
|
||||
if (*p != UC_SENTINEL) {
|
||||
if (!kmcmp::MapUSCharToVK(*p, &key, &shift)) {
|
||||
return CERR_CasedKeysMustContainOnlyVirtualKeys;
|
||||
return KmnCompilerMessages::ERROR_CasedKeysMustContainOnlyVirtualKeys;
|
||||
}
|
||||
if (shift & K_SHIFTFLAG) {
|
||||
return CERR_CasedKeysMustNotIncludeShiftStates;
|
||||
return KmnCompilerMessages::ERROR_CasedKeysMustNotIncludeShiftStates;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (*(p + 1) != CODE_EXTENDED) {
|
||||
return CERR_CasedKeysMustContainOnlyVirtualKeys;
|
||||
return KmnCompilerMessages::ERROR_CasedKeysMustContainOnlyVirtualKeys;
|
||||
}
|
||||
shift = *(p + 2);
|
||||
key = *(p + 3);
|
||||
if (shift != ISVIRTUALKEY) {
|
||||
return CERR_CasedKeysMustNotIncludeShiftStates;
|
||||
return KmnCompilerMessages::ERROR_CasedKeysMustNotIncludeShiftStates;
|
||||
}
|
||||
}
|
||||
*q++ = UC_SENTINEL;
|
||||
|
|
@ -66,7 +66,7 @@ KMX_DWORD VerifyCasedKeys(PFILE_STORE sp) {
|
|||
delete[] sp->dpString;
|
||||
sp->dpString = buf;
|
||||
|
||||
return CERR_None;
|
||||
return STATUS_Success;
|
||||
}
|
||||
|
||||
KMX_DWORD ExpandCapsRulesForGroup(PFILE_KEYBOARD fk, PFILE_GROUP gp) {
|
||||
|
|
@ -76,14 +76,14 @@ KMX_DWORD ExpandCapsRulesForGroup(PFILE_KEYBOARD fk, PFILE_GROUP gp) {
|
|||
if (kmcmp::FMnemonicLayout) {
|
||||
// The &CasedKeys system store is not supported for
|
||||
// mnemonic layouts in 14.0
|
||||
return CERR_None;
|
||||
return STATUS_Success;
|
||||
}
|
||||
|
||||
PFILE_STORE sp = FindSystemStore(fk, TSS_CASEDKEYS);
|
||||
if (!sp) {
|
||||
// If there is no &CasedKeys system store, then we do not
|
||||
// process the key
|
||||
return CERR_None;
|
||||
return STATUS_Success;
|
||||
}
|
||||
|
||||
KMX_DWORD msg;
|
||||
|
|
@ -92,11 +92,11 @@ KMX_DWORD ExpandCapsRulesForGroup(PFILE_KEYBOARD fk, PFILE_GROUP gp) {
|
|||
// dereference the array every call
|
||||
int cxKeyArray = gp->cxKeyArray;
|
||||
for (int i = 0; i < cxKeyArray; i++) {
|
||||
if ((msg = ExpandCapsRule(gp, &gp->dpKeyArray[i], sp)) != CERR_None) {
|
||||
if ((msg = ExpandCapsRule(gp, &gp->dpKeyArray[i], sp)) != STATUS_Success) {
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
return CERR_None;
|
||||
return STATUS_Success;
|
||||
}
|
||||
|
||||
KMX_DWORD ExpandCapsRule(PFILE_GROUP gp, PFILE_KEY kpp, PFILE_STORE sp) {
|
||||
|
|
@ -106,13 +106,13 @@ KMX_DWORD ExpandCapsRule(PFILE_GROUP gp, PFILE_KEY kpp, PFILE_STORE sp) {
|
|||
if (shift == 0) {
|
||||
// Convert US key cap to a virtual key
|
||||
if (!kmcmp::MapUSCharToVK(kpp->Key, &key, &shift)) {
|
||||
return CERR_None;
|
||||
return STATUS_Success;
|
||||
}
|
||||
}
|
||||
|
||||
if (shift & (CAPITALFLAG | NOTCAPITALFLAG)) {
|
||||
// Don't attempt expansion if either Caps Lock flag is specified in the key rule
|
||||
return CERR_None;
|
||||
return STATUS_Success;
|
||||
}
|
||||
|
||||
PKMX_WCHAR p = sp->dpString;
|
||||
|
|
@ -125,13 +125,13 @@ KMX_DWORD ExpandCapsRule(PFILE_GROUP gp, PFILE_KEY kpp, PFILE_STORE sp) {
|
|||
|
||||
if (!*p) {
|
||||
// This key is not modified by Caps Lock
|
||||
return CERR_None;
|
||||
return STATUS_Success;
|
||||
}
|
||||
|
||||
// This key is modified by Caps Lock, so we need to duplicate this rule
|
||||
int offset = (int)(kpp - gp->dpKeyArray);
|
||||
if(!resizeKeyArray(gp)) {
|
||||
return CERR_CannotAllocateMemory;
|
||||
return KmnCompilerMessages::FATAL_CannotAllocateMemory;
|
||||
}
|
||||
kpp = &gp->dpKeyArray[offset];
|
||||
gp->cxKeyArray++;
|
||||
|
|
@ -149,5 +149,5 @@ KMX_DWORD ExpandCapsRule(PFILE_GROUP gp, PFILE_KEY kpp, PFILE_STORE sp) {
|
|||
kpp->Key = key;
|
||||
kpp->ShiftFlags = shift | NOTCAPITALFLAG;
|
||||
|
||||
return CERR_None;
|
||||
return STATUS_Success;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#include "CheckForDuplicates.h"
|
||||
|
||||
KMX_DWORD CheckForDuplicateGroup(PFILE_KEYBOARD fk, PFILE_GROUP gp) noexcept {
|
||||
KMX_BOOL CheckForDuplicateGroup(PFILE_KEYBOARD fk, PFILE_GROUP gp) noexcept {
|
||||
KMX_DWORD i;
|
||||
PFILE_GROUP gp0 = fk->dpGroupArray;
|
||||
for (i = 0; i < fk->cxGroupArray; i++, gp0++) {
|
||||
|
|
@ -18,18 +18,21 @@ KMX_DWORD CheckForDuplicateGroup(PFILE_KEYBOARD fk, PFILE_GROUP gp) noexcept {
|
|||
continue;
|
||||
}
|
||||
if (u16icmp(gp0->szName, gp->szName) == 0) {
|
||||
snprintf(ErrExtraLIB, ERR_EXTRA_LIB_LEN, " Group '%s' declared on line %d", string_from_u16string(gp->szName).c_str(), gp0->Line);
|
||||
return CERR_DuplicateGroup;
|
||||
ReportCompilerMessage(KmnCompilerMessages::ERROR_DuplicateGroup, {
|
||||
/*groupName*/ string_from_u16string(gp->szName),
|
||||
/*lineNumber*/ std::to_string(gp0->Line)
|
||||
});
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return CERR_None;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
KMX_DWORD CheckForDuplicateStore(PFILE_KEYBOARD fk, PFILE_STORE sp) noexcept {
|
||||
KMX_BOOL CheckForDuplicateStore(PFILE_KEYBOARD fk, PFILE_STORE sp) noexcept {
|
||||
if (!sp->szName[0]) {
|
||||
// Stores with zero length names are reserved system stores.
|
||||
// They cannot be defined in user code. This is not an issue.
|
||||
return CERR_None;
|
||||
return TRUE;
|
||||
}
|
||||
KMX_DWORD i;
|
||||
PFILE_STORE sp0 = fk->dpStoreArray;
|
||||
|
|
@ -38,9 +41,12 @@ KMX_DWORD CheckForDuplicateStore(PFILE_KEYBOARD fk, PFILE_STORE sp) noexcept {
|
|||
continue;
|
||||
}
|
||||
if (u16icmp(sp0->szName, sp->szName) == 0) {
|
||||
snprintf(ErrExtraLIB, ERR_EXTRA_LIB_LEN, " Store '%s' declared on line %d", string_from_u16string(sp0->szName).c_str(), sp0->line);
|
||||
return CERR_DuplicateStore;
|
||||
ReportCompilerMessage(KmnCompilerMessages::ERROR_DuplicateStore, {
|
||||
/*storeName*/ string_from_u16string(sp0->szName),
|
||||
/*lineNumber*/ std::to_string(sp0->line)
|
||||
});
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return CERR_None;
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
KMX_DWORD CheckForDuplicateGroup(PFILE_KEYBOARD fk, PFILE_GROUP gp) noexcept;
|
||||
KMX_DWORD CheckForDuplicateStore(PFILE_KEYBOARD fk, PFILE_STORE sp) noexcept;
|
||||
KMX_BOOL CheckForDuplicateGroup(PFILE_KEYBOARD fk, PFILE_GROUP gp) noexcept;
|
||||
KMX_BOOL CheckForDuplicateStore(PFILE_KEYBOARD fk, PFILE_STORE sp) noexcept;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
*
|
||||
* @param fk Keyboard to check
|
||||
*/
|
||||
bool CheckNCapsConsistency(PFILE_KEYBOARD fk) {
|
||||
void CheckNCapsConsistency(PFILE_KEYBOARD fk) {
|
||||
struct CapsUsage {
|
||||
int ncaps_line, caps_line, neither_line;
|
||||
};
|
||||
|
|
@ -87,13 +87,11 @@ bool CheckNCapsConsistency(PFILE_KEYBOARD fk) {
|
|||
if (caps_ncaps_usage[i].neither_line && (caps_ncaps_usage[i].caps_line || caps_ncaps_usage[i].ncaps_line)) {
|
||||
// We set the current line to one needing work: the developer should add the NCAPS flag
|
||||
kmcmp::currentLine = caps_ncaps_usage[i].neither_line;
|
||||
AddWarningBool(CWARN_KeyShouldIncludeNCaps);
|
||||
ReportCompilerMessage(KmnCompilerMessages::WARN_KeyShouldIncludeNCaps);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] caps_ncaps_usage;
|
||||
|
||||
kmcmp::currentLine = oldCurrentLine;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
#include <compfile.h>
|
||||
|
||||
bool CheckNCapsConsistency(PFILE_KEYBOARD fk);
|
||||
void CheckNCapsConsistency(PFILE_KEYBOARD fk);
|
||||
|
|
|
|||
|
|
@ -1,155 +0,0 @@
|
|||
#include <CompMsg.h>
|
||||
#include <map>
|
||||
|
||||
std::map<KMX_DWORD, const KMX_CHAR*> CompilerErrorMap = {
|
||||
{ CERR_InvalidLayoutLine , "Invalid 'layout' command"},
|
||||
{ CERR_NoVersionLine , "No version line found for file"},
|
||||
{ CERR_InvalidGroupLine , "Invalid 'group' command"},
|
||||
{ CERR_InvalidStoreLine , "Invalid 'store' command"},
|
||||
{ CERR_InvalidCodeInKeyPartOfRule , "Invalid command or code found in key part of rule"},
|
||||
{ CERR_InvalidDeadkey , "Invalid 'deadkey' or 'dk' command"},
|
||||
{ CERR_InvalidValue , "Invalid value in extended string"},
|
||||
{ CERR_ZeroLengthString , "A string of zero characters was found"},
|
||||
{ CERR_TooManyIndexToKeyRefs , "Too many index commands refering to key string"},
|
||||
{ CERR_UnterminatedString , "Unterminated string in line"},
|
||||
{ CERR_StringInVirtualKeySection , "extend string illegal in virtual key section"},
|
||||
{ CERR_AnyInVirtualKeySection , "'any' command is illegal in virtual key section"},
|
||||
{ CERR_InvalidAny , "Invalid 'any' command"},
|
||||
{ CERR_StoreDoesNotExist , "Store referenced does not exist"},
|
||||
{ CERR_BeepInVirtualKeySection , "'beep' command is illegal in virtual key section"},
|
||||
{ CERR_IndexInVirtualKeySection , "'index' command is illegal in virtual key section"},
|
||||
{ CERR_BadCallParams , "CompileKeyboardFile was called with bad parameters"},
|
||||
{ CERR_InfileNotExist , "Cannot find the input file"},
|
||||
// { CERR_CannotCreateOutfile , "Cannot open output file for writing"}, unused
|
||||
{ CERR_UnableToWriteFully , "Unable to write the file completely"},
|
||||
{ CERR_CannotReadInfile , "Cannot read the input file"},
|
||||
{ CERR_SomewhereIGotItWrong , "Internal error: contact Keyman"},
|
||||
{ CERR_BufferOverflow , "The compiler memory buffer overflowed"},
|
||||
{ CERR_Break , "Compiler interrupted by user"},
|
||||
{ CERR_CannotAllocateMemory , "Out of memory"},
|
||||
{ CERR_InvalidBitmapLine , "Invalid 'bitmaps' command"},
|
||||
{ CERR_CannotReadBitmapFile , "Cannot open the bitmap or icon file for reading"},
|
||||
{ CERR_IndexDoesNotPointToAny , "An index() in the output does not have a corresponding any() statement"},
|
||||
{ CERR_ReservedCharacter , "A reserved character was found"},
|
||||
{ CERR_InvalidCharacter , "A character was found that is outside the valid Unicode range (U+0000 - U+10FFFF)"},
|
||||
{ CERR_InvalidCall , "The 'call' command is invalid"},
|
||||
{ CERR_CallInVirtualKeySection , "'call' command is illegal in virtual key section"},
|
||||
{ CERR_CodeInvalidInKeyStore , "The command is invalid inside a store that is used in a key part of the rule"},
|
||||
{ CERR_CannotLoadIncludeFile , "Cannot load the included file: it is either invalid or does not exist"},
|
||||
{ CERR_60FeatureOnly_EthnologueCode , "EthnologueCode system store requires VERSION 6.0 or higher"},
|
||||
{ CERR_60FeatureOnly_MnemonicLayout , "MnemonicLayout functionality requires VERSION 6.0 or higher"},
|
||||
{ CERR_60FeatureOnly_OldCharPosMatching , "OldCharPosMatching system store requires VERSION 6.0 or higher"},
|
||||
{ CERR_60FeatureOnly_NamedCodes , "Named character constants requires VERSION 6.0 or higher"},
|
||||
{ CERR_60FeatureOnly_Contextn , "Context(n) requires VERSION 6.0 or higher"},
|
||||
{ CERR_501FeatureOnly_Call , "Call() requires VERSION 5.01 or higher"},
|
||||
{ CERR_InvalidNamedCode , "Invalid named code constant"},
|
||||
{ CERR_InvalidSystemStore , "Invalid system store name found"},
|
||||
{ CERR_60FeatureOnly_VirtualCharKey , "Virtual character keys require VERSION 6.0 or higher"},
|
||||
{ CERR_VersionAlreadyIncluded , "Only one VERSION or store(version) line allowed in a source file."},
|
||||
{ CERR_70FeatureOnly , "This feature requires store(version) '7.0' or higher"},
|
||||
{ CERR_80FeatureOnly , "This feature requires store(version) '8.0' or higher"},
|
||||
{ CERR_InvalidInVirtualKeySection , "This statement is not valid in a virtual key section"},
|
||||
{ CERR_InvalidIf , "The if() statement is not valid"},
|
||||
{ CERR_InvalidReset , "The reset() statement is not valid"},
|
||||
{ CERR_InvalidSet , "The set() statement is not valid"},
|
||||
{ CERR_InvalidSave , "The save() statement is not valid"},
|
||||
{ CERR_InvalidEthnologueCode , "Invalid ethnologuecode format"},
|
||||
{ CERR_90FeatureOnly_IfSystemStores , "if(store) requires store(version) '9.0' or higher"},
|
||||
{ CERR_IfSystemStore_NotFound , "System store in if() not found"},
|
||||
{ CERR_90FeatureOnly_SetSystemStores , "set(store) requires store(version) '9.0' or higher"},
|
||||
{ CERR_SetSystemStore_NotFound , "System store in set() not found"},
|
||||
{ CERR_90FeatureOnlyVirtualKeyDictionary , "Custom virtual key names require store(version) '9.0'"},
|
||||
{ CERR_InvalidIndex , "Invalid 'index' command"},
|
||||
{ CERR_OutsInVirtualKeySection , "'outs' command is illegal in virtual key section"},
|
||||
{ CERR_InvalidOuts , "Invalid 'outs' command"},
|
||||
{ CERR_ContextInVirtualKeySection , "'context' command is illegal in virtual key section"},
|
||||
{ CERR_InvalidUse , "Invalid 'use' command"},
|
||||
{ CERR_GroupDoesNotExist , "Group does not exist"},
|
||||
{ CERR_VirtualKeyNotAllowedHere , "Virtual key is not allowed here"},
|
||||
{ CERR_InvalidSwitch , "Invalid 'switch' command"},
|
||||
{ CERR_NoTokensFound , "No tokens found in line"},
|
||||
{ CERR_InvalidLineContinuation , "Invalid line continuation"},
|
||||
{ CERR_LineTooLong , "Line too long"},
|
||||
{ CERR_InvalidCopyright , "Invalid 'copyright' command"},
|
||||
{ CERR_CodeInvalidInThisSection , "This line is invalid in this section of the file"},
|
||||
{ CERR_InvalidMessage , "Invalid 'message' command"},
|
||||
{ CERR_InvalidLanguageName , "Invalid 'languagename' command"},
|
||||
{ CERR_EndOfFile , "(no error - reserved code)"},
|
||||
{ CERR_InvalidToken , "Invalid token found"},
|
||||
{ CERR_InvalidBegin , "Invalid 'begin' command"},
|
||||
{ CERR_InvalidName , "Invalid 'name' command"},
|
||||
{ CERR_InvalidVersion , "Invalid 'version' command"},
|
||||
{ CERR_InvalidLanguageLine , "Invalid 'language' command"},
|
||||
{ CERR_LayoutButNoLanguage , "Layout command found but no language command"},
|
||||
{ CERR_CannotCreateTempfile , "Cannot create temp file"},
|
||||
{ CERR_90FeatureOnlyLayoutFile , "Touch layout file reference requires store(version) '9.0' or higher"},
|
||||
{ CERR_90FeatureOnlyKeyboardVersion , "KeyboardVersion system store requires store(version) '9.0' or higher"},
|
||||
{ CERR_KeyboardVersionFormatInvalid , "KeyboardVersion format is invalid, expecting dot-separated integers"},
|
||||
{ CERR_ContextExHasInvalidOffset , "context() statement has offset out of range"},
|
||||
{ CERR_90FeatureOnlyEmbedCSS , "Embedding CSS requires store(version) '9.0' or higher"},
|
||||
{ CERR_90FeatureOnlyTargets , "TARGETS system store requires store(version) '9.0' or higher"},
|
||||
{ CERR_ContextAndIndexInvalidInMatchNomatch , "context and index statements cannot be used in a match or nomatch statement"},
|
||||
{ CERR_140FeatureOnlyContextAndNotAnyWeb , "For web and touch platforms, context() statement referring to notany() requires store(version) '14.0' or higher"},
|
||||
{ CERR_ExpansionMustFollowCharacterOrVKey , "An expansion must follow a character or a virtual key"},
|
||||
{ CERR_VKeyExpansionMustBeFollowedByVKey , "A virtual key expansion must be terminated by a virtual key"},
|
||||
{ CERR_CharacterExpansionMustBeFollowedByCharacter , "A character expansion must be terminated by a character key"},
|
||||
{ CERR_VKeyExpansionMustUseConsistentShift , "A virtual key expansion must use the same shift state for both terminators"},
|
||||
{ CERR_ExpansionMustBePositive , "An expansion must have positive difference (i.e. A-Z, not Z-A)"},
|
||||
{ CERR_CasedKeysMustContainOnlyVirtualKeys , "The &CasedKeys system store must contain only virtual keys or characters found on a US English keyboard"},
|
||||
{ CERR_CasedKeysMustNotIncludeShiftStates , "The &CasedKeys system store must not include shift states"},
|
||||
{ CERR_CasedKeysNotSupportedWithMnemonicLayout , "The &CasedKeys system store is not supported with mnemonic layouts"},
|
||||
{ CERR_CannotUseReadWriteGroupFromReadonlyGroup , "Group used from a readonly group must also be readonly"},
|
||||
{ CERR_StatementNotPermittedInReadonlyGroup , "Statement is not permitted in output of readonly group"},
|
||||
{ CERR_OutputInReadonlyGroup , "Output is not permitted in a readonly group"},
|
||||
{ CERR_NewContextGroupMustBeReadonly , "Group used in begin newContext must be readonly"},
|
||||
{ CERR_PostKeystrokeGroupMustBeReadonly , "Group used in begin postKeystroke must be readonly"},
|
||||
{ CERR_DuplicateGroup , "A group with this name has already been defined."},
|
||||
{ CERR_DuplicateStore , "A store with this name has already been defined."},
|
||||
{ CERR_RepeatedBegin , "Begin has already been set"},
|
||||
{ CERR_VirtualKeyInContext , "Virtual keys are not permitted in context"},
|
||||
{ CERR_OutsTooLong , "Store cannot be inserted with outs() as it makes the extended string too long" },
|
||||
{ CERR_ExtendedStringTooLong , "Extended string is too long" },
|
||||
{ CERR_VirtualKeyExpansionTooLong , "Virtual key expansion is too large" },
|
||||
{ CERR_CharacterRangeTooLong , "Character range is too large and cannot be expanded" },
|
||||
{ CERR_NonBMPCharactersNotSupportedInKeySection , "Characters with codepoints over U+FFFF are not supported in the key part of the rule" },
|
||||
|
||||
{ CHINT_UnreachableRule , "This rule will never be matched as another rule takes precedence"},
|
||||
{ CHINT_NonUnicodeFile , "Keyman Developer has detected that the file has ANSI encoding. Consider converting this file to UTF-8"},
|
||||
{ CHINT_IndexStoreLong , "The store referenced in index() is longer than the store referenced in any()"},
|
||||
|
||||
{ CWARN_TooManyWarnings , "Too many warnings or errors"},
|
||||
{ CWARN_OldVersion , "The keyboard file is an old version"},
|
||||
{ CWARN_BitmapNotUsed , "The 'bitmaps' statement is obsolete and only the first bitmap referred to will be used, you should use 'bitmap'."},
|
||||
{ CWARN_CustomLanguagesNotSupported , "Languages over 0x1FF, 0x1F are not supported correctly by Windows. You should use no LANGUAGE line instead."},
|
||||
{ CWARN_KeyBadLength , "There are too many characters in the keystroke part of the rule."},
|
||||
{ CWARN_IndexStoreShort , "The store referenced in index() is shorter than the store referenced in any()"},
|
||||
{ CWARN_UnicodeInANSIGroup , "A Unicode character was found in an ANSI group"},
|
||||
{ CWARN_ANSIInUnicodeGroup , "An ANSI character was found in a Unicode group"},
|
||||
{ CWARN_UnicodeSurrogateUsed , "A Unicode surrogate character was found. You should use Unicode scalar values to represent values > U+FFFF"},
|
||||
{ CWARN_ReservedCharacter , "A Unicode character was found that should not be used"},
|
||||
{ CWARN_Info , "Information"},
|
||||
{ CWARN_VirtualKeyWithMnemonicLayout , "Virtual key used instead of virtual character key with a mnemonic layout"},
|
||||
{ CWARN_VirtualCharKeyWithPositionalLayout , "Virtual character key used with a positional layout instead of mnemonic layout"},
|
||||
{ CWARN_StoreAlreadyUsedAsOptionOrCall , "Store already used as an option or in a call statement and should not be used as a normal store"},
|
||||
{ CWARN_StoreAlreadyUsedAsStoreOrCall , "Store already used as a normal store or in a call statement and should not be used as an option"},
|
||||
{ CWARN_StoreAlreadyUsedAsStoreOrOption , "Store already used as a normal store or as an option and should not be used in a call statement"},
|
||||
{ CWARN_PunctuationInEthnologueCode , "Punctuation should not be used to separate Ethnologue codes; instead use spaces"},
|
||||
{ CWARN_PlatformNotInTargets , "The specified platform is not a target platform"},
|
||||
{ CWARN_HeaderStatementIsDeprecated , "Header statements are deprecated; use instead the equivalent system store"},
|
||||
{ CWARN_UseNotLastStatementInRule , "A rule with use() statements in the output should not have other content following the use() statements"},
|
||||
{ CWARN_KVKFileIsInSourceFormat , ".kvk file should be binary but is an XML file"},
|
||||
{ CWARN_DontMixChiralAndNonChiralModifiers , "Don't mix the use of left/right modifiers with non-left/right modifiers in the same platform"},
|
||||
{ CWARN_MixingLeftAndRightModifiers , "Left and right modifiers should not both be used in the same rule"},
|
||||
{ CWARN_LanguageHeadersDeprecatedInKeyman10 , "This language header has been deprecated in Keyman 10. Instead, add language metadata in the package file"},
|
||||
{ CWARN_HotkeyHasInvalidModifier , "Hotkey has modifiers that are not supported. Use only SHIFT, CTRL and ALT"},
|
||||
{ CWARN_NulNotFirstStatementInContext , "nul must be the first statement in the context"},
|
||||
{ CWARN_IfShouldBeAtStartOfContext , "if, platform and baselayout should be at start of context (after nul, if present)"},
|
||||
{ CWARN_KeyShouldIncludeNCaps , "Other rules which reference this key include CAPS or NCAPS modifiers, so this rule must include NCAPS modifier to avoid inconsistent matches"},
|
||||
{ CWARN_VirtualKeyInOutput , "Virtual keys are not supported in output"},
|
||||
|
||||
{ 0, nullptr }
|
||||
};
|
||||
|
||||
const KMX_CHAR *GetCompilerErrorString(KMX_DWORD code) {
|
||||
return CompilerErrorMap[code];
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
#include "km_types.h"
|
||||
#include <kmn_compiler_errors.h>
|
||||
|
||||
const KMX_CHAR *GetCompilerErrorString(KMX_DWORD code) ;
|
||||
|
|
@ -20,13 +20,13 @@ bool CompileKeyboardBuffer(KMX_BYTE* infile, int sz, PFILE_KEYBOARD fk)
|
|||
kmcmp::FMnemonicLayout = FALSE;
|
||||
|
||||
if (!fk) {
|
||||
AddCompileError(CERR_SomewhereIGotItWrong);
|
||||
ReportCompilerMessage(KmnCompilerMessages::FATAL_SomewhereIGotItWrong);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
str = new KMX_WCHAR[LINESIZE];
|
||||
if (!str) {
|
||||
AddCompileError(CERR_CannotAllocateMemory);
|
||||
ReportCompilerMessage(KmnCompilerMessages::FATAL_CannotAllocateMemory);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -66,39 +66,42 @@ bool CompileKeyboardBuffer(KMX_BYTE* infile, int sz, PFILE_KEYBOARD fk)
|
|||
|
||||
if(kmcmp::FShouldAddCompilerVersion) {
|
||||
u16sprintf(str,LINESIZE, L"Created with Keyman Developer version %d.%d.%d.%d", KEYMAN_VersionMajor, KEYMAN_VersionMinor, KEYMAN_VersionPatch, 0);
|
||||
AddStore(fk, TSS_KEYMANCOPYRIGHT, str);
|
||||
if(!AddStore(fk, TSS_KEYMANCOPYRIGHT, str)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a system store for the Keyman edition number */
|
||||
AddStore(fk, TSS_CUSTOMKEYMANEDITION, u"0");
|
||||
AddStore(fk, TSS_CUSTOMKEYMANEDITIONNAME, u"Keyman");
|
||||
if(!AddStore(fk, TSS_CUSTOMKEYMANEDITION, u"0")) {
|
||||
return FALSE;
|
||||
}
|
||||
if(!AddStore(fk, TSS_CUSTOMKEYMANEDITIONNAME, u"Keyman")) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
|
||||
// must preprocess for group and store names -> this isn't really necessary, but never mind!
|
||||
while ((msg = ReadLine(infile, sz, offset, str, TRUE)) == CERR_None)
|
||||
while ((msg = ReadLine(infile, sz, offset, str, TRUE)) == STATUS_Success)
|
||||
{
|
||||
p = str;
|
||||
switch (LineTokenType(&p))
|
||||
{
|
||||
case T_VERSION:
|
||||
*(p + 4) = 0;
|
||||
if ((msg = AddStore(fk, TSS_VERSION, p)) != CERR_None) {
|
||||
AddCompileError(msg);
|
||||
if (!AddStore(fk, TSS_VERSION, p)) {
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case T_GROUP:
|
||||
if ((msg = ProcessGroupLine(fk, p)) != CERR_None) {
|
||||
AddCompileError(msg);
|
||||
if (!ProcessGroupLine(fk, p)) {
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case T_STORE:
|
||||
if ((msg = ProcessStoreLine(fk, p)) != CERR_None) {
|
||||
AddCompileError(msg);
|
||||
if (!ProcessStoreLine(fk, p)) {
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
|
@ -108,8 +111,8 @@ bool CompileKeyboardBuffer(KMX_BYTE* infile, int sz, PFILE_KEYBOARD fk)
|
|||
}
|
||||
}
|
||||
|
||||
if (msg != CERR_EndOfFile) {
|
||||
AddCompileError(msg);
|
||||
if (msg != STATUS_EndOfFile) {
|
||||
ReportCompilerMessage(msg);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -121,32 +124,30 @@ bool CompileKeyboardBuffer(KMX_BYTE* infile, int sz, PFILE_KEYBOARD fk)
|
|||
kmcmp::CodeConstants->reindex();
|
||||
|
||||
/* ReadLine will automatically skip over $Keyman lines, and parse wrapped lines */
|
||||
while ((msg = ReadLine(infile, sz, offset, str, FALSE)) == CERR_None)
|
||||
while ((msg = ReadLine(infile, sz, offset, str, FALSE)) == STATUS_Success)
|
||||
{
|
||||
msg = ParseLine(fk, str);
|
||||
if (msg != CERR_None) {
|
||||
AddCompileError(msg);
|
||||
if(!ParseLine(fk, str)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg != CERR_EndOfFile) {
|
||||
AddCompileError(msg);
|
||||
if (msg != STATUS_EndOfFile) {
|
||||
ReportCompilerMessage(msg);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ProcessGroupFinish(fk);
|
||||
if(!ProcessGroupFinish(fk)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (kmcmp::FSaveDebug) kmcmp::RecordDeadkeyNames(fk);
|
||||
|
||||
/* Add the compiler version as a system store */
|
||||
if ((msg = kmcmp::AddCompilerVersionStore(fk)) != CERR_None) {
|
||||
AddCompileError(msg);
|
||||
if (!kmcmp::AddCompilerVersionStore(fk)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((msg = BuildVKDictionary(fk)) != CERR_None) {
|
||||
AddCompileError(msg);
|
||||
if (!BuildVKDictionary(fk)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
31
developer/src/kmcmplib/src/CompilerErrors.cpp
Normal file
31
developer/src/kmcmplib/src/CompilerErrors.cpp
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#include "pch.h"
|
||||
|
||||
#include <kmcmplibapi.h>
|
||||
#include <kmcmplib.h>
|
||||
#include <kmn_compiler_errors.h>
|
||||
|
||||
namespace kmcmp {
|
||||
int ErrChr;
|
||||
int nErrors = 0;
|
||||
kmcmp_CompilerMessageProc msgproc = nullptr;
|
||||
void* msgprocContext = NULL;
|
||||
std::string messageFilename;
|
||||
}
|
||||
|
||||
void ReportCompilerMessage(KMX_DWORD msg, const std::vector<std::string>& parameters) {
|
||||
const KMX_DWORD severity = msg & MESSAGE_SEVERITY_MASK;
|
||||
|
||||
if (severity == CompilerErrorSeverity::Error || severity == CompilerErrorSeverity::Fatal) {
|
||||
kmcmp::nErrors++;
|
||||
}
|
||||
|
||||
KMCMP_COMPILER_RESULT_MESSAGE message;
|
||||
message.errorCode = msg;
|
||||
message.lineNumber = kmcmp::currentLine + 1;
|
||||
message.columnNumber = kmcmp::ErrChr;
|
||||
message.parameters = parameters;
|
||||
message.filename = kmcmp::messageFilename;
|
||||
(*kmcmp::msgproc)(message, kmcmp::msgprocContext);
|
||||
|
||||
kmcmp::ErrChr = 0;
|
||||
}
|
||||
12
developer/src/kmcmplib/src/CompilerErrors.h
Normal file
12
developer/src/kmcmplib/src/CompilerErrors.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace kmcmp {
|
||||
extern kmcmp_CompilerMessageProc msgproc;
|
||||
extern void* msgprocContext;
|
||||
extern std::string messageFilename;
|
||||
}
|
||||
|
||||
void ReportCompilerMessage(KMX_DWORD msg, const std::vector<std::string>& parameters = {});
|
||||
|
|
@ -25,39 +25,38 @@ EXTERN bool kmcmp_CompileKeyboard(
|
|||
kmcmp::CompileTarget = options.target;
|
||||
|
||||
if (!messageProc || !loadFileProc || !pszInfile) {
|
||||
AddCompileError(CERR_BadCallParams);
|
||||
ReportCompilerMessage(KmnCompilerMessages::FATAL_BadCallParams);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
msgproc = messageProc;
|
||||
loadfileproc = loadFileProc;
|
||||
msgprocContext = (void*)procContext;
|
||||
kmcmp::messageFilename = pszInfile;
|
||||
kmcmp::msgproc = messageProc;
|
||||
kmcmp::loadfileproc = loadFileProc;
|
||||
kmcmp::msgprocContext = (void*)procContext;
|
||||
kmcmp::currentLine = 0;
|
||||
kmcmp::nErrors = 0;
|
||||
|
||||
int sz;
|
||||
if(!loadFileProc(pszInfile, "", nullptr, &sz, msgprocContext)) {
|
||||
AddCompileError(CERR_InfileNotExist);
|
||||
std::vector<uint8_t> bufvec = kmcmp::loadfileproc(pszInfile, "");
|
||||
sz = bufvec.size();
|
||||
if(!sz) {
|
||||
ReportCompilerMessage(KmnCompilerMessages::ERROR_InfileNotExist);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(sz < 3) {
|
||||
// Technically, a 3 byte file can never be a valid .kmn, so we can shortcut
|
||||
// here and avoid testing outside memory bounds for looking at BOM
|
||||
AddCompileError(CERR_CannotReadInfile);
|
||||
ReportCompilerMessage(KmnCompilerMessages::ERROR_CannotReadInfile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
KMX_BYTE* infile = new KMX_BYTE[sz+1];
|
||||
if(!infile) {
|
||||
AddCompileError(CERR_CannotAllocateMemory);
|
||||
return FALSE;
|
||||
}
|
||||
if(!loadFileProc(pszInfile, "", infile, &sz, msgprocContext)) {
|
||||
delete[] infile;
|
||||
AddCompileError(CERR_CannotReadInfile);
|
||||
ReportCompilerMessage(KmnCompilerMessages::FATAL_CannotAllocateMemory);
|
||||
return FALSE;
|
||||
}
|
||||
std::copy(bufvec.begin(), bufvec.end(), infile);
|
||||
infile[sz] = 0; // zero-terminate for safety, not technically needed but helps avoid memory bugs
|
||||
|
||||
int offset = 0;
|
||||
|
|
@ -70,7 +69,7 @@ EXTERN bool kmcmp_CompileKeyboard(
|
|||
int sz16;
|
||||
if(!UTF16TempFromUTF8(infile, sz, &infile16, &sz16)) {
|
||||
delete[] infile;
|
||||
AddCompileError(CERR_CannotCreateTempfile);
|
||||
ReportCompilerMessage(KmnCompilerMessages::FATAL_CannotCreateTempfile);
|
||||
return FALSE;
|
||||
}
|
||||
delete[] infile;
|
||||
|
|
@ -96,8 +95,8 @@ EXTERN bool kmcmp_CompileKeyboard(
|
|||
|
||||
//TODO: FreeKeyboardPointers(fk);
|
||||
|
||||
if(msg != CERR_None) {
|
||||
AddCompileError(msg);
|
||||
if(msg != STATUS_Success) {
|
||||
ReportCompilerMessage(msg);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,49 +3,20 @@
|
|||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
|
||||
/*
|
||||
WASM interface for compiler message callback
|
||||
*/
|
||||
EM_JS(int, wasm_msgproc, (int line, int msgcode, const char* text, char* context), {
|
||||
const proc = globalThis[UTF8ToString(context)].message;
|
||||
if(!proc || typeof proc != 'function') {
|
||||
console.log(`[${line}: ${msgcode}: ${UTF8ToString(text)}]`);
|
||||
return 0;
|
||||
} else {
|
||||
return proc(line, msgcode, UTF8ToString(text));
|
||||
struct WasmCallbackInterface {
|
||||
virtual void message(const KMCMP_COMPILER_RESULT_MESSAGE& message) = 0;
|
||||
virtual const std::vector<uint8_t> loadFile(const std::string& filename, const std::string& baseFilename) = 0;
|
||||
virtual ~WasmCallbackInterface() {}
|
||||
};
|
||||
|
||||
struct WasmCallbackInterfaceWrapper : public emscripten::wrapper<WasmCallbackInterface> {
|
||||
EMSCRIPTEN_WRAPPER(WasmCallbackInterfaceWrapper);
|
||||
void message(const KMCMP_COMPILER_RESULT_MESSAGE& message) {
|
||||
return call<void>("message", message);
|
||||
}
|
||||
});
|
||||
|
||||
EM_JS(int, wasm_loadfileproc, (const char* filename, const char* baseFilename, void* buffer, int bufferSize, char* context), {
|
||||
const proc = globalThis[UTF8ToString(context)].loadFile;
|
||||
if(!proc || typeof proc != 'function') {
|
||||
return 0;
|
||||
} else {
|
||||
if(buffer == 0) {
|
||||
return proc(UTF8ToString(filename), UTF8ToString(baseFilename), 0, 0);
|
||||
} else {
|
||||
return proc(UTF8ToString(filename), UTF8ToString(baseFilename), buffer, bufferSize);
|
||||
}
|
||||
const std::vector<uint8_t> loadFile(const std::string& filename, const std::string& baseFilename) {
|
||||
return call<const std::vector<uint8_t>>("loadFile", filename, baseFilename);
|
||||
}
|
||||
});
|
||||
|
||||
bool wasm_LoadFileProc(const char* filename, const char* baseFilename, void* buffer, int* bufferSize, void* context) {
|
||||
char* msgProc = static_cast<char*>(context);
|
||||
if(buffer == nullptr) {
|
||||
*bufferSize = wasm_loadfileproc(filename, baseFilename, 0, 0, msgProc);
|
||||
return *bufferSize != -1;
|
||||
} else {
|
||||
return wasm_loadfileproc(filename, baseFilename, buffer, *bufferSize, msgProc) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
int wasm_CompilerMessageProc(int line, uint32_t dwMsgCode, const char* szText, void* context) {
|
||||
char* msgProc = static_cast<char*>(context);
|
||||
return wasm_msgproc(line, dwMsgCode, szText, msgProc);
|
||||
}
|
||||
|
||||
struct WASM_COMPILER_INTERFACE {
|
||||
std::string callbacksKey; // key of callbacks object on globalThis
|
||||
};
|
||||
|
||||
struct WASM_COMPILER_RESULT {
|
||||
|
|
@ -56,16 +27,28 @@ struct WASM_COMPILER_RESULT {
|
|||
KMCMP_COMPILER_RESULT_EXTRA extra;
|
||||
};
|
||||
|
||||
WASM_COMPILER_RESULT kmcmp_wasm_compile(std::string pszInfile, const KMCMP_COMPILER_OPTIONS options, const WASM_COMPILER_INTERFACE intf) {
|
||||
WasmCallbackInterface* globalCallbacks = nullptr;
|
||||
|
||||
const std::vector<uint8_t> wasm_LoadFileProc(const std::string& filename, const std::string& baseFilename) {
|
||||
return globalCallbacks->loadFile(filename, baseFilename);
|
||||
}
|
||||
|
||||
void wasm_CompilerMessageProc(const KMCMP_COMPILER_RESULT_MESSAGE& message, void* context) {
|
||||
globalCallbacks->message(message);
|
||||
}
|
||||
|
||||
WASM_COMPILER_RESULT kmcmp_wasm_compile(std::string pszInfile, const KMCMP_COMPILER_OPTIONS options, WasmCallbackInterface& callbacks) {
|
||||
WASM_COMPILER_RESULT r = {false};
|
||||
KMCMP_COMPILER_RESULT kr;
|
||||
|
||||
globalCallbacks = &callbacks;
|
||||
|
||||
r.result = kmcmp_CompileKeyboard(
|
||||
pszInfile.c_str(),
|
||||
options,
|
||||
wasm_CompilerMessageProc,
|
||||
wasm_LoadFileProc,
|
||||
intf.callbacksKey.c_str(),
|
||||
"", //TODO: eliminate?
|
||||
kr
|
||||
);
|
||||
|
||||
|
|
@ -76,6 +59,8 @@ WASM_COMPILER_RESULT kmcmp_wasm_compile(std::string pszInfile, const KMCMP_COMPI
|
|||
r.extra = kr.extra;
|
||||
}
|
||||
|
||||
globalCallbacks = nullptr;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -119,6 +104,12 @@ int kmcmp_testSentry() {
|
|||
|
||||
EMSCRIPTEN_BINDINGS(compiler_interface) {
|
||||
|
||||
emscripten::class_<WasmCallbackInterface>("WasmCallbackInterface")
|
||||
.function("message", &WasmCallbackInterface::message, emscripten::pure_virtual())
|
||||
.function("loadFile", &WasmCallbackInterface::loadFile, emscripten::pure_virtual())
|
||||
.allow_subclass<WasmCallbackInterfaceWrapper>("WasmCallbackInterfaceWrapper")
|
||||
;
|
||||
|
||||
emscripten::class_<KMCMP_COMPILER_OPTIONS>("CompilerOptions")
|
||||
.constructor<>()
|
||||
.property("saveDebug", &KMCMP_COMPILER_OPTIONS::saveDebug)
|
||||
|
|
@ -128,11 +119,6 @@ EMSCRIPTEN_BINDINGS(compiler_interface) {
|
|||
.property("target", &KMCMP_COMPILER_OPTIONS::target)
|
||||
;
|
||||
|
||||
emscripten::class_<WASM_COMPILER_INTERFACE>("CompilerInterface")
|
||||
.constructor<>()
|
||||
.property("callbacksKey", &WASM_COMPILER_INTERFACE::callbacksKey)
|
||||
;
|
||||
|
||||
emscripten::class_<WASM_COMPILER_RESULT>("CompilerResult")
|
||||
.constructor<>()
|
||||
.property("result", &WASM_COMPILER_RESULT::result)
|
||||
|
|
@ -141,6 +127,15 @@ EMSCRIPTEN_BINDINGS(compiler_interface) {
|
|||
.property("extra", &WASM_COMPILER_RESULT::extra)
|
||||
;
|
||||
|
||||
emscripten::class_<KMCMP_COMPILER_RESULT_MESSAGE>("CompilerResultMessage")
|
||||
.constructor<>()
|
||||
.property("errorCode", &KMCMP_COMPILER_RESULT_MESSAGE::errorCode)
|
||||
.property("lineNumber", &KMCMP_COMPILER_RESULT_MESSAGE::lineNumber)
|
||||
.property("columnNumber", &KMCMP_COMPILER_RESULT_MESSAGE::columnNumber)
|
||||
.property("filename", &KMCMP_COMPILER_RESULT_MESSAGE::filename)
|
||||
.property("parameters", &KMCMP_COMPILER_RESULT_MESSAGE::parameters)
|
||||
;
|
||||
|
||||
emscripten::class_<KMCMP_COMPILER_RESULT_EXTRA>("CompilerResultExtra")
|
||||
.constructor<>()
|
||||
.property("targets", &KMCMP_COMPILER_RESULT_EXTRA::targets)
|
||||
|
|
|
|||
|
|
@ -6,15 +6,14 @@
|
|||
#include "kmcmplib.h"
|
||||
#include "DeprecationChecks.h"
|
||||
|
||||
KMX_BOOL kmcmp::WarnDeprecatedHeader() { // I4866
|
||||
if( AWarnDeprecatedCode_GLOBAL_LIB){
|
||||
AddWarningBool(CWARN_HeaderStatementIsDeprecated);
|
||||
void kmcmp::WarnDeprecatedHeader() { // I4866
|
||||
if (AWarnDeprecatedCode_GLOBAL_LIB) {
|
||||
ReportCompilerMessage(KmnCompilerMessages::WARN_HeaderStatementIsDeprecated);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Flag presence of deprecated features */
|
||||
KMX_BOOL kmcmp::CheckForDeprecatedFeatures(PFILE_KEYBOARD fk) {
|
||||
void kmcmp::CheckForDeprecatedFeatures(PFILE_KEYBOARD fk) {
|
||||
/*
|
||||
For Keyman 10, we deprecated:
|
||||
// < Keyman 7
|
||||
|
|
@ -31,7 +30,7 @@ KMX_BOOL kmcmp::CheckForDeprecatedFeatures(PFILE_KEYBOARD fk) {
|
|||
PFILE_STORE sp;
|
||||
|
||||
if (!AWarnDeprecatedCode_GLOBAL_LIB) {
|
||||
return TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (fk->version >= VERSION_100) {
|
||||
|
|
@ -42,12 +41,10 @@ KMX_BOOL kmcmp::CheckForDeprecatedFeatures(PFILE_KEYBOARD fk) {
|
|||
sp->dwSystemID == TSS_ETHNOLOGUECODE ||
|
||||
sp->dwSystemID == TSS_WINDOWSLANGUAGES) {
|
||||
kmcmp::currentLine = sp->line;
|
||||
AddWarningBool(CWARN_LanguageHeadersDeprecatedInKeyman10);
|
||||
ReportCompilerMessage(KmnCompilerMessages::WARN_LanguageHeadersDeprecatedInKeyman10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kmcmp::currentLine = oldCurrentLine;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@
|
|||
#include "kmcmplib.h"
|
||||
|
||||
namespace kmcmp{
|
||||
KMX_BOOL WarnDeprecatedHeader();
|
||||
KMX_BOOL CheckForDeprecatedFeatures(PFILE_KEYBOARD fk);
|
||||
void WarnDeprecatedHeader();
|
||||
void CheckForDeprecatedFeatures(PFILE_KEYBOARD fk);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,15 +120,14 @@ KMX_BOOL NamedCodeConstants::LoadFile(PFILE_KEYBOARD fk, const KMX_WCHAR *filena
|
|||
|
||||
int FileSize;
|
||||
KMX_BYTE* Buf;
|
||||
if(!loadfileproc(szNameUtf8.c_str(), fk->extra->kmnFilename.c_str(), nullptr, &FileSize, msgprocContext)) {
|
||||
std::vector<uint8_t> bufvec = loadfileproc(szNameUtf8, fk->extra->kmnFilename);
|
||||
FileSize = bufvec.size();
|
||||
if(!FileSize) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Buf = new KMX_BYTE[FileSize+1];
|
||||
if(!loadfileproc(szNameUtf8.c_str(), fk->extra->kmnFilename.c_str(), Buf, &FileSize, msgprocContext)) {
|
||||
delete[] Buf;
|
||||
return FALSE;
|
||||
}
|
||||
std::copy(bufvec.begin(), bufvec.end(), Buf);
|
||||
Buf[FileSize] = 0; // zero-terminate for strtok
|
||||
|
||||
char* filetok;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ namespace kmcmp {
|
|||
}
|
||||
|
||||
}
|
||||
KMX_DWORD VerifyUnreachableRules(PFILE_GROUP gp) {
|
||||
|
||||
void VerifyUnreachableRules(PFILE_GROUP gp) {
|
||||
PFILE_KEY kp = gp->dpKeyArray;
|
||||
KMX_DWORD i;
|
||||
|
||||
|
|
@ -41,8 +42,9 @@ KMX_DWORD VerifyUnreachableRules(PFILE_GROUP gp) {
|
|||
if (kp->Line != k1.Line && reportedLines.count(kp->Line) == 0) {
|
||||
reportedLines.insert(kp->Line);
|
||||
kmcmp::currentLine = kp->Line;
|
||||
snprintf(ErrExtraLIB, ERR_EXTRA_LIB_LEN, " Overridden by rule on line %d", k1.Line);
|
||||
AddWarning(CHINT_UnreachableRule);
|
||||
ReportCompilerMessage(KmnCompilerMessages::HINT_UnreachableRule, {
|
||||
/* LineNumber */ std::to_string(k1.Line)
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -51,6 +53,4 @@ KMX_DWORD VerifyUnreachableRules(PFILE_GROUP gp) {
|
|||
}
|
||||
|
||||
kmcmp::currentLine = oldCurrentLine;
|
||||
|
||||
return CERR_None;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
KMX_DWORD VerifyUnreachableRules(PFILE_GROUP gp);
|
||||
void VerifyUnreachableRules(PFILE_GROUP gp);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
#define SZMAX_STORENAME 80
|
||||
#define SZMAX_GROUPNAME 80
|
||||
#define SZMAX_DEADKEYNAME 80
|
||||
#define SZMAX_ERRORTEXT 512
|
||||
#define SZMAX_VKDICTIONARYNAME 80
|
||||
|
||||
#define MAX_WARNINGS 100
|
||||
|
|
@ -167,26 +166,4 @@ const KMX_DWORD sz_FILE_DEADKEY = sizeof(FILE_DEADKEY);
|
|||
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;
|
||||
};
|
||||
|
||||
typedef COMPMSG *PCOMPMSG;
|
||||
|
||||
struct COMPILEMESSAGES {
|
||||
int nMessages;
|
||||
int nErrors;
|
||||
|
||||
PCOMPMSG cm;
|
||||
|
||||
KMX_DWORD fatalCode;
|
||||
KMX_CHAR szFatalText[SZMAX_ERRORTEXT];
|
||||
|
||||
KMX_DWORD currentLine;
|
||||
};
|
||||
|
||||
typedef COMPILEMESSAGES *PCOMPILEMESSAGES;
|
||||
|
||||
#endif // _COMPFILE_H
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
#include <kmcmplibapi.h>
|
||||
#include "compfile.h"
|
||||
#include "NamedCodeConstants.h"
|
||||
#include <CompilerErrors.h>
|
||||
|
||||
namespace kmcmp {
|
||||
KMX_BOOL AddCompileWarning(char* buf);
|
||||
extern int currentLine;
|
||||
extern KMX_BOOL FShouldAddCompilerVersion;
|
||||
extern KMX_BOOL FSaveDebug, FCompilerWarningsAsErrors; // I4865 // I4866
|
||||
|
|
@ -17,34 +17,24 @@ namespace kmcmp {
|
|||
extern int BeginLine[4];
|
||||
extern int currentLine;
|
||||
extern NamedCodeConstants *CodeConstants;
|
||||
extern kmcmp_LoadFileProc loadfileproc;
|
||||
|
||||
void RecordDeadkeyNames(PFILE_KEYBOARD fk);
|
||||
KMX_DWORD AddCompilerVersionStore(PFILE_KEYBOARD fk);
|
||||
KMX_BOOL AddCompilerVersionStore(PFILE_KEYBOARD fk);
|
||||
}
|
||||
|
||||
extern kmcmp_CompilerMessageProc msgproc;
|
||||
extern kmcmp_LoadFileProc loadfileproc;
|
||||
extern void* msgprocContext;
|
||||
|
||||
extern KMX_BOOL AWarnDeprecatedCode_GLOBAL_LIB;
|
||||
#define ERR_EXTRA_LIB_LEN 256
|
||||
extern char ErrExtraLIB[ERR_EXTRA_LIB_LEN];
|
||||
KMX_BOOL AddCompileError(KMX_DWORD msg);
|
||||
|
||||
/// Use AddWarningBool for functions that return bool or KMX_BOOL
|
||||
#define AddWarningBool(warn) { if(AddCompileError(warn)) return FALSE; }
|
||||
/// Use AddWarning for functions that return KMX_DWORD
|
||||
#define AddWarning(warn) { if(AddCompileError(warn)) return CERR_Break; }
|
||||
|
||||
PKMX_WCHAR strtowstr(PKMX_STR in);
|
||||
PFILE_STORE FindSystemStore(PFILE_KEYBOARD fk, KMX_DWORD dwSystemID);
|
||||
bool UTF16TempFromUTF8(KMX_BYTE* infile, int sz, KMX_BYTE** tempfile, int *sz16);
|
||||
KMX_DWORD WriteCompiledKeyboard(PFILE_KEYBOARD fk, KMX_BYTE**data, size_t& dataSize);
|
||||
KMX_DWORD AddStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, const KMX_WCHAR * str, KMX_DWORD *dwStoreID= NULL);
|
||||
KMX_BOOL AddStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, const KMX_WCHAR * str, KMX_DWORD *dwStoreID= NULL);
|
||||
KMX_DWORD ReadLine(KMX_BYTE* infile, int sz, int& offset, PKMX_WCHAR wstr, KMX_BOOL PreProcess);
|
||||
KMX_DWORD ParseLine(PFILE_KEYBOARD fk, PKMX_WCHAR str);
|
||||
KMX_DWORD ProcessGroupLine(PFILE_KEYBOARD fk, PKMX_WCHAR p);
|
||||
KMX_DWORD ProcessGroupFinish(PFILE_KEYBOARD fk);
|
||||
KMX_DWORD ProcessStoreLine(PFILE_KEYBOARD fk, PKMX_WCHAR p);
|
||||
KMX_BOOL ParseLine(PFILE_KEYBOARD fk, PKMX_WCHAR str);
|
||||
KMX_BOOL ProcessGroupLine(PFILE_KEYBOARD fk, PKMX_WCHAR p);
|
||||
KMX_BOOL ProcessGroupFinish(PFILE_KEYBOARD fk);
|
||||
KMX_BOOL ProcessStoreLine(PFILE_KEYBOARD fk, PKMX_WCHAR p);
|
||||
int LineTokenType(PKMX_WCHAR *str);
|
||||
KMX_DWORD BuildVKDictionary(PFILE_KEYBOARD fk); // I3438
|
||||
KMX_BOOL BuildVKDictionary(PFILE_KEYBOARD fk); // I3438
|
||||
|
|
|
|||
|
|
@ -72,9 +72,9 @@ lib = library('kmcmplib',
|
|||
'CheckNCapsConsistency.cpp',
|
||||
'CompileKeyboardBuffer.cpp',
|
||||
'Compiler.cpp',
|
||||
'CompilerErrors.cpp',
|
||||
'CompilerInterfaces.cpp',
|
||||
'CompilerInterfacesWasm.cpp',
|
||||
'CompMsg.cpp',
|
||||
'cp1252.cpp',
|
||||
'DeprecationChecks.cpp',
|
||||
'Edition.cpp',
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
#include "versioning.h"
|
||||
|
||||
KMX_BOOL kmcmp::CheckKeyboardFinalVersion(PFILE_KEYBOARD fk) {
|
||||
KMX_CHAR buf[128];
|
||||
|
||||
if (fk->dwFlags & KF_AUTOMATICVERSION) {
|
||||
if (fk->version <= 0) {
|
||||
fk->version = VERSION_60; // minimum version that we can be safe with
|
||||
|
|
@ -15,8 +13,10 @@ KMX_BOOL kmcmp::CheckKeyboardFinalVersion(PFILE_KEYBOARD fk) {
|
|||
if(kmcmp::CompileTarget != CKF_KEYMANWEB) {
|
||||
// Note: the KeymanWeb compiler is responsible for reporting minimum
|
||||
// version for the web targets
|
||||
snprintf(buf, 128, "The compiler has assigned a minimum engine version of %d.%d based on features used in this keyboard", (int)((fk->version & 0xFF00) >> 8), (int)(fk->version & 0xFF));
|
||||
AddCompileWarning(buf);
|
||||
ReportCompilerMessage(KmnCompilerMessages::INFO_MinimumCoreEngineVersion, {
|
||||
/* majorVersion */ std::to_string((fk->version & 0xFF00) >> 8),
|
||||
/* minorVersion */ std::to_string(fk->version & 0xFF)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,11 +3,6 @@
|
|||
#include "compfile.h"
|
||||
#include "../../../../common/include/km_types.h"
|
||||
|
||||
#define VERIFY_KEYBOARD_VERSION(fk, ver, err) { \
|
||||
if(!VerifyKeyboardVersion((fk), (ver))) \
|
||||
return (err); \
|
||||
}
|
||||
|
||||
namespace kmcmp {
|
||||
KMX_BOOL CheckKeyboardFinalVersion(PFILE_KEYBOARD fk);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ int main(int argc, char *argv[]) {
|
|||
setup();
|
||||
test_kmcmp_CompileKeyboard(argv[1]);
|
||||
|
||||
setup();
|
||||
test_GetCompileTargetsFromTargetsStore();
|
||||
|
||||
return 0;
|
||||
|
|
@ -65,35 +66,72 @@ void test_kmcmp_CompileKeyboard(char *kmn_file) {
|
|||
options.target = CKF_KEYMAN;
|
||||
assert(!kmcmp_CompileKeyboard(kmn_file, options, msgproc, loadfileProc, nullptr, result));
|
||||
assert(error_vec.size() == 1);
|
||||
assert(error_vec[0] == CERR_CannotReadInfile);
|
||||
assert(error_vec[0] == KmnCompilerMessages::ERROR_InfileNotExist); // zero byte no longer gives us KmnCompilerMessages::ERROR_CannotReadInfile
|
||||
|
||||
unlink(kmn_file);
|
||||
}
|
||||
|
||||
extern KMX_DWORD GetCompileTargetsFromTargetsStore(const KMX_WCHAR* store, int &targets);
|
||||
extern KMX_BOOL GetCompileTargetsFromTargetsStore(const KMX_WCHAR* store, int &targets);
|
||||
|
||||
void test_GetCompileTargetsFromTargetsStore() {
|
||||
int targets = 0;
|
||||
assert(GetCompileTargetsFromTargetsStore(u"any", targets) == CERR_None);
|
||||
|
||||
setup();
|
||||
assert(GetCompileTargetsFromTargetsStore(u"any", targets));
|
||||
assert(error_vec.size() == 0);
|
||||
assert(targets == (COMPILETARGETS_KMX | COMPILETARGETS_JS));
|
||||
assert(GetCompileTargetsFromTargetsStore(u"windows", targets) == CERR_None);
|
||||
|
||||
setup();
|
||||
assert(GetCompileTargetsFromTargetsStore(u"windows", targets));
|
||||
assert(error_vec.size() == 0);
|
||||
assert(targets == COMPILETARGETS_KMX);
|
||||
assert(GetCompileTargetsFromTargetsStore(u"desktop", targets) == CERR_None);
|
||||
|
||||
setup();
|
||||
assert(GetCompileTargetsFromTargetsStore(u"desktop", targets));
|
||||
assert(error_vec.size() == 0);
|
||||
assert(targets == COMPILETARGETS_KMX);
|
||||
assert(GetCompileTargetsFromTargetsStore(u"mobile", targets) == CERR_None);
|
||||
|
||||
setup();
|
||||
assert(GetCompileTargetsFromTargetsStore(u"mobile", targets));
|
||||
assert(error_vec.size() == 0);
|
||||
assert(targets == COMPILETARGETS_JS);
|
||||
assert(GetCompileTargetsFromTargetsStore(u"web", targets) == CERR_None);
|
||||
|
||||
setup();
|
||||
assert(GetCompileTargetsFromTargetsStore(u"web", targets));
|
||||
assert(error_vec.size() == 0);
|
||||
assert(targets == COMPILETARGETS_JS);
|
||||
assert(GetCompileTargetsFromTargetsStore(u"desktop mobile", targets) == CERR_None);
|
||||
|
||||
setup();
|
||||
assert(GetCompileTargetsFromTargetsStore(u"desktop mobile", targets));
|
||||
assert(error_vec.size() == 0);
|
||||
assert(targets == (COMPILETARGETS_KMX | COMPILETARGETS_JS));
|
||||
assert(GetCompileTargetsFromTargetsStore(u"desktop tablet", targets) == CERR_None);
|
||||
|
||||
setup();
|
||||
assert(GetCompileTargetsFromTargetsStore(u"desktop tablet", targets));
|
||||
assert(error_vec.size() == 0);
|
||||
assert(targets == (COMPILETARGETS_KMX | COMPILETARGETS_JS));
|
||||
assert(GetCompileTargetsFromTargetsStore(u"foo bar baz", targets) == CERR_InvalidTarget);
|
||||
|
||||
setup();
|
||||
assert(!GetCompileTargetsFromTargetsStore(u"foo bar baz", targets));
|
||||
assert(error_vec.size() == 1);
|
||||
assert(error_vec[0] == KmnCompilerMessages::ERROR_InvalidTarget);
|
||||
assert(targets == 0);
|
||||
assert(GetCompileTargetsFromTargetsStore(u"windows chromeos", targets) == CERR_InvalidTarget);
|
||||
|
||||
setup();
|
||||
assert(!GetCompileTargetsFromTargetsStore(u"windows chromeos", targets));
|
||||
assert(error_vec.size() == 1);
|
||||
assert(error_vec[0] == KmnCompilerMessages::ERROR_InvalidTarget);
|
||||
assert(targets == 0);
|
||||
assert(GetCompileTargetsFromTargetsStore(u" ", targets) == CERR_NoTargetsSpecified);
|
||||
|
||||
setup();
|
||||
assert(!GetCompileTargetsFromTargetsStore(u" ", targets));
|
||||
assert(error_vec.size() == 1);
|
||||
assert(error_vec[0] == KmnCompilerMessages::ERROR_NoTargetsSpecified);
|
||||
assert(targets == 0);
|
||||
assert(GetCompileTargetsFromTargetsStore(u"", targets) == CERR_NoTargetsSpecified);
|
||||
|
||||
setup();
|
||||
assert(!GetCompileTargetsFromTargetsStore(u"", targets));
|
||||
assert(error_vec.size() == 1);
|
||||
assert(error_vec[0] == KmnCompilerMessages::ERROR_NoTargetsSpecified);
|
||||
assert(targets == 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,15 +3,14 @@
|
|||
#include "../include/kmcmplibapi.h"
|
||||
#include "../src/kmx_u16.h"
|
||||
#include "../src/compfile.h"
|
||||
#include "../src/CompMsg.h"
|
||||
#include "../src/CompilerErrors.h"
|
||||
#include "../../common/include/kmn_compiler_errors.h"
|
||||
#include "../../../../common/include/km_types.h"
|
||||
#include "../../../../common/include/kmx_file.h"
|
||||
|
||||
PKMX_WCHAR strtowstr(PKMX_STR in);
|
||||
PKMX_STR wstrtostr(PKMX_WCHAR in);
|
||||
KMX_BOOL AddCompileError(KMX_DWORD msg);
|
||||
KMX_DWORD ProcessBeginLine(PFILE_KEYBOARD fk, PKMX_WCHAR p);
|
||||
KMX_BOOL ProcessBeginLine(PFILE_KEYBOARD fk, PKMX_WCHAR p);
|
||||
KMX_DWORD ValidateMatchNomatchOutput(PKMX_WCHAR p);
|
||||
KMX_BOOL IsValidKeyboardVersion(KMX_WCHAR *dpString);
|
||||
PKMX_WCHAR GetDelimitedString(PKMX_WCHAR *p, KMX_WCHAR const * Delimiters, KMX_WORD Flags);
|
||||
|
|
@ -25,19 +24,13 @@ bool isIntegerWstring(PKMX_WCHAR p);
|
|||
bool hasPreamble(std::u16string result);
|
||||
KMX_DWORD ProcessKeyLineImpl(PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX_BOOL IsUnicode, PKMX_WCHAR pklIn, PKMX_WCHAR pklKey, PKMX_WCHAR pklOut);
|
||||
|
||||
extern kmcmp_CompilerMessageProc msgproc;
|
||||
|
||||
namespace kmcmp {
|
||||
extern int nErrors;
|
||||
extern int ErrChr;
|
||||
extern int BeginLine[4];
|
||||
extern int CompileTarget;
|
||||
KMX_BOOL AddCompileWarning(char* buf);
|
||||
}
|
||||
|
||||
#define ERR_EXTRA_LIB_LEN 256
|
||||
extern char ErrExtraLIB[ERR_EXTRA_LIB_LEN];
|
||||
|
||||
class CompilerTest : public testing::Test {
|
||||
protected:
|
||||
FILE_KEYBOARD fileKeyboard;
|
||||
|
|
@ -53,11 +46,10 @@ class CompilerTest : public testing::Test {
|
|||
}
|
||||
|
||||
void initGlobals() {
|
||||
msgproc = NULL;
|
||||
szText_stub[0] = '\0';
|
||||
kmcmp::msgproc = msgproc_collect;
|
||||
msgproc_errors.clear();
|
||||
kmcmp::nErrors = 0;
|
||||
kmcmp::ErrChr = 0;
|
||||
ErrExtraLIB[0] = '\0';
|
||||
kmcmp::BeginLine[BEGIN_ANSI] = -1;
|
||||
kmcmp::BeginLine[BEGIN_UNICODE] = -1;
|
||||
kmcmp::BeginLine[BEGIN_NEWCONTEXT] = -1;
|
||||
|
|
@ -115,21 +107,14 @@ class CompilerTest : public testing::Test {
|
|||
}
|
||||
|
||||
public:
|
||||
static KMX_CHAR szText_stub[];
|
||||
static std::vector<KMCMP_COMPILER_RESULT_MESSAGE> msgproc_errors;
|
||||
|
||||
static int msgproc_true_stub(int line, uint32_t dwMsgCode, const char* szText, void* context) {
|
||||
strcpy(szText_stub, szText);
|
||||
return 1;
|
||||
};
|
||||
|
||||
static int msgproc_false_stub(int line, uint32_t dwMsgCode, const char* szText, void* context) {
|
||||
strcpy(szText_stub, szText);
|
||||
return 0;
|
||||
};
|
||||
static void msgproc_collect(const KMCMP_COMPILER_RESULT_MESSAGE &message, void* context) {
|
||||
msgproc_errors.push_back(message);
|
||||
}
|
||||
};
|
||||
|
||||
#define COMPILE_ERROR_MAX_LEN (SZMAX_ERRORTEXT + 1 + 280)
|
||||
KMX_CHAR CompilerTest::szText_stub[COMPILE_ERROR_MAX_LEN];
|
||||
std::vector<KMCMP_COMPILER_RESULT_MESSAGE> CompilerTest::msgproc_errors;
|
||||
|
||||
TEST_F(CompilerTest, strtowstr_test) {
|
||||
EXPECT_EQ(0, u16cmp(u"hello", strtowstr((PKMX_STR)"hello")));
|
||||
|
|
@ -141,129 +126,120 @@ TEST_F(CompilerTest, wstrtostr_test) {
|
|||
EXPECT_EQ(0, strcmp("", wstrtostr((PKMX_WCHAR)u"")));
|
||||
};
|
||||
|
||||
TEST_F(CompilerTest, AddCompileWarning_test) {
|
||||
msgproc = msgproc_false_stub;
|
||||
const char *const WARNING_TEXT = "warning";
|
||||
EXPECT_EQ(0, kmcmp::nErrors);
|
||||
EXPECT_FALSE(kmcmp::AddCompileWarning((PKMX_CHAR)WARNING_TEXT));
|
||||
EXPECT_EQ(0, strcmp(WARNING_TEXT, szText_stub));
|
||||
EXPECT_EQ(0, kmcmp::nErrors);
|
||||
};
|
||||
// TEST_F(CompilerTest, ReportCompilerMessage_test) {
|
||||
// msgproc = msgproc_true_stub;
|
||||
// kmcmp::ErrChr = 0;
|
||||
|
||||
TEST_F(CompilerTest, AddCompileError_test) {
|
||||
msgproc = msgproc_true_stub;
|
||||
kmcmp::ErrChr = 0;
|
||||
ErrExtraLIB[0] = '\0';
|
||||
KMX_CHAR expected[COMPILE_ERROR_MAX_LEN];
|
||||
// // SevFatal
|
||||
// EXPECT_EQ(0, kmcmp::nErrors);
|
||||
// EXPECT_EQ(SevFatal, KmnCompilerMessages::FATAL_CannotCreateTempfile & SevFatal);
|
||||
// EXPECT_TRUE(ReportCompilerMessage(KmnCompilerMessages::FATAL_CannotCreateTempfile));
|
||||
// EXPECT_EQ(1, kmcmp::nErrors);
|
||||
|
||||
// CERR_FATAL
|
||||
EXPECT_EQ(0, kmcmp::nErrors);
|
||||
EXPECT_EQ(CERR_FATAL, CERR_CannotCreateTempfile & CERR_FATAL);
|
||||
EXPECT_TRUE(AddCompileError(CERR_CannotCreateTempfile));
|
||||
EXPECT_EQ(0, strcmp(GetCompilerErrorString(CERR_CannotCreateTempfile), szText_stub));
|
||||
EXPECT_EQ(1, kmcmp::nErrors);
|
||||
// // SevError
|
||||
// EXPECT_EQ(SevError, KmnCompilerMessages::ERROR_InvalidLayoutLine & SevError);
|
||||
// EXPECT_FALSE(ReportCompilerMessage(KmnCompilerMessages::ERROR_InvalidLayoutLine));
|
||||
// EXPECT_EQ(2, kmcmp::nErrors);
|
||||
|
||||
// CERR_ERROR
|
||||
EXPECT_EQ(CERR_ERROR, CERR_InvalidLayoutLine & CERR_ERROR);
|
||||
EXPECT_FALSE(AddCompileError(CERR_InvalidLayoutLine));
|
||||
EXPECT_EQ(0, strcmp(GetCompilerErrorString(CERR_InvalidLayoutLine), szText_stub));
|
||||
EXPECT_EQ(2, kmcmp::nErrors);
|
||||
// // Unknown
|
||||
// const KMX_DWORD UNKNOWN_ERROR = 0x00004FFF; // top of range ERROR
|
||||
// EXPECT_EQ(SevError, UNKNOWN_ERROR & SevError);
|
||||
// EXPECT_FALSE(ReportCompilerMessage(UNKNOWN_ERROR));
|
||||
// sprintf(expected, "Unknown error %x", UNKNOWN_ERROR);
|
||||
// EXPECT_EQ(3, kmcmp::nErrors);
|
||||
|
||||
// Unknown
|
||||
const KMX_DWORD UNKNOWN_ERROR = 0x00004FFF; // top of range ERROR
|
||||
EXPECT_EQ(CERR_ERROR, UNKNOWN_ERROR & CERR_ERROR);
|
||||
EXPECT_FALSE(AddCompileError(UNKNOWN_ERROR));
|
||||
sprintf(expected, "Unknown error %x", UNKNOWN_ERROR);
|
||||
EXPECT_EQ(0, strcmp(expected, szText_stub));
|
||||
EXPECT_EQ(3, kmcmp::nErrors);
|
||||
// // ErrChr
|
||||
// const int ERROR_CHAR_INDEX = 42;
|
||||
// kmcmp::ErrChr = ERROR_CHAR_INDEX ;
|
||||
// EXPECT_EQ(SevError, KmnCompilerMessages::ERROR_InvalidLayoutLine & SevError);
|
||||
// EXPECT_FALSE(ReportCompilerMessage(KmnCompilerMessages::ERROR_InvalidLayoutLine));
|
||||
// kmcmp::ErrChr = 0;
|
||||
// EXPECT_EQ(4, kmcmp::nErrors);
|
||||
|
||||
// ErrChr
|
||||
const int ERROR_CHAR_INDEX = 42;
|
||||
kmcmp::ErrChr = ERROR_CHAR_INDEX ;
|
||||
EXPECT_EQ(CERR_ERROR, CERR_InvalidLayoutLine & CERR_ERROR);
|
||||
EXPECT_FALSE(AddCompileError(CERR_InvalidLayoutLine));
|
||||
sprintf(expected, "%s character offset: %d", GetCompilerErrorString(CERR_InvalidLayoutLine), ERROR_CHAR_INDEX);
|
||||
EXPECT_EQ(0, strcmp(expected, szText_stub));
|
||||
kmcmp::ErrChr = 0;
|
||||
EXPECT_EQ(4, kmcmp::nErrors);
|
||||
|
||||
// ErrExtraLIB
|
||||
const char *const EXTRA_LIB_TEXT = " extra lib";
|
||||
strcpy(ErrExtraLIB, EXTRA_LIB_TEXT);
|
||||
EXPECT_EQ(CERR_ERROR, CERR_InvalidLayoutLine & CERR_ERROR);
|
||||
EXPECT_FALSE(AddCompileError(CERR_InvalidLayoutLine));
|
||||
sprintf(expected, "%s%s", GetCompilerErrorString(CERR_InvalidLayoutLine), EXTRA_LIB_TEXT);
|
||||
EXPECT_EQ(0, strcmp(expected, szText_stub));
|
||||
ErrExtraLIB[0] = '\0';
|
||||
EXPECT_EQ(5, kmcmp::nErrors);
|
||||
|
||||
// msgproc returns FALSE
|
||||
msgproc = msgproc_false_stub;
|
||||
EXPECT_EQ(CERR_ERROR, CERR_InvalidLayoutLine & CERR_ERROR);
|
||||
EXPECT_TRUE(AddCompileError(CERR_InvalidLayoutLine));
|
||||
EXPECT_EQ(0, strcmp(GetCompilerErrorString(CERR_InvalidLayoutLine), szText_stub));
|
||||
EXPECT_EQ(6, kmcmp::nErrors);
|
||||
};
|
||||
// // msgproc returns FALSE
|
||||
// msgproc = msgproc_false_stub;
|
||||
// EXPECT_EQ(SevError, KmnCompilerMessages::ERROR_InvalidLayoutLine & SevError);
|
||||
// EXPECT_TRUE(ReportCompilerMessage(KmnCompilerMessages::ERROR_InvalidLayoutLine));
|
||||
// EXPECT_EQ(6, kmcmp::nErrors);
|
||||
// };
|
||||
|
||||
TEST_F(CompilerTest, ProcessBeginLine_test) {
|
||||
KMX_WCHAR str[LINESIZE];
|
||||
|
||||
// CERR_NoTokensFound
|
||||
// KmnCompilerMessages::ERROR_NoTokensFound
|
||||
msgproc_errors.clear();
|
||||
u16cpy(str, u"");
|
||||
EXPECT_EQ(CERR_NoTokensFound, ProcessBeginLine(&fileKeyboard, str));
|
||||
EXPECT_EQ(FALSE, ProcessBeginLine(&fileKeyboard, str));
|
||||
EXPECT_EQ(1, msgproc_errors.size());
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_NoTokensFound, msgproc_errors[0].errorCode);
|
||||
|
||||
// CERR_InvalidToken
|
||||
// KmnCompilerMessages::ERROR_InvalidToken
|
||||
msgproc_errors.clear();
|
||||
u16cpy(str, u"abc >");
|
||||
EXPECT_EQ(CERR_InvalidToken, ProcessBeginLine(&fileKeyboard, str));
|
||||
EXPECT_EQ(FALSE, ProcessBeginLine(&fileKeyboard, str));
|
||||
EXPECT_EQ(1, msgproc_errors.size());
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, msgproc_errors[0].errorCode);
|
||||
|
||||
// CERR_RepeatedBegin, BEGIN_UNICODE
|
||||
// KmnCompilerMessages::ERROR_RepeatedBegin, BEGIN_UNICODE
|
||||
msgproc_errors.clear();
|
||||
kmcmp::BeginLine[BEGIN_UNICODE] = 0; // not -1
|
||||
u16cpy(str, u" unicode>");
|
||||
EXPECT_EQ(CERR_RepeatedBegin, ProcessBeginLine(&fileKeyboard, str));
|
||||
EXPECT_EQ(FALSE, ProcessBeginLine(&fileKeyboard, str));
|
||||
EXPECT_EQ(1, msgproc_errors.size());
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_RepeatedBegin, msgproc_errors[0].errorCode);
|
||||
kmcmp::BeginLine[BEGIN_UNICODE] = -1;
|
||||
|
||||
// CERR_RepeatedBegin, BEGIN_ANSI
|
||||
// KmnCompilerMessages::ERROR_RepeatedBegin, BEGIN_ANSI
|
||||
msgproc_errors.clear();
|
||||
kmcmp::BeginLine[BEGIN_ANSI] = 0; // not -1
|
||||
u16cpy(str, u" ansi>");
|
||||
EXPECT_EQ(CERR_RepeatedBegin, ProcessBeginLine(&fileKeyboard, str));
|
||||
EXPECT_EQ(FALSE, ProcessBeginLine(&fileKeyboard, str));
|
||||
EXPECT_EQ(1, msgproc_errors.size());
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_RepeatedBegin, msgproc_errors[0].errorCode);
|
||||
kmcmp::BeginLine[BEGIN_ANSI] = -1;
|
||||
|
||||
// CERR_RepeatedBegin, BEGIN_NEWCONTEXT
|
||||
// KmnCompilerMessages::ERROR_RepeatedBegin, BEGIN_NEWCONTEXT
|
||||
msgproc_errors.clear();
|
||||
kmcmp::BeginLine[BEGIN_NEWCONTEXT] = 0; // not -1
|
||||
u16cpy(str, u" newContext>");
|
||||
EXPECT_EQ(CERR_RepeatedBegin, ProcessBeginLine(&fileKeyboard, str));
|
||||
EXPECT_EQ(FALSE, ProcessBeginLine(&fileKeyboard, str));
|
||||
EXPECT_EQ(1, msgproc_errors.size());
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_RepeatedBegin, msgproc_errors[0].errorCode);
|
||||
kmcmp::BeginLine[BEGIN_NEWCONTEXT] = -1;
|
||||
|
||||
// CERR_RepeatedBegin, BEGIN_POSTKEYSTROKE
|
||||
// KmnCompilerMessages::ERROR_RepeatedBegin, BEGIN_POSTKEYSTROKE
|
||||
msgproc_errors.clear();
|
||||
kmcmp::BeginLine[BEGIN_POSTKEYSTROKE] = 0; // not -1
|
||||
u16cpy(str, u" postKeystroke>");
|
||||
EXPECT_EQ(CERR_RepeatedBegin, ProcessBeginLine(&fileKeyboard, str));
|
||||
EXPECT_EQ(FALSE, ProcessBeginLine(&fileKeyboard, str));
|
||||
EXPECT_EQ(1, msgproc_errors.size());
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_RepeatedBegin, msgproc_errors[0].errorCode);
|
||||
kmcmp::BeginLine[BEGIN_POSTKEYSTROKE] = -1;
|
||||
};
|
||||
|
||||
TEST_F(CompilerTest, ValidateMatchNomatchOutput_test) {
|
||||
EXPECT_EQ(CERR_None, ValidateMatchNomatchOutput(NULL));
|
||||
EXPECT_EQ(CERR_None, ValidateMatchNomatchOutput((PKMX_WCHAR)u""));
|
||||
EXPECT_EQ(STATUS_Success, ValidateMatchNomatchOutput(NULL));
|
||||
EXPECT_EQ(STATUS_Success, ValidateMatchNomatchOutput((PKMX_WCHAR)u""));
|
||||
const KMX_WCHAR context[] = { 'a', 'b', 'c', UC_SENTINEL, CODE_CONTEXT, 'd', 'e', 'f', 0 };
|
||||
EXPECT_EQ(CERR_ContextAndIndexInvalidInMatchNomatch, ValidateMatchNomatchOutput((PKMX_WCHAR)context));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_ContextAndIndexInvalidInMatchNomatch, ValidateMatchNomatchOutput((PKMX_WCHAR)context));
|
||||
const KMX_WCHAR contextex[] = { 'a', 'b', 'c', UC_SENTINEL, CODE_CONTEXTEX, 'd', 'e', 'f', 0 };
|
||||
EXPECT_EQ(CERR_ContextAndIndexInvalidInMatchNomatch, ValidateMatchNomatchOutput((PKMX_WCHAR)contextex));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_ContextAndIndexInvalidInMatchNomatch, ValidateMatchNomatchOutput((PKMX_WCHAR)contextex));
|
||||
const KMX_WCHAR index[] = { 'a', 'b', 'c', UC_SENTINEL, CODE_INDEX, 'd', 'e', 'f', 0 };
|
||||
EXPECT_EQ(CERR_ContextAndIndexInvalidInMatchNomatch, ValidateMatchNomatchOutput((PKMX_WCHAR)index));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_ContextAndIndexInvalidInMatchNomatch, ValidateMatchNomatchOutput((PKMX_WCHAR)index));
|
||||
const KMX_WCHAR sentinel[] = { 'a', 'b', 'c', UC_SENTINEL, 'd', 'e', 'f', 0 };
|
||||
EXPECT_EQ(CERR_None, ValidateMatchNomatchOutput((PKMX_WCHAR)sentinel));
|
||||
EXPECT_EQ(STATUS_Success, ValidateMatchNomatchOutput((PKMX_WCHAR)sentinel));
|
||||
};
|
||||
|
||||
// KMX_DWORD ParseLine(PFILE_KEYBOARD fk, PKMX_WCHAR str)
|
||||
// KMX_DWORD ProcessGroupLine(PFILE_KEYBOARD fk, PKMX_WCHAR p)
|
||||
// KMX_BOOL ParseLine(PFILE_KEYBOARD fk, PKMX_WCHAR str)
|
||||
// KMX_BOOL ProcessGroupLine(PFILE_KEYBOARD fk, PKMX_WCHAR p)
|
||||
// int kmcmp::cmpkeys(const void *key, const void *elem)
|
||||
// KMX_DWORD ProcessGroupFinish(PFILE_KEYBOARD fk)
|
||||
// KMX_DWORD ProcessStoreLine(PFILE_KEYBOARD fk, PKMX_WCHAR p)
|
||||
// KMX_BOOL ProcessGroupFinish(PFILE_KEYBOARD fk)
|
||||
// KMX_BOOL ProcessStoreLine(PFILE_KEYBOARD fk, PKMX_WCHAR p)
|
||||
// bool resizeStoreArray(PFILE_KEYBOARD fk)
|
||||
// bool resizeKeyArray(PFILE_GROUP gp, int increment)
|
||||
// KMX_DWORD AddStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, const KMX_WCHAR * str, KMX_DWORD *dwStoreID)
|
||||
// KMX_BOOL AddStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, const KMX_WCHAR * str, KMX_DWORD *dwStoreID)
|
||||
// KMX_DWORD AddDebugStore(PFILE_KEYBOARD fk, KMX_WCHAR const * str)
|
||||
// KMX_DWORD ProcessSystemStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, PFILE_STORE sp)
|
||||
// KMX_BOOL ProcessSystemStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, PFILE_STORE sp)
|
||||
// int GetCompileTargetsFromTargetsStore(const KMX_WCHAR* store)
|
||||
|
||||
TEST_F(CompilerTest, IsValidKeyboardVersion_test) {
|
||||
|
|
@ -281,7 +257,7 @@ TEST_F(CompilerTest, IsValidKeyboardVersion_test) {
|
|||
|
||||
// KMX_DWORD kmcmp::AddCompilerVersionStore(PFILE_KEYBOARD fk)
|
||||
// KMX_DWORD CheckStatementOffsets(PFILE_KEYBOARD fk, PFILE_GROUP gp, PKMX_WCHAR context, PKMX_WCHAR output, PKMX_WCHAR key)
|
||||
// KMX_BOOL CheckContextStatementPositions(PKMX_WCHAR context)
|
||||
// void CheckContextStatementPositions(PKMX_WCHAR context)
|
||||
// KMX_DWORD CheckUseStatementsInOutput(PKMX_WCHAR output)
|
||||
// KMX_DWORD CheckVirtualKeysInOutput(PKMX_WCHAR output)
|
||||
// KMX_DWORD InjectContextToReadonlyOutput(PKMX_WCHAR pklOut)
|
||||
|
|
@ -300,10 +276,10 @@ TEST_F(CompilerTest, ProcessKeyLineImpl_test) {
|
|||
|
||||
// #11643: non-BMP characters do not makes sense for key codes
|
||||
u16cpy(str, u"+ 'A' > 'test'\n"); // baseline
|
||||
EXPECT_EQ(CERR_None, ProcessKeyLineImpl(&fileKeyboard, str, TRUE, pklIn, pklKey, pklOut));
|
||||
EXPECT_EQ(STATUS_Success, ProcessKeyLineImpl(&fileKeyboard, str, TRUE, pklIn, pklKey, pklOut));
|
||||
|
||||
u16cpy(str, u"+ '\U00010000' > 'test'\n"); // surrogate pair
|
||||
EXPECT_EQ(CERR_NonBMPCharactersNotSupportedInKeySection, ProcessKeyLineImpl(&fileKeyboard, str, TRUE, pklIn, pklKey, pklOut));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_NonBMPCharactersNotSupportedInKeySection, ProcessKeyLineImpl(&fileKeyboard, str, TRUE, pklIn, pklKey, pklOut));
|
||||
|
||||
delete[] pklIn;
|
||||
delete[] pklKey;
|
||||
|
|
@ -672,22 +648,22 @@ TEST_F(CompilerTest, GetXStringImpl_test) {
|
|||
PKMX_WCHAR newp = nullptr;
|
||||
KMX_WCHAR token[128];
|
||||
|
||||
// CERR_BufferOverflow, max=0
|
||||
EXPECT_EQ(CERR_BufferOverflow, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 0, 0, &newp, FALSE));
|
||||
// KmnCompilerMessages::FATAL_BufferOverflow, max=0
|
||||
EXPECT_EQ(KmnCompilerMessages::FATAL_BufferOverflow, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 0, 0, &newp, FALSE));
|
||||
|
||||
// CERR_None, no token
|
||||
// STATUS_Success, no token
|
||||
u16cpy(str, u"");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// CERR_NoTokensFound, empty
|
||||
// KmnCompilerMessages::ERROR_NoTokensFound, empty
|
||||
u16cpy(str, u"");
|
||||
u16cpy(token, u"c");
|
||||
EXPECT_EQ(CERR_NoTokensFound, GetXStringImpl(tstr, &fileKeyboard, str, token, output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_NoTokensFound, GetXStringImpl(tstr, &fileKeyboard, str,token, output, 80, 0, &newp, FALSE));
|
||||
|
||||
// CERR_NoTokensFound, whitespace
|
||||
// KmnCompilerMessages::ERROR_NoTokensFound, whitespace
|
||||
u16cpy(str, u" ");
|
||||
u16cpy(token, u"c");
|
||||
EXPECT_EQ(CERR_NoTokensFound, GetXStringImpl(tstr, &fileKeyboard, str, token, output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_NoTokensFound, GetXStringImpl(tstr, &fileKeyboard, str, token, output, 80, 0, &newp, FALSE));
|
||||
}
|
||||
|
||||
// tests strings starting with 'x' or 'd'
|
||||
|
|
@ -699,28 +675,28 @@ TEST_F(CompilerTest, GetXStringImpl_type_xd_test) {
|
|||
|
||||
// hex 32-bit
|
||||
u16cpy(str, u"x10330"); // Gothic A
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_GothicA[] = { 0xD800, 0xDF30, 0 }; // see UTF32ToUTF16
|
||||
EXPECT_EQ(0, u16cmp(tstr_GothicA, tstr));
|
||||
|
||||
// decimal 8-bit
|
||||
u16cpy(str, u"d18");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(0, u16cmp(u"\u0012", tstr));
|
||||
|
||||
// hex capital 8-bit
|
||||
u16cpy(str, u"X12");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(0, u16cmp(u"\u0012", tstr));
|
||||
|
||||
// hex 32-bit, CERR_InvalidCharacter
|
||||
// hex 32-bit, KmnCompilerMessages::ERROR_InvalidCharacter
|
||||
u16cpy(str, u"x110000");
|
||||
EXPECT_EQ(CERR_InvalidCharacter, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidCharacter, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// dk, valid
|
||||
u16cpy(str, u"dk(A)");
|
||||
EXPECT_EQ(0, (int)fileKeyboard.cxDeadKeyArray);
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_dk_valid[] = { UC_SENTINEL, CODE_DEADKEY, 1, 0 }; // setup deadkeys
|
||||
EXPECT_EQ(0, u16cmp(tstr_dk_valid, tstr));
|
||||
fileKeyboard.cxDeadKeyArray = 0;
|
||||
|
|
@ -728,22 +704,22 @@ TEST_F(CompilerTest, GetXStringImpl_type_xd_test) {
|
|||
// deadkey, valid
|
||||
u16cpy(str, u"deadkey(A)");
|
||||
EXPECT_EQ(0, (int)fileKeyboard.cxDeadKeyArray);
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_deadkey_valid[] = { UC_SENTINEL, CODE_DEADKEY, 1, 0 }; // setup deadkeys
|
||||
EXPECT_EQ(0, u16cmp(tstr_deadkey_valid, tstr));
|
||||
fileKeyboard.cxDeadKeyArray = 0;
|
||||
|
||||
// dk, CERR_InvalidDeadkey, bad character
|
||||
// dk, KmnCompilerMessages::ERROR_InvalidDeadkey, bad character
|
||||
u16cpy(str, u"dk(%)");
|
||||
EXPECT_EQ(CERR_InvalidDeadkey, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidDeadkey, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// dk, CERR_InvalidDeadkey, no close delimiter => NULL
|
||||
// dk, KmnCompilerMessages::ERROR_InvalidDeadkey, no close delimiter => NULL
|
||||
u16cpy(str, u"dk(");
|
||||
EXPECT_EQ(CERR_InvalidDeadkey, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidDeadkey, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// dk, CERR_InvalidDeadkey, empty delimiters => empty string
|
||||
// dk, KmnCompilerMessages::ERROR_InvalidDeadkey, empty delimiters => empty string
|
||||
u16cpy(str, u"dk()");
|
||||
EXPECT_EQ(CERR_InvalidDeadkey, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidDeadkey, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
}
|
||||
|
||||
// tests strings starting with double quote
|
||||
|
|
@ -755,18 +731,18 @@ TEST_F(CompilerTest, GetXStringImpl_type_double_quote_test) {
|
|||
|
||||
// valid
|
||||
u16cpy(str, u"\"abc\"");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(0, u16cmp(u"abc", tstr));
|
||||
|
||||
// CERR_UnterminatedString
|
||||
// KmnCompilerMessages::ERROR_UnterminatedString
|
||||
u16cpy(str, u"\"abc");
|
||||
EXPECT_EQ(CERR_UnterminatedString, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_UnterminatedString, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// CERR_ExtendedStringTooLong
|
||||
// KmnCompilerMessages::ERROR_ExtendedStringTooLong
|
||||
u16cpy(str, u"\"abc\"");
|
||||
EXPECT_EQ(CERR_ExtendedStringTooLong, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 2, 0, &newp, FALSE)); // max reduced to force error
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_ExtendedStringTooLong, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 2, 0, &newp, FALSE)); // max reduced to force error
|
||||
|
||||
// CERR_StringInVirtualKeySection *** TODO ***
|
||||
// KmnCompilerMessages::ERROR_StringInVirtualKeySection *** TODO ***
|
||||
}
|
||||
|
||||
// tests strings starting with single quote
|
||||
|
|
@ -778,18 +754,18 @@ TEST_F(CompilerTest, GetXStringImpl_type_single_quote_test) {
|
|||
|
||||
// valid
|
||||
u16cpy(str, u"\'abc\'");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(0, u16cmp(u"abc", tstr));
|
||||
|
||||
// CERR_UnterminatedString
|
||||
// KmnCompilerMessages::ERROR_UnterminatedString
|
||||
u16cpy(str, u"\'abc");
|
||||
EXPECT_EQ(CERR_UnterminatedString, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_UnterminatedString, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// CERR_ExtendedStringTooLong
|
||||
// KmnCompilerMessages::ERROR_ExtendedStringTooLong
|
||||
u16cpy(str, u"\'abc\'");
|
||||
EXPECT_EQ(CERR_ExtendedStringTooLong, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 2, 0, &newp, FALSE)); // max reduced to force error
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_ExtendedStringTooLong, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 2, 0, &newp, FALSE)); // max reduced to force error
|
||||
|
||||
// CERR_StringInVirtualKeySection *** TODO ***
|
||||
// KmnCompilerMessages::ERROR_StringInVirtualKeySection *** TODO ***
|
||||
}
|
||||
|
||||
// tests strings starting with 'a'
|
||||
|
|
@ -805,59 +781,59 @@ TEST_F(CompilerTest, GetXStringImpl_type_a_test) {
|
|||
u16cpy(file_store[1].szName, u"b");
|
||||
u16cpy(file_store[2].szName, u"c");
|
||||
|
||||
// CERR_InvalidToken
|
||||
// KmnCompilerMessages::ERROR_InvalidToken
|
||||
u16cpy(str, u"abc");
|
||||
EXPECT_EQ(CERR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// CERR_AnyInVirtualKeySection *** TODO ***
|
||||
// KmnCompilerMessages::ERROR_AnyInVirtualKeySection *** TODO ***
|
||||
|
||||
// CERR_InvalidAny, no close delimiter => NULL
|
||||
// KmnCompilerMessages::ERROR_InvalidAny, no close delimiter => NULL
|
||||
u16cpy(str, u"any(");
|
||||
EXPECT_EQ(CERR_InvalidAny, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidAny, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// CERR_InvalidAny, empty delimiters => empty string
|
||||
// KmnCompilerMessages::ERROR_InvalidAny, empty delimiters => empty string
|
||||
u16cpy(str, u"any()");
|
||||
EXPECT_EQ(CERR_InvalidAny, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidAny, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// CERR_InvalidAny, space in delimiters (see I11814, I11937, #11910, #11894, #11938)
|
||||
// KmnCompilerMessages::ERROR_InvalidAny, space in delimiters (see I11814, I11937, #11910, #11894, #11938)
|
||||
u16cpy(str, u"any( )");
|
||||
EXPECT_EQ(CERR_InvalidAny, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidAny, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// CERR_StoreDoesNotExist
|
||||
// KmnCompilerMessages::ERROR_StoreDoesNotExist
|
||||
u16cpy(str, u"any(d)");
|
||||
EXPECT_EQ(CERR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// CERR_StoreDoesNotExist, space before store
|
||||
// KmnCompilerMessages::ERROR_StoreDoesNotExist, space before store
|
||||
u16cpy(str, u"any( d)");
|
||||
EXPECT_EQ(CERR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// CERR_StoreDoesNotExist, space after store
|
||||
// KmnCompilerMessages::ERROR_StoreDoesNotExist, space after store
|
||||
u16cpy(str, u"any(d )");
|
||||
EXPECT_EQ(CERR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// CERR_ZeroLengthString
|
||||
// KmnCompilerMessages::ERROR_ZeroLengthString
|
||||
u16cpy(str, u"any(b)");
|
||||
file_store[1].dpString = (PKMX_WCHAR)u"";
|
||||
EXPECT_EQ(CERR_ZeroLengthString, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_ZeroLengthString, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// valid
|
||||
u16cpy(str, u"any(b)");
|
||||
file_store[1].dpString = (PKMX_WCHAR)u"abc"; // non-empty
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_any_valid[] = { UC_SENTINEL, CODE_ANY, 2, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_any_valid, tstr));
|
||||
|
||||
// space before store, valid
|
||||
u16cpy(str, u"any( b)");
|
||||
file_store[1].dpString = (PKMX_WCHAR)u"abc"; // non-empty
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_any_space_before_valid[] = { UC_SENTINEL, CODE_ANY, 2, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_any_space_before_valid, tstr));
|
||||
|
||||
// space after store, valid (see I11937, #11938)
|
||||
u16cpy(str, u"any(b )");
|
||||
file_store[1].dpString = (PKMX_WCHAR)u"abc"; // non-empty
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_any_space_after_valid[] = { UC_SENTINEL, CODE_ANY, 2, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_any_space_after_valid, tstr));
|
||||
}
|
||||
|
|
@ -870,53 +846,53 @@ TEST_F(CompilerTest, GetXStringImpl_type_b_test) {
|
|||
KMX_WCHAR output[GLOBAL_BUFSIZE];
|
||||
PKMX_WCHAR newp = nullptr;
|
||||
|
||||
// CERR_InvalidToken
|
||||
// KmnCompilerMessages::ERROR_InvalidToken
|
||||
u16cpy(str, u"bcd");
|
||||
EXPECT_EQ(CERR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// beep, CERR_BeepInVirtualKeySection *** TODO ***
|
||||
// beep, KmnCompilerMessages::ERROR_BeepInVirtualKeySection *** TODO ***
|
||||
|
||||
// beep, valid
|
||||
u16cpy(str, u"beep");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_beep_valid[] = { UC_SENTINEL, CODE_BEEP, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_beep_valid, tstr));
|
||||
|
||||
// baselayout, CERR_90FeatureOnly_IfSystemStores
|
||||
// baselayout, KmnCompilerMessages::ERROR_90FeatureOnly_IfSystemStores
|
||||
fileKeyboard.version = VERSION_80;
|
||||
fileKeyboard.dwFlags = 0u;
|
||||
u16cpy(str, u"baselayout");
|
||||
EXPECT_EQ(CERR_90FeatureOnly_IfSystemStores, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_90FeatureOnly_IfSystemStores, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
fileKeyboard.version = VERSION_90;
|
||||
|
||||
// baselayout, CERR_InvalidInVirtualKeySection *** TODO ***
|
||||
// baselayout, KmnCompilerMessages::ERROR_InvalidInVirtualKeySection *** TODO ***
|
||||
|
||||
// baselayout, no close delimiter => NULL
|
||||
fileKeyboard.version = VERSION_90;
|
||||
u16cpy(str, u"baselayout(");
|
||||
EXPECT_EQ(CERR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// baselayout, empty delimiters => empty string
|
||||
fileKeyboard.version = VERSION_90;
|
||||
u16cpy(str, u"baselayout()");
|
||||
EXPECT_EQ(CERR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// baselayout, space in delimiters (see I11814, I11937, #11910, #11894, #11938)
|
||||
fileKeyboard.version = VERSION_90;
|
||||
u16cpy(str, u"baselayout( )");
|
||||
EXPECT_EQ(CERR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// baselayout, CERR_InvalidToken from process_baselayout
|
||||
// baselayout, KmnCompilerMessages::ERROR_InvalidToken from process_baselayout
|
||||
fileKeyboard.version = VERSION_90;
|
||||
u16cpy(str, u"baselayout(abc)");
|
||||
EXPECT_EQ(CERR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// baselayout, valid
|
||||
fileKeyboard.version = VERSION_90;
|
||||
fileKeyboard.cxStoreArray = 0;
|
||||
fileKeyboard.dpStoreArray = nullptr;
|
||||
u16cpy(str, u"baselayout(beep)");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_baselayout_valid[] = { UC_SENTINEL, CODE_IFSYSTEMSTORE, TSS_BASELAYOUT+1, 2, 1, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_baselayout_valid, tstr));
|
||||
|
||||
|
|
@ -925,7 +901,7 @@ TEST_F(CompilerTest, GetXStringImpl_type_b_test) {
|
|||
fileKeyboard.cxStoreArray = 0;
|
||||
fileKeyboard.dpStoreArray = nullptr;
|
||||
u16cpy(str, u"baselayout( beep)");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_baselayout_space_before_valid[] = { UC_SENTINEL, CODE_IFSYSTEMSTORE, TSS_BASELAYOUT+1, 2, 1, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_baselayout_space_before_valid, tstr));
|
||||
|
||||
|
|
@ -934,7 +910,7 @@ TEST_F(CompilerTest, GetXStringImpl_type_b_test) {
|
|||
fileKeyboard.cxStoreArray = 0;
|
||||
fileKeyboard.dpStoreArray = nullptr;
|
||||
u16cpy(str, u"baselayout(beep )");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_baselayout_space_after_valid[] = { UC_SENTINEL, CODE_IFSYSTEMSTORE, TSS_BASELAYOUT+1, 2, 1, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_baselayout_space_after_valid, tstr));
|
||||
}
|
||||
|
|
@ -953,56 +929,56 @@ TEST_F(CompilerTest, GetXStringImpl_type_i_test) {
|
|||
u16cpy(option[1].szName, u"b");
|
||||
u16cpy(option[2].szName, u"c");
|
||||
|
||||
// CERR_InvalidToken
|
||||
// KmnCompilerMessages::ERROR_InvalidToken
|
||||
u16cpy(str, u"ijk");
|
||||
EXPECT_EQ(CERR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// if, CERR_80FeatureOnly
|
||||
// if, KmnCompilerMessages::ERROR_80FeatureOnly
|
||||
fileKeyboard.version = VERSION_70;
|
||||
fileKeyboard.dwFlags = 0u;
|
||||
u16cpy(str, u"if");
|
||||
EXPECT_EQ(CERR_80FeatureOnly, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_80FeatureOnly, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
fileKeyboard.version = VERSION_80;
|
||||
|
||||
// if, CERR_InvalidInVirtualKeySection *** TODO ***
|
||||
// if, KmnCompilerMessages::ERROR_InvalidInVirtualKeySection *** TODO ***
|
||||
|
||||
// if, no close delimiter => NULL
|
||||
fileKeyboard.version = VERSION_80;
|
||||
u16cpy(str, u"if(");
|
||||
EXPECT_EQ(CERR_InvalidIf, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIf, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// if, empty delimiters => empty string
|
||||
fileKeyboard.version = VERSION_80;
|
||||
fileKeyboard.dwFlags = 0u;
|
||||
u16cpy(str, u"if()");
|
||||
EXPECT_EQ(CERR_InvalidIf, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIf, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// if, space in delimiters (see I11814, I11937, #11910, #11894, #11938)
|
||||
fileKeyboard.version = VERSION_80;
|
||||
fileKeyboard.dwFlags = 0u;
|
||||
u16cpy(str, u"if( )");
|
||||
EXPECT_EQ(CERR_InvalidIf, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIf, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// if, invalid
|
||||
fileKeyboard.version = VERSION_80;
|
||||
u16cpy(str, u"if(abc)");
|
||||
EXPECT_EQ(CERR_InvalidIf, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIf, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// if, CERR_90FeatureOnly_IfSystemStores
|
||||
// if, KmnCompilerMessages::ERROR_90FeatureOnly_IfSystemStores
|
||||
fileKeyboard.version = VERSION_80;
|
||||
u16cpy(str, u"if(&BITMAP=)");
|
||||
EXPECT_EQ(CERR_90FeatureOnly_IfSystemStores, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_90FeatureOnly_IfSystemStores, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// if, CERR_IfSystemStore_NotFound
|
||||
// if, KmnCompilerMessages::ERROR_IfSystemStore_NotFound
|
||||
fileKeyboard.version = VERSION_90;
|
||||
u16cpy(str, u"if(&abc=)");
|
||||
EXPECT_EQ(CERR_IfSystemStore_NotFound, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_IfSystemStore_NotFound, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// if, system store, equal, valid
|
||||
fileKeyboard.version = VERSION_90;
|
||||
fileKeyboard.cxStoreArray = 3u;
|
||||
u16cpy(str, u"if(&BITMAP=beep)");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_if_equal_system_store_valid[] = { UC_SENTINEL, CODE_IFSYSTEMSTORE, 2, 2, 4, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_if_equal_system_store_valid, tstr));
|
||||
|
||||
|
|
@ -1010,14 +986,14 @@ TEST_F(CompilerTest, GetXStringImpl_type_i_test) {
|
|||
fileKeyboard.version = VERSION_90;
|
||||
fileKeyboard.cxStoreArray = 3u;
|
||||
u16cpy(str, u"if(&BITMAP!=beep)");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_if_not_equal_system_store_valid[] = { UC_SENTINEL, CODE_IFSYSTEMSTORE, 2, 1, 4, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_if_not_equal_system_store_valid, tstr));
|
||||
|
||||
// if, option, CERR_StoreDoesNotExist
|
||||
// if, option, KmnCompilerMessages::ERROR_StoreDoesNotExist
|
||||
fileKeyboard.version = VERSION_80;
|
||||
u16cpy(str, u"if(d=beep)");
|
||||
EXPECT_EQ(CERR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// if, option, equal, valid
|
||||
fileKeyboard.version = VERSION_80;
|
||||
|
|
@ -1025,7 +1001,7 @@ TEST_F(CompilerTest, GetXStringImpl_type_i_test) {
|
|||
fileKeyboard.dpStoreArray = option;
|
||||
option[1].fIsOption = TRUE;
|
||||
u16cpy(str, u"if(b=beep)");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_if_option_valid[] = { UC_SENTINEL, CODE_IFOPT, 2, 2, 4, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_if_option_valid, tstr));
|
||||
|
||||
|
|
@ -1035,7 +1011,7 @@ TEST_F(CompilerTest, GetXStringImpl_type_i_test) {
|
|||
fileKeyboard.dpStoreArray = option;
|
||||
option[1].fIsOption = TRUE;
|
||||
u16cpy(str, u"if(b =beep)");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_if_option_space_before_assign_valid[] = { UC_SENTINEL, CODE_IFOPT, 2, 2, 4, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_if_option_space_before_assign_valid, tstr));
|
||||
|
||||
|
|
@ -1045,7 +1021,7 @@ TEST_F(CompilerTest, GetXStringImpl_type_i_test) {
|
|||
fileKeyboard.dpStoreArray = option;
|
||||
option[1].fIsOption = TRUE;
|
||||
u16cpy(str, u"if(b= beep)");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_if_option_space_before_rhs_valid[] = { UC_SENTINEL, CODE_IFOPT, 2, 2, 4, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_if_option_space_before_rhs_valid, tstr));
|
||||
|
||||
|
|
@ -1055,7 +1031,7 @@ TEST_F(CompilerTest, GetXStringImpl_type_i_test) {
|
|||
fileKeyboard.dpStoreArray = option;
|
||||
option[1].fIsOption = TRUE;
|
||||
u16cpy(str, u"if(b=beep )");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_if_option_space_after_rhs_valid[] = { UC_SENTINEL, CODE_IFOPT, 2, 2, 4, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_if_option_space_after_rhs_valid, tstr));
|
||||
|
||||
|
|
@ -1068,53 +1044,53 @@ TEST_F(CompilerTest, GetXStringImpl_type_i_test) {
|
|||
u16cpy(file_store[1].szName, u"b");
|
||||
u16cpy(file_store[2].szName, u"c");
|
||||
|
||||
// index, CERR_InvalidInVirtualKeySection *** TODO ***
|
||||
// index, KmnCompilerMessages::ERROR_InvalidInVirtualKeySection *** TODO ***
|
||||
|
||||
// index, no close delimiter => NULL
|
||||
u16cpy(str, u"index(");
|
||||
EXPECT_EQ(CERR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// index, empty delimiters => empty string
|
||||
u16cpy(str, u"index()");
|
||||
EXPECT_EQ(CERR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// index, space in delimiters (see I11814, I11937, #11910, #11894, #11938)
|
||||
u16cpy(str, u"index( )");
|
||||
EXPECT_EQ(CERR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// index, no comma or space
|
||||
u16cpy(str, u"index(b)");
|
||||
EXPECT_EQ(CERR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// index, no comma, space before store
|
||||
u16cpy(str, u"index( b)");
|
||||
EXPECT_EQ(CERR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// index, no comma, space after store
|
||||
u16cpy(str, u"index(b )");
|
||||
EXPECT_EQ(CERR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// index, CERR_StoreDoesNotExist
|
||||
// index, KmnCompilerMessages::ERROR_StoreDoesNotExist
|
||||
u16cpy(str, u"index(d,4)");
|
||||
EXPECT_EQ(CERR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// index, comma, offset=0
|
||||
fileKeyboard.cxStoreArray = 3u;
|
||||
fileKeyboard.dpStoreArray = file_store;
|
||||
u16cpy(str, u"index(b,0)");
|
||||
EXPECT_EQ(CERR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// index, comma, negative offset
|
||||
fileKeyboard.cxStoreArray = 3u;
|
||||
fileKeyboard.dpStoreArray = file_store;
|
||||
u16cpy(str, u"index(b,-1)");
|
||||
EXPECT_EQ(CERR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// index, comma, valid
|
||||
fileKeyboard.cxStoreArray = 3u;
|
||||
fileKeyboard.dpStoreArray = file_store;
|
||||
u16cpy(str, u"index(b,4)");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_index_comma_valid[] = { UC_SENTINEL, CODE_INDEX, 2, 4, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_index_comma_valid, tstr));
|
||||
|
||||
|
|
@ -1122,7 +1098,7 @@ TEST_F(CompilerTest, GetXStringImpl_type_i_test) {
|
|||
fileKeyboard.cxStoreArray = 3u;
|
||||
fileKeyboard.dpStoreArray = file_store;
|
||||
u16cpy(str, u"index( b,4)");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_index_initial_space_and_comma_valid[] = { UC_SENTINEL, CODE_INDEX, 2, 4, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_index_initial_space_and_comma_valid, tstr));
|
||||
|
||||
|
|
@ -1130,7 +1106,7 @@ TEST_F(CompilerTest, GetXStringImpl_type_i_test) {
|
|||
fileKeyboard.cxStoreArray = 3u;
|
||||
fileKeyboard.dpStoreArray = file_store;
|
||||
u16cpy(str, u"index(b, 4)");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_index_comma_and_space_valid[] = { UC_SENTINEL, CODE_INDEX, 2, 4, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_index_comma_and_space_valid, tstr));
|
||||
|
||||
|
|
@ -1138,7 +1114,7 @@ TEST_F(CompilerTest, GetXStringImpl_type_i_test) {
|
|||
u16cpy(str, u"index(b 4)");
|
||||
fileKeyboard.cxStoreArray = 3u;
|
||||
fileKeyboard.dpStoreArray = file_store;
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_index_space_valid[] = { UC_SENTINEL, CODE_INDEX, 2, 4, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_index_space_valid, tstr));
|
||||
|
||||
|
|
@ -1146,33 +1122,33 @@ TEST_F(CompilerTest, GetXStringImpl_type_i_test) {
|
|||
u16cpy(str, u"index(b,42)");
|
||||
fileKeyboard.cxStoreArray = 3u;
|
||||
fileKeyboard.dpStoreArray = file_store;
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_index_two_digit_valid[] = { UC_SENTINEL, CODE_INDEX, 2, 42, 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_index_two_digit_valid, tstr));
|
||||
|
||||
// index, comma, non-digit parameter, CERR_InvalidIndex
|
||||
// index, comma, non-digit parameter, KmnCompilerMessages::ERROR_InvalidIndex
|
||||
u16cpy(str, u"index(b,g)");
|
||||
fileKeyboard.cxStoreArray = 3u;
|
||||
fileKeyboard.dpStoreArray = file_store;
|
||||
EXPECT_EQ(CERR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// index, comma, no parameter, CERR_InvalidIndex
|
||||
// index, comma, no parameter, KmnCompilerMessages::ERROR_InvalidIndex
|
||||
u16cpy(str, u"index(b,)");
|
||||
fileKeyboard.cxStoreArray = 3u;
|
||||
fileKeyboard.dpStoreArray = file_store;
|
||||
EXPECT_EQ(CERR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// index, space and comma, no parameter, CERR_InvalidIndex
|
||||
// index, space and comma, no parameter, KmnCompilerMessages::ERROR_InvalidIndex
|
||||
u16cpy(str, u"index(b ,)");
|
||||
fileKeyboard.cxStoreArray = 3u;
|
||||
fileKeyboard.dpStoreArray = file_store;
|
||||
EXPECT_EQ(CERR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// index, comma, no parameter but space, CERR_InvalidIndex
|
||||
// index, comma, no parameter but space, KmnCompilerMessages::ERROR_InvalidIndex
|
||||
u16cpy(str, u"index(b, )");
|
||||
fileKeyboard.cxStoreArray = 3u;
|
||||
fileKeyboard.dpStoreArray = file_store;
|
||||
EXPECT_EQ(CERR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
}
|
||||
|
||||
// tests strings starting with 'o'
|
||||
|
|
@ -1190,61 +1166,61 @@ TEST_F(CompilerTest, GetXStringImpl_type_o_test) {
|
|||
u16cpy(file_store[1].szName, u"b");
|
||||
u16cpy(file_store[2].szName, u"c");
|
||||
|
||||
// CERR_InvalidToken
|
||||
// KmnCompilerMessages::ERROR_InvalidToken
|
||||
u16cpy(str, u"opq");
|
||||
EXPECT_EQ(CERR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// outs, CERR_OutsInVirtualKeySection *** TODO ***
|
||||
// outs, KmnCompilerMessages::ERROR_OutsInVirtualKeySection *** TODO ***
|
||||
|
||||
// outs, no close delimiter => NULL
|
||||
u16cpy(str, u"outs(");
|
||||
EXPECT_EQ(CERR_InvalidOuts, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidOuts, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// outs, empty delimiters => empty string
|
||||
u16cpy(str, u"outs()");
|
||||
EXPECT_EQ(CERR_InvalidOuts, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidOuts, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// outs, space in delimiters (see I11814, I11937, #11910, #11894, #11938)
|
||||
u16cpy(str, u"outs( )");
|
||||
EXPECT_EQ(CERR_InvalidOuts, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidOuts, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// outs, CERR_StoreDoesNotExist
|
||||
// outs, KmnCompilerMessages::ERROR_StoreDoesNotExist
|
||||
u16cpy(str, u"outs(d)");
|
||||
EXPECT_EQ(CERR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// outs, CERR_StoreDoesNotExist, space before store
|
||||
// outs, KmnCompilerMessages::ERROR_StoreDoesNotExist, space before store
|
||||
u16cpy(str, u"outs( d)");
|
||||
EXPECT_EQ(CERR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// outs, CERR_StoreDoesNotExist, space after store
|
||||
// outs, KmnCompilerMessages::ERROR_StoreDoesNotExist, space after store
|
||||
u16cpy(str, u"outs(d )");
|
||||
EXPECT_EQ(CERR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
|
||||
// outs, CERR_OutsTooLong
|
||||
// outs, KmnCompilerMessages::ERROR_OutsTooLong
|
||||
PKMX_WCHAR dpString = (PKMX_WCHAR)u"abc";
|
||||
file_store[1].dpString = dpString; // length 4 => max should be > 4, otherwise a CERR_OutsTooLong is emitted
|
||||
file_store[1].dpString = dpString; // length 4 => max should be > 4, otherwise a ERROR_OutsTooLong is emitted
|
||||
int max = u16len(dpString) + 1; // 4, including terminating '\0'
|
||||
u16cpy(str, u"outs(b)");
|
||||
EXPECT_EQ(CERR_OutsTooLong, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, max, 0, &newp, FALSE)); // max reduced to force error
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_OutsTooLong, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, max, 0, &newp, FALSE)); // max reduced to force error
|
||||
|
||||
// outs, valid
|
||||
file_store[1].dpString = (PKMX_WCHAR)u"abc";
|
||||
u16cpy(str, u"outs(b)");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_outs_valid[] = { 'a', 'b', 'c', 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_outs_valid, tstr));
|
||||
|
||||
// outs, space before store, valid
|
||||
file_store[1].dpString = (PKMX_WCHAR)u"abc";
|
||||
u16cpy(str, u"outs( b)");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_outs_space_before_valid[] = { 'a', 'b', 'c', 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_outs_space_before_valid, tstr));
|
||||
|
||||
// outs, space after store, valid (see I11937, #11938)
|
||||
file_store[1].dpString = (PKMX_WCHAR)u"abc";
|
||||
u16cpy(str, u"outs(b )");
|
||||
EXPECT_EQ(CERR_None, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
||||
const KMX_WCHAR tstr_outs_space_after_valid[] = { 'a', 'b', 'c', 0 };
|
||||
EXPECT_EQ(0, u16cmp(tstr_outs_space_after_valid, tstr));
|
||||
}
|
||||
|
|
@ -1262,25 +1238,25 @@ TEST_F(CompilerTest, GetXStringImpl_type_o_test) {
|
|||
// int GetGroupNum(PFILE_KEYBOARD fk, PKMX_WCHAR p)
|
||||
|
||||
TEST_F(CompilerTest, ProcessEthnologueStore_test) {
|
||||
EXPECT_EQ(CERR_None, ProcessEthnologueStore((PKMX_WCHAR)u"abc"));
|
||||
EXPECT_EQ(CWARN_PunctuationInEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u";abc"));
|
||||
EXPECT_EQ(CWARN_PunctuationInEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u",abc"));
|
||||
EXPECT_EQ(CERR_None, ProcessEthnologueStore((PKMX_WCHAR)u" abc"));
|
||||
EXPECT_EQ(CERR_InvalidEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"abc "));
|
||||
EXPECT_EQ(CERR_InvalidEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"abcd"));
|
||||
EXPECT_EQ(CERR_InvalidEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"ab"));
|
||||
EXPECT_EQ(CERR_InvalidEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"a"));
|
||||
EXPECT_EQ(CERR_InvalidEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"a2b"));
|
||||
EXPECT_EQ(CERR_None, ProcessEthnologueStore((PKMX_WCHAR)u"")); // needs correcting ... see #11955
|
||||
EXPECT_EQ(CERR_None, ProcessEthnologueStore((PKMX_WCHAR)u"abc def"));
|
||||
EXPECT_EQ(CERR_None, ProcessEthnologueStore((PKMX_WCHAR)u"abc def"));
|
||||
EXPECT_EQ(CWARN_PunctuationInEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"abc,def"));
|
||||
EXPECT_EQ(CWARN_PunctuationInEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"abc;def"));
|
||||
EXPECT_EQ(STATUS_Success, ProcessEthnologueStore((PKMX_WCHAR)u"abc"));
|
||||
EXPECT_EQ(KmnCompilerMessages::WARN_PunctuationInEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u";abc"));
|
||||
EXPECT_EQ(KmnCompilerMessages::WARN_PunctuationInEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u",abc"));
|
||||
EXPECT_EQ(STATUS_Success, ProcessEthnologueStore((PKMX_WCHAR)u" abc"));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"abc "));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"abcd"));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"ab"));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"a"));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"a2b"));
|
||||
EXPECT_EQ(STATUS_Success, ProcessEthnologueStore((PKMX_WCHAR)u"")); // needs correcting ... see #11955
|
||||
EXPECT_EQ(STATUS_Success, ProcessEthnologueStore((PKMX_WCHAR)u"abc def"));
|
||||
EXPECT_EQ(STATUS_Success, ProcessEthnologueStore((PKMX_WCHAR)u"abc def"));
|
||||
EXPECT_EQ(KmnCompilerMessages::WARN_PunctuationInEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"abc,def"));
|
||||
EXPECT_EQ(KmnCompilerMessages::WARN_PunctuationInEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"abc;def"));
|
||||
}
|
||||
|
||||
// KMX_DWORD ProcessHotKey(PKMX_WCHAR p, KMX_DWORD *hk)
|
||||
// void SetChecksum(PKMX_BYTE buf, PKMX_DWORD CheckSum, KMX_DWORD sz)
|
||||
// KMX_BOOL kmcmp::CheckStoreUsage(PFILE_KEYBOARD fk, int storeIndex, KMX_BOOL fIsStore, KMX_BOOL fIsOption, KMX_BOOL fIsCall)
|
||||
// void kmcmp::CheckStoreUsage(PFILE_KEYBOARD fk, int storeIndex, KMX_BOOL fIsStore, KMX_BOOL fIsOption, KMX_BOOL fIsCall)
|
||||
// KMX_DWORD WriteCompiledKeyboard(PFILE_KEYBOARD fk, KMX_BYTE**data, size_t& dataSize)
|
||||
// KMX_DWORD ReadLine(KMX_BYTE* infile, int sz, int& offset, PKMX_WCHAR wstr, KMX_BOOL PreProcess)
|
||||
|
||||
|
|
@ -1288,17 +1264,17 @@ TEST_F(CompilerTest, GetRHS_test) {
|
|||
KMX_WCHAR str[LINESIZE];
|
||||
KMX_WCHAR tstr[128];
|
||||
|
||||
// CERR_NoTokensFound, empty string
|
||||
// KmnCompilerMessages::ERROR_NoTokensFound, empty string
|
||||
u16cpy(str, u"");
|
||||
EXPECT_EQ(CERR_NoTokensFound, GetRHS(&fileKeyboard, str, tstr, 80, 0, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_NoTokensFound, GetRHS(&fileKeyboard, str, tstr, 80, 0, FALSE));
|
||||
|
||||
// CERR_NoTokensFound, no '>'
|
||||
// KmnCompilerMessages::ERROR_NoTokensFound, no '>'
|
||||
u16cpy(str, u"abc");
|
||||
EXPECT_EQ(CERR_NoTokensFound, GetRHS(&fileKeyboard, str, tstr, 80, 0, FALSE));
|
||||
EXPECT_EQ(KmnCompilerMessages::ERROR_NoTokensFound, GetRHS(&fileKeyboard, str, tstr, 80, 0, FALSE));
|
||||
|
||||
// CERR_None
|
||||
// STATUS_Success
|
||||
u16cpy(str, u"> nul c\n");
|
||||
EXPECT_EQ(CERR_None, GetRHS(&fileKeyboard, str, tstr, 80, 0, FALSE));
|
||||
EXPECT_EQ(STATUS_Success, GetRHS(&fileKeyboard, str, tstr, 80, 0, FALSE));
|
||||
}
|
||||
|
||||
// void safe_wcsncpy(PKMX_WCHAR out, PKMX_WCHAR in, int cbMax)
|
||||
|
|
@ -1326,7 +1302,7 @@ TEST_F(CompilerTest, isIntegerWstring_test) {
|
|||
}
|
||||
|
||||
// KMX_DWORD kmcmp::UTF32ToUTF16(int n, int *n1, int *n2)
|
||||
// KMX_DWORD BuildVKDictionary(PFILE_KEYBOARD fk)
|
||||
// KMX_BOOL BuildVKDictionary(PFILE_KEYBOARD fk)
|
||||
// int GetVKCode(PFILE_KEYBOARD fk, PKMX_WCHAR p)
|
||||
// int GetDeadKey(PFILE_KEYBOARD fk, PKMX_WCHAR p)
|
||||
// void kmcmp::RecordDeadkeyNames(PFILE_KEYBOARD fk)
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include "../../common/include/kmn_compiler_errors.h"
|
||||
#include "../../../../common/include/km_types.h"
|
||||
|
||||
const KMX_CHAR *GetCompilerErrorString(KMX_DWORD code);
|
||||
|
||||
class CompMsgTest : public testing::Test {
|
||||
protected:
|
||||
CompMsgTest() {}
|
||||
~CompMsgTest() override {}
|
||||
void SetUp() override {}
|
||||
void TearDown() override {}
|
||||
};
|
||||
|
||||
TEST_F(CompMsgTest, GetCompilerErrorString) {
|
||||
EXPECT_EQ(nullptr, GetCompilerErrorString(CERR_None));
|
||||
EXPECT_EQ(nullptr, GetCompilerErrorString(0x00004FFF)); // top of range ERROR
|
||||
EXPECT_EQ("Invalid 'layout' command", GetCompilerErrorString(CERR_InvalidLayoutLine));
|
||||
};
|
||||
|
|
@ -24,11 +24,6 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
#define CERR_FATAL 0x00008000
|
||||
#define CERR_ERROR 0x00004000
|
||||
#define CERR_WARNING 0x00002000
|
||||
#define CERR_HINT 0x00001000
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if(argc < 4) {
|
||||
|
|
@ -53,8 +48,7 @@ int main(int argc, char *argv[])
|
|||
if(*p == '\\') *p = '/';
|
||||
}
|
||||
|
||||
char first5[6] = "CERR_";
|
||||
char* pfirst5 = first5;
|
||||
const char* first5 = "CERR_";
|
||||
|
||||
KMCMP_COMPILER_RESULT result;
|
||||
KMCMP_COMPILER_OPTIONS options;
|
||||
|
|
@ -66,7 +60,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
if(kmcmp_CompileKeyboard(kmn_file, options, msgproc, loadfileProc, nullptr, result)) {
|
||||
char* testname = strrchr( (char*) kmn_file, '/') + 1;
|
||||
if(strncmp(testname, pfirst5, 5) == 0){
|
||||
if(strncmp(testname, first5, strlen(first5)) == 0){
|
||||
return __LINE__; // exit code: CERR_ in Name + no Error found
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +93,7 @@ int main(int argc, char *argv[])
|
|||
char* testname = strrchr( (char*) kmn_file, '/') + 1;
|
||||
|
||||
// Does testname contain CERR_ && contains '_' on pos 9 ? -> Get ErrorValue
|
||||
if ((strncmp(testname, pfirst5, 5) == 0) && (testname[9] == '_')) {
|
||||
if ((strncmp(testname, first5, strlen(first5)) == 0) && (testname[9] == '_')) {
|
||||
char* ErrNr = strchr(testname, '_') +1 ;
|
||||
std::istringstream(ErrNr) >> std::hex >> error_val;
|
||||
|
||||
|
|
|
|||
|
|
@ -168,17 +168,6 @@ gtestcompilertest = executable('gtest-compiler-test', 'gtest-compiler-test.cpp',
|
|||
|
||||
test('gtest-compiler-test', gtestcompilertest)
|
||||
|
||||
gtestcompmsgtest = executable('gtest-compmsg-test', 'gtest-compmsg-test.cpp',
|
||||
cpp_args: defns + flags,
|
||||
include_directories: inc,
|
||||
name_suffix: name_suffix,
|
||||
link_args: links + tests_links,
|
||||
objects: lib.extract_all_objects(),
|
||||
dependencies: [ icuuc_dep, gtest_dep, gmock_dep ],
|
||||
)
|
||||
|
||||
test('gtest-compmsg-test', gtestcompmsgtest)
|
||||
|
||||
gtestkmx_u16test = executable('gtest-kmx_u16-test', 'gtest-kmx_u16-test.cpp',
|
||||
cpp_args: defns + flags,
|
||||
include_directories: inc,
|
||||
|
|
|
|||
|
|
@ -7,53 +7,57 @@
|
|||
|
||||
std::vector<int> error_vec;
|
||||
|
||||
int msgproc(int line, uint32_t dwMsgCode, const char* szText, void* context) {
|
||||
error_vec.push_back(dwMsgCode);
|
||||
void msgproc(const KMCMP_COMPILER_RESULT_MESSAGE &message, void* context) {
|
||||
error_vec.push_back(message.errorCode);
|
||||
const char*t = "unknown";
|
||||
switch(dwMsgCode & 0xF000) {
|
||||
case CERR_HINT: t=" hint"; break;
|
||||
case CERR_WARNING: t="warning"; break;
|
||||
case CERR_ERROR: t=" error"; break;
|
||||
case CERR_FATAL: t=" fatal"; break;
|
||||
switch(message.errorCode & MESSAGE_SEVERITY_MASK) {
|
||||
case CompilerErrorSeverity::Hint: t=" SevHint"; break;
|
||||
case CompilerErrorSeverity::Warn: t=" SevWarn"; break;
|
||||
case CompilerErrorSeverity::Error: t="SevError"; break;
|
||||
case CompilerErrorSeverity::Fatal: t="SevFatal"; break;
|
||||
case CompilerErrorSeverity::Info: t=" SevInfo"; break;
|
||||
}
|
||||
printf("line %d %s %4.4x: %s\n", line, t, (unsigned int)dwMsgCode, szText);
|
||||
return 1;
|
||||
printf("[CompilerMessage] %s(%d): %s | 0x%3.3x (",
|
||||
message.filename.c_str(),
|
||||
message.lineNumber,
|
||||
t,
|
||||
(unsigned int)message.errorCode & MESSAGE_BASEERROR_MASK
|
||||
);
|
||||
for(auto it = message.parameters.begin(); it != message.parameters.end(); it++) {
|
||||
printf("%s'%s'", it == message.parameters.begin() ? "" : ", ", it->c_str());
|
||||
}
|
||||
printf(")\n");
|
||||
}
|
||||
|
||||
bool loadfileProc(const char* filename, const char* baseFilename, void* data, int* size, void* context) {
|
||||
const std::vector<uint8_t> loadfileProc(const std::string& filename, const std::string& baseFilename) {
|
||||
std::string resolvedFilename = filename;
|
||||
if(baseFilename && *baseFilename && IsRelativePath(filename)) {
|
||||
if(baseFilename.length() && IsRelativePath(filename.c_str())) {
|
||||
char* p;
|
||||
if ((p = strrchr_slash((char*)baseFilename)) != nullptr) {
|
||||
std::string basePath = std::string(baseFilename, (int)(p - baseFilename + 1));
|
||||
resolvedFilename = basePath;
|
||||
const char *base = baseFilename.c_str();
|
||||
if ((p = strrchr_slash((char*)base)) != nullptr) {
|
||||
resolvedFilename = std::string(baseFilename, 0, (int)(p - base + 1));
|
||||
resolvedFilename.append(filename);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> buf;
|
||||
|
||||
FILE* fp = Open_File(resolvedFilename.c_str(), "rb");
|
||||
if(!fp) {
|
||||
return false;
|
||||
return buf;
|
||||
}
|
||||
|
||||
if(!data) {
|
||||
// return size
|
||||
if(fseek(fp, 0, SEEK_END) != 0) {
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
*size = ftell(fp);
|
||||
if(*size == -1L) {
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// return data
|
||||
if(fread(data, 1, *size, fp) != (size_t)(*size)) {
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
if(fseek(fp, 0, SEEK_END) != 0) {
|
||||
fclose(fp);
|
||||
return buf;
|
||||
}
|
||||
size_t size = ftell(fp);
|
||||
|
||||
buf.resize(size);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
if(fread(buf.data(), 1, size, fp) != size) {
|
||||
buf.resize(0);
|
||||
}
|
||||
fclose(fp);
|
||||
return true;
|
||||
return buf;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
int msgproc(int line, uint32_t dwMsgCode, const char* szText, void* context);
|
||||
bool loadfileProc(const char* filename, const char* baseFilename, void* data, int* size, void* context);
|
||||
void msgproc(const KMCMP_COMPILER_RESULT_MESSAGE &message, void* context);
|
||||
const std::vector<uint8_t> loadfileProc(const std::string& filename, const std::string& baseFilename);
|
||||
|
||||
extern std::vector<int> error_vec;
|
||||
|
|
@ -22,4 +22,8 @@
|
|||
"include": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../../common/web/keyman-version" },
|
||||
{ "path": "../common/web/utils" },
|
||||
]
|
||||
}
|
||||
|
|
|
|||
8
docs/build/linux-ubuntu.md
vendored
8
docs/build/linux-ubuntu.md
vendored
|
|
@ -53,9 +53,13 @@ sudo mk-build-deps --install linux/debian/control
|
|||
|
||||
#### Node.js
|
||||
|
||||
Node.js v18 is required for Core builds, Web builds, and Developer command line tool builds and usage.
|
||||
Node.js is required for Core builds, Web builds, and Developer command line tool builds and usage.
|
||||
|
||||
Follow the instructions on the [NodeSource Distributions](https://github.com/nodesource/distributions#table-of-contents) page.
|
||||
Our recommended way to install node.js is with
|
||||
[nvm](https://github.com/nvm-sh/nvm). This makes it easy to switch between
|
||||
versions of node.js.
|
||||
|
||||
See [node.md](node.md) for more information.
|
||||
|
||||
#### Emscripten
|
||||
|
||||
|
|
|
|||
18
docs/build/macos.md
vendored
18
docs/build/macos.md
vendored
|
|
@ -77,10 +77,24 @@ PATH="$HOMEBREW_PREFIX/opt/coreutils/libexec/gnubin:$PATH"
|
|||
|
||||
## KeymanWeb Dependencies
|
||||
|
||||
* node.js 22+, emscripten 3.1.46 or later
|
||||
* node.js, emscripten 3.1.46 or later
|
||||
|
||||
### node.js
|
||||
|
||||
Our recommended way to install node.js is with
|
||||
[nvm](https://github.com/nvm-sh/nvm). This makes it easy to switch between
|
||||
versions of node.js.
|
||||
|
||||
Alternatively, you can install node.js with `brew`.
|
||||
|
||||
See [node.md](node.md) for more information.
|
||||
|
||||
### emscripten
|
||||
|
||||
To install emscripten:
|
||||
|
||||
```shell
|
||||
brew install node emscripten
|
||||
brew install emscripten
|
||||
```
|
||||
|
||||
Note: if you install emscripten with brew on macOS, only emscripten binaries are
|
||||
|
|
|
|||
71
docs/build/node.md
vendored
Normal file
71
docs/build/node.md
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# Node use in the Keyman project
|
||||
|
||||
For a given release cycle, we select and pin to a specific version of node.js,
|
||||
and try to use that throughout. The version in use can be found in
|
||||
`package.json/engines.node`.
|
||||
|
||||
If we encounter a blocking issue, we will upgrade to a known-good release, but
|
||||
this is exceptional.
|
||||
|
||||
Generally, as a developer, if you use the same major version as is found in
|
||||
package.json, you probably won't have significant issues. However, if you are
|
||||
switching between stable branches and alpha branches, you may find the required
|
||||
node version changes.
|
||||
|
||||
## Automatic node version selection
|
||||
|
||||
The Keyman build system can be configured to manage the node.js version for you.
|
||||
This does have several caveats, so it is not enabled by default.
|
||||
|
||||
When this is enabled, the build system will download the required node version
|
||||
and make it available on the PATH, and it will also stop the build if the node
|
||||
version mismatches. This happens in `build.sh configure` steps for any
|
||||
Typescript/Javascript project.
|
||||
|
||||
To enable automatic node version selection, add the variable `KEYMAN_USE_NVM=1`
|
||||
to your environment.
|
||||
|
||||
### Caveats
|
||||
|
||||
nvm (for macOS/Linux) and nvm-windows use somewhat different paradigms, so the
|
||||
caveats vary per platform.
|
||||
|
||||
### Caveats on macOS/Linux
|
||||
|
||||
On macOS/Linux, nvm is provided as a shell function that modifies the current
|
||||
environment PATH to make a specific node version available -- and so this does
|
||||
not affect unrelated processes.
|
||||
|
||||
1. You must use [nvm](https://github.com/nvm-sh/nvm) (macOS/Linux) to install
|
||||
and manage Node versions.
|
||||
2. The Keyman build environment will create a symlink at `~/.keyman/node`
|
||||
pointing to the version of node selected by nvm.
|
||||
3. You should add `$HOME/.keyman/node` to the front of your `PATH` variable,
|
||||
e.g. in `~/.bash_profile`. This means that the node version _will_ be set for
|
||||
the entire system, unlike with standard nvm usage. This allows build scripts
|
||||
to run without calling `nvm` for each invocation.
|
||||
|
||||
### Caveats on Windows
|
||||
|
||||
On Windows, nvm-windows creates a symlink to the current node version, and
|
||||
this symlink is what is on the system PATH, so it affects all processes on the
|
||||
system.
|
||||
|
||||
1. You must use [nvm-windows](https://github.com/coreybutler/nvm-windows) to
|
||||
install and manage Node versions.
|
||||
2. By default on Windows, creating symlinks requires elevation. While
|
||||
nvm-windows does this for you, it can be irritating to have a build script
|
||||
pause for elevation. In Local Group Policy Editor, `Computer Configuration`,
|
||||
`Windows Settings`, `Security Settings`, `Local Policies`,
|
||||
`User Rights Assignment`, you can add your username to the
|
||||
`Create symbolic links` policy (and reboot), to avoid elevation.
|
||||
|
||||
## Build Agents
|
||||
|
||||
The Keyman build agents use nvm as described above, including the caveats.
|
||||
|
||||
## Implementation
|
||||
|
||||
See `_select_node_version_with_nvm()` in
|
||||
`/resources/build/shellHelperFunctions.sh`, and
|
||||
`/resources/build/_builder_nvm.sh`.
|
||||
24
docs/build/windows.md
vendored
24
docs/build/windows.md
vendored
|
|
@ -206,7 +206,15 @@ installed emsdk (most likely %LocalAppData%\emsdk\upstream\emscripten)
|
|||
**Environment variables**:
|
||||
* `EMSCRIPTEN_BASE`: `<your-emsdk-path>\upstream\emscripten`
|
||||
|
||||
After installing emscripten, you'll need to install node.js and openjdk:
|
||||
After installing emscripten, you'll need to install node.js and openjdk.
|
||||
|
||||
#### node.js
|
||||
|
||||
Our recommended way to install node.js is to use
|
||||
[nvm-windows](https://github.com/coreybutler/nvm-windows). This makes it
|
||||
easy to switch between versions of node.js.
|
||||
|
||||
Alternatively, use Powershell + Chocolatey to install node.js:
|
||||
|
||||
```ps1
|
||||
# Elevated PowerShell
|
||||
|
|
@ -214,9 +222,23 @@ After installing emscripten, you'll need to install node.js and openjdk:
|
|||
# for *much* faster download, hide progress bar (PowerShell/PowerShell#2138)
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
choco install nodejs
|
||||
```
|
||||
|
||||
See [node.md](node.md) for more information.
|
||||
|
||||
#### openjdk
|
||||
|
||||
Use Powershell + Chocolatey to install OpenJDK:
|
||||
|
||||
```ps1
|
||||
# Elevated PowerShell
|
||||
|
||||
# for *much* faster download, hide progress bar (PowerShell/PowerShell#2138)
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
choco install openjdk
|
||||
```
|
||||
|
||||
|
||||
### Windows Platform Dependencies
|
||||
|
||||
**Projects**:
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ https://help.keyman.com/developer/engine/android/latest-version/
|
|||
| KEYMAN_MIN_VERSION_CPP | 17 |
|
||||
| KEYMAN_MIN_VERSION_EMSCRIPTEN | 3.1.44 |
|
||||
| KEYMAN_MIN_VERSION_MESON | 1.0.0 |
|
||||
| KEYMAN_MIN_VERSION_NODE_MAJOR | 18 |
|
||||
| KEYMAN_MIN_VERSION_NODE_MAJOR | 20 |
|
||||
| KEYMAN_MIN_VERSION_NPM | 10.5.1 |
|
||||
| KEYMAN_MIN_VERSION_VISUAL_STUDIO | 2019 |
|
||||
| KEYMAN_VERSION_JAVA | 11 |
|
||||
|
|
|
|||
2
package-lock.json
generated
2
package-lock.json
generated
|
|
@ -66,7 +66,7 @@
|
|||
"typescript": "^5.4.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.x"
|
||||
"node": "20.16.0"
|
||||
}
|
||||
},
|
||||
"common/models/templates": {
|
||||
|
|
|
|||
|
|
@ -63,6 +63,6 @@
|
|||
"@keymanapp/ldml-keyboard-constants": "file:core/include/ldml"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.x"
|
||||
"node": "20.16.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
51
resources/build/_builder_nvm.sh
Executable file
51
resources/build/_builder_nvm.sh
Executable file
|
|
@ -0,0 +1,51 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# See also /docs/build/node.md
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "This script is called by shellHelperFunctions.sh, _select_node_version_with_nvm()"
|
||||
echo "during build.sh configure steps. It is not intended to be called directly, as it"
|
||||
echo "is a wrapper for nvm."
|
||||
exit 99
|
||||
fi
|
||||
|
||||
REQUIRED_NODE_VERSION="$1"
|
||||
|
||||
if [[ -z "${NVM_DIR+x}" ]]; then
|
||||
export NVM_DIR="$HOME/.nvm"
|
||||
fi
|
||||
|
||||
#
|
||||
# nvm on macos and linux is a shell function. `source`ing it into our scripts is
|
||||
# fragile because it uses some of the same variable names that we do. We have
|
||||
# marked our most precious variables as `readonly`, which breaks nvm re-use of
|
||||
# them also! Safest way to work around this is to load nvm in a child process
|
||||
# and run it there. Downside is then of course we don't get the `PATH` changes
|
||||
# that nvm does for us, so we have to do it ourselves back in the caller,
|
||||
# `_select_node_version_with_nvm()`.
|
||||
#
|
||||
# Note: the readonly attribute for variables is not inherited by child
|
||||
# processes.
|
||||
#
|
||||
# See also https://github.com/nvm-sh/nvm/issues/3257 (among others)
|
||||
#
|
||||
|
||||
type -t nvm >/dev/null || {
|
||||
source "$NVM_DIR/nvm.sh"
|
||||
type -t nvm >/dev/null || {
|
||||
echo "Failed to find nvm"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
nvm install "$REQUIRED_NODE_VERSION"
|
||||
nvm use "$REQUIRED_NODE_VERSION"
|
||||
|
||||
# Beware the hardcoded path below -- it should already be in the system PATH
|
||||
|
||||
mkdir -p "$HOME/.keyman"
|
||||
rm -f "$HOME/.keyman/node"
|
||||
ln -s "$NVM_BIN" "$HOME/.keyman/node"
|
||||
|
|
@ -6,27 +6,29 @@
|
|||
# Linux/macOS: jq
|
||||
#
|
||||
|
||||
## START STANDARD BUILD SCRIPT INCLUDE
|
||||
# adjust relative paths as necessary
|
||||
JQ_THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
|
||||
# . "${THIS_SCRIPT%/*}/build-utils.sh"
|
||||
## END STANDARD BUILD SCRIPT INCLUDE
|
||||
if [[ -z "${JQ+x}" ]]; then
|
||||
## START STANDARD BUILD SCRIPT INCLUDE
|
||||
# adjust relative paths as necessary
|
||||
JQ_THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
|
||||
# . "${THIS_SCRIPT%/*}/build-utils.sh"
|
||||
## END STANDARD BUILD SCRIPT INCLUDE
|
||||
|
||||
case "${OSTYPE}" in
|
||||
"cygwin")
|
||||
JQ=$(dirname "$JQ_THIS_SCRIPT")/jq-win64.exe
|
||||
;;
|
||||
"msys")
|
||||
JQ=$(dirname "$JQ_THIS_SCRIPT")/jq-win64.exe
|
||||
;;
|
||||
*)
|
||||
JQ=jq
|
||||
;;
|
||||
esac
|
||||
case "${OSTYPE}" in
|
||||
"cygwin")
|
||||
JQ=$(dirname "$JQ_THIS_SCRIPT")/jq-win64.exe
|
||||
;;
|
||||
"msys")
|
||||
JQ=$(dirname "$JQ_THIS_SCRIPT")/jq-win64.exe
|
||||
;;
|
||||
*)
|
||||
JQ=jq
|
||||
;;
|
||||
esac
|
||||
|
||||
readonly JQ
|
||||
readonly JQ
|
||||
|
||||
# JQ with inplace file replacement
|
||||
function jqi() {
|
||||
cat <<< "$($JQ -c "$1" < "$2")" > "$2"
|
||||
}
|
||||
# JQ with inplace file replacement
|
||||
function jqi() {
|
||||
cat <<< "$($JQ -c "$1" < "$2")" > "$2"
|
||||
}
|
||||
fi
|
||||
|
|
@ -13,7 +13,7 @@ KEYMAN_MIN_TARGET_VERSION_UBUNTU=20.04 # Ubuntu 20.04 Focal
|
|||
KEYMAN_MIN_TARGET_VERSION_CHROME=95.0 # Final version that runs on Android 5.0
|
||||
|
||||
# Dependency versions
|
||||
KEYMAN_MIN_VERSION_NODE_MAJOR=18
|
||||
KEYMAN_MIN_VERSION_NODE_MAJOR=20 # node version source of truth is /package.json:/engines/node
|
||||
KEYMAN_MIN_VERSION_NPM=10.5.1 # 10.5.0 has bug, discussed in #10350
|
||||
KEYMAN_MIN_VERSION_EMSCRIPTEN=3.1.44 # Warning: 3.1.45 is bad (#9529); newer versions work
|
||||
KEYMAN_MAX_VERSION_EMSCRIPTEN=3.1.58 # See #9529
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# We only import JQ if not already defined; jq is used by
|
||||
# _select_node_version_with_nvm()
|
||||
|
||||
if [[ -z "${JQ+x}" ]]; then
|
||||
if [[ "$BUILDER_OS" == win ]]; then
|
||||
. "$KEYMAN_ROOT/resources/build/jq.inc.sh"
|
||||
else
|
||||
JQ=jq
|
||||
fi
|
||||
fi
|
||||
|
||||
# Allows for a quick macOS check for those scripts requiring a macOS environment.
|
||||
verify_on_mac() {
|
||||
if [[ "${OSTYPE}" != "darwin"* ]]; then
|
||||
|
|
@ -243,6 +254,13 @@ verify_npm_setup() {
|
|||
fi
|
||||
builder_set_module_has_been_built /external/npm-ci
|
||||
|
||||
# If we are on CI environment, automatically select a node version with nvm
|
||||
# Also, a developer can set KEYMAN_USE_NVM variable to get this behaviour
|
||||
# automatically too (see /docs/build/node.md)
|
||||
if [[ "$VERSION_ENVIRONMENT" != local || ! -z "${KEYMAN_USE_NVM+x}" ]]; then
|
||||
_select_node_version_with_nvm
|
||||
fi
|
||||
|
||||
# Check if Node.JS/npm is installed.
|
||||
type npm >/dev/null ||\
|
||||
builder_die "Build environment setup error detected! Please ensure Node.js is installed!"
|
||||
|
|
@ -252,4 +270,29 @@ verify_npm_setup() {
|
|||
try_multiple_times npm ci
|
||||
|
||||
popd > /dev/null
|
||||
}
|
||||
}
|
||||
|
||||
# Use nvm to select a node version according to package.json
|
||||
# see /docs/build/node.md
|
||||
_select_node_version_with_nvm() {
|
||||
local REQUIRED_NODE_VERSION="$("$JQ" -r '.engines.node' "$KEYMAN_ROOT/package.json")"
|
||||
|
||||
if [[ $BUILDER_OS != win ]]; then
|
||||
# launch nvm in a sub process, see _builder_nvm.sh for details
|
||||
"$KEYMAN_ROOT/resources/build/_builder_nvm.sh" "$REQUIRED_NODE_VERSION"
|
||||
else
|
||||
nvm install "$REQUIRED_NODE_VERSION"
|
||||
nvm use "$REQUIRED_NODE_VERSION"
|
||||
fi
|
||||
|
||||
# Now, check that the node version is correct, on all systems
|
||||
|
||||
# Note: On windows, `nvm use` and `nvm install` always return success.
|
||||
# https://github.com/coreybutler/nvm-windows/issues/738
|
||||
|
||||
# note the 'v' prefix that node emits (and npm doesn't!)
|
||||
local CURRENT_NODE_VERSION="$(node --version)"
|
||||
if [[ "$CURRENT_NODE_VERSION" != "v$REQUIRED_NODE_VERSION" ]]; then
|
||||
builder_die "Attempted to select node.js version $REQUIRED_NODE_VERSION but found $CURRENT_NODE_VERSION instead"
|
||||
fi
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue