mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-12 20:05:34 +00:00
refactor(developer): move fs for kmn load to caller
This commit is contained in:
parent
f36a908d94
commit
71df68cd13
9 changed files with 194 additions and 160 deletions
|
|
@ -36,7 +36,7 @@ struct KMCMP_COMPILER_RESULT {
|
|||
};
|
||||
|
||||
// TODO: parameters in UTF-8
|
||||
typedef int (*kmcmp_CompilerMessageProc)(int line, uint32_t dwMsgCode, char* szText, void* context);
|
||||
typedef int (*kmcmp_CompilerMessageProc)(int line, uint32_t dwMsgCode, const char* szText, void* context);
|
||||
|
||||
// parameters in UTF-8
|
||||
// TODO typical usage:
|
||||
|
|
@ -48,7 +48,7 @@ typedef int (*kmcmp_CompilerMessageProc)(int line, uint32_t dwMsgCode, char* szT
|
|||
// delete[] buf;
|
||||
// return error;
|
||||
// }
|
||||
typedef bool (*kmcmp_LoadFileProc)(char* loadFilename, char* baseFilename, void* buffer, int* bufferSize);
|
||||
typedef bool (*kmcmp_LoadFileProc)(const char* loadFilename, const char* baseFilename, void* buffer, int* bufferSize, void* context);
|
||||
|
||||
// Parameters in UTF-8
|
||||
EXTERN bool kmcmp_CompileKeyboard(
|
||||
|
|
|
|||
|
|
@ -94,6 +94,9 @@
|
|||
#include "CasedKeys.h"
|
||||
#include <vector>
|
||||
#include <xstring.h>
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
|
||||
#include "CheckFilenameConsistency.h"
|
||||
#include "UnreachableRules.h"
|
||||
#include "CheckForDuplicates.h"
|
||||
|
|
@ -230,6 +233,8 @@ enum LinePrefixType { lptNone, lptKeymanAndKeymanWeb, lptKeymanWebOnly, lptKeyma
|
|||
/* Compile target */
|
||||
|
||||
kmcmp_CompilerMessageProc msgproc = NULL;
|
||||
kmcmp_LoadFileProc loadfileproc = NULL;
|
||||
|
||||
void* msgprocContext = NULL;
|
||||
|
||||
int kmcmp::currentLine = 0;
|
||||
|
|
@ -3068,7 +3073,7 @@ KMX_DWORD WriteCompiledKeyboard(PFILE_KEYBOARD fk, KMX_BYTE**data, size_t& dataS
|
|||
return CERR_None;
|
||||
}
|
||||
|
||||
KMX_DWORD ReadLine(FILE* fp_in , PKMX_WCHAR wstr, KMX_BOOL PreProcess)
|
||||
KMX_DWORD ReadLine(KMX_BYTE* infile, int sz, int& offset, PKMX_WCHAR wstr, KMX_BOOL PreProcess)
|
||||
{
|
||||
KMX_DWORD len;
|
||||
PKMX_WCHAR p;
|
||||
|
|
@ -3076,21 +3081,26 @@ KMX_DWORD ReadLine(FILE* fp_in , PKMX_WCHAR wstr, KMX_BOOL PreProcess)
|
|||
KMX_DWORD n;
|
||||
KMX_WCHAR currentQuotes = 0;
|
||||
KMX_WCHAR str[LINESIZE + 3];
|
||||
len = (KMX_DWORD)fread( str , 1 ,LINESIZE * 2,fp_in);
|
||||
if (ferror(fp_in) ) return CERR_CannotReadInfile;
|
||||
|
||||
if(offset >= sz) {
|
||||
return CERR_EndOfFile;
|
||||
}
|
||||
|
||||
len = offset + LINESIZE*2 > sz ? sz-offset : LINESIZE*2;
|
||||
memcpy(str, infile+offset, len);
|
||||
offset += len;
|
||||
len /= 2;
|
||||
str[len] = 0; auto cur = ftell(fp_in);
|
||||
fseek(fp_in, 0, SEEK_END);
|
||||
auto fsize = ftell(fp_in);
|
||||
fseek(fp_in, cur, SEEK_SET);
|
||||
str[len] = 0;
|
||||
|
||||
if (cur == fsize)
|
||||
if(offset == sz) {
|
||||
// \r\n is still added here even though Linux doesn`t use \r.
|
||||
// This is to ensure to still have a working windows-only-version
|
||||
u16ncat(str, u"\r\n", _countof(str)); // I3481 // Always a "\r\n" to the EOF, avoids funny bugs
|
||||
}
|
||||
|
||||
// \r\n is still added here even though Linux doesn`t use \r.
|
||||
// This is to ensure to still have a working windows-only-version
|
||||
u16ncat(str, u"\r\n", _countof(str)); // I3481 // Always a "\r\n" to the EOF, avoids funny bugs
|
||||
|
||||
if (len == 0) return CERR_EndOfFile;
|
||||
if (len == 0) {
|
||||
return CERR_EndOfFile;
|
||||
}
|
||||
|
||||
// neccessary to add this block for using on non-windows platforms (removes all \r for platforms that use \n instead of \r\n)
|
||||
for (p = str, n = 0; n < len; n++, p++) {
|
||||
|
|
@ -3172,9 +3182,13 @@ KMX_DWORD ReadLine(FILE* fp_in , PKMX_WCHAR wstr, KMX_BOOL PreProcess)
|
|||
return (PreProcess ? CERR_None : CERR_LineTooLong);
|
||||
}
|
||||
|
||||
if (*p == L'\n') kmcmp::currentLine++;
|
||||
kmcmp::currentLine++;
|
||||
|
||||
fseek(fp_in, -(int)(len * 2 - (int)(p - str) * 2 - 2), SEEK_CUR);
|
||||
offset -= (int)(len * 2 - (int)(p - str) * 2 - 2);
|
||||
if(offset >= sz) {
|
||||
// If we've appended a \n, we can go past EOF
|
||||
offset = sz;
|
||||
}
|
||||
|
||||
p--;
|
||||
while (p >= str && iswspace(*p)) p--;
|
||||
|
|
@ -3427,81 +3441,39 @@ KMX_BOOL kmcmp::IsValidCallStore(PFILE_STORE fs)
|
|||
return i == 1;
|
||||
}
|
||||
|
||||
FILE* CreateTempFile()
|
||||
{
|
||||
return tmpfile();
|
||||
}
|
||||
|
||||
///////////////////
|
||||
|
||||
FILE* UTF16TempFromUTF8(FILE* fp_in , KMX_BOOL hasPreamble)
|
||||
{
|
||||
FILE *fp_out = CreateTempFile();
|
||||
if(fp_out == NULL) // I3228 // I3510
|
||||
{
|
||||
fclose(fp_in);
|
||||
return NULL; //return INVALID_HANDLE_VALUE; _S2 can I exchange that?
|
||||
bool hasPreamble(std::u16string result) {
|
||||
return result.size() > 0 && result[0] == 0xFEFF;
|
||||
}
|
||||
|
||||
bool UTF16TempFromUTF8(KMX_BYTE* infile, int sz, KMX_BYTE** tempfile, int *sz16) {
|
||||
if(sz == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PKMX_BYTE buf, p;
|
||||
PKMX_WCHAR outbuf, poutbuf;
|
||||
KMX_DWORD len;
|
||||
KMX_DWORD len2;
|
||||
KMX_WCHAR prolog = 0xFEFF;
|
||||
fwrite(&prolog,2, 1, fp_out);
|
||||
std::u16string result;
|
||||
|
||||
fseek(fp_in, 0, SEEK_END);
|
||||
len = (KMX_DWORD)ftell(fp_in);
|
||||
fseek(fp_in, 0, SEEK_SET);
|
||||
if (hasPreamble) {
|
||||
fseek( fp_in,3,SEEK_SET); // Cut off UTF-8 marker
|
||||
len -= 3;
|
||||
try {
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter;
|
||||
result = converter.from_bytes((char*)infile, (char*)infile+sz-1);
|
||||
} catch(std::range_error e) {
|
||||
std::wstring_convert<std::codecvt_utf16<char16_t>, char16_t> converter;
|
||||
result = converter.from_bytes((char*)infile, (char*)infile+sz-1);
|
||||
}
|
||||
|
||||
buf = new KMX_BYTE[len + 1]; // null terminated
|
||||
outbuf = new KMX_WCHAR[len + 1];
|
||||
if(hasPreamble(result)) {
|
||||
*sz16 = result.size() * 2 - 1;
|
||||
*tempfile = new KMX_BYTE[*sz16];
|
||||
memcpy(*tempfile, result.c_str() + 2, *sz16);
|
||||
|
||||
len2= (KMX_DWORD)fread(buf,1,len,fp_in);
|
||||
if (len2) {
|
||||
buf[len2] = 0;
|
||||
p = buf;
|
||||
poutbuf = outbuf;
|
||||
if (hasPreamble) {
|
||||
// We have a preamble, so we attempt to read as UTF-8 and allow conversion errors to be filtered. This is not great for a
|
||||
// compiler but matches existing behaviour -- in future versions we may not do lenient conversion.
|
||||
ConvertUTF8toUTF16(&p, &buf[len2], (UTF16 **)&poutbuf, (const UTF16 *)&outbuf[len], lenientConversion);
|
||||
fwrite(outbuf, (KMX_DWORD)(poutbuf - outbuf) * 2 , 1, fp_out);
|
||||
}
|
||||
else {
|
||||
// No preamble, so we attempt to read as strict UTF-8 and fall back to ANSI if that fails
|
||||
ConversionResult cr = ConvertUTF8toUTF16(&p, &buf[len2], (UTF16 **)&poutbuf, (const UTF16 *)&outbuf[len], strictConversion);
|
||||
if (cr == sourceIllegal) {
|
||||
// Not a valid UTF-8 file, so fall back to ANSI
|
||||
// AddCompileError(CHINT_NonUnicodeFile);
|
||||
// note, while this message is defined, for now we will not emit it
|
||||
// because we don't support HINT/INFO messages yet and we don't want
|
||||
// this to cause a blocking compile at this stage
|
||||
// do strtowstr only when no invalid characters are found
|
||||
if( p==0){
|
||||
poutbuf = strtowstr((PKMX_STR)buf);
|
||||
fwrite(poutbuf, (KMX_DWORD)u16len(poutbuf) * 2 , 1, fp_out);
|
||||
delete[] poutbuf;
|
||||
}
|
||||
else
|
||||
AddCompileError(CERR_InvalidCharacter);
|
||||
}
|
||||
|
||||
else {
|
||||
fwrite(outbuf, (KMX_DWORD)(poutbuf - outbuf) * 2 , 1, fp_out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose( fp_in);
|
||||
delete[] buf;
|
||||
delete[] outbuf;
|
||||
fseek( fp_out,2,SEEK_SET);
|
||||
return fp_out;
|
||||
*sz16 = result.size() * 2;
|
||||
*tempfile = new KMX_BYTE[*sz16];
|
||||
memcpy(*tempfile, result.c_str(), *sz16);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PFILE_STORE FindSystemStore(PFILE_KEYBOARD fk, KMX_DWORD dwSystemID)
|
||||
|
|
|
|||
|
|
@ -11,14 +11,14 @@
|
|||
#include "../../../../common/windows/cpp/include/ConvertUTF.h"
|
||||
#include "../../../../common/windows/cpp/include/keymanversion.h"
|
||||
|
||||
bool CompileKeyboardHandle(FILE* fp_in, PFILE_KEYBOARD fk);
|
||||
bool CompileKeyboardHandle(KMX_BYTE* infile, int sz, PFILE_KEYBOARD fk);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
|
||||
/*
|
||||
WASM interface for compiler message callback
|
||||
*/
|
||||
EM_JS(int, wasm_msgproc, (int line, int msgcode, char* text, char* context), {
|
||||
EM_JS(int, wasm_msgproc, (int line, int msgcode, const char* text, char* context), {
|
||||
const proc = globalThis[UTF8ToString(context)];
|
||||
if(!proc || typeof proc != 'function') {
|
||||
console.log(`[${line}: ${msgcode}: ${UTF8ToString(text)}]`);
|
||||
|
|
@ -28,7 +28,21 @@ EM_JS(int, wasm_msgproc, (int line, int msgcode, char* text, char* context), {
|
|||
}
|
||||
});
|
||||
|
||||
int wasm_CompilerMessageProc(int line, uint32_t dwMsgCode, char* szText, void* context) {
|
||||
EM_JS(bool, wasm_loadfileproc, (const char* filename, const char* baseFilename, void* buffer, int* bufferSize, char* context), {
|
||||
const proc = globalThis[UTF8ToString(context)];
|
||||
if(!proc || typeof proc != 'function') {
|
||||
return 0;
|
||||
} else {
|
||||
return proc(UTF8ToString(filename), UTF8ToString(baseFilename), buffer, bufferSize);
|
||||
}
|
||||
});
|
||||
|
||||
bool wasm_LoadFileProc(const char* filename, const char* baseFilename, void* buffer, int* bufferSize, void* context) {
|
||||
char* msgProc = static_cast<char*>(context);
|
||||
return wasm_loadfileproc(filename, baseFilename, buffer, bufferSize, msgProc);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
@ -61,7 +75,7 @@ WASM_COMPILER_RESULT kmcmp_wasm_compile(std::string pszInfile, const KMCMP_COMPI
|
|||
pszInfile.c_str(),
|
||||
options,
|
||||
wasm_CompilerMessageProc,
|
||||
nullptr, //wasm_LoadFileProc,
|
||||
wasm_LoadFileProc,
|
||||
intf.messageCallback.c_str(),
|
||||
kr
|
||||
);
|
||||
|
|
@ -116,8 +130,6 @@ EXTERN bool kmcmp_CompileKeyboard(
|
|||
KMCMP_COMPILER_RESULT& result
|
||||
) {
|
||||
|
||||
FILE* fp_in = NULL;
|
||||
KMX_CHAR str[260];
|
||||
FILE_KEYBOARD fk;
|
||||
|
||||
kmcmp::FSaveDebug = options.saveDebug; // I3681
|
||||
|
|
@ -126,7 +138,7 @@ EXTERN bool kmcmp_CompileKeyboard(
|
|||
kmcmp::FShouldAddCompilerVersion = options.shouldAddCompilerVersion;
|
||||
kmcmp::CompileTarget = options.target;
|
||||
|
||||
if (!messageProc || !pszInfile) { // TODO: add loadFileProc
|
||||
if (!messageProc || !loadFileProc || !pszInfile) {
|
||||
AddCompileError(CERR_BadCallParams);
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -142,43 +154,58 @@ EXTERN bool kmcmp_CompileKeyboard(
|
|||
}
|
||||
|
||||
msgproc = messageProc;
|
||||
//TODO: loadfileproc = loadFileProc;
|
||||
loadfileproc = loadFileProc;
|
||||
msgprocContext = (void*)procContext;
|
||||
kmcmp::currentLine = 0;
|
||||
kmcmp::nErrors = 0;
|
||||
|
||||
fp_in = Open_File(pszInfile, "rb");
|
||||
|
||||
if (fp_in == NULL) {
|
||||
int sz;
|
||||
if(!loadFileProc(pszInfile, "", nullptr, &sz, msgprocContext)) {
|
||||
AddCompileError(CERR_InfileNotExist);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Transfer the file to a memory stream for processing UTF-8 or ANSI to UTF-16?
|
||||
// What about really large files? Transfer to a temp file...
|
||||
if (!fread(str, 1, 3, fp_in)) {
|
||||
fclose(fp_in);
|
||||
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);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fseek(fp_in, 0, SEEK_SET);
|
||||
if (str[0] == UTF8Sig[0] && str[1] == UTF8Sig[1] && str[2] == UTF8Sig[2])
|
||||
fp_in = UTF16TempFromUTF8(fp_in, TRUE);
|
||||
else if (str[0] == UTF16Sig[0] && str[1] == UTF16Sig[1])
|
||||
fseek(fp_in, 2, SEEK_SET);
|
||||
else
|
||||
fp_in = UTF16TempFromUTF8(fp_in, FALSE);
|
||||
if (fp_in == NULL) {
|
||||
AddCompileError(CERR_CannotCreateTempfile);
|
||||
KMX_BYTE* infile = new KMX_BYTE[sz];
|
||||
if(!infile) {
|
||||
AddCompileError(CERR_CannotAllocateMemory);
|
||||
return FALSE;
|
||||
}
|
||||
if(!loadFileProc(pszInfile, "", infile, &sz, msgprocContext)) {
|
||||
delete[] infile;
|
||||
AddCompileError(CERR_CannotReadInfile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
if(infile[0] == (KMX_BYTE) UTF16Sig[0] && infile[1] == (KMX_BYTE) UTF16Sig[1]) {
|
||||
// UTF-16 source file
|
||||
offset = 2;
|
||||
} else {
|
||||
// UTF-8 source file
|
||||
KMX_BYTE* infile16;
|
||||
int sz16;
|
||||
if(!UTF16TempFromUTF8(infile, sz, &infile16, &sz16)) {
|
||||
delete[] infile;
|
||||
AddCompileError(CERR_CannotCreateTempfile);
|
||||
return FALSE;
|
||||
}
|
||||
delete[] infile;
|
||||
infile = infile16;
|
||||
sz = sz16;
|
||||
}
|
||||
|
||||
kmcmp::CodeConstants = new kmcmp::NamedCodeConstants;
|
||||
bool success = CompileKeyboardHandle(fp_in, &fk);
|
||||
bool success = CompileKeyboardHandle(infile+offset, sz-offset, &fk);
|
||||
delete kmcmp::CodeConstants;
|
||||
|
||||
fclose(fp_in);
|
||||
delete[] infile;
|
||||
|
||||
if (kmcmp::nErrors > 0 || !success) {
|
||||
return FALSE;
|
||||
|
|
@ -204,7 +231,7 @@ EXTERN bool kmcmp_CompileKeyboard(
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
bool CompileKeyboardHandle(FILE* fp_in, PFILE_KEYBOARD fk)
|
||||
bool CompileKeyboardHandle(KMX_BYTE* infile, int sz, PFILE_KEYBOARD fk)
|
||||
{
|
||||
PKMX_WCHAR str, p;
|
||||
|
||||
|
|
@ -263,8 +290,10 @@ bool CompileKeyboardHandle(FILE* fp_in, PFILE_KEYBOARD fk)
|
|||
AddStore(fk, TSS_CUSTOMKEYMANEDITION, u"0");
|
||||
AddStore(fk, TSS_CUSTOMKEYMANEDITIONNAME, u"Keyman");
|
||||
|
||||
int offset = 0;
|
||||
|
||||
// must preprocess for group and store names -> this isn't really necessary, but never mind!
|
||||
while ((msg = ReadLine(fp_in, str, TRUE)) == CERR_None)
|
||||
while ((msg = ReadLine(infile, sz, offset, str, TRUE)) == CERR_None)
|
||||
{
|
||||
p = str;
|
||||
switch (LineTokenType(&p))
|
||||
|
|
@ -301,7 +330,7 @@ bool CompileKeyboardHandle(FILE* fp_in, PFILE_KEYBOARD fk)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
fseek( fp_in,2,SEEK_SET);
|
||||
offset = 0;
|
||||
kmcmp::currentLine = 0;
|
||||
|
||||
/* Reindex the list of codeconstants after stores added */
|
||||
|
|
@ -309,7 +338,7 @@ bool CompileKeyboardHandle(FILE* fp_in, PFILE_KEYBOARD fk)
|
|||
kmcmp::CodeConstants->reindex();
|
||||
|
||||
/* ReadLine will automatically skip over $Keyman lines, and parse wrapped lines */
|
||||
while ((msg = ReadLine(fp_in, str, FALSE)) == CERR_None)
|
||||
while ((msg = ReadLine(infile, sz, offset, str, FALSE)) == CERR_None)
|
||||
{
|
||||
msg = ParseLine(fk, str);
|
||||
if (msg != CERR_None) {
|
||||
|
|
|
|||
|
|
@ -197,33 +197,4 @@ struct COMPILEMESSAGES {
|
|||
|
||||
typedef COMPILEMESSAGES *PCOMPILEMESSAGES;
|
||||
|
||||
/*
|
||||
struct TVersion
|
||||
{
|
||||
//int MinVersion; // 0x0500 usually
|
||||
//int CompilerVersion[4];
|
||||
//int MinCompilerVersion[4];
|
||||
int KeyboardVersion; // 0x0500 usually
|
||||
};
|
||||
|
||||
extern TVersion FVersionInfo;
|
||||
*/
|
||||
|
||||
/*
|
||||
#define bstrcpy(c,d) (LPBYTE)strcpy((LPSTR)(c),(LPSTR)(d))
|
||||
#define bstrlen(c) strlen((LPSTR)(c))
|
||||
#define bstrcmp(c,d) strcmp((LPSTR)(c),(LPSTR)(d))
|
||||
#define bstrncmp(c,d,n) strncmp((LPSTR)(c),(LPSTR)(d),(n))
|
||||
#define bstrnicmp(c,d,n) strnicmp((LPSTR)(c),(LPSTR)(d),(n))
|
||||
#define bstricmp(c,d) stricmp((LPSTR)(c),(LPSTR)(d))
|
||||
#define bstrchr(c,ch) (LPBYTE)strchr((LPSTR)(c),(char)ch)
|
||||
#define bstrncpy(c,d,n) (LPBYTE)strncpy((LPSTR)(c),(LPSTR)(d),(n))
|
||||
#define bstrtok(c,d) (LPBYTE)strtok((LPSTR)(c),(LPSTR)(d))
|
||||
#define bstrcat(c,d) (LPBYTE)strcat((LPSTR)(c),(LPSTR)(d))
|
||||
#define bstrncat(c,d,n) (LPBYTE)strncat((LPSTR)(c),(LPSTR)(d),(n))
|
||||
#define bstrrev(c) (LPBYTE)strrev((LPSTR)(c))
|
||||
#define batoi(c) atoi((LPSTR)(c))
|
||||
#define bstrtol(c,d,n) strtol((LPSTR)(c),(LPSTR *)(d),(n))
|
||||
*/
|
||||
|
||||
#endif // _COMPFILE_H
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ namespace kmcmp {
|
|||
}
|
||||
|
||||
extern kmcmp_CompilerMessageProc msgproc;
|
||||
extern kmcmp_LoadFileProc loadfileproc;
|
||||
extern void* msgprocContext;
|
||||
|
||||
extern KMX_BOOL AWarnDeprecatedCode_GLOBAL_LIB;
|
||||
|
|
@ -40,10 +41,10 @@ KMX_BOOL AddCompileError(KMX_DWORD msg);
|
|||
|
||||
PKMX_WCHAR strtowstr(PKMX_STR in);
|
||||
PFILE_STORE FindSystemStore(PFILE_KEYBOARD fk, KMX_DWORD dwSystemID);
|
||||
FILE* UTF16TempFromUTF8(FILE* fp_in , KMX_BOOL hasPreamble);
|
||||
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_DWORD ReadLine(FILE* fp_in , PKMX_WCHAR wstr, KMX_BOOL PreProcess);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
# TODO: is this required? It should be Keyman Core only
|
||||
defns += ['-DKMN_KBP_EXPORTING']
|
||||
version_res = []
|
||||
lib_links = []
|
||||
|
||||
if cpp_compiler.get_id() == 'gcc' or cpp_compiler.get_id() == 'clang'
|
||||
warns += [
|
||||
|
|
@ -24,12 +25,13 @@ endif
|
|||
name_suffix = []
|
||||
|
||||
if cpp_compiler.get_id() == 'emscripten'
|
||||
links += ['-lnodefs.js', '-sMODULARIZE', '-sEXPORT_ES6', '--whole-archive', '--bind', '-sEXPORTED_RUNTIME_METHODS=[\'UTF8ToString\']']
|
||||
lib_links = ['--whole-archive', '--bind', '-sMODULARIZE', '-sEXPORT_ES6']
|
||||
links += ['-lnodefs.js', '--bind', '-sEXPORTED_RUNTIME_METHODS=[\'UTF8ToString\']']
|
||||
# tests are building as ES6 so we need to declare the file extension
|
||||
# note that meson currently struggles with the sanitycheckc_cross.exe
|
||||
# program, because it has a hard coded extension (.exe) which is not
|
||||
# valid for node programs in module mode.
|
||||
name_suffix = '.mjs'
|
||||
# name_suffix = '.mjs'
|
||||
endif
|
||||
|
||||
icu = subproject('icu-for-uset', default_options: [ 'default_library=static', 'cpp_std=c++17', 'warning_level=0', 'werror=false'])
|
||||
|
|
@ -63,7 +65,7 @@ lib = library('kmcmplib',
|
|||
|
||||
version_res,
|
||||
cpp_args: defns + warns + flags,
|
||||
link_args: links,
|
||||
link_args: links + lib_links,
|
||||
version: meson.project_version(),
|
||||
include_directories: inc,
|
||||
install: true,
|
||||
|
|
|
|||
|
|
@ -18,13 +18,14 @@
|
|||
#include <kmn_compiler_errors.h>
|
||||
#include "../src/compfile.h"
|
||||
#include <test_assert.h>
|
||||
#include "../src/filesystem.h"
|
||||
|
||||
void setup();
|
||||
void test_kmcmp_CompileKeyboard();
|
||||
void test_kmcmp_CompileKeyboard(char *kmn_file);
|
||||
|
||||
std::vector<int> error_vec;
|
||||
|
||||
int msgproc(int line, uint32_t dwMsgCode, char* szText, void* context) {
|
||||
int msgproc(int line, uint32_t dwMsgCode, const char* szText, void* context) {
|
||||
error_vec.push_back(dwMsgCode);
|
||||
const char*t = "unknown";
|
||||
switch(dwMsgCode & 0xF000) {
|
||||
|
|
@ -37,9 +38,42 @@ int msgproc(int line, uint32_t dwMsgCode, char* szText, void* context) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
bool loadfileProc(const char* filename, const char* baseFilename, void* data, int* size, void* context) {
|
||||
FILE* fp = Open_File(filename, "rb");
|
||||
if(!fp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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) {
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if(argc < 1) {
|
||||
puts("Usage: api-test <full-path-to-blank_keyboard.kmn>");
|
||||
puts("Warning: blank_keyboard will be overwritten");
|
||||
return 1;
|
||||
}
|
||||
setup();
|
||||
test_kmcmp_CompileKeyboard();
|
||||
test_kmcmp_CompileKeyboard(argv[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -48,13 +82,9 @@ void setup() {
|
|||
error_vec.clear();
|
||||
}
|
||||
|
||||
void test_kmcmp_CompileKeyboard() {
|
||||
char kmn_file[L_tmpnam], kmx_file[L_tmpnam];
|
||||
tmpnam(kmn_file);
|
||||
tmpnam(kmx_file);
|
||||
|
||||
void test_kmcmp_CompileKeyboard(char *kmn_file) {
|
||||
// Create an empty file
|
||||
FILE *fp = fopen(kmn_file, "w");
|
||||
FILE *fp = Open_File(kmn_file, "wb");
|
||||
fclose(fp);
|
||||
|
||||
// It should fail when a zero-byte file is passed in
|
||||
|
|
@ -65,7 +95,7 @@ void test_kmcmp_CompileKeyboard() {
|
|||
options.warnDeprecatedCode = true;
|
||||
options.shouldAddCompilerVersion = false;
|
||||
options.target = CKF_KEYMAN;
|
||||
assert(!kmcmp_CompileKeyboard(kmn_file, options, msgproc, nullptr, nullptr, result));
|
||||
assert(!kmcmp_CompileKeyboard(kmn_file, options, msgproc, loadfileProc, nullptr, result));
|
||||
assert(error_vec.size() == 1);
|
||||
assert(error_vec[0] == CERR_CannotReadInfile);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <sstream>
|
||||
#include <kmcmplibapi.h>
|
||||
#include <kmx_file.h>
|
||||
#include "../src/filesystem.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#else
|
||||
|
|
@ -28,7 +29,7 @@ vector < int > error_vec;
|
|||
#define CERR_WARNING 0x00002000
|
||||
#define CERR_HINT 0x00001000
|
||||
|
||||
int msgproc(int line, uint32_t dwMsgCode, char* szText, void* context)
|
||||
int msgproc(int line, uint32_t dwMsgCode, const char* szText, void* context)
|
||||
{
|
||||
error_vec.push_back(dwMsgCode);
|
||||
const char*t = "unknown";
|
||||
|
|
@ -42,6 +43,34 @@ int msgproc(int line, uint32_t dwMsgCode, char* szText, void* context)
|
|||
return 1;
|
||||
}
|
||||
|
||||
bool loadfileProc(const char* filename, const char* baseFilename, void* data, int* size, void* context) {
|
||||
FILE* fp = Open_File(filename, "rb");
|
||||
if(!fp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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) {
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "../src/filesystem.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
|
@ -79,7 +108,7 @@ int main(int argc, char *argv[])
|
|||
options.shouldAddCompilerVersion = false;
|
||||
options.target = CKF_KEYMAN;
|
||||
|
||||
if(kmcmp_CompileKeyboard(kmn_file, options, msgproc, nullptr, nullptr, result)) {
|
||||
if(kmcmp_CompileKeyboard(kmn_file, options, msgproc, loadfileProc, nullptr, result)) {
|
||||
char* testname = strrchr( (char*) kmn_file, '/') + 1;
|
||||
if(strncmp(testname, pfirst5, 5) == 0){
|
||||
return __LINE__; // exit code: CERR_ in Name + no Error found
|
||||
|
|
|
|||
|
|
@ -113,10 +113,10 @@ apitest = executable('api-test', 'api-test.cpp',
|
|||
name_suffix: name_suffix,
|
||||
link_args: links + tests_flags,
|
||||
objects: lib.extract_all_objects(),
|
||||
dependencies: icuuc_dep,
|
||||
dependencies: icuuc_dep
|
||||
)
|
||||
|
||||
test('api-test', apitest)
|
||||
test('api-test', apitest, args: [output_path / 'blank_keyboard.kmx'])
|
||||
|
||||
usetapitest = executable('uset-api-test', 'uset-api-test.cpp',
|
||||
cpp_args: defns,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue