diff --git a/developer/src/common/include/kmn_compiler_errors.h b/developer/src/common/include/kmn_compiler_errors.h index 4955df5e73..f2410f03b0 100644 --- a/developer/src/common/include/kmn_compiler_errors.h +++ b/developer/src/common/include/kmn_compiler_errors.h @@ -90,16 +90,16 @@ namespace KmnCompilerMessages { ERROR_ZeroLengthString = SevError | 0x017, ERROR_TooManyIndexToKeyRefs = SevError | 0x018, ERROR_UnterminatedString = SevError | 0x019, - ERROR_StringInVirtualKeySection = SevError | 0x01A, - ERROR_AnyInVirtualKeySection = SevError | 0x01B, +// ERROR_StringInVirtualKeySection = SevError | 0x01A, no longer used, see #12612 +// ERROR_AnyInVirtualKeySection = SevError | 0x01B, no longer used, see #12612 ERROR_InvalidAny = SevError | 0x01C, ERROR_StoreDoesNotExist = SevError | 0x01D, - ERROR_BeepInVirtualKeySection = SevError | 0x01E, - ERROR_IndexInVirtualKeySection = SevError | 0x01F, +// ERROR_BeepInVirtualKeySection = SevError | 0x01E, no longer used, see #12612 +// ERROR_IndexInVirtualKeySection = SevError | 0x01F, no longer used, see #12612 ERROR_InvalidIndex = SevError | 0x020, - ERROR_OutsInVirtualKeySection = SevError | 0x021, +// ERROR_OutsInVirtualKeySection = SevError | 0x021, no longer used, see #12612 ERROR_InvalidOuts = SevError | 0x022, - ERROR_ContextInVirtualKeySection = SevError | 0x024, +// ERROR_ContextInVirtualKeySection = SevError | 0x024, no longer used, see #12612 ERROR_InvalidUse = SevError | 0x025, ERROR_GroupDoesNotExist = SevError | 0x026, ERROR_VirtualKeyNotAllowedHere = SevError | 0x027, @@ -117,7 +117,7 @@ namespace KmnCompilerMessages { ERROR_ReservedCharacter = SevError | 0x033, ERROR_InvalidCharacter = SevError | 0x034, ERROR_InvalidCall = SevError | 0x035, - ERROR_CallInVirtualKeySection = SevError | 0x036, +// ERROR_CallInVirtualKeySection = SevError | 0x036, no longer used, see #12612 ERROR_CodeInvalidInKeyStore = SevError | 0x037, ERROR_CannotLoadIncludeFile = SevError | 0x038, @@ -138,7 +138,7 @@ namespace KmnCompilerMessages { ERROR_70FeatureOnly = SevError | 0x046, ERROR_80FeatureOnly = SevError | 0x047, - ERROR_InvalidInVirtualKeySection = SevError | 0x048, +// ERROR_InvalidInVirtualKeySection = SevError | 0x048, no longer used, see #12612 ERROR_InvalidIf = SevError | 0x049, ERROR_InvalidReset = SevError | 0x04A, ERROR_InvalidSet = SevError | 0x04B, diff --git a/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts b/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts index f4b8693812..2e9ec068f3 100644 --- a/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts +++ b/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts @@ -274,11 +274,11 @@ export class KmnCompilerMessages { static ERROR_UnterminatedString = SevError | 0x019; static Error_UnterminatedString = () => m(this.ERROR_UnterminatedString, `Unterminated string in line`); - static ERROR_StringInVirtualKeySection = SevError | 0x01A; - static Error_StringInVirtualKeySection = () => m(this.ERROR_StringInVirtualKeySection, `extend string illegal in virtual key section`); + // static ERROR_StringInVirtualKeySection = SevError | 0x01A; // no longer used, see #12612 + // static Error_StringInVirtualKeySection = () => m(this.ERROR_StringInVirtualKeySection, `extend string illegal in virtual key section`); - static ERROR_AnyInVirtualKeySection = SevError | 0x01B; - static Error_AnyInVirtualKeySection = () => m(this.ERROR_AnyInVirtualKeySection, `'any' command is illegal in virtual key section`); + // static ERROR_AnyInVirtualKeySection = SevError | 0x01B; // no longer used, see #12612 + // static Error_AnyInVirtualKeySection = () => m(this.ERROR_AnyInVirtualKeySection, `'any' command is illegal in virtual key section`); static ERROR_InvalidAny = SevError | 0x01C; static Error_InvalidAny = () => m(this.ERROR_InvalidAny, `Invalid 'any' command`); @@ -286,23 +286,23 @@ export class KmnCompilerMessages { static ERROR_StoreDoesNotExist = SevError | 0x01D; static Error_StoreDoesNotExist = () => m(this.ERROR_StoreDoesNotExist, `Store referenced does not exist`); - static ERROR_BeepInVirtualKeySection = SevError | 0x01E; - static Error_BeepInVirtualKeySection = () => m(this.ERROR_BeepInVirtualKeySection, `'beep' command is illegal in virtual key section`); + // static ERROR_BeepInVirtualKeySection = SevError | 0x01E; // no longer used, see #12612 + // static Error_BeepInVirtualKeySection = () => m(this.ERROR_BeepInVirtualKeySection, `'beep' command is illegal in virtual key section`); - static ERROR_IndexInVirtualKeySection = SevError | 0x01F; - static Error_IndexInVirtualKeySection = () => m(this.ERROR_IndexInVirtualKeySection, `'index' command is illegal in virtual key section`); + // static ERROR_IndexInVirtualKeySection = SevError | 0x01F; // no longer used, see #12612 + // static Error_IndexInVirtualKeySection = () => m(this.ERROR_IndexInVirtualKeySection, `'index' command is illegal in virtual key section`); static ERROR_InvalidIndex = SevError | 0x020; static Error_InvalidIndex = () => m(this.ERROR_InvalidIndex, `Invalid 'index' command`); - static ERROR_OutsInVirtualKeySection = SevError | 0x021; - static Error_OutsInVirtualKeySection = () => m(this.ERROR_OutsInVirtualKeySection, `'outs' command is illegal in virtual key section`); + // static ERROR_OutsInVirtualKeySection = SevError | 0x021; // no longer used, see #12612 + // static Error_OutsInVirtualKeySection = () => m(this.ERROR_OutsInVirtualKeySection, `'outs' command is illegal in virtual key section`); static ERROR_InvalidOuts = SevError | 0x022; static Error_InvalidOuts = () => m(this.ERROR_InvalidOuts, `Invalid 'outs' command`); - static ERROR_ContextInVirtualKeySection = SevError | 0x024; - static Error_ContextInVirtualKeySection = () => m(this.ERROR_ContextInVirtualKeySection, `'context' command is illegal in virtual key section`); + // static ERROR_ContextInVirtualKeySection = SevError | 0x024; // no longer used, see #12612 + // static Error_ContextInVirtualKeySection = () => m(this.ERROR_ContextInVirtualKeySection, `'context' command is illegal in virtual key section`); static ERROR_InvalidUse = SevError | 0x025; static Error_InvalidUse = () => m(this.ERROR_InvalidUse, `Invalid 'use' command`); @@ -355,8 +355,8 @@ export class KmnCompilerMessages { static ERROR_InvalidCall = SevError | 0x035; static Error_InvalidCall = () => m(this.ERROR_InvalidCall, `The 'call' command is invalid`); - static ERROR_CallInVirtualKeySection = SevError | 0x036; - static Error_CallInVirtualKeySection = () => m(this.ERROR_CallInVirtualKeySection, `'call' command is illegal in virtual key section`); + // static ERROR_CallInVirtualKeySection = SevError | 0x036; // no longer used, see #12612 + // static Error_CallInVirtualKeySection = () => m(this.ERROR_CallInVirtualKeySection, `'call' command is illegal in virtual key section`); static ERROR_CodeInvalidInKeyStore = SevError | 0x037; static Error_CodeInvalidInKeyStore = () => m(this.ERROR_CodeInvalidInKeyStore, `The command is invalid inside a store that is used in a key part of the rule`); @@ -401,8 +401,8 @@ export class KmnCompilerMessages { static ERROR_80FeatureOnly = SevError | 0x047; static Error_80FeatureOnly = () => m(this.ERROR_80FeatureOnly, `This feature requires store(version) '8.0' or higher`); - static ERROR_InvalidInVirtualKeySection = SevError | 0x048; - static Error_InvalidInVirtualKeySection = () => m(this.ERROR_InvalidInVirtualKeySection, `This statement is not valid in a virtual key section`); + // static ERROR_InvalidInVirtualKeySection = SevError | 0x048; // no longer used, see #12612 + // static Error_InvalidInVirtualKeySection = () => m(this.ERROR_InvalidInVirtualKeySection, `This statement is not valid in a virtual key section`); static ERROR_InvalidIf = SevError | 0x049; static Error_InvalidIf = () => m(this.ERROR_InvalidIf, `The if() statement is not valid`); diff --git a/developer/src/kmcmplib/src/Compiler.cpp b/developer/src/kmcmplib/src/Compiler.cpp index e878e4690e..ff4ab560a5 100644 --- a/developer/src/kmcmplib/src/Compiler.cpp +++ b/developer/src/kmcmplib/src/Compiler.cpp @@ -2031,10 +2031,8 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX ) { KMX_DWORD err; PKMX_WCHAR p = str, q, r; - int type, mx = 0, n, n1, n2, tokenFound = FALSE, z, sFlag = 0, j; + int type, mx = 0, n, n1, n2, tokenFound = FALSE, z, j; KMX_DWORD i; - KMX_BOOL finished = FALSE; - KMX_BOOL wsRequired = FALSE; KMX_WCHAR c; *tstr = 0; @@ -2127,7 +2125,6 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX q = (PKMX_WCHAR) u16chr(p + 1, '\"'); if (!q) return KmnCompilerMessages::ERROR_UnterminatedString; if ((int)(q - p) - 1 + mx > max) return KmnCompilerMessages::ERROR_ExtendedStringTooLong; - if (sFlag) return KmnCompilerMessages::ERROR_StringInVirtualKeySection; u16ncat(tstr, p + 1, (int)(q - p) - 1); // I3481 mx += (int)(q - p) - 1; tstr[mx] = 0; @@ -2137,7 +2134,6 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX q = (PKMX_WCHAR) u16chr(p + 1, '\''); if (!q) return KmnCompilerMessages::ERROR_UnterminatedString; if ((int)(q - p) - 1 + mx > max) return KmnCompilerMessages::ERROR_ExtendedStringTooLong; - if (sFlag) return KmnCompilerMessages::ERROR_StringInVirtualKeySection; u16ncat(tstr, p + 1, (int)(q - p) - 1); // I3481 mx += (int)(q - p) - 1; tstr[mx] = 0; @@ -2145,7 +2141,6 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX continue; case 3: if (u16nicmp(p, u"any", 3) != 0) return KmnCompilerMessages::ERROR_InvalidToken; - if (sFlag) return KmnCompilerMessages::ERROR_AnyInVirtualKeySection; p += 3; q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); if (!q || !*q) return KmnCompilerMessages::ERROR_InvalidAny; @@ -2167,7 +2162,6 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX case 4: if (u16nicmp(p, u"beep", 4) == 0) { - if (sFlag) return KmnCompilerMessages::ERROR_BeepInVirtualKeySection; p += 4; tstr[mx++] = UC_SENTINEL; tstr[mx++] = CODE_BEEP; @@ -2178,7 +2172,6 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX if(!VerifyKeyboardVersion(fk, VERSION_90)) { return KmnCompilerMessages::ERROR_90FeatureOnly_IfSystemStores; } - if (sFlag) return KmnCompilerMessages::ERROR_InvalidInVirtualKeySection; p += 10; q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); if (!q || !*q) return KmnCompilerMessages::ERROR_InvalidToken; @@ -2195,7 +2188,6 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX if(!VerifyKeyboardVersion(fk, VERSION_80)) { return KmnCompilerMessages::ERROR_80FeatureOnly; } - if (sFlag) return KmnCompilerMessages::ERROR_InvalidInVirtualKeySection; p += 2; q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); if (!q || !*q) return KmnCompilerMessages::ERROR_InvalidIf; @@ -2206,7 +2198,6 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX else { if (u16nicmp(p, u"index", 5) != 0) return KmnCompilerMessages::ERROR_InvalidToken; - if (sFlag) return KmnCompilerMessages::ERROR_IndexInVirtualKeySection; p += 5; q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); @@ -2241,7 +2232,6 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX continue; case 6: if (u16nicmp(p, u"outs", 4) != 0) return KmnCompilerMessages::ERROR_InvalidToken; - if (sFlag) return KmnCompilerMessages::ERROR_OutsInVirtualKeySection; p += 4; q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); if (!q || !*q) return KmnCompilerMessages::ERROR_InvalidOuts; @@ -2267,7 +2257,6 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX if (iswspace(*(p + 1))) break; // is a comment -- pre-stripped - so why this test? if (u16nicmp(p, u"context", 7) == 0) { - if (sFlag) return KmnCompilerMessages::ERROR_ContextInVirtualKeySection; p += 7; q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); @@ -2303,7 +2292,6 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX if(!VerifyKeyboardVersion(fk, VERSION_501)) { return KmnCompilerMessages::ERROR_501FeatureOnly_Call; } - if (sFlag) return KmnCompilerMessages::ERROR_CallInVirtualKeySection; p += 4; q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); if (!q || !*q) return KmnCompilerMessages::ERROR_InvalidCall; @@ -2333,7 +2321,6 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX if(!VerifyKeyboardVersion(fk, VERSION_70)) { return KmnCompilerMessages::ERROR_70FeatureOnly; } - if (sFlag) return KmnCompilerMessages::ERROR_AnyInVirtualKeySection; p += 6; q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); if (!q || !*q) return KmnCompilerMessages::ERROR_InvalidAny; @@ -2391,7 +2378,6 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX if(!VerifyKeyboardVersion(fk, VERSION_80)) { return KmnCompilerMessages::ERROR_80FeatureOnly; } - if (sFlag) return KmnCompilerMessages::ERROR_InvalidInVirtualKeySection; p += 5; q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); if (!q || !*q) return KmnCompilerMessages::ERROR_InvalidReset; @@ -2413,167 +2399,171 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX } continue; case 11: - p++; sFlag = ISVIRTUALKEY /* 0 */; finished = FALSE; wsRequired = FALSE; - - //printf("--EXTENDEDSTRING--\n"); - - do { - if (wsRequired && !iswspace(*p)) - return KmnCompilerMessages::ERROR_InvalidToken; // #12307 + int sFlag = ISVIRTUALKEY /* 0 */; + KMX_BOOL finished = FALSE; + KMX_BOOL wsRequired = FALSE; - while (iswspace(*p)) p++; + p++; - switch (towupper(*p)) + //printf("--EXTENDEDSTRING--\n"); + + do { - case 'N': - if (u16nicmp(p, u"NCAPS", 5) == 0) - sFlag |= NOTCAPITALFLAG, wsRequired = TRUE, p += 5; - else finished = TRUE; - break; - case 'L': - if (u16nicmp(p, u"LALT", 4) == 0) - sFlag |= LALTFLAG, wsRequired = TRUE, p += 4; - else if (u16nicmp(p, u"LCTRL", 5) == 0) - sFlag |= LCTRLFLAG, wsRequired = TRUE, p += 5; - else finished = TRUE; - break; - case 'R': - if (u16nicmp(p, u"RALT", 4) == 0) - sFlag |= RALTFLAG, wsRequired = TRUE, p += 4; - else if (u16nicmp(p, u"RCTRL", 5) == 0) - sFlag |= RCTRLFLAG, wsRequired = TRUE, p += 5; - else finished = TRUE; - break; - case 'A': - if (u16nicmp(p, u"ALT", 3) == 0) - sFlag |= K_ALTFLAG, wsRequired = TRUE, p += 3; - else finished = TRUE; - break; - case 'C': - if (u16nicmp(p, u"CTRL", 4) == 0) - sFlag |= K_CTRLFLAG, wsRequired = TRUE, p += 4; - else if (u16nicmp(p, u"CAPS", 4) == 0) - sFlag |= CAPITALFLAG, wsRequired = TRUE, p += 4; - else finished = TRUE; - break; - case 'S': - if (u16nicmp(p, u"SHIFT", 5) == 0) - sFlag |= K_SHIFTFLAG, wsRequired = TRUE, p += 5; - else finished = TRUE; - break; - default: - finished = TRUE; - break; - } - } while (!finished); + if (wsRequired && !iswspace(*p)) + return KmnCompilerMessages::ERROR_InvalidToken; // #12307 - if ((sFlag & (LCTRLFLAG | LALTFLAG)) && (sFlag & (RCTRLFLAG | RALTFLAG))) { - ReportCompilerMessage(KmnCompilerMessages::WARN_MixingLeftAndRightModifiers); - } + while (iswspace(*p)) p++; - // If we use chiral modifiers, or we use state keys, and we target web in - // the keyboard, and we don't manually specify a keyboard version, bump - // the minimum version to 10.0. This makes an assumption that if we are - // using these features in a keyboard and it has no version specified, - // that we want to use the features in the web target platform, even if - // there are platform() rules excluding this possibility. In that (rare) - // situation, the keyboard developer should simply specify the &version to - // be 9.0 or whatever to avoid this behaviour. - if (sFlag & (LCTRLFLAG | LALTFLAG | RCTRLFLAG | RALTFLAG | CAPITALFLAG | NOTCAPITALFLAG | NUMLOCKFLAG | NOTNUMLOCKFLAG | SCROLLFLAG | NOTSCROLLFLAG) && - kmcmp::CompileTarget == CKF_KEYMANWEB && - fk->dwFlags & KF_AUTOMATICVERSION) { - if(!VerifyKeyboardVersion(fk, VERSION_100)) { - return STATUS_Success; - } - } - //printf("sFlag: %x\n", sFlag); + switch (towupper(*p)) + { + case 'N': + if (u16nicmp(p, u"NCAPS", 5) == 0) + sFlag |= NOTCAPITALFLAG, wsRequired = TRUE, p += 5; + else finished = TRUE; + break; + case 'L': + if (u16nicmp(p, u"LALT", 4) == 0) + sFlag |= LALTFLAG, wsRequired = TRUE, p += 4; + else if (u16nicmp(p, u"LCTRL", 5) == 0) + sFlag |= LCTRLFLAG, wsRequired = TRUE, p += 5; + else finished = TRUE; + break; + case 'R': + if (u16nicmp(p, u"RALT", 4) == 0) + sFlag |= RALTFLAG, wsRequired = TRUE, p += 4; + else if (u16nicmp(p, u"RCTRL", 5) == 0) + sFlag |= RCTRLFLAG, wsRequired = TRUE, p += 5; + else finished = TRUE; + break; + case 'A': + if (u16nicmp(p, u"ALT", 3) == 0) + sFlag |= K_ALTFLAG, wsRequired = TRUE, p += 3; + else finished = TRUE; + break; + case 'C': + if (u16nicmp(p, u"CTRL", 4) == 0) + sFlag |= K_CTRLFLAG, wsRequired = TRUE, p += 4; + else if (u16nicmp(p, u"CAPS", 4) == 0) + sFlag |= CAPITALFLAG, wsRequired = TRUE, p += 4; + else finished = TRUE; + break; + case 'S': + if (u16nicmp(p, u"SHIFT", 5) == 0) + sFlag |= K_SHIFTFLAG, wsRequired = TRUE, p += 5; + else finished = TRUE; + break; + default: + finished = TRUE; + break; + } + } while (!finished); - tstr[mx++] = UC_SENTINEL; - tstr[mx++] = CODE_EXTENDED; - tstr[mx++] = sFlag; - - q = p; - - if (*q == ']') { - return KmnCompilerMessages::ERROR_InvalidToken; // I3137 - key portion of VK is missing e.g. "[CTRL ALT]", this generates invalid kmx file that can crash Keyman or compiler later on // I3511 - } - - if (*q == '\'' || *q == '"') { - if(!VerifyKeyboardVersion(fk, VERSION_60)) { - return KmnCompilerMessages::ERROR_60FeatureOnly_VirtualCharKey; + if ((sFlag & (LCTRLFLAG | LALTFLAG)) && (sFlag & (RCTRLFLAG | RALTFLAG))) { + ReportCompilerMessage(KmnCompilerMessages::WARN_MixingLeftAndRightModifiers); } - if (!kmcmp::FMnemonicLayout) { - ReportCompilerMessage(KmnCompilerMessages::WARN_VirtualCharKeyWithPositionalLayout); + // If we use chiral modifiers, or we use state keys, and we target web in + // the keyboard, and we don't manually specify a keyboard version, bump + // the minimum version to 10.0. This makes an assumption that if we are + // using these features in a keyboard and it has no version specified, + // that we want to use the features in the web target platform, even if + // there are platform() rules excluding this possibility. In that (rare) + // situation, the keyboard developer should simply specify the &version to + // be 9.0 or whatever to avoid this behaviour. + if (sFlag & (LCTRLFLAG | LALTFLAG | RCTRLFLAG | RALTFLAG | CAPITALFLAG | NOTCAPITALFLAG | NUMLOCKFLAG | NOTNUMLOCKFLAG | SCROLLFLAG | NOTSCROLLFLAG) && + kmcmp::CompileTarget == CKF_KEYMANWEB && + fk->dwFlags & KF_AUTOMATICVERSION) { + if(!VerifyKeyboardVersion(fk, VERSION_100)) { + return STATUS_Success; + } + } + //printf("sFlag: %x\n", sFlag); + + tstr[mx++] = UC_SENTINEL; + tstr[mx++] = CODE_EXTENDED; + tstr[mx++] = sFlag; + + q = p; + + if (*q == ']') { + return KmnCompilerMessages::ERROR_InvalidToken; // I3137 - key portion of VK is missing e.g. "[CTRL ALT]", this generates invalid kmx file that can crash Keyman or compiler later on // I3511 } - KMX_WCHAR chQuote = *q; + if (*q == '\'' || *q == '"') { + if(!VerifyKeyboardVersion(fk, VERSION_60)) { + return KmnCompilerMessages::ERROR_60FeatureOnly_VirtualCharKey; + } - q++; // skip quote - if (*q == chQuote || *q == '\n' || *q == 0) - return KmnCompilerMessages::ERROR_InvalidToken; + if (!kmcmp::FMnemonicLayout) { + ReportCompilerMessage(KmnCompilerMessages::WARN_VirtualCharKeyWithPositionalLayout); + } - tstr[mx - 1] |= VIRTUALCHARKEY; - tstr[mx++] = *q; + KMX_WCHAR chQuote = *q; - q++; // skip key - if (*q != chQuote) - return KmnCompilerMessages::ERROR_InvalidToken; - q++; // skip quote - } else { - for (j = 0; !iswspace(*q) && *q != ']' && *q != 0; q++, j++); + q++; // skip quote + if (*q == chQuote || *q == '\n' || *q == 0) + return KmnCompilerMessages::ERROR_InvalidToken; - if (*q == 0) - return KmnCompilerMessages::ERROR_InvalidToken; + tstr[mx - 1] |= VIRTUALCHARKEY; + tstr[mx++] = *q; - KMX_WCHAR vkname[SZMAX_VKDICTIONARYNAME]; // I3438 + q++; // skip key + if (*q != chQuote) + return KmnCompilerMessages::ERROR_InvalidToken; + q++; // skip quote + } else { + for (j = 0; !iswspace(*q) && *q != ']' && *q != 0; q++, j++); - if (j >= SZMAX_VKDICTIONARYNAME) - return KmnCompilerMessages::ERROR_InvalidToken; + if (*q == 0) + return KmnCompilerMessages::ERROR_InvalidToken; - u16ncpy(vkname, p, j); // I3481 - vkname[j] = 0; + KMX_WCHAR vkname[SZMAX_VKDICTIONARYNAME]; // I3438 - if (u16icmp(vkname, u"K_NPENTER") == 0) - i = 5; // I649 - K_NPENTER hack - else { - for (i = 0; i <= VK__MAX; i++) { - if (u16icmp(vkname, VKeyNames[i]) == 0 || u16icmp(vkname, VKeyISO9995Names[i]) == 0) - break; + if (j >= SZMAX_VKDICTIONARYNAME) + return KmnCompilerMessages::ERROR_InvalidToken; + + u16ncpy(vkname, p, j); // I3481 + vkname[j] = 0; + + if (u16icmp(vkname, u"K_NPENTER") == 0) + i = 5; // I649 - K_NPENTER hack + else { + for (i = 0; i <= VK__MAX; i++) { + if (u16icmp(vkname, VKeyNames[i]) == 0 || u16icmp(vkname, VKeyISO9995Names[i]) == 0) + break; + } + } + + if (i == VK__MAX + 1) { + if(!VerifyKeyboardVersion(fk, VERSION_90)) { + return KmnCompilerMessages::ERROR_InvalidToken; + } + + i = GetVKCode(fk, vkname); // I3438 + if (i == 0) + return KmnCompilerMessages::ERROR_InvalidToken; + } + + tstr[mx++] = (int)i; + + if (kmcmp::FMnemonicLayout && (i <= VK__MAX) && VKeyMayBeVCKey[i]) { + ReportCompilerMessage(KmnCompilerMessages::WARN_VirtualKeyWithMnemonicLayout); // I3438 } } - if (i == VK__MAX + 1) { - if(!VerifyKeyboardVersion(fk, VERSION_90)) { - return KmnCompilerMessages::ERROR_InvalidToken; - } + while (iswspace(*q)) q++; - i = GetVKCode(fk, vkname); // I3438 - if (i == 0) - return KmnCompilerMessages::ERROR_InvalidToken; - } + if (*q != ']') + return KmnCompilerMessages::ERROR_InvalidToken; - tstr[mx++] = (int)i; + tstr[mx++] = UC_SENTINEL_EXTENDEDEND; + tstr[mx] = 0; + //printf("--EXTENDEDEND--\n"); - if (kmcmp::FMnemonicLayout && (i <= VK__MAX) && VKeyMayBeVCKey[i]) { - ReportCompilerMessage(KmnCompilerMessages::WARN_VirtualKeyWithMnemonicLayout); // I3438 - } + p = q + 1; } - while (iswspace(*q)) q++; - - if (*q != ']') - return KmnCompilerMessages::ERROR_InvalidToken; - - tstr[mx++] = UC_SENTINEL_EXTENDEDEND; - tstr[mx] = 0; - //printf("--EXTENDEDEND--\n"); - - p = q + 1; - - sFlag = 0; - continue; case 14: if (u16nicmp(p, u"set", 3) == 0) @@ -2649,7 +2639,6 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX if(!VerifyKeyboardVersion(fk, VERSION_90)) { return KmnCompilerMessages::ERROR_90FeatureOnly_IfSystemStores; } - if (sFlag) return KmnCompilerMessages::ERROR_InvalidInVirtualKeySection; p += 8; q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); if (!q || !*q) return KmnCompilerMessages::ERROR_InvalidToken; @@ -2661,7 +2650,6 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX if(!VerifyKeyboardVersion(fk, VERSION_90)) { return KmnCompilerMessages::ERROR_90FeatureOnly_SetSystemStores; } - if (sFlag) return KmnCompilerMessages::ERROR_InvalidInVirtualKeySection; p += 5; q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); if (!q || !*q) return KmnCompilerMessages::ERROR_InvalidToken; @@ -2670,7 +2658,6 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX continue; case 19: // #2241 if (*(p + 1) != '.') return KmnCompilerMessages::ERROR_InvalidToken; - if (sFlag) return KmnCompilerMessages::ERROR_InvalidInVirtualKeySection; p += 2; err = process_expansion(fk, p, tstr, &mx, max); if (err != STATUS_Success) return err; diff --git a/developer/src/kmcmplib/tests/gtest-compiler-test.cpp b/developer/src/kmcmplib/tests/gtest-compiler-test.cpp index ba66e31365..ca8f40f6d8 100644 --- a/developer/src/kmcmplib/tests/gtest-compiler-test.cpp +++ b/developer/src/kmcmplib/tests/gtest-compiler-test.cpp @@ -786,8 +786,6 @@ TEST_F(CompilerTest, GetXStringImpl_type_double_quote_test) { // KmnCompilerMessages::ERROR_ExtendedStringTooLong u16cpy(str, u"\"abc\""); EXPECT_EQ(KmnCompilerMessages::ERROR_ExtendedStringTooLong, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 2, 0, &newp, FALSE)); // max reduced to force error - - // KmnCompilerMessages::ERROR_StringInVirtualKeySection *** TODO *** } // tests strings starting with single quote @@ -809,8 +807,6 @@ TEST_F(CompilerTest, GetXStringImpl_type_single_quote_test) { // KmnCompilerMessages::ERROR_ExtendedStringTooLong u16cpy(str, u"\'abc\'"); EXPECT_EQ(KmnCompilerMessages::ERROR_ExtendedStringTooLong, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 2, 0, &newp, FALSE)); // max reduced to force error - - // KmnCompilerMessages::ERROR_StringInVirtualKeySection *** TODO *** } // tests strings starting with 'a' @@ -825,8 +821,6 @@ TEST_F(CompilerTest, GetXStringImpl_type_a_test) { u16cpy(str, u"abc"); EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); - // KmnCompilerMessages::ERROR_AnyInVirtualKeySection *** TODO *** - // KmnCompilerMessages::ERROR_InvalidAny, no delimiters => NULL u16cpy(str, u"any"); EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidAny, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); @@ -892,8 +886,6 @@ TEST_F(CompilerTest, GetXStringImpl_type_b_test) { u16cpy(str, u"bcd"); EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); - // beep, KmnCompilerMessages::ERROR_BeepInVirtualKeySection *** TODO *** - // beep, valid u16cpy(str, u"beep"); EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); @@ -907,8 +899,6 @@ TEST_F(CompilerTest, GetXStringImpl_type_b_test) { EXPECT_EQ(KmnCompilerMessages::ERROR_90FeatureOnly_IfSystemStores, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); fileKeyboard.version = VERSION_90; - // baselayout, KmnCompilerMessages::ERROR_InvalidInVirtualKeySection *** TODO *** - // baselayout, no delimiters => NULL fileKeyboard.version = VERSION_90; u16cpy(str, u"baselayout"); @@ -980,8 +970,6 @@ TEST_F(CompilerTest, GetXStringImpl_type_i_test) { EXPECT_EQ(KmnCompilerMessages::ERROR_80FeatureOnly, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); fileKeyboard.version = VERSION_80; - // if, KmnCompilerMessages::ERROR_InvalidInVirtualKeySection *** TODO *** - // if, no delimiters => NULL fileKeyboard.version = VERSION_80; u16cpy(str, u"if"); @@ -1077,8 +1065,6 @@ TEST_F(CompilerTest, GetXStringImpl_type_i_test) { initFileStoreArray(fileKeyboard, {u"a", u"b", u"c"}); fileKeyboard.dpStoreArray[1].fIsStore = TRUE; - // index, KmnCompilerMessages::ERROR_InvalidInVirtualKeySection *** TODO *** - // index, no delimiters => NULL u16cpy(str, u"index"); EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); @@ -1190,8 +1176,6 @@ TEST_F(CompilerTest, GetXStringImpl_type_o_test) { u16cpy(str, u"opq"); EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); - // outs, KmnCompilerMessages::ERROR_OutsInVirtualKeySection *** TODO *** - // outs, no delimiters => NULL u16cpy(str, u"outs"); EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidOuts, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); @@ -1266,8 +1250,6 @@ TEST_F(CompilerTest, GetXStringImpl_type_c_test) { u16cpy(str, u"cde"); EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); - // context, KmnCompilerMessages::ERROR_ContextInVirtualKeySection *** TODO *** - // context, no offset, valid fileKeyboard.version = VERSION_60; u16cpy(str, u"context"); @@ -1352,8 +1334,6 @@ TEST_F(CompilerTest, GetXStringImpl_type_c_test) { u16cpy(str, u"call"); EXPECT_EQ(KmnCompilerMessages::ERROR_501FeatureOnly_Call, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); - // call, KmnCompilerMessages::ERROR_CallInVirtualKeySection *** TODO *** - // call, no delimiters => NULL fileKeyboard.version = VERSION_501; u16cpy(str, u"call"); @@ -1443,8 +1423,6 @@ TEST_F(CompilerTest, GetXStringImpl_type_n_test) { u16cpy(str, u"notany"); EXPECT_EQ(KmnCompilerMessages::ERROR_70FeatureOnly, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); - // notany, KmnCompilerMessages::ERROR_AnyInVirtualKeySection *** TODO *** - // notany, no delimiters => NULL fileKeyboard.version = VERSION_70; u16cpy(str, u"notany"); @@ -1629,8 +1607,6 @@ TEST_F(CompilerTest, GetXStringImpl_type_r_test) { u16cpy(str, u"reset"); EXPECT_EQ(KmnCompilerMessages::ERROR_80FeatureOnly, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE)); - // reset, KmnCompilerMessages::ERROR_InvalidInVirtualKeySection *** TODO *** - // reset, no delimiters => NULL fileKeyboard.version = VERSION_80; u16cpy(str, u"reset");