blob: 04c4056a56333afaa1e28653839d1dce0245f8c1 [file] [log] [blame]
Jim Cownie5e8470a2013-09-27 10:38:44 +00001/*
Jonathan Peytonde4749b2016-12-14 23:01:24 +00002 * kmp_str.cpp -- String manipulation routines.
Jim Cownie5e8470a2013-09-27 10:38:44 +00003 */
4
Jim Cownie5e8470a2013-09-27 10:38:44 +00005//===----------------------------------------------------------------------===//
6//
7// The LLVM Compiler Infrastructure
8//
9// This file is dual licensed under the MIT and the University of Illinois Open
10// Source Licenses. See LICENSE.txt for details.
11//
12//===----------------------------------------------------------------------===//
13
Jim Cownie5e8470a2013-09-27 10:38:44 +000014#include "kmp_str.h"
15
Jonathan Peyton30419822017-05-12 18:01:32 +000016#include <stdarg.h> // va_*
17#include <stdio.h> // vsnprintf()
18#include <stdlib.h> // malloc(), realloc()
Jim Cownie5e8470a2013-09-27 10:38:44 +000019
20#include "kmp.h"
21#include "kmp_i18n.h"
22
Jonathan Peyton30419822017-05-12 18:01:32 +000023/* String buffer.
Jim Cownie5e8470a2013-09-27 10:38:44 +000024
Jonathan Peyton30419822017-05-12 18:01:32 +000025 Usage:
Jim Cownie5e8470a2013-09-27 10:38:44 +000026
Jonathan Peyton30419822017-05-12 18:01:32 +000027 // Declare buffer and initialize it.
28 kmp_str_buf_t buffer;
29 __kmp_str_buf_init( & buffer );
Jim Cownie5e8470a2013-09-27 10:38:44 +000030
Jonathan Peyton30419822017-05-12 18:01:32 +000031 // Print to buffer.
32 __kmp_str_buf_print(& buffer, "Error in file \"%s\" line %d\n", "foo.c", 12);
33 __kmp_str_buf_print(& buffer, " <%s>\n", line);
Jim Cownie5e8470a2013-09-27 10:38:44 +000034
Jonathan Peyton30419822017-05-12 18:01:32 +000035 // Use buffer contents. buffer.str is a pointer to data, buffer.used is a
36 // number of printed characters (not including terminating zero).
37 write( fd, buffer.str, buffer.used );
Jim Cownie5e8470a2013-09-27 10:38:44 +000038
Jonathan Peyton30419822017-05-12 18:01:32 +000039 // Free buffer.
40 __kmp_str_buf_free( & buffer );
Jim Cownie5e8470a2013-09-27 10:38:44 +000041
Jonathan Peyton30419822017-05-12 18:01:32 +000042 // Alternatively, you can detach allocated memory from buffer:
43 __kmp_str_buf_detach( & buffer );
44 return buffer.str; // That memory should be freed eventually.
Jim Cownie5e8470a2013-09-27 10:38:44 +000045
Jonathan Peyton30419822017-05-12 18:01:32 +000046 Notes:
Jim Cownie5e8470a2013-09-27 10:38:44 +000047
Jonathan Peyton30419822017-05-12 18:01:32 +000048 * Buffer users may use buffer.str and buffer.used. Users should not change
49 any fields of buffer directly.
50 * buffer.str is never NULL. If buffer is empty, buffer.str points to empty
51 string ("").
52 * For performance reasons, buffer uses stack memory (buffer.bulk) first. If
53 stack memory is exhausted, buffer allocates memory on heap by malloc(), and
54 reallocates it by realloc() as amount of used memory grows.
55 * Buffer doubles amount of allocated memory each time it is exhausted.
Jim Cownie5e8470a2013-09-27 10:38:44 +000056*/
57
58// TODO: __kmp_str_buf_print() can use thread local memory allocator.
59
Jonathan Peyton30419822017-05-12 18:01:32 +000060#define KMP_STR_BUF_INVARIANT(b) \
61 { \
62 KMP_DEBUG_ASSERT((b)->str != NULL); \
63 KMP_DEBUG_ASSERT((b)->size >= sizeof((b)->bulk)); \
64 KMP_DEBUG_ASSERT((b)->size % sizeof((b)->bulk) == 0); \
65 KMP_DEBUG_ASSERT((unsigned)(b)->used < (b)->size); \
66 KMP_DEBUG_ASSERT( \
67 (b)->size == sizeof((b)->bulk) ? (b)->str == &(b)->bulk[0] : 1); \
68 KMP_DEBUG_ASSERT((b)->size > sizeof((b)->bulk) ? (b)->str != &(b)->bulk[0] \
69 : 1); \
70 }
Jim Cownie5e8470a2013-09-27 10:38:44 +000071
Jonathan Peyton30419822017-05-12 18:01:32 +000072void __kmp_str_buf_clear(kmp_str_buf_t *buffer) {
73 KMP_STR_BUF_INVARIANT(buffer);
74 if (buffer->used > 0) {
75 buffer->used = 0;
76 buffer->str[0] = 0;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +000077 }
Jonathan Peyton30419822017-05-12 18:01:32 +000078 KMP_STR_BUF_INVARIANT(buffer);
Jim Cownie5e8470a2013-09-27 10:38:44 +000079} // __kmp_str_buf_clear
80
Jonathan Peyton30419822017-05-12 18:01:32 +000081void __kmp_str_buf_reserve(kmp_str_buf_t *buffer, int size) {
82 KMP_STR_BUF_INVARIANT(buffer);
83 KMP_DEBUG_ASSERT(size >= 0);
Jim Cownie5e8470a2013-09-27 10:38:44 +000084
Jonathan Peyton30419822017-05-12 18:01:32 +000085 if (buffer->size < (unsigned int)size) {
86 // Calculate buffer size.
87 do {
88 buffer->size *= 2;
89 } while (buffer->size < (unsigned int)size);
Jim Cownie5e8470a2013-09-27 10:38:44 +000090
Jonathan Peyton30419822017-05-12 18:01:32 +000091 // Enlarge buffer.
92 if (buffer->str == &buffer->bulk[0]) {
93 buffer->str = (char *)KMP_INTERNAL_MALLOC(buffer->size);
94 if (buffer->str == NULL) {
95 KMP_FATAL(MemoryAllocFailed);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +000096 }
Jonathan Peyton30419822017-05-12 18:01:32 +000097 KMP_MEMCPY_S(buffer->str, buffer->size, buffer->bulk, buffer->used + 1);
98 } else {
99 buffer->str = (char *)KMP_INTERNAL_REALLOC(buffer->str, buffer->size);
100 if (buffer->str == NULL) {
101 KMP_FATAL(MemoryAllocFailed);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000102 }
103 }
104 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000105
Jonathan Peyton30419822017-05-12 18:01:32 +0000106 KMP_DEBUG_ASSERT(buffer->size > 0);
107 KMP_DEBUG_ASSERT(buffer->size >= (unsigned)size);
108 KMP_STR_BUF_INVARIANT(buffer);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000109} // __kmp_str_buf_reserve
110
Jonathan Peyton30419822017-05-12 18:01:32 +0000111void __kmp_str_buf_detach(kmp_str_buf_t *buffer) {
112 KMP_STR_BUF_INVARIANT(buffer);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000113
Jonathan Peyton30419822017-05-12 18:01:32 +0000114 // If internal bulk is used, allocate memory and copy it.
115 if (buffer->size <= sizeof(buffer->bulk)) {
116 buffer->str = (char *)KMP_INTERNAL_MALLOC(buffer->size);
117 if (buffer->str == NULL) {
118 KMP_FATAL(MemoryAllocFailed);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000119 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000120 KMP_MEMCPY_S(buffer->str, buffer->size, buffer->bulk, buffer->used + 1);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000121 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000122} // __kmp_str_buf_detach
123
Jonathan Peyton30419822017-05-12 18:01:32 +0000124void __kmp_str_buf_free(kmp_str_buf_t *buffer) {
125 KMP_STR_BUF_INVARIANT(buffer);
126 if (buffer->size > sizeof(buffer->bulk)) {
127 KMP_INTERNAL_FREE(buffer->str);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000128 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000129 buffer->str = buffer->bulk;
130 buffer->size = sizeof(buffer->bulk);
131 buffer->used = 0;
132 KMP_STR_BUF_INVARIANT(buffer);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000133} // __kmp_str_buf_free
134
Jonathan Peyton30419822017-05-12 18:01:32 +0000135void __kmp_str_buf_cat(kmp_str_buf_t *buffer, char const *str, int len) {
136 KMP_STR_BUF_INVARIANT(buffer);
137 KMP_DEBUG_ASSERT(str != NULL);
138 KMP_DEBUG_ASSERT(len >= 0);
139 __kmp_str_buf_reserve(buffer, buffer->used + len + 1);
140 KMP_MEMCPY(buffer->str + buffer->used, str, len);
141 buffer->str[buffer->used + len] = 0;
142 buffer->used += len;
143 KMP_STR_BUF_INVARIANT(buffer);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000144} // __kmp_str_buf_cat
145
Jonathan Peyton30419822017-05-12 18:01:32 +0000146void __kmp_str_buf_vprint(kmp_str_buf_t *buffer, char const *format,
147 va_list args) {
148 KMP_STR_BUF_INVARIANT(buffer);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000149
Jonathan Peyton30419822017-05-12 18:01:32 +0000150 for (;;) {
151 int const free = buffer->size - buffer->used;
152 int rc;
153 int size;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000154
Jonathan Peyton30419822017-05-12 18:01:32 +0000155 // Try to format string.
156 {
157/* On Linux* OS Intel(R) 64, vsnprintf() modifies args argument, so vsnprintf()
158 crashes if it is called for the second time with the same args. To prevent
159 the crash, we have to pass a fresh intact copy of args to vsnprintf() on each
160 iteration.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000161
Jonathan Peyton30419822017-05-12 18:01:32 +0000162 Unfortunately, standard va_copy() macro is not available on Windows* OS.
163 However, it seems vsnprintf() does not modify args argument on Windows* OS.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000164*/
165
Jonathan Peyton30419822017-05-12 18:01:32 +0000166#if !KMP_OS_WINDOWS
167 va_list _args;
Jonathan Peyton04477082017-08-19 23:53:36 +0000168 va_copy(_args, args); // Make copy of args.
Jonathan Peyton30419822017-05-12 18:01:32 +0000169#define args _args // Substitute args with its copy, _args.
170#endif // KMP_OS_WINDOWS
171 rc = KMP_VSNPRINTF(buffer->str + buffer->used, free, format, args);
172#if !KMP_OS_WINDOWS
173#undef args // Remove substitution.
174 va_end(_args);
175#endif // KMP_OS_WINDOWS
176 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000177
Jonathan Peyton30419822017-05-12 18:01:32 +0000178 // No errors, string has been formatted.
179 if (rc >= 0 && rc < free) {
180 buffer->used += rc;
181 break;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000182 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000183
Jonathan Peyton30419822017-05-12 18:01:32 +0000184 // Error occurred, buffer is too small.
185 if (rc >= 0) {
186 // C99-conforming implementation of vsnprintf returns required buffer size
187 size = buffer->used + rc + 1;
188 } else {
189 // Older implementations just return -1. Double buffer size.
190 size = buffer->size * 2;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000191 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000192
Jonathan Peyton30419822017-05-12 18:01:32 +0000193 // Enlarge buffer.
194 __kmp_str_buf_reserve(buffer, size);
195
196 // And try again.
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000197 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000198
199 KMP_DEBUG_ASSERT(buffer->size > 0);
200 KMP_STR_BUF_INVARIANT(buffer);
201} // __kmp_str_buf_vprint
202
203void __kmp_str_buf_print(kmp_str_buf_t *buffer, char const *format, ...) {
204 va_list args;
205 va_start(args, format);
206 __kmp_str_buf_vprint(buffer, format, args);
207 va_end(args);
208} // __kmp_str_buf_print
209
210/* The function prints specified size to buffer. Size is expressed using biggest
211 possible unit, for example 1024 is printed as "1k". */
212void __kmp_str_buf_print_size(kmp_str_buf_t *buf, size_t size) {
213 char const *names[] = {"", "k", "M", "G", "T", "P", "E", "Z", "Y"};
214 int const units = sizeof(names) / sizeof(char const *);
215 int u = 0;
216 if (size > 0) {
217 while ((size % 1024 == 0) && (u + 1 < units)) {
218 size = size / 1024;
219 ++u;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000220 }
221 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000222
223 __kmp_str_buf_print(buf, "%" KMP_SIZE_T_SPEC "%s", size, names[u]);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000224} // __kmp_str_buf_print_size
225
Jonathan Peyton30419822017-05-12 18:01:32 +0000226void __kmp_str_fname_init(kmp_str_fname_t *fname, char const *path) {
227 fname->path = NULL;
228 fname->dir = NULL;
229 fname->base = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000230
Jonathan Peyton30419822017-05-12 18:01:32 +0000231 if (path != NULL) {
232 char *slash = NULL; // Pointer to the last character of dir.
233 char *base = NULL; // Pointer to the beginning of basename.
234 fname->path = __kmp_str_format("%s", path);
235 // Original code used strdup() function to copy a string, but on Windows* OS
236 // Intel(R) 64 it causes assertioon id debug heap, so I had to replace
237 // strdup with __kmp_str_format().
238 if (KMP_OS_WINDOWS) {
239 __kmp_str_replace(fname->path, '\\', '/');
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000240 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000241 fname->dir = __kmp_str_format("%s", fname->path);
242 slash = strrchr(fname->dir, '/');
243 if (KMP_OS_WINDOWS &&
244 slash == NULL) { // On Windows* OS, if slash not found,
245 char first = TOLOWER(fname->dir[0]); // look for drive.
246 if ('a' <= first && first <= 'z' && fname->dir[1] == ':') {
247 slash = &fname->dir[1];
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000248 }
249 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000250 base = (slash == NULL ? fname->dir : slash + 1);
251 fname->base = __kmp_str_format("%s", base); // Copy basename
252 *base = 0; // and truncate dir.
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000253 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000254
255} // kmp_str_fname_init
256
Jonathan Peyton30419822017-05-12 18:01:32 +0000257void __kmp_str_fname_free(kmp_str_fname_t *fname) {
Jonas Hahnfeldaeb40ad2017-11-09 15:52:25 +0000258 __kmp_str_free(&fname->path);
259 __kmp_str_free(&fname->dir);
260 __kmp_str_free(&fname->base);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000261} // kmp_str_fname_free
262
Jonathan Peyton30419822017-05-12 18:01:32 +0000263int __kmp_str_fname_match(kmp_str_fname_t const *fname, char const *pattern) {
264 int dir_match = 1;
265 int base_match = 1;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000266
Jonathan Peyton30419822017-05-12 18:01:32 +0000267 if (pattern != NULL) {
268 kmp_str_fname_t ptrn;
269 __kmp_str_fname_init(&ptrn, pattern);
270 dir_match = strcmp(ptrn.dir, "*/") == 0 ||
271 (fname->dir != NULL && __kmp_str_eqf(fname->dir, ptrn.dir));
272 base_match = strcmp(ptrn.base, "*") == 0 ||
273 (fname->base != NULL && __kmp_str_eqf(fname->base, ptrn.base));
274 __kmp_str_fname_free(&ptrn);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000275 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000276
Jonathan Peyton30419822017-05-12 18:01:32 +0000277 return dir_match && base_match;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000278} // __kmp_str_fname_match
279
Jonathan Peyton30419822017-05-12 18:01:32 +0000280kmp_str_loc_t __kmp_str_loc_init(char const *psource, int init_fname) {
281 kmp_str_loc_t loc;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000282
Jonathan Peyton30419822017-05-12 18:01:32 +0000283 loc._bulk = NULL;
284 loc.file = NULL;
285 loc.func = NULL;
286 loc.line = 0;
287 loc.col = 0;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000288
Jonathan Peyton30419822017-05-12 18:01:32 +0000289 if (psource != NULL) {
290 char *str = NULL;
291 char *dummy = NULL;
292 char *line = NULL;
293 char *col = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000294
Jonathan Peyton30419822017-05-12 18:01:32 +0000295 // Copy psource to keep it intact.
296 loc._bulk = __kmp_str_format("%s", psource);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000297
Jonathan Peyton30419822017-05-12 18:01:32 +0000298 // Parse psource string: ";file;func;line;col;;"
299 str = loc._bulk;
300 __kmp_str_split(str, ';', &dummy, &str);
301 __kmp_str_split(str, ';', &loc.file, &str);
302 __kmp_str_split(str, ';', &loc.func, &str);
303 __kmp_str_split(str, ';', &line, &str);
304 __kmp_str_split(str, ';', &col, &str);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000305
Jonathan Peyton30419822017-05-12 18:01:32 +0000306 // Convert line and col into numberic values.
307 if (line != NULL) {
308 loc.line = atoi(line);
309 if (loc.line < 0) {
310 loc.line = 0;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000311 }
312 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000313 if (col != NULL) {
314 loc.col = atoi(col);
315 if (loc.col < 0) {
316 loc.col = 0;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000317 }
318 }
319 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000320
Jonathan Peyton30419822017-05-12 18:01:32 +0000321 __kmp_str_fname_init(&loc.fname, init_fname ? loc.file : NULL);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000322
Jonathan Peyton30419822017-05-12 18:01:32 +0000323 return loc;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000324} // kmp_str_loc_init
325
Jonathan Peyton30419822017-05-12 18:01:32 +0000326void __kmp_str_loc_free(kmp_str_loc_t *loc) {
327 __kmp_str_fname_free(&loc->fname);
Jonas Hahnfeldaeb40ad2017-11-09 15:52:25 +0000328 __kmp_str_free(&(loc->_bulk));
Jonathan Peyton30419822017-05-12 18:01:32 +0000329 loc->file = NULL;
330 loc->func = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000331} // kmp_str_loc_free
332
Jonathan Peyton30419822017-05-12 18:01:32 +0000333/* This function is intended to compare file names. On Windows* OS file names
334 are case-insensitive, so functions performs case-insensitive comparison. On
335 Linux* OS it performs case-sensitive comparison. Note: The function returns
336 *true* if strings are *equal*. */
337int __kmp_str_eqf( // True, if strings are equal, false otherwise.
338 char const *lhs, // First string.
339 char const *rhs // Second string.
340 ) {
341 int result;
342#if KMP_OS_WINDOWS
343 result = (_stricmp(lhs, rhs) == 0);
344#else
345 result = (strcmp(lhs, rhs) == 0);
346#endif
347 return result;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000348} // __kmp_str_eqf
349
Jonathan Peyton30419822017-05-12 18:01:32 +0000350/* This function is like sprintf, but it *allocates* new buffer, which must be
351 freed eventually by __kmp_str_free(). The function is very convenient for
352 constructing strings, it successfully replaces strdup(), strcat(), it frees
353 programmer from buffer allocations and helps to avoid buffer overflows.
354 Examples:
Jim Cownie5e8470a2013-09-27 10:38:44 +0000355
Jonathan Peyton30419822017-05-12 18:01:32 +0000356 str = __kmp_str_format("%s", orig); //strdup() doesn't care about buffer size
357 __kmp_str_free( & str );
358 str = __kmp_str_format( "%s%s", orig1, orig2 ); // strcat(), doesn't care
359 // about buffer size.
360 __kmp_str_free( & str );
361 str = __kmp_str_format( "%s/%s.txt", path, file ); // constructing string.
362 __kmp_str_free( & str );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000363
Jonathan Peyton30419822017-05-12 18:01:32 +0000364 Performance note:
365 This function allocates memory with malloc() calls, so do not call it from
366 performance-critical code. In performance-critical code consider using
367 kmp_str_buf_t instead, since it uses stack-allocated buffer for short
368 strings.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000369
Jonathan Peyton30419822017-05-12 18:01:32 +0000370 Why does this function use malloc()?
371 1. __kmp_allocate() returns cache-aligned memory allocated with malloc().
372 There are no reasons in using __kmp_allocate() for strings due to extra
373 overhead while cache-aligned memory is not necessary.
374 2. __kmp_thread_malloc() cannot be used because it requires pointer to thread
375 structure. We need to perform string operations during library startup
376 (for example, in __kmp_register_library_startup()) when no thread
377 structures are allocated yet.
378 So standard malloc() is the only available option.
Jim Cownie5e8470a2013-09-27 10:38:44 +0000379*/
380
Jonathan Peyton30419822017-05-12 18:01:32 +0000381char *__kmp_str_format( // Allocated string.
382 char const *format, // Format string.
383 ... // Other parameters.
384 ) {
385 va_list args;
386 int size = 512;
387 char *buffer = NULL;
388 int rc;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000389
Jonathan Peyton30419822017-05-12 18:01:32 +0000390 // Allocate buffer.
391 buffer = (char *)KMP_INTERNAL_MALLOC(size);
392 if (buffer == NULL) {
393 KMP_FATAL(MemoryAllocFailed);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000394 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000395
Jonathan Peyton30419822017-05-12 18:01:32 +0000396 for (;;) {
397 // Try to format string.
398 va_start(args, format);
399 rc = KMP_VSNPRINTF(buffer, size, format, args);
400 va_end(args);
401
402 // No errors, string has been formatted.
403 if (rc >= 0 && rc < size) {
404 break;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000405 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000406
Jonathan Peyton30419822017-05-12 18:01:32 +0000407 // Error occurred, buffer is too small.
408 if (rc >= 0) {
409 // C99-conforming implementation of vsnprintf returns required buffer
410 // size.
411 size = rc + 1;
412 } else {
413 // Older implementations just return -1.
414 size = size * 2;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000415 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000416
Jonathan Peyton30419822017-05-12 18:01:32 +0000417 // Enlarge buffer and try again.
418 buffer = (char *)KMP_INTERNAL_REALLOC(buffer, size);
419 if (buffer == NULL) {
420 KMP_FATAL(MemoryAllocFailed);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000421 }
422 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000423
Jonathan Peyton30419822017-05-12 18:01:32 +0000424 return buffer;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000425} // func __kmp_str_format
426
Jonas Hahnfeldaeb40ad2017-11-09 15:52:25 +0000427void __kmp_str_free(char **str) {
Jonathan Peyton30419822017-05-12 18:01:32 +0000428 KMP_DEBUG_ASSERT(str != NULL);
Jonas Hahnfeldaeb40ad2017-11-09 15:52:25 +0000429 KMP_INTERNAL_FREE(*str);
Jonathan Peyton30419822017-05-12 18:01:32 +0000430 *str = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000431} // func __kmp_str_free
432
Jonathan Peyton30419822017-05-12 18:01:32 +0000433/* If len is zero, returns true iff target and data have exact case-insensitive
434 match. If len is negative, returns true iff target is a case-insensitive
435 substring of data. If len is positive, returns true iff target is a
436 case-insensitive substring of data or vice versa, and neither is shorter than
437 len. */
438int __kmp_str_match(char const *target, int len, char const *data) {
439 int i;
440 if (target == NULL || data == NULL) {
441 return FALSE;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000442 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000443 for (i = 0; target[i] && data[i]; ++i) {
444 if (TOLOWER(target[i]) != TOLOWER(data[i])) {
445 return FALSE;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000446 }
447 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000448 return ((len > 0) ? i >= len : (!target[i] && (len || !data[i])));
Jim Cownie5e8470a2013-09-27 10:38:44 +0000449} // __kmp_str_match
450
Jonathan Peyton30419822017-05-12 18:01:32 +0000451int __kmp_str_match_false(char const *data) {
452 int result =
453 __kmp_str_match("false", 1, data) || __kmp_str_match("off", 2, data) ||
454 __kmp_str_match("0", 1, data) || __kmp_str_match(".false.", 2, data) ||
Jonathan Peyton60eec6f2018-09-26 20:19:44 +0000455 __kmp_str_match(".f.", 2, data) || __kmp_str_match("no", 1, data) ||
456 __kmp_str_match("disabled", 0, data);
Jonathan Peyton30419822017-05-12 18:01:32 +0000457 return result;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000458} // __kmp_str_match_false
459
Jonathan Peyton30419822017-05-12 18:01:32 +0000460int __kmp_str_match_true(char const *data) {
461 int result =
462 __kmp_str_match("true", 1, data) || __kmp_str_match("on", 2, data) ||
463 __kmp_str_match("1", 1, data) || __kmp_str_match(".true.", 2, data) ||
Jonathan Peyton60eec6f2018-09-26 20:19:44 +0000464 __kmp_str_match(".t.", 2, data) || __kmp_str_match("yes", 1, data) ||
465 __kmp_str_match("enabled", 0, data);
Jonathan Peyton30419822017-05-12 18:01:32 +0000466 return result;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000467} // __kmp_str_match_true
468
Jonathan Peyton30419822017-05-12 18:01:32 +0000469void __kmp_str_replace(char *str, char search_for, char replace_with) {
470 char *found = NULL;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000471
Jonathan Peyton30419822017-05-12 18:01:32 +0000472 found = strchr(str, search_for);
473 while (found) {
474 *found = replace_with;
475 found = strchr(found + 1, search_for);
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000476 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000477} // __kmp_str_replace
478
Jonathan Peyton30419822017-05-12 18:01:32 +0000479void __kmp_str_split(char *str, // I: String to split.
480 char delim, // I: Character to split on.
481 char **head, // O: Pointer to head (may be NULL).
482 char **tail // O: Pointer to tail (may be NULL).
483 ) {
484 char *h = str;
485 char *t = NULL;
486 if (str != NULL) {
487 char *ptr = strchr(str, delim);
488 if (ptr != NULL) {
489 *ptr = 0;
490 t = ptr + 1;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000491 }
492 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000493 if (head != NULL) {
494 *head = h;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000495 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000496 if (tail != NULL) {
497 *tail = t;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000498 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000499} // __kmp_str_split
500
Jonathan Peyton30419822017-05-12 18:01:32 +0000501/* strtok_r() is not available on Windows* OS. This function reimplements
502 strtok_r(). */
503char *__kmp_str_token(
504 char *str, // String to split into tokens. Note: String *is* modified!
505 char const *delim, // Delimiters.
506 char **buf // Internal buffer.
507 ) {
508 char *token = NULL;
509#if KMP_OS_WINDOWS
510 // On Windows* OS there is no strtok_r() function. Let us implement it.
511 if (str != NULL) {
512 *buf = str; // First call, initialize buf.
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000513 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000514 *buf += strspn(*buf, delim); // Skip leading delimiters.
515 if (**buf != 0) { // Rest of the string is not yet empty.
516 token = *buf; // Use it as result.
517 *buf += strcspn(*buf, delim); // Skip non-delimiters.
518 if (**buf != 0) { // Rest of the string is not yet empty.
519 **buf = 0; // Terminate token here.
520 *buf += 1; // Advance buf to start with the next token next time.
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000521 }
522 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000523#else
524 // On Linux* OS and OS X*, strtok_r() is available. Let us use it.
525 token = strtok_r(str, delim, buf);
526#endif
527 return token;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000528} // __kmp_str_token
Jim Cownie5e8470a2013-09-27 10:38:44 +0000529
Jonathan Peyton30419822017-05-12 18:01:32 +0000530int __kmp_str_to_int(char const *str, char sentinel) {
531 int result, factor;
532 char const *t;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000533
Jonathan Peyton30419822017-05-12 18:01:32 +0000534 result = 0;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000535
Jonathan Peyton30419822017-05-12 18:01:32 +0000536 for (t = str; *t != '\0'; ++t) {
537 if (*t < '0' || *t > '9')
538 break;
539 result = (result * 10) + (*t - '0');
540 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000541
Jonathan Peyton30419822017-05-12 18:01:32 +0000542 switch (*t) {
543 case '\0': /* the current default for no suffix is bytes */
544 factor = 1;
545 break;
546 case 'b':
547 case 'B': /* bytes */
548 ++t;
549 factor = 1;
550 break;
551 case 'k':
552 case 'K': /* kilo-bytes */
553 ++t;
554 factor = 1024;
555 break;
556 case 'm':
557 case 'M': /* mega-bytes */
558 ++t;
559 factor = (1024 * 1024);
560 break;
561 default:
562 if (*t != sentinel)
563 return (-1);
564 t = "";
565 factor = 1;
566 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000567
Jonathan Peyton30419822017-05-12 18:01:32 +0000568 if (result > (INT_MAX / factor))
569 result = INT_MAX;
570 else
571 result *= factor;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000572
Jonathan Peyton30419822017-05-12 18:01:32 +0000573 return (*t != 0 ? 0 : result);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000574} // __kmp_str_to_int
575
Jonathan Peyton30419822017-05-12 18:01:32 +0000576/* The routine parses input string. It is expected it is a unsigned integer with
577 optional unit. Units are: "b" for bytes, "kb" or just "k" for kilobytes, "mb"
578 or "m" for megabytes, ..., "yb" or "y" for yottabytes. :-) Unit name is
579 case-insensitive. The routine returns 0 if everything is ok, or error code:
580 -1 in case of overflow, -2 in case of unknown unit. *size is set to parsed
581 value. In case of overflow *size is set to KMP_SIZE_T_MAX, in case of unknown
582 unit *size is set to zero. */
583void __kmp_str_to_size( // R: Error code.
584 char const *str, // I: String of characters, unsigned number and unit ("b",
585 // "kb", etc).
586 size_t *out, // O: Parsed number.
587 size_t dfactor, // I: The factor if none of the letters specified.
588 char const **error // O: Null if everything is ok, error message otherwise.
589 ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000590
Jonathan Peyton30419822017-05-12 18:01:32 +0000591 size_t value = 0;
592 size_t factor = 0;
593 int overflow = 0;
594 int i = 0;
595 int digit;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000596
Jonathan Peyton30419822017-05-12 18:01:32 +0000597 KMP_DEBUG_ASSERT(str != NULL);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000598
Jonathan Peyton30419822017-05-12 18:01:32 +0000599 // Skip spaces.
600 while (str[i] == ' ' || str[i] == '\t') {
601 ++i;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000602 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000603
Jonathan Peyton30419822017-05-12 18:01:32 +0000604 // Parse number.
605 if (str[i] < '0' || str[i] > '9') {
606 *error = KMP_I18N_STR(NotANumber);
607 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000608 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000609 do {
610 digit = str[i] - '0';
611 overflow = overflow || (value > (KMP_SIZE_T_MAX - digit) / 10);
612 value = (value * 10) + digit;
613 ++i;
614 } while (str[i] >= '0' && str[i] <= '9');
Jim Cownie5e8470a2013-09-27 10:38:44 +0000615
Jonathan Peyton30419822017-05-12 18:01:32 +0000616 // Skip spaces.
617 while (str[i] == ' ' || str[i] == '\t') {
618 ++i;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000619 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000620
Jonathan Peyton30419822017-05-12 18:01:32 +0000621// Parse unit.
622#define _case(ch, exp) \
623 case ch: \
624 case ch - ('a' - 'A'): { \
625 size_t shift = (exp)*10; \
626 ++i; \
627 if (shift < sizeof(size_t) * 8) { \
628 factor = (size_t)(1) << shift; \
629 } else { \
630 overflow = 1; \
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000631 } \
Jonathan Peyton30419822017-05-12 18:01:32 +0000632 } break;
633 switch (str[i]) {
634 _case('k', 1); // Kilo
635 _case('m', 2); // Mega
636 _case('g', 3); // Giga
637 _case('t', 4); // Tera
638 _case('p', 5); // Peta
639 _case('e', 6); // Exa
640 _case('z', 7); // Zetta
641 _case('y', 8); // Yotta
642 // Oops. No more units...
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000643 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000644#undef _case
645 if (str[i] == 'b' || str[i] == 'B') { // Skip optional "b".
646 if (factor == 0) {
647 factor = 1;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000648 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000649 ++i;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000650 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000651 if (!(str[i] == ' ' || str[i] == '\t' || str[i] == 0)) { // Bad unit
652 *error = KMP_I18N_STR(BadUnit);
653 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000654 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000655
Jonathan Peyton30419822017-05-12 18:01:32 +0000656 if (factor == 0) {
657 factor = dfactor;
658 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000659
Jonathan Peyton30419822017-05-12 18:01:32 +0000660 // Apply factor.
661 overflow = overflow || (value > (KMP_SIZE_T_MAX / factor));
662 value *= factor;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000663
Jonathan Peyton30419822017-05-12 18:01:32 +0000664 // Skip spaces.
665 while (str[i] == ' ' || str[i] == '\t') {
666 ++i;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000667 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000668
Jonathan Peyton30419822017-05-12 18:01:32 +0000669 if (str[i] != 0) {
670 *error = KMP_I18N_STR(IllegalCharacters);
671 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000672 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000673
Jonathan Peyton30419822017-05-12 18:01:32 +0000674 if (overflow) {
675 *error = KMP_I18N_STR(ValueTooLarge);
676 *out = KMP_SIZE_T_MAX;
677 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000678 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000679
Jonathan Peyton30419822017-05-12 18:01:32 +0000680 *error = NULL;
681 *out = value;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000682} // __kmp_str_to_size
683
Jonathan Peyton30419822017-05-12 18:01:32 +0000684void __kmp_str_to_uint( // R: Error code.
685 char const *str, // I: String of characters, unsigned number.
686 kmp_uint64 *out, // O: Parsed number.
687 char const **error // O: Null if everything is ok, error message otherwise.
688 ) {
689 size_t value = 0;
690 int overflow = 0;
691 int i = 0;
692 int digit;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000693
Jonathan Peyton30419822017-05-12 18:01:32 +0000694 KMP_DEBUG_ASSERT(str != NULL);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000695
Jonathan Peyton30419822017-05-12 18:01:32 +0000696 // Skip spaces.
697 while (str[i] == ' ' || str[i] == '\t') {
698 ++i;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000699 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000700
Jonathan Peyton30419822017-05-12 18:01:32 +0000701 // Parse number.
702 if (str[i] < '0' || str[i] > '9') {
703 *error = KMP_I18N_STR(NotANumber);
704 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000705 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000706 do {
707 digit = str[i] - '0';
708 overflow = overflow || (value > (KMP_SIZE_T_MAX - digit) / 10);
709 value = (value * 10) + digit;
710 ++i;
711 } while (str[i] >= '0' && str[i] <= '9');
Jim Cownie5e8470a2013-09-27 10:38:44 +0000712
Jonathan Peyton30419822017-05-12 18:01:32 +0000713 // Skip spaces.
714 while (str[i] == ' ' || str[i] == '\t') {
715 ++i;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000716 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000717
Jonathan Peyton30419822017-05-12 18:01:32 +0000718 if (str[i] != 0) {
719 *error = KMP_I18N_STR(IllegalCharacters);
720 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000721 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000722
Jonathan Peyton30419822017-05-12 18:01:32 +0000723 if (overflow) {
724 *error = KMP_I18N_STR(ValueTooLarge);
725 *out = (kmp_uint64)-1;
726 return;
Jonathan Peytonbd3a7632017-09-27 20:36:27 +0000727 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000728
Jonathan Peyton30419822017-05-12 18:01:32 +0000729 *error = NULL;
730 *out = value;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000731} // __kmp_str_to_unit
732
Jim Cownie5e8470a2013-09-27 10:38:44 +0000733// end of file //