refactor(developer): move fs for kmn load to caller

This commit is contained in:
Marc Durdin 2023-05-30 10:52:05 +07:00
parent f36a908d94
commit 71df68cd13
9 changed files with 194 additions and 160 deletions

View file

@ -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(

View file

@ -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)

View file

@ -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) {

View file

@ -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

View file

@ -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);

View file

@ -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,

View file

@ -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);

View file

@ -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

View file

@ -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,