59#define KMP_STR_BUF_INVARIANT(b) \
61 KMP_DEBUG_ASSERT((b)->str != NULL); \
62 KMP_DEBUG_ASSERT((b)->size >= sizeof((b)->bulk)); \
63 KMP_DEBUG_ASSERT((b)->size % sizeof((b)->bulk) == 0); \
64 KMP_DEBUG_ASSERT((unsigned)(b)->used < (b)->size); \
66 (b)->size == sizeof((b)->bulk) ? (b)->str == &(b)->bulk[0] : 1); \
67 KMP_DEBUG_ASSERT((b)->size > sizeof((b)->bulk) ? (b)->str != &(b)->bulk[0] \
71void __kmp_str_buf_clear(kmp_str_buf_t *buffer) {
72 KMP_STR_BUF_INVARIANT(buffer);
73 if (buffer->used > 0) {
77 KMP_STR_BUF_INVARIANT(buffer);
80void __kmp_str_buf_reserve(kmp_str_buf_t *buffer,
size_t size) {
81 KMP_STR_BUF_INVARIANT(buffer);
82 KMP_DEBUG_ASSERT(size >= 0);
84 if (buffer->size < (
unsigned int)size) {
88 }
while (buffer->size < (
unsigned int)size);
91 if (buffer->str == &buffer->bulk[0]) {
92 buffer->str = (
char *)KMP_INTERNAL_MALLOC(buffer->size);
93 if (buffer->str == NULL) {
94 KMP_FATAL(MemoryAllocFailed);
96 KMP_MEMCPY_S(buffer->str, buffer->size, buffer->bulk, buffer->used + 1);
98 buffer->str = (
char *)KMP_INTERNAL_REALLOC(buffer->str, buffer->size);
99 if (buffer->str == NULL) {
100 KMP_FATAL(MemoryAllocFailed);
105 KMP_DEBUG_ASSERT(buffer->size > 0);
106 KMP_DEBUG_ASSERT(buffer->size >= (
unsigned)size);
107 KMP_STR_BUF_INVARIANT(buffer);
110void __kmp_str_buf_detach(kmp_str_buf_t *buffer) {
111 KMP_STR_BUF_INVARIANT(buffer);
114 if (buffer->size <=
sizeof(buffer->bulk)) {
115 buffer->str = (
char *)KMP_INTERNAL_MALLOC(buffer->size);
116 if (buffer->str == NULL) {
117 KMP_FATAL(MemoryAllocFailed);
119 KMP_MEMCPY_S(buffer->str, buffer->size, buffer->bulk, buffer->used + 1);
123void __kmp_str_buf_free(kmp_str_buf_t *buffer) {
124 KMP_STR_BUF_INVARIANT(buffer);
125 if (buffer->size >
sizeof(buffer->bulk)) {
126 KMP_INTERNAL_FREE(buffer->str);
128 buffer->str = buffer->bulk;
129 buffer->size =
sizeof(buffer->bulk);
131 KMP_STR_BUF_INVARIANT(buffer);
134void __kmp_str_buf_cat(kmp_str_buf_t *buffer,
char const *str,
size_t len) {
135 KMP_STR_BUF_INVARIANT(buffer);
136 KMP_DEBUG_ASSERT(str != NULL);
137 KMP_DEBUG_ASSERT(len >= 0);
139 __kmp_str_buf_reserve(buffer, buffer->used + len + 1);
140 buffer->str[buffer->used] =
'\0';
141 KMP_STRNCAT_S(buffer->str + buffer->used, len + 1, str, len);
142 __kmp_type_convert(buffer->used + len, &(buffer->used));
143 KMP_STR_BUF_INVARIANT(buffer);
146void __kmp_str_buf_catbuf(kmp_str_buf_t *dest,
const kmp_str_buf_t *src) {
147 KMP_DEBUG_ASSERT(dest);
148 KMP_DEBUG_ASSERT(src);
149 KMP_STR_BUF_INVARIANT(dest);
150 KMP_STR_BUF_INVARIANT(src);
151 if (!src->str || !src->used)
153 __kmp_str_buf_reserve(dest, dest->used + src->used + 1);
154 dest->str[dest->used] =
'\0';
155 KMP_STRNCAT_S(dest->str + dest->used, src->used + 1, src->str, src->used);
156 dest->used += src->used;
157 KMP_STR_BUF_INVARIANT(dest);
161int __kmp_str_buf_vprint(kmp_str_buf_t *buffer,
char const *format,
164 KMP_STR_BUF_INVARIANT(buffer);
167 int const free = buffer->size - buffer->used;
184 va_copy(_args, args);
187 rc = KMP_VSNPRINTF(buffer->str + buffer->used, free, format, args);
195 if (rc >= 0 && rc < free) {
203 size = buffer->used + rc + 1;
206 size = buffer->size * 2;
210 __kmp_str_buf_reserve(buffer, size);
215 KMP_DEBUG_ASSERT(buffer->size > 0);
216 KMP_STR_BUF_INVARIANT(buffer);
221int __kmp_str_buf_print(kmp_str_buf_t *buffer,
char const *format, ...) {
224 va_start(args, format);
225 rc = __kmp_str_buf_vprint(buffer, format, args);
232void __kmp_str_buf_print_size(kmp_str_buf_t *buf,
size_t size) {
233 char const *names[] = {
"",
"k",
"M",
"G",
"T",
"P",
"E",
"Z",
"Y"};
234 int const units =
sizeof(names) /
sizeof(
char const *);
237 while ((size % 1024 == 0) && (u + 1 < units)) {
243 __kmp_str_buf_print(buf,
"%" KMP_SIZE_T_SPEC
"%s", size, names[u]);
246void __kmp_str_fname_init(kmp_str_fname_t *fname,
char const *path) {
254 fname->path = __kmp_str_format(
"%s", path);
258 if (KMP_OS_WINDOWS) {
259 __kmp_str_replace(fname->path,
'\\',
'/');
261 fname->dir = __kmp_str_format(
"%s", fname->path);
262 slash = strrchr(fname->dir,
'/');
263 if (KMP_OS_WINDOWS &&
265 char first = (char)TOLOWER(fname->dir[0]);
266 if (
'a' <= first && first <=
'z' && fname->dir[1] ==
':') {
267 slash = &fname->dir[1];
270 base = (slash == NULL ? fname->dir : slash + 1);
271 fname->base = __kmp_str_format(
"%s", base);
277void __kmp_str_fname_free(kmp_str_fname_t *fname) {
278 __kmp_str_free(&fname->path);
279 __kmp_str_free(&fname->dir);
280 __kmp_str_free(&fname->base);
283int __kmp_str_fname_match(kmp_str_fname_t
const *fname,
char const *pattern) {
287 if (pattern != NULL) {
288 kmp_str_fname_t ptrn;
289 __kmp_str_fname_init(&ptrn, pattern);
290 dir_match = strcmp(ptrn.dir,
"*/") == 0 ||
291 (fname->dir != NULL && __kmp_str_eqf(fname->dir, ptrn.dir));
292 base_match = strcmp(ptrn.base,
"*") == 0 ||
293 (fname->base != NULL && __kmp_str_eqf(fname->base, ptrn.base));
294 __kmp_str_fname_free(&ptrn);
297 return dir_match && base_match;
305void __kmp_str_loc_numbers(
char const *Psource,
int *LineBeg,
308 KMP_DEBUG_ASSERT(LineBeg);
309 KMP_DEBUG_ASSERT(LineEndOrCol);
314 KMP_DEBUG_ASSERT(Psource);
316 Str = strchr(CCAST(
char *, Psource),
';');
318 Str = strchr(Psource,
';');
323 Str = strchr(Str + 1,
';');
327 Str = strchr(Str + 1,
';');
331 *LineBeg = atoi(Str + 1);
333 Str = strchr(Str + 1,
';');
340 *LineEndOrCol = atoi(Str + 1);
347kmp_str_loc_t __kmp_str_loc_init(
char const *psource,
bool init_fname) {
356 if (psource != NULL) {
363 loc._bulk = __kmp_str_format(
"%s", psource);
367 __kmp_str_split(str,
';', &dummy, &str);
368 __kmp_str_split(str,
';', &loc.file, &str);
369 __kmp_str_split(str,
';', &loc.func, &str);
370 __kmp_str_split(str,
';', &line, &str);
371 __kmp_str_split(str,
';', &col, &str);
375 loc.line = atoi(line);
388 __kmp_str_fname_init(&loc.fname, init_fname ? loc.file : NULL);
393void __kmp_str_loc_free(kmp_str_loc_t *loc) {
394 __kmp_str_fname_free(&loc->fname);
395 __kmp_str_free(&(loc->_bulk));
410 result = (_stricmp(lhs, rhs) == 0);
412 result = (strcmp(lhs, rhs) == 0);
448char *__kmp_str_format(
458 buffer = (
char *)KMP_INTERNAL_MALLOC(size);
459 if (buffer == NULL) {
460 KMP_FATAL(MemoryAllocFailed);
465 va_start(args, format);
466 rc = KMP_VSNPRINTF(buffer, size, format, args);
470 if (rc >= 0 && rc < size) {
485 buffer = (
char *)KMP_INTERNAL_REALLOC(buffer, size);
486 if (buffer == NULL) {
487 KMP_FATAL(MemoryAllocFailed);
494void __kmp_str_free(
char **str) {
495 KMP_DEBUG_ASSERT(str != NULL);
496 KMP_INTERNAL_FREE(*str);
505int __kmp_str_match(
char const *target,
int len,
char const *data) {
507 if (target == NULL || data == NULL) {
510 for (i = 0; target[i] && data[i]; ++i) {
511 if (TOLOWER(target[i]) != TOLOWER(data[i])) {
515 return ((len > 0) ? i >= len : (!target[i] && (len || !data[i])));
520bool __kmp_str_contains(
char const *target,
int len,
char const *data) {
521 int i = 0, j = 0, start = 0;
522 if (target == NULL || data == NULL) {
528 if (TOLOWER(target[i]) != TOLOWER(data[j])) {
543int __kmp_str_match_false(
char const *data) {
545 __kmp_str_match(
"false", 1, data) || __kmp_str_match(
"off", 2, data) ||
546 __kmp_str_match(
"0", 1, data) || __kmp_str_match(
".false.", 2, data) ||
547 __kmp_str_match(
".f.", 2, data) || __kmp_str_match(
"no", 1, data) ||
548 __kmp_str_match(
"disabled", 0, data);
552int __kmp_str_match_true(
char const *data) {
554 __kmp_str_match(
"true", 1, data) || __kmp_str_match(
"on", 2, data) ||
555 __kmp_str_match(
"1", 1, data) || __kmp_str_match(
".true.", 2, data) ||
556 __kmp_str_match(
".t.", 2, data) || __kmp_str_match(
"yes", 1, data) ||
557 __kmp_str_match(
"enabled", 0, data);
561void __kmp_str_replace(
char *str,
char search_for,
char replace_with) {
564 found = strchr(str, search_for);
566 *found = replace_with;
567 found = strchr(found + 1, search_for);
571void __kmp_str_split(
char *str,
579 char *ptr = strchr(str, delim);
595char *__kmp_str_token(
606 *buf += strspn(*buf, delim);
609 *buf += strcspn(*buf, delim);
617 token = strtok_r(str, delim, buf);
622int __kmp_basic_str_to_int(
char const *str) {
628 for (t = str; *t !=
'\0'; ++t) {
629 if (*t <
'0' || *t >
'9')
631 result = (result * 10) + (*t -
'0');
637int __kmp_str_to_int(
char const *str,
char sentinel) {
643 for (t = str; *t !=
'\0'; ++t) {
644 if (*t <
'0' || *t >
'9')
646 result = (result * 10) + (*t -
'0');
666 factor = (1024 * 1024);
675 if (result > (INT_MAX / factor))
680 return (*t != 0 ? 0 : result);
690void __kmp_str_to_size(
704 KMP_DEBUG_ASSERT(str != NULL);
707 while (str[i] ==
' ' || str[i] ==
'\t') {
712 if (str[i] <
'0' || str[i] >
'9') {
713 *error = KMP_I18N_STR(NotANumber);
717 digit = str[i] -
'0';
718 overflow = overflow || (value > (KMP_SIZE_T_MAX - digit) / 10);
719 value = (value * 10) + digit;
721 }
while (str[i] >=
'0' && str[i] <=
'9');
724 while (str[i] ==
' ' || str[i] ==
'\t') {
729#define _case(ch, exp) \
731 case ch - ('a' - 'A'): { \
732 size_t shift = (exp)*10; \
734 if (shift < sizeof(size_t) * 8) { \
735 factor = (size_t)(1) << shift; \
752 if (str[i] ==
'b' || str[i] ==
'B') {
758 if (!(str[i] ==
' ' || str[i] ==
'\t' || str[i] == 0)) {
759 *error = KMP_I18N_STR(BadUnit);
768 overflow = overflow || (value > (KMP_SIZE_T_MAX / factor));
772 while (str[i] ==
' ' || str[i] ==
'\t') {
777 *error = KMP_I18N_STR(IllegalCharacters);
782 *error = KMP_I18N_STR(ValueTooLarge);
783 *out = KMP_SIZE_T_MAX;
791void __kmp_str_to_uint(
801 KMP_DEBUG_ASSERT(str != NULL);
804 while (str[i] ==
' ' || str[i] ==
'\t') {
809 if (str[i] <
'0' || str[i] >
'9') {
810 *error = KMP_I18N_STR(NotANumber);
814 digit = str[i] -
'0';
815 overflow = overflow || (value > (KMP_SIZE_T_MAX - digit) / 10);
816 value = (value * 10) + digit;
818 }
while (str[i] >=
'0' && str[i] <=
'9');
821 while (str[i] ==
' ' || str[i] ==
'\t') {
826 *error = KMP_I18N_STR(IllegalCharacters);
831 *error = KMP_I18N_STR(ValueTooLarge);
832 *out = (kmp_uint64)-1;