| #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; |