17 #include "kmp_debug.h" 28 #include "kmp_environment.h" 29 #include "kmp_i18n_default.inc" 34 #define get_section(id) ((id) >> 16) 35 #define get_number(id) ((id)&0xFFFF) 37 kmp_msg_t __kmp_msg_null = {kmp_mt_dummy, 0, NULL, 0};
38 static char const *no_message_available =
"(No message available)";
40 static void __kmp_msg(kmp_msg_severity_t severity, kmp_msg_t message,
43 enum kmp_i18n_cat_status {
48 typedef enum kmp_i18n_cat_status kmp_i18n_cat_status_t;
49 static volatile kmp_i18n_cat_status_t status = KMP_I18N_CLOSED;
57 static void __kmp_i18n_do_catopen();
58 static kmp_bootstrap_lock_t lock = KMP_BOOTSTRAP_LOCK_INITIALIZER(lock);
63 void __kmp_i18n_catopen() {
64 if (status == KMP_I18N_CLOSED) {
65 __kmp_acquire_bootstrap_lock(&lock);
66 if (status == KMP_I18N_CLOSED) {
67 __kmp_i18n_do_catopen();
69 __kmp_release_bootstrap_lock(&lock);
79 #define KMP_I18N_NULLCAT ((nl_catd)(-1)) 80 static nl_catd cat = KMP_I18N_NULLCAT;
81 static char const *name =
82 (KMP_VERSION_MAJOR == 4 ?
"libguide.cat" :
"libomp.cat");
90 void __kmp_i18n_do_catopen() {
92 char *lang = __kmp_env_get(
"LANG");
95 KMP_DEBUG_ASSERT(status == KMP_I18N_CLOSED);
96 KMP_DEBUG_ASSERT(cat == KMP_I18N_NULLCAT);
98 english = lang == NULL ||
99 strcmp(lang,
"") == 0 || strcmp(lang,
" ") == 0 ||
102 strcmp(lang,
"C") == 0 || strcmp(lang,
"POSIX") == 0;
108 __kmp_str_split(lang,
'@', &lang, &tail);
109 __kmp_str_split(lang,
'.', &lang, &tail);
110 __kmp_str_split(lang,
'_', &lang, &tail);
111 english = (strcmp(lang,
"en") == 0);
114 KMP_INTERNAL_FREE(lang);
119 status = KMP_I18N_ABSENT;
124 cat = catopen(name, 0);
126 status = (cat == KMP_I18N_NULLCAT ? KMP_I18N_ABSENT : KMP_I18N_OPENED);
128 if (status == KMP_I18N_ABSENT) {
129 if (__kmp_generate_warnings > kmp_warnings_low) {
132 char *nlspath = __kmp_env_get(
"NLSPATH");
133 char *lang = __kmp_env_get(
"LANG");
138 kmp_msg_t err_code = KMP_ERR(error);
139 __kmp_msg(kmp_ms_warning, KMP_MSG(CantOpenMessageCatalog, name), err_code,
140 KMP_HNT(CheckEnvVar,
"NLSPATH", nlspath),
141 KMP_HNT(CheckEnvVar,
"LANG", lang), __kmp_msg_null);
142 if (__kmp_generate_warnings == kmp_warnings_off) {
143 __kmp_str_free(&err_code.str);
146 KMP_INFORM(WillUseDefaultMessages);
147 KMP_INTERNAL_FREE(nlspath);
148 KMP_INTERNAL_FREE(lang);
151 int section = get_section(kmp_i18n_prp_Version);
152 int number = get_number(kmp_i18n_prp_Version);
153 char const *expected = __kmp_i18n_default_table.sect[section].str[number];
155 kmp_str_buf_t version;
156 __kmp_str_buf_init(&version);
157 __kmp_str_buf_print(&version,
"%s", catgets(cat, section, number, NULL));
160 if (strcmp(version.str, expected) != 0) {
161 __kmp_i18n_catclose();
162 status = KMP_I18N_ABSENT;
163 if (__kmp_generate_warnings > kmp_warnings_low) {
166 char const *name =
"NLSPATH";
167 char const *nlspath = __kmp_env_get(name);
168 __kmp_msg(kmp_ms_warning,
169 KMP_MSG(WrongMessageCatalog, name, version.str, expected),
170 KMP_HNT(CheckEnvVar, name, nlspath), __kmp_msg_null);
171 KMP_INFORM(WillUseDefaultMessages);
172 KMP_INTERNAL_FREE(CCAST(
char *, nlspath));
175 __kmp_str_buf_free(&version);
179 void __kmp_i18n_catclose() {
180 if (status == KMP_I18N_OPENED) {
181 KMP_DEBUG_ASSERT(cat != KMP_I18N_NULLCAT);
183 cat = KMP_I18N_NULLCAT;
185 status = KMP_I18N_CLOSED;
188 char const *__kmp_i18n_catgets(kmp_i18n_id_t
id) {
190 int section = get_section(
id);
191 int number = get_number(
id);
192 char const *message = NULL;
194 if (1 <= section && section <= __kmp_i18n_default_table.size) {
195 if (1 <= number && number <= __kmp_i18n_default_table.sect[section].size) {
196 if (status == KMP_I18N_CLOSED) {
197 __kmp_i18n_catopen();
199 if (status == KMP_I18N_OPENED) {
200 message = catgets(cat, section, number,
201 __kmp_i18n_default_table.sect[section].str[number]);
203 if (message == NULL) {
204 message = __kmp_i18n_default_table.sect[section].str[number];
208 if (message == NULL) {
209 message = no_message_available;
215 #endif // KMP_OS_UNIX 222 #include "kmp_environment.h" 225 #define KMP_I18N_NULLCAT NULL 226 static HMODULE cat = KMP_I18N_NULLCAT;
227 static char const *name =
228 (KMP_VERSION_MAJOR == 4 ?
"libguide40ui.dll" :
"libompui.dll");
230 static kmp_i18n_table_t table = {0, NULL};
234 static UINT
const default_code_page = CP_OEMCP;
235 static UINT code_page = default_code_page;
237 static char const *___catgets(kmp_i18n_id_t
id);
238 static UINT get_code_page();
239 static void kmp_i18n_table_free(kmp_i18n_table_t *table);
241 static UINT get_code_page() {
243 UINT cp = default_code_page;
244 char const *value = __kmp_env_get(
"KMP_CODEPAGE");
246 if (_stricmp(value,
"ANSI") == 0) {
248 }
else if (_stricmp(value,
"OEM") == 0) {
250 }
else if (_stricmp(value,
"UTF-8") == 0 || _stricmp(value,
"UTF8") == 0) {
252 }
else if (_stricmp(value,
"UTF-7") == 0 || _stricmp(value,
"UTF7") == 0) {
258 KMP_INTERNAL_FREE((
void *)value);
263 static void kmp_i18n_table_free(kmp_i18n_table_t *table) {
266 for (s = 0; s < table->size; ++s) {
267 for (m = 0; m < table->sect[s].size; ++m) {
269 KMP_INTERNAL_FREE((
void *)table->sect[s].str[m]);
270 table->sect[s].str[m] = NULL;
272 table->sect[s].size = 0;
274 KMP_INTERNAL_FREE((
void *)table->sect[s].str);
275 table->sect[s].str = NULL;
278 KMP_INTERNAL_FREE((
void *)table->sect);
282 void __kmp_i18n_do_catopen() {
284 LCID locale_id = GetThreadLocale();
285 WORD lang_id = LANGIDFROMLCID(locale_id);
286 WORD primary_lang_id = PRIMARYLANGID(lang_id);
289 KMP_DEBUG_ASSERT(status == KMP_I18N_CLOSED);
290 KMP_DEBUG_ASSERT(cat == KMP_I18N_NULLCAT);
292 __kmp_str_buf_init(&path);
296 if (primary_lang_id == LANG_ENGLISH) {
297 status = KMP_I18N_ABSENT;
309 BOOL brc = GetModuleHandleEx(
310 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
311 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
312 reinterpret_cast<LPCSTR>(&__kmp_i18n_do_catopen), &handle);
314 status = KMP_I18N_ABSENT;
323 DWORD drc = GetModuleFileName(handle, path.str, path.size);
325 status = KMP_I18N_ABSENT;
328 if (drc < path.size) {
332 __kmp_str_buf_reserve(&path, path.size * 2);
337 __kmp_str_fname_init(&fname, path.str);
338 __kmp_str_buf_clear(&path);
339 __kmp_str_buf_print(&path,
"%s%lu/%s", fname.dir,
340 (
unsigned long)(locale_id), name);
341 __kmp_str_fname_free(&fname);
346 cat = LoadLibraryEx(path.str, NULL, LOAD_LIBRARY_AS_DATAFILE);
347 status = (cat == KMP_I18N_NULLCAT ? KMP_I18N_ABSENT : KMP_I18N_OPENED);
349 if (status == KMP_I18N_ABSENT) {
350 if (__kmp_generate_warnings > kmp_warnings_low) {
352 DWORD error = GetLastError();
366 kmp_msg_t err_code = KMP_SYSERRCODE(error);
367 __kmp_msg(kmp_ms_warning, KMP_MSG(CantOpenMessageCatalog, path.str),
368 err_code, (error == ERROR_BAD_EXE_FORMAT
369 ? KMP_HNT(BadExeFormat, path.str, KMP_ARCH_STR)
372 if (__kmp_generate_warnings == kmp_warnings_off) {
373 __kmp_str_free(&err_code.str);
375 KMP_INFORM(WillUseDefaultMessages);
379 int section = get_section(kmp_i18n_prp_Version);
380 int number = get_number(kmp_i18n_prp_Version);
381 char const *expected = __kmp_i18n_default_table.sect[section].str[number];
382 kmp_str_buf_t version;
383 __kmp_str_buf_init(&version);
384 __kmp_str_buf_print(&version,
"%s", ___catgets(kmp_i18n_prp_Version));
386 if (strcmp(version.str, expected) != 0) {
388 __kmp_i18n_catclose();
389 status = KMP_I18N_ABSENT;
390 if (__kmp_generate_warnings > kmp_warnings_low) {
392 __kmp_msg(kmp_ms_warning,
393 KMP_MSG(WrongMessageCatalog, path.str, version.str, expected),
395 KMP_INFORM(WillUseDefaultMessages);
398 __kmp_str_buf_free(&version);
400 code_page = get_code_page();
403 __kmp_str_buf_free(&path);
407 void __kmp_i18n_catclose() {
408 if (status == KMP_I18N_OPENED) {
409 KMP_DEBUG_ASSERT(cat != KMP_I18N_NULLCAT);
410 kmp_i18n_table_free(&table);
412 cat = KMP_I18N_NULLCAT;
414 code_page = default_code_page;
415 status = KMP_I18N_CLOSED;
444 static int ___strip_crs(
char *str) {
448 if (str[in] !=
'\r') {
460 static char const *___catgets(kmp_i18n_id_t
id) {
464 wchar_t *wmsg = NULL;
470 KMP_DEBUG_ASSERT(cat != KMP_I18N_NULLCAT);
472 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
473 FORMAT_MESSAGE_FROM_HMODULE |
474 FORMAT_MESSAGE_IGNORE_INSERTS,
483 wmsg = (
wchar_t *)addr;
487 len = WideCharToMultiByte(code_page,
498 msg = (
char *)KMP_INTERNAL_MALLOC(len + 1);
501 rc = WideCharToMultiByte(code_page,
507 if (rc <= 0 || rc > len) {
510 KMP_DEBUG_ASSERT(rc == len);
515 len = ___strip_crs(msg);
518 if (len >= 1 && msg[len - 1] ==
'\n') {
530 KMP_INTERNAL_FREE(msg);
540 char const *__kmp_i18n_catgets(kmp_i18n_id_t
id) {
542 int section = get_section(
id);
543 int number = get_number(
id);
544 char const *message = NULL;
546 if (1 <= section && section <= __kmp_i18n_default_table.size) {
547 if (1 <= number && number <= __kmp_i18n_default_table.sect[section].size) {
548 if (status == KMP_I18N_CLOSED) {
549 __kmp_i18n_catopen();
551 if (cat != KMP_I18N_NULLCAT) {
552 if (table.size == 0) {
553 table.sect = (kmp_i18n_section_t *)KMP_INTERNAL_CALLOC(
554 (__kmp_i18n_default_table.size + 2),
sizeof(kmp_i18n_section_t));
555 table.size = __kmp_i18n_default_table.size;
557 if (table.sect[section].size == 0) {
558 table.sect[section].str = (
const char **)KMP_INTERNAL_CALLOC(
559 __kmp_i18n_default_table.sect[section].size + 2,
560 sizeof(
char const *));
561 table.sect[section].size =
562 __kmp_i18n_default_table.sect[section].size;
564 if (table.sect[section].str[number] == NULL) {
565 table.sect[section].str[number] = ___catgets(
id);
567 message = table.sect[section].str[number];
569 if (message == NULL) {
572 message = __kmp_i18n_default_table.sect[section].str[number];
576 if (message == NULL) {
577 message = no_message_available;
583 #endif // KMP_OS_WINDOWS 588 #error I18n support is not implemented for this OS. 589 #endif // KMP_I18N_OK 593 void __kmp_i18n_dump_catalog(kmp_str_buf_t *buffer) {
595 struct kmp_i18n_id_range_t {
600 static struct kmp_i18n_id_range_t ranges[] = {
601 {kmp_i18n_prp_first, kmp_i18n_prp_last},
602 {kmp_i18n_str_first, kmp_i18n_str_last},
603 {kmp_i18n_fmt_first, kmp_i18n_fmt_last},
604 {kmp_i18n_msg_first, kmp_i18n_msg_last},
605 {kmp_i18n_hnt_first, kmp_i18n_hnt_last}};
607 int num_of_ranges =
sizeof(ranges) /
sizeof(
struct kmp_i18n_id_range_t);
611 for (range = 0; range < num_of_ranges; ++range) {
612 __kmp_str_buf_print(buffer,
"*** Set #%d ***\n", range + 1);
613 for (
id = (kmp_i18n_id_t)(ranges[range].first + 1);
id < ranges[range].last;
614 id = (kmp_i18n_id_t)(
id + 1)) {
615 __kmp_str_buf_print(buffer,
"%d: <<%s>>\n",
id, __kmp_i18n_catgets(
id));
619 __kmp_printf(
"%s", buffer->str);
624 kmp_msg_t __kmp_msg_format(
unsigned id_arg, ...) {
628 kmp_str_buf_t buffer;
629 __kmp_str_buf_init(&buffer);
631 va_start(args, id_arg);
636 kmp_i18n_id_t
id = (kmp_i18n_id_t)id_arg;
641 __kmp_str_buf_vprint(&buffer, __kmp_i18n_catgets(
id), args);
649 FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
650 __kmp_i18n_catgets(
id), 0, 0, (LPTSTR)(&str), 0, &args);
651 len = ___strip_crs(str);
652 __kmp_str_buf_cat(&buffer, str, len);
659 __kmp_str_buf_detach(&buffer);
661 msg.type = (kmp_msg_type_t)(
id >> 16);
662 msg.num =
id & 0xFFFF;
663 msg.str = buffer.str;
664 msg.len = buffer.used;
671 static char *sys_error(
int err) {
673 char *message = NULL;
677 LPVOID buffer = NULL;
681 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
682 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
683 (LPTSTR)&buffer, 0, NULL);
686 message = __kmp_str_format(
"%s", (
char *)buffer);
687 len = ___strip_crs(message);
689 while (len > 0 && message[len - 1] ==
'\n') {
699 if (buffer != NULL) {
703 #else // Non-Windows* OS: Linux* OS or OS X* 711 #if (defined(__GLIBC__) && defined(_GNU_SOURCE)) || \ 712 (defined(__BIONIC__) && defined(_GNU_SOURCE) && \ 713 __ANDROID_API__ >= __ANDROID_API_M__) 717 char *
const err_msg = strerror_r(err, buffer,
sizeof(buffer));
721 message = __kmp_str_format(
"%s", err_msg);
723 #else // OS X*, FreeBSD* etc. 726 char *buffer = (
char *)KMP_INTERNAL_MALLOC(size);
728 if (buffer == NULL) {
729 KMP_FATAL(MemoryAllocFailed);
731 rc = strerror_r(err, buffer, size);
735 while (rc == ERANGE) {
736 KMP_INTERNAL_FREE(buffer);
738 buffer = (
char *)KMP_INTERNAL_MALLOC(size);
739 if (buffer == NULL) {
740 KMP_FATAL(MemoryAllocFailed);
742 rc = strerror_r(err, buffer, size);
750 KMP_INTERNAL_FREE(buffer);
757 if (message == NULL) {
759 message = __kmp_str_format(
"%s",
"(No system error message available)");
765 kmp_msg_t __kmp_msg_error_code(
int code) {
768 msg.type = kmp_mt_syserr;
770 msg.str = sys_error(code);
771 msg.len = KMP_STRLEN(msg.str);
777 kmp_msg_t __kmp_msg_error_mesg(
char const *mesg) {
780 msg.type = kmp_mt_syserr;
782 msg.str = __kmp_str_format(
"%s", mesg);
783 msg.len = KMP_STRLEN(msg.str);
789 void __kmp_msg(kmp_msg_severity_t severity, kmp_msg_t message, va_list args) {
790 kmp_i18n_id_t format;
792 kmp_str_buf_t buffer;
794 if (severity != kmp_ms_fatal && __kmp_generate_warnings == kmp_warnings_off)
797 __kmp_str_buf_init(&buffer);
801 case kmp_ms_inform: {
802 format = kmp_i18n_fmt_Info;
804 case kmp_ms_warning: {
805 format = kmp_i18n_fmt_Warning;
808 format = kmp_i18n_fmt_Fatal;
810 default: { KMP_DEBUG_ASSERT(0); }
812 fmsg = __kmp_msg_format(format, message.num, message.str);
813 __kmp_str_free(&message.str);
814 __kmp_str_buf_cat(&buffer, fmsg.str, fmsg.len);
815 __kmp_str_free(&fmsg.str);
819 message = va_arg(args, kmp_msg_t);
820 if (message.type == kmp_mt_dummy && message.str == NULL) {
823 switch (message.type) {
825 format = kmp_i18n_fmt_Hint;
828 fmsg = __kmp_msg_format(format, message.str);
830 case kmp_mt_syserr: {
831 format = kmp_i18n_fmt_SysErr;
832 fmsg = __kmp_msg_format(format, message.num, message.str);
834 default: { KMP_DEBUG_ASSERT(0); }
836 __kmp_str_free(&message.str);
837 __kmp_str_buf_cat(&buffer, fmsg.str, fmsg.len);
838 __kmp_str_free(&fmsg.str);
845 __kmp_printf(
"%s", buffer.str);
846 __kmp_str_buf_free(&buffer);
853 void __kmp_msg(kmp_msg_severity_t severity, kmp_msg_t message, ...) {
855 va_start(args, message);
856 __kmp_msg(severity, message, args);
860 void __kmp_fatal(kmp_msg_t message, ...) {
862 va_start(args, message);
863 __kmp_msg(kmp_ms_fatal, message, args);
867 __kmp_thread_sleep(500);
869 __kmp_abort_process();