LLVM OpenMP 22.0.0git
kmp_i18n.cpp
Go to the documentation of this file.
1/*
2 * kmp_i18n.cpp
3 */
4
5//===----------------------------------------------------------------------===//
6//
7// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8// See https://llvm.org/LICENSE.txt for license information.
9// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
10//
11//===----------------------------------------------------------------------===//
12
13#include "kmp_i18n.h"
14
15#include "kmp.h"
16#include "kmp_debug.h"
17#include "kmp_io.h" // __kmp_printf.
18#include "kmp_lock.h"
19#include "kmp_os.h"
20
21#include <errno.h>
22#include <locale.h>
23#include <stdarg.h>
24#include <stdio.h>
25#include <string.h>
26
27#include "kmp_environment.h"
28#include "kmp_i18n_default.inc"
29#include "kmp_str.h"
30
31#undef KMP_I18N_OK
32
33#define get_section(id) ((id) >> 16)
34#define get_number(id) ((id)&0xFFFF)
35
37static char const *no_message_available = "(No message available)";
38
39static void __kmp_msg(kmp_msg_severity_t severity, kmp_msg_t message,
40 va_list ap);
41
43 KMP_I18N_CLOSED, // Not yet opened or closed.
44 KMP_I18N_OPENED, // Opened successfully, ready to use.
45 KMP_I18N_ABSENT // Opening failed, message catalog should not be used.
46}; // enum kmp_i18n_cat_status
49
50/* Message catalog is opened at first usage, so we have to synchronize opening
51 to avoid race and multiple openings.
52
53 Closing does not require synchronization, because catalog is closed very late
54 at library shutting down, when no other threads are alive. */
55
58// `lock' variable may be placed into __kmp_i18n_catopen function because it is
59// used only by that function. But we afraid a (buggy) compiler may treat it
60// wrongly. So we put it outside of function just in case.
61
63 if (status == KMP_I18N_CLOSED) {
65 if (status == KMP_I18N_CLOSED) {
67 }
69 }
70} // func __kmp_i18n_catopen
71
72/* Linux* OS and OS X* part */
73#if KMP_OS_UNIX
74#define KMP_I18N_OK
75
76#include <nl_types.h>
77
78#define KMP_I18N_NULLCAT ((nl_catd)(-1))
79static nl_catd cat = KMP_I18N_NULLCAT; // !!! Shall it be volatile?
80static char const *name =
81 (KMP_VERSION_MAJOR == 4 ? "libguide.cat" : "libomp.cat");
82
83/* Useful links:
84http://www.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html#tag_08_02
85http://www.opengroup.org/onlinepubs/000095399/functions/catopen.html
86http://www.opengroup.org/onlinepubs/000095399/functions/setlocale.html
87*/
88
90 int english = 0;
91 char *lang = __kmp_env_get("LANG");
92 // TODO: What about LC_ALL or LC_MESSAGES?
93
95 KMP_DEBUG_ASSERT(cat == KMP_I18N_NULLCAT);
96
97 english = lang == NULL || // In all these cases English language is used.
98 strcmp(lang, "") == 0 || strcmp(lang, " ") == 0 ||
99 // Workaround for Fortran RTL bug DPD200137873 "Fortran runtime
100 // resets LANG env var to space if it is not set".
101 strcmp(lang, "C") == 0 || strcmp(lang, "POSIX") == 0;
102
103 if (!english) { // English language is not yet detected, let us continue.
104 // Format of LANG is: [language[_territory][.codeset][@modifier]]
105 // Strip all parts except language.
106 char *tail = NULL;
107 __kmp_str_split(lang, '@', &lang, &tail);
108 __kmp_str_split(lang, '.', &lang, &tail);
109 __kmp_str_split(lang, '_', &lang, &tail);
110 english = (strcmp(lang, "en") == 0);
111 }
112
113 KMP_INTERNAL_FREE(lang);
114
115 // Do not try to open English catalog because internal messages are
116 // exact copy of messages in English catalog.
117 if (english) {
118 status = KMP_I18N_ABSENT; // mark catalog as absent so it will not
119 // be re-opened.
120 return;
121 }
122
123 cat = catopen(name, 0);
124 // TODO: Why do we pass 0 in flags?
125 status = (cat == KMP_I18N_NULLCAT ? KMP_I18N_ABSENT : KMP_I18N_OPENED);
126
127 if (status == KMP_I18N_ABSENT) {
129 // AC: only issue warning in case explicitly asked to
130 int error = errno; // Save errno immediately.
131 char *nlspath = __kmp_env_get("NLSPATH");
132 char *lang = __kmp_env_get("LANG");
133
134 // Infinite recursion will not occur -- status is KMP_I18N_ABSENT now, so
135 // __kmp_i18n_catgets() will not try to open catalog, but will return
136 // default message.
137 kmp_msg_t err_code = KMP_ERR(error);
138 __kmp_msg(kmp_ms_warning, KMP_MSG(CantOpenMessageCatalog, name), err_code,
139 KMP_HNT(CheckEnvVar, "NLSPATH", nlspath),
140 KMP_HNT(CheckEnvVar, "LANG", lang), __kmp_msg_null);
142 __kmp_str_free(&err_code.str);
143 }
144
145 KMP_INFORM(WillUseDefaultMessages);
146 KMP_INTERNAL_FREE(nlspath);
147 KMP_INTERNAL_FREE(lang);
148 }
149 } else { // status == KMP_I18N_OPENED
150 int section = get_section(kmp_i18n_prp_Version);
151 int number = get_number(kmp_i18n_prp_Version);
152 char const *expected = __kmp_i18n_default_table.sect[section].str[number];
153 // Expected version of the catalog.
154 kmp_str_buf_t version; // Actual version of the catalog.
155 __kmp_str_buf_init(&version);
156 __kmp_str_buf_print(&version, "%s", catgets(cat, section, number, NULL));
157
158 // String returned by catgets is invalid after closing catalog, so copy it.
159 if (strcmp(version.str, expected) != 0) {
160 __kmp_i18n_catclose(); // Close bad catalog.
161 status = KMP_I18N_ABSENT; // And mark it as absent.
163 // AC: only issue warning in case explicitly asked to
164 // And now print a warning using default messages.
165 char const *name = "NLSPATH";
166 char const *nlspath = __kmp_env_get(name);
168 KMP_MSG(WrongMessageCatalog, name, version.str, expected),
169 KMP_HNT(CheckEnvVar, name, nlspath), __kmp_msg_null);
170 KMP_INFORM(WillUseDefaultMessages);
171 KMP_INTERNAL_FREE(CCAST(char *, nlspath));
172 } // __kmp_generate_warnings
173 }
174 __kmp_str_buf_free(&version);
175 }
176} // func __kmp_i18n_do_catopen
177
178void __kmp_i18n_catclose() {
179 if (status == KMP_I18N_OPENED) {
180 KMP_DEBUG_ASSERT(cat != KMP_I18N_NULLCAT);
181 catclose(cat);
182 cat = KMP_I18N_NULLCAT;
183 }
185} // func __kmp_i18n_catclose
186
187char const *__kmp_i18n_catgets(kmp_i18n_id_t id) {
188
189 int section = get_section(id);
190 int number = get_number(id);
191 char const *message = NULL;
192
193 if (1 <= section && section <= __kmp_i18n_default_table.size) {
194 if (1 <= number && number <= __kmp_i18n_default_table.sect[section].size) {
195 if (status == KMP_I18N_CLOSED) {
197 }
198 if (status == KMP_I18N_OPENED) {
199 message = catgets(cat, section, number,
200 __kmp_i18n_default_table.sect[section].str[number]);
201 }
202 if (message == NULL) {
203 message = __kmp_i18n_default_table.sect[section].str[number];
204 }
205 }
206 }
207 if (message == NULL) {
208 message = no_message_available;
209 }
210 return message;
211
212} // func __kmp_i18n_catgets
213
214#endif // KMP_OS_UNIX
215
216/* Windows* OS part. */
217
218#if KMP_OS_WINDOWS
219#define KMP_I18N_OK
220
221#include "kmp_environment.h"
222#include <windows.h>
223
224#define KMP_I18N_NULLCAT NULL
225static HMODULE cat = KMP_I18N_NULLCAT; // !!! Shall it be volatile?
226static char const *name =
227 (KMP_VERSION_MAJOR == 4 ? "libguide40ui.dll" : "libompui.dll");
228
229static kmp_i18n_table_t table = {0, NULL};
230// Messages formatted by FormatMessage() should be freed, but catgets()
231// interface assumes user will not free messages. So we cache all the retrieved
232// messages in the table, which are freed at catclose().
233static UINT const default_code_page = CP_OEMCP;
234static UINT code_page = default_code_page;
235
236static char const *___catgets(kmp_i18n_id_t id);
237static UINT get_code_page();
238static void kmp_i18n_table_free(kmp_i18n_table_t *table);
239
240static UINT get_code_page() {
241
242 UINT cp = default_code_page;
243 char const *value = __kmp_env_get("KMP_CODEPAGE");
244 if (value != NULL) {
245 if (_stricmp(value, "ANSI") == 0) {
246 cp = CP_ACP;
247 } else if (_stricmp(value, "OEM") == 0) {
248 cp = CP_OEMCP;
249 } else if (_stricmp(value, "UTF-8") == 0 || _stricmp(value, "UTF8") == 0) {
250 cp = CP_UTF8;
251 } else if (_stricmp(value, "UTF-7") == 0 || _stricmp(value, "UTF7") == 0) {
252 cp = CP_UTF7;
253 } else {
254 // !!! TODO: Issue a warning?
255 }
256 }
257 KMP_INTERNAL_FREE((void *)value);
258 return cp;
259
260} // func get_code_page
261
262static void kmp_i18n_table_free(kmp_i18n_table_t *table) {
263 int s;
264 int m;
265 for (s = 0; s < table->size; ++s) {
266 for (m = 0; m < table->sect[s].size; ++m) {
267 // Free message.
268 KMP_INTERNAL_FREE((void *)table->sect[s].str[m]);
269 table->sect[s].str[m] = NULL;
270 }
271 table->sect[s].size = 0;
272 // Free section itself.
273 KMP_INTERNAL_FREE((void *)table->sect[s].str);
274 table->sect[s].str = NULL;
275 }
276 table->size = 0;
277 KMP_INTERNAL_FREE((void *)table->sect);
278 table->sect = NULL;
279} // kmp_i18n_table_free
280
282
283 LCID locale_id = GetThreadLocale();
284 WORD lang_id = LANGIDFROMLCID(locale_id);
285 WORD primary_lang_id = PRIMARYLANGID(lang_id);
287
289 KMP_DEBUG_ASSERT(cat == KMP_I18N_NULLCAT);
290
292
293 // Do not try to open English catalog because internal messages are exact copy
294 // of messages in English catalog.
295 if (primary_lang_id == LANG_ENGLISH) {
296 status = KMP_I18N_ABSENT; // mark catalog as absent so it will not
297 // be re-opened.
298 goto end;
299 }
300
301 // Construct resource DLL name.
302 /* Simple LoadLibrary( name ) is not suitable due to security issue (see
303 http://www.microsoft.com/technet/security/advisory/2269637.mspx). We have
304 to specify full path to the message catalog. */
305 {
306 // Get handle of our DLL first.
307 HMODULE handle;
308 BOOL brc = GetModuleHandleEx(
309 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
310 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
311 reinterpret_cast<LPCSTR>(&__kmp_i18n_do_catopen), &handle);
312 if (!brc) { // Error occurred.
313 status = KMP_I18N_ABSENT; // mark catalog as absent so it will not be
314 // re-opened.
315 goto end;
316 // TODO: Enable multiple messages (KMP_MSG) to be passed to __kmp_msg; and
317 // print a proper warning.
318 }
319
320 // Now get path to the our DLL.
321 for (;;) {
322 DWORD drc = GetModuleFileName(handle, path.str, path.size);
323 if (drc == 0) { // Error occurred.
325 goto end;
326 }
327 if (drc < path.size) {
328 path.used = drc;
329 break;
330 }
331 __kmp_str_buf_reserve(&path, path.size * 2);
332 }
333
334 // Now construct the name of message catalog.
335 kmp_str_fname fname;
336 __kmp_str_fname_init(&fname, path.str);
338 __kmp_str_buf_print(&path, "%s%lu/%s", fname.dir,
339 (unsigned long)(locale_id), name);
340 __kmp_str_fname_free(&fname);
341 }
342
343 // For security reasons, use LoadLibraryEx() and load message catalog as a
344 // data file.
345 cat = LoadLibraryEx(path.str, NULL, LOAD_LIBRARY_AS_DATAFILE);
346 status = (cat == KMP_I18N_NULLCAT ? KMP_I18N_ABSENT : KMP_I18N_OPENED);
347
348 if (status == KMP_I18N_ABSENT) {
350 // AC: only issue warning in case explicitly asked to
351 DWORD error = GetLastError();
352 // Infinite recursion will not occur -- status is KMP_I18N_ABSENT now, so
353 // __kmp_i18n_catgets() will not try to open catalog but will return
354 // default message.
355 /* If message catalog for another architecture found (e.g. OpenMP RTL for
356 IA-32 architecture opens libompui.dll for Intel(R) 64) Windows* OS
357 returns error 193 (ERROR_BAD_EXE_FORMAT). However, FormatMessage fails
358 to return a message for this error, so user will see:
359
360 OMP: Warning #2: Cannot open message catalog "1041\libompui.dll":
361 OMP: System error #193: (No system error message available)
362 OMP: Info #3: Default messages will be used.
363
364 Issue hint in this case so cause of trouble is more understandable. */
365 kmp_msg_t err_code = KMP_SYSERRCODE(error);
366 __kmp_msg(kmp_ms_warning, KMP_MSG(CantOpenMessageCatalog, path.str),
367 err_code,
368 (error == ERROR_BAD_EXE_FORMAT
369 ? KMP_HNT(BadExeFormat, path.str, KMP_ARCH_STR)
373 __kmp_str_free(&err_code.str);
374 }
375 KMP_INFORM(WillUseDefaultMessages);
376 }
377 } else { // status == KMP_I18N_OPENED
378
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; // 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.
389 status = KMP_I18N_ABSENT; // And mark it as absent.
391 // And now print a warning using default messages.
393 KMP_MSG(WrongMessageCatalog, path.str, version.str, expected),
395 KMP_INFORM(WillUseDefaultMessages);
396 } // __kmp_generate_warnings
397 }
398 __kmp_str_buf_free(&version);
399 }
400 code_page = get_code_page();
401
402end:
404 return;
405} // func __kmp_i18n_do_catopen
406
407void __kmp_i18n_catclose() {
408 if (status == KMP_I18N_OPENED) {
409 KMP_DEBUG_ASSERT(cat != KMP_I18N_NULLCAT);
410 kmp_i18n_table_free(&table);
411 FreeLibrary(cat);
412 cat = KMP_I18N_NULLCAT;
413 }
414 code_page = default_code_page;
416} // func __kmp_i18n_catclose
417
418/* We use FormatMessage() to get strings from catalog, get system error
419 messages, etc. FormatMessage() tends to return Windows* OS-style
420 end-of-lines, "\r\n". When string is printed, printf() also replaces all the
421 occurrences of "\n" with "\r\n" (again!), so sequences like "\r\r\r\n"
422 appear in output. It is not too good.
423
424 Additional mess comes from message catalog: Our catalog source en_US.mc file
425 (generated by message-converter.pl) contains only "\n" characters, but
426 en_US_msg_1033.bin file (produced by mc.exe) may contain "\r\n" or just "\n".
427 This mess goes from en_US_msg_1033.bin file to message catalog,
428 libompui.dll. For example, message
429
430 Error
431
432 (there is "\n" at the end) is compiled by mc.exe to "Error\r\n", while
433
434 OMP: Error %1!d!: %2!s!\n
435
436 (there is "\n" at the end as well) is compiled to "OMP: Error %1!d!:
437 %2!s!\r\n\n".
438
439 Thus, stripping all "\r" normalizes string and returns it to canonical form,
440 so printf() will produce correct end-of-line sequences.
441
442 ___strip_crs() serves for this purpose: it removes all the occurrences of
443 "\r" in-place and returns new length of string. */
444static int ___strip_crs(char *str) {
445 int in = 0; // Input character index.
446 int out = 0; // Output character index.
447 for (;;) {
448 if (str[in] != '\r') {
449 str[out] = str[in];
450 ++out;
451 }
452 if (str[in] == 0) {
453 break;
454 }
455 ++in;
456 }
457 return out - 1;
458} // func __strip_crs
459
460static char const *___catgets(kmp_i18n_id_t id) {
461
462 char *result = NULL;
463 PVOID addr = NULL;
464 wchar_t *wmsg = NULL;
465 DWORD wlen = 0;
466 char *msg = NULL;
467 int len = 0;
468 int rc;
469
470 KMP_DEBUG_ASSERT(cat != KMP_I18N_NULLCAT);
471 wlen = // wlen does *not* include terminating null.
472 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
473 FORMAT_MESSAGE_FROM_HMODULE |
474 FORMAT_MESSAGE_IGNORE_INSERTS,
475 cat, id,
476 0, // LangId
477 (LPWSTR)&addr,
478 0, // Size in elements, not in bytes.
479 NULL);
480 if (wlen <= 0) {
481 goto end;
482 }
483 wmsg = (wchar_t *)addr; // Warning: wmsg may be not nul-terminated!
484
485 // Calculate length of multibyte message.
486 // Since wlen does not include terminating null, len does not include it also.
487 len = WideCharToMultiByte(code_page,
488 0, // Flags.
489 wmsg, wlen, // Wide buffer and size.
490 NULL, 0, // Buffer and size.
491 NULL, NULL // Default char and used default char.
492 );
493 if (len <= 0) {
494 goto end;
495 }
496
497 // Allocate memory.
498 msg = (char *)KMP_INTERNAL_MALLOC(len + 1);
499
500 // Convert wide message to multibyte one.
501 rc = WideCharToMultiByte(code_page,
502 0, // Flags.
503 wmsg, wlen, // Wide buffer and size.
504 msg, len, // Buffer and size.
505 NULL, NULL // Default char and used default char.
506 );
507 if (rc <= 0 || rc > len) {
508 goto end;
509 }
510 KMP_DEBUG_ASSERT(rc == len);
511 len = rc;
512 msg[len] = 0; // Put terminating null to the end.
513
514 // Stripping all "\r" before stripping last end-of-line simplifies the task.
515 len = ___strip_crs(msg);
516
517 // Every message in catalog is terminated with "\n". Strip it.
518 if (len >= 1 && msg[len - 1] == '\n') {
519 --len;
520 msg[len] = 0;
521 }
522
523 // Everything looks ok.
524 result = msg;
525 msg = NULL;
526
527end:
528
529 if (msg != NULL) {
531 }
532 if (wmsg != NULL) {
533 LocalFree(wmsg);
534 }
535
536 return result;
537
538} // ___catgets
539
540char const *__kmp_i18n_catgets(kmp_i18n_id_t id) {
541
542 int section = get_section(id);
543 int number = get_number(id);
544 char const *message = NULL;
545
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) {
550 }
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;
556 }
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;
563 }
564 if (table.sect[section].str[number] == NULL) {
565 table.sect[section].str[number] = ___catgets(id);
566 }
567 message = table.sect[section].str[number];
568 }
569 if (message == NULL) {
570 // Catalog is not opened or message is not found, return default
571 // message.
572 message = __kmp_i18n_default_table.sect[section].str[number];
573 }
574 }
575 }
576 if (message == NULL) {
577 message = no_message_available;
578 }
579 return message;
580
581} // func __kmp_i18n_catgets
582
583#endif // KMP_OS_WINDOWS
584
585// -----------------------------------------------------------------------------
586
587#ifndef KMP_I18N_OK
588#error I18n support is not implemented for this OS.
589#endif // KMP_I18N_OK
590
591// -----------------------------------------------------------------------------
592
594
595 struct kmp_i18n_id_range_t {
596 kmp_i18n_id_t first;
597 kmp_i18n_id_t last;
598 }; // struct kmp_i18n_id_range_t
599
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}}; // ranges
606
607 int num_of_ranges = sizeof(ranges) / sizeof(struct kmp_i18n_id_range_t);
608 int range;
609 kmp_i18n_id_t id;
610
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));
616 }
617 }
618
619 __kmp_printf("%s", buffer->str);
620
621} // __kmp_i18n_dump_catalog
622
623// -----------------------------------------------------------------------------
624kmp_msg_t __kmp_msg_format(unsigned id_arg, ...) {
625
626 kmp_msg_t msg;
627 va_list args;
628 kmp_str_buf_t buffer;
629 __kmp_str_buf_init(&buffer);
630
631 va_start(args, id_arg);
632
633 // We use unsigned for the ID argument and explicitly cast it here to the
634 // right enumerator because variadic functions are not compatible with
635 // default promotions.
636 kmp_i18n_id_t id = (kmp_i18n_id_t)id_arg;
637
638#if KMP_OS_UNIX
639 // On Linux* OS and OS X*, printf() family functions process parameter
640 // numbers, for example: "%2$s %1$s".
642#elif KMP_OS_WINDOWS
643 // On Windows, printf() family functions does not recognize GNU style
644 // parameter numbers, so we have to use FormatMessage() instead. It recognizes
645 // parameter numbers, e. g.: "%2!s! "%1!s!".
646 {
647 LPTSTR str = NULL;
648 int len;
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);
653 LocalFree(str);
654 }
655#else
656#error
657#endif
658 va_end(args);
659 __kmp_str_buf_detach(&buffer);
660
661 msg.type = (kmp_msg_type_t)(id >> 16);
662 msg.num = id & 0xFFFF;
663 msg.str = buffer.str;
664 msg.len = buffer.used;
665
666 return msg;
667
668} // __kmp_msg_format
669
670// -----------------------------------------------------------------------------
671static char *sys_error(int err) {
672
673 char *message = NULL;
674
675#if KMP_OS_WINDOWS
676
677 LPVOID buffer = NULL;
678 int len;
679 DWORD rc;
680 rc = FormatMessage(
681 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
682 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language.
683 (LPTSTR)&buffer, 0, NULL);
684 if (rc > 0) {
685 // Message formatted. Copy it (so we can free it later with normal free().
686 message = __kmp_str_format("%s", (char *)buffer);
687 len = ___strip_crs(message); // Delete carriage returns if any.
688 // Strip trailing newlines.
689 while (len > 0 && message[len - 1] == '\n') {
690 --len;
691 }
692 message[len] = 0;
693 } else {
694 // FormatMessage() failed to format system error message. GetLastError()
695 // would give us error code, which we would convert to message... this it
696 // dangerous recursion, which cannot clarify original error, so we will not
697 // even start it.
698 }
699 if (buffer != NULL) {
700 LocalFree(buffer);
701 }
702
703#else // Non-Windows* OS: Linux* OS or OS X*
704
705 /* There are 2 incompatible versions of strerror_r:
706
707 char * strerror_r( int, char *, size_t ); // GNU version
708 int strerror_r( int, char *, size_t ); // XSI version
709 */
710
711#if (defined(__GLIBC__) && defined(_GNU_SOURCE)) || \
712 (defined(__BIONIC__) && defined(_GNU_SOURCE) && \
713 __ANDROID_API__ >= __ANDROID_API_M__)
714 // GNU version of strerror_r.
715
716 char buffer[2048];
717 char *const err_msg = strerror_r(err, buffer, sizeof(buffer));
718 // Do not eliminate this assignment to temporary variable, otherwise compiler
719 // would not issue warning if strerror_r() returns `int' instead of expected
720 // `char *'.
721 message = __kmp_str_format("%s", err_msg);
722
723#else // OS X*, FreeBSD* etc.
724 // XSI version of strerror_r.
725 int size = 2048;
726 char *buffer = (char *)KMP_INTERNAL_MALLOC(size);
727 int rc;
728 if (buffer == NULL) {
729 KMP_FATAL(MemoryAllocFailed);
730 }
731 rc = strerror_r(err, buffer, size);
732 if (rc == -1) {
733 rc = errno; // XSI version sets errno.
734 }
735 while (rc == ERANGE) { // ERANGE means the buffer is too small.
736 KMP_INTERNAL_FREE(buffer);
737 size *= 2;
738 buffer = (char *)KMP_INTERNAL_MALLOC(size);
739 if (buffer == NULL) {
740 KMP_FATAL(MemoryAllocFailed);
741 }
742 rc = strerror_r(err, buffer, size);
743 if (rc == -1) {
744 rc = errno; // XSI version sets errno.
745 }
746 }
747 if (rc == 0) {
748 message = buffer;
749 } else { // Buffer is unused. Free it.
750 KMP_INTERNAL_FREE(buffer);
751 }
752
753#endif
754
755#endif /* KMP_OS_WINDOWS */
756
757 if (message == NULL) {
758 // TODO: I18n this message.
759 message = __kmp_str_format("%s", "(No system error message available)");
760 }
761 return message;
762} // sys_error
763
764// -----------------------------------------------------------------------------
766
767 kmp_msg_t msg;
768 msg.type = kmp_mt_syserr;
769 msg.num = code;
770 msg.str = sys_error(code);
771 msg.len = KMP_STRLEN(msg.str);
772 return msg;
773
774} // __kmp_msg_error_code
775
776// -----------------------------------------------------------------------------
778
779 kmp_msg_t msg;
780 msg.type = kmp_mt_syserr;
781 msg.num = 0;
782 msg.str = __kmp_str_format("%s", mesg);
783 msg.len = KMP_STRLEN(msg.str);
784 return msg;
785
786} // __kmp_msg_error_mesg
787
788// -----------------------------------------------------------------------------
789void __kmp_msg(kmp_msg_severity_t severity, kmp_msg_t message, va_list args) {
790 kmp_i18n_id_t format; // format identifier
791 kmp_msg_t fmsg; // formatted message
792 kmp_str_buf_t buffer;
793
795 // Have to free all possible pre-allocated messages
796 // sent in through message and args
797 __kmp_str_free(&message.str);
798 for (;;) {
799 message = va_arg(args, kmp_msg_t);
800 if (message.type == kmp_mt_dummy && message.str == NULL) {
801 break;
802 }
803 __kmp_str_free(&message.str);
804 }
805 return; // no reason to form a string in order to not print it
806 }
807
808 __kmp_str_buf_init(&buffer);
809
810 // Format the primary message.
811 switch (severity) {
812 case kmp_ms_inform: {
813 format = kmp_i18n_fmt_Info;
814 } break;
815 case kmp_ms_warning: {
816 format = kmp_i18n_fmt_Warning;
817 } break;
818 case kmp_ms_fatal: {
819 format = kmp_i18n_fmt_Fatal;
820 } break;
821 default: {
823 }
824 }
825 fmsg = __kmp_msg_format(format, message.num, message.str);
826 __kmp_str_free(&message.str);
827 __kmp_str_buf_cat(&buffer, fmsg.str, fmsg.len);
828 __kmp_str_free(&fmsg.str);
829
830 // Format other messages.
831 for (;;) {
832 message = va_arg(args, kmp_msg_t);
833 if (message.type == kmp_mt_dummy && message.str == NULL) {
834 break;
835 }
836 switch (message.type) {
837 case kmp_mt_hint: {
838 format = kmp_i18n_fmt_Hint;
839 // we cannot skip %1$ and only use %2$ to print the message without the
840 // number
841 fmsg = __kmp_msg_format(format, message.str);
842 } break;
843 case kmp_mt_syserr: {
844 format = kmp_i18n_fmt_SysErr;
845 fmsg = __kmp_msg_format(format, message.num, message.str);
846 } break;
847 default: {
849 }
850 }
851 __kmp_str_free(&message.str);
852 __kmp_str_buf_cat(&buffer, fmsg.str, fmsg.len);
853 __kmp_str_free(&fmsg.str);
854 }
855
856 // Print formatted messages.
857 // This lock prevents multiple fatal errors on the same problem.
858 // __kmp_acquire_bootstrap_lock( & lock ); // GEH - This lock causing tests
859 // to hang on OS X*.
860 __kmp_printf("%s", buffer.str);
861 __kmp_str_buf_free(&buffer);
862
863 // __kmp_release_bootstrap_lock( & lock ); // GEH - this lock causing tests
864 // to hang on OS X*.
865
866} // __kmp_msg
867
868void __kmp_msg(kmp_msg_severity_t severity, kmp_msg_t message, ...) {
869 va_list args;
870 va_start(args, message);
871 __kmp_msg(severity, message, args);
872 va_end(args);
873}
874
875void __kmp_fatal(kmp_msg_t message, ...) {
876 va_list args;
877 va_start(args, message);
878 __kmp_msg(kmp_ms_fatal, message, args);
879 va_end(args);
880#if KMP_OS_WINDOWS
881 // Delay to give message a chance to appear before reaping
883#endif
885} // __kmp_fatal
886
887// end of file //
int result[2]
__itt_string_handle * name
Definition ittnotify.h:3305
void const char const char int ITT_FORMAT __itt_group_sync s
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp end
void * addr
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_id __itt_string_handle __itt_metadata_type size_t void ITT_FORMAT p const __itt_domain __itt_id __itt_string_handle const wchar_t size_t ITT_FORMAT lu const __itt_domain __itt_id __itt_relation __itt_id ITT_FORMAT p const wchar_t int ITT_FORMAT __itt_group_mark d __itt_event ITT_FORMAT __itt_group_mark d void const wchar_t const wchar_t int ITT_FORMAT __itt_group_sync __itt_group_fsync x void const wchar_t int const wchar_t int int ITT_FORMAT __itt_group_sync __itt_group_fsync x void ITT_FORMAT __itt_group_sync __itt_group_fsync p void ITT_FORMAT __itt_group_sync __itt_group_fsync p void size_t ITT_FORMAT lu no args __itt_obj_prop_t __itt_obj_state_t ITT_FORMAT d const char ITT_FORMAT s const char ITT_FORMAT s __itt_frame ITT_FORMAT p __itt_counter ITT_FORMAT p __itt_counter unsigned long long ITT_FORMAT lu __itt_counter unsigned long long ITT_FORMAT lu __itt_counter __itt_clock_domain unsigned long long void ITT_FORMAT p const wchar_t ITT_FORMAT S __itt_mark_type const wchar_t ITT_FORMAT S __itt_mark_type const char ITT_FORMAT s __itt_mark_type ITT_FORMAT d __itt_caller ITT_FORMAT p __itt_caller ITT_FORMAT p no args const __itt_domain __itt_clock_domain unsigned long long __itt_id ITT_FORMAT lu const __itt_domain __itt_clock_domain unsigned long long __itt_id __itt_id void ITT_FORMAT p const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_clock_domain unsigned long long __itt_id __itt_string_handle __itt_scope ITT_FORMAT d const __itt_domain __itt_scope __itt_string_handle const char size_t ITT_FORMAT lu const __itt_domain __itt_clock_domain unsigned long long __itt_relation __itt_id ITT_FORMAT lu __itt_track_group __itt_string_handle __itt_track_group_type ITT_FORMAT d __itt_track ITT_FORMAT p void int const int int const char int ITT_FORMAT d void void const char * path
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long value
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t size
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_id __itt_string_handle __itt_metadata_type size_t void ITT_FORMAT p const __itt_domain __itt_id __itt_string_handle const wchar_t size_t ITT_FORMAT lu const __itt_domain __itt_id __itt_relation __itt_id tail
int __kmp_generate_warnings
#define KMP_INTERNAL_MALLOC(sz)
Definition kmp.h:113
KMP_NORETURN void __kmp_abort_process(void)
void __kmp_thread_sleep(int millis)
#define KMP_INTERNAL_CALLOC(n, sz)
Definition kmp.h:116
#define KMP_INTERNAL_FREE(p)
Definition kmp.h:114
#define KMP_DEBUG_ASSERT(cond)
Definition kmp_debug.h:61
char * __kmp_env_get(char const *name)
static volatile kmp_i18n_cat_status_t status
Definition kmp_i18n.cpp:48
static kmp_bootstrap_lock_t lock
Definition kmp_i18n.cpp:57
static char * sys_error(int err)
Definition kmp_i18n.cpp:671
kmp_msg_t __kmp_msg_null
Definition kmp_i18n.cpp:36
kmp_msg_t __kmp_msg_error_mesg(char const *mesg)
Definition kmp_i18n.cpp:777
static void __kmp_msg(kmp_msg_severity_t severity, kmp_msg_t message, va_list ap)
Definition kmp_i18n.cpp:789
#define get_section(id)
Definition kmp_i18n.cpp:33
enum kmp_i18n_cat_status kmp_i18n_cat_status_t
Definition kmp_i18n.cpp:47
static char const * no_message_available
Definition kmp_i18n.cpp:37
kmp_msg_t __kmp_msg_error_code(int code)
Definition kmp_i18n.cpp:765
static void __kmp_i18n_do_catopen()
void __kmp_i18n_catopen()
Definition kmp_i18n.cpp:62
kmp_i18n_cat_status
Definition kmp_i18n.cpp:42
@ KMP_I18N_CLOSED
Definition kmp_i18n.cpp:43
@ KMP_I18N_OPENED
Definition kmp_i18n.cpp:44
@ KMP_I18N_ABSENT
Definition kmp_i18n.cpp:45
#define get_number(id)
Definition kmp_i18n.cpp:34
kmp_msg_t __kmp_msg_format(unsigned id_arg,...)
Definition kmp_i18n.cpp:624
void __kmp_i18n_dump_catalog(kmp_str_buf_t *buffer)
Definition kmp_i18n.cpp:593
void __kmp_fatal(kmp_msg_t message,...)
Definition kmp_i18n.cpp:875
#define KMP_INFORM(...)
Definition kmp_i18n.h:142
enum kmp_msg_type kmp_msg_type_t
Definition kmp_i18n.h:100
#define KMP_MSG(...)
Definition kmp_i18n.h:121
struct kmp_msg kmp_msg_t
Definition kmp_i18n.h:108
@ kmp_ms_inform
Definition kmp_i18n.h:129
@ kmp_ms_fatal
Definition kmp_i18n.h:131
@ kmp_ms_warning
Definition kmp_i18n.h:130
@ kmp_mt_dummy
Definition kmp_i18n.h:94
@ kmp_mt_syserr
Definition kmp_i18n.h:98
@ kmp_mt_hint
Definition kmp_i18n.h:97
#define KMP_SYSERRCODE(code)
Definition kmp_i18n.h:123
enum kmp_msg_severity kmp_msg_severity_t
Definition kmp_i18n.h:133
char const * __kmp_i18n_catgets(kmp_i18n_id_t id)
#define KMP_FATAL(...)
Definition kmp_i18n.h:146
#define KMP_HNT(...)
Definition kmp_i18n.h:122
void __kmp_i18n_catclose()
#define KMP_ERR
Definition kmp_i18n.h:125
void __kmp_printf(char const *format,...)
Definition kmp_io.cpp:186
static void __kmp_release_bootstrap_lock(kmp_bootstrap_lock_t *lck)
Definition kmp_lock.h:535
kmp_ticket_lock_t kmp_bootstrap_lock_t
Definition kmp_lock.h:521
static int __kmp_acquire_bootstrap_lock(kmp_bootstrap_lock_t *lck)
Definition kmp_lock.h:527
#define KMP_BOOTSTRAP_LOCK_INITIALIZER(lock)
Definition kmp_lock.h:523
@ kmp_warnings_off
Definition kmp_os.h:1241
@ kmp_warnings_low
Definition kmp_os.h:1242
#define CCAST(type, var)
Definition kmp_os.h:291
#define KMP_STRLEN
void __kmp_str_fname_init(kmp_str_fname_t *fname, char const *path)
Definition kmp_str.cpp:246
void __kmp_str_fname_free(kmp_str_fname_t *fname)
Definition kmp_str.cpp:277
void __kmp_str_split(char *str, char delim, char **head, char **tail)
Definition kmp_str.cpp:571
void __kmp_str_buf_clear(kmp_str_buf_t *buffer)
Definition kmp_str.cpp:71
void __kmp_str_buf_detach(kmp_str_buf_t *buffer)
Definition kmp_str.cpp:110
void __kmp_str_buf_reserve(kmp_str_buf_t *buffer, size_t size)
Definition kmp_str.cpp:80
int __kmp_str_buf_vprint(kmp_str_buf_t *buffer, char const *format, va_list args)
Definition kmp_str.cpp:161
void __kmp_str_buf_free(kmp_str_buf_t *buffer)
Definition kmp_str.cpp:123
char * __kmp_str_format(char const *format,...)
Definition kmp_str.cpp:448
void __kmp_str_buf_cat(kmp_str_buf_t *buffer, char const *str, size_t len)
Definition kmp_str.cpp:134
#define args
int __kmp_str_buf_print(kmp_str_buf_t *buffer, char const *format,...)
Definition kmp_str.cpp:221
void __kmp_str_free(char **str)
Definition kmp_str.cpp:494
struct kmp_str_buf kmp_str_buf_t
Definition kmp_str.h:38
#define __kmp_str_buf_init(b)
Definition kmp_str.h:40
int num
Definition kmp_i18n.h:104
kmp_msg_type_t type
Definition kmp_i18n.h:103
size_t len
Definition kmp_i18n.h:106
char * str
Definition kmp_i18n.h:105
char * str
Definition kmp_str.h:33
char * dir
Definition kmp_str.h:69
static int err