blob: 6774c9e9e22c049132c373fd60e1d75349434293 [file] [log] [blame]
Jim Cownie5e8470a2013-09-27 10:38:44 +00001/*
Jonathan Peytonde4749b2016-12-14 23:01:24 +00002 * kmp_i18n.cpp
Jim Cownie5e8470a2013-09-27 10:38:44 +00003 */
4
5
6//===----------------------------------------------------------------------===//
7//
8// The LLVM Compiler Infrastructure
9//
10// This file is dual licensed under the MIT and the University of Illinois Open
11// Source Licenses. See LICENSE.txt for details.
12//
13//===----------------------------------------------------------------------===//
14
15
Jim Cownie5e8470a2013-09-27 10:38:44 +000016#include "kmp_i18n.h"
17
Jim Cownie5e8470a2013-09-27 10:38:44 +000018#include "kmp.h"
Jonathan Peyton30419822017-05-12 18:01:32 +000019#include "kmp_debug.h"
20#include "kmp_io.h" // __kmp_printf.
Jim Cownie5e8470a2013-09-27 10:38:44 +000021#include "kmp_lock.h"
Jonathan Peyton30419822017-05-12 18:01:32 +000022#include "kmp_os.h"
Jim Cownie5e8470a2013-09-27 10:38:44 +000023
Jim Cownie5e8470a2013-09-27 10:38:44 +000024#include <errno.h>
Jim Cownie5e8470a2013-09-27 10:38:44 +000025#include <locale.h>
26#include <stdarg.h>
Jonathan Peyton30419822017-05-12 18:01:32 +000027#include <stdio.h>
28#include <string.h>
Jim Cownie5e8470a2013-09-27 10:38:44 +000029
Jonathan Peyton30419822017-05-12 18:01:32 +000030#include "kmp_environment.h"
Jim Cownie5e8470a2013-09-27 10:38:44 +000031#include "kmp_i18n_default.inc"
32#include "kmp_str.h"
Jim Cownie5e8470a2013-09-27 10:38:44 +000033
34#undef KMP_I18N_OK
35
Jonathan Peyton30419822017-05-12 18:01:32 +000036#define get_section(id) ((id) >> 16)
37#define get_number(id) ((id)&0xFFFF)
Jim Cownie5e8470a2013-09-27 10:38:44 +000038
Jonathan Peyton30419822017-05-12 18:01:32 +000039kmp_msg_t __kmp_msg_empty = {kmp_mt_dummy, 0, "", 0};
40kmp_msg_t __kmp_msg_null = {kmp_mt_dummy, 0, NULL, 0};
41static char const *no_message_available = "(No message available)";
Jim Cownie5e8470a2013-09-27 10:38:44 +000042
43enum kmp_i18n_cat_status {
Jonathan Peyton30419822017-05-12 18:01:32 +000044 KMP_I18N_CLOSED, // Not yet opened or closed.
45 KMP_I18N_OPENED, // Opened successfully, ready to use.
46 KMP_I18N_ABSENT // Opening failed, message catalog should not be used.
Jim Cownie5e8470a2013-09-27 10:38:44 +000047}; // enum kmp_i18n_cat_status
Jonathan Peyton30419822017-05-12 18:01:32 +000048typedef enum kmp_i18n_cat_status kmp_i18n_cat_status_t;
49static volatile kmp_i18n_cat_status_t status = KMP_I18N_CLOSED;
Jim Cownie5e8470a2013-09-27 10:38:44 +000050
Jonathan Peyton30419822017-05-12 18:01:32 +000051/* Message catalog is opened at first usage, so we have to synchronize opening
52 to avoid race and multiple openings.
Jim Cownie5e8470a2013-09-27 10:38:44 +000053
Jonathan Peyton30419822017-05-12 18:01:32 +000054 Closing does not require synchronization, because catalog is closed very late
55 at library shutting down, when no other threads are alive. */
Jim Cownie5e8470a2013-09-27 10:38:44 +000056
57static void __kmp_i18n_do_catopen();
Jonathan Peyton30419822017-05-12 18:01:32 +000058static kmp_bootstrap_lock_t lock = KMP_BOOTSTRAP_LOCK_INITIALIZER(lock);
59// `lock' variable may be placed into __kmp_i18n_catopen function because it is
60// used only by that function. But we afraid a (buggy) compiler may treat it
61// wrongly. So we put it outside of function just in case.
Jim Cownie5e8470a2013-09-27 10:38:44 +000062
Jonathan Peyton30419822017-05-12 18:01:32 +000063void __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();
Jim Cownie5e8470a2013-09-27 10:38:44 +000068 }; // if
Jonathan Peyton30419822017-05-12 18:01:32 +000069 __kmp_release_bootstrap_lock(&lock);
70 }; // if
Jim Cownie5e8470a2013-09-27 10:38:44 +000071} // func __kmp_i18n_catopen
72
Jonathan Peyton30419822017-05-12 18:01:32 +000073/* Linux* OS and OS X* part */
Jim Cownie5e8470a2013-09-27 10:38:44 +000074#if KMP_OS_UNIX
75#define KMP_I18N_OK
76
77#include <nl_types.h>
78
Jonathan Peyton30419822017-05-12 18:01:32 +000079#define KMP_I18N_NULLCAT ((nl_catd)(-1))
80static nl_catd cat = KMP_I18N_NULLCAT; // !!! Shall it be volatile?
81static char const *name =
82 (KMP_VERSION_MAJOR == 4 ? "libguide.cat" : "libomp.cat");
Jim Cownie5e8470a2013-09-27 10:38:44 +000083
Jonathan Peyton30419822017-05-12 18:01:32 +000084/* Useful links:
85http://www.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html#tag_08_02
86http://www.opengroup.org/onlinepubs/000095399/functions/catopen.html
87http://www.opengroup.org/onlinepubs/000095399/functions/setlocale.html
Jim Cownie5e8470a2013-09-27 10:38:44 +000088*/
89
Jonathan Peyton30419822017-05-12 18:01:32 +000090void __kmp_i18n_do_catopen() {
91 int english = 0;
92 char *lang = __kmp_env_get("LANG");
93 // TODO: What about LC_ALL or LC_MESSAGES?
Jim Cownie5e8470a2013-09-27 10:38:44 +000094
Jonathan Peyton30419822017-05-12 18:01:32 +000095 KMP_DEBUG_ASSERT(status == KMP_I18N_CLOSED);
96 KMP_DEBUG_ASSERT(cat == KMP_I18N_NULLCAT);
Jim Cownie5e8470a2013-09-27 10:38:44 +000097
Jonathan Peyton30419822017-05-12 18:01:32 +000098 english = lang == NULL || // In all these cases English language is used.
99 strcmp(lang, "") == 0 || strcmp(lang, " ") == 0 ||
100 // Workaround for Fortran RTL bug DPD200137873 "Fortran runtime
101 // resets LANG env var to space if it is not set".
102 strcmp(lang, "C") == 0 || strcmp(lang, "POSIX") == 0;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000103
Jonathan Peyton30419822017-05-12 18:01:32 +0000104 if (!english) { // English language is not yet detected, let us continue.
105 // Format of LANG is: [language[_territory][.codeset][@modifier]]
106 // Strip all parts except language.
107 char *tail = NULL;
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);
112 }; // if
Jim Cownie5e8470a2013-09-27 10:38:44 +0000113
Jonathan Peyton30419822017-05-12 18:01:32 +0000114 KMP_INTERNAL_FREE(lang);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000115
Jonathan Peyton30419822017-05-12 18:01:32 +0000116 // Do not try to open English catalog because internal messages are
117 // exact copy of messages in English catalog.
118 if (english) {
119 status = KMP_I18N_ABSENT; // mark catalog as absent so it will not
120 // be re-opened.
121 return;
122 }
123
124 cat = catopen(name, 0);
125 // TODO: Why do we pass 0 in flags?
126 status = (cat == KMP_I18N_NULLCAT ? KMP_I18N_ABSENT : KMP_I18N_OPENED);
127
128 if (status == KMP_I18N_ABSENT) {
129 if (__kmp_generate_warnings > kmp_warnings_low) {
130 // AC: only issue warning in case explicitly asked to
131 int error = errno; // Save errno immediately.
132 char *nlspath = __kmp_env_get("NLSPATH");
133 char *lang = __kmp_env_get("LANG");
134
135 // Infinite recursion will not occur -- status is KMP_I18N_ABSENT now, so
136 // __kmp_i18n_catgets() will not try to open catalog, but will return
137 // default message.
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);
144 }
145
146 KMP_INFORM(WillUseDefaultMessages);
147 KMP_INTERNAL_FREE(nlspath);
148 KMP_INTERNAL_FREE(lang);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000149 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000150 } else { // status == KMP_I18N_OPENED
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];
154 // Expected version of the catalog.
155 kmp_str_buf_t version; // Actual version of the catalog.
156 __kmp_str_buf_init(&version);
157 __kmp_str_buf_print(&version, "%s", catgets(cat, section, number, NULL));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000158
Jonathan Peyton30419822017-05-12 18:01:32 +0000159 // String returned by catgets is invalid after closing catalog, so copy it.
160 if (strcmp(version.str, expected) != 0) {
161 __kmp_i18n_catclose(); // Close bad catalog.
162 status = KMP_I18N_ABSENT; // And mark it as absent.
163 if (__kmp_generate_warnings > kmp_warnings_low) {
164 // AC: only issue warning in case explicitly asked to
165 // And now print a warning using default messages.
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);
Andrey Churbanovc47afcd2017-07-03 11:24:08 +0000172 KMP_INTERNAL_FREE(CCAST(char *, nlspath));
Jonathan Peyton30419822017-05-12 18:01:32 +0000173 } // __kmp_generate_warnings
Jim Cownie5e8470a2013-09-27 10:38:44 +0000174 }; // if
Jonathan Peyton30419822017-05-12 18:01:32 +0000175 __kmp_str_buf_free(&version);
176 }; // if
Jim Cownie5e8470a2013-09-27 10:38:44 +0000177} // func __kmp_i18n_do_catopen
178
Jonathan Peyton30419822017-05-12 18:01:32 +0000179void __kmp_i18n_catclose() {
180 if (status == KMP_I18N_OPENED) {
181 KMP_DEBUG_ASSERT(cat != KMP_I18N_NULLCAT);
182 catclose(cat);
183 cat = KMP_I18N_NULLCAT;
184 }; // if
185 status = KMP_I18N_CLOSED;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000186} // func __kmp_i18n_catclose
187
Jonathan Peyton30419822017-05-12 18:01:32 +0000188char const *__kmp_i18n_catgets(kmp_i18n_id_t id) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000189
Jonathan Peyton30419822017-05-12 18:01:32 +0000190 int section = get_section(id);
191 int number = get_number(id);
192 char const *message = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000193
Jonathan Peyton30419822017-05-12 18:01:32 +0000194 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();
198 }; // if
199 if (status == KMP_I18N_OPENED) {
200 message = catgets(cat, section, number,
201 __kmp_i18n_default_table.sect[section].str[number]);
202 }; // if
203 if (message == NULL) {
204 message = __kmp_i18n_default_table.sect[section].str[number];
205 }; // if
Jim Cownie5e8470a2013-09-27 10:38:44 +0000206 }; // if
Jonathan Peyton30419822017-05-12 18:01:32 +0000207 }; // if
208 if (message == NULL) {
209 message = no_message_available;
210 }; // if
211 return message;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000212
213} // func __kmp_i18n_catgets
214
Jim Cownie5e8470a2013-09-27 10:38:44 +0000215#endif // KMP_OS_UNIX
216
Jonathan Peyton30419822017-05-12 18:01:32 +0000217/* Windows* OS part. */
Jim Cownie5e8470a2013-09-27 10:38:44 +0000218
219#if KMP_OS_WINDOWS
220#define KMP_I18N_OK
221
222#include "kmp_environment.h"
223#include <windows.h>
224
Jonathan Peyton30419822017-05-12 18:01:32 +0000225#define KMP_I18N_NULLCAT NULL
226static HMODULE cat = KMP_I18N_NULLCAT; // !!! Shall it be volatile?
227static char const *name =
228 (KMP_VERSION_MAJOR == 4 ? "libguide40ui.dll" : "libompui.dll");
Jim Cownie5e8470a2013-09-27 10:38:44 +0000229
Jonathan Peyton30419822017-05-12 18:01:32 +0000230static kmp_i18n_table_t table = {0, NULL};
231// Messages formatted by FormatMessage() should be freed, but catgets()
232// interface assumes user will not free messages. So we cache all the retrieved
233// messages in the table, which are freed at catclose().
234static UINT const default_code_page = CP_OEMCP;
235static UINT code_page = default_code_page;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000236
Jonathan Peyton30419822017-05-12 18:01:32 +0000237static char const *___catgets(kmp_i18n_id_t id);
238static UINT get_code_page();
239static void kmp_i18n_table_free(kmp_i18n_table_t *table);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000240
Jonathan Peyton30419822017-05-12 18:01:32 +0000241static UINT get_code_page() {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000242
Jonathan Peyton30419822017-05-12 18:01:32 +0000243 UINT cp = default_code_page;
244 char const *value = __kmp_env_get("KMP_CODEPAGE");
245 if (value != NULL) {
246 if (_stricmp(value, "ANSI") == 0) {
247 cp = CP_ACP;
248 } else if (_stricmp(value, "OEM") == 0) {
249 cp = CP_OEMCP;
250 } else if (_stricmp(value, "UTF-8") == 0 || _stricmp(value, "UTF8") == 0) {
251 cp = CP_UTF8;
252 } else if (_stricmp(value, "UTF-7") == 0 || _stricmp(value, "UTF7") == 0) {
253 cp = CP_UTF7;
254 } else {
255 // !!! TODO: Issue a warning?
Jim Cownie5e8470a2013-09-27 10:38:44 +0000256 }; // if
Jonathan Peyton30419822017-05-12 18:01:32 +0000257 }; // if
258 KMP_INTERNAL_FREE((void *)value);
259 return cp;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000260
261} // func get_code_page
262
Jonathan Peyton30419822017-05-12 18:01:32 +0000263static void kmp_i18n_table_free(kmp_i18n_table_t *table) {
264 int s;
265 int m;
266 for (s = 0; s < table->size; ++s) {
267 for (m = 0; m < table->sect[s].size; ++m) {
268 // Free message.
269 KMP_INTERNAL_FREE((void *)table->sect[s].str[m]);
270 table->sect[s].str[m] = NULL;
271 }; // for m
272 table->sect[s].size = 0;
273 // Free section itself.
274 KMP_INTERNAL_FREE((void *)table->sect[s].str);
275 table->sect[s].str = NULL;
276 }; // for s
277 table->size = 0;
278 KMP_INTERNAL_FREE((void *)table->sect);
279 table->sect = NULL;
Andrey Churbanovbcadbd62016-11-28 19:23:09 +0000280} // kmp_i18n_table_free
Jim Cownie5e8470a2013-09-27 10:38:44 +0000281
Jonathan Peyton30419822017-05-12 18:01:32 +0000282void __kmp_i18n_do_catopen() {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000283
Jonathan Peyton30419822017-05-12 18:01:32 +0000284 LCID locale_id = GetThreadLocale();
285 WORD lang_id = LANGIDFROMLCID(locale_id);
286 WORD primary_lang_id = PRIMARYLANGID(lang_id);
287 kmp_str_buf_t path;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000288
Jonathan Peyton30419822017-05-12 18:01:32 +0000289 KMP_DEBUG_ASSERT(status == KMP_I18N_CLOSED);
290 KMP_DEBUG_ASSERT(cat == KMP_I18N_NULLCAT);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000291
Jonathan Peyton30419822017-05-12 18:01:32 +0000292 __kmp_str_buf_init(&path);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000293
Jonathan Peyton30419822017-05-12 18:01:32 +0000294 // Do not try to open English catalog because internal messages are exact copy
295 // of messages in English catalog.
296 if (primary_lang_id == LANG_ENGLISH) {
297 status = KMP_I18N_ABSENT; // mark catalog as absent so it will not
298 // be re-opened.
299 goto end;
300 }; // if
Jim Cownie5e8470a2013-09-27 10:38:44 +0000301
Jonathan Peyton30419822017-05-12 18:01:32 +0000302 // Construct resource DLL name.
303 /* Simple LoadLibrary( name ) is not suitable due to security issue (see
304 http://www.microsoft.com/technet/security/advisory/2269637.mspx). We have
305 to specify full path to the message catalog. */
306 {
307 // Get handle of our DLL first.
308 HMODULE handle;
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);
313 if (!brc) { // Error occurred.
314 status = KMP_I18N_ABSENT; // mark catalog as absent so it will not be
315 // re-opened.
316 goto end;
317 // TODO: Enable multiple messages (KMP_MSG) to be passed to __kmp_msg; and
318 // print a proper warning.
319 }; // if
320
321 // Now get path to the our DLL.
322 for (;;) {
323 DWORD drc = GetModuleFileName(handle, path.str, path.size);
324 if (drc == 0) { // Error occurred.
325 status = KMP_I18N_ABSENT;
Andrey Churbanovbcadbd62016-11-28 19:23:09 +0000326 goto end;
Jonathan Peyton30419822017-05-12 18:01:32 +0000327 }; // if
328 if (drc < path.size) {
329 path.used = drc;
330 break;
331 }; // if
332 __kmp_str_buf_reserve(&path, path.size * 2);
333 }; // forever
Jim Cownie5e8470a2013-09-27 10:38:44 +0000334
Jonathan Peyton30419822017-05-12 18:01:32 +0000335 // Now construct the name of message catalog.
336 kmp_str_fname fname;
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);
342 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000343
Jonathan Peyton30419822017-05-12 18:01:32 +0000344 // For security reasons, use LoadLibraryEx() and load message catalog as a
345 // data file.
346 cat = LoadLibraryEx(path.str, NULL, LOAD_LIBRARY_AS_DATAFILE);
347 status = (cat == KMP_I18N_NULLCAT ? KMP_I18N_ABSENT : KMP_I18N_OPENED);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000348
Jonathan Peyton30419822017-05-12 18:01:32 +0000349 if (status == KMP_I18N_ABSENT) {
350 if (__kmp_generate_warnings > kmp_warnings_low) {
351 // AC: only issue warning in case explicitly asked to
352 DWORD error = GetLastError();
353 // Infinite recursion will not occur -- status is KMP_I18N_ABSENT now, so
354 // __kmp_i18n_catgets() will not try to open catalog but will return
355 // default message.
356 /* If message catalog for another architecture found (e.g. OpenMP RTL for
357 IA-32 architecture opens libompui.dll for Intel(R) 64) Windows* OS
358 returns error 193 (ERROR_BAD_EXE_FORMAT). However, FormatMessage fails
359 to return a message for this error, so user will see:
Jim Cownie5e8470a2013-09-27 10:38:44 +0000360
Jonathan Peyton30419822017-05-12 18:01:32 +0000361 OMP: Warning #2: Cannot open message catalog "1041\libompui.dll":
362 OMP: System error #193: (No system error message available)
363 OMP: Info #3: Default messages will be used.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000364
Jonathan Peyton30419822017-05-12 18:01:32 +0000365 Issue hint in this case so cause of trouble is more understandable. */
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)
370 : __kmp_msg_null),
371 __kmp_msg_null);
372 if (__kmp_generate_warnings == kmp_warnings_off) {
373 __kmp_str_free(&err_code.str);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000374 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000375 KMP_INFORM(WillUseDefaultMessages);
376 }
377 } else { // status == KMP_I18N_OPENED
Jim Cownie5e8470a2013-09-27 10:38:44 +0000378
Jonathan Peyton30419822017-05-12 18:01:32 +0000379 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; // Actual version of the catalog.
383 __kmp_str_buf_init(&version);
384 __kmp_str_buf_print(&version, "%s", ___catgets(kmp_i18n_prp_Version));
385 // String returned by catgets is invalid after closing catalog, so copy it.
386 if (strcmp(version.str, expected) != 0) {
387 // Close bad catalog.
388 __kmp_i18n_catclose();
389 status = KMP_I18N_ABSENT; // And mark it as absent.
390 if (__kmp_generate_warnings > kmp_warnings_low) {
391 // And now print a warning using default messages.
392 __kmp_msg(kmp_ms_warning,
393 KMP_MSG(WrongMessageCatalog, path.str, version.str, expected),
394 __kmp_msg_null);
395 KMP_INFORM(WillUseDefaultMessages);
396 } // __kmp_generate_warnings
Jim Cownie5e8470a2013-09-27 10:38:44 +0000397 }; // if
Jonathan Peyton30419822017-05-12 18:01:32 +0000398 __kmp_str_buf_free(&version);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000399
Jonathan Peyton30419822017-05-12 18:01:32 +0000400 }; // if
401 code_page = get_code_page();
Jim Cownie5e8470a2013-09-27 10:38:44 +0000402
Jonathan Peyton30419822017-05-12 18:01:32 +0000403end:
404 __kmp_str_buf_free(&path);
405 return;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000406} // func __kmp_i18n_do_catopen
407
Jonathan Peyton30419822017-05-12 18:01:32 +0000408void __kmp_i18n_catclose() {
409 if (status == KMP_I18N_OPENED) {
410 KMP_DEBUG_ASSERT(cat != KMP_I18N_NULLCAT);
411 kmp_i18n_table_free(&table);
412 FreeLibrary(cat);
413 cat = KMP_I18N_NULLCAT;
414 }; // if
415 code_page = default_code_page;
416 status = KMP_I18N_CLOSED;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000417} // func __kmp_i18n_catclose
418
Jonathan Peyton30419822017-05-12 18:01:32 +0000419/* We use FormatMessage() to get strings from catalog, get system error
420 messages, etc. FormatMessage() tends to return Windows* OS-style
421 end-of-lines, "\r\n". When string is printed, printf() also replaces all the
422 occurrences of "\n" with "\r\n" (again!), so sequences like "\r\r\r\n"
423 appear in output. It is not too good.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000424
Jonathan Peyton30419822017-05-12 18:01:32 +0000425 Additional mess comes from message catalog: Our catalog source en_US.mc file
426 (generated by message-converter.pl) contains only "\n" characters, but
427 en_US_msg_1033.bin file (produced by mc.exe) may contain "\r\n" or just "\n".
428 This mess goes from en_US_msg_1033.bin file to message catalog,
429 libompui.dll. For example, message
Jim Cownie5e8470a2013-09-27 10:38:44 +0000430
Jonathan Peyton30419822017-05-12 18:01:32 +0000431 Error
Jim Cownie5e8470a2013-09-27 10:38:44 +0000432
Jonathan Peyton30419822017-05-12 18:01:32 +0000433 (there is "\n" at the end) is compiled by mc.exe to "Error\r\n", while
Jim Cownie5e8470a2013-09-27 10:38:44 +0000434
Jonathan Peyton30419822017-05-12 18:01:32 +0000435 OMP: Error %1!d!: %2!s!\n
Jim Cownie5e8470a2013-09-27 10:38:44 +0000436
Jonathan Peyton30419822017-05-12 18:01:32 +0000437 (there is "\n" at the end as well) is compiled to "OMP: Error %1!d!:
438 %2!s!\r\n\n".
Jim Cownie5e8470a2013-09-27 10:38:44 +0000439
Jonathan Peyton30419822017-05-12 18:01:32 +0000440 Thus, stripping all "\r" normalizes string and returns it to canonical form,
441 so printf() will produce correct end-of-line sequences.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000442
Jonathan Peyton30419822017-05-12 18:01:32 +0000443 ___strip_crs() serves for this purpose: it removes all the occurrences of
444 "\r" in-place and returns new length of string. */
445static int ___strip_crs(char *str) {
446 int in = 0; // Input character index.
447 int out = 0; // Output character index.
448 for (;;) {
449 if (str[in] != '\r') {
450 str[out] = str[in];
451 ++out;
452 }; // if
453 if (str[in] == 0) {
454 break;
455 }; // if
456 ++in;
457 }; // forever
458 return out - 1;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000459} // func __strip_crs
460
Jonathan Peyton30419822017-05-12 18:01:32 +0000461static char const *___catgets(kmp_i18n_id_t id) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000462
Jonathan Peyton30419822017-05-12 18:01:32 +0000463 char *result = NULL;
464 PVOID addr = NULL;
465 wchar_t *wmsg = NULL;
466 DWORD wlen = 0;
467 char *msg = NULL;
468 int len = 0;
469 int rc;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000470
Jonathan Peyton30419822017-05-12 18:01:32 +0000471 KMP_DEBUG_ASSERT(cat != KMP_I18N_NULLCAT);
472 wlen = // wlen does *not* include terminating null.
473 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
474 FORMAT_MESSAGE_FROM_HMODULE |
475 FORMAT_MESSAGE_IGNORE_INSERTS,
476 cat, id,
477 0, // LangId
478 (LPWSTR)&addr,
479 0, // Size in elements, not in bytes.
480 NULL);
481 if (wlen <= 0) {
482 goto end;
483 }; // if
484 wmsg = (wchar_t *)addr; // Warning: wmsg may be not nul-terminated!
Jim Cownie5e8470a2013-09-27 10:38:44 +0000485
Jonathan Peyton30419822017-05-12 18:01:32 +0000486 // Calculate length of multibyte message.
487 // Since wlen does not include terminating null, len does not include it also.
488 len = WideCharToMultiByte(code_page,
489 0, // Flags.
490 wmsg, wlen, // Wide buffer and size.
491 NULL, 0, // Buffer and size.
492 NULL, NULL // Default char and used default char.
493 );
494 if (len <= 0) {
495 goto end;
496 }; // if
Jim Cownie5e8470a2013-09-27 10:38:44 +0000497
Jonathan Peyton30419822017-05-12 18:01:32 +0000498 // Allocate memory.
499 msg = (char *)KMP_INTERNAL_MALLOC(len + 1);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000500
Jonathan Peyton30419822017-05-12 18:01:32 +0000501 // Convert wide message to multibyte one.
502 rc = WideCharToMultiByte(code_page,
503 0, // Flags.
504 wmsg, wlen, // Wide buffer and size.
505 msg, len, // Buffer and size.
506 NULL, NULL // Default char and used default char.
507 );
508 if (rc <= 0 || rc > len) {
509 goto end;
510 }; // if
511 KMP_DEBUG_ASSERT(rc == len);
512 len = rc;
513 msg[len] = 0; // Put terminating null to the end.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000514
Jonathan Peyton30419822017-05-12 18:01:32 +0000515 // Stripping all "\r" before stripping last end-of-line simplifies the task.
516 len = ___strip_crs(msg);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000517
Jonathan Peyton30419822017-05-12 18:01:32 +0000518 // Every message in catalog is terminated with "\n". Strip it.
519 if (len >= 1 && msg[len - 1] == '\n') {
520 --len;
521 msg[len] = 0;
522 }; // if
Jim Cownie5e8470a2013-09-27 10:38:44 +0000523
Jonathan Peyton30419822017-05-12 18:01:32 +0000524 // Everything looks ok.
525 result = msg;
526 msg = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000527
Jonathan Peyton30419822017-05-12 18:01:32 +0000528end:
Jim Cownie5e8470a2013-09-27 10:38:44 +0000529
Jonathan Peyton30419822017-05-12 18:01:32 +0000530 if (msg != NULL) {
531 KMP_INTERNAL_FREE(msg);
532 }; // if
533 if (wmsg != NULL) {
534 LocalFree(wmsg);
535 }; // if
Jim Cownie5e8470a2013-09-27 10:38:44 +0000536
Jonathan Peyton30419822017-05-12 18:01:32 +0000537 return result;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000538
539} // ___catgets
540
Jonathan Peyton30419822017-05-12 18:01:32 +0000541char const *__kmp_i18n_catgets(kmp_i18n_id_t id) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000542
Jonathan Peyton30419822017-05-12 18:01:32 +0000543 int section = get_section(id);
544 int number = get_number(id);
545 char const *message = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000546
Jonathan Peyton30419822017-05-12 18:01:32 +0000547 if (1 <= section && section <= __kmp_i18n_default_table.size) {
548 if (1 <= number && number <= __kmp_i18n_default_table.sect[section].size) {
549 if (status == KMP_I18N_CLOSED) {
550 __kmp_i18n_catopen();
551 }; // if
552 if (cat != KMP_I18N_NULLCAT) {
553 if (table.size == 0) {
554 table.sect = (kmp_i18n_section_t *)KMP_INTERNAL_CALLOC(
555 (__kmp_i18n_default_table.size + 2), sizeof(kmp_i18n_section_t));
556 table.size = __kmp_i18n_default_table.size;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000557 }; // if
Jonathan Peyton30419822017-05-12 18:01:32 +0000558 if (table.sect[section].size == 0) {
559 table.sect[section].str = (const char **)KMP_INTERNAL_CALLOC(
560 __kmp_i18n_default_table.sect[section].size + 2,
561 sizeof(char const *));
562 table.sect[section].size =
563 __kmp_i18n_default_table.sect[section].size;
564 }; // if
565 if (table.sect[section].str[number] == NULL) {
566 table.sect[section].str[number] = ___catgets(id);
567 }; // if
568 message = table.sect[section].str[number];
569 }; // if
570 if (message == NULL) {
571 // Catalog is not opened or message is not found, return default
572 // message.
573 message = __kmp_i18n_default_table.sect[section].str[number];
574 }; // if
Jim Cownie5e8470a2013-09-27 10:38:44 +0000575 }; // if
Jonathan Peyton30419822017-05-12 18:01:32 +0000576 }; // if
577 if (message == NULL) {
578 message = no_message_available;
579 }; // if
580 return message;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000581
582} // func __kmp_i18n_catgets
583
Jim Cownie5e8470a2013-09-27 10:38:44 +0000584#endif // KMP_OS_WINDOWS
585
Jonathan Peyton30419822017-05-12 18:01:32 +0000586// -----------------------------------------------------------------------------
Jim Cownie5e8470a2013-09-27 10:38:44 +0000587
588#ifndef KMP_I18N_OK
Jonathan Peyton30419822017-05-12 18:01:32 +0000589#error I18n support is not implemented for this OS.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000590#endif // KMP_I18N_OK
591
Jonathan Peyton30419822017-05-12 18:01:32 +0000592// -----------------------------------------------------------------------------
Jim Cownie5e8470a2013-09-27 10:38:44 +0000593
Jonathan Peyton30419822017-05-12 18:01:32 +0000594void __kmp_i18n_dump_catalog(kmp_str_buf_t *buffer) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000595
Jonathan Peyton30419822017-05-12 18:01:32 +0000596 struct kmp_i18n_id_range_t {
597 kmp_i18n_id_t first;
598 kmp_i18n_id_t last;
599 }; // struct kmp_i18n_id_range_t
Jim Cownie5e8470a2013-09-27 10:38:44 +0000600
Jonathan Peyton30419822017-05-12 18:01:32 +0000601 static struct kmp_i18n_id_range_t ranges[] = {
602 {kmp_i18n_prp_first, kmp_i18n_prp_last},
603 {kmp_i18n_str_first, kmp_i18n_str_last},
604 {kmp_i18n_fmt_first, kmp_i18n_fmt_last},
605 {kmp_i18n_msg_first, kmp_i18n_msg_last},
606 {kmp_i18n_hnt_first, kmp_i18n_hnt_last}}; // ranges
Jim Cownie5e8470a2013-09-27 10:38:44 +0000607
Jonathan Peyton30419822017-05-12 18:01:32 +0000608 int num_of_ranges = sizeof(ranges) / sizeof(struct kmp_i18n_id_range_t);
609 int range;
610 kmp_i18n_id_t id;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000611
Jonathan Peyton30419822017-05-12 18:01:32 +0000612 for (range = 0; range < num_of_ranges; ++range) {
613 __kmp_str_buf_print(buffer, "*** Set #%d ***\n", range + 1);
614 for (id = (kmp_i18n_id_t)(ranges[range].first + 1); id < ranges[range].last;
615 id = (kmp_i18n_id_t)(id + 1)) {
616 __kmp_str_buf_print(buffer, "%d: <<%s>>\n", id, __kmp_i18n_catgets(id));
617 }; // for id
618 }; // for range
Jim Cownie5e8470a2013-09-27 10:38:44 +0000619
Jonathan Peyton30419822017-05-12 18:01:32 +0000620 __kmp_printf("%s", buffer->str);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000621
622} // __kmp_i18n_dump_catalog
623
Jonathan Peyton30419822017-05-12 18:01:32 +0000624// -----------------------------------------------------------------------------
625kmp_msg_t __kmp_msg_format(unsigned id_arg, ...) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000626
Jonathan Peyton30419822017-05-12 18:01:32 +0000627 kmp_msg_t msg;
628 va_list args;
629 kmp_str_buf_t buffer;
630 __kmp_str_buf_init(&buffer);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000631
Jonathan Peyton30419822017-05-12 18:01:32 +0000632 va_start(args, id_arg);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000633
Jonathan Peyton30419822017-05-12 18:01:32 +0000634 // We use unsigned for the ID argument and explicitly cast it here to the
635 // right enumerator because variadic functions are not compatible with
636 // default promotions.
637 kmp_i18n_id_t id = (kmp_i18n_id_t)id_arg;
Samuel Antao71fef772016-07-22 16:05:35 +0000638
Jonathan Peyton30419822017-05-12 18:01:32 +0000639#if KMP_OS_UNIX
640 // On Linux* OS and OS X*, printf() family functions process parameter
641 // numbers, for example: "%2$s %1$s".
642 __kmp_str_buf_vprint(&buffer, __kmp_i18n_catgets(id), args);
643#elif KMP_OS_WINDOWS
644 // On Winodws, printf() family functions does not recognize GNU style
645 // parameter numbers, so we have to use FormatMessage() instead. It recognizes
646 // parameter numbers, e. g.: "%2!s! "%1!s!".
647 {
648 LPTSTR str = NULL;
649 int len;
650 FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
651 __kmp_i18n_catgets(id), 0, 0, (LPTSTR)(&str), 0, &args);
652 len = ___strip_crs(str);
653 __kmp_str_buf_cat(&buffer, str, len);
654 LocalFree(str);
655 }
656#else
657#error
658#endif
659 va_end(args);
660 __kmp_str_buf_detach(&buffer);
Samuel Antao71fef772016-07-22 16:05:35 +0000661
Jonathan Peyton30419822017-05-12 18:01:32 +0000662 msg.type = (kmp_msg_type_t)(id >> 16);
663 msg.num = id & 0xFFFF;
664 msg.str = buffer.str;
665 msg.len = buffer.used;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000666
Jonathan Peyton30419822017-05-12 18:01:32 +0000667 return msg;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000668
669} // __kmp_msg_format
670
Jonathan Peyton30419822017-05-12 18:01:32 +0000671// -----------------------------------------------------------------------------
672static char *sys_error(int err) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000673
Jonathan Peyton30419822017-05-12 18:01:32 +0000674 char *message = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000675
Jonathan Peyton30419822017-05-12 18:01:32 +0000676#if KMP_OS_WINDOWS
Jim Cownie5e8470a2013-09-27 10:38:44 +0000677
Jonathan Peyton30419822017-05-12 18:01:32 +0000678 LPVOID buffer = NULL;
679 int len;
680 DWORD rc;
681 rc = FormatMessage(
682 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
683 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language.
684 (LPTSTR)&buffer, 0, NULL);
685 if (rc > 0) {
686 // Message formatted. Copy it (so we can free it later with normal free().
687 message = __kmp_str_format("%s", (char *)buffer);
688 len = ___strip_crs(message); // Delete carriage returns if any.
689 // Strip trailing newlines.
690 while (len > 0 && message[len - 1] == '\n') {
691 --len;
692 }; // while
693 message[len] = 0;
694 } else {
695 // FormatMessage() failed to format system error message. GetLastError()
696 // would give us error code, which we would convert to message... this it
697 // dangerous recursion, which cannot clarify original error, so we will not
698 // even start it.
699 }; // if
700 if (buffer != NULL) {
701 LocalFree(buffer);
702 }; // if
Jim Cownie5e8470a2013-09-27 10:38:44 +0000703
Jonathan Peyton30419822017-05-12 18:01:32 +0000704#else // Non-Windows* OS: Linux* OS or OS X*
Jim Cownie5e8470a2013-09-27 10:38:44 +0000705
Jonathan Peyton30419822017-05-12 18:01:32 +0000706/* There are 2 incompatible versions of strerror_r:
Jim Cownie5e8470a2013-09-27 10:38:44 +0000707
Jonathan Peyton30419822017-05-12 18:01:32 +0000708 char * strerror_r( int, char *, size_t ); // GNU version
709 int strerror_r( int, char *, size_t ); // XSI version
710*/
Jim Cownie5e8470a2013-09-27 10:38:44 +0000711
Jonathan Peyton30419822017-05-12 18:01:32 +0000712#if (defined(__GLIBC__) && defined(_GNU_SOURCE)) || \
713 (defined(__BIONIC__) && defined(_GNU_SOURCE) && \
714 __ANDROID_API__ >= __ANDROID_API_M__)
715 // GNU version of strerror_r.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000716
Jonathan Peyton30419822017-05-12 18:01:32 +0000717 char buffer[2048];
718 char *const err_msg = strerror_r(err, buffer, sizeof(buffer));
719 // Do not eliminate this assignment to temporary variable, otherwise compiler
720 // would not issue warning if strerror_r() returns `int' instead of expected
721 // `char *'.
722 message = __kmp_str_format("%s", err_msg);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000723
Jonathan Peyton30419822017-05-12 18:01:32 +0000724#else // OS X*, FreeBSD* etc.
725 // XSI version of strerror_r.
726 int size = 2048;
727 char *buffer = (char *)KMP_INTERNAL_MALLOC(size);
728 int rc;
729 if (buffer == NULL) {
730 KMP_FATAL(MemoryAllocFailed);
731 }
732 rc = strerror_r(err, buffer, size);
733 if (rc == -1) {
734 rc = errno; // XSI version sets errno.
735 }; // if
736 while (rc == ERANGE) { // ERANGE means the buffer is too small.
737 KMP_INTERNAL_FREE(buffer);
738 size *= 2;
739 buffer = (char *)KMP_INTERNAL_MALLOC(size);
740 if (buffer == NULL) {
741 KMP_FATAL(MemoryAllocFailed);
742 }
743 rc = strerror_r(err, buffer, size);
744 if (rc == -1) {
745 rc = errno; // XSI version sets errno.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000746 }; // if
Jonathan Peyton30419822017-05-12 18:01:32 +0000747 }; // while
748 if (rc == 0) {
749 message = buffer;
750 } else { // Buffer is unused. Free it.
751 KMP_INTERNAL_FREE(buffer);
752 }; // if
Jim Cownie5e8470a2013-09-27 10:38:44 +0000753
Jonathan Peyton30419822017-05-12 18:01:32 +0000754#endif
755
756#endif /* KMP_OS_WINDOWS */
757
758 if (message == NULL) {
759 // TODO: I18n this message.
760 message = __kmp_str_format("%s", "(No system error message available)");
761 }; // if
762 return message;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000763} // sys_error
764
Jonathan Peyton30419822017-05-12 18:01:32 +0000765// -----------------------------------------------------------------------------
766kmp_msg_t __kmp_msg_error_code(int code) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000767
Jonathan Peyton30419822017-05-12 18:01:32 +0000768 kmp_msg_t msg;
769 msg.type = kmp_mt_syserr;
770 msg.num = code;
771 msg.str = sys_error(code);
772 msg.len = KMP_STRLEN(msg.str);
773 return msg;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000774
775} // __kmp_msg_error_code
776
Jonathan Peyton30419822017-05-12 18:01:32 +0000777// -----------------------------------------------------------------------------
778kmp_msg_t __kmp_msg_error_mesg(char const *mesg) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000779
Jonathan Peyton30419822017-05-12 18:01:32 +0000780 kmp_msg_t msg;
781 msg.type = kmp_mt_syserr;
782 msg.num = 0;
783 msg.str = __kmp_str_format("%s", mesg);
784 msg.len = KMP_STRLEN(msg.str);
785 return msg;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000786
787} // __kmp_msg_error_mesg
788
Jonathan Peyton30419822017-05-12 18:01:32 +0000789// -----------------------------------------------------------------------------
790void __kmp_msg(kmp_msg_severity_t severity, kmp_msg_t message, ...) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000791
Jonathan Peyton30419822017-05-12 18:01:32 +0000792 va_list args;
793 kmp_i18n_id_t format; // format identifier
794 kmp_msg_t fmsg; // formatted message
795 kmp_str_buf_t buffer;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000796
Jonathan Peyton30419822017-05-12 18:01:32 +0000797 if (severity != kmp_ms_fatal && __kmp_generate_warnings == kmp_warnings_off)
798 return; // no reason to form a string in order to not print it
Jim Cownie5e8470a2013-09-27 10:38:44 +0000799
Jonathan Peyton30419822017-05-12 18:01:32 +0000800 __kmp_str_buf_init(&buffer);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000801
Jonathan Peyton30419822017-05-12 18:01:32 +0000802 // Format the primary message.
803 switch (severity) {
804 case kmp_ms_inform: {
805 format = kmp_i18n_fmt_Info;
806 } break;
807 case kmp_ms_warning: {
808 format = kmp_i18n_fmt_Warning;
809 } break;
810 case kmp_ms_fatal: {
811 format = kmp_i18n_fmt_Fatal;
812 } break;
813 default: { KMP_DEBUG_ASSERT(0); };
814 }; // switch
815 fmsg = __kmp_msg_format(format, message.num, message.str);
816 __kmp_str_free(&message.str);
817 __kmp_str_buf_cat(&buffer, fmsg.str, fmsg.len);
818 __kmp_str_free(&fmsg.str);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000819
Jonathan Peyton30419822017-05-12 18:01:32 +0000820 // Format other messages.
821 va_start(args, message);
822 for (;;) {
823 message = va_arg(args, kmp_msg_t);
824 if (message.type == kmp_mt_dummy && message.str == NULL) {
825 break;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000826 }; // if
Jonathan Peyton30419822017-05-12 18:01:32 +0000827 if (message.type == kmp_mt_dummy && message.str == __kmp_msg_empty.str) {
828 continue;
829 }; // if
830 switch (message.type) {
831 case kmp_mt_hint: {
832 format = kmp_i18n_fmt_Hint;
833 } break;
834 case kmp_mt_syserr: {
835 format = kmp_i18n_fmt_SysErr;
836 } break;
837 default: { KMP_DEBUG_ASSERT(0); };
838 }; // switch
839 fmsg = __kmp_msg_format(format, message.num, message.str);
840 __kmp_str_free(&message.str);
841 __kmp_str_buf_cat(&buffer, fmsg.str, fmsg.len);
842 __kmp_str_free(&fmsg.str);
843 }; // forever
844 va_end(args);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000845
Jonathan Peyton30419822017-05-12 18:01:32 +0000846 // Print formatted messages.
847 // This lock prevents multiple fatal errors on the same problem.
848 // __kmp_acquire_bootstrap_lock( & lock ); // GEH - This lock causing tests
849 // to hang on OS X*.
850 __kmp_printf("%s", buffer.str);
851 __kmp_str_buf_free(&buffer);
852
853 if (severity == kmp_ms_fatal) {
854#if KMP_OS_WINDOWS
855 __kmp_thread_sleep(
856 500); /* Delay to give message a chance to appear before reaping */
857#endif
858 __kmp_abort_process();
859 }; // if
860
861 // __kmp_release_bootstrap_lock( & lock ); // GEH - this lock causing tests
862 // to hang on OS X*.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000863
864} // __kmp_msg
865
Jim Cownie5e8470a2013-09-27 10:38:44 +0000866// end of file //