#CXXFLAGS+=-s USE_PTHREADS=1 | #CXXFLAGS+=-s USE_PTHREADS=1 | ||||
# NOTE: extra flags for emscripten | # NOTE: extra flags for emscripten | ||||
EM_CXXFLAGS=-s RESERVED_FUNCTION_POINTERS=2 --memory-init-file 0 -s FORCE_FILESYSTEM=1 -s WASM=0 | |||||
EM_CXXFLAGS=-s RESERVED_FUNCTION_POINTERS=2 --memory-init-file 0 -s FORCE_FILESYSTEM=1 -s WASM=0 -s ERROR_ON_UNDEFINED_SYMBOLS=0 | |||||
if (typeof WorkerGlobalScope !== 'undefined') { | if (typeof WorkerGlobalScope !== 'undefined') { | ||||
var worker; | var worker; | ||||
Module.postRun = Module.postRun || []; | |||||
Module.postRun.push(function () { | Module.postRun.push(function () { | ||||
worker = new eSpeakNGWorker(); | worker = new eSpeakNGWorker(); |
// a RULE_GROUP_END. | // a RULE_GROUP_END. | ||||
if (*p != RULE_GROUP_END) while (*p != 0) { | if (*p != RULE_GROUP_END) while (*p != 0) { | ||||
if (*p != RULE_GROUP_START) { | if (*p != RULE_GROUP_START) { | ||||
fprintf(stderr, "Bad rules data in '%s_dict' at 0x%x (%c)\n", dictionary_name, (unsigned int)(p - tr->data_dictrules), p); | |||||
fprintf(stderr, "Bad rules data in '%s_dict' at 0x%x (%c)\n", dictionary_name, (unsigned int)(p - tr->data_dictrules), *p); | |||||
break; | break; | ||||
} | } | ||||
p++; | p++; | ||||
if (p[0] == RULE_REPLACEMENTS) { | if (p[0] == RULE_REPLACEMENTS) { | ||||
p = (char *)(((intptr_t)p+4) & ~3); // advance to next word boundary | p = (char *)(((intptr_t)p+4) & ~3); // advance to next word boundary | ||||
tr->langopts.replace_chars = (unsigned char *)p; | tr->langopts.replace_chars = (unsigned char *)p; | ||||
while (*(unsigned int *)p != 0) | |||||
// Don't cast to (unsigned int), result may not be garanted depending on compiler | |||||
while ( !is_str_fully_empty(p, 4) ) { | |||||
p++; | p++; | ||||
} | |||||
while (*p != RULE_GROUP_END) p++; | while (*p != RULE_GROUP_END) p++; | ||||
p++; | p++; | ||||
continue; | continue; |
return CLAUSE_NONE; | return CLAUSE_NONE; | ||||
} | } | ||||
int is_str_fully_empty(const char* str, int size) { | |||||
// Tests if all bytes of str are null uf to size | |||||
// This should never be reimplemented with integers, because | |||||
// this function has to work with unaligned char* | |||||
// (casting to int when unaligned may result in ungaranteed behaviors) | |||||
return *str || memcmp(str, str+1, size-1); | |||||
} | |||||
int towlower2(unsigned int c, Translator *translator) | int towlower2(unsigned int c, Translator *translator) | ||||
{ | { | ||||
// check for non-standard upper to lower case conversions | // check for non-standard upper to lower case conversions |
extern PARAM_STACK param_stack[]; | extern PARAM_STACK param_stack[]; | ||||
int clause_type_from_codepoint(uint32_t c); | |||||
// Tests if all bytes of str up to size are null | |||||
int is_str_fully_empty(const char* str, int size); | |||||
int clause_type_from_codepoint(uint32_t c); | |||||
int towlower2(unsigned int c, Translator *translator); // Supports Turkish I | int towlower2(unsigned int c, Translator *translator); // Supports Turkish I | ||||
int Eof(void); | int Eof(void); | ||||
const char *WordToString2(unsigned int word); | const char *WordToString2(unsigned int word); | ||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
} | } | ||||
#endif | #endif |
static const char *FindReplacementChars(Translator *tr, const char **pfrom, unsigned int c, const char *next, int *ignore_next_n) | static const char *FindReplacementChars(Translator *tr, const char **pfrom, unsigned int c, const char *next, int *ignore_next_n) | ||||
{ | { | ||||
const char *from = *pfrom; | const char *from = *pfrom; | ||||
while (*(unsigned int *)from != 0) { | |||||
while ( !is_str_fully_empty(from, 4) ) { | |||||
unsigned int fc = 0; // from character | unsigned int fc = 0; // from character | ||||
unsigned int nc = c; // next character | unsigned int nc = c; // next character | ||||
const char *match_next = next; | const char *match_next = next; |