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] \
71 void __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);
80 void __kmp_str_buf_reserve(kmp_str_buf_t *buffer,
int 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);
110 void __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);
123 void __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);
134 void __kmp_str_buf_cat(kmp_str_buf_t *buffer,
char const *str,
int len) {
135 KMP_STR_BUF_INVARIANT(buffer);
136 KMP_DEBUG_ASSERT(str != NULL);
137 KMP_DEBUG_ASSERT(len >= 0);
138 __kmp_str_buf_reserve(buffer, buffer->used + len + 1);
139 KMP_MEMCPY(buffer->str + buffer->used, str, len);
140 buffer->str[buffer->used + len] = 0;
142 KMP_STR_BUF_INVARIANT(buffer);
145 void __kmp_str_buf_catbuf(kmp_str_buf_t *dest,
const kmp_str_buf_t *src) {
146 KMP_DEBUG_ASSERT(dest);
147 KMP_DEBUG_ASSERT(src);
148 KMP_STR_BUF_INVARIANT(dest);
149 KMP_STR_BUF_INVARIANT(src);
150 if (!src->str || !src->used)
152 __kmp_str_buf_reserve(dest, dest->used + src->used + 1);
153 KMP_MEMCPY(dest->str + dest->used, src->str, src->used);
154 dest->str[dest->used + src->used] = 0;
155 dest->used += src->used;
156 KMP_STR_BUF_INVARIANT(dest);
160 int __kmp_str_buf_vprint(kmp_str_buf_t *buffer,
char const *format,
163 KMP_STR_BUF_INVARIANT(buffer);
166 int const free = buffer->size - buffer->used;
182 va_copy(_args, args);
183 #define args _args // Substitute args with its copy, _args.
184 #endif // KMP_OS_WINDOWS
185 rc = KMP_VSNPRINTF(buffer->str + buffer->used, free, format, args);
187 #undef args // Remove substitution.
189 #endif // KMP_OS_WINDOWS
193 if (rc >= 0 && rc < free) {
201 size = buffer->used + rc + 1;
204 size = buffer->size * 2;
208 __kmp_str_buf_reserve(buffer, size);
213 KMP_DEBUG_ASSERT(buffer->size > 0);
214 KMP_STR_BUF_INVARIANT(buffer);
219 int __kmp_str_buf_print(kmp_str_buf_t *buffer,
char const *format, ...) {
222 va_start(args, format);
223 rc = __kmp_str_buf_vprint(buffer, format, args);
230 void __kmp_str_buf_print_size(kmp_str_buf_t *buf,
size_t size) {
231 char const *names[] = {
"",
"k",
"M",
"G",
"T",
"P",
"E",
"Z",
"Y"};
232 int const units =
sizeof(names) /
sizeof(
char const *);
235 while ((size % 1024 == 0) && (u + 1 < units)) {
241 __kmp_str_buf_print(buf,
"%" KMP_SIZE_T_SPEC
"%s", size, names[u]);
244 void __kmp_str_fname_init(kmp_str_fname_t *fname,
char const *path) {
252 fname->path = __kmp_str_format(
"%s", path);
256 if (KMP_OS_WINDOWS) {
257 __kmp_str_replace(fname->path,
'\\',
'/');
259 fname->dir = __kmp_str_format(
"%s", fname->path);
260 slash = strrchr(fname->dir,
'/');
261 if (KMP_OS_WINDOWS &&
263 char first = TOLOWER(fname->dir[0]);
264 if (
'a' <= first && first <= 'z' && fname->dir[1] ==
':') {
265 slash = &fname->dir[1];
268 base = (slash == NULL ? fname->dir : slash + 1);
269 fname->base = __kmp_str_format(
"%s", base);
275 void __kmp_str_fname_free(kmp_str_fname_t *fname) {
276 __kmp_str_free(&fname->path);
277 __kmp_str_free(&fname->dir);
278 __kmp_str_free(&fname->base);
281 int __kmp_str_fname_match(kmp_str_fname_t
const *fname,
char const *pattern) {
285 if (pattern != NULL) {
286 kmp_str_fname_t ptrn;
287 __kmp_str_fname_init(&ptrn, pattern);
288 dir_match = strcmp(ptrn.dir,
"*/") == 0 ||
289 (fname->dir != NULL && __kmp_str_eqf(fname->dir, ptrn.dir));
290 base_match = strcmp(ptrn.base,
"*") == 0 ||
291 (fname->base != NULL && __kmp_str_eqf(fname->base, ptrn.base));
292 __kmp_str_fname_free(&ptrn);
295 return dir_match && base_match;
298 kmp_str_loc_t __kmp_str_loc_init(
char const *psource,
int init_fname) {
307 if (psource != NULL) {
314 loc._bulk = __kmp_str_format(
"%s", psource);
318 __kmp_str_split(str,
';', &dummy, &str);
319 __kmp_str_split(str,
';', &loc.file, &str);
320 __kmp_str_split(str,
';', &loc.func, &str);
321 __kmp_str_split(str,
';', &line, &str);
322 __kmp_str_split(str,
';', &col, &str);
326 loc.line = atoi(line);
339 __kmp_str_fname_init(&loc.fname, init_fname ? loc.file : NULL);
344 void __kmp_str_loc_free(kmp_str_loc_t *loc) {
345 __kmp_str_fname_free(&loc->fname);
346 __kmp_str_free(&(loc->_bulk));
361 result = (_stricmp(lhs, rhs) == 0);
363 result = (strcmp(lhs, rhs) == 0);
399 char *__kmp_str_format(
409 buffer = (
char *)KMP_INTERNAL_MALLOC(size);
410 if (buffer == NULL) {
411 KMP_FATAL(MemoryAllocFailed);
416 va_start(args, format);
417 rc = KMP_VSNPRINTF(buffer, size, format, args);
421 if (rc >= 0 && rc < size) {
436 buffer = (
char *)KMP_INTERNAL_REALLOC(buffer, size);
437 if (buffer == NULL) {
438 KMP_FATAL(MemoryAllocFailed);
445 void __kmp_str_free(
char **str) {
446 KMP_DEBUG_ASSERT(str != NULL);
447 KMP_INTERNAL_FREE(*str);
456 int __kmp_str_match(
char const *target,
int len,
char const *data) {
458 if (target == NULL || data == NULL) {
461 for (i = 0; target[i] && data[i]; ++i) {
462 if (TOLOWER(target[i]) != TOLOWER(data[i])) {
466 return ((len > 0) ? i >= len : (!target[i] && (len || !data[i])));
469 int __kmp_str_match_false(
char const *data) {
471 __kmp_str_match(
"false", 1, data) || __kmp_str_match(
"off", 2, data) ||
472 __kmp_str_match(
"0", 1, data) || __kmp_str_match(
".false.", 2, data) ||
473 __kmp_str_match(
".f.", 2, data) || __kmp_str_match(
"no", 1, data) ||
474 __kmp_str_match(
"disabled", 0, data);
478 int __kmp_str_match_true(
char const *data) {
480 __kmp_str_match(
"true", 1, data) || __kmp_str_match(
"on", 2, data) ||
481 __kmp_str_match(
"1", 1, data) || __kmp_str_match(
".true.", 2, data) ||
482 __kmp_str_match(
".t.", 2, data) || __kmp_str_match(
"yes", 1, data) ||
483 __kmp_str_match(
"enabled", 0, data);
487 void __kmp_str_replace(
char *str,
char search_for,
char replace_with) {
490 found = strchr(str, search_for);
492 *found = replace_with;
493 found = strchr(found + 1, search_for);
497 void __kmp_str_split(
char *str,
505 char *ptr = strchr(str, delim);
521 char *__kmp_str_token(
532 *buf += strspn(*buf, delim);
535 *buf += strcspn(*buf, delim);
543 token = strtok_r(str, delim, buf);
548 int __kmp_str_to_int(
char const *str,
char sentinel) {
554 for (t = str; *t !=
'\0'; ++t) {
555 if (*t < '0' || *t >
'9')
557 result = (result * 10) + (*t -
'0');
577 factor = (1024 * 1024);
586 if (result > (INT_MAX / factor))
591 return (*t != 0 ? 0 : result);
601 void __kmp_str_to_size(
615 KMP_DEBUG_ASSERT(str != NULL);
618 while (str[i] ==
' ' || str[i] ==
'\t') {
623 if (str[i] <
'0' || str[i] >
'9') {
624 *error = KMP_I18N_STR(NotANumber);
628 digit = str[i] -
'0';
629 overflow = overflow || (value > (KMP_SIZE_T_MAX - digit) / 10);
630 value = (value * 10) + digit;
632 }
while (str[i] >=
'0' && str[i] <=
'9');
635 while (str[i] ==
' ' || str[i] ==
'\t') {
640 #define _case(ch, exp) \
642 case ch - ('a' - 'A'): { \
643 size_t shift = (exp)*10; \
645 if (shift < sizeof(size_t) * 8) { \
646 factor = (size_t)(1) << shift; \
663 if (str[i] ==
'b' || str[i] ==
'B') {
669 if (!(str[i] ==
' ' || str[i] ==
'\t' || str[i] == 0)) {
670 *error = KMP_I18N_STR(BadUnit);
679 overflow = overflow || (value > (KMP_SIZE_T_MAX / factor));
683 while (str[i] ==
' ' || str[i] ==
'\t') {
688 *error = KMP_I18N_STR(IllegalCharacters);
693 *error = KMP_I18N_STR(ValueTooLarge);
694 *out = KMP_SIZE_T_MAX;
702 void __kmp_str_to_uint(
712 KMP_DEBUG_ASSERT(str != NULL);
715 while (str[i] ==
' ' || str[i] ==
'\t') {
720 if (str[i] <
'0' || str[i] >
'9') {
721 *error = KMP_I18N_STR(NotANumber);
725 digit = str[i] -
'0';
726 overflow = overflow || (value > (KMP_SIZE_T_MAX - digit) / 10);
727 value = (value * 10) + digit;
729 }
while (str[i] >=
'0' && str[i] <=
'9');
732 while (str[i] ==
' ' || str[i] ==
'\t') {
737 *error = KMP_I18N_STR(IllegalCharacters);
742 *error = KMP_I18N_STR(ValueTooLarge);
743 *out = (kmp_uint64)-1;